たま日記

たまに書く

TX81Zを解析した(Operator Output Level編)

TX81Zの音色はVCED(Voice Edit Parameters)で設定する.Attack RateやAlgorithmなどはYM2414のレジスタに書き込む値をほぼそのまま設定するのだが,Operator Output LevelやLFO Speedなどは0~99の値を設定する.この0~99の値は何らかの計算により0~127などに変換されレジスタに書き込まれる.この計算方法を知りたくて中古のTX81Zを購入し解析をしていた.ある程度知見が溜まったので書いてみる.

http://sr4.sakura.ne.jp/fmsound/opz.htmlで述べられている通り,YM2414はYM2151とほぼ同じアドレス構成を持つ.このうちレジスタTL(0x60~0x7f)に書き込まれる値V_{TL}は次の式で求まる.

V_{TL} = 0 + A_{vol} + A_{alg} + A_{ol} + A_{ls} + A_{kvs} + A_{ebs}

A_{vol}A_{alg}などはVCEDの設定値で決まる減衰量を表す.V_{TL}は0のときに最大,127で最小の出力レベルになる.キャリアとなるオペレータなら音量,モジュレータとなるオペレータなら変調度となる.最大となる0の値にA_{vol}などの減衰量を加算することでV_{TL}を決める.以下,各減衰量について述べる.

A_{vol}:マスターボリュームによる減衰量
前面パネルのMASTER VOLUMEボタンで設定した0~99の音量で決まる減衰量.ただしキャリアとなるオペレータにのみ反映される.対応を以下に示す.0や3など同じ音量があるが,LCDパネルに表示される音量は変わらなくても内部では減衰量が変化している.

Volume	Avol
 0	127
 0	102
 1	 90
 2	 83
 3	 77
 3	 72
 4	 68
 5	 65
 6	 62
 7	 60
 7	 57
 8	 55
 9	 53
10	 51
10	 50
11	 48
12	 47
13	 45
14	 44
14	 43
15	 42
16	 41
17	 40
17	 39
18	 38
19	 37
20	 36
21	 35
21	 34
22	 33
23	 33
24	 32
25	 31
25	 30
26	 30
27	 29
28	 28
28	 28
29	 27
30	 27
31	 26
32	 25
32	 25
33	 24
34	 24
35	 23
35	 23
36	 22
37	 22
38	 21
39	 21
39	 21
40	 20
41	 20
42	 19
42	 19
43	 18
44	 18
45	 18
46	 17
46	 17
47	 16
48	 16
49	 16
50	 15
50	 15
51	 15
52	 14
53	 14
53	 14
54	 13
55	 13
56	 13
57	 12
57	 12
58	 12
59	 11
60	 11
60	 11
61	 10
62	 10
63	 10
64	 10
64	  9
65	  9
66	  9
67	  9
67	  8
68	  8
69	  8
70	  8
71	  7
71	  7
72	  7
73	  7
74	  6
75	  6
75	  6
76	  6
77	  5
78	  5
78	  5
79	  5
80	  4
81	  4
82	  4
82	  4
83	  3
84	  3
85	  3
85	  3
86	  3
87	  2
88	  2
89	  2
89	  2
90	  2
91	  1
92	  1
92	  1
93	  1
94	  1
95	  0
96	  0
96	  0
97	  0
98	  0
99	  0


A_{alg}アルゴリズムによる減衰量
オペレータop1~op4によって異なる


A_{ol}:Operator Output Levelによる減衰量
OL(Operator Output Level)とA_{ol}の関係を以下に示す.

OL	Aol
99	 0
98	 1
97	 2
96	 3
95	 4
94	 5
93	 6
92	 7
91	 8
90	 9
89	10
88	11
87	12
86	13
85	14
84	15
83	16
82	17
81	18
80	19
79	20
78	21
77	22
76	23
75	24
74	25
73	26
72	27
71	28
70	29
69	30
68	31
67	32
66	33
65	34
64	35
63	36
62	37
61	38
60	39
59	40
58	41
57	42
56	43
55	44
54	45
53	46
52	47
51	48
50	49
49	50
48	51
47	52
46	53
45	54
44	55
43	56
42	57
41	58
40	59
39	60
38	61
37	62
36	63
35	64
34	65
33	66
32	67
31	68
30	69
29	70
28	71
27	72
26	73
25	74
24	75
23	76
22	77
21	78
20	79    #ここまでは1ずつ減少
19	81
18	82
17	84
16	85
15	86
14	88
13	90
12	92
11	94
10	96
 9	98
 8	100
 7	102
 6	104
 5	107
 4	110
 3	114
 2	118
 1	122
 0	127

A_{ls}:Level Scalingによる減衰量
VCEDのLS(Level Scaling)の値と発音するMIDIノート番号によって決まる減衰量.LSは音の高さが高いほど単純な音質になる度合を0~127で表現するパラメータ.MIDIノート番号は音の高さを0~127で表現する番号.LSとMIDIノート番号からA_{ls}がどのような値を取るか以下に示す.

  • 縦軸はLSの値99~0.
  • 横軸はMIDIノート番号.30の列は0~30,33の列は31~33.109~120の列は97~108の列と同じ.121~127の列は97~103の列と同じ.


   30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 
