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)に書き込まれる値は次の式で求まる.
,などはVCEDの設定値で決まる減衰量を表す.は0のときに最大,127で最小の出力レベルになる.キャリアとなるオペレータなら音量,モジュレータとなるオペレータなら変調度となる.最大となる0の値になどの減衰量を加算することでを決める.以下,各減衰量について述べる.
:マスターボリュームによる減衰量
前面パネルの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
:アルゴリズムによる減衰量
オペレータop1~op4によって異なる
- アルゴリズム1234:op1,2,3,4の減衰量は0
- アルゴリズム5:op1,3の減衰量は8,op2,4の減衰量は0
- アルゴリズム67:op1,2,3の減衰量は13,op4の減衰量は0
- アルゴリズム8:op1,2,3,4の減衰量は16
:Operator Output Levelによる減衰量
OL(Operator Output Level)との関係を以下に示す.
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
:Level Scalingによる減衰量
VCEDのLS(Level Scaling)の値と発音するMIDIノート番号によって決まる減衰量.LSは音の高さが高いほど単純な音質になる度合を0~127で表現するパラメータ.MIDIノート番号は音の高さを0~127で表現する番号.LSとMIDIノート番号からがどのような値を取るか以下に示す.
- 縦軸は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
:Key Velocity Sensitivityによる減衰量
VCEDのKVS(Key Velocity Sensitivity)の値と発音するMIDIのvelocity値によって決まる減衰量.KVSはvelocity値が大きいほど大きな出力になる度合を0~7で表現するパラメータ.velocity値は音の大きさ(打鍵の速さ?)を0~127で表現する番号.KVSとvelocityからがどのような値を取るか以下に示す.
- 縦軸はvelocityの値0~127.
- 横軸はkvsの値1~7.kvs=0のとき=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
: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も早いらしい。
teensy4.0とロジックレベル変換モジュールをつなげてみる。ESP32の苦労がウソのようにあっさり動いた。音を出していないときでも$28~$37(音の高さ)と$60~$7F(音の大きさ)に書き込み続けていることが分かった。詳しい解析はこれから。
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を改造してみることにする。現時点で追加・変更した機能は次の通り:
- 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をインストールして起動してみた。
YM2414ではなくTX81Zをエミューレートしているらしい。ブレスコントローラの入力を音に反映させる機能もあるみたい。リバーブも組み込めるようで素晴らしい。プリセットもたくさんある。ESP32で動かすことはできないだろうか?
BLE MIDIの通信
ESP32とWindows10の間でBLE MIDI通信したときに,頻度がどうなるか調べてみた.参考にしたのは
- プログラム全体:ここからたどったこのプログラム
- タイムスタンプの付け方:このプログラム
- コネクションインターバルの設定方法:onConect()内で設定
結果
- 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メッセージについては以下が詳しい。
★iPAD
KORGのBluetooth MIDI Connectをインストール。KORG製品でなくてもちゃんとつながる。らしいのだけど、役割がわからない。GarageBand内のBluetoothMIDIデバイスに表示されるようになるのか?とにかくつなげることができた。
★Windows10
こちらもKORGのBLE-MIDI Driver for Windowsをインストールしたらつながった。以下を参考にした。
BLE MIDIによるレイテンシは気にならないレベル。WindowsのVST音源やGarageBandの音源の音は豪華。ESP32に組み込んである内蔵音源にリバーブでもかけたら素敵になるかな。