1 // Copyright (C) 2013-2016 Alexey Khokholov (Nuke.YKT) 2 // 3 // This program is free software; you can redistribute it and/or 4 // modify it under the terms of the GNU General Public License 5 // as published by the Free Software Foundation; either version 2 6 // of the License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // 14 // Nuked OPL3 emulator. 15 // Thanks: 16 // MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh): 17 // Feedback and Rhythm part calculation information. 18 // forums.submarine.org.uk(carbon14, opl3): 19 // Tremolo and phase generator calculation information. 20 // OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): 21 // OPL2 ROMs. 22 // 23 // version: 1.7.4 24 /++ 25 OPL3 (1990's midi chip) emulator. 26 27 License: 28 GPL2 29 Authors: 30 Originally written in C by Alexey Khokholov, ported to D by ketmar, very slightly modified by me. 31 +/ 32 module arsd.nukedopl3 /*is aliced*/; 33 nothrow @trusted @nogc: 34 35 public: 36 enum OPL_WRITEBUF_SIZE = 1024; 37 enum OPL_WRITEBUF_DELAY = 2; 38 39 40 // ////////////////////////////////////////////////////////////////////////// // 41 version(genmidi_dumper) import iv.strex; 42 43 44 // ////////////////////////////////////////////////////////////////////////// // 45 private: 46 enum OPL_RATE = 49716; 47 48 struct OPL3Slot { 49 OPL3Channel* channel; 50 OPL3Chip* chip; 51 short out_; 52 short fbmod; 53 short* mod; 54 short prout; 55 short eg_rout; 56 short eg_out; 57 ubyte eg_inc; 58 ubyte eg_gen; 59 ubyte eg_rate; 60 ubyte eg_ksl; 61 ubyte *trem; 62 ubyte reg_vib; 63 ubyte reg_type; 64 ubyte reg_ksr; 65 ubyte reg_mult; 66 ubyte reg_ksl; 67 ubyte reg_tl; 68 ubyte reg_ar; 69 ubyte reg_dr; 70 ubyte reg_sl; 71 ubyte reg_rr; 72 ubyte reg_wf; 73 ubyte key; 74 uint pg_phase; 75 uint timer; 76 } 77 78 struct OPL3Channel { 79 OPL3Slot*[2] slots; 80 OPL3Channel* pair; 81 OPL3Chip* chip; 82 short*[4] out_; 83 ubyte chtype; 84 ushort f_num; 85 ubyte block; 86 ubyte fb; 87 ubyte con; 88 ubyte alg; 89 ubyte ksv; 90 ushort cha, chb; 91 } 92 93 struct OPL3WriteBuf { 94 ulong time; 95 ushort reg; 96 ubyte data; 97 } 98 99 /// 100 public struct OPL3Chip { 101 private: 102 OPL3Channel[18] channel; 103 OPL3Slot[36] slot; 104 ushort timer; 105 ubyte newm; 106 ubyte nts; 107 ubyte rhy; 108 ubyte vibpos; 109 ubyte vibshift; 110 ubyte tremolo; 111 ubyte tremolopos; 112 ubyte tremoloshift; 113 uint noise; 114 short zeromod; 115 int[2] mixbuff; 116 //OPL3L 117 int rateratio; 118 int samplecnt; 119 short[2] oldsamples; 120 short[2] samples; 121 122 ulong writebuf_samplecnt; 123 uint writebuf_cur; 124 uint writebuf_last; 125 ulong writebuf_lasttime; 126 OPL3WriteBuf[OPL_WRITEBUF_SIZE] writebuf; 127 } 128 129 130 private: 131 enum RSM_FRAC = 10; 132 133 // Channel types 134 135 enum { 136 ch_2op = 0, 137 ch_4op = 1, 138 ch_4op2 = 2, 139 ch_drum = 3 140 } 141 142 // Envelope key types 143 144 enum { 145 egk_norm = 0x01, 146 egk_drum = 0x02 147 } 148 149 150 // 151 // logsin table 152 // 153 154 static immutable ushort[256] logsinrom = [ 155 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471, 156 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365, 157 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd, 158 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261, 159 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f, 160 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd, 161 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195, 162 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166, 163 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c, 164 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118, 165 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8, 166 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db, 167 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1, 168 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9, 169 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094, 170 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081, 171 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070, 172 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060, 173 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052, 174 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045, 175 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039, 176 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f, 177 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026, 178 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e, 179 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017, 180 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011, 181 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c, 182 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007, 183 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004, 184 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002, 185 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 186 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 187 ]; 188 189 // 190 // exp table 191 // 192 193 static immutable ushort[256] exprom = [ 194 0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014, 195 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a, 196 0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042, 197 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a, 198 0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072, 199 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b, 200 0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4, 201 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be, 202 0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9, 203 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4, 204 0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110, 205 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c, 206 0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149, 207 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167, 208 0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185, 209 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4, 210 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 211 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4, 212 0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205, 213 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227, 214 0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249, 215 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d, 216 0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291, 217 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5, 218 0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db, 219 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302, 220 0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329, 221 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351, 222 0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a, 223 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4, 224 0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf, 225 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa 226 ]; 227 228 // 229 // freq mult table multiplied by 2 230 // 231 // 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 232 // 233 234 static immutable ubyte[16] mt = [ 235 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30 236 ]; 237 238 // 239 // ksl table 240 // 241 242 static immutable ubyte[16] kslrom = [ 243 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64 244 ]; 245 246 static immutable ubyte[4] kslshift = [ 247 8, 1, 2, 0 248 ]; 249 250 // 251 // envelope generator constants 252 // 253 254 static immutable ubyte[8][4][3] eg_incstep = [ 255 [ 256 [ 0, 0, 0, 0, 0, 0, 0, 0 ], 257 [ 0, 0, 0, 0, 0, 0, 0, 0 ], 258 [ 0, 0, 0, 0, 0, 0, 0, 0 ], 259 [ 0, 0, 0, 0, 0, 0, 0, 0 ] 260 ], 261 [ 262 [ 0, 1, 0, 1, 0, 1, 0, 1 ], 263 [ 0, 1, 0, 1, 1, 1, 0, 1 ], 264 [ 0, 1, 1, 1, 0, 1, 1, 1 ], 265 [ 0, 1, 1, 1, 1, 1, 1, 1 ] 266 ], 267 [ 268 [ 1, 1, 1, 1, 1, 1, 1, 1 ], 269 [ 2, 2, 1, 1, 1, 1, 1, 1 ], 270 [ 2, 2, 1, 1, 2, 2, 1, 1 ], 271 [ 2, 2, 2, 2, 2, 2, 1, 1 ] 272 ] 273 ]; 274 275 static immutable ubyte[16] eg_incdesc = [ 276 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 277 ]; 278 279 static immutable byte[16] eg_incsh = [ 280 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2 281 ]; 282 283 // 284 // address decoding 285 // 286 287 static immutable byte[0x20] ad_slot = [ 288 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1, 289 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 290 ]; 291 292 static immutable ubyte[18] ch_slot = [ 293 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 294 ]; 295 296 // 297 // Envelope generator 298 // 299 300 alias envelope_sinfunc = short function (ushort phase, ushort envelope) nothrow @trusted @nogc; 301 alias envelope_genfunc = void function (OPL3Slot *slott) nothrow @trusted @nogc; 302 303 private short OPL3_EnvelopeCalcExp (uint level) { 304 if (level > 0x1fff) level = 0x1fff; 305 return cast(short)(((exprom.ptr[(level&0xff)^0xff]|0x400)<<1)>>(level>>8)); 306 } 307 308 private short OPL3_EnvelopeCalcSin0 (ushort phase, ushort envelope) { 309 ushort out_ = 0; 310 ushort neg = 0; 311 phase &= 0x3ff; 312 if (phase&0x200) neg = ushort.max; 313 if (phase&0x100) out_ = logsinrom.ptr[(phase&0xff)^0xff]; else out_ = logsinrom.ptr[phase&0xff]; 314 return OPL3_EnvelopeCalcExp(out_+(envelope<<3))^neg; 315 } 316 317 private short OPL3_EnvelopeCalcSin1 (ushort phase, ushort envelope) { 318 ushort out_ = 0; 319 phase &= 0x3ff; 320 if (phase&0x200) out_ = 0x1000; 321 else if (phase&0x100) out_ = logsinrom.ptr[(phase&0xff)^0xff]; 322 else out_ = logsinrom.ptr[phase&0xff]; 323 return OPL3_EnvelopeCalcExp(out_+(envelope<<3)); 324 } 325 326 private short OPL3_EnvelopeCalcSin2 (ushort phase, ushort envelope) { 327 ushort out_ = 0; 328 phase &= 0x3ff; 329 if (phase&0x100) out_ = logsinrom.ptr[(phase&0xff)^0xff]; else out_ = logsinrom.ptr[phase&0xff]; 330 return OPL3_EnvelopeCalcExp(out_+(envelope<<3)); 331 } 332 333 private short OPL3_EnvelopeCalcSin3 (ushort phase, ushort envelope) { 334 ushort out_ = 0; 335 phase &= 0x3ff; 336 if (phase&0x100) out_ = 0x1000; else out_ = logsinrom.ptr[phase&0xff]; 337 return OPL3_EnvelopeCalcExp(out_+(envelope<<3)); 338 } 339 340 private short OPL3_EnvelopeCalcSin4 (ushort phase, ushort envelope) { 341 ushort out_ = 0; 342 ushort neg = 0; 343 phase &= 0x3ff; 344 if ((phase&0x300) == 0x100) neg = ushort.max; 345 if (phase&0x200) out_ = 0x1000; 346 else if (phase&0x80) out_ = logsinrom.ptr[((phase^0xff)<<1)&0xff]; 347 else out_ = logsinrom.ptr[(phase<<1)&0xff]; 348 return OPL3_EnvelopeCalcExp(out_+(envelope<<3))^neg; 349 } 350 351 private short OPL3_EnvelopeCalcSin5 (ushort phase, ushort envelope) { 352 ushort out_ = 0; 353 phase &= 0x3ff; 354 if (phase&0x200) out_ = 0x1000; 355 else if (phase&0x80) out_ = logsinrom.ptr[((phase^0xff)<<1)&0xff]; 356 else out_ = logsinrom.ptr[(phase<<1)&0xff]; 357 return OPL3_EnvelopeCalcExp(out_+(envelope<<3)); 358 } 359 360 private short OPL3_EnvelopeCalcSin6 (ushort phase, ushort envelope) { 361 ushort neg = 0; 362 phase &= 0x3ff; 363 if (phase&0x200) neg = ushort.max; 364 return OPL3_EnvelopeCalcExp(envelope<<3)^neg; 365 } 366 367 private short OPL3_EnvelopeCalcSin7 (ushort phase, ushort envelope) { 368 ushort out_ = 0; 369 ushort neg = 0; 370 phase &= 0x3ff; 371 if (phase&0x200) { 372 neg = ushort.max; 373 phase = (phase&0x1ff)^0x1ff; 374 } 375 out_ = cast(ushort)(phase<<3); 376 return OPL3_EnvelopeCalcExp(out_+(envelope<<3))^neg; 377 } 378 379 static immutable envelope_sinfunc[8] envelope_sin = [ 380 &OPL3_EnvelopeCalcSin0, 381 &OPL3_EnvelopeCalcSin1, 382 &OPL3_EnvelopeCalcSin2, 383 &OPL3_EnvelopeCalcSin3, 384 &OPL3_EnvelopeCalcSin4, 385 &OPL3_EnvelopeCalcSin5, 386 &OPL3_EnvelopeCalcSin6, 387 &OPL3_EnvelopeCalcSin7 388 ]; 389 390 static immutable envelope_genfunc[5] envelope_gen = [ 391 &OPL3_EnvelopeGenOff, 392 &OPL3_EnvelopeGenAttack, 393 &OPL3_EnvelopeGenDecay, 394 &OPL3_EnvelopeGenSustain, 395 &OPL3_EnvelopeGenRelease 396 ]; 397 398 alias envelope_gen_num = int; 399 enum /*envelope_gen_num*/:int { 400 envelope_gen_num_off = 0, 401 envelope_gen_num_attack = 1, 402 envelope_gen_num_decay = 2, 403 envelope_gen_num_sustain = 3, 404 envelope_gen_num_release = 4 405 } 406 407 private ubyte OPL3_EnvelopeCalcRate (OPL3Slot* slot, ubyte reg_rate) { 408 if (reg_rate == 0x00) return 0x00; 409 ubyte rate = cast(ubyte)((reg_rate<<2)+(slot.reg_ksr ? slot.channel.ksv : (slot.channel.ksv>>2))); 410 if (rate > 0x3c) rate = 0x3c; 411 return rate; 412 } 413 414 private void OPL3_EnvelopeUpdateKSL (OPL3Slot* slot) { 415 short ksl = (kslrom.ptr[slot.channel.f_num>>6]<<2)-((0x08-slot.channel.block)<<5); 416 if (ksl < 0) ksl = 0; 417 slot.eg_ksl = cast(ubyte)ksl; 418 } 419 420 private void OPL3_EnvelopeUpdateRate (OPL3Slot* slot) { 421 switch (slot.eg_gen) { 422 case envelope_gen_num_off: 423 case envelope_gen_num_attack: 424 slot.eg_rate = OPL3_EnvelopeCalcRate(slot, slot.reg_ar); 425 break; 426 case envelope_gen_num_decay: 427 slot.eg_rate = OPL3_EnvelopeCalcRate(slot, slot.reg_dr); 428 break; 429 case envelope_gen_num_sustain: 430 case envelope_gen_num_release: 431 slot.eg_rate = OPL3_EnvelopeCalcRate(slot, slot.reg_rr); 432 break; 433 default: break; 434 } 435 } 436 437 private void OPL3_EnvelopeGenOff (OPL3Slot* slot) { 438 slot.eg_rout = 0x1ff; 439 } 440 441 private void OPL3_EnvelopeGenAttack (OPL3Slot* slot) { 442 if (slot.eg_rout == 0x00) { 443 slot.eg_gen = envelope_gen_num_decay; 444 OPL3_EnvelopeUpdateRate(slot); 445 } else { 446 slot.eg_rout += ((~cast(uint)slot.eg_rout)*slot.eg_inc)>>3; 447 if (slot.eg_rout < 0x00) slot.eg_rout = 0x00; 448 } 449 } 450 451 private void OPL3_EnvelopeGenDecay (OPL3Slot* slot) { 452 if (slot.eg_rout >= slot.reg_sl<<4) { 453 slot.eg_gen = envelope_gen_num_sustain; 454 OPL3_EnvelopeUpdateRate(slot); 455 } else { 456 slot.eg_rout += slot.eg_inc; 457 } 458 } 459 460 private void OPL3_EnvelopeGenSustain (OPL3Slot* slot) { 461 if (!slot.reg_type) OPL3_EnvelopeGenRelease(slot); 462 } 463 464 private void OPL3_EnvelopeGenRelease (OPL3Slot* slot) { 465 if (slot.eg_rout >= 0x1ff) { 466 slot.eg_gen = envelope_gen_num_off; 467 slot.eg_rout = 0x1ff; 468 OPL3_EnvelopeUpdateRate(slot); 469 } else { 470 slot.eg_rout += slot.eg_inc; 471 } 472 } 473 474 private void OPL3_EnvelopeCalc (OPL3Slot* slot) { 475 ubyte rate_h, rate_l; 476 ubyte inc = 0; 477 rate_h = slot.eg_rate>>2; 478 rate_l = slot.eg_rate&3; 479 if (eg_incsh.ptr[rate_h] > 0) { 480 if ((slot.chip.timer&((1<<eg_incsh.ptr[rate_h])-1)) == 0) { 481 inc = eg_incstep.ptr[eg_incdesc.ptr[rate_h]].ptr[rate_l].ptr[((slot.chip.timer)>> eg_incsh.ptr[rate_h])&0x07]; 482 } 483 } else { 484 inc = cast(ubyte)(eg_incstep.ptr[eg_incdesc.ptr[rate_h]].ptr[rate_l].ptr[slot.chip.timer&0x07]<<(-cast(int)(eg_incsh.ptr[rate_h]))); 485 } 486 slot.eg_inc = inc; 487 slot.eg_out = cast(short)(slot.eg_rout+(slot.reg_tl<<2)+(slot.eg_ksl>>kslshift.ptr[slot.reg_ksl])+*slot.trem); 488 envelope_gen[slot.eg_gen](slot); 489 } 490 491 private void OPL3_EnvelopeKeyOn (OPL3Slot* slot, ubyte type) { 492 if (!slot.key) { 493 slot.eg_gen = envelope_gen_num_attack; 494 OPL3_EnvelopeUpdateRate(slot); 495 if ((slot.eg_rate>>2) == 0x0f) { 496 slot.eg_gen = envelope_gen_num_decay; 497 OPL3_EnvelopeUpdateRate(slot); 498 slot.eg_rout = 0x00; 499 } 500 slot.pg_phase = 0x00; 501 } 502 slot.key |= type; 503 } 504 505 private void OPL3_EnvelopeKeyOff (OPL3Slot* slot, ubyte type) { 506 if (slot.key) { 507 slot.key &= (~cast(uint)type); 508 if (!slot.key) { 509 slot.eg_gen = envelope_gen_num_release; 510 OPL3_EnvelopeUpdateRate(slot); 511 } 512 } 513 } 514 515 // 516 // Phase Generator 517 // 518 519 private void OPL3_PhaseGenerate (OPL3Slot* slot) { 520 ushort f_num; 521 uint basefreq; 522 523 f_num = slot.channel.f_num; 524 if (slot.reg_vib) { 525 byte range; 526 ubyte vibpos; 527 528 range = (f_num>>7)&7; 529 vibpos = slot.chip.vibpos; 530 531 if (!(vibpos&3)) range = 0; 532 else if (vibpos&1) range >>= 1; 533 range >>= slot.chip.vibshift; 534 535 if (vibpos&4) range = cast(byte) -cast(int)(range); 536 f_num += range; 537 } 538 basefreq = (f_num<<slot.channel.block)>>1; 539 slot.pg_phase += (basefreq*mt.ptr[slot.reg_mult])>>1; 540 } 541 542 // 543 // Noise Generator 544 // 545 546 private void OPL3_NoiseGenerate (OPL3Chip* chip) { 547 if (chip.noise&0x01) chip.noise ^= 0x800302; 548 chip.noise >>= 1; 549 } 550 551 // 552 // Slot 553 // 554 555 private void OPL3_SlotWrite20 (OPL3Slot* slot, ubyte data) { 556 slot.trem = ((data>>7)&0x01 ? &slot.chip.tremolo : cast(ubyte*)&slot.chip.zeromod); 557 slot.reg_vib = (data>>6)&0x01; 558 slot.reg_type = (data>>5)&0x01; 559 slot.reg_ksr = (data>>4)&0x01; 560 slot.reg_mult = data&0x0f; 561 OPL3_EnvelopeUpdateRate(slot); 562 } 563 564 private void OPL3_SlotWrite40 (OPL3Slot* slot, ubyte data) { 565 slot.reg_ksl = (data>>6)&0x03; 566 slot.reg_tl = data&0x3f; 567 OPL3_EnvelopeUpdateKSL(slot); 568 } 569 570 private void OPL3_SlotWrite60 (OPL3Slot* slot, ubyte data) { 571 slot.reg_ar = (data>>4)&0x0f; 572 slot.reg_dr = data&0x0f; 573 OPL3_EnvelopeUpdateRate(slot); 574 } 575 576 private void OPL3_SlotWrite80 (OPL3Slot* slot, ubyte data) { 577 slot.reg_sl = (data>>4)&0x0f; 578 if (slot.reg_sl == 0x0f) slot.reg_sl = 0x1f; 579 slot.reg_rr = data&0x0f; 580 OPL3_EnvelopeUpdateRate(slot); 581 } 582 583 private void OPL3_SlotWriteE0 (OPL3Slot* slot, ubyte data) { 584 slot.reg_wf = data&0x07; 585 if (slot.chip.newm == 0x00) slot.reg_wf &= 0x03; 586 } 587 588 private void OPL3_SlotGeneratePhase (OPL3Slot* slot, ushort phase) { 589 slot.out_ = envelope_sin[slot.reg_wf](phase, slot.eg_out); 590 } 591 592 private void OPL3_SlotGenerate (OPL3Slot* slot) { 593 OPL3_SlotGeneratePhase(slot, cast(ushort)(cast(ushort)(slot.pg_phase>>9)+*slot.mod)); 594 } 595 596 private void OPL3_SlotGenerateZM (OPL3Slot* slot) { 597 OPL3_SlotGeneratePhase(slot, cast(ushort)(slot.pg_phase>>9)); 598 } 599 600 private void OPL3_SlotCalcFB (OPL3Slot* slot) { 601 slot.fbmod = (slot.channel.fb != 0x00 ? cast(short)((slot.prout+slot.out_)>>(0x09-slot.channel.fb)) : 0); 602 slot.prout = slot.out_; 603 } 604 605 // 606 // Channel 607 // 608 609 private void OPL3_ChannelUpdateRhythm (OPL3Chip* chip, ubyte data) { 610 OPL3Channel* channel6; 611 OPL3Channel* channel7; 612 OPL3Channel* channel8; 613 ubyte chnum; 614 615 chip.rhy = data&0x3f; 616 if (chip.rhy&0x20) { 617 channel6 = &chip.channel.ptr[6]; 618 channel7 = &chip.channel.ptr[7]; 619 channel8 = &chip.channel.ptr[8]; 620 channel6.out_.ptr[0] = &channel6.slots.ptr[1].out_; 621 channel6.out_.ptr[1] = &channel6.slots.ptr[1].out_; 622 channel6.out_.ptr[2] = &chip.zeromod; 623 channel6.out_.ptr[3] = &chip.zeromod; 624 channel7.out_.ptr[0] = &channel7.slots.ptr[0].out_; 625 channel7.out_.ptr[1] = &channel7.slots.ptr[0].out_; 626 channel7.out_.ptr[2] = &channel7.slots.ptr[1].out_; 627 channel7.out_.ptr[3] = &channel7.slots.ptr[1].out_; 628 channel8.out_.ptr[0] = &channel8.slots.ptr[0].out_; 629 channel8.out_.ptr[1] = &channel8.slots.ptr[0].out_; 630 channel8.out_.ptr[2] = &channel8.slots.ptr[1].out_; 631 channel8.out_.ptr[3] = &channel8.slots.ptr[1].out_; 632 for (chnum = 6; chnum < 9; ++chnum) chip.channel.ptr[chnum].chtype = ch_drum; 633 OPL3_ChannelSetupAlg(channel6); 634 //hh 635 if (chip.rhy&0x01) { 636 OPL3_EnvelopeKeyOn(channel7.slots.ptr[0], egk_drum); 637 } else { 638 OPL3_EnvelopeKeyOff(channel7.slots.ptr[0], egk_drum); 639 } 640 //tc 641 if (chip.rhy&0x02) { 642 OPL3_EnvelopeKeyOn(channel8.slots.ptr[1], egk_drum); 643 } else { 644 OPL3_EnvelopeKeyOff(channel8.slots.ptr[1], egk_drum); 645 } 646 //tom 647 if (chip.rhy&0x04) { 648 OPL3_EnvelopeKeyOn(channel8.slots.ptr[0], egk_drum); 649 } else { 650 OPL3_EnvelopeKeyOff(channel8.slots.ptr[0], egk_drum); 651 } 652 //sd 653 if (chip.rhy&0x08) { 654 OPL3_EnvelopeKeyOn(channel7.slots.ptr[1], egk_drum); 655 } else { 656 OPL3_EnvelopeKeyOff(channel7.slots.ptr[1], egk_drum); 657 } 658 //bd 659 if (chip.rhy&0x10) { 660 OPL3_EnvelopeKeyOn(channel6.slots.ptr[0], egk_drum); 661 OPL3_EnvelopeKeyOn(channel6.slots.ptr[1], egk_drum); 662 } else { 663 OPL3_EnvelopeKeyOff(channel6.slots.ptr[0], egk_drum); 664 OPL3_EnvelopeKeyOff(channel6.slots.ptr[1], egk_drum); 665 } 666 } else { 667 for (chnum = 6; chnum < 9; ++chnum) { 668 chip.channel.ptr[chnum].chtype = ch_2op; 669 OPL3_ChannelSetupAlg(&chip.channel.ptr[chnum]); 670 OPL3_EnvelopeKeyOff(chip.channel.ptr[chnum].slots.ptr[0], egk_drum); 671 OPL3_EnvelopeKeyOff(chip.channel.ptr[chnum].slots.ptr[1], egk_drum); 672 } 673 } 674 } 675 676 private void OPL3_ChannelWriteA0 (OPL3Channel* channel, ubyte data) { 677 if (channel.chip.newm && channel.chtype == ch_4op2) return; 678 channel.f_num = (channel.f_num&0x300)|data; 679 channel.ksv = cast(ubyte)((channel.block<<1)|((channel.f_num>>(0x09-channel.chip.nts))&0x01)); 680 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[0]); 681 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[1]); 682 OPL3_EnvelopeUpdateRate(channel.slots.ptr[0]); 683 OPL3_EnvelopeUpdateRate(channel.slots.ptr[1]); 684 if (channel.chip.newm && channel.chtype == ch_4op) { 685 channel.pair.f_num = channel.f_num; 686 channel.pair.ksv = channel.ksv; 687 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[0]); 688 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[1]); 689 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[0]); 690 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[1]); 691 } 692 } 693 694 private void OPL3_ChannelWriteB0 (OPL3Channel* channel, ubyte data) { 695 if (channel.chip.newm && channel.chtype == ch_4op2) return; 696 channel.f_num = (channel.f_num&0xff)|((data&0x03)<<8); 697 channel.block = (data>>2)&0x07; 698 channel.ksv = cast(ubyte)((channel.block<<1)|((channel.f_num>>(0x09-channel.chip.nts))&0x01)); 699 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[0]); 700 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[1]); 701 OPL3_EnvelopeUpdateRate(channel.slots.ptr[0]); 702 OPL3_EnvelopeUpdateRate(channel.slots.ptr[1]); 703 if (channel.chip.newm && channel.chtype == ch_4op) { 704 channel.pair.f_num = channel.f_num; 705 channel.pair.block = channel.block; 706 channel.pair.ksv = channel.ksv; 707 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[0]); 708 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[1]); 709 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[0]); 710 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[1]); 711 } 712 } 713 714 private void OPL3_ChannelSetupAlg (OPL3Channel* channel) { 715 if (channel.chtype == ch_drum) { 716 final switch (channel.alg&0x01) { 717 case 0x00: 718 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod; 719 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_; 720 break; 721 case 0x01: 722 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod; 723 channel.slots.ptr[1].mod = &channel.chip.zeromod; 724 break; 725 } 726 return; 727 } 728 if (channel.alg&0x08) return; 729 if (channel.alg&0x04) { 730 channel.pair.out_.ptr[0] = &channel.chip.zeromod; 731 channel.pair.out_.ptr[1] = &channel.chip.zeromod; 732 channel.pair.out_.ptr[2] = &channel.chip.zeromod; 733 channel.pair.out_.ptr[3] = &channel.chip.zeromod; 734 final switch (channel.alg&0x03) { 735 case 0x00: 736 channel.pair.slots.ptr[0].mod = &channel.pair.slots.ptr[0].fbmod; 737 channel.pair.slots.ptr[1].mod = &channel.pair.slots.ptr[0].out_; 738 channel.slots.ptr[0].mod = &channel.pair.slots.ptr[1].out_; 739 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_; 740 channel.out_.ptr[0] = &channel.slots.ptr[1].out_; 741 channel.out_.ptr[1] = &channel.chip.zeromod; 742 channel.out_.ptr[2] = &channel.chip.zeromod; 743 channel.out_.ptr[3] = &channel.chip.zeromod; 744 break; 745 case 0x01: 746 channel.pair.slots.ptr[0].mod = &channel.pair.slots.ptr[0].fbmod; 747 channel.pair.slots.ptr[1].mod = &channel.pair.slots.ptr[0].out_; 748 channel.slots.ptr[0].mod = &channel.chip.zeromod; 749 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_; 750 channel.out_.ptr[0] = &channel.pair.slots.ptr[1].out_; 751 channel.out_.ptr[1] = &channel.slots.ptr[1].out_; 752 channel.out_.ptr[2] = &channel.chip.zeromod; 753 channel.out_.ptr[3] = &channel.chip.zeromod; 754 break; 755 case 0x02: 756 channel.pair.slots.ptr[0].mod = &channel.pair.slots.ptr[0].fbmod; 757 channel.pair.slots.ptr[1].mod = &channel.chip.zeromod; 758 channel.slots.ptr[0].mod = &channel.pair.slots.ptr[1].out_; 759 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_; 760 channel.out_.ptr[0] = &channel.pair.slots.ptr[0].out_; 761 channel.out_.ptr[1] = &channel.slots.ptr[1].out_; 762 channel.out_.ptr[2] = &channel.chip.zeromod; 763 channel.out_.ptr[3] = &channel.chip.zeromod; 764 break; 765 case 0x03: 766 channel.pair.slots.ptr[0].mod = &channel.pair.slots.ptr[0].fbmod; 767 channel.pair.slots.ptr[1].mod = &channel.chip.zeromod; 768 channel.slots.ptr[0].mod = &channel.pair.slots.ptr[1].out_; 769 channel.slots.ptr[1].mod = &channel.chip.zeromod; 770 channel.out_.ptr[0] = &channel.pair.slots.ptr[0].out_; 771 channel.out_.ptr[1] = &channel.slots.ptr[0].out_; 772 channel.out_.ptr[2] = &channel.slots.ptr[1].out_; 773 channel.out_.ptr[3] = &channel.chip.zeromod; 774 break; 775 } 776 } else { 777 final switch (channel.alg&0x01) { 778 case 0x00: 779 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod; 780 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_; 781 channel.out_.ptr[0] = &channel.slots.ptr[1].out_; 782 channel.out_.ptr[1] = &channel.chip.zeromod; 783 channel.out_.ptr[2] = &channel.chip.zeromod; 784 channel.out_.ptr[3] = &channel.chip.zeromod; 785 break; 786 case 0x01: 787 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod; 788 channel.slots.ptr[1].mod = &channel.chip.zeromod; 789 channel.out_.ptr[0] = &channel.slots.ptr[0].out_; 790 channel.out_.ptr[1] = &channel.slots.ptr[1].out_; 791 channel.out_.ptr[2] = &channel.chip.zeromod; 792 channel.out_.ptr[3] = &channel.chip.zeromod; 793 break; 794 } 795 } 796 } 797 798 private void OPL3_ChannelWriteC0 (OPL3Channel* channel, ubyte data) { 799 channel.fb = (data&0x0e)>>1; 800 channel.con = data&0x01; 801 channel.alg = channel.con; 802 if (channel.chip.newm) { 803 if (channel.chtype == ch_4op) { 804 channel.pair.alg = cast(ubyte)(0x04|(channel.con<<1)|(channel.pair.con)); 805 channel.alg = 0x08; 806 OPL3_ChannelSetupAlg(channel.pair); 807 } else if (channel.chtype == ch_4op2) { 808 channel.alg = cast(ubyte)(0x04|(channel.pair.con<<1)|(channel.con)); 809 channel.pair.alg = 0x08; 810 OPL3_ChannelSetupAlg(channel); 811 } else { 812 OPL3_ChannelSetupAlg(channel); 813 } 814 } else { 815 OPL3_ChannelSetupAlg(channel); 816 } 817 if (channel.chip.newm) { 818 channel.cha = ((data>>4)&0x01 ? ushort.max : 0); 819 channel.chb = ((data>>5)&0x01 ? ushort.max : 0); 820 } else { 821 channel.cha = channel.chb = ushort.max; 822 } 823 } 824 825 private void OPL3_ChannelKeyOn (OPL3Channel* channel) { 826 if (channel.chip.newm) { 827 if (channel.chtype == ch_4op) { 828 OPL3_EnvelopeKeyOn(channel.slots.ptr[0], egk_norm); 829 OPL3_EnvelopeKeyOn(channel.slots.ptr[1], egk_norm); 830 OPL3_EnvelopeKeyOn(channel.pair.slots.ptr[0], egk_norm); 831 OPL3_EnvelopeKeyOn(channel.pair.slots.ptr[1], egk_norm); 832 } else if (channel.chtype == ch_2op || channel.chtype == ch_drum) { 833 OPL3_EnvelopeKeyOn(channel.slots.ptr[0], egk_norm); 834 OPL3_EnvelopeKeyOn(channel.slots.ptr[1], egk_norm); 835 } 836 } else { 837 OPL3_EnvelopeKeyOn(channel.slots.ptr[0], egk_norm); 838 OPL3_EnvelopeKeyOn(channel.slots.ptr[1], egk_norm); 839 } 840 } 841 842 private void OPL3_ChannelKeyOff (OPL3Channel* channel) { 843 if (channel.chip.newm) { 844 if (channel.chtype == ch_4op) { 845 OPL3_EnvelopeKeyOff(channel.slots.ptr[0], egk_norm); 846 OPL3_EnvelopeKeyOff(channel.slots.ptr[1], egk_norm); 847 OPL3_EnvelopeKeyOff(channel.pair.slots.ptr[0], egk_norm); 848 OPL3_EnvelopeKeyOff(channel.pair.slots.ptr[1], egk_norm); 849 } else if (channel.chtype == ch_2op || channel.chtype == ch_drum) { 850 OPL3_EnvelopeKeyOff(channel.slots.ptr[0], egk_norm); 851 OPL3_EnvelopeKeyOff(channel.slots.ptr[1], egk_norm); 852 } 853 } else { 854 OPL3_EnvelopeKeyOff(channel.slots.ptr[0], egk_norm); 855 OPL3_EnvelopeKeyOff(channel.slots.ptr[1], egk_norm); 856 } 857 } 858 859 private void OPL3_ChannelSet4Op (OPL3Chip* chip, ubyte data) { 860 ubyte bit; 861 ubyte chnum; 862 for (bit = 0; bit < 6; ++bit) { 863 chnum = bit; 864 if (bit >= 3) chnum += 9-3; 865 if ((data>>bit)&0x01) { 866 chip.channel.ptr[chnum].chtype = ch_4op; 867 chip.channel.ptr[chnum+3].chtype = ch_4op2; 868 } else { 869 chip.channel.ptr[chnum].chtype = ch_2op; 870 chip.channel.ptr[chnum+3].chtype = ch_2op; 871 } 872 } 873 } 874 875 private short OPL3_ClipSample (int sample) pure { 876 pragma(inline, true); 877 if (sample > 32767) sample = 32767; 878 else if (sample < -32768) sample = -32768; 879 return cast(short)sample; 880 } 881 882 private void OPL3_GenerateRhythm1 (OPL3Chip* chip) { 883 OPL3Channel* channel6; 884 OPL3Channel* channel7; 885 OPL3Channel* channel8; 886 ushort phase14; 887 ushort phase17; 888 ushort phase; 889 ushort phasebit; 890 891 channel6 = &chip.channel.ptr[6]; 892 channel7 = &chip.channel.ptr[7]; 893 channel8 = &chip.channel.ptr[8]; 894 OPL3_SlotGenerate(channel6.slots.ptr[0]); 895 phase14 = (channel7.slots.ptr[0].pg_phase>>9)&0x3ff; 896 phase17 = (channel8.slots.ptr[1].pg_phase>>9)&0x3ff; 897 phase = 0x00; 898 //hh tc phase bit 899 phasebit = ((phase14&0x08)|(((phase14>>5)^phase14)&0x04)|(((phase17>>2)^phase17)&0x08)) ? 0x01 : 0x00; 900 //hh 901 phase = cast(ushort)((phasebit<<9)|(0x34<<((phasebit^(chip.noise&0x01))<<1))); 902 OPL3_SlotGeneratePhase(channel7.slots.ptr[0], phase); 903 //tt 904 OPL3_SlotGenerateZM(channel8.slots.ptr[0]); 905 } 906 907 private void OPL3_GenerateRhythm2 (OPL3Chip* chip) { 908 OPL3Channel* channel6; 909 OPL3Channel* channel7; 910 OPL3Channel* channel8; 911 ushort phase14; 912 ushort phase17; 913 ushort phase; 914 ushort phasebit; 915 916 channel6 = &chip.channel.ptr[6]; 917 channel7 = &chip.channel.ptr[7]; 918 channel8 = &chip.channel.ptr[8]; 919 OPL3_SlotGenerate(channel6.slots.ptr[1]); 920 phase14 = (channel7.slots.ptr[0].pg_phase>>9)&0x3ff; 921 phase17 = (channel8.slots.ptr[1].pg_phase>>9)&0x3ff; 922 phase = 0x00; 923 //hh tc phase bit 924 phasebit = ((phase14&0x08)|(((phase14>>5)^phase14)&0x04)|(((phase17>>2)^phase17)&0x08)) ? 0x01 : 0x00; 925 //sd 926 phase = (0x100<<((phase14>>8)&0x01))^((chip.noise&0x01)<<8); 927 OPL3_SlotGeneratePhase(channel7.slots.ptr[1], phase); 928 //tc 929 phase = cast(ushort)(0x100|(phasebit<<9)); 930 OPL3_SlotGeneratePhase(channel8.slots.ptr[1], phase); 931 } 932 933 934 // ////////////////////////////////////////////////////////////////////////// // 935 /// OPL3_Generate 936 public void generate (ref OPL3Chip chip, short* buf) { 937 ubyte ii; 938 ubyte jj; 939 short accm; 940 941 buf[1] = OPL3_ClipSample(chip.mixbuff.ptr[1]); 942 943 for (ii = 0; ii < 12; ++ii) { 944 OPL3_SlotCalcFB(&chip.slot.ptr[ii]); 945 OPL3_PhaseGenerate(&chip.slot.ptr[ii]); 946 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]); 947 OPL3_SlotGenerate(&chip.slot.ptr[ii]); 948 } 949 950 for (ii = 12; ii < 15; ++ii) { 951 OPL3_SlotCalcFB(&chip.slot.ptr[ii]); 952 OPL3_PhaseGenerate(&chip.slot.ptr[ii]); 953 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]); 954 } 955 956 if (chip.rhy&0x20) { 957 OPL3_GenerateRhythm1(&chip); 958 } else { 959 OPL3_SlotGenerate(&chip.slot.ptr[12]); 960 OPL3_SlotGenerate(&chip.slot.ptr[13]); 961 OPL3_SlotGenerate(&chip.slot.ptr[14]); 962 } 963 964 chip.mixbuff.ptr[0] = 0; 965 for (ii = 0; ii < 18; ++ii) { 966 accm = 0; 967 for (jj = 0; jj < 4; ++jj) accm += *chip.channel.ptr[ii].out_.ptr[jj]; 968 chip.mixbuff.ptr[0] += cast(short)(accm&chip.channel.ptr[ii].cha); 969 } 970 971 for (ii = 15; ii < 18; ++ii) { 972 OPL3_SlotCalcFB(&chip.slot.ptr[ii]); 973 OPL3_PhaseGenerate(&chip.slot.ptr[ii]); 974 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]); 975 } 976 977 if (chip.rhy&0x20) { 978 OPL3_GenerateRhythm2(&chip); 979 } else { 980 OPL3_SlotGenerate(&chip.slot.ptr[15]); 981 OPL3_SlotGenerate(&chip.slot.ptr[16]); 982 OPL3_SlotGenerate(&chip.slot.ptr[17]); 983 } 984 985 buf[0] = OPL3_ClipSample(chip.mixbuff.ptr[0]); 986 987 for (ii = 18; ii < 33; ++ii) { 988 OPL3_SlotCalcFB(&chip.slot.ptr[ii]); 989 OPL3_PhaseGenerate(&chip.slot.ptr[ii]); 990 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]); 991 OPL3_SlotGenerate(&chip.slot.ptr[ii]); 992 } 993 994 chip.mixbuff.ptr[1] = 0; 995 for (ii = 0; ii < 18; ++ii) { 996 accm = 0; 997 for (jj = 0; jj < 4; jj++) accm += *chip.channel.ptr[ii].out_.ptr[jj]; 998 chip.mixbuff.ptr[1] += cast(short)(accm&chip.channel.ptr[ii].chb); 999 } 1000 1001 for (ii = 33; ii < 36; ++ii) { 1002 OPL3_SlotCalcFB(&chip.slot.ptr[ii]); 1003 OPL3_PhaseGenerate(&chip.slot.ptr[ii]); 1004 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]); 1005 OPL3_SlotGenerate(&chip.slot.ptr[ii]); 1006 } 1007 1008 OPL3_NoiseGenerate(&chip); 1009 1010 if ((chip.timer&0x3f) == 0x3f) chip.tremolopos = (chip.tremolopos+1)%210; 1011 chip.tremolo = (chip.tremolopos < 105 ? chip.tremolopos>>chip.tremoloshift : cast(ubyte)((210-chip.tremolopos)>>chip.tremoloshift)); 1012 if ((chip.timer&0x3ff) == 0x3ff) chip.vibpos = (chip.vibpos+1)&7; 1013 1014 ++chip.timer; 1015 1016 while (chip.writebuf.ptr[chip.writebuf_cur].time <= chip.writebuf_samplecnt) { 1017 if (!(chip.writebuf.ptr[chip.writebuf_cur].reg&0x200)) break; 1018 chip.writebuf.ptr[chip.writebuf_cur].reg &= 0x1ff; 1019 chip.writeReg(chip.writebuf.ptr[chip.writebuf_cur].reg, chip.writebuf.ptr[chip.writebuf_cur].data); 1020 chip.writebuf_cur = (chip.writebuf_cur+1)%OPL_WRITEBUF_SIZE; 1021 } 1022 ++chip.writebuf_samplecnt; 1023 } 1024 1025 1026 /// OPL3_GenerateResampled 1027 public void generateResampled (ref OPL3Chip chip, short* buf) { 1028 while (chip.samplecnt >= chip.rateratio) { 1029 chip.oldsamples.ptr[0] = chip.samples.ptr[0]; 1030 chip.oldsamples.ptr[1] = chip.samples.ptr[1]; 1031 chip.generate(chip.samples.ptr); 1032 chip.samplecnt -= chip.rateratio; 1033 } 1034 buf[0] = cast(short)((chip.oldsamples.ptr[0]*(chip.rateratio-chip.samplecnt)+chip.samples.ptr[0]*chip.samplecnt)/chip.rateratio); 1035 buf[1] = cast(short)((chip.oldsamples.ptr[1]*(chip.rateratio-chip.samplecnt)+chip.samples.ptr[1]*chip.samplecnt)/chip.rateratio); 1036 chip.samplecnt += 1<<RSM_FRAC; 1037 } 1038 1039 1040 /// OPL3_Reset 1041 public void reset (ref OPL3Chip chip, uint samplerate) { 1042 ubyte slotnum; 1043 ubyte channum; 1044 1045 //ubyte* cc = cast(ubyte*)chip; 1046 //cc[0..OPL3Chip.sizeof] = 0; 1047 chip = chip.init; 1048 1049 for (slotnum = 0; slotnum < 36; ++slotnum) { 1050 chip.slot.ptr[slotnum].chip = &chip; 1051 chip.slot.ptr[slotnum].mod = &chip.zeromod; 1052 chip.slot.ptr[slotnum].eg_rout = 0x1ff; 1053 chip.slot.ptr[slotnum].eg_out = 0x1ff; 1054 chip.slot.ptr[slotnum].eg_gen = envelope_gen_num_off; 1055 chip.slot.ptr[slotnum].trem = cast(ubyte*)&chip.zeromod; 1056 } 1057 for (channum = 0; channum < 18; ++channum) { 1058 chip.channel.ptr[channum].slots.ptr[0] = &chip.slot.ptr[ch_slot.ptr[channum]]; 1059 chip.channel.ptr[channum].slots.ptr[1] = &chip.slot.ptr[ch_slot.ptr[channum]+3]; 1060 chip.slot.ptr[ch_slot.ptr[channum]].channel = &chip.channel.ptr[channum]; 1061 chip.slot.ptr[ch_slot.ptr[channum]+3].channel = &chip.channel.ptr[channum]; 1062 if ((channum%9) < 3) chip.channel.ptr[channum].pair = &chip.channel.ptr[channum+3]; 1063 else if ((channum%9) < 6) chip.channel.ptr[channum].pair = &chip.channel.ptr[channum-3]; 1064 chip.channel.ptr[channum].chip = &chip; 1065 chip.channel.ptr[channum].out_.ptr[0] = &chip.zeromod; 1066 chip.channel.ptr[channum].out_.ptr[1] = &chip.zeromod; 1067 chip.channel.ptr[channum].out_.ptr[2] = &chip.zeromod; 1068 chip.channel.ptr[channum].out_.ptr[3] = &chip.zeromod; 1069 chip.channel.ptr[channum].chtype = ch_2op; 1070 chip.channel.ptr[channum].cha = ushort.max; 1071 chip.channel.ptr[channum].chb = ushort.max; 1072 OPL3_ChannelSetupAlg(&chip.channel.ptr[channum]); 1073 } 1074 chip.noise = 0x306600; 1075 chip.rateratio = (samplerate<<RSM_FRAC)/OPL_RATE; 1076 chip.tremoloshift = 4; 1077 chip.vibshift = 1; 1078 } 1079 1080 1081 /// OPL3_WriteReg 1082 public void writeReg (ref OPL3Chip chip, ushort reg, ubyte v) { 1083 ubyte high = (reg>>8)&0x01; 1084 ubyte regm = reg&0xff; 1085 switch (regm&0xf0) { 1086 case 0x00: 1087 if (high) { 1088 switch (regm&0x0f) { 1089 case 0x04: 1090 OPL3_ChannelSet4Op(&chip, v); 1091 break; 1092 case 0x05: 1093 chip.newm = v&0x01; 1094 break; 1095 default: break; 1096 } 1097 } else { 1098 switch (regm&0x0f) { 1099 case 0x08: 1100 chip.nts = (v>>6)&0x01; 1101 break; 1102 default: break; 1103 } 1104 } 1105 break; 1106 case 0x20: 1107 case 0x30: 1108 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite20(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v); 1109 break; 1110 case 0x40: 1111 case 0x50: 1112 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite40(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v); 1113 break; 1114 case 0x60: 1115 case 0x70: 1116 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite60(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v); 1117 break; 1118 case 0x80: 1119 case 0x90: 1120 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite80(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v); 1121 break; 1122 case 0xe0: 1123 case 0xf0: 1124 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWriteE0(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v); 1125 break; 1126 case 0xa0: 1127 if ((regm&0x0f) < 9) OPL3_ChannelWriteA0(&chip.channel.ptr[9*high+(regm&0x0f)], v); 1128 break; 1129 case 0xb0: 1130 if (regm == 0xbd && !high) { 1131 chip.tremoloshift = (((v>>7)^1)<<1)+2; 1132 chip.vibshift = ((v>>6)&0x01)^1; 1133 OPL3_ChannelUpdateRhythm(&chip, v); 1134 } else if ((regm&0x0f) < 9) { 1135 OPL3_ChannelWriteB0(&chip.channel.ptr[9*high+(regm&0x0f)], v); 1136 if (v&0x20) OPL3_ChannelKeyOn(&chip.channel.ptr[9*high+(regm&0x0f)]); else OPL3_ChannelKeyOff(&chip.channel.ptr[9*high+(regm&0x0f)]); 1137 } 1138 break; 1139 case 0xc0: 1140 if ((regm&0x0f) < 9) OPL3_ChannelWriteC0(&chip.channel.ptr[9*high+(regm&0x0f)], v); 1141 break; 1142 default: break; 1143 } 1144 } 1145 1146 1147 /// OPL3_WriteRegBuffered 1148 public void writeRegBuffered (ref OPL3Chip chip, ushort reg, ubyte v) { 1149 ulong time1, time2; 1150 1151 if (chip.writebuf.ptr[chip.writebuf_last].reg&0x200) { 1152 chip.writeReg(chip.writebuf.ptr[chip.writebuf_last].reg&0x1ff, chip.writebuf.ptr[chip.writebuf_last].data); 1153 chip.writebuf_cur = (chip.writebuf_last+1)%OPL_WRITEBUF_SIZE; 1154 chip.writebuf_samplecnt = chip.writebuf.ptr[chip.writebuf_last].time; 1155 } 1156 1157 chip.writebuf.ptr[chip.writebuf_last].reg = reg|0x200; 1158 chip.writebuf.ptr[chip.writebuf_last].data = v; 1159 time1 = chip.writebuf_lasttime+OPL_WRITEBUF_DELAY; 1160 time2 = chip.writebuf_samplecnt; 1161 1162 if (time1 < time2) time1 = time2; 1163 1164 chip.writebuf.ptr[chip.writebuf_last].time = time1; 1165 chip.writebuf_lasttime = time1; 1166 chip.writebuf_last = (chip.writebuf_last+1)%OPL_WRITEBUF_SIZE; 1167 } 1168 1169 1170 /// OPL3_GenerateStream; outputs STEREO stream 1171 public void generateStream (ref OPL3Chip chip, short[] smpbuf) { 1172 auto sndptr = smpbuf.ptr; 1173 foreach (immutable _; 0..smpbuf.length/2) { 1174 chip.generateResampled(sndptr); 1175 sndptr += 2; 1176 } 1177 } 1178 1179 1180 // ////////////////////////////////////////////////////////////////////////// // 1181 // simple DooM MUS / Midi player 1182 public final class OPLPlayer { 1183 private: 1184 static immutable ubyte[128] opl_voltable = [ 1185 0x00, 0x01, 0x03, 0x05, 0x06, 0x08, 0x0a, 0x0b, 1186 0x0d, 0x0e, 0x10, 0x11, 0x13, 0x14, 0x16, 0x17, 1187 0x19, 0x1a, 0x1b, 0x1d, 0x1e, 0x20, 0x21, 0x22, 1188 0x24, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x2f, 0x31, 1189 0x32, 0x34, 0x36, 0x37, 0x39, 0x3b, 0x3c, 0x3d, 1190 0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 1191 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f, 0x50, 0x51, 1192 0x52, 0x53, 0x54, 0x54, 0x55, 0x56, 0x57, 0x58, 1193 0x59, 0x5a, 0x5b, 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 1194 0x60, 0x60, 0x61, 0x62, 0x63, 0x63, 0x64, 0x65, 1195 0x65, 0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 1196 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 1197 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 1198 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 1199 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 1200 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f 1201 ]; 1202 1203 static immutable ushort[284+384] opl_freqtable = [ 1204 0x0133, 0x0133, 0x0134, 0x0134, 0x0135, 0x0136, 0x0136, 0x0137, 1205 0x0137, 0x0138, 0x0138, 0x0139, 0x0139, 0x013a, 0x013b, 0x013b, 1206 0x013c, 0x013c, 0x013d, 0x013d, 0x013e, 0x013f, 0x013f, 0x0140, 1207 0x0140, 0x0141, 0x0142, 0x0142, 0x0143, 0x0143, 0x0144, 0x0144, 1208 0x0145, 0x0146, 0x0146, 0x0147, 0x0147, 0x0148, 0x0149, 0x0149, 1209 0x014a, 0x014a, 0x014b, 0x014c, 0x014c, 0x014d, 0x014d, 0x014e, 1210 0x014f, 0x014f, 0x0150, 0x0150, 0x0151, 0x0152, 0x0152, 0x0153, 1211 0x0153, 0x0154, 0x0155, 0x0155, 0x0156, 0x0157, 0x0157, 0x0158, 1212 0x0158, 0x0159, 0x015a, 0x015a, 0x015b, 0x015b, 0x015c, 0x015d, 1213 0x015d, 0x015e, 0x015f, 0x015f, 0x0160, 0x0161, 0x0161, 0x0162, 1214 0x0162, 0x0163, 0x0164, 0x0164, 0x0165, 0x0166, 0x0166, 0x0167, 1215 0x0168, 0x0168, 0x0169, 0x016a, 0x016a, 0x016b, 0x016c, 0x016c, 1216 0x016d, 0x016e, 0x016e, 0x016f, 0x0170, 0x0170, 0x0171, 0x0172, 1217 0x0172, 0x0173, 0x0174, 0x0174, 0x0175, 0x0176, 0x0176, 0x0177, 1218 0x0178, 0x0178, 0x0179, 0x017a, 0x017a, 0x017b, 0x017c, 0x017c, 1219 0x017d, 0x017e, 0x017e, 0x017f, 0x0180, 0x0181, 0x0181, 0x0182, 1220 0x0183, 0x0183, 0x0184, 0x0185, 0x0185, 0x0186, 0x0187, 0x0188, 1221 0x0188, 0x0189, 0x018a, 0x018a, 0x018b, 0x018c, 0x018d, 0x018d, 1222 0x018e, 0x018f, 0x018f, 0x0190, 0x0191, 0x0192, 0x0192, 0x0193, 1223 0x0194, 0x0194, 0x0195, 0x0196, 0x0197, 0x0197, 0x0198, 0x0199, 1224 0x019a, 0x019a, 0x019b, 0x019c, 0x019d, 0x019d, 0x019e, 0x019f, 1225 0x01a0, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a3, 0x01a4, 0x01a5, 1226 0x01a6, 0x01a6, 0x01a7, 0x01a8, 0x01a9, 0x01a9, 0x01aa, 0x01ab, 1227 0x01ac, 0x01ad, 0x01ad, 0x01ae, 0x01af, 0x01b0, 0x01b0, 0x01b1, 1228 0x01b2, 0x01b3, 0x01b4, 0x01b4, 0x01b5, 0x01b6, 0x01b7, 0x01b8, 1229 0x01b8, 0x01b9, 0x01ba, 0x01bb, 0x01bc, 0x01bc, 0x01bd, 0x01be, 1230 0x01bf, 0x01c0, 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x01c4, 0x01c4, 1231 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01c9, 0x01ca, 0x01cb, 1232 0x01cc, 0x01cd, 0x01ce, 0x01ce, 0x01cf, 0x01d0, 0x01d1, 0x01d2, 1233 0x01d3, 0x01d3, 0x01d4, 0x01d5, 0x01d6, 0x01d7, 0x01d8, 0x01d8, 1234 0x01d9, 0x01da, 0x01db, 0x01dc, 0x01dd, 0x01de, 0x01de, 0x01df, 1235 0x01e0, 0x01e1, 0x01e2, 0x01e3, 0x01e4, 0x01e5, 0x01e5, 0x01e6, 1236 0x01e7, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ec, 0x01ed, 0x01ed, 1237 0x01ee, 0x01ef, 0x01f0, 0x01f1, 0x01f2, 0x01f3, 0x01f4, 0x01f5, 1238 0x01f6, 0x01f6, 0x01f7, 0x01f8, 0x01f9, 0x01fa, 0x01fb, 0x01fc, 1239 0x01fd, 0x01fe, 0x01ff, 0x0200, 0x0201, 0x0201, 0x0202, 0x0203, 1240 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020b, 1241 0x020c, 0x020d, 0x020e, 0x020f, 0x0210, 0x0210, 0x0211, 0x0212, 1242 0x0213, 0x0214, 0x0215, 0x0216, 0x0217, 0x0218, 0x0219, 0x021a, 1243 0x021b, 0x021c, 0x021d, 0x021e, 0x021f, 0x0220, 0x0221, 0x0222, 1244 0x0223, 0x0224, 0x0225, 0x0226, 0x0227, 0x0228, 0x0229, 0x022a, 1245 0x022b, 0x022c, 0x022d, 0x022e, 0x022f, 0x0230, 0x0231, 0x0232, 1246 0x0233, 0x0234, 0x0235, 0x0236, 0x0237, 0x0238, 0x0239, 0x023a, 1247 0x023b, 0x023c, 0x023d, 0x023e, 0x023f, 0x0240, 0x0241, 0x0242, 1248 0x0244, 0x0245, 0x0246, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b, 1249 0x024c, 0x024d, 0x024e, 0x024f, 0x0250, 0x0251, 0x0252, 0x0253, 1250 0x0254, 0x0256, 0x0257, 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 1251 0x025d, 0x025e, 0x025f, 0x0260, 0x0262, 0x0263, 0x0264, 0x0265, 1252 0x0266, 0x0267, 0x0268, 0x0269, 0x026a, 0x026c, 0x026d, 0x026e, 1253 0x026f, 0x0270, 0x0271, 0x0272, 0x0273, 0x0275, 0x0276, 0x0277, 1254 0x0278, 0x0279, 0x027a, 0x027b, 0x027d, 0x027e, 0x027f, 0x0280, 1255 0x0281, 0x0282, 0x0284, 0x0285, 0x0286, 0x0287, 0x0288, 0x0289, 1256 0x028b, 0x028c, 0x028d, 0x028e, 0x028f, 0x0290, 0x0292, 0x0293, 1257 0x0294, 0x0295, 0x0296, 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 1258 0x029e, 0x029f, 0x02a0, 0x02a1, 0x02a2, 0x02a4, 0x02a5, 0x02a6, 1259 0x02a7, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ae, 0x02af, 0x02b0, 1260 0x02b1, 0x02b2, 0x02b4, 0x02b5, 0x02b6, 0x02b7, 0x02b9, 0x02ba, 1261 0x02bb, 0x02bd, 0x02be, 0x02bf, 0x02c0, 0x02c2, 0x02c3, 0x02c4, 1262 0x02c5, 0x02c7, 0x02c8, 0x02c9, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 1263 0x02d0, 0x02d1, 0x02d2, 0x02d4, 0x02d5, 0x02d6, 0x02d8, 0x02d9, 1264 0x02da, 0x02dc, 0x02dd, 0x02de, 0x02e0, 0x02e1, 0x02e2, 0x02e4, 1265 0x02e5, 0x02e6, 0x02e8, 0x02e9, 0x02ea, 0x02ec, 0x02ed, 0x02ee, 1266 0x02f0, 0x02f1, 0x02f2, 0x02f4, 0x02f5, 0x02f6, 0x02f8, 0x02f9, 1267 0x02fb, 0x02fc, 0x02fd, 0x02ff, 0x0300, 0x0302, 0x0303, 0x0304, 1268 0x0306, 0x0307, 0x0309, 0x030a, 0x030b, 0x030d, 0x030e, 0x0310, 1269 0x0311, 0x0312, 0x0314, 0x0315, 0x0317, 0x0318, 0x031a, 0x031b, 1270 0x031c, 0x031e, 0x031f, 0x0321, 0x0322, 0x0324, 0x0325, 0x0327, 1271 0x0328, 0x0329, 0x032b, 0x032c, 0x032e, 0x032f, 0x0331, 0x0332, 1272 0x0334, 0x0335, 0x0337, 0x0338, 0x033a, 0x033b, 0x033d, 0x033e, 1273 0x0340, 0x0341, 0x0343, 0x0344, 0x0346, 0x0347, 0x0349, 0x034a, 1274 0x034c, 0x034d, 0x034f, 0x0350, 0x0352, 0x0353, 0x0355, 0x0357, 1275 0x0358, 0x035a, 0x035b, 0x035d, 0x035e, 0x0360, 0x0361, 0x0363, 1276 0x0365, 0x0366, 0x0368, 0x0369, 0x036b, 0x036c, 0x036e, 0x0370, 1277 0x0371, 0x0373, 0x0374, 0x0376, 0x0378, 0x0379, 0x037b, 0x037c, 1278 0x037e, 0x0380, 0x0381, 0x0383, 0x0384, 0x0386, 0x0388, 0x0389, 1279 0x038b, 0x038d, 0x038e, 0x0390, 0x0392, 0x0393, 0x0395, 0x0397, 1280 0x0398, 0x039a, 0x039c, 0x039d, 0x039f, 0x03a1, 0x03a2, 0x03a4, 1281 0x03a6, 0x03a7, 0x03a9, 0x03ab, 0x03ac, 0x03ae, 0x03b0, 0x03b1, 1282 0x03b3, 0x03b5, 0x03b7, 0x03b8, 0x03ba, 0x03bc, 0x03bd, 0x03bf, 1283 0x03c1, 0x03c3, 0x03c4, 0x03c6, 0x03c8, 0x03ca, 0x03cb, 0x03cd, 1284 0x03cf, 0x03d1, 0x03d2, 0x03d4, 0x03d6, 0x03d8, 0x03da, 0x03db, 1285 0x03dd, 0x03df, 0x03e1, 0x03e3, 0x03e4, 0x03e6, 0x03e8, 0x03ea, 1286 0x03ec, 0x03ed, 0x03ef, 0x03f1, 0x03f3, 0x03f5, 0x03f6, 0x03f8, 1287 0x03fa, 0x03fc, 0x03fe, 0x036c 1288 ]; 1289 1290 private: 1291 // GenMidi lump structure 1292 static align(1) struct GenMidi { 1293 align(1): 1294 public: 1295 static align(1) struct Operator { 1296 align(1): 1297 ubyte mult; /* Tremolo / vibrato / sustain / KSR / multi */ 1298 ubyte attack; /* Attack rate / decay rate */ 1299 ubyte sustain; /* Sustain level / release rate */ 1300 ubyte wave; /* Waveform select */ 1301 ubyte ksl; /* Key scale level */ 1302 ubyte level; /* Output level */ 1303 ubyte feedback; /* Feedback for modulator, unused for carrier */ 1304 } 1305 1306 static align(1) struct Voice { 1307 align(1): 1308 Operator mod; /* modulator */ 1309 Operator car; /* carrier */ 1310 /* Base note offset. This is used to offset the MIDI note values. 1311 Several of the GENMIDI instruments have a base note offset of -12, 1312 causing all notes to be offset down by one octave. */ 1313 short offset; 1314 } 1315 1316 static align(1) struct Patch { 1317 align(1): 1318 public: 1319 enum Flag : ushort { 1320 Fixed = 0x01, 1321 DualVoice = 0x04, 1322 } 1323 public: 1324 /* bit 0: Fixed pitch - Instrument always plays the same note. 1325 Most MIDI instruments play a note that is specified in the MIDI "key on" event, 1326 but some (most notably percussion instruments) always play the same fixed note. 1327 bit 1: Unknown - used in instrument #65 of the Doom GENMIDI lump. 1328 bit 2: Double voice - Play two voices simultaneously. This is used even on an OPL2 chip. 1329 If this is not set, only the first voice is played. If it is set, the fine tuning 1330 field (see below) can be used to adjust the pitch of the second voice relative to 1331 the first. 1332 */ 1333 version(genmidi_dumper) { 1334 ushort flags; 1335 } else { 1336 ubyte flags; 1337 } 1338 /* Fine tuning - This normally has a value of 128, but can be adjusted to adjust the tuning of 1339 the instrument. This field only applies to the second voice of double-voice instruments; 1340 for single voice instruments it has no effect. The offset values are similar to MIDI pitch 1341 bends; for example, a value of 82 (hex) in this field is equivalent to a MIDI pitch bend of +256. 1342 */ 1343 ubyte finetune; 1344 /* Note number used for fixed pitch instruments */ 1345 ubyte note; 1346 Voice[2] voice; 1347 version(genmidi_dumper) { 1348 // no name in this mode 1349 } else { 1350 string name; // patch name 1351 } 1352 } 1353 1354 public: 1355 //char[8] header; 1356 Patch[175] patch; 1357 version(genmidi_dumper) { 1358 char[32][175] namestrs; // patch names 1359 @property const(char)[] name (usize patchidx) const pure nothrow @safe @nogc { 1360 const(char)[] res = namestrs[patchidx][]; 1361 foreach (immutable idx, immutable char ch; res) if (ch == 0) return res[0..idx]; 1362 return res; 1363 } 1364 } 1365 1366 public: 1367 version(genmidi_dumper) { 1368 void dump (VFile fo) { 1369 fo.writeln("static immutable GenMidi mGenMidi = GenMidi(["); 1370 foreach (immutable idx, const ref Patch pt; patch[]) { 1371 fo.write(" GenMidi.Patch("); 1372 fo.writef("0x%02x,", pt.flags); 1373 fo.writef("%3u,", pt.finetune); 1374 fo.writef("%3u,[", pt.note); 1375 // voices 1376 foreach (immutable vidx, const ref v; pt.voice[]) { 1377 fo.write("GenMidi.Voice("); 1378 fo.write("GenMidi.Operator("); 1379 fo.writef("%3u,", v.mod.mult); 1380 fo.writef("%3u,", v.mod.attack); 1381 fo.writef("%3u,", v.mod.sustain); 1382 fo.writef("%3u,", v.mod.wave); 1383 fo.writef("%3u,", v.mod.ksl); 1384 fo.writef("%3u,", v.mod.level); 1385 fo.writef("%3u),", v.mod.feedback); 1386 fo.write("GenMidi.Operator("); 1387 fo.writef("%3u,", v.car.mult); 1388 fo.writef("%3u,", v.car.attack); 1389 fo.writef("%3u,", v.car.sustain); 1390 fo.writef("%3u,", v.car.wave); 1391 fo.writef("%3u,", v.car.ksl); 1392 fo.writef("%3u,", v.car.level); 1393 fo.writef("%3u),", v.car.feedback); 1394 fo.writef("%4d),", v.offset); 1395 } 1396 fo.write("],", name(idx).quote); 1397 fo.writeln("),"); 1398 } 1399 fo.writeln("]);"); 1400 } 1401 } 1402 } 1403 1404 version(genmidi_dumper) { 1405 } else { 1406 //mixin(import("zgenmidi.d")); 1407 static immutable GenMidi mGenMidi = GenMidi([ 1408 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,240,243, 1, 64, 20, 10),GenMidi.Operator( 48,241,244, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Acoustic Grand Piano"), 1409 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,240,243, 0, 64, 18, 10),GenMidi.Operator( 48,241,244, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Bright Acoustic Piano"), 1410 GenMidi.Patch(0x04,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,225,243, 1, 64, 14, 8),GenMidi.Operator( 48,241,244, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 17,232, 21, 0, 0, 0, 1),GenMidi.Operator( 18,247, 20, 0, 0, 0, 0), 0),],"Electric Grand Piano"), 1411 GenMidi.Patch(0x04,130, 0,[GenMidi.Voice(GenMidi.Operator( 16,241, 83, 1, 64, 15, 6),GenMidi.Operator( 16,209,244, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 17,241, 83, 0, 64, 15, 6),GenMidi.Operator( 17,209,244, 0, 0, 0, 0), 0),],"Honky-tonk Piano"), 1412 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 33,241, 81, 0, 64, 38, 6),GenMidi.Operator( 49,210,229, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Rhodes Paino"), 1413 GenMidi.Patch(0x04,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,241,230, 0, 64, 17, 6),GenMidi.Operator(176,241,229, 0, 64, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 18,242,121, 0, 64, 3, 9),GenMidi.Operator( 16,241,153, 0, 64, 0, 0), 0),],"Chorused Piano"), 1414 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,242, 1, 2,128, 7, 6),GenMidi.Operator( 48,193,244, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Harpsichord"), 1415 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(144,161, 98, 1,128, 14, 12),GenMidi.Operator( 16,145,167, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Clavinet"), 1416 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 40,242,100, 1, 64, 15, 8),GenMidi.Operator( 49,242,228, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Celesta"), 1417 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 19,145, 17, 0, 0, 14, 9),GenMidi.Operator( 20,125, 52, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Glockenspiel"), 1418 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(178,246, 65, 0, 0, 15, 0),GenMidi.Operator(144,210,146, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Music Box"), 1419 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(240,241,243, 0, 0, 2, 1),GenMidi.Operator(242,241,244, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Vibraphone"), 1420 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(128,121, 21, 0, 0, 0, 1),GenMidi.Operator(131,248,117, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Marimba"), 1421 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 20,246,147, 0, 0, 31, 8),GenMidi.Operator( 16,246, 83, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Xylophone"), 1422 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(129,182, 19, 1,128, 25, 10),GenMidi.Operator( 2,255, 19, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Tubular-bell"), 1423 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,145, 17, 0, 64, 7, 8),GenMidi.Operator( 17, 82, 83, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Dulcimer"), 1424 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(160,177, 22, 0,128, 8, 7),GenMidi.Operator( 97,209, 23, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Hammond Organ"), 1425 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,241, 5, 1, 0, 0, 7),GenMidi.Operator(148,244, 54, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Percussive Organ"), 1426 GenMidi.Patch(0x04,138, 0,[GenMidi.Voice(GenMidi.Operator(226,242, 23, 0,128, 30, 0),GenMidi.Operator( 96,255, 7, 1,128, 0, 0), -12),GenMidi.Voice(GenMidi.Operator(224,242, 23, 1,128, 30, 0),GenMidi.Operator(160,255, 7, 0,128, 0, 0), 0),],"Rock Organ"), 1427 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48, 48, 4, 0,128, 18, 9),GenMidi.Operator( 49, 84, 20, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 49, 84, 20, 2,128, 18, 9),GenMidi.Operator( 48,253, 68, 0,128, 0, 0), 0),],"Church Organ"), 1428 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 0,128, 23, 0, 64, 9, 6),GenMidi.Operator(129, 96, 23, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Reed Organ"), 1429 GenMidi.Patch(0x04,125, 0,[GenMidi.Voice(GenMidi.Operator( 32,162, 21, 0, 64, 8, 10),GenMidi.Operator( 49, 65, 38, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 32,130, 21, 0, 64, 10, 10),GenMidi.Operator( 49, 70, 38, 1, 0, 0, 0), 0),],"Accordion"), 1430 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(176, 96, 52, 0, 0, 12, 8),GenMidi.Operator(178, 66, 22, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(176, 96, 52, 0, 0, 12, 8),GenMidi.Operator(178, 66, 22, 0,128, 0, 0), 12),],"Harmonica"), 1431 GenMidi.Patch(0x04,129, 0,[GenMidi.Voice(GenMidi.Operator( 32,240, 5, 1,128, 18, 8),GenMidi.Operator( 49, 82, 5, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 32,240, 5, 1,128, 18, 0),GenMidi.Operator( 49, 82, 5, 2, 0, 0, 0), 0),],"Tango Accordion"), 1432 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,241,245, 0,128, 13, 0),GenMidi.Operator( 32,241,246, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Acoustic Guitar (nylon)"), 1433 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,225,228, 1, 0, 13, 10),GenMidi.Operator( 48,242,227, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Acoustic Guitar (steel)"), 1434 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 0,241, 31, 2, 0, 33, 10),GenMidi.Operator( 0,244,136, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Electric Guitar (jazz)"), 1435 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 16,234, 50, 1,128, 7, 2),GenMidi.Operator( 16,210,231, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Electric Guitar (clean)"), 1436 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,224,244, 0,128, 18, 0),GenMidi.Operator( 48,242,245, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Electric Guitar (muted)"), 1437 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 0,241,255, 0, 0, 16, 10),GenMidi.Operator( 81,240,255, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0, 0, 0, 0, 0, 0),GenMidi.Operator( 0, 0, 0, 0, 0, 0, 0), 0),],"Overdriven Guitar"), 1438 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 16,241,255, 0, 0, 13, 12),GenMidi.Operator( 81,240,255, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0, 0, 0, 0, 0, 0),GenMidi.Operator( 0, 0, 0, 0, 0, 0, 0), 0),],"Distortion Guitar"), 1439 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 16,161,151, 2, 64, 3, 0),GenMidi.Operator( 17,225,231, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Guitar Harmonics"), 1440 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,196, 32, 0, 0, 14, 0),GenMidi.Operator(176,195,246, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0, 0, 0, 0, 0, 0),GenMidi.Operator( 0, 0, 0, 0, 0, 0, 0), 0),],"Acoustic Bass"), 1441 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,240,255, 0,128, 22, 10),GenMidi.Operator( 49,241,248, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Electric Bass (finger)"), 1442 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,224, 20, 0,128, 15, 8),GenMidi.Operator( 48,225,214, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Electric Bass (pick)"), 1443 GenMidi.Patch(0x04,126, 0,[GenMidi.Voice(GenMidi.Operator(225, 81, 69, 1, 64, 13, 0),GenMidi.Operator(160,145, 70, 1, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator(161, 81, 69, 1, 64, 13, 0),GenMidi.Operator(160,129, 70, 1, 0, 0, 0), 0),],"Fretless Bass"), 1444 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,240,231, 2, 0, 0, 0),GenMidi.Operator( 49,241, 71, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 16,245,231, 1, 0, 13, 13),GenMidi.Operator( 16,246,231, 2, 0, 0, 0), 0),],"* Slap Bass 1"), 1445 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,240,229, 0,128, 16, 8),GenMidi.Operator( 49,241,245, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Slap Bass 2"), 1446 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,244,245, 1, 0, 10, 10),GenMidi.Operator( 48,243,246, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Synth Bass 1"), 1447 GenMidi.Patch(0x04,118, 0,[GenMidi.Voice(GenMidi.Operator( 48,131, 70, 1, 0, 21, 10),GenMidi.Operator( 49,210, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 48,131, 70, 1, 0, 21, 10),GenMidi.Operator( 49,210, 23, 0, 0, 0, 0), 0),],"Synth Bass 2"), 1448 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 96, 80, 69, 1, 0, 23, 6),GenMidi.Operator(161, 97, 70, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Violin"), 1449 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(240, 96, 68, 0,128, 15, 2),GenMidi.Operator(113, 65, 21, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Viola"), 1450 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(176,208, 20, 2, 0, 15, 6),GenMidi.Operator( 97, 98, 23, 1,128, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Cello"), 1451 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(240,177, 17, 2,128, 10, 6),GenMidi.Operator( 32,160, 21, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Contrabass"), 1452 GenMidi.Patch(0x04,139, 0,[GenMidi.Voice(GenMidi.Operator(240,195, 1, 2,128, 9, 6),GenMidi.Operator( 97,131, 5, 0, 64, 0, 0), -12),GenMidi.Voice(GenMidi.Operator(112,179, 1, 2,128, 9, 6),GenMidi.Operator( 96,147, 5, 1, 64, 0, 0), 0),],"Tremolo Strings"), 1453 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,248,249, 2,128, 23, 14),GenMidi.Operator( 32,118,230, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Pizzicato Strings"), 1454 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 49,241, 53, 0, 0, 36, 0),GenMidi.Operator( 32,243,179, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Orchestral Harp"), 1455 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 0,170,200, 0, 0, 4, 10),GenMidi.Operator( 16,210,179, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Timpani"), 1456 GenMidi.Patch(0x04,120, 0,[GenMidi.Voice(GenMidi.Operator( 96,192, 4, 1, 64, 17, 4),GenMidi.Operator(177, 85, 4, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(160,144, 4, 1, 64, 18, 6),GenMidi.Operator( 49, 85, 4, 1,128, 0, 0), 0),],"String Ensemble 1"), 1457 GenMidi.Patch(0x04,133, 0,[GenMidi.Voice(GenMidi.Operator( 32,144, 5, 1, 64, 17, 4),GenMidi.Operator(161, 53, 5, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(160,144, 5, 1, 64, 18, 6),GenMidi.Operator( 33, 53, 5, 1,128, 0, 0), 0),],"String Ensemble 2"), 1458 GenMidi.Patch(0x04,123, 0,[GenMidi.Voice(GenMidi.Operator(161,105, 5, 2,128, 19, 10),GenMidi.Operator(241,102, 2, 2, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator(161,105, 5, 2,128, 19, 10),GenMidi.Operator(241,102, 2, 2, 0, 0, 0), -12),],"Synth Strings 1"), 1459 GenMidi.Patch(0x04,132, 0,[GenMidi.Voice(GenMidi.Operator( 33, 17, 3, 0, 64, 13, 0),GenMidi.Operator( 32, 49, 4, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 17, 51, 2,128, 2, 8),GenMidi.Operator( 0, 49, 54, 1,128, 0, 0), 0),],"Synth Strings 2"), 1460 GenMidi.Patch(0x04,138, 0,[GenMidi.Voice(GenMidi.Operator( 96,144, 84, 0, 64, 22, 0),GenMidi.Operator( 96,112, 4, 0, 64, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 32,144, 84, 0,128, 18, 0),GenMidi.Operator( 96,112, 4, 0,192, 0, 0), 0),],"Choir Aahs"), 1461 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(160,177,183, 0,128, 25, 0),GenMidi.Operator(160,114,133, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 18,102,240, 0,192, 6, 12),GenMidi.Operator( 81,174,182, 0,192, 0, 0), -12),],"Voice Oohs"), 1462 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(176, 96, 84, 0, 64, 26, 0),GenMidi.Operator(176, 48,116, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Synth Voice"), 1463 GenMidi.Patch(0x04,128, 0,[GenMidi.Voice(GenMidi.Operator( 16, 48, 67, 0,128, 16, 2),GenMidi.Operator( 16,100, 20, 0, 0, 0, 0), -24),GenMidi.Voice(GenMidi.Operator(144, 80, 66, 0,128, 15, 2),GenMidi.Operator( 17, 84, 69, 0, 0, 0, 0), -12),],"Orchestra Hit"), 1464 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,128, 21, 1,128, 14, 10),GenMidi.Operator( 48, 81, 54, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Trumpet"), 1465 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(176,113, 31, 0, 0, 26, 14),GenMidi.Operator( 32,114, 59, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Trombone"), 1466 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,128, 70, 0, 0, 22, 12),GenMidi.Operator( 32,146, 86, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0,128, 0, 0),GenMidi.Operator( 0, 0,240, 0,128, 0, 0), 0),],"Tuba"), 1467 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(128,128,230, 1,128, 13, 12),GenMidi.Operator(144, 81,246, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Muted Trumpet"), 1468 GenMidi.Patch(0x04,129, 0,[GenMidi.Voice(GenMidi.Operator( 32,112,184, 0, 0, 34, 14),GenMidi.Operator( 32, 97,150, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 32,112,184, 0, 0, 35, 14),GenMidi.Operator( 32, 97,150, 0,128, 0, 0), 0),],"French Horn"), 1469 GenMidi.Patch(0x04,131, 0,[GenMidi.Voice(GenMidi.Operator( 32, 96, 21, 1,128, 14, 10),GenMidi.Operator( 48, 81, 54, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 48,112, 23, 1,128, 18, 14),GenMidi.Operator( 48, 97, 54, 1, 0, 0, 0), 0),],"Brass Section"), 1470 GenMidi.Patch(0x04,134, 0,[GenMidi.Voice(GenMidi.Operator( 32,145,166, 2, 64, 13, 12),GenMidi.Operator( 32,129,151, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 32,145,166, 2,128, 12, 12),GenMidi.Operator( 32,145,151, 1, 0, 0, 0), 0),],"Synth Brass 1"), 1471 GenMidi.Patch(0x04,134, 0,[GenMidi.Voice(GenMidi.Operator( 48,129,166, 2, 64, 16, 12),GenMidi.Operator( 48, 97,151, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 48,129,166, 2, 64, 10, 10),GenMidi.Operator( 48, 97,151, 1, 0, 0, 0), 0),],"Synth Bass 2"), 1472 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(160, 96, 5, 0,128, 22, 6),GenMidi.Operator(177, 82, 22, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Soprano Sax"), 1473 GenMidi.Patch(0x02,128, 0,[GenMidi.Voice(GenMidi.Operator(160,112, 6, 1,128, 9, 6),GenMidi.Operator(176, 98, 22, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Alto Sax"), 1474 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(160,152, 11, 0, 64, 10, 10),GenMidi.Operator(176,115, 11, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Tenor Sax"), 1475 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(160,144, 11, 1,128, 5, 10),GenMidi.Operator(176, 99, 27, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Baritone Sax"), 1476 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(112,112, 22, 0,128, 16, 6),GenMidi.Operator(162, 92, 8, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Oboe"), 1477 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,200, 7, 0, 64, 15, 10),GenMidi.Operator( 49,115, 7, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"English Horn"), 1478 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,144, 25, 0,128, 17, 10),GenMidi.Operator( 49, 97, 27, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Bassoon"), 1479 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,165, 23, 0,128, 13, 8),GenMidi.Operator(176, 99, 23, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Clarinet"), 1480 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(240,110,143, 0,128, 0, 14),GenMidi.Operator(112, 53, 42, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Piccolo"), 1481 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(160, 80,136, 0,128, 19, 8),GenMidi.Operator( 96, 85, 42, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Flute"), 1482 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,101, 23, 0, 0, 10, 11),GenMidi.Operator(160,116, 39, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Recorder"), 1483 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(176, 36, 39, 1,128, 4, 9),GenMidi.Operator(176, 69, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 23,240, 2, 0, 0, 14),GenMidi.Operator( 0, 37,240, 0, 0, 0, 0), 0),],"Pan Flute"), 1484 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(225, 87, 4, 0,128, 45, 14),GenMidi.Operator( 96, 87, 55, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Bottle Blow"), 1485 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(241, 87, 52, 3, 0, 40, 14),GenMidi.Operator(225,103, 93, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Shakuhachi"), 1486 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(208, 49, 15, 0,192, 7, 11),GenMidi.Operator(112, 50, 5, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Whistle"), 1487 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(176, 81, 5, 0,192, 7, 11),GenMidi.Operator( 48, 66, 41, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Ocarina"), 1488 GenMidi.Patch(0x04,130, 0,[GenMidi.Voice(GenMidi.Operator( 34, 81, 91, 1, 64, 18, 0),GenMidi.Operator( 48, 96, 37, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 34,145, 91, 1, 64, 13, 0),GenMidi.Operator( 48,240, 37, 1, 0, 0, 0), 0),],"Lead 1 (square)"), 1489 GenMidi.Patch(0x04,127, 0,[GenMidi.Voice(GenMidi.Operator( 32,193,155, 1, 64, 3, 8),GenMidi.Operator( 49,192,101, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 96,177,171, 1, 64, 1, 8),GenMidi.Operator( 49,241, 5, 0, 0, 0, 0), 0),],"Lead 2 (sawtooth)"), 1490 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(240, 87, 51, 3, 0, 40, 14),GenMidi.Operator(224,103, 7, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Lead 3 (calliope)"), 1491 GenMidi.Patch(0x04,130, 0,[GenMidi.Voice(GenMidi.Operator(224, 87, 4, 3, 0, 35, 14),GenMidi.Operator(224,103, 77, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(224,247, 4, 3, 0, 35, 14),GenMidi.Operator(224,135, 77, 0, 0, 0, 0), 0),],"Lead 4 (chiffer)"), 1492 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(161,120, 11, 1, 64, 2, 8),GenMidi.Operator( 48,241, 43, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Lead 5 (charang)"), 1493 GenMidi.Patch(0x04,122, 0,[GenMidi.Voice(GenMidi.Operator( 96,128, 85, 0, 0, 33, 8),GenMidi.Operator(224,242, 20, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 32,144, 85, 0, 0, 33, 8),GenMidi.Operator(160,162, 20, 0, 0, 0, 0), 0),],"Lead 6 (voice)"), 1494 GenMidi.Patch(0x04,125, 0,[GenMidi.Voice(GenMidi.Operator( 32,193,149, 1, 64, 3, 10),GenMidi.Operator(176,112, 99, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(160,145,149, 1, 64, 9, 10),GenMidi.Operator( 49, 97, 99, 1, 0, 0, 0), -5),],"Lead 7 (5th sawtooth)"), 1495 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 36, 81, 7, 1, 64, 0, 9),GenMidi.Operator(160,253, 41, 2, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Lead 8 (bass & lead)"), 1496 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 36, 81, 7, 1, 64, 0, 9),GenMidi.Operator(160,253, 41, 2, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* Lead 8 (bass & lead)"), 1497 GenMidi.Patch(0x04,130, 0,[GenMidi.Voice(GenMidi.Operator(128, 50, 5, 0,192, 0, 9),GenMidi.Operator( 96, 51, 5, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 64, 50, 5, 0, 64, 0, 9),GenMidi.Operator(224, 51, 5, 0, 0, 0, 0), 0),],"Pad 2 (warm)"), 1498 GenMidi.Patch(0x04,130, 0,[GenMidi.Voice(GenMidi.Operator(160,161,165, 2,128, 15, 12),GenMidi.Operator(160,161,150, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(160,161,165, 2,128, 15, 12),GenMidi.Operator(160,161,150, 1, 0, 0, 0), 0),],"Pad 3 (polysynth)"), 1499 GenMidi.Patch(0x04,139, 0,[GenMidi.Voice(GenMidi.Operator(224,240, 5, 0, 64, 4, 1),GenMidi.Operator( 96,129, 84, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(224,240, 5, 1, 64, 4, 1),GenMidi.Operator( 96,113, 84, 0,128, 0, 0), 0),],"Pad 4 (choir)"), 1500 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(128,161, 51, 0,128, 10, 7),GenMidi.Operator(224, 82, 84, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Pad 5 (bowed glass)"), 1501 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(129,128, 82, 1,128, 29, 14),GenMidi.Operator( 64, 35, 83, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Pad 6 (metal)"), 1502 GenMidi.Patch(0x04,126, 0,[GenMidi.Voice(GenMidi.Operator(225, 81, 69, 1, 64, 13, 0),GenMidi.Operator(160,145, 70, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(161, 81, 69, 1, 64, 13, 0),GenMidi.Operator(160,129, 70, 1, 0, 0, 0), 0),],"Pad 7 (halo)"), 1503 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(225, 17, 82, 1,128, 12, 8),GenMidi.Operator(224,128,115, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Pad 8 (sweep)"), 1504 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,114, 71, 0, 64, 0, 11),GenMidi.Operator(131,248, 25, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"FX 1 (rain)"), 1505 GenMidi.Patch(0x04,136, 0,[GenMidi.Voice(GenMidi.Operator( 0,133, 2, 1,192, 18, 10),GenMidi.Operator(193, 69, 18, 1, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 34, 69, 3, 0,192, 18, 10),GenMidi.Operator(227, 53, 53, 2, 0, 0, 0), -5),],"FX 2 (soundtrack)"), 1506 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 4,246,116, 0,192, 0, 0),GenMidi.Operator( 2,163, 36, 0, 0, 0, 0), -24),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* FX 3 (crystal)"), 1507 GenMidi.Patch(0x04,126, 0,[GenMidi.Voice(GenMidi.Operator(144,192,210, 0,128, 14, 0),GenMidi.Operator( 48,209,210, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(144,208,210, 0,128, 14, 0),GenMidi.Operator( 48,241,210, 0, 0, 0, 0), 0),],"FX 4 (atmosphere)"), 1508 GenMidi.Patch(0x04,116, 0,[GenMidi.Voice(GenMidi.Operator(208,144,243, 0, 0, 18, 0),GenMidi.Operator(192,194,243, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator(208,144,243, 0, 0, 18, 0),GenMidi.Operator(192,194,242, 0,128, 0, 0), 0),],"FX 5 (brightness)"), 1509 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(224, 19, 82, 1, 0, 26, 0),GenMidi.Operator(241, 51, 19, 2,128, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"FX 6 (goblin)"), 1510 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(224, 69,186, 0, 0, 26, 0),GenMidi.Operator(240, 50,145, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"FX 7 (echo drops)"), 1511 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 16, 88, 2, 1, 0, 24, 10),GenMidi.Operator( 2, 66,114, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"* FX 8 (star-theme)"), 1512 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32, 99,179, 0, 0, 8, 2),GenMidi.Operator( 36, 99,179, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Sitar"), 1513 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,119, 18, 0, 0, 13, 4),GenMidi.Operator( 16,243,244, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0,249,250, 2, 0, 10, 15),GenMidi.Operator( 0,249,250, 3, 64, 0, 0), 0),],"Banjo"), 1514 GenMidi.Patch(0x04,128, 0,[GenMidi.Voice(GenMidi.Operator( 0,249, 51, 0,128, 0, 0),GenMidi.Operator( 0,244,115, 2,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 7,249,172, 2, 0, 26, 0),GenMidi.Operator( 15,249, 41, 2, 0, 0, 0), 0),],"Shamisen"), 1515 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,242, 83, 1, 0, 33, 8),GenMidi.Operator( 34,145,228, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Koto"), 1516 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 3,241, 57, 3, 64, 15, 6),GenMidi.Operator( 21,214,116, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Kalimba"), 1517 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,137, 21, 1, 64, 2, 10),GenMidi.Operator( 33,107, 7, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Bag Pipe"), 1518 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48,161, 3, 0, 0, 31, 14),GenMidi.Operator( 33, 82, 38, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Fiddle"), 1519 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 48, 64, 19, 0, 0, 19, 8),GenMidi.Operator( 48, 97, 22, 1,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Shanai"), 1520 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 19,161, 50, 0, 0, 0, 1),GenMidi.Operator( 18,178,114, 1,128, 0, 0), -7),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Tinkle Bell"), 1521 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(149,231, 1, 0,128, 1, 4),GenMidi.Operator( 22,150,103, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Agogo"), 1522 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 3,240, 4, 1, 64, 9, 6),GenMidi.Operator( 32,130, 5, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Steel Drums"), 1523 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 19,248,209, 0, 64, 4, 6),GenMidi.Operator( 18,245,120, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Woodblock"), 1524 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 16,167,236, 0, 0, 11, 0),GenMidi.Operator( 16,213,245, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Taiko Drum"), 1525 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 32,168,200, 0, 0, 11, 0),GenMidi.Operator( 1,214,183, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Melodic Tom"), 1526 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 0,248,196, 0, 0, 11, 0),GenMidi.Operator( 0,211,183, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Synth Drum"), 1527 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 12, 65, 49, 0,128, 15, 14),GenMidi.Operator( 16, 33, 29, 3,128, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Reverse Cymbal"), 1528 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 50, 52,179, 1, 0, 33, 14),GenMidi.Operator( 49, 84,247, 3, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Guitar Fret Noise"), 1529 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(209, 55, 4, 0,128, 45, 14),GenMidi.Operator( 80, 55, 52, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Breath Noise"), 1530 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 2, 62, 1, 2, 0, 0, 14),GenMidi.Operator( 8, 20,243, 2, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Seashore"), 1531 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(245,235, 3, 0,192, 20, 7),GenMidi.Operator(246, 69,104, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Bird Tweet"), 1532 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator(240,218,113, 1, 0, 0, 8),GenMidi.Operator(202,176, 23, 1,192, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Telephone Ring"), 1533 GenMidi.Patch(0x01,128, 17,[GenMidi.Voice(GenMidi.Operator(240, 30, 17, 1, 0, 0, 8),GenMidi.Operator(226, 33, 17, 1,192, 0, 0), -24),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Helicopter"), 1534 GenMidi.Patch(0x01,128, 65,[GenMidi.Voice(GenMidi.Operator(239, 83, 0, 2,128, 6, 14),GenMidi.Operator(239, 16, 2, 3,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Applause"), 1535 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 12,240,240, 2, 0, 0, 14),GenMidi.Operator( 4,246,230, 0, 0, 0, 0), -12),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Gun Shot"), 1536 GenMidi.Patch(0x01,128, 38,[GenMidi.Voice(GenMidi.Operator( 0,249, 87, 2, 0, 0, 0),GenMidi.Operator( 0,251, 70, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Acoustic Bass Drum"), 1537 GenMidi.Patch(0x01,128, 25,[GenMidi.Voice(GenMidi.Operator( 0,250, 71, 0, 0, 0, 6),GenMidi.Operator( 0,249, 6, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Acoustic Bass Drum"), 1538 GenMidi.Patch(0x01,128, 83,[GenMidi.Voice(GenMidi.Operator( 2,253,103, 0,128, 0, 6),GenMidi.Operator( 3,247,120, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Slide Stick"), 1539 GenMidi.Patch(0x01,128, 32,[GenMidi.Voice(GenMidi.Operator( 15,247, 20, 2, 0, 5, 14),GenMidi.Operator( 0,249, 71, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Acoustic Snare"), 1540 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator(225,136,251, 3, 0, 0, 15),GenMidi.Operator(255,166,168, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Hand Clap"), 1541 GenMidi.Patch(0x05,128, 36,[GenMidi.Voice(GenMidi.Operator( 6,170,255, 0, 0, 0, 14),GenMidi.Operator( 0,247,250, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 63, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 42),],"Electric Snare"), 1542 GenMidi.Patch(0x01,128, 15,[GenMidi.Voice(GenMidi.Operator( 2,245,108, 0, 0, 0, 7),GenMidi.Operator( 3,247, 56, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Floor Tom"), 1543 GenMidi.Patch(0x01,128, 88,[GenMidi.Voice(GenMidi.Operator( 12,152, 94, 2, 0, 0, 15),GenMidi.Operator( 15,251, 6, 3, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Closed High-Hat"), 1544 GenMidi.Patch(0x01,128, 19,[GenMidi.Voice(GenMidi.Operator( 2,245,120, 0, 0, 0, 7),GenMidi.Operator( 0,247, 55, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High Floor Tom"), 1545 GenMidi.Patch(0x01,128, 88,[GenMidi.Voice(GenMidi.Operator( 12,120, 94, 2, 0, 0, 15),GenMidi.Operator( 10,138, 43, 3,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Pedal High Hat"), 1546 GenMidi.Patch(0x01,128, 21,[GenMidi.Voice(GenMidi.Operator( 2,245, 55, 0, 0, 0, 3),GenMidi.Operator( 2,247, 55, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Tom"), 1547 GenMidi.Patch(0x01,128, 79,[GenMidi.Voice(GenMidi.Operator( 0,199, 1, 2, 64, 5, 14),GenMidi.Operator( 11,249, 51, 2, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Open High Hat"), 1548 GenMidi.Patch(0x01,128, 26,[GenMidi.Voice(GenMidi.Operator( 2,245, 55, 0, 0, 0, 3),GenMidi.Operator( 2,247, 55, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low-Mid Tom"), 1549 GenMidi.Patch(0x01,128, 28,[GenMidi.Voice(GenMidi.Operator( 2,245, 55, 0, 0, 0, 3),GenMidi.Operator( 2,247, 55, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High-Mid Tom"), 1550 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator( 4,194,230, 0, 0, 16, 14),GenMidi.Operator( 0,232, 67, 3, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Crash Cymbal 1"), 1551 GenMidi.Patch(0x01,128, 32,[GenMidi.Voice(GenMidi.Operator( 2,245, 55, 0, 0, 0, 3),GenMidi.Operator( 2,247, 55, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High Tom"), 1552 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator( 3,253, 18, 2,128, 0, 10),GenMidi.Operator( 2,253, 5, 2,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Ride Cymbal 1"), 1553 GenMidi.Patch(0x01,128, 96,[GenMidi.Voice(GenMidi.Operator( 0,228,133, 0,128, 0, 14),GenMidi.Operator(192,215, 52, 2,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Chinses Cymbal"), 1554 GenMidi.Patch(0x01,128, 72,[GenMidi.Voice(GenMidi.Operator( 4,226,230, 0,128, 16, 14),GenMidi.Operator( 1,184, 68, 1, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Ride Bell"), 1555 GenMidi.Patch(0x01,128, 79,[GenMidi.Voice(GenMidi.Operator( 2,118,119, 2,128, 7, 15),GenMidi.Operator( 1,152,103, 3, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Tambourine"), 1556 GenMidi.Patch(0x01,128, 69,[GenMidi.Voice(GenMidi.Operator( 4,246,112, 2,128, 1, 14),GenMidi.Operator( 7,198,163, 3, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Splash Cymbal"), 1557 GenMidi.Patch(0x01,128, 71,[GenMidi.Voice(GenMidi.Operator( 0,253,103, 0, 0, 0, 6),GenMidi.Operator( 1,246,152, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Cowbell"), 1558 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator( 4,194,230, 0, 0, 16, 14),GenMidi.Operator( 0,232, 67, 3, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Crash Cymbal 2"), 1559 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 1,249,181, 0, 0, 7, 11),GenMidi.Operator(191,212, 80, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Vibraslap"), 1560 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator( 3,253, 18, 2,128, 0, 10),GenMidi.Operator( 2,253, 5, 2,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Ride Cymbal 2"), 1561 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator( 0,251, 86, 2, 0, 0, 4),GenMidi.Operator( 0,250, 38, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High Bongo"), 1562 GenMidi.Patch(0x01,128, 54,[GenMidi.Voice(GenMidi.Operator( 0,251, 86, 2, 0, 0, 4),GenMidi.Operator( 0,250, 38, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Bango"), 1563 GenMidi.Patch(0x01,128, 72,[GenMidi.Voice(GenMidi.Operator( 0,251, 86, 2,128, 0, 0),GenMidi.Operator( 0,247, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Mute High Conga"), 1564 GenMidi.Patch(0x01,128, 67,[GenMidi.Voice(GenMidi.Operator( 0,251, 86, 2,128, 0, 0),GenMidi.Operator( 0,247, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Open High Conga"), 1565 GenMidi.Patch(0x01,128, 60,[GenMidi.Voice(GenMidi.Operator( 0,251, 86, 2,128, 0, 0),GenMidi.Operator( 0,247, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Conga"), 1566 GenMidi.Patch(0x01,128, 55,[GenMidi.Voice(GenMidi.Operator( 3,251, 86, 0,128, 1, 0),GenMidi.Operator( 0,247, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High Timbale"), 1567 GenMidi.Patch(0x01,128, 48,[GenMidi.Voice(GenMidi.Operator( 3,251, 86, 0,128, 1, 0),GenMidi.Operator( 0,247, 23, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Timbale"), 1568 GenMidi.Patch(0x01,128, 77,[GenMidi.Voice(GenMidi.Operator( 1,253,103, 3, 0, 0, 8),GenMidi.Operator( 1,246,152, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High Agogo"), 1569 GenMidi.Patch(0x01,128, 72,[GenMidi.Voice(GenMidi.Operator( 1,253,103, 3, 0, 0, 8),GenMidi.Operator( 1,246,152, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Agogo"), 1570 GenMidi.Patch(0x01,128, 88,[GenMidi.Voice(GenMidi.Operator( 12,120, 94, 2, 0, 0, 15),GenMidi.Operator( 10,138, 43, 3,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Cabasa"), 1571 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 0, 90,214, 2, 0, 14, 10),GenMidi.Operator(191,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Maracas"), 1572 GenMidi.Patch(0x01,128, 49,[GenMidi.Voice(GenMidi.Operator( 0,249,199, 1, 0, 7, 10),GenMidi.Operator(128,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Short Whistle"), 1573 GenMidi.Patch(0x01,128, 49,[GenMidi.Voice(GenMidi.Operator( 0,249,199, 1, 0, 7, 10),GenMidi.Operator(128,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Long Whistle"), 1574 GenMidi.Patch(0x01,128, 49,[GenMidi.Voice(GenMidi.Operator( 0,249,199, 1, 0, 7, 10),GenMidi.Operator(128,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Short Guiro"), 1575 GenMidi.Patch(0x01,128, 49,[GenMidi.Voice(GenMidi.Operator( 0,249,199, 1, 0, 7, 10),GenMidi.Operator(128,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Long Guiro"), 1576 GenMidi.Patch(0x01,128, 73,[GenMidi.Voice(GenMidi.Operator( 19,248,209, 1, 64, 4, 6),GenMidi.Operator( 18,245,120, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Claves"), 1577 GenMidi.Patch(0x01,128, 68,[GenMidi.Voice(GenMidi.Operator( 19,248,209, 1, 64, 4, 6),GenMidi.Operator( 18,245,120, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"High Wood Block"), 1578 GenMidi.Patch(0x01,128, 61,[GenMidi.Voice(GenMidi.Operator( 19,248,209, 1, 64, 4, 6),GenMidi.Operator( 18,245,120, 0, 0, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Low Wood Block"), 1579 GenMidi.Patch(0x00,128, 0,[GenMidi.Voice(GenMidi.Operator( 1, 94,220, 1, 0, 11, 10),GenMidi.Operator(191,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Mute Cuica"), 1580 GenMidi.Patch(0x01,128, 49,[GenMidi.Voice(GenMidi.Operator( 0,249,199, 1, 0, 7, 10),GenMidi.Operator(128,255,255, 0,192, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Open Cuica"), 1581 GenMidi.Patch(0x01,128, 90,[GenMidi.Voice(GenMidi.Operator(197,242, 96, 0, 64, 15, 8),GenMidi.Operator(212,244,122, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Mute Triangle"), 1582 GenMidi.Patch(0x01,128, 90,[GenMidi.Voice(GenMidi.Operator(133,242, 96, 1, 64, 15, 8),GenMidi.Operator(148,242,183, 0,128, 0, 0), 0),GenMidi.Voice(GenMidi.Operator( 0, 0,240, 0, 0, 0, 0),GenMidi.Operator( 0, 0,240, 0, 0, 0, 0), 0),],"Open Triangle"), 1583 ]); 1584 } 1585 1586 private: 1587 static struct SynthMidiChannel { 1588 ubyte volume; 1589 ushort volume_t; 1590 ubyte pan; 1591 ubyte reg_pan; 1592 ubyte pitch; 1593 const(GenMidi.Patch)* patch; 1594 bool drum; 1595 } 1596 1597 static struct SynthVoice { 1598 ubyte bank; 1599 1600 ubyte op_base; 1601 ubyte ch_base; 1602 1603 uint freq; 1604 1605 ubyte[2] tl; 1606 ubyte additive; 1607 1608 bool voice_dual; 1609 const(GenMidi.Voice)* voice_data; 1610 const(GenMidi.Patch)* patch; 1611 1612 SynthMidiChannel* chan; 1613 1614 ubyte velocity; 1615 ubyte key; 1616 ubyte note; 1617 1618 int finetune; 1619 1620 ubyte pan; 1621 } 1622 1623 static align(1) struct MidiHeader { 1624 align(1): 1625 char[4] header; 1626 uint length; 1627 ushort format; 1628 ushort count; 1629 ushort time; 1630 ubyte[0] data; 1631 } 1632 1633 static align(1) struct MidiTrack { 1634 align(1): 1635 char[4] header; 1636 uint length; 1637 ubyte[0] data; 1638 } 1639 1640 static struct Track { 1641 const(ubyte)* data; 1642 const(ubyte)* pointer; 1643 uint length; 1644 uint time; 1645 ubyte lastevent; 1646 bool finish; 1647 uint num; 1648 } 1649 1650 static align(1) struct MusHeader { 1651 align(1): 1652 char[4] header; 1653 ushort length; 1654 ushort offset; 1655 } 1656 1657 private: 1658 // config 1659 uint mSampleRate; 1660 bool mOPL2Mode; 1661 bool mStereo; 1662 1663 // genmidi lump 1664 version(genmidi_dumper) { 1665 GenMidi mGenMidi; 1666 bool mGenMidiLoaded; 1667 } 1668 1669 // OPL3 emulator 1670 OPL3Chip chip; 1671 1672 SynthMidiChannel[16] mSynthMidiChannels; 1673 SynthVoice[18] mSynthVoices; 1674 uint mSynthVoiceNum; 1675 SynthVoice*[18] mSynthVoicesAllocated; 1676 uint mSynthVoicesAllocatedNum; 1677 SynthVoice*[18] mSynthVoicesFree; 1678 uint mSynthVoicesFreeNum; 1679 1680 Track[] mMidiTracks; 1681 uint mMidiCount; 1682 uint mMidiTimebase; 1683 uint mMidiCallrate; 1684 uint mMidiTimer; 1685 uint mMidiTimechange; 1686 uint mMidiRate; 1687 uint mMidiFinished; 1688 ubyte[16] mMidiChannels; 1689 ubyte mMidiChannelcnt; 1690 1691 const(ubyte)* mMusData; 1692 const(ubyte)* mMusPointer; 1693 ushort mMusLength; 1694 uint mMusTimer; 1695 uint mMusTimeend; 1696 ubyte[16] mMusChanVelo; 1697 1698 uint mSongTempo; 1699 bool mPlayerActive; 1700 bool mPlayLooped; 1701 1702 enum DataFormat { 1703 Unknown, 1704 Midi, 1705 Mus, 1706 } 1707 DataFormat mDataFormat = DataFormat.Unknown; 1708 1709 uint mOPLCounter; 1710 1711 ubyte[] songdata; 1712 1713 private: 1714 static ushort MISC_Read16LE (ushort n) pure nothrow @trusted @nogc { 1715 const(ubyte)* m = cast(const(ubyte)*)&n; 1716 return cast(ushort)(m[0]|(m[1]<<8)); 1717 } 1718 1719 static ushort MISC_Read16BE (ushort n) pure nothrow @trusted @nogc { 1720 const(ubyte)* m = cast(const(ubyte)*)&n; 1721 return cast(ushort)(m[1]|(m[0]<<8)); 1722 } 1723 1724 static uint MISC_Read32LE (uint n) pure nothrow @trusted @nogc { 1725 const(ubyte)* m = cast(const(ubyte)*)&n; 1726 return m[0]|(m[1]<<8)|(m[2]<<16)|(m[3]<<24); 1727 } 1728 1729 static uint MISC_Read32BE (uint n) pure nothrow @trusted @nogc { 1730 const(ubyte)* m = cast(const(ubyte)*)&n; 1731 return m[3]|(m[2]<<8)|(m[1]<<16)|(m[0]<<24); 1732 } 1733 1734 // ////////////////////////////////////////////////////////////////////// // 1735 // synth 1736 enum SynthCmd : ubyte { 1737 NoteOff, 1738 NoteOn, 1739 PitchBend, 1740 Patch, 1741 Control, 1742 } 1743 1744 enum SynthCtl : ubyte { 1745 Bank, 1746 Modulation, 1747 Volume, 1748 Pan, 1749 Expression, 1750 Reverb, 1751 Chorus, 1752 Sustain, 1753 Soft, 1754 AllNoteOff, 1755 MonoMode, 1756 PolyMode, 1757 Reset, 1758 } 1759 1760 void SynthResetVoice (ref SynthVoice voice) nothrow @trusted @nogc { 1761 voice.freq = 0; 1762 voice.voice_dual = false; 1763 voice.voice_data = null; 1764 voice.patch = null; 1765 voice.chan = null; 1766 voice.velocity = 0; 1767 voice.key = 0; 1768 voice.note = 0; 1769 voice.pan = 0x30; 1770 voice.finetune = 0; 1771 voice.tl.ptr[0] = 0x3f; 1772 voice.tl.ptr[1] = 0x3f; 1773 } 1774 1775 void SynthResetChip (ref OPL3Chip chip) nothrow @safe @nogc { 1776 for (ushort i = 0x40; i < 0x56; ++i) chip.writeReg(i, 0x3f); 1777 for (ushort i = 0x60; i < 0xf6; ++i) chip.writeReg(i, 0x00); 1778 for (ushort i = 0x01; i < 0x40; ++i) chip.writeReg(i, 0x00); 1779 1780 chip.writeReg(0x01, 0x20); 1781 1782 if (!mOPL2Mode) { 1783 chip.writeReg(0x105, 0x01); 1784 for (ushort i = 0x140; i < 0x156; ++i) chip.writeReg(i, 0x3f); 1785 for (ushort i = 0x160; i < 0x1f6; ++i) chip.writeReg(i, 0x00); 1786 for (ushort i = 0x101; i < 0x140; ++i) chip.writeReg(i, 0x00); 1787 chip.writeReg(0x105, 0x01); 1788 } else { 1789 chip.writeReg(0x105, 0x00); 1790 } 1791 } 1792 1793 void SynthResetMidi (ref SynthMidiChannel channel) nothrow @trusted @nogc { 1794 channel.volume = 100; 1795 channel.volume_t = opl_voltable.ptr[channel.volume]+1; 1796 channel.pan = 64; 1797 channel.reg_pan = 0x30; 1798 channel.pitch = 64; 1799 channel.patch = &mGenMidi.patch.ptr[0]; 1800 channel.drum = false; 1801 if (&channel is &mSynthMidiChannels.ptr[15]) channel.drum = true; 1802 } 1803 1804 void SynthInit () nothrow @trusted @nogc { 1805 static immutable ubyte[9] opl_slotoffset = [0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12]; 1806 1807 for (uint i = 0; i < 18; ++i) { 1808 mSynthVoices.ptr[i].bank = cast(ubyte)(i/9); 1809 mSynthVoices.ptr[i].op_base = opl_slotoffset.ptr[i%9]; 1810 mSynthVoices.ptr[i].ch_base = i%9; 1811 SynthResetVoice(mSynthVoices.ptr[i]); 1812 } 1813 1814 for (uint i = 0; i < 16; ++i) SynthResetMidi(mSynthMidiChannels.ptr[i]); 1815 1816 SynthResetChip(chip); 1817 1818 mSynthVoiceNum = (mOPL2Mode ? 9 : 18); 1819 1820 for (ubyte i = 0; i < mSynthVoiceNum; i++) mSynthVoicesFree.ptr[i] = &mSynthVoices.ptr[i]; 1821 1822 mSynthVoicesAllocatedNum = 0; 1823 mSynthVoicesFreeNum = mSynthVoiceNum; 1824 } 1825 1826 void SynthWriteReg (uint bank, ushort reg, ubyte data) nothrow @trusted @nogc { 1827 reg |= bank<<8; 1828 chip.writeReg(reg, data); 1829 } 1830 1831 void SynthVoiceOff (SynthVoice* voice) nothrow @trusted @nogc { 1832 SynthWriteReg(voice.bank, cast(ushort)(0xb0+voice.ch_base), cast(ubyte)(voice.freq>>8)); 1833 voice.freq = 0; 1834 for (uint i = 0; i < mSynthVoicesAllocatedNum; ++i) { 1835 if (mSynthVoicesAllocated.ptr[i] is voice) { 1836 for (uint j = i; j < mSynthVoicesAllocatedNum-1; ++j) { 1837 mSynthVoicesAllocated.ptr[j] = mSynthVoicesAllocated.ptr[j+1]; 1838 } 1839 break; 1840 } 1841 } 1842 --mSynthVoicesAllocatedNum; 1843 mSynthVoicesFree.ptr[mSynthVoicesFreeNum++] = voice; 1844 } 1845 1846 void SynthVoiceFreq (SynthVoice* voice) nothrow @trusted @nogc { 1847 int freq = voice.chan.pitch+voice.finetune+32*voice.note; 1848 uint block = 0; 1849 1850 if (freq < 0) { 1851 freq = 0; 1852 } else if (freq >= 284) { 1853 freq -= 284; 1854 block = freq/384; 1855 if (block > 7) block = 7; 1856 freq %= 384; 1857 freq += 284; 1858 } 1859 1860 freq = (block<<10)|opl_freqtable.ptr[freq]; 1861 1862 SynthWriteReg(voice.bank, 0xa0+voice.ch_base, freq&0xff); 1863 SynthWriteReg(voice.bank, cast(ushort)(0xb0+voice.ch_base), cast(ubyte)((freq>>8)|0x20)); 1864 1865 voice.freq = freq; 1866 } 1867 1868 void SynthVoiceVolume (SynthVoice* voice) nothrow @trusted @nogc { 1869 ubyte volume = cast(ubyte)(0x3f-(voice.chan.volume_t*opl_voltable.ptr[voice.velocity])/256); 1870 if ((voice.tl.ptr[0]&0x3f) != volume) { 1871 voice.tl.ptr[0] = (voice.tl.ptr[0]&0xc0)|volume; 1872 SynthWriteReg(voice.bank, 0x43+voice.op_base, voice.tl.ptr[0]); 1873 if (voice.additive) { 1874 ubyte volume2 = cast(ubyte)(0x3f-voice.additive); 1875 if (volume2 < volume) volume2 = volume; 1876 volume2 |= voice.tl.ptr[1]&0xc0; 1877 if (volume2 != voice.tl.ptr[1]) { 1878 voice.tl.ptr[1] = volume2; 1879 SynthWriteReg(voice.bank, 0x40+voice.op_base, voice.tl.ptr[1]); 1880 } 1881 } 1882 } 1883 } 1884 1885 ubyte SynthOperatorSetup (uint bank, uint base, const(GenMidi.Operator)* op, bool volume) nothrow @trusted @nogc { 1886 ubyte tl = op.ksl; 1887 if (volume) tl |= 0x3f; else tl |= op.level; 1888 SynthWriteReg(bank, cast(ushort)(0x40+base), tl); 1889 SynthWriteReg(bank, cast(ushort)(0x20+base), op.mult); 1890 SynthWriteReg(bank, cast(ushort)(0x60+base), op.attack); 1891 SynthWriteReg(bank, cast(ushort)(0x80+base), op.sustain); 1892 SynthWriteReg(bank, cast(ushort)(0xE0+base), op.wave); 1893 return tl; 1894 } 1895 1896 void SynthVoiceOn (SynthMidiChannel* channel, const(GenMidi.Patch)* patch, bool dual, ubyte key, ubyte velocity) nothrow @trusted @nogc { 1897 SynthVoice* voice; 1898 const(GenMidi.Voice)* voice_data; 1899 uint bank; 1900 uint base; 1901 int note; 1902 1903 if (mSynthVoicesFreeNum == 0) return; 1904 1905 voice = mSynthVoicesFree.ptr[0]; 1906 1907 --mSynthVoicesFreeNum; 1908 1909 for (uint i = 0; i < mSynthVoicesFreeNum; ++i) mSynthVoicesFree.ptr[i] = mSynthVoicesFree.ptr[i+1]; 1910 1911 mSynthVoicesAllocated.ptr[mSynthVoicesAllocatedNum++] = voice; 1912 1913 voice.chan = channel; 1914 voice.key = key; 1915 voice.velocity = velocity; 1916 voice.patch = patch; 1917 voice.voice_dual = dual; 1918 1919 if (dual) { 1920 voice_data = &patch.voice.ptr[1]; 1921 voice.finetune = cast(int)(patch.finetune>>1)-64; 1922 } else { 1923 voice_data = &patch.voice.ptr[0]; 1924 voice.finetune = 0; 1925 } 1926 1927 voice.pan = channel.reg_pan; 1928 1929 if (voice.voice_data != voice_data) { 1930 voice.voice_data = voice_data; 1931 bank = voice.bank; 1932 base = voice.op_base; 1933 1934 voice.tl.ptr[0] = SynthOperatorSetup(bank, base+3, &voice_data.car, true); 1935 1936 if (voice_data.mod.feedback&1) { 1937 voice.additive = cast(ubyte)(0x3f-voice_data.mod.level); 1938 voice.tl.ptr[1] = SynthOperatorSetup(bank, base, &voice_data.mod, true); 1939 } else { 1940 voice.additive = 0; 1941 voice.tl.ptr[1] = SynthOperatorSetup(bank, base, &voice_data.mod, false); 1942 } 1943 } 1944 1945 SynthWriteReg(voice.bank, 0xc0+voice.ch_base, voice_data.mod.feedback|voice.pan); 1946 1947 if (MISC_Read16LE(patch.flags)&GenMidi.Patch.Flag.Fixed) { 1948 note = patch.note; 1949 } else { 1950 if (channel.drum) { 1951 note = 60; 1952 } else { 1953 note = key; 1954 note += cast(short)MISC_Read16LE(cast(ushort)voice_data.offset); 1955 while (note < 0) note += 12; 1956 while (note > 95) note -= 12; 1957 } 1958 } 1959 voice.note = cast(ubyte)note; 1960 1961 SynthVoiceVolume(voice); 1962 SynthVoiceFreq(voice); 1963 } 1964 1965 void SynthKillVoice () nothrow @trusted @nogc { 1966 SynthVoice* voice; 1967 if (mSynthVoicesFreeNum > 0) return; 1968 voice = mSynthVoicesAllocated.ptr[0]; 1969 for (uint i = 0; i < mSynthVoicesAllocatedNum; i++) { 1970 if (mSynthVoicesAllocated.ptr[i].voice_dual || mSynthVoicesAllocated.ptr[i].chan >= voice.chan) { 1971 voice = mSynthVoicesAllocated.ptr[i]; 1972 } 1973 } 1974 SynthVoiceOff(voice); 1975 } 1976 1977 void SynthNoteOff (SynthMidiChannel* channel, ubyte note) nothrow @trusted @nogc { 1978 for (uint i = 0; i < mSynthVoicesAllocatedNum; ) { 1979 if (mSynthVoicesAllocated.ptr[i].chan is channel && mSynthVoicesAllocated.ptr[i].key == note) { 1980 SynthVoiceOff(mSynthVoicesAllocated.ptr[i]); 1981 } else { 1982 ++i; 1983 } 1984 } 1985 } 1986 1987 void SynthNoteOn (SynthMidiChannel* channel, ubyte note, ubyte velo) nothrow @trusted @nogc { 1988 const(GenMidi.Patch)* patch; 1989 1990 if (velo == 0) { 1991 SynthNoteOff(channel, note); 1992 return; 1993 } 1994 1995 if (channel.drum) { 1996 if (note < 35 || note > 81) return; 1997 patch = &mGenMidi.patch.ptr[note-35+128]; 1998 } else { 1999 patch = channel.patch; 2000 } 2001 2002 SynthKillVoice(); 2003 2004 SynthVoiceOn(channel, patch, false, note, velo); 2005 2006 if (mSynthVoicesFreeNum > 0 && MISC_Read16LE(patch.flags)&GenMidi.Patch.Flag.DualVoice) { 2007 SynthVoiceOn(channel, patch, true, note, velo); 2008 } 2009 } 2010 2011 void SynthPitchBend (SynthMidiChannel* channel, ubyte pitch) nothrow @trusted @nogc { 2012 SynthVoice*[18] mSynthChannelVoices; 2013 SynthVoice*[18] mSynthOtherVoices; 2014 2015 uint cnt1 = 0; 2016 uint cnt2 = 0; 2017 2018 channel.pitch = pitch; 2019 2020 for (uint i = 0; i < mSynthVoicesAllocatedNum; ++i) { 2021 if (mSynthVoicesAllocated.ptr[i].chan is channel) { 2022 SynthVoiceFreq(mSynthVoicesAllocated.ptr[i]); 2023 mSynthChannelVoices.ptr[cnt1++] = mSynthVoicesAllocated.ptr[i]; 2024 } else { 2025 mSynthOtherVoices.ptr[cnt2++] = mSynthVoicesAllocated.ptr[i]; 2026 } 2027 } 2028 2029 for (uint i = 0; i < cnt2; ++i) mSynthVoicesAllocated.ptr[i] = mSynthOtherVoices.ptr[i]; 2030 for (uint i = 0; i < cnt1; ++i) mSynthVoicesAllocated.ptr[i+cnt2] = mSynthChannelVoices.ptr[i]; 2031 } 2032 2033 void SynthUpdatePatch (SynthMidiChannel* channel, ubyte patch) nothrow @trusted @nogc { 2034 if (patch >= mGenMidi.patch.length) patch = 0; 2035 channel.patch = &mGenMidi.patch.ptr[patch]; 2036 } 2037 2038 void SynthUpdatePan (SynthMidiChannel* channel, ubyte pan) nothrow @trusted @nogc { 2039 ubyte new_pan = 0x30; 2040 if (pan <= 48) new_pan = 0x20; else if (pan >= 96) new_pan = 0x10; 2041 channel.pan = pan; 2042 if (channel.reg_pan != new_pan) { 2043 channel.reg_pan = new_pan; 2044 for (uint i = 0; i < mSynthVoicesAllocatedNum; ++i) { 2045 if (mSynthVoicesAllocated.ptr[i].chan is channel) { 2046 mSynthVoicesAllocated.ptr[i].pan = new_pan; 2047 SynthWriteReg(mSynthVoicesAllocated.ptr[i].bank, 2048 0xc0+mSynthVoicesAllocated.ptr[i].ch_base, 2049 mSynthVoicesAllocated.ptr[i].voice_data.mod.feedback|new_pan); 2050 } 2051 } 2052 } 2053 } 2054 2055 void SynthUpdateVolume (SynthMidiChannel* channel, ubyte volume) nothrow @trusted @nogc { 2056 if (volume&0x80) volume = 0x7f; 2057 if (channel.volume != volume) { 2058 channel.volume = volume; 2059 channel.volume_t = opl_voltable.ptr[channel.volume]+1; 2060 for (uint i = 0; i < mSynthVoicesAllocatedNum; ++i) { 2061 if (mSynthVoicesAllocated.ptr[i].chan is channel) { 2062 SynthVoiceVolume(mSynthVoicesAllocated.ptr[i]); 2063 } 2064 } 2065 } 2066 } 2067 2068 void SynthNoteOffAll (SynthMidiChannel* channel) nothrow @trusted @nogc { 2069 for (uint i = 0; i < mSynthVoicesAllocatedNum; ) { 2070 if (mSynthVoicesAllocated.ptr[i].chan is channel) { 2071 SynthVoiceOff(mSynthVoicesAllocated.ptr[i]); 2072 } else { 2073 ++i; 2074 } 2075 } 2076 } 2077 2078 void SynthEventReset (SynthMidiChannel* channel) nothrow @trusted @nogc { 2079 SynthNoteOffAll(channel); 2080 channel.reg_pan = 0x30; 2081 channel.pan = 64; 2082 channel.pitch = 64; 2083 } 2084 2085 void SynthReset () nothrow @trusted @nogc { 2086 for (ubyte i = 0; i < 16; ++i) { 2087 SynthNoteOffAll(&mSynthMidiChannels.ptr[i]); 2088 SynthResetMidi(mSynthMidiChannels.ptr[i]); 2089 } 2090 } 2091 2092 void SynthWrite (ubyte command, ubyte data1, ubyte data2) nothrow @trusted @nogc { 2093 SynthMidiChannel* channel = &mSynthMidiChannels.ptr[command&0x0f]; 2094 command >>= 4; 2095 switch (command) { 2096 case SynthCmd.NoteOff: SynthNoteOff(channel, data1); break; 2097 case SynthCmd.NoteOn: SynthNoteOn(channel, data1, data2); break; 2098 case SynthCmd.PitchBend: SynthPitchBend(channel, data2); break; 2099 case SynthCmd.Patch: SynthUpdatePatch(channel, data1); break; 2100 case SynthCmd.Control: 2101 switch (data1) { 2102 case SynthCtl.Volume: SynthUpdateVolume(channel, data2); break; 2103 case SynthCtl.Pan: SynthUpdatePan(channel, data2); break; 2104 case SynthCtl.AllNoteOff: SynthNoteOffAll(channel); break; 2105 case SynthCtl.Reset: SynthEventReset(channel); break; 2106 default: break; 2107 } 2108 break; 2109 default: break; 2110 } 2111 } 2112 2113 // ////////////////////////////////////////////////////////////////////// // 2114 // MIDI 2115 uint MIDI_ReadDelay (const(ubyte)** data) nothrow @trusted @nogc { 2116 const(ubyte)* dn = *data; 2117 uint delay = 0; 2118 do { 2119 delay = (delay<<7)|((*dn)&0x7f); 2120 } while (*dn++&0x80); 2121 *data = dn; 2122 return delay; 2123 } 2124 2125 bool MIDI_LoadSong () nothrow @trusted { 2126 enum midh = "MThd"; 2127 enum mtrkh = "MTrk"; 2128 2129 import core.stdc.string : memcmp; 2130 2131 if (songdata.length <= MidiHeader.sizeof) return false; 2132 2133 if (memcmp(songdata.ptr, "RIFF".ptr, 4) == 0) 2134 songdata = songdata[0x14 .. $]; 2135 2136 const(MidiHeader)* mid = cast(const(MidiHeader)*)songdata.ptr; 2137 2138 if (memcmp(mid.header.ptr, midh.ptr, 4) != 0 || MISC_Read32BE(mid.length) != 6) return false; 2139 2140 mMidiCount = MISC_Read16BE(mid.count); 2141 const(ubyte)[] midi_data = mid.data.ptr[0..songdata.length-MidiHeader.sizeof]; 2142 mMidiTimebase = MISC_Read16BE(mid.time); 2143 2144 // if (mMidiTracks !is null) delete mMidiTracks; 2145 2146 mMidiTracks = new Track[](mMidiCount); 2147 2148 uint trknum = 0; 2149 while (trknum < mMidiCount) { 2150 if (midi_data.length < 8) { /*delete mMidiTracks;*/ return false; } // out of data 2151 const(MidiTrack)* track = cast(const(MidiTrack)*)midi_data.ptr; 2152 uint datasize = MISC_Read32BE(track.length); 2153 if (midi_data.length-8 < datasize) { /*delete mMidiTracks;*/ return false; } // out of data 2154 if (memcmp(track.header.ptr, mtrkh.ptr, 4) != 0) { 2155 // not a track, skip this chunk 2156 midi_data = midi_data[datasize+8..$]; 2157 } else { 2158 // track 2159 mMidiTracks[trknum].length = datasize; 2160 mMidiTracks[trknum].data = track.data.ptr; 2161 mMidiTracks[trknum].num = trknum++; 2162 // move to next chunk 2163 midi_data = midi_data[datasize+8..$]; 2164 } 2165 } 2166 // check if we have all tracks 2167 if (trknum != mMidiCount) { /*delete mMidiTracks;*/ return false; } // out of tracks 2168 2169 mDataFormat = DataFormat.Midi; 2170 2171 return true; 2172 } 2173 2174 bool MIDI_StartSong () nothrow @trusted @nogc { 2175 if (mDataFormat != DataFormat.Midi || mPlayerActive) return false; 2176 2177 for (uint i = 0; i < mMidiCount; ++i) { 2178 mMidiTracks[i].pointer = mMidiTracks[i].data; 2179 mMidiTracks[i].time = MIDI_ReadDelay(&mMidiTracks[i].pointer); 2180 mMidiTracks[i].lastevent = 0x80; 2181 mMidiTracks[i].finish = 0; 2182 } 2183 2184 for (uint i = 0; i < 16; ++i) mMidiChannels.ptr[i] = 0xff; 2185 2186 mMidiChannelcnt = 0; 2187 2188 mMidiRate = 1000000/(500000/mMidiTimebase); 2189 mMidiCallrate = mSongTempo; 2190 mMidiTimer = 0; 2191 mMidiTimechange = 0; 2192 mMidiFinished = 0; 2193 2194 mPlayerActive = true; 2195 2196 return true; 2197 } 2198 2199 void MIDI_StopSong () nothrow @trusted @nogc { 2200 if (mDataFormat != DataFormat.Midi || !mPlayerActive) return; 2201 mPlayerActive = false; 2202 for (uint i = 0; i < 16; ++i) { 2203 SynthWrite(cast(ubyte)((SynthCmd.Control<<4)|i), SynthCtl.AllNoteOff, 0); 2204 } 2205 SynthReset(); 2206 } 2207 2208 Track* MIDI_NextTrack () nothrow @trusted @nogc { 2209 Track* mintrack = &mMidiTracks[0]; 2210 for (uint i = 1; i < mMidiCount; i++) { 2211 if ((mMidiTracks[i].time < mintrack.time && !mMidiTracks[i].finish) || mintrack.finish) { 2212 mintrack = &mMidiTracks[i]; 2213 } 2214 } 2215 return mintrack; 2216 } 2217 2218 ubyte MIDI_GetChannel (ubyte chan) nothrow @trusted @nogc { 2219 if (chan == 9) return 15; 2220 if (mMidiChannels.ptr[chan] == 0xff) mMidiChannels.ptr[chan] = mMidiChannelcnt++; 2221 return mMidiChannels.ptr[chan]; 2222 } 2223 2224 void MIDI_Command (const(ubyte)** datap, ubyte evnt) nothrow @trusted @nogc { 2225 ubyte chan; 2226 const(ubyte)* data; 2227 ubyte v1, v2; 2228 2229 data = *datap; 2230 chan = MIDI_GetChannel(evnt&0x0f); 2231 switch (evnt&0xf0) { 2232 case 0x80: 2233 v1 = *data++; 2234 v2 = *data++; 2235 SynthWrite((SynthCmd.NoteOff<<4)|chan, v1, 0); 2236 break; 2237 case 0x90: 2238 v1 = *data++; 2239 v2 = *data++; 2240 SynthWrite((SynthCmd.NoteOn<<4)|chan, v1, v2); 2241 break; 2242 case 0xa0: 2243 data += 2; 2244 break; 2245 case 0xb0: 2246 v1 = *data++; 2247 v2 = *data++; 2248 switch (v1) { 2249 case 0x00: case 0x20: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Bank, v2); break; 2250 case 0x01: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Modulation, v2); break; 2251 case 0x07: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Volume, v2); break; 2252 case 0x0a: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Pan, v2); break; 2253 case 0x0b: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Expression, v2); break; 2254 case 0x40: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Sustain, v2); break; 2255 case 0x43: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Soft, v2); break; 2256 case 0x5b: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Reverb, v2); break; 2257 case 0x5d: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Chorus, v2); break; 2258 case 0x78: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.AllNoteOff, v2); break; 2259 case 0x79: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Reset, v2); break; 2260 case 0x7b: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.AllNoteOff, v2); break; 2261 case 0x7e: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.MonoMode, v2); break; 2262 case 0x7f: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.PolyMode, v2); break; 2263 default: break; 2264 } 2265 break; 2266 case 0xc0: 2267 v1 = *data++; 2268 SynthWrite((SynthCmd.Patch<<4)|chan, v1, 0); 2269 break; 2270 case 0xd0: 2271 data += 1; 2272 break; 2273 case 0xe0: 2274 v1 = *data++; 2275 v2 = *data++; 2276 SynthWrite((SynthCmd.PitchBend<<4)|chan, v1, v2); 2277 break; 2278 default: break; 2279 } 2280 *datap = data; 2281 } 2282 2283 void MIDI_FinishTrack (Track* trck) nothrow @trusted @nogc { 2284 if (trck.finish) return; 2285 trck.finish = true; 2286 ++mMidiFinished; 2287 } 2288 2289 void MIDI_AdvanceTrack (Track* trck) nothrow @trusted @nogc { 2290 ubyte evnt; 2291 ubyte meta; 2292 ubyte length; 2293 uint tempo; 2294 const(ubyte)* data; 2295 2296 evnt = *trck.pointer++; 2297 2298 if (!(evnt&0x80)) { 2299 evnt = trck.lastevent; 2300 --trck.pointer; 2301 } 2302 2303 switch (evnt) { 2304 case 0xf0: 2305 case 0xf7: 2306 length = cast(ubyte)MIDI_ReadDelay(&trck.pointer); 2307 trck.pointer += length; 2308 break; 2309 case 0xff: 2310 meta = *trck.pointer++; 2311 length = cast(ubyte)MIDI_ReadDelay(&trck.pointer); 2312 data = trck.pointer; 2313 trck.pointer += length; 2314 switch (meta) { 2315 case 0x2f: 2316 MIDI_FinishTrack(trck); 2317 break; 2318 case 0x51: 2319 if (length == 0x03) { 2320 tempo = (data[0]<<16)|(data[1]<<8)|data[2]; 2321 mMidiTimechange += (mMidiTimer*mMidiRate)/mMidiCallrate; 2322 mMidiTimer = 0; 2323 mMidiRate = 1000000/(tempo/mMidiTimebase); 2324 } 2325 break; 2326 default: break; 2327 } 2328 break; 2329 default: 2330 MIDI_Command(&trck.pointer,evnt); 2331 break; 2332 } 2333 2334 trck.lastevent = evnt; 2335 if (trck.pointer >= trck.data+trck.length) MIDI_FinishTrack(trck); 2336 } 2337 2338 void MIDI_Callback () nothrow @trusted @nogc { 2339 Track* trck; 2340 2341 if (mDataFormat != DataFormat.Midi || !mPlayerActive) return; 2342 2343 for (;;) { 2344 trck = MIDI_NextTrack(); 2345 if (trck.finish || trck.time > mMidiTimechange+(mMidiTimer*mMidiRate)/mMidiCallrate) break; 2346 MIDI_AdvanceTrack(trck); 2347 if (!trck.finish) trck.time += MIDI_ReadDelay(&trck.pointer); 2348 } 2349 2350 ++mMidiTimer; 2351 2352 if (mMidiFinished == mMidiCount) { 2353 if (!mPlayLooped) MIDI_StopSong(); 2354 for (uint i = 0; i < mMidiCount; i++) { 2355 mMidiTracks[i].pointer = mMidiTracks[i].data; 2356 mMidiTracks[i].time = MIDI_ReadDelay(&mMidiTracks[i].pointer); 2357 mMidiTracks[i].lastevent = 0x80; 2358 mMidiTracks[i].finish = 0; 2359 } 2360 2361 for (uint i = 0; i < 16; i++) mMidiChannels.ptr[i] = 0xff; 2362 2363 mMidiChannelcnt = 0; 2364 2365 mMidiRate = 1000000/(500000/mMidiTimebase); 2366 mMidiTimer = 0; 2367 mMidiTimechange = 0; 2368 mMidiFinished = 0; 2369 2370 SynthReset(); 2371 } 2372 } 2373 2374 // ////////////////////////////////////////////////////////////////////// // 2375 // MUS 2376 void MUS_Callback () nothrow @trusted @nogc { 2377 if (mDataFormat != DataFormat.Mus || !mPlayerActive) return; 2378 while (mMusTimer == mMusTimeend) { 2379 ubyte cmd; 2380 ubyte evnt; 2381 ubyte chan; 2382 ubyte data1; 2383 ubyte data2; 2384 2385 cmd = *mMusPointer++; 2386 chan = cmd&0x0f; 2387 evnt = (cmd>>4)&7; 2388 2389 switch (evnt) { 2390 case 0x00: 2391 data1 = *mMusPointer++; 2392 SynthWrite((SynthCmd.NoteOff<<4)|chan, data1, 0); 2393 break; 2394 case 0x01: 2395 data1 = *mMusPointer++; 2396 if (data1&0x80) { 2397 data1 &= 0x7f; 2398 mMusChanVelo.ptr[chan] = *mMusPointer++; 2399 } 2400 SynthWrite((SynthCmd.NoteOn<<4)|chan, data1, mMusChanVelo.ptr[chan]); 2401 break; 2402 case 0x02: 2403 data1 = *mMusPointer++; 2404 SynthWrite((SynthCmd.PitchBend<<4)|chan, (data1&1)<<6, data1>>1); 2405 break; 2406 case 0x03: 2407 case 0x04: 2408 data1 = *mMusPointer++; 2409 data2 = 0; 2410 if (evnt == 0x04) data2 = *mMusPointer++; 2411 switch (data1) { 2412 case 0x00: SynthWrite((SynthCmd.Patch<<4)|chan, data2, 0); break; 2413 case 0x01: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Bank, data2); break; 2414 case 0x02: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Modulation, data2); break; 2415 case 0x03: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Volume, data2); break; 2416 case 0x04: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Pan, data2); break; 2417 case 0x05: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Expression, data2); break; 2418 case 0x06: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Reverb, data2); break; 2419 case 0x07: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Chorus, data2); break; 2420 case 0x08: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Sustain, data2); break; 2421 case 0x09: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Soft, data2); break; 2422 case 0x0a: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.AllNoteOff, data2); break; 2423 case 0x0b: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.AllNoteOff, data2); break; 2424 case 0x0c: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.MonoMode, data2); break; 2425 case 0x0d: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.PolyMode, data2); break; 2426 case 0x0e: SynthWrite((SynthCmd.Control<<4)|chan, SynthCtl.Reset, data2); break; 2427 case 0x0f: break; 2428 default: break; 2429 } 2430 break; 2431 case 0x05: 2432 break; 2433 case 0x06: 2434 if (!mPlayLooped) { 2435 MUS_StopSong(); 2436 return; 2437 } 2438 mMusPointer = mMusData; 2439 cmd = 0; 2440 SynthReset(); 2441 break; 2442 case 0x07: 2443 ++mMusPointer; 2444 break; 2445 default: break; 2446 } 2447 2448 if (cmd&0x80) { 2449 mMusTimeend += MIDI_ReadDelay(&mMusPointer); 2450 break; 2451 } 2452 } 2453 ++mMusTimer; 2454 } 2455 2456 bool MUS_LoadSong () nothrow @trusted @nogc { 2457 enum mush = "MUS\x1a"; 2458 import core.stdc.string : memcmp; 2459 if (songdata.length <= MusHeader.sizeof) return false; 2460 const(MusHeader)* mus = cast(const(MusHeader)*)songdata.ptr; 2461 if (memcmp(mus.header.ptr, mush.ptr, 4) != 0) return false; 2462 mMusLength = MISC_Read16LE(mus.length); 2463 uint musofs = MISC_Read16LE(mus.offset); 2464 if (musofs >= songdata.length) return false; 2465 if (songdata.length-musofs < mMusLength) return false; 2466 mMusData = &(cast(const(ubyte)*)songdata.ptr)[musofs]; 2467 mDataFormat = DataFormat.Mus; 2468 return true; 2469 } 2470 2471 bool MUS_StartSong () nothrow @trusted @nogc { 2472 if (mDataFormat != DataFormat.Mus || mPlayerActive) return true; 2473 mMusPointer = mMusData; 2474 mMusTimer = 0; 2475 mMusTimeend = 0; 2476 mPlayerActive = true; 2477 return false; 2478 } 2479 2480 void MUS_StopSong () nothrow @trusted @nogc { 2481 if (mDataFormat != DataFormat.Mus || !mPlayerActive) return; 2482 mPlayerActive = false; 2483 for (uint i = 0; i < 16; i++) { 2484 SynthWrite(cast(ubyte)((SynthCmd.Control<<4)|i), SynthCtl.AllNoteOff, 0); 2485 } 2486 SynthReset(); 2487 } 2488 2489 void PlayerInit () nothrow @trusted @nogc { 2490 mSongTempo = DefaultTempo; 2491 mPlayerActive = false; 2492 mDataFormat = DataFormat.Unknown; 2493 mPlayLooped = false; 2494 mMidiTracks = null; 2495 } 2496 2497 version(genmidi_dumper) static immutable string genmidiData = import("GENMIDI.lmp"); 2498 2499 version(genmidi_dumper) bool loadGenMIDI (const(void)* data) nothrow @trusted @nogc { 2500 import core.stdc.string : memcmp, memcpy; 2501 static immutable string genmidi_head = "#OPL_II#"; 2502 if (memcmp(data, data, 8) != 0) return false; 2503 memcpy(&mGenMidi, (cast(const(ubyte)*)data)+8, GenMidi.sizeof); 2504 mGenMidiLoaded = true; 2505 return true; 2506 } 2507 2508 version(genmidi_dumper) public void dumpGenMidi (VFile fo) { mGenMidi.dump(fo); } 2509 2510 public: 2511 enum DefaultTempo = 140; 2512 2513 public: 2514 this (int asamplerate=48000, bool aopl3mode=true, bool astereo=true) nothrow @trusted @nogc { 2515 version(genmidi_dumper) mGenMidiLoaded = false; 2516 songdata = null; 2517 sendConfig(asamplerate, aopl3mode, astereo); 2518 SynthInit(); 2519 PlayerInit(); 2520 mOPLCounter = 0; 2521 version(genmidi_dumper) loadGenMIDI(genmidiData.ptr); 2522 } 2523 2524 private void sendConfig (int asamplerate, bool aopl3mode, bool astereo) nothrow @safe @nogc { 2525 if (asamplerate < 4096) asamplerate = 4096; 2526 if (asamplerate > 96000) asamplerate = 96000; 2527 mSampleRate = asamplerate; 2528 chip.reset(mSampleRate); 2529 mOPL2Mode = !aopl3mode; 2530 mStereo = astereo; 2531 SynthInit(); 2532 } 2533 2534 bool load (const(void)[] data) { 2535 import core.stdc.string : memcpy; 2536 stop(); // just in case 2537 mDataFormat = DataFormat.Unknown; 2538 //delete songdata; 2539 version(genmidi_dumper) if (!mGenMidiLoaded) return false; 2540 // just in case 2541 scope(failure) { 2542 mDataFormat = DataFormat.Unknown; 2543 //delete songdata; 2544 } 2545 if (data.length == 0) return false; 2546 songdata.length = data.length; 2547 memcpy(songdata.ptr, data.ptr, data.length); 2548 if (MUS_LoadSong() || MIDI_LoadSong()) return true; 2549 mDataFormat = DataFormat.Unknown; 2550 //delete songdata; 2551 return false; 2552 } 2553 2554 @property void tempo (uint atempo) pure nothrow @safe @nogc { 2555 if (atempo < 1) atempo = 1; else if (atempo > 255) atempo = 255; 2556 mSongTempo = atempo; 2557 } 2558 2559 @property uint tempo () const pure nothrow @safe @nogc { return mSongTempo; } 2560 2561 @property void looped (bool loop) pure nothrow @safe @nogc { mPlayLooped = loop; } 2562 @property bool looped () const pure nothrow @safe @nogc { return mPlayLooped; } 2563 2564 @property bool loaded () const pure nothrow @safe @nogc { return (mDataFormat != DataFormat.Unknown); } 2565 2566 @property bool playing () const pure nothrow @safe @nogc { return mPlayerActive; } 2567 2568 @property void stereo (bool v) pure nothrow @safe @nogc { mStereo = v; } 2569 @property bool stereo () const pure nothrow @safe @nogc { return mStereo; } 2570 2571 // returns `false` if song cannot be started (or if it is already playing) 2572 bool play () nothrow @safe @nogc { 2573 bool res = false; 2574 final switch (mDataFormat) { 2575 case DataFormat.Unknown: break; 2576 case DataFormat.Midi: res = MIDI_StartSong(); break; 2577 case DataFormat.Mus: res = MUS_StartSong(); break; 2578 } 2579 return res; 2580 } 2581 2582 void stop () nothrow @safe @nogc { 2583 final switch (mDataFormat) { 2584 case DataFormat.Unknown: break; 2585 case DataFormat.Midi: MIDI_StopSong(); break; 2586 case DataFormat.Mus: MUS_StopSong(); break; 2587 } 2588 } 2589 2590 // return number of generated *frames* 2591 // returns 0 if song is complete (and player is not looped) 2592 uint generate (short[] buffer) nothrow @trusted @nogc { 2593 if (mDataFormat == DataFormat.Unknown) return 0; 2594 if (buffer.length > uint.max/64) buffer = buffer[0..uint.max/64]; 2595 uint length = cast(uint)buffer.length; 2596 if (mStereo) length /= 2; 2597 if (length < 1) return 0; // oops 2598 short[2] accm = void; 2599 uint i = 0; 2600 while (i < length) { 2601 if (!mPlayerActive) break; 2602 while (mOPLCounter >= mSampleRate) { 2603 if (mPlayerActive) { 2604 final switch (mDataFormat) { 2605 case DataFormat.Unknown: assert(0, "the thing that should not be"); 2606 case DataFormat.Midi: MIDI_Callback(); break; 2607 case DataFormat.Mus: MUS_Callback(); break; 2608 } 2609 } 2610 mOPLCounter -= mSampleRate; 2611 } 2612 mOPLCounter += mSongTempo; 2613 chip.generateResampled(accm.ptr); 2614 if (mStereo) { 2615 buffer.ptr[i*2] = accm.ptr[0]; 2616 buffer.ptr[i*2+1] = accm.ptr[1]; 2617 } else { 2618 buffer.ptr[i] = (accm.ptr[0]+accm.ptr[1])/2; 2619 } 2620 ++i; 2621 } 2622 return i; 2623 } 2624 }