LS:-----------------------------------------------------------------------------------
99: 0  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 23 28 33 39 47 56 66 79  94 111 127
98: 0  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 23 28 32 39 46 55 65 78  93 110 125
97: 0  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 22 27 32 39 46 55 65 78  92 109 124
96: 0  1  1  2  2  3  3  4  5  6  7  9 11 13 15 18 22 27 32 38 45 54 64 77  91 108 123
95: 0  1  1  2  2  3  3  4  5  6  7  9 10 13 15 18 22 27 31 38 45 53 63 76  90 106 121
94: 0  1  1  2  2  3  3  4  5  6  7  8 10 13 15 18 22 26 31 37 44 53 63 75  89 105 120
93: 0  1  1  2  2  3  3  4  5  6  7  8 10 13 15 18 21 26 31 37 44 52 62 74  88 104 119
92: 0  1  1  2  2  3  3  4  5  6  7  8 10 12 15 18 21 26 31 37 43 52 62 74  87 103 118
91: 0  1  1  2  2  3  3  4  5  6  7  8 10 12 15 17 21 26 30 36 43 51 61 73  86 102 116
90: 0  1  1  2  2  3  3  4  4  6  7  8 10 12 14 17 21 25 30 36 43 51 60 72  86 101 115
89: 0  1  1  2  2  3  3  4  4  6  7  8 10 12 14 17 21 25 29 35 42 50 59 71  84 100 114
88: 0  1  1  2  2  3  3  3  4  6  7  8 10 12 14 17 20 25 29 35 41 49 59 70  83  98 112
87: 0  1  1  2  2  3  3  3  4  6  7  8 10 12 14 17 20 24 29 35 41 49 58 70  83  98 111
86: 0  1  1  2  2  3  3  3  4  6  6  8  9 12 14 16 20 24 28 34 41 48 57 69  82  96 110
85: 0  1  1  2  2  2  3  3  4  5  6  8  9 11 14 16 20 24 28 34 40 48 57 68  81  95 109
84: 0  1  1  2  2  2  3  3  4  5  6  8  9 11 13 16 19 24 28 33 40 47 56 67  80  94 107
83: 0  1  1  2  2  2  3  3  4  5  6  7  9 11 13 16 19 23 27 33 39 47 55 66  79  93 106
82: 0  1  1  2  2  2  3  3  4  5  6  7  9 11 13 16 19 23 27 32 39 46 55 65  78  92 105
81: 0  1  1  2  2  2  3  3  4  5  6  7  9 11 13 15 19 23 27 32 38 45 54 65  77  91 103
80: 0  1  1  2  2  2  3  3  4  5  6  7  9 11 13 15 18 22 26 32 38 45 53 64  76  90 102
79: 0  1  1  1  2  2  3  3  4  5  6  7  9 11 13 15 18 22 26 31 37 44 53 63  75  88 101
78: 0  1  1  1  2  2  3  3  4  5  6  7  9 10 12 15 18 22 26 31 37 44 52 62  74  87 100
77: 0  1  1  1  2  2  3  3  4  5  6  7  8 10 12 15 18 22 25 30 36 43 51 61  73  86  98
76: 0  1  1  1  2  2  3  3  4  5  6  7  8 10 12 14 17 21 25 30 36 43 51 60  72  85  97
75: 0  1  1  1  2  2  3  3  4  5  6  7  8 10 12 14 17 21 25 30 35 42 50 60  71  84  96
74: 0  1  1  1  2  2  2  3  4  5  5  7  8 10 12 14 17 21 24 29 35 41 49 59  70  83  94
73: 0  1  1  1  2  2  2  3  4  5  5  6  8 10 12 14 17 20 24 29 34 41 49 58  69  82  93
72: 0  1  1  1  2  2  2  3  3  5  5  6  8 10 11 14 16 20 24 28 34 40 48 57  68  80  92
71: 0  1  1  1  2  2  2  3  3  5  5  6  8 10 11 13 16 20 23 28 33 40 47 57  67  80  91
70: 0  1  1  1  2  2  2  3  3  4  5  6  8  9 11 13 16 20 23 28 33 39 47 56  66  78  89
69: 0  1  1  1  2  2  2  3  3  4  5  6  7  9 11 13 16 19 23 27 32 39 46 55  65  77  88
68: 0  1  1  1  2  2  2  3  3  4  5  6  7  9 11 13 16 19 22 27 32 38 45 54  64  76  87
67: 0  1  1  1  2  2  2  3  3  4  5  6  7  9 11 13 15 19 22 26 31 37 45 53  63  75  85
66: 0  0  1  1  1  2  2  2  3  4  5  6  7  9 10 12 15 18 22 26 31 37 44 53  63  74  84
65: 0  0  1  1  1  2  2  2  3  4  5  6  7  9 10 12 15 18 21 26 30 36 43 52  61  73  83
64: 0  0  1  1  1  2  2  2  3  4  5  6  7  9 10 12 15 18 21 25 30 36 43 51  61  72  82
63: 0  0  1  1  1  2  2  2  3  4  5  6  7  8 10 12 14 18 21 25 30 35 42 50  60  70  80
62: 0  0  1  1  1  2  2  2  3  4  4  5  7  8 10 12 14 17 20 24 29 35 41 49  59  69  79
61: 0  0  1  1  1  2  2  2  3  4  4  5  7  8 10 11 14 17 20 24 29 34 41 49  58  68  78
60: 0  0  1  1  1  2  2  2  3  4  4  5  6  8  9 11 14 17 20 24 28 33 40 48  57  67  76
59: 0  0  1  1  1  2  2  2  3  4  4  5  6  8  9 11 13 16 19 23 28 33 39 47  56  66  75
58: 0  0  1  1  1  2  2  2  3  4  4  5  6  8  9 11 13 16 19 23 27 32 38 46  55  65  74
57: 0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 22 27 32 38 45  54  63  72
56: 0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 10 13 16 18 22 26 31 37 45  53  63  71
55: 0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 10 12 15 18 22 26 31 36 44  52  61  70
54: 0  0  1  1  1  1  2  2  2  3  4  5  6  7  8 10 12 15 18 21 25 30 36 43  51  60  69
53: 0  0  1  1  1  1  2  2  2  3  4  5  6  7  8 10 12 15 17 21 25 30 35 42  50  59  67
52: 0  0  1  1  1  1  2  2  2  3  4  4  6  7  8 10 12 14 17 20 24 29 35 41  49  58  66
51: 0  0  1  1  1  1  2  2  2  3  4  4  5  7  8  9 12 14 17 20 24 28 34 40  48  57  65
50: 0  0  1  1  1  1  2  2  2  3  4  4  5  7  8  9 11 14 16 20 23 28 33 40  47  56  63
49: 0  0  0  1  1  1  1  2  2  3  3  4  5  6  8  9 11 14 16 19 23 27 32 39  46  55  62
48: 0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 22 27 32 38  45  53  61
47: 0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 15 18 22 26 31 37  44  52  60
46: 0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8 10 13 15 18 21 26 30 36  43  51  58
45: 0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8 10 12 15 18 21 25 30 36  43  50  57
44: 0  0  0  1  1  1  1  1  2  3  3  4  5  6  7  8 10 12 14 17 20 24 29 35  41  49  56
43: 0  0  0  1  1  1  1  1  2  3  3  4  4  6  7  8 10 12 14 17 20 24 28 34  40  48  54
42: 0  0  0  1  1  1  1  1  2  2  3  4  4  5  6  8  9 12 14 16 20 23 28 33  40  47  53
41: 0  0  0  1  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 23 27 32  38  45  52
40: 0  0  0  1  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 22 26 32  38  45  51
39: 0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 15 18 22 26 31  37  43  49
38: 0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8 10 12 15 17 21 25 30  35  42  48
37: 0  0  0  0  1  1  1  1  2  2  2  3  4  5  6  7  8 10 12 14 17 20 24 29  35  41  47
36: 0  0  0  0  1  1  1  1  1  2  2  3  4  5  5  7  8 10 12 14 17 20 24 28  34  40  45
35: 0  0  0  0  1  1  1  1  1  2  2  3  4  4  5  6  8 10 11 14 16 19 23 28  33  39  44
34: 0  0  0  0  1  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 16 19 22 27  32  38  43
33: 0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 15 18 22 26  31  37  42
32: 0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 10 12 15 18 21 25  30  35  40
31: 0  0  0  0  0  1  1  1  1  2  2  2  3  4  5  6  7  8 10 12 14 17 20 24  29  34  39
30: 0  0  0  0  0  1  1  1  1  2  2  2  3  4  4  5  7  8 10 12 14 16 20 24  28  33  38
29: 0  0  0  0  0  1  1  1  1  2  2  2  3  4  4  5  6  8  9 11 13 16 19 23  27  32  36
28: 0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  8  9 11 13 15 18 22  26  31  35
27: 0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 10 12 15 18 21  25  30  34
26: 0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8 10 12 14 17 20  24  29  33
25: 0  0  0  0  0  0  1  1  1  1  2  2  2  3  4  4  5  7  8 10 11 14 16 20  23  28  31
24: 0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 15 19  22  26  30
23: 0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 10 13 15 18  21  25  29
22: 0  0  0  0  0  0  0  0  1  1  1  2  2  3  3  4  5  6  7  8 10 12 14 17  20  24  27
21: 0  0  0  0  0  0  0  0  1  1  1  2  2  2  3  4  4  6  7  8 10 11 14 16  20  23  26
20: 0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13 15  18  22  25
19: 0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8 10 12 15  17  21  23
18: 0  0  0  0  0  0  0  0  0  1  1  1  2  2  2  3  4  5  6  7  8 10 12 14  17  20  22
17: 0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 11 13  15  18  21
16: 0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9 10 12  15  17  20
15: 0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  2  3  4  4  5  7  8  9 11  14  16  18
14: 0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  4  4  5  6  7  9 11  13  15  17
13: 0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8 10  12  14  16
12: 0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  9  11  13  14
11: 0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7  8  10  12  13
10: 0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7   9  10  12
 9: 0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6  7   8  10  11
 8: 0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4  5  6   7   8   9
 7: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  2  2  2  3  3  4  5   6   7   8
 6: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3  4   5   6   7
 5: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3  3   4   5   5
 4: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2  2  3   3   4   4
 3: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1  1  2   2   3   3
 2: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1   1   2   2
 1: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0   0   0
 0: 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0   0   0

