アルトヴェノーヴァを手に入れた
ESP32によるWT11エミュレーションの実装は概ね終了した。実機と比較しても何となく同じような音が出ているような気がする。
FM音源的?な音色を聴いているうちに、だんだんと物理モデリング音源を鳴らしたくなってきた。STKの実装を見ていると、それほど難しくはなさそう。クラリネットとかサックスぽい音が出るみたい。
ところがパラメータを見ると、リードの固さとか息の強さとか、本物の吹奏楽器を触らないとよく理解できないものがあって実際のところが知りたくなった。特にリードの付いた楽器に興味が出てきた。リードの噛み方?によって音階が出るとか意味が分からない???
というわけでヤマハのアルトヴェノーヴァを購入してみた。思っていた以上に息を強く吹く必要があったり、リードがぶるぶる震えてたり、発見がある。まだまだ自由に音を出せる状態ではない。しばらく練習してみて、自作ウィンドシンセに反映できるといいと思う。
WT11が発声するボイスについて調べた
ウィンドシンセ用音源 Yamaha WT11はTX81Zと互換性がある。ただしWT11はTX81Zでいうパフォーマンスモードで動作する。音色の選択は96個あるパフォーマンスから1つを選択することで行う。1つのパフォーマンスは1つ以上のボイスから構成される。つまりMIDIのnote onを1つ受け取ると、複数のボイスを同時発声する。ボイスはTX81Zでいうシングルモードの音色に相当する。
A01~C32のパフォーマンスそれぞれが発生するボイスを以下に示す。ボイス番号(A01~D32)に続く「_数字」は、このボイスを割り当てたYM2414のチャンネル数を表す(1~8)。たとえば「A01 Oboe 1」なら、ch1~ch4にA01のボイスが、ch5~ch8にA02のボイスがセットされており、note onを受け取るたびにch1+ch5→ch2+ch6→ch3+ch7→ch4+ch8→ch1+ch5→...のように発声する。
Performance : Voices A01 Oboe 1 : A01_4 A02_4 A02 Oboe 2 : A03_4 A02_4 A03 Bassoon : A04_8 A04 Clarinet : A05_4 A26_4 A05 Piccolo : A08_8 A06 Flute : A06_4 A07_4 A07 PanFlute : A14_4 A14_4 A08 PuffPanFlt: A15_4 A16_1 A32_3 A09 SopranoSax: A12_3 A25_3 A27_2 A10 TenorSax 1: A10_2 A11_3 A26_3 A11 TenorSax 2: A10_2 A25_3 A26_3 A12 BaritonSax: A10_4 A09_4 A13 Recorder : A13_8 A14 Ocarina : A19_8 A15 Shakuhachi: A17_4 A18_4 A16 ClearWinds: A20_4 A20_4 A17 WoodWinds : A02_4 A04_4 A18 Picc/Clar : A05_4 A06_4 A19 PowerWood : A21_4 A21_4 A20 HolloWood : A22_8 A21 HardWood : A24_8 A22 ReedWinds : A03_4 A05_4 A23 SilverWind: A08_4 A13_4 A24 FatReed 1 : A23_4 A30_4 A25 FatReed 2 : A26_4 A30_4 A26 FluteEns. : A29_3 A29_3 A07_2 A27 Flute 5ths: A06_4 A06_4 A28 SaxSect.1 : A26_2 A25_2 A29 SaxSect.2 : A12_3 A26_3 A09_2 A30 Chime/Oboe: A02_4 A31_4 A31 BassoonDuo: A04_4 A04_4 A32 Mammoth ! : A04_3 A26_3 A31_1 A31_1 B01 Trumpet 1 : B26_4 B13_4 B02 Trumpet 2 : B02_4 B12_4 B03 MutedTrp. : B03_3 B03_2 B04_2 B01_1 B04 Flugel 1 : B18_4 B12_4 B05 Flugel 2 : B04_4 B04_4 B06 Trombone : B05_8 B07 FrenchHorn: B06_4 B06_4 B08 Tuba : B07_8 B09 BrassEns. : B05_3 B07_3 B05_2 B10 FusionBrs : B02_3 B05_3 B02_2 B11 HardPopBrs: B31_2 B05_2 B31_2 B13_2 B12 HvyPopBrs : B32_3 B05_3 B13_2 B13 ClassicBrs: B13_3 B04_3 B05_2 B14 ClassicHrn: B04_4 B06_4 B15 OrchHorns : B06_3 B06_3 B04_2 B16 MuteBrass : B05_3 B03_3 B03_2 B17 TuttiBrass: B13_1 B13_1 B05_1 B05_1 B13_1 B13_1 B07_1 B07_1 B18 HarmoSynth: B10_4 B10_4 B19 SmoothBrs : B11_4 B11_4 B20 DualSynth : B14_4 B14_4 B21 LyriSynth : B15_4 B15_4 B22 MelloSynth: B16_4 B16_4 B23 BuzzySynth: B17_4 B17_4 B24 SharpSynth: B20_4 B20_4 B25 SolidSynth: B21_4 B21_4 B26 SwampSynth: B09_4 B09_4 B27 SandyBrass: B25_4 B25_4 B28 AttackSyn.: B27_4 B08_4 B29 SynthBrs 1: B28_4 B10_4 B30 SynthBrs 2: B29_4 B28_4 B31 SynthBrs 3: B08_4 B08_4 B32 SynthOrch : B23_3 B24_3 B15_2 C01 Harmonica1: C01_8 C02 Harmonica2: C02_8 C03 Concertina: C03_4 C03_4 C04 Bandonion : C04_4 C04_4 C05 Accordion : C05_4 C05_4 C06 Violin : C19_4 C20_4 C07 Cello : D03_4 D04_4 C08 Strings : D06_3 D06_3 D06_2 C09 DualString: D06_3 D06_3 D06_2 C10 DistGuitar: C06_4 C07_4 C11 A.Guitar : C16_4 C17_4 C12 Fretless : C13_4 C13_4 C13 UpriteBass: C14_4 C15_4 C14 PipeOrgan : C29_4 C29_4 C15 Choir : D01_4 D01_4 C16 Whistle : C22_3 C22_3 C22_2 C17 Bells : C31_3 C31_3 C31_2 C18 GuitarSyn : C08_4 C08_4 C19 PortaLead : C18_4 C18_4 C20 Clavidion1: C09_4 C09_4 C21 Clavidion2: C10_4 C10_4 C22 SynthLead : C28_3 C28_3 C28_2 C23 FuzzySax : C11_4 C12_4 C24 Fuzz 5ths : C24_4 C24_4 C25 BreathHit : C25_4 C26_1 C26_1 C26_1 C26_1 C26 Breath 5th: C25_4 C25_1 C25_1 C25_1 C25_1 C27 TalkingBox: C30_3 C30_3 C30_2 C28 HarmoWhist: D07_3 D08_3 D08_2 C29 SpaceDust : D02_3 D05_3 D02_2 C30 Str/Flute : D16_2 D16_2 D16_2 D09_2 C31 Str/Oboe : D16_2 D16_2 D16_2 D15_2 C32 FreeJazz : D11_4 D12_4
Voice [Performances] A01 [A01_Oboe 1 ] A02 [A01_Oboe 1 , A02_Oboe 2 , A17_WoodWinds , A30_Chime/Oboe] A03 [A02_Oboe 2 , A22_ReedWinds ] A04 [A03_Bassoon , A17_WoodWinds , A31_BassoonDuo, A31_BassoonDuo, A32_Mammoth ! ] A05 [A04_Clarinet , A18_Picc/Clar , A22_ReedWinds ] A06 [A06_Flute , A18_Picc/Clar , A27_Flute 5ths, A27_Flute 5ths] A07 m[A06_Flute , A26_FluteEns. ] A08 [A05_Piccolo , A23_SilverWind] A09 [A12_BaritonSax, A29_SaxSect.2 ] A10 0m[A10_TenorSax 1, A11_TenorSax 2, A12_BaritonSax] A11 [A10_TenorSax 1] A12 [A09_SopranoSax, A29_SaxSect.2 ] A13 [A13_Recorder , A23_SilverWind] A14 [A07_PanFlute , A07_PanFlute ] A15 [A08_PuffPanFlt] A16 m[A08_PuffPanFlt] A17 [A15_Shakuhachi] A18 [A15_Shakuhachi] A19 [A14_Ocarina ] A20 [A16_ClearWinds, A16_ClearWinds] A21 [A19_PowerWood , A19_PowerWood ] A22 [A20_HolloWood ] A23 [A24_FatReed 1 ] A24 [A21_HardWood ] A25 [A09_SopranoSax, A11_TenorSax 2, A28_SaxSect.1 ] A26 [A04_Clarinet , A10_TenorSax 1, A11_TenorSax 2, A25_FatReed 2 , A28_SaxSect.1 , A29_SaxSect.2 , A32_Mammoth ! ] A27 m[A09_SopranoSax] A28 [] A29 [A26_FluteEns. , A26_FluteEns. ] A30 [A24_FatReed 1 , A25_FatReed 2 ] A31 m[A30_Chime/Oboe, A32_Mammoth ! , A32_Mammoth ! ] A32 [A08_PuffPanFlt] B01 m[B03_MutedTrp. ] B02 [B02_Trumpet 2 , B10_FusionBrs , B10_FusionBrs ] B03 [B03_MutedTrp. , B03_MutedTrp. , B16_MuteBrass , B16_MuteBrass ] B04 [B03_MutedTrp. , B05_Flugel 2 , B05_Flugel 2 , B13_ClassicBrs, B14_ClassicHrn, B15_OrchHorns ] B05 [B06_Trombone , B09_BrassEns. , B09_BrassEns. , B10_FusionBrs , B11_HardPopBrs, B12_HvyPopBrs , B13_ClassicBrs, B16_MuteBrass , B17_TuttiBrass, B17_TuttiBrass] B06 [B07_FrenchHorn, B07_FrenchHorn, B14_ClassicHrn, B15_OrchHorns , B15_OrchHorns ] B07 [B08_Tuba , B09_BrassEns. , B17_TuttiBrass, B17_TuttiBrass] B08 [B28_AttackSyn., B31_SynthBrs 3, B31_SynthBrs 3] B09 m[B26_SwampSynth, B26_SwampSynth] B10 [B18_HarmoSynth, B18_HarmoSynth, B29_SynthBrs 1] B11 [B19_SmoothBrs , B19_SmoothBrs ] B12 m[B02_Trumpet 2 , B04_Flugel 1 ] B13 [B01_Trumpet 1 , B11_HardPopBrs, B12_HvyPopBrs , B13_ClassicBrs, B17_TuttiBrass, B17_TuttiBrass, B17_TuttiBrass, B17_TuttiBrass] B14 [B20_DualSynth , B20_DualSynth ] B15 [B21_LyriSynth , B21_LyriSynth , B32_SynthOrch ] B16 [B22_MelloSynth, B22_MelloSynth] B17 [B23_BuzzySynth, B23_BuzzySynth] B18 [B04_Flugel 1 ] B19 [] B20 [B24_SharpSynth, B24_SharpSynth] B21 [B25_SolidSynth, B25_SolidSynth] B22 [] B23 [B32_SynthOrch ] B24 [B32_SynthOrch ] B25 [B27_SandyBrass, B27_SandyBrass] B26 m[B01_Trumpet 1 ] B27 m[B28_AttackSyn.] B28 [B29_SynthBrs 1, B30_SynthBrs 2] B29 [B30_SynthBrs 2] B30 [] B31 [B11_HardPopBrs, B11_HardPopBrs] B32 [B12_HvyPopBrs ] C01 [C01_Harmonica1] C02 [C02_Harmonica2] C03 [C03_Concertina, C03_Concertina] C04 [C04_Bandonion , C04_Bandonion ] C05 [C05_Accordion , C05_Accordion ] C06 [C10_DistGuitar] C07 [C10_DistGuitar] C08 [C18_GuitarSyn , C18_GuitarSyn ] C09 [C20_Clavidion1, C20_Clavidion1] C10 [C21_Clavidion2, C21_Clavidion2] C11 [C23_FuzzySax ] C12 [C23_FuzzySax ] C13 [C12_Fretless , C12_Fretless ] C14 0m[C13_UpriteBass] C15 0 [C13_UpriteBass] C16 0m[C11_A.Guitar ] C17 0 [C11_A.Guitar ] C18 m[C19_PortaLead , C19_PortaLead ] C19 [C06_Violin ] C20 [C06_Violin ] C21 [] C22 [C16_Whistle , C16_Whistle , C16_Whistle ] C23 0m[] C24 [C24_Fuzz 5ths , C24_Fuzz 5ths ] C25 [C25_BreathHit , C26_Breath 5th, C26_Breath 5th, C26_Breath 5th, C26_Breath 5th, C26_Breath 5th] C26 m[C25_BreathHit , C25_BreathHit , C25_BreathHit , C25_BreathHit ] C27 [] C28 [C22_SynthLead , C22_SynthLead , C22_SynthLead ] C29 [C14_PipeOrgan , C14_PipeOrgan ] C30 [C27_TalkingBox, C27_TalkingBox, C27_TalkingBox] C31 [C17_Bells , C17_Bells , C17_Bells ] C32 0 [] D01 [C15_Choir , C15_Choir ] D02 [C29_SpaceDust , C29_SpaceDust ] D03 [C07_Cello ] D04 [C07_Cello ] D05 [C29_SpaceDust ] D06 [C08_Strings , C08_Strings , C08_Strings , C09_DualString, C09_DualString, C09_DualString] D07 [C28_HarmoWhist] D08 [C28_HarmoWhist, C28_HarmoWhist] D09 [C30_Str/Flute ] D10 0 [] D11 [C32_FreeJazz ] D12 [C32_FreeJazz ] D13 [] D14 [] D15 [C31_Str/Oboe ] D16 [C30_Str/Flute , C30_Str/Flute , C30_Str/Flute , C31_Str/Oboe , C31_Str/Oboe , C31_Str/Oboe ] D17 0 [] D18 0 [] D19 0 [] D20 0 [] D21 0 [] D22 0 [] D23 0 [] D24 0 [] D25 0 [] D26 0 [] D27 0 [] D28 0 [] D29 0 [] D30 0 [] D31 0 [] D32 0 []
- [ ]の前に m が付いているボイスはMonoモード(Polyモードではない=エンベロープをリトリガしない)
- [ ]の前に 0 が付いているボイスはBCEG bias=0(他は全て99)「プァン」という音の出だしの表現?
他に気づいたこと:
- Portament time > 0 なのはボイスC18のみ
- OP1~4のKVS(Key Velocity Sensitivity、note onで与えられるvelocity値の感度)が0以外のものもある。
- OP1~4のEBS(EG Bias Sensitivity、ブレスが音量に与える影響の感度)が7以外のものもある。
TX81Zを解析した(パフォーマンスモード編 追記)
TX81ZのPCEDの設定項目「Volume」について調査し忘れていた。パフォーマンスモードで設定できる8つの楽器ごとに音量を設定するためのパラメータである。
VCEDのVolumeと同様に0~99の値を指定する。YM2414のTLレジスタにセットされる値に影響することも同様。4つのオペレータのうち、キャリアとなるオペレータのみに影響することも同様。
次の値がTLレジスタに書き込まれる値に加算される。TLレジスタは値が0の時に音量最大となり、値が127の時に音量最小となる。
vol 加算値 0 127 1 127 2 96 3 86 4 77 5 72 6 67 7 62 8 60 9 56 10 54 11 51 12 50 13 48 14 45 15 44 16 42 17 41 18 40 19 39 20 37 21 36 22 35 23 34 24 33 25 32 26 31 27 30 28 29 29 28 30 28 31 27 32 26 33 25 34 25 35 24 36 23 37 23 38 22 39 21 40 21 41 20 42 20 43 19 44 19 45 18 46 18 47 17 48 17 49 16 50 16 51 15 52 15 53 14 54 14 55 13 56 13 57 13 58 12 59 12 60 11 61 11 62 11 63 10 64 10 65 9 66 9 67 9 68 8 69 8 70 8 71 7 72 7 73 7 74 7 75 6 76 6 77 6 78 5 79 5 80 5 81 4 82 4 83 4 84 3 85 3 86 3 87 3 88 2 89 2 90 2 91 2 92 1 93 1 94 1 95 1 96 0 97 0 98 0 99 0
TX81Zを解析した(パフォーマンスモード編)
TX81Zに搭載されているOPZは(OPMと同様に)異なる8音を同時に発声する能力を持つ。1つのNote on信号を受信するとシングルモードでは1音を発声するのに対し、パフォーマンスモードでは2つ以上の音を同時に発声することができる。どのように組み合わせるかはPCED(Performance Edit Parameters)で指定する。
以下、Instrument Detuneというパラメータの働きを述べる。音の高さを微妙にずらすためのもので、音の厚み?を増やすのに使うようだ。-7~+7の値をとる。OPZのKF(Key Fraction:半音の1/64)に素直に加算されるかと思っていたが、その加算量は音の高さによって異なることが解析の結果判明した。
まず音の高さから。発声される音の高さは次のように決まる:
- MIDIのNote on信号で0~127が指定される
- この値にVCEDのTransposeパラメータで-24~+24が加算される
- さらにPCEDのNoteShiftパラメータで-24~+24が加算される
- 12以下の場合、13以上になるまで12を足す
- 109以上の場合、108以下になるまで12を引く
- この結果、音の高さ は13(C#-1)~108(C7)となる。真ん中のドは60(C3)。
この音の高さとInstrument Detuneパラメータの値でKF=0からずらす量が決まる。
横軸: Instrument Detune (-7~7) 縦軸: (音の高さ - 13) / 4 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 +------------------------------------------------------- 0 | -17 -15 -12 -10 -8 -5 -3 0 2 4 7 9 12 14 17 1 | -17 -15 -12 -10 -7 -5 -3 0 2 4 7 9 11 14 16 2 | -16 -14 -12 -10 -7 -5 -3 0 2 4 6 9 11 13 16 3 | -16 -14 -12 -9 -7 -5 -3 0 2 4 6 9 11 13 15 4 | -16 -13 -11 -9 -7 -5 -2 0 2 4 6 8 10 13 15 5 | -15 -13 -11 -9 -7 -5 -2 0 2 4 6 8 10 12 14 6 | -15 -13 -11 -9 -6 -4 -2 0 2 4 6 8 10 12 14 7 | -14 -12 -10 -8 -6 -4 -2 0 2 4 6 8 10 12 14 8 | -14 -12 -10 -8 -6 -4 -2 0 1 3 5 7 9 11 13 9 | -13 -12 -10 -8 -6 -4 -2 0 1 3 5 7 9 11 13 10 | -13 -11 -9 -8 -6 -4 -2 0 1 3 5 7 9 10 12 11 | -13 -11 -9 -7 -6 -4 -2 0 1 3 5 7 8 10 12 12 | -12 -10 -9 -7 -5 -4 -2 0 1 3 5 6 8 10 11 13 | -12 -10 -8 -7 -5 -4 -2 0 1 3 4 6 8 9 11 14 | -11 -10 -8 -7 -5 -3 -2 0 1 3 4 6 7 9 10 15 | -11 -9 -8 -6 -5 -3 -2 0 1 3 4 6 7 9 10 16 | -10 -9 -7 -6 -5 -3 -2 0 1 2 4 5 7 8 10 17 | -10 -9 -7 -6 -4 -3 -2 0 1 2 4 5 6 8 9 18 | -9 -8 -7 -6 -4 -3 -2 0 1 2 3 5 6 7 9 19 | -9 -8 -7 -5 -4 -3 -2 0 1 2 3 5 6 7 8 20 | -9 -7 -6 -5 -4 -3 -1 0 1 2 3 4 5 7 8 21 | -8 -7 -6 -5 -4 -3 -1 0 1 2 3 4 5 6 7 22 | -8 -7 -6 -5 -3 -2 -1 0 1 2 3 4 5 6 7 23 | -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
あとは実装。しばらくプログラムから離れていたので思い出すところから。エミュレーションしたいのはWT11なので、TX81Zの解析結果がそのまま適用できるか微妙…。
WT11固有のパラメータ
WT11のエディットバッファ内のボイスデータ・パフォーマンスデータをTX81Z Programmerで取得する、という記事を前回書いた。その後マニュアルを眺めていたらTX81Zにはない固有のパラメータが存在するのに気が付いた。
ボイスデータについては、TX81ZのVCED・ACEDに加えWT11にはACED2というデータがある。アフタータッチの感度などを設定できる。
パフォーマンスデータについては、TX81ZのPCEDに加えWT11にはPCED2というデータがある。DSPエフェクタの設定項目のように見える。
ACED2・PCED2はTX81Z Programmerでは取得できなそうなので、吸出しプログラムを作ってみた。WT11はsecret modeで起動した後に本体のキーでボイスやパフォーマンスを変更するとsysexをMIDIに出力するようなので、それを拾って表示することにした。
ボイスデータを変更すると、こんなsysexデータが出力される。各行の先頭の数字はsysexのサイズ。マニュアルのTOTAL BULK SIZEにあるように、VCED=101、ACED=41、ACED2=28bytesとなる。
101:f0 43 00 03 00 5d 14 12 00 07 0f 0a 01 04 00 00 46 0a 03 1f 1f 00 07 0f 0f 01 03 00 00 44 04 03 15 14 00 05 0f 09 01 02 00 00 2f 08 03 12 1f 00 0b 0f 1f 01 05 00 00 63 0a 03 03 00 1f 0a 00 00 00 02 05 00 18 00 02 00 00 28 01 00 00 0f 00 0f 00 32 63 57 54 31 31 20 20 41 30 31 20 63 63 63 32 32 32 56 f7 41:f0 43 00 7e 00 21 4c 4d 20 20 38 39 37 36 41 45 00 00 00 02 00 00 00 00 01 00 00 00 00 03 00 00 00 00 03 00 00 00 00 3a f7 28:f0 43 00 7e 00 14 4c 4d 20 20 38 30 32 33 41 45 00 00 32 00 00 00 00 00 00 00 22 f7
一方パフォーマンスデータのsysexデータはこんな感じ。PCED=128、PCED2=51bytesとなる。
128:f0 43 00 7e 00 78 4c 4d 20 20 38 39 37 36 50 45 04 00 20 00 00 3b 07 18 47 03 01 00 04 00 21 00 00 7f 07 18 63 03 01 00 00 00 20 00 00 7f 07 18 63 03 00 00 00 00 20 00 00 7f 07 18 63 03 00 00 00 00 20 00 00 7f 07 18 63 03 00 00 00 00 20 00 00 7f 07 18 63 03 00 00 00 00 20 00 00 7f 07 18 63 03 00 00 00 00 20 00 00 7f 07 18 63 03 00 00 00 00 00 00 4f 62 6f 65 20 31 20 20 20 20 13 f7 51:f0 43 00 7e 00 2b 4c 4d 20 20 38 30 37 33 50 45 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 01 25 64 00 14 00 00 00 00 00 00 00 00 00 00 00 00 1a f7
プログラムはJavaで作った。Javaは意外とMIDI関連ライブラリが充実している。
import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiMessage; import javax.sound.midi.MidiSystem; import javax.sound.midi.Receiver; import javax.sound.midi.SysexMessage; import javax.sound.midi.Transmitter; /** * WT11をsecret modeで起動すると, * 本体のキーでボイス/パフォーマンスを切り替えるときにMIDIにダンプデータが出てくる * これを拾って表示する */ public class WT11sysex { Receiver receiver; Transmitter transmitter; MidiDevice deviceIn, deviceOut; WT11sysex() { String AUDIOIF = "UR22mkII"; // オーディオインタフェース名 try { MidiDevice.Info info[] = MidiSystem.getMidiDeviceInfo(); for (MidiDevice.Info i: info) { MidiDevice device = MidiSystem.getMidiDevice(i); String name = i.getName(); String desc = i.getDescription(); System.out.printf("%s ## %s\n", name, desc); if (name.contains(AUDIOIF) && device.getMaxReceivers() != 0) deviceOut = device; if (name.contains(AUDIOIF) && device.getMaxTransmitters() != 0) deviceIn = device; } deviceOut.open(); receiver = deviceOut.getReceiver(); deviceIn.open(); transmitter = deviceIn.getTransmitter(); transmitter.setReceiver(new MyReceiver()); } catch (Exception e) { e.printStackTrace(); } } void shutdown() { receiver.close(); transmitter.close(); deviceOut.close(); deviceIn.close(); } /** 拾ったsysexデータを表示する */ class MyReceiver implements Receiver { @Override public void send(MidiMessage message, long timeStamp) { int len = message.getLength(); byte b[] = message.getMessage(); System.out.printf("%5d:", len); for (int i=0; i<len; i++) System.out.printf("%02x ", b[i]); System.out.println(); } @Override public void close() { } } /** SYSEXを送る予定だったが不要だった */ void sendSysex() { try { int seq[] = { 0xf0,0x43,0x20,0x7e,'L','M',' ',' ','8','0','2','3','A','E',0xf7 }; // (3)ACED2 + ACED + VCED byte b[] = new byte[seq.length]; for (int i=0; i<seq.length; i++) b[i] = (byte)(seq[i] & 0xff); SysexMessage message = new SysexMessage(b, b.length); receiver.send(message, -1); } catch (Exception ex) { ex.printStackTrace(); } } /** 60秒のうちにキーで切り替える */ public static void main(String args[]) throws Exception { WT11sysex wt11 = new WT11sysex(); //wt11.sendSysex(); Thread.sleep(60000); wt11.shutdown(); } }
WT11をゲットした
TX81Zを検索していると、ちょいちょいWT11のページも引っかかる。面白そうなので中古品を買ってみた。
WT11はYAMAHAから発売された音源モジュール。プリセットのほとんどが木管/金管楽器でWX11などのブレス入力MIDIコントローラーとつないで使う。Wikipediaによると30年以上前の設計のようだ。
- 1986年:TX81Z発売(FMシンセサイザ)
- 1987年:WX7発売(MIDIコントローラー)
- 1988年:WX11発売( 〃 )
- 1988年:WT11発売(FMシンセサイザ)
- 1998年:WX5発売(MIDIコントローラー 10年経ってからの発売)
WT11の中身はTX81Zとほぼ同じでエフェクタ付き、という仕様なのが分かった。TX81Zとも互換性?があるようだ。シークレットモードへの移行方法も説明されている。
ameblo.jp
というわけで、次の目標は「WT11のプリセットを自作ウィンドシンセで鳴らす」ということにする。まずはプリセットデータの取り出しから行った。
WT11はTX81Zで言うパフォーマンスモードで動いている。取り出すべきデータは次の2つ:
- PCED (Performance Edit Parameters):96個
- VCED+ACED (Voice Edit Parameters + Additional Parameters):112個
取説の40ページによると、これらをパフォーマンスエディットバッファ・ボイスエディットバッファに入れればMIDI経由で読み取れるように見える。TX81Z Programmerで取り出しを行った。
PCEDデータの取り出しは通常モードでできる。「A01 Oboe 1」~「C32 FreeJazz」という名前のデータ96個を得ることができた。
VCED+ACEDデータの取り出しはシークレットモードへの移行が必要(通常モードだとバッファにセットする方法がなさそうなので)。ちょっと変則的な名前がついていて、
- 「WT11 A01 」~「WT11 A32 」
- 「WT11 B01 」~「WT11 B32 」
- 「WT11 C01 」~「WT11 C32 」
- 「WT11-D01」~「WT11-D16」
という名前のデータ112個を得ることができた。パフォーマンスモードの実装はこれから。
話は変わるがちょっと前にティンホイッスルを買った。強く息を吹くとオクターブが高くなるという不思議な楽器だ。楽譜も買った。アイリッシュ音楽は祝祭感があってよいと思う(無印ぽい気もするが)。
celtnofue.com
リバーブつけた
今までのなんちゃってリバーブをFreeverbに変更した。ソースコードは以下のページからリンクされているページで入手できる。
prettoguitar.blogspot.com
リンク先はFreeverb3というVSTの作者のページ。Freeverbより音質がよいらしい。ESP32で動くかどうかは分からない。
freeverb3vst.osdn.jp
freeverbsource.zipをダウンロードし、
- allpass.cpp, allpass.hpp
- comb.cpp, comb.hpp
- denormals.h
- revmodel.cpp, revmodel.hpp
- tuning.h
をESP32ソースファイルの置き場所にコピーし、
revmodel *freeverb;
:
freeverb = new revmodel();
でリバーブモデル?を生成しておく。入出力バッファを
float revInput1[64], revInput2[64]; float revOutput1[64], revOutput2[64];
で64サンプル×2ch分確保しておく。ym2151.cのym2151_update_one()で得られる64サンプル2ch分をrevInput1/2[]に格納して
freeverb->processreplace(revInput1, revInput2, revOutput1, revOutput2, 64, 1);
を呼び出すとrevOutput1/2[]に出力される。これをi2s_write()に渡すとリバーブされた音が出る。思っていた以上にきれいな音だった。耳の肥えていない自分にはこれで十分かな。パラメータはroomsize, damp, wet, dry, widthの5つ。tuning.hに初期値が設定してある。dryが0だったので0.67に変更した。
ESP32で処理するときの負荷だが、44100サンプル作るのに
だった。結構ぎりぎり! 今はcore0で実行している。BLE MIDIと一緒に使うのは無理かもしれない。