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