A_{kvs}:Key Velocity Sensitivityによる減衰量
VCEDのKVS(Key Velocity Sensitivity)の値と発音するMIDIのvelocity値によって決まる減衰量.KVSはvelocity値が大きいほど大きな出力になる度合を0~7で表現するパラメータ.velocity値は音の大きさ(打鍵の速さ?)を0~127で表現する番号.KVSとvelocityからA_{kvs}がどのような値を取るか以下に示す.

  • 縦軸はvelocityの値0~127.
  • 横軸はkvsの値1~7.kvs=0のときA_{kvs}=0.

//kvs=1  2   3   4   5   6   7
    18, 29, 40, 51, 62, 73, 84, // velocity=1
    17, 28, 38, 48, 58, 69, 79, // 2
    17, 27, 37, 47, 56, 66, 76, // 3
    17, 26, 36, 45, 55, 64, 74, // 4
    16, 25, 34, 44, 53, 62, 71, // 5
    16, 25, 34, 43, 51, 60, 69, // 6
    16, 24, 33, 41, 50, 58, 67, // 7
    15, 24, 32, 40, 48, 57, 65, // 8
    15, 23, 31, 39, 47, 55, 63, // 9
    15, 23, 30, 38, 46, 54, 62, // 10
    15, 22, 30, 38, 45, 53, 60,
    14, 22, 29, 37, 44, 51, 59,
    14, 21, 28, 36, 43, 50, 57,
    14, 21, 28, 35, 42, 49, 56,
    14, 21, 27, 34, 41, 48, 55,
    14, 20, 27, 34, 40, 47, 53,
    13, 20, 26, 33, 39, 46, 52,
    13, 20, 26, 32, 38, 45, 51,
    13, 19, 25, 32, 38, 44, 50,
    13, 19, 25, 31, 37, 43, 49, // 20
    13, 19, 24, 30, 36, 42, 48,
    13, 18, 24, 30, 35, 41, 47,
    13, 18, 24, 29, 35, 40, 46,
    12, 18, 23, 29, 34, 40, 45,
    12, 18, 23, 28, 34, 39, 44,
    12, 17, 23, 28, 33, 38, 43,
    12, 17, 22, 27, 32, 37, 42,
    12, 17, 22, 27, 32, 37, 42,
    12, 17, 21, 26, 31, 36, 41,
    12, 17, 21, 26, 31, 36, 40, // 30
    12, 16, 21, 26, 30, 35, 39,
    12, 16, 21, 25, 30, 34, 39,
    11, 16, 20, 25, 29, 33, 38,
    11, 16, 20, 24, 29, 33, 37,
    11, 15, 20, 24, 28, 32, 36,
    11, 15, 19, 24, 28, 32, 36,
    11, 15, 19, 23, 27, 31, 35,
    11, 15, 19, 23, 27, 31, 35,
    11, 15, 19, 23, 26, 30, 34,
    11, 15, 18, 22, 26, 30, 33, // 40
    11, 14, 18, 22, 25, 29, 33,
    11, 14, 18, 22, 25, 29, 32,
    11, 14, 18, 21, 25, 28, 32,
    10, 14, 17, 21, 24, 28, 31,
    10, 14, 17, 21, 24, 27, 31,
    10, 14, 17, 20, 23, 27, 30,
    10, 13, 17, 20, 23, 26, 29,
    10, 13, 16, 20, 23, 26, 29,
    10, 13, 16, 19, 22, 25, 28,
    10, 13, 16, 19, 22, 25, 28, // 50
    10, 13, 16, 19, 22, 25, 28,
    10, 13, 16, 19, 21, 24, 27,
    10, 13, 15, 18, 21, 24, 26,
    10, 12, 15, 18, 20, 23, 26,
    10, 12, 15, 18, 20, 23, 25,
    10, 12, 15, 17, 20, 22, 25,
    10, 12, 15, 17, 20, 22, 25,
     9, 12, 14, 17, 19, 22, 24,
     9, 12, 14, 17, 19, 21, 24,
     9, 12, 14, 16, 19, 21, 23, // 60
     9, 12, 14, 16, 18, 21, 23,
     9, 11, 13, 16, 18, 20, 22,
     9, 11, 13, 15, 17, 19, 21,
     9, 11, 13, 15, 17, 19, 21,
     9, 11, 13, 15, 17, 19, 21,
     9, 11, 13, 15, 16, 18, 20,
     9, 11, 12, 14, 16, 18, 20,
     9, 11, 12, 14, 16, 18, 19,
     9, 10, 12, 14, 15, 17, 19,
     9, 10, 12, 14, 15, 17, 18, // 70
     9, 10, 12, 13, 15, 16, 18,
     9, 10, 12, 13, 15, 16, 18,
     8, 10, 11, 13, 14, 16, 17,
     8, 10, 11, 13, 14, 15, 17,
     8, 10, 11, 12, 14, 15, 16,
     8, 10, 11, 12, 13, 15, 16,
     8,  9, 11, 12, 13, 14, 15,
     8,  9, 10, 12, 13, 14, 15,
     8,  9, 10, 11, 12, 13, 14,
     8,  9, 10, 11, 12, 13, 14, // 80
     8,  9, 10, 11, 12, 13, 14,
     8,  9, 10, 11, 11, 12, 13,
     8,  9,  9, 10, 11, 12, 13,
     8,  9,  9, 10, 11, 12, 12,
     8,  8,  9, 10, 10, 11, 12,
     8,  8,  9, 10, 10, 11, 11,
     8,  8,  9, 10, 10, 11, 11,
     8,  8,  9,  9, 10, 10, 11,
     8,  8,  9,  9, 10, 10, 11,
     7,  8,  8,  9,  9, 10, 10, // 90
     7,  8,  8,  9,  9,  9, 10,
     7,  8,  8,  9,  9,  9, 10,
     7,  8,  8,  8,  9,  9,  9,
     7,  8,  8,  8,  8,  9,  9,
     7,  7,  8,  8,  8,  8,  8,
     7,  7,  7,  8,  8,  8,  8,
     7,  7,  7,  8,  8,  8,  8,
     7,  7,  7,  7,  7,  7,  7,
     7,  7,  7,  7,  7,  7,  7,
     7,  7,  7,  7,  7,  7,  7, // 100
     7,  7,  7,  7,  7,  7,  7,
     7,  7,  7,  7,  6,  6,  6,
     7,  7,  7,  7,  6,  6,  6,
     7,  7,  6,  6,  6,  6,  6,
     7,  7,  6,  6,  6,  6,  5,
     7,  7,  6,  6,  6,  6,  5,
     7,  6,  6,  6,  5,  5,  5,
     7,  6,  6,  6,  5,  5,  5,
     7,  6,  6,  6,  5,  5,  4,
     7,  6,  6,  5,  5,  4,  4, // 110
     7,  6,  6,  5,  5,  4,  4,
     7,  6,  6,  5,  5,  4,  4,
     6,  6,  5,  5,  4,  4,  3,
     6,  6,  5,  5,  4,  4,  3,
     6,  6,  5,  5,  4,  3,  3,
     6,  6,  5,  5,  4,  3,  3,
     6,  6,  5,  4,  4,  3,  2,
     6,  6,  5,  4,  4,  3,  2,
     6,  6,  5,  4,  3,  3,  2,
     6,  6,  5,  4,  3,  3,  2, // 120
     6,  5,  5,  4,  3,  2,  1, // 121
     6,  5,  5,  4,  3,  2,  1, // 122
     6,  5,  4,  4,  3,  2,  1, // 123
     6,  5,  4,  4,  3,  2,  1, // 124
     6,  5,  4,  3,  2,  1,  0, // 125
     6,  5,  4,  3,  2,  1,  0, // 126
     6,  5,  4,  3,  2,  1,  0  // 127


A_{ebs}:EG Bias Sensitivityによる減衰量
これについては別ページで.


表を見ていると対数ぽく見えるのだが,計算式は分からない.

TX81Zをゲットした

TX81Zのプリセットがym2151.c改でうまく鳴らせなかった問題は半分くらい解決した。音の高さによってオペレータのOutputLevelを小さくするLevelScalingという項目がプリセットにあって、勘で適当に実装したら何となくそれっぽい音が出るようになった。

 

でも正しく鳴らない音も多い。実機ではどんな音で鳴るのか?どんなパラメータを与えているのか?知りたくなったので中古のTX81Zを買ってみた。

 

EWI USBと一緒に買ったもののホコリをかぶっていたUR22mk2とmicroKEY 25をPCにつないで鳴らしてみた。本物の音は重厚だった!(ような気がする)

 

というわけで、中身のYM2414のレジスタに書き込んでいる値を調べてみる。ピン配置はYM2151と同じらしい。ロジアナも買って波形を見てみると、アドレス/データをお膳立てしてからYM2414のCSをH→L→Hして書き込んでいるらしい。ロジアナは8chしか観察できないのでマイコンで観察することにする。

 

ESP32でできるかも?といろいろ試してみた。が速度が足りないのか信号を取りこぼす。もう少し早いのはないのか探していると、teensyというマイコンを見つけた。クロック600MHzだって。めちゃくちゃ早い。GPIOも早いらしい。

mimono.wpblog.jp

teensy4.0とロジックレベル変換モジュールをつなげてみる。ESP32の苦労がウソのようにあっさり動いた。音を出していないときでも$28~$37(音の高さ)と$60~$7F(音の大きさ)に書き込み続けていることが分かった。詳しい解析はこれから。

 
f:id:androuet:20201018213605j:image

DeicsOnzeは無理だった

自作ウィンドシンセの内蔵ソフト音源として考えていたDeicsOnze、TX81ZなるFM音源モジュールのエミュレータなのだがESP32で動かすことはできなかった…残念! 波形?を保存するテーブルがメモリに入りきらず、Arduino環境ではコンパイルできなかった。Windows上でMSYS2 MinGW64 + ASIO + PortAudioで動かすところまではできたんだけど、あきらめる。

というわけで、これまで使ってきたVGMPlayのym2151.cにTX81Zの機能を追加していく作業をしていた。TX81Zのプリセットを鳴らせることが目標。

DX7ぐらいしか聞いたことなかったのだが、他にもいろんなFM音源製品が発売されていたことを知る。TX81Zも相当有名なFM音源らしくあちこちに有用な資料が転がっている。マニュアルもPDFでダウンロードできた。

TX81ZのFM音源チップはYM2414(OPZ)。YM2151(OPM)の後継?チップだそうな。音色データを移植しているサイトもあった。
ameblo.jp
blog.livedoor.jp
だからきっと、ym2151.cを使えばTX81Z(に近い音)を再現できるはず!


プリセットのフォーマットはVoice Bulk Data Format(VMEM)という基本形式に、Additional Voice Bulk Data Formatという形式で機能拡張している。DeicsOnzeのソースツリー内に2000個以上登録されている。テキスト形式なので見やすい。なぜかTX81ZやDX11のファクトリープリセットまで登録されている。いいのか?

このデータを構成する値を読み込めるようにym2151.cを改造してみることにする。現時点で追加・変更した機能は次の通り:

  • レジスタに書き込む値:VMEMの値 0~99 を 0~127に変換してYM2151のレジスタに書き込む必要があるものがある。ここが参考になった。ROMコードを解析して調べたらしい。すごいな。
  • オペレータの波形:サイン波以外の波形が発振可能なので増やす。ここここが参考になった。
  • DET2以外:YM2151では16種のMUL値と4種のDT2値{1.00 | 1.41 | 1.57 | 1.73 }でオペレータの周波数を指定するが、TX81Zはもっと細かく指定できる。
  • LFO:ピッチや音量の変化を出音の最初からさせるのではなく、遅らせて変化をかける機能がある。

ym2151.cの正しさはある程度担保されているはずだが、自分が加えた変更は正しいかどうか不明。実機はない。ので前述したファクトリープリセットで鳴らした音と実機の音を聴けるサイトの音を聴き比べてみることにした。

似ている音もあるし、似ていない音もある。ピアノ系は再現できていない。何が違うのかよく分からない。吹く楽器だけでも再現できていればいいか。ym2151.cを単純に鳴らしていたのに比べるとずいぶん楽器らしくなってきた。まだWindowsでしか動かしていない。多分ESP32でも動くと思われ。


今後の予定:

EWI Soloが発売されたことには驚いた。もう少し小さいとよいのだけれど。
ewi.akai-pro.jp

TX81Zエミュレーター

ウィンドシンセはブレスの強さによってピッチや音色を変える機能があるらしい。YouTubeのサックス動画を見ていても、確かに吹いている途中で音が変化している。表現力?の向上には必要だ。

現在使っているym2151.cにはnote onとoffの途中にピッチや音色をブレス強度に応じて自由に変える機能はない。今は音量を変えているだけ。なんだか平板だなと感じる。ソフトで制御するコードを組み込むか?

調べていたら、DeicsOnzeというFM音源エミュレーターを見つけた。YM2414(OPZ)を使用したTX81ZというFM音源モジュールのエミュレーターだ。MusEというMIDIオーディオシーケンサーに組み込まれている。Ubuntu StudioのソフトウェアでMusEをインストールして起動してみた。


f:id:androuet:20200710085722j:image

YM2414ではなくTX81Zをエミューレートしているらしい。ブレスコントローラの入力を音に反映させる機能もあるみたい。リバーブも組み込めるようで素晴らしい。プリセットもたくさんある。ESP32で動かすことはできないだろうか?

BLE MIDIの通信

ESP32とWindows10の間でBLE MIDI通信したときに,頻度がどうなるか調べてみた.参考にしたのは

結果

  • ESP32側で13.333ms毎にnotify()した 全て届いた
  • onConnect()内でconn_params.max_int を0x20にすると40ms毎に、0x0cにすると15ms毎に届く(値 * 1.25ms)それより小さい値を設定しても15msより短くはならないみたい 設定値より遅れることもある
  • 同じ時刻に届く(MIDI-OXに認識される)こともある
 ===> MIDI-OX Version: 7.0.2.372
 ===> Log Opened: Tue 30-Jun-2020 11:56:51 ===>
 TIMESTAMP IN PORT STATUS DATA1 DATA2 CHAN NOTE EVENT               
        20  1  --    176     2    49    1  ---  CC: Breath            
        35  1  --    176     2    50    1  ---  CC: Breath            
        51  1  --    176     2    51    1  ---  CC: Breath            
        65  1  --    176     2    52    1  ---  CC: Breath            
        66  1  --    176     2    53    1  ---  CC: Breath            
        80  1  --    176     2    54    1  ---  CC: Breath            
        95  1  --    176     2    55    1  ---  CC: Breath            
       110  1  --    176     2    56    1  ---  CC: Breath            
       125  1  --    176     2    57    1  ---  CC: Breath            
       140  1  --    176     2    58    1  ---  CC: Breath            
       155  1  --    176     2    59    1  ---  CC: Breath            
       170  1  --    176     2    60    1  ---  CC: Breath            
       185  1  --    176     2    61    1  ---  CC: Breath            
       200  1  --    176     2    62    1  ---  CC: Breath            
       201  1  --    176     2    63    1  ---  CC: Breath            
       215  1  --    176     2    64    1  ---  CC: Breath            
       230  1  --    176     2    65    1  ---  CC: Breath            
       245  1  --    176     2    66    1  ---  CC: Breath            
       260  1  --    176     2    67    1  ---  CC: Breath            
       275  1  --    176     2    68    1  ---  CC: Breath            
       290  1  --    176     2    69    1  ---  CC: Breath            
       305  1  --    176     2    70    1  ---  CC: Breath            
       320  1  --    176     2    71    1  ---  CC: Breath            
       335  1  --    176     2    72    1  ---  CC: Breath            
       335  1  --    176     2    73    1  ---  CC: Breath            
       350  1  --    176     2    74    1  ---  CC: Breath            
       365  1  --    176     2     0    1  ---  CC: Breath            
       380  1  --    176     2     1    1  ---  CC: Breath            
       395  1  --    176     2     2    1  ---  CC: Breath            
       410  1  --    176     2     3    1  ---  CC: Breath            
       426  1  --    176     2     4    1  ---  CC: Breath            
       440  1  --    176     2     5    1  ---  CC: Breath            
       455  1  --    176     2     6    1  ---  CC: Breath            
       470  1  --    176     2     7    1  ---  CC: Breath            
       470  1  --    176     2     8    1  ---  CC: Breath            
       485  1  --    176     2     9    1  ---  CC: Breath            
       500  1  --    176     2    10    1  ---  CC: Breath            
       515  1  --    176     2    11    1  ---  CC: Breath            
       530  1  --    176     2    12    1  ---  CC: Breath            
       545  1  --    176     2    13    1  ---  CC: Breath            
       560  1  --    176     2    14    1  ---  CC: Breath            
       575  1  --    176     2    15    1  ---  CC: Breath            
       590  1  --    176     2    16    1  ---  CC: Breath            
       605  1  --    176     2    17    1  ---  CC: Breath            
       606  1  --    176     2    18    1  ---  CC: Breath            
       620  1  --    176     2    19    1  ---  CC: Breath            
       636  1  --    176     2    20    1  ---  CC: Breath            
       650  1  --    176     2    21    1  ---  CC: Breath            
       665  1  --    176     2    22    1  ---  CC: Breath            
       680  1  --    176     2    23    1  ---  CC: Breath            
       695  1  --    176     2    24    1  ---  CC: Breath            
       710  1  --    176     2    25    1  ---  CC: Breath            
       725  1  --    176     2    26    1  ---  CC: Breath            
       740  1  --    176     2    27    1  ---  CC: Breath            
       741  1  --    176     2    28    1  ---  CC: Breath            
       755  1  --    176     2    29    1  ---  CC: Breath            
       770  1  --    176     2    30    1  ---  CC: Breath            
       785  1  --    176     2    31    1  ---  CC: Breath            
       800  1  --    176     2    32    1  ---  CC: Breath            
       815  1  --    176     2    33    1  ---  CC: Breath            
       838  1  --    176     2    34    1  ---  CC: Breath            
       845  1  --    176     2    35    1  ---  CC: Breath            
       862  1  --    176     2    36    1  ---  CC: Breath            
       875  1  --    176     2    37    1  ---  CC: Breath            
       875  1  --    176     2    38    1  ---  CC: Breath            
       890  1  --    176     2    39    1  ---  CC: Breath            
       905  1  --    176     2    40    1  ---  CC: Breath            
       920  1  --    176     2    41    1  ---  CC: Breath            
       935  1  --    176     2    42    1  ---  CC: Breath            
       950  1  --    176     2    43    1  ---  CC: Breath            
       965  1  --    176     2    44    1  ---  CC: Breath            
       980  1  --    176     2    45    1  ---  CC: Breath            
       995  1  --    176     2    46    1  ---  CC: Breath            
      1010  1  --    176     2    47    1  ---  CC: Breath            
      1011  1  --    176     2    48    1  ---  CC: Breath            
      1025  1  --    176     2    49    1  ---  CC: Breath            
      1040  1  --    176     2    50    1  ---  CC: Breath            
      1055  1  --    176     2    51    1  ---  CC: Breath            
      1070  1  --    176     2    52    1  ---  CC: Breath            
      1085  1  --    176     2    53    1  ---  CC: Breath            
      1100  1  --    176     2    54    1  ---  CC: Breath            
      1115  1  --    176     2    55    1  ---  CC: Breath            
      1130  1  --    176     2    56    1  ---  CC: Breath            
      1145  1  --    176     2    57    1  ---  CC: Breath            
      1145  1  --    176     2    58    1  ---  CC: Breath            
      1160  1  --    176     2    59    1  ---  CC: Breath            
      1175  1  --    176     2    60    1  ---  CC: Breath            
      1190  1  --    176     2    61    1  ---  CC: Breath            
      1205  1  --    176     2    62    1  ---  CC: Breath            
      1227  1  --    176     2    63    1  ---  CC: Breath            
      1235  1  --    176     2    64    1  ---  CC: Breath            
      1250  1  --    176     2    65    1  ---  CC: Breath            
      1265  1  --    176     2    66    1  ---  CC: Breath            
      1280  1  --    176     2    67    1  ---  CC: Breath            
      1281  1  --    176     2    68    1  ---  CC: Breath            
      1295  1  --    176     2    69    1  ---  CC: Breath            
      1310  1  --    176     2    70    1  ---  CC: Breath            
      1325  1  --    176     2    71    1  ---  CC: Breath            
      1340  1  --    176     2    72    1  ---  CC: Breath            
      1355  1  --    176     2    73    1  ---  CC: Breath            
      1371  1  --    176     2    74    1  ---  CC: Breath            
      1385  1  --    176     2     0    1  ---  CC: Breath            
      1400  1  --    176     2     1    1  ---  CC: Breath            
      1415  1  --    176     2     2    1  ---  CC: Breath            
      1415  1  --    176     2     3    1  ---  CC: Breath            
      1430  1  --    176     2     4    1  ---  CC: Breath            
      1445  1  --    176     2     5    1  ---  CC: Breath            
      1460  1  --    176     2     6    1  ---  CC: Breath            
      1475  1  --    176     2     7    1  ---  CC: Breath            
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

#define SERVICE_UUID        "03b80e5a-ede8-4b33-a751-6ce34ec4c700"
#define CHARACTERISTIC_UUID "7772e5db-3868-4112-a1a9-f2669d106bf3"

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;

uint8_t midiPacket[] = {
   0x80,  // header
   0x80,  // timestamp, not implemented 
   0x00,  // status
   0x3c,  // 0x3c == 60 == middle c
   0x00   // velocity
};

void setup() {
    delay(500);
    Serial.begin(115200);
    BLE_init();
}

void loop() {
    noteOn(60, 120);
    for (;;) {
        for (int i=0; i<75; i++) {
            setBreath(i);
            delayMicroseconds(13333); // 75Hz
        }
    }
}

void setBreath(int value) {
    setTimestamp();
    midiPacket[2] = 0xB0;   // control change
    midiPacket[3] = 2;      // breath
    midiPacket[4] = value;  // value
    pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes
    pCharacteristic->notify();
}

void setTimestamp() {
    auto currentTimestamp = millis() & 0x01fff;
    midiPacket[0] = ((currentTimestamp >> 7) & 0x3f) | 0x80;
    midiPacket[1] = (currentTimestamp & 0x7f) | 0x80;
}

class MyServerCallbacks: public BLEServerCallbacks {
    
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      Serial.println("con0");
    };

    void onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t* param) {
        Serial.println("con1");
        esp_ble_conn_update_params_t conn_params = {0};
        memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
        conn_params.latency = 0;
        conn_params.max_int = 0x0c;    // max_int = 0x0c*1.25ms = 15ms
        conn_params.min_int = 0x06;    // min_int = 0x06*1.25ms = 7.5ms
        conn_params.timeout = 400;     // timeout = 400*10ms = 4000ms
        //start sent the update connection parameters to the peer device.
        esp_ble_gap_update_conn_params(&conn_params);
    }

    void onDisconnect(BLEServer* pServer) {
      Serial.println("discon");
      deviceConnected = false;
    }
};

void BLE_init() {
    BLEDevice::init("ESP32 MIDI Example");
    
    // Create the BLE Server
    BLEServer *pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());

    // Create the BLE Service
    BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));

    // Create a BLE Characteristic
    pCharacteristic = pService->createCharacteristic(
        BLEUUID(CHARACTERISTIC_UUID),
        BLECharacteristic::PROPERTY_READ   |
        BLECharacteristic::PROPERTY_WRITE  |
        BLECharacteristic::PROPERTY_NOTIFY |
        BLECharacteristic::PROPERTY_WRITE_NR
    );

    // Create a BLE Descriptor
    pCharacteristic->addDescriptor(new BLE2902());

    // Start the service
    pService->start();

    // Start advertising
    BLEAdvertising *pAdvertising = pServer->getAdvertising();
    pAdvertising->addServiceUUID(pService->getUUID());
    pAdvertising->start();
}

EWI USBからの出力

ふと気になって、手持ちのEWI USBからUSB経由で出力されるMIDIメッセージについて調べてみた。

MIDI-OXを使うとMIDIメッセージを観察できる。メニューOptions->Data displayのHexを外してタイムスタンプの単位を10進数(ms)に。Logも有効にしてみる。

息を吹き込むと次のデータが届くことが確認できる。

  • 最初に0x90(ノートオン)
  • 0xB002(コントロールチェンジ#2)と0xD0(アフタータッチ)が繰り返される data2は息の強さ
  • 最後に0x90(data2=0なのでノートオフ?)

コントロールチェンジだけを見てると概ね3ms毎に届いている。今使っている圧力センサLPS33HWは75Hzなので周期は13.3ms。ずいぶん荒くなる…

timestamp status data1 data2 chan event
9149 144 97 120 1 C# 7 Note On
9150 176 2 1 1 CC: Breath
9150 208 1 --- 1 Channel Aft
9153 176 2 2 1 CC: Breath
9153 208 2 --- 1 Channel Aft
9156 176 2 4 1 CC: Breath
9156 208 4 --- 1 Channel Aft
9162 176 2 6 1 CC: Breath
9162 208 6 --- 1 Channel Aft
9165 176 2 7 1 CC: Breath
9165 208 7 --- 1 Channel Aft
9167 176 2 8 1 CC: Breath
9168 208 8 --- 1 Channel Aft
9170 176 2 10 1 CC: Breath
9171 208 10 --- 1 Channel Aft
: : : : : :
14035 176 2 5 1 CC: Breath
14036 208 5 --- 1 Channel Aft
14038 176 2 1 1 CC: Breath
14038 208 1 --- 1 Channel Aft
14041 176 2 0 1 CC: Breath
14041 208 0 --- 1 Channel Aft
14041 144 97 0 1 C# 7 Note Off

BLE MIDI

iPadやWindows10とESP32をBluetoothでつなげることができた。

 

★ESP32のプログラム

このページで紹介されているBLE MIDIのサンプルプログラムを利用。midiPacket[2,3,4]の3byteにMIDIメッセージを格納すればいいらしい。MIDIメッセージについては以下が詳しい。

www.g200kg.com

iPAD

KORGBluetooth MIDI Connectをインストール。KORG製品でなくてもちゃんとつながる。らしいのだけど、役割がわからない。GarageBand内のBluetoothMIDIデバイスに表示されるようになるのか?とにかくつなげることができた。

 

★Windows10

こちらもKORGのBLE-MIDI Driver for Windowsをインストールしたらつながった。以下を参考にした。

av.watch.impress.co.jp

 

BLE MIDIによるレイテンシは気にならないレベル。WindowsVST音源やGarageBandの音源の音は豪華。ESP32に組み込んである内蔵音源にリバーブでもかけたら素敵になるかな。