cosmetix
[iv.d.git] / nukedopl3.d
blob43cbc402ad0419d8a285abef86723b0e141ae037
1 //
2 // Copyright (C) 2013-2016 Alexey Khokholov (Nuke.YKT)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
15 // Nuked OPL3 emulator.
16 // Thanks:
17 // MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
18 // Feedback and Rhythm part calculation information.
19 // forums.submarine.org.uk(carbon14, opl3):
20 // Tremolo and phase generator calculation information.
21 // OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
22 // OPL2 ROMs.
24 // version: 1.7.4
25 module iv.nukedopl3 /*is aliced*/;
26 import iv.alice;
27 nothrow @trusted @nogc:
29 public:
30 enum OPL_WRITEBUF_SIZE = 1024;
31 enum OPL_WRITEBUF_DELAY = 2;
34 // ////////////////////////////////////////////////////////////////////////// //
35 private:
36 struct OPL3Slot {
37 OPL3Channel* channel;
38 OPL3Chip* chip;
39 short out_;
40 short fbmod;
41 short* mod;
42 short prout;
43 short eg_rout;
44 short eg_out;
45 ubyte eg_inc;
46 ubyte eg_gen;
47 ubyte eg_rate;
48 ubyte eg_ksl;
49 ubyte *trem;
50 ubyte reg_vib;
51 ubyte reg_type;
52 ubyte reg_ksr;
53 ubyte reg_mult;
54 ubyte reg_ksl;
55 ubyte reg_tl;
56 ubyte reg_ar;
57 ubyte reg_dr;
58 ubyte reg_sl;
59 ubyte reg_rr;
60 ubyte reg_wf;
61 ubyte key;
62 uint pg_phase;
63 uint timer;
66 struct OPL3Channel {
67 OPL3Slot*[2] slots;
68 OPL3Channel* pair;
69 OPL3Chip* chip;
70 short*[4] out_;
71 ubyte chtype;
72 ushort f_num;
73 ubyte block;
74 ubyte fb;
75 ubyte con;
76 ubyte alg;
77 ubyte ksv;
78 ushort cha, chb;
81 struct OPL3WriteBuf {
82 ulong time;
83 ushort reg;
84 ubyte data;
87 ///
88 public struct OPL3Chip {
89 private:
90 OPL3Channel[18] channel;
91 OPL3Slot[36] slot;
92 ushort timer;
93 ubyte newm;
94 ubyte nts;
95 ubyte rhy;
96 ubyte vibpos;
97 ubyte vibshift;
98 ubyte tremolo;
99 ubyte tremolopos;
100 ubyte tremoloshift;
101 uint noise;
102 short zeromod;
103 int[2] mixbuff;
104 //OPL3L
105 int rateratio;
106 int samplecnt;
107 short[2] oldsamples;
108 short[2] samples;
110 ulong writebuf_samplecnt;
111 uint writebuf_cur;
112 uint writebuf_last;
113 ulong writebuf_lasttime;
114 OPL3WriteBuf[OPL_WRITEBUF_SIZE] writebuf;
118 private:
119 enum RSM_FRAC = 10;
121 // Channel types
123 enum {
124 ch_2op = 0,
125 ch_4op = 1,
126 ch_4op2 = 2,
127 ch_drum = 3
130 // Envelope key types
132 enum {
133 egk_norm = 0x01,
134 egk_drum = 0x02
139 // logsin table
142 static immutable ushort[256] logsinrom = [
143 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,
144 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
145 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,
146 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
147 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,
148 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
149 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,
150 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
151 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,
152 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
153 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,
154 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
155 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,
156 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
157 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,
158 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
159 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,
160 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
161 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,
162 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
163 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,
164 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
165 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,
166 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
167 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,
168 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
169 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,
170 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
171 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,
172 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
173 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
174 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
178 // exp table
181 static immutable ushort[256] exprom = [
182 0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014,
183 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a,
184 0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042,
185 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a,
186 0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072,
187 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b,
188 0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4,
189 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be,
190 0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9,
191 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4,
192 0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110,
193 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c,
194 0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149,
195 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167,
196 0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185,
197 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4,
198 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4,
199 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4,
200 0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205,
201 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227,
202 0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249,
203 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d,
204 0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291,
205 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5,
206 0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db,
207 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302,
208 0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329,
209 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351,
210 0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a,
211 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4,
212 0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf,
213 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa
217 // freq mult table multiplied by 2
219 // 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15
222 static immutable ubyte[16] mt = [
223 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30
227 // ksl table
230 static immutable ubyte[16] kslrom = [
231 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64
234 static immutable ubyte[4] kslshift = [
235 8, 1, 2, 0
239 // envelope generator constants
242 static immutable ubyte[8][4][3] eg_incstep = [
244 [ 0, 0, 0, 0, 0, 0, 0, 0 ],
245 [ 0, 0, 0, 0, 0, 0, 0, 0 ],
246 [ 0, 0, 0, 0, 0, 0, 0, 0 ],
247 [ 0, 0, 0, 0, 0, 0, 0, 0 ]
250 [ 0, 1, 0, 1, 0, 1, 0, 1 ],
251 [ 0, 1, 0, 1, 1, 1, 0, 1 ],
252 [ 0, 1, 1, 1, 0, 1, 1, 1 ],
253 [ 0, 1, 1, 1, 1, 1, 1, 1 ]
256 [ 1, 1, 1, 1, 1, 1, 1, 1 ],
257 [ 2, 2, 1, 1, 1, 1, 1, 1 ],
258 [ 2, 2, 1, 1, 2, 2, 1, 1 ],
259 [ 2, 2, 2, 2, 2, 2, 1, 1 ]
263 static immutable ubyte[16] eg_incdesc = [
264 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2
267 static immutable byte[16] eg_incsh = [
268 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2
272 // address decoding
275 static immutable byte[0x20] ad_slot = [
276 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1,
277 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
280 static immutable ubyte[18] ch_slot = [
281 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32
285 // Envelope generator
288 alias envelope_sinfunc = short function (ushort phase, ushort envelope) nothrow @trusted @nogc;
289 alias envelope_genfunc = void function (OPL3Slot *slott) nothrow @trusted @nogc;
291 private short OPL3_EnvelopeCalcExp (uint level) {
292 if (level > 0x1fff) level = 0x1fff;
293 return cast(short)(((exprom.ptr[(level&0xff)^0xff]|0x400)<<1)>>(level>>8));
296 private short OPL3_EnvelopeCalcSin0 (ushort phase, ushort envelope) {
297 ushort out_ = 0;
298 ushort neg = 0;
299 phase &= 0x3ff;
300 if (phase&0x200) neg = ushort.max;
301 if (phase&0x100) out_ = logsinrom.ptr[(phase&0xff)^0xff]; else out_ = logsinrom.ptr[phase&0xff];
302 return OPL3_EnvelopeCalcExp(out_+(envelope<<3))^neg;
305 private short OPL3_EnvelopeCalcSin1 (ushort phase, ushort envelope) {
306 ushort out_ = 0;
307 phase &= 0x3ff;
308 if (phase&0x200) out_ = 0x1000;
309 else if (phase&0x100) out_ = logsinrom.ptr[(phase&0xff)^0xff];
310 else out_ = logsinrom.ptr[phase&0xff];
311 return OPL3_EnvelopeCalcExp(out_+(envelope<<3));
314 private short OPL3_EnvelopeCalcSin2 (ushort phase, ushort envelope) {
315 ushort out_ = 0;
316 phase &= 0x3ff;
317 if (phase&0x100) out_ = logsinrom.ptr[(phase&0xff)^0xff]; else out_ = logsinrom.ptr[phase&0xff];
318 return OPL3_EnvelopeCalcExp(out_+(envelope<<3));
321 private short OPL3_EnvelopeCalcSin3 (ushort phase, ushort envelope) {
322 ushort out_ = 0;
323 phase &= 0x3ff;
324 if (phase&0x100) out_ = 0x1000; else out_ = logsinrom.ptr[phase&0xff];
325 return OPL3_EnvelopeCalcExp(out_+(envelope<<3));
328 private short OPL3_EnvelopeCalcSin4 (ushort phase, ushort envelope) {
329 ushort out_ = 0;
330 ushort neg = 0;
331 phase &= 0x3ff;
332 if ((phase&0x300) == 0x100) neg = ushort.max;
333 if (phase&0x200) out_ = 0x1000;
334 else if (phase&0x80) out_ = logsinrom.ptr[((phase^0xff)<<1)&0xff];
335 else out_ = logsinrom.ptr[(phase<<1)&0xff];
336 return OPL3_EnvelopeCalcExp(out_+(envelope<<3))^neg;
339 private short OPL3_EnvelopeCalcSin5 (ushort phase, ushort envelope) {
340 ushort out_ = 0;
341 phase &= 0x3ff;
342 if (phase&0x200) out_ = 0x1000;
343 else if (phase&0x80) out_ = logsinrom.ptr[((phase^0xff)<<1)&0xff];
344 else out_ = logsinrom.ptr[(phase<<1)&0xff];
345 return OPL3_EnvelopeCalcExp(out_+(envelope<<3));
348 private short OPL3_EnvelopeCalcSin6 (ushort phase, ushort envelope) {
349 ushort neg = 0;
350 phase &= 0x3ff;
351 if (phase&0x200) neg = ushort.max;
352 return OPL3_EnvelopeCalcExp(envelope<<3)^neg;
355 private short OPL3_EnvelopeCalcSin7 (ushort phase, ushort envelope) {
356 ushort out_ = 0;
357 ushort neg = 0;
358 phase &= 0x3ff;
359 if (phase&0x200) {
360 neg = ushort.max;
361 phase = (phase&0x1ff)^0x1ff;
363 out_ = cast(ushort)(phase<<3);
364 return OPL3_EnvelopeCalcExp(out_+(envelope<<3))^neg;
367 static immutable envelope_sinfunc[8] envelope_sin = [
368 &OPL3_EnvelopeCalcSin0,
369 &OPL3_EnvelopeCalcSin1,
370 &OPL3_EnvelopeCalcSin2,
371 &OPL3_EnvelopeCalcSin3,
372 &OPL3_EnvelopeCalcSin4,
373 &OPL3_EnvelopeCalcSin5,
374 &OPL3_EnvelopeCalcSin6,
375 &OPL3_EnvelopeCalcSin7
378 static immutable envelope_genfunc[5] envelope_gen = [
379 &OPL3_EnvelopeGenOff,
380 &OPL3_EnvelopeGenAttack,
381 &OPL3_EnvelopeGenDecay,
382 &OPL3_EnvelopeGenSustain,
383 &OPL3_EnvelopeGenRelease
386 alias envelope_gen_num = int;
387 enum /*envelope_gen_num*/:int {
388 envelope_gen_num_off = 0,
389 envelope_gen_num_attack = 1,
390 envelope_gen_num_decay = 2,
391 envelope_gen_num_sustain = 3,
392 envelope_gen_num_release = 4
395 private ubyte OPL3_EnvelopeCalcRate (OPL3Slot* slot, ubyte reg_rate) {
396 if (reg_rate == 0x00) return 0x00;
397 ubyte rate = cast(ubyte)((reg_rate<<2)+(slot.reg_ksr ? slot.channel.ksv : (slot.channel.ksv>>2)));
398 if (rate > 0x3c) rate = 0x3c;
399 return rate;
402 private void OPL3_EnvelopeUpdateKSL (OPL3Slot* slot) {
403 short ksl = (kslrom.ptr[slot.channel.f_num>>6]<<2)-((0x08-slot.channel.block)<<5);
404 if (ksl < 0) ksl = 0;
405 slot.eg_ksl = cast(ubyte)ksl;
408 private void OPL3_EnvelopeUpdateRate (OPL3Slot* slot) {
409 switch (slot.eg_gen) {
410 case envelope_gen_num_off:
411 case envelope_gen_num_attack:
412 slot.eg_rate = OPL3_EnvelopeCalcRate(slot, slot.reg_ar);
413 break;
414 case envelope_gen_num_decay:
415 slot.eg_rate = OPL3_EnvelopeCalcRate(slot, slot.reg_dr);
416 break;
417 case envelope_gen_num_sustain:
418 case envelope_gen_num_release:
419 slot.eg_rate = OPL3_EnvelopeCalcRate(slot, slot.reg_rr);
420 break;
421 default: break;
425 private void OPL3_EnvelopeGenOff (OPL3Slot* slot) {
426 slot.eg_rout = 0x1ff;
429 private void OPL3_EnvelopeGenAttack (OPL3Slot* slot) {
430 if (slot.eg_rout == 0x00) {
431 slot.eg_gen = envelope_gen_num_decay;
432 OPL3_EnvelopeUpdateRate(slot);
433 } else {
434 slot.eg_rout += ((~slot.eg_rout)*slot.eg_inc)>>3;
435 if (slot.eg_rout < 0x00) slot.eg_rout = 0x00;
439 private void OPL3_EnvelopeGenDecay (OPL3Slot* slot) {
440 if (slot.eg_rout >= slot.reg_sl<<4) {
441 slot.eg_gen = envelope_gen_num_sustain;
442 OPL3_EnvelopeUpdateRate(slot);
443 } else {
444 slot.eg_rout += slot.eg_inc;
448 private void OPL3_EnvelopeGenSustain (OPL3Slot* slot) {
449 if (!slot.reg_type) OPL3_EnvelopeGenRelease(slot);
452 private void OPL3_EnvelopeGenRelease (OPL3Slot* slot) {
453 if (slot.eg_rout >= 0x1ff) {
454 slot.eg_gen = envelope_gen_num_off;
455 slot.eg_rout = 0x1ff;
456 OPL3_EnvelopeUpdateRate(slot);
457 } else {
458 slot.eg_rout += slot.eg_inc;
462 private void OPL3_EnvelopeCalc (OPL3Slot* slot) {
463 ubyte rate_h, rate_l;
464 ubyte inc = 0;
465 rate_h = slot.eg_rate>>2;
466 rate_l = slot.eg_rate&3;
467 if (eg_incsh.ptr[rate_h] > 0) {
468 if ((slot.chip.timer&((1<<eg_incsh.ptr[rate_h])-1)) == 0) {
469 inc = eg_incstep.ptr[eg_incdesc.ptr[rate_h]].ptr[rate_l].ptr[((slot.chip.timer)>> eg_incsh.ptr[rate_h])&0x07];
471 } else {
472 inc = cast(ubyte)(eg_incstep.ptr[eg_incdesc.ptr[rate_h]].ptr[rate_l].ptr[slot.chip.timer&0x07]<<(-(eg_incsh.ptr[rate_h])));
474 slot.eg_inc = inc;
475 slot.eg_out = cast(short)(slot.eg_rout+(slot.reg_tl<<2)+(slot.eg_ksl>>kslshift.ptr[slot.reg_ksl])+*slot.trem);
476 envelope_gen[slot.eg_gen](slot);
479 private void OPL3_EnvelopeKeyOn (OPL3Slot* slot, ubyte type) {
480 if (!slot.key) {
481 slot.eg_gen = envelope_gen_num_attack;
482 OPL3_EnvelopeUpdateRate(slot);
483 if ((slot.eg_rate>>2) == 0x0f) {
484 slot.eg_gen = envelope_gen_num_decay;
485 OPL3_EnvelopeUpdateRate(slot);
486 slot.eg_rout = 0x00;
488 slot.pg_phase = 0x00;
490 slot.key |= type;
493 private void OPL3_EnvelopeKeyOff (OPL3Slot* slot, ubyte type) {
494 if (slot.key) {
495 slot.key &= (~type);
496 if (!slot.key) {
497 slot.eg_gen = envelope_gen_num_release;
498 OPL3_EnvelopeUpdateRate(slot);
504 // Phase Generator
507 private void OPL3_PhaseGenerate (OPL3Slot* slot) {
508 ushort f_num;
509 uint basefreq;
511 f_num = slot.channel.f_num;
512 if (slot.reg_vib) {
513 byte range;
514 ubyte vibpos;
516 range = (f_num>>7)&7;
517 vibpos = slot.chip.vibpos;
519 if (!(vibpos&3)) range = 0;
520 else if (vibpos&1) range >>= 1;
521 range >>= slot.chip.vibshift;
523 if (vibpos&4) range = -(range);
524 f_num += range;
526 basefreq = (f_num<<slot.channel.block)>>1;
527 slot.pg_phase += (basefreq*mt.ptr[slot.reg_mult])>>1;
531 // Noise Generator
534 private void OPL3_NoiseGenerate (OPL3Chip* chip) {
535 if (chip.noise&0x01) chip.noise ^= 0x800302;
536 chip.noise >>= 1;
540 // Slot
543 private void OPL3_SlotWrite20 (OPL3Slot* slot, ubyte data) {
544 slot.trem = ((data>>7)&0x01 ? &slot.chip.tremolo : cast(ubyte*)&slot.chip.zeromod);
545 slot.reg_vib = (data>>6)&0x01;
546 slot.reg_type = (data>>5)&0x01;
547 slot.reg_ksr = (data>>4)&0x01;
548 slot.reg_mult = data&0x0f;
549 OPL3_EnvelopeUpdateRate(slot);
552 private void OPL3_SlotWrite40 (OPL3Slot* slot, ubyte data) {
553 slot.reg_ksl = (data>>6)&0x03;
554 slot.reg_tl = data&0x3f;
555 OPL3_EnvelopeUpdateKSL(slot);
558 private void OPL3_SlotWrite60 (OPL3Slot* slot, ubyte data) {
559 slot.reg_ar = (data>>4)&0x0f;
560 slot.reg_dr = data&0x0f;
561 OPL3_EnvelopeUpdateRate(slot);
564 private void OPL3_SlotWrite80 (OPL3Slot* slot, ubyte data) {
565 slot.reg_sl = (data>>4)&0x0f;
566 if (slot.reg_sl == 0x0f) slot.reg_sl = 0x1f;
567 slot.reg_rr = data&0x0f;
568 OPL3_EnvelopeUpdateRate(slot);
571 private void OPL3_SlotWriteE0 (OPL3Slot* slot, ubyte data) {
572 slot.reg_wf = data&0x07;
573 if (slot.chip.newm == 0x00) slot.reg_wf &= 0x03;
576 private void OPL3_SlotGeneratePhase (OPL3Slot* slot, ushort phase) {
577 slot.out_ = envelope_sin[slot.reg_wf](phase, slot.eg_out);
580 private void OPL3_SlotGenerate (OPL3Slot* slot) {
581 OPL3_SlotGeneratePhase(slot, cast(ushort)(cast(ushort)(slot.pg_phase>>9)+*slot.mod));
584 private void OPL3_SlotGenerateZM (OPL3Slot* slot) {
585 OPL3_SlotGeneratePhase(slot, cast(ushort)(slot.pg_phase>>9));
588 private void OPL3_SlotCalcFB (OPL3Slot* slot) {
589 slot.fbmod = (slot.channel.fb != 0x00 ? cast(short)((slot.prout+slot.out_)>>(0x09-slot.channel.fb)) : 0);
590 slot.prout = slot.out_;
594 // Channel
597 private void OPL3_ChannelUpdateRhythm (OPL3Chip* chip, ubyte data) {
598 OPL3Channel* channel6;
599 OPL3Channel* channel7;
600 OPL3Channel* channel8;
601 ubyte chnum;
603 chip.rhy = data&0x3f;
604 if (chip.rhy&0x20) {
605 channel6 = &chip.channel.ptr[6];
606 channel7 = &chip.channel.ptr[7];
607 channel8 = &chip.channel.ptr[8];
608 channel6.out_.ptr[0] = &channel6.slots.ptr[1].out_;
609 channel6.out_.ptr[1] = &channel6.slots.ptr[1].out_;
610 channel6.out_.ptr[2] = &chip.zeromod;
611 channel6.out_.ptr[3] = &chip.zeromod;
612 channel7.out_.ptr[0] = &channel7.slots.ptr[0].out_;
613 channel7.out_.ptr[1] = &channel7.slots.ptr[0].out_;
614 channel7.out_.ptr[2] = &channel7.slots.ptr[1].out_;
615 channel7.out_.ptr[3] = &channel7.slots.ptr[1].out_;
616 channel8.out_.ptr[0] = &channel8.slots.ptr[0].out_;
617 channel8.out_.ptr[1] = &channel8.slots.ptr[0].out_;
618 channel8.out_.ptr[2] = &channel8.slots.ptr[1].out_;
619 channel8.out_.ptr[3] = &channel8.slots.ptr[1].out_;
620 for (chnum = 6; chnum < 9; ++chnum) chip.channel.ptr[chnum].chtype = ch_drum;
621 OPL3_ChannelSetupAlg(channel6);
622 //hh
623 if (chip.rhy&0x01) {
624 OPL3_EnvelopeKeyOn(channel7.slots.ptr[0], egk_drum);
625 } else {
626 OPL3_EnvelopeKeyOff(channel7.slots.ptr[0], egk_drum);
628 //tc
629 if (chip.rhy&0x02) {
630 OPL3_EnvelopeKeyOn(channel8.slots.ptr[1], egk_drum);
631 } else {
632 OPL3_EnvelopeKeyOff(channel8.slots.ptr[1], egk_drum);
634 //tom
635 if (chip.rhy&0x04) {
636 OPL3_EnvelopeKeyOn(channel8.slots.ptr[0], egk_drum);
637 } else {
638 OPL3_EnvelopeKeyOff(channel8.slots.ptr[0], egk_drum);
640 //sd
641 if (chip.rhy&0x08) {
642 OPL3_EnvelopeKeyOn(channel7.slots.ptr[1], egk_drum);
643 } else {
644 OPL3_EnvelopeKeyOff(channel7.slots.ptr[1], egk_drum);
646 //bd
647 if (chip.rhy&0x10) {
648 OPL3_EnvelopeKeyOn(channel6.slots.ptr[0], egk_drum);
649 OPL3_EnvelopeKeyOn(channel6.slots.ptr[1], egk_drum);
650 } else {
651 OPL3_EnvelopeKeyOff(channel6.slots.ptr[0], egk_drum);
652 OPL3_EnvelopeKeyOff(channel6.slots.ptr[1], egk_drum);
654 } else {
655 for (chnum = 6; chnum < 9; ++chnum) {
656 chip.channel.ptr[chnum].chtype = ch_2op;
657 OPL3_ChannelSetupAlg(&chip.channel.ptr[chnum]);
658 OPL3_EnvelopeKeyOff(chip.channel.ptr[chnum].slots.ptr[0], egk_drum);
659 OPL3_EnvelopeKeyOff(chip.channel.ptr[chnum].slots.ptr[1], egk_drum);
664 private void OPL3_ChannelWriteA0 (OPL3Channel* channel, ubyte data) {
665 if (channel.chip.newm && channel.chtype == ch_4op2) return;
666 channel.f_num = (channel.f_num&0x300)|data;
667 channel.ksv = cast(ubyte)((channel.block<<1)|((channel.f_num>>(0x09-channel.chip.nts))&0x01));
668 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[0]);
669 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[1]);
670 OPL3_EnvelopeUpdateRate(channel.slots.ptr[0]);
671 OPL3_EnvelopeUpdateRate(channel.slots.ptr[1]);
672 if (channel.chip.newm && channel.chtype == ch_4op) {
673 channel.pair.f_num = channel.f_num;
674 channel.pair.ksv = channel.ksv;
675 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[0]);
676 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[1]);
677 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[0]);
678 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[1]);
682 private void OPL3_ChannelWriteB0 (OPL3Channel* channel, ubyte data) {
683 if (channel.chip.newm && channel.chtype == ch_4op2) return;
684 channel.f_num = (channel.f_num&0xff)|((data&0x03)<<8);
685 channel.block = (data>>2)&0x07;
686 channel.ksv = cast(ubyte)((channel.block<<1)|((channel.f_num>>(0x09-channel.chip.nts))&0x01));
687 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[0]);
688 OPL3_EnvelopeUpdateKSL(channel.slots.ptr[1]);
689 OPL3_EnvelopeUpdateRate(channel.slots.ptr[0]);
690 OPL3_EnvelopeUpdateRate(channel.slots.ptr[1]);
691 if (channel.chip.newm && channel.chtype == ch_4op) {
692 channel.pair.f_num = channel.f_num;
693 channel.pair.block = channel.block;
694 channel.pair.ksv = channel.ksv;
695 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[0]);
696 OPL3_EnvelopeUpdateKSL(channel.pair.slots.ptr[1]);
697 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[0]);
698 OPL3_EnvelopeUpdateRate(channel.pair.slots.ptr[1]);
702 private void OPL3_ChannelSetupAlg (OPL3Channel* channel) {
703 if (channel.chtype == ch_drum) {
704 final switch (channel.alg&0x01) {
705 case 0x00:
706 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod;
707 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_;
708 break;
709 case 0x01:
710 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod;
711 channel.slots.ptr[1].mod = &channel.chip.zeromod;
712 break;
714 return;
716 if (channel.alg&0x08) return;
717 if (channel.alg&0x04) {
718 channel.pair.out_.ptr[0] = &channel.chip.zeromod;
719 channel.pair.out_.ptr[1] = &channel.chip.zeromod;
720 channel.pair.out_.ptr[2] = &channel.chip.zeromod;
721 channel.pair.out_.ptr[3] = &channel.chip.zeromod;
722 final switch (channel.alg&0x03) {
723 case 0x00:
724 channel.pair.slots.ptr[0].mod = &channel.pair.slots.ptr[0].fbmod;
725 channel.pair.slots.ptr[1].mod = &channel.pair.slots.ptr[0].out_;
726 channel.slots.ptr[0].mod = &channel.pair.slots.ptr[1].out_;
727 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_;
728 channel.out_.ptr[0] = &channel.slots.ptr[1].out_;
729 channel.out_.ptr[1] = &channel.chip.zeromod;
730 channel.out_.ptr[2] = &channel.chip.zeromod;
731 channel.out_.ptr[3] = &channel.chip.zeromod;
732 break;
733 case 0x01:
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.chip.zeromod;
737 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_;
738 channel.out_.ptr[0] = &channel.pair.slots.ptr[1].out_;
739 channel.out_.ptr[1] = &channel.slots.ptr[1].out_;
740 channel.out_.ptr[2] = &channel.chip.zeromod;
741 channel.out_.ptr[3] = &channel.chip.zeromod;
742 break;
743 case 0x02:
744 channel.pair.slots.ptr[0].mod = &channel.pair.slots.ptr[0].fbmod;
745 channel.pair.slots.ptr[1].mod = &channel.chip.zeromod;
746 channel.slots.ptr[0].mod = &channel.pair.slots.ptr[1].out_;
747 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_;
748 channel.out_.ptr[0] = &channel.pair.slots.ptr[0].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 0x03:
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.chip.zeromod;
758 channel.out_.ptr[0] = &channel.pair.slots.ptr[0].out_;
759 channel.out_.ptr[1] = &channel.slots.ptr[0].out_;
760 channel.out_.ptr[2] = &channel.slots.ptr[1].out_;
761 channel.out_.ptr[3] = &channel.chip.zeromod;
762 break;
764 } else {
765 final switch (channel.alg&0x01) {
766 case 0x00:
767 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod;
768 channel.slots.ptr[1].mod = &channel.slots.ptr[0].out_;
769 channel.out_.ptr[0] = &channel.slots.ptr[1].out_;
770 channel.out_.ptr[1] = &channel.chip.zeromod;
771 channel.out_.ptr[2] = &channel.chip.zeromod;
772 channel.out_.ptr[3] = &channel.chip.zeromod;
773 break;
774 case 0x01:
775 channel.slots.ptr[0].mod = &channel.slots.ptr[0].fbmod;
776 channel.slots.ptr[1].mod = &channel.chip.zeromod;
777 channel.out_.ptr[0] = &channel.slots.ptr[0].out_;
778 channel.out_.ptr[1] = &channel.slots.ptr[1].out_;
779 channel.out_.ptr[2] = &channel.chip.zeromod;
780 channel.out_.ptr[3] = &channel.chip.zeromod;
781 break;
786 private void OPL3_ChannelWriteC0 (OPL3Channel* channel, ubyte data) {
787 channel.fb = (data&0x0e)>>1;
788 channel.con = data&0x01;
789 channel.alg = channel.con;
790 if (channel.chip.newm) {
791 if (channel.chtype == ch_4op) {
792 channel.pair.alg = cast(ubyte)(0x04|(channel.con<<1)|(channel.pair.con));
793 channel.alg = 0x08;
794 OPL3_ChannelSetupAlg(channel.pair);
795 } else if (channel.chtype == ch_4op2) {
796 channel.alg = cast(ubyte)(0x04|(channel.pair.con<<1)|(channel.con));
797 channel.pair.alg = 0x08;
798 OPL3_ChannelSetupAlg(channel);
799 } else {
800 OPL3_ChannelSetupAlg(channel);
802 } else {
803 OPL3_ChannelSetupAlg(channel);
805 if (channel.chip.newm) {
806 channel.cha = ((data>>4)&0x01 ? ushort.max : 0);
807 channel.chb = ((data>>5)&0x01 ? ushort.max : 0);
808 } else {
809 channel.cha = channel.chb = ushort.max;
813 private void OPL3_ChannelKeyOn (OPL3Channel* channel) {
814 if (channel.chip.newm) {
815 if (channel.chtype == ch_4op) {
816 OPL3_EnvelopeKeyOn(channel.slots.ptr[0], egk_norm);
817 OPL3_EnvelopeKeyOn(channel.slots.ptr[1], egk_norm);
818 OPL3_EnvelopeKeyOn(channel.pair.slots.ptr[0], egk_norm);
819 OPL3_EnvelopeKeyOn(channel.pair.slots.ptr[1], egk_norm);
820 } else if (channel.chtype == ch_2op || channel.chtype == ch_drum) {
821 OPL3_EnvelopeKeyOn(channel.slots.ptr[0], egk_norm);
822 OPL3_EnvelopeKeyOn(channel.slots.ptr[1], egk_norm);
824 } else {
825 OPL3_EnvelopeKeyOn(channel.slots.ptr[0], egk_norm);
826 OPL3_EnvelopeKeyOn(channel.slots.ptr[1], egk_norm);
830 private void OPL3_ChannelKeyOff (OPL3Channel* channel) {
831 if (channel.chip.newm) {
832 if (channel.chtype == ch_4op) {
833 OPL3_EnvelopeKeyOff(channel.slots.ptr[0], egk_norm);
834 OPL3_EnvelopeKeyOff(channel.slots.ptr[1], egk_norm);
835 OPL3_EnvelopeKeyOff(channel.pair.slots.ptr[0], egk_norm);
836 OPL3_EnvelopeKeyOff(channel.pair.slots.ptr[1], egk_norm);
837 } else if (channel.chtype == ch_2op || channel.chtype == ch_drum) {
838 OPL3_EnvelopeKeyOff(channel.slots.ptr[0], egk_norm);
839 OPL3_EnvelopeKeyOff(channel.slots.ptr[1], egk_norm);
841 } else {
842 OPL3_EnvelopeKeyOff(channel.slots.ptr[0], egk_norm);
843 OPL3_EnvelopeKeyOff(channel.slots.ptr[1], egk_norm);
847 private void OPL3_ChannelSet4Op (OPL3Chip* chip, ubyte data) {
848 ubyte bit;
849 ubyte chnum;
850 for (bit = 0; bit < 6; ++bit) {
851 chnum = bit;
852 if (bit >= 3) chnum += 9-3;
853 if ((data>>bit)&0x01) {
854 chip.channel.ptr[chnum].chtype = ch_4op;
855 chip.channel.ptr[chnum+3].chtype = ch_4op2;
856 } else {
857 chip.channel.ptr[chnum].chtype = ch_2op;
858 chip.channel.ptr[chnum+3].chtype = ch_2op;
863 private short OPL3_ClipSample (int sample) pure {
864 pragma(inline, true);
865 if (sample > 32767) sample = 32767;
866 else if (sample < -32768) sample = -32768;
867 return cast(short)sample;
870 private void OPL3_GenerateRhythm1 (OPL3Chip* chip) {
871 OPL3Channel* channel6;
872 OPL3Channel* channel7;
873 OPL3Channel* channel8;
874 ushort phase14;
875 ushort phase17;
876 ushort phase;
877 ushort phasebit;
879 channel6 = &chip.channel.ptr[6];
880 channel7 = &chip.channel.ptr[7];
881 channel8 = &chip.channel.ptr[8];
882 OPL3_SlotGenerate(channel6.slots.ptr[0]);
883 phase14 = (channel7.slots.ptr[0].pg_phase>>9)&0x3ff;
884 phase17 = (channel8.slots.ptr[1].pg_phase>>9)&0x3ff;
885 phase = 0x00;
886 //hh tc phase bit
887 phasebit = ((phase14&0x08)|(((phase14>>5)^phase14)&0x04)|(((phase17>>2)^phase17)&0x08)) ? 0x01 : 0x00;
888 //hh
889 phase = cast(ushort)((phasebit<<9)|(0x34<<((phasebit^(chip.noise&0x01))<<1)));
890 OPL3_SlotGeneratePhase(channel7.slots.ptr[0], phase);
891 //tt
892 OPL3_SlotGenerateZM(channel8.slots.ptr[0]);
895 private void OPL3_GenerateRhythm2 (OPL3Chip* chip) {
896 OPL3Channel* channel6;
897 OPL3Channel* channel7;
898 OPL3Channel* channel8;
899 ushort phase14;
900 ushort phase17;
901 ushort phase;
902 ushort phasebit;
904 channel6 = &chip.channel.ptr[6];
905 channel7 = &chip.channel.ptr[7];
906 channel8 = &chip.channel.ptr[8];
907 OPL3_SlotGenerate(channel6.slots.ptr[1]);
908 phase14 = (channel7.slots.ptr[0].pg_phase>>9)&0x3ff;
909 phase17 = (channel8.slots.ptr[1].pg_phase>>9)&0x3ff;
910 phase = 0x00;
911 //hh tc phase bit
912 phasebit = ((phase14&0x08)|(((phase14>>5)^phase14)&0x04)|(((phase17>>2)^phase17)&0x08)) ? 0x01 : 0x00;
913 //sd
914 phase = (0x100<<((phase14>>8)&0x01))^((chip.noise&0x01)<<8);
915 OPL3_SlotGeneratePhase(channel7.slots.ptr[1], phase);
916 //tc
917 phase = cast(ushort)(0x100|(phasebit<<9));
918 OPL3_SlotGeneratePhase(channel8.slots.ptr[1], phase);
922 // ////////////////////////////////////////////////////////////////////////// //
923 /// OPL3_Generate
924 public void generate (ref OPL3Chip chip, short* buf) {
925 ubyte ii;
926 ubyte jj;
927 short accm;
929 buf[1] = OPL3_ClipSample(chip.mixbuff.ptr[1]);
931 for (ii = 0; ii < 12; ++ii) {
932 OPL3_SlotCalcFB(&chip.slot.ptr[ii]);
933 OPL3_PhaseGenerate(&chip.slot.ptr[ii]);
934 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]);
935 OPL3_SlotGenerate(&chip.slot.ptr[ii]);
938 for (ii = 12; ii < 15; ++ii) {
939 OPL3_SlotCalcFB(&chip.slot.ptr[ii]);
940 OPL3_PhaseGenerate(&chip.slot.ptr[ii]);
941 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]);
944 if (chip.rhy&0x20) {
945 OPL3_GenerateRhythm1(&chip);
946 } else {
947 OPL3_SlotGenerate(&chip.slot.ptr[12]);
948 OPL3_SlotGenerate(&chip.slot.ptr[13]);
949 OPL3_SlotGenerate(&chip.slot.ptr[14]);
952 chip.mixbuff.ptr[0] = 0;
953 for (ii = 0; ii < 18; ++ii) {
954 accm = 0;
955 for (jj = 0; jj < 4; ++jj) accm += *chip.channel.ptr[ii].out_.ptr[jj];
956 chip.mixbuff.ptr[0] += cast(short)(accm&chip.channel.ptr[ii].cha);
959 for (ii = 15; ii < 18; ++ii) {
960 OPL3_SlotCalcFB(&chip.slot.ptr[ii]);
961 OPL3_PhaseGenerate(&chip.slot.ptr[ii]);
962 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]);
965 if (chip.rhy&0x20) {
966 OPL3_GenerateRhythm2(&chip);
967 } else {
968 OPL3_SlotGenerate(&chip.slot.ptr[15]);
969 OPL3_SlotGenerate(&chip.slot.ptr[16]);
970 OPL3_SlotGenerate(&chip.slot.ptr[17]);
973 buf[0] = OPL3_ClipSample(chip.mixbuff.ptr[0]);
975 for (ii = 18; ii < 33; ++ii) {
976 OPL3_SlotCalcFB(&chip.slot.ptr[ii]);
977 OPL3_PhaseGenerate(&chip.slot.ptr[ii]);
978 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]);
979 OPL3_SlotGenerate(&chip.slot.ptr[ii]);
982 chip.mixbuff.ptr[1] = 0;
983 for (ii = 0; ii < 18; ++ii) {
984 accm = 0;
985 for (jj = 0; jj < 4; jj++) accm += *chip.channel.ptr[ii].out_.ptr[jj];
986 chip.mixbuff.ptr[1] += cast(short)(accm&chip.channel.ptr[ii].chb);
989 for (ii = 33; ii < 36; ++ii) {
990 OPL3_SlotCalcFB(&chip.slot.ptr[ii]);
991 OPL3_PhaseGenerate(&chip.slot.ptr[ii]);
992 OPL3_EnvelopeCalc(&chip.slot.ptr[ii]);
993 OPL3_SlotGenerate(&chip.slot.ptr[ii]);
996 OPL3_NoiseGenerate(&chip);
998 if ((chip.timer&0x3f) == 0x3f) chip.tremolopos = (chip.tremolopos+1)%210;
999 chip.tremolo = (chip.tremolopos < 105 ? chip.tremolopos>>chip.tremoloshift : cast(ubyte)((210-chip.tremolopos)>>chip.tremoloshift));
1000 if ((chip.timer&0x3ff) == 0x3ff) chip.vibpos = (chip.vibpos+1)&7;
1002 ++chip.timer;
1004 while (chip.writebuf.ptr[chip.writebuf_cur].time <= chip.writebuf_samplecnt) {
1005 if (!(chip.writebuf.ptr[chip.writebuf_cur].reg&0x200)) break;
1006 chip.writebuf.ptr[chip.writebuf_cur].reg &= 0x1ff;
1007 chip.writeReg(chip.writebuf.ptr[chip.writebuf_cur].reg, chip.writebuf.ptr[chip.writebuf_cur].data);
1008 chip.writebuf_cur = (chip.writebuf_cur+1)%OPL_WRITEBUF_SIZE;
1010 ++chip.writebuf_samplecnt;
1014 /// OPL3_GenerateResampled
1015 public void generateResampled (ref OPL3Chip chip, short* buf) {
1016 while (chip.samplecnt >= chip.rateratio) {
1017 chip.oldsamples.ptr[0] = chip.samples.ptr[0];
1018 chip.oldsamples.ptr[1] = chip.samples.ptr[1];
1019 chip.generate(chip.samples.ptr);
1020 chip.samplecnt -= chip.rateratio;
1022 buf[0] = cast(short)((chip.oldsamples.ptr[0]*(chip.rateratio-chip.samplecnt)+chip.samples.ptr[0]*chip.samplecnt)/chip.rateratio);
1023 buf[1] = cast(short)((chip.oldsamples.ptr[1]*(chip.rateratio-chip.samplecnt)+chip.samples.ptr[1]*chip.samplecnt)/chip.rateratio);
1024 chip.samplecnt += 1<<RSM_FRAC;
1028 /// OPL3_Reset
1029 public void reset (ref OPL3Chip chip, uint samplerate) {
1030 ubyte slotnum;
1031 ubyte channum;
1033 //ubyte* cc = cast(ubyte*)chip;
1034 //cc[0..OPL3Chip.sizeof] = 0;
1035 chip = chip.init;
1037 for (slotnum = 0; slotnum < 36; ++slotnum) {
1038 chip.slot.ptr[slotnum].chip = &chip;
1039 chip.slot.ptr[slotnum].mod = &chip.zeromod;
1040 chip.slot.ptr[slotnum].eg_rout = 0x1ff;
1041 chip.slot.ptr[slotnum].eg_out = 0x1ff;
1042 chip.slot.ptr[slotnum].eg_gen = envelope_gen_num_off;
1043 chip.slot.ptr[slotnum].trem = cast(ubyte*)&chip.zeromod;
1045 for (channum = 0; channum < 18; ++channum) {
1046 chip.channel.ptr[channum].slots.ptr[0] = &chip.slot.ptr[ch_slot.ptr[channum]];
1047 chip.channel.ptr[channum].slots.ptr[1] = &chip.slot.ptr[ch_slot.ptr[channum]+3];
1048 chip.slot.ptr[ch_slot.ptr[channum]].channel = &chip.channel.ptr[channum];
1049 chip.slot.ptr[ch_slot.ptr[channum]+3].channel = &chip.channel.ptr[channum];
1050 if ((channum%9) < 3) chip.channel.ptr[channum].pair = &chip.channel.ptr[channum+3];
1051 else if ((channum%9) < 6) chip.channel.ptr[channum].pair = &chip.channel.ptr[channum-3];
1052 chip.channel.ptr[channum].chip = &chip;
1053 chip.channel.ptr[channum].out_.ptr[0] = &chip.zeromod;
1054 chip.channel.ptr[channum].out_.ptr[1] = &chip.zeromod;
1055 chip.channel.ptr[channum].out_.ptr[2] = &chip.zeromod;
1056 chip.channel.ptr[channum].out_.ptr[3] = &chip.zeromod;
1057 chip.channel.ptr[channum].chtype = ch_2op;
1058 chip.channel.ptr[channum].cha = ushort.max;
1059 chip.channel.ptr[channum].chb = ushort.max;
1060 OPL3_ChannelSetupAlg(&chip.channel.ptr[channum]);
1062 chip.noise = 0x306600;
1063 chip.rateratio = (samplerate<<RSM_FRAC)/49716;
1064 chip.tremoloshift = 4;
1065 chip.vibshift = 1;
1069 /// OPL3_WriteReg
1070 public void writeReg (ref OPL3Chip chip, ushort reg, ubyte v) {
1071 ubyte high = (reg>>8)&0x01;
1072 ubyte regm = reg&0xff;
1073 switch (regm&0xf0) {
1074 case 0x00:
1075 if (high) {
1076 switch (regm&0x0f) {
1077 case 0x04:
1078 OPL3_ChannelSet4Op(&chip, v);
1079 break;
1080 case 0x05:
1081 chip.newm = v&0x01;
1082 break;
1083 default: break;
1085 } else {
1086 switch (regm&0x0f) {
1087 case 0x08:
1088 chip.nts = (v>>6)&0x01;
1089 break;
1090 default: break;
1093 break;
1094 case 0x20:
1095 case 0x30:
1096 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite20(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v);
1097 break;
1098 case 0x40:
1099 case 0x50:
1100 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite40(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v);
1101 break;
1102 case 0x60:
1103 case 0x70:
1104 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite60(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v);
1105 break;
1106 case 0x80:
1107 case 0x90:
1108 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWrite80(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v);
1109 break;
1110 case 0xe0:
1111 case 0xf0:
1112 if (ad_slot.ptr[regm&0x1f] >= 0) OPL3_SlotWriteE0(&chip.slot.ptr[18*high+ad_slot.ptr[regm&0x1f]], v);
1113 break;
1114 case 0xa0:
1115 if ((regm&0x0f) < 9) OPL3_ChannelWriteA0(&chip.channel.ptr[9*high+(regm&0x0f)], v);
1116 break;
1117 case 0xb0:
1118 if (regm == 0xbd && !high) {
1119 chip.tremoloshift = (((v>>7)^1)<<1)+2;
1120 chip.vibshift = ((v>>6)&0x01)^1;
1121 OPL3_ChannelUpdateRhythm(&chip, v);
1122 } else if ((regm&0x0f) < 9) {
1123 OPL3_ChannelWriteB0(&chip.channel.ptr[9*high+(regm&0x0f)], v);
1124 if (v&0x20) OPL3_ChannelKeyOn(&chip.channel.ptr[9*high+(regm&0x0f)]); else OPL3_ChannelKeyOff(&chip.channel.ptr[9*high+(regm&0x0f)]);
1126 break;
1127 case 0xc0:
1128 if ((regm&0x0f) < 9) OPL3_ChannelWriteC0(&chip.channel.ptr[9*high+(regm&0x0f)], v);
1129 break;
1130 default: break;
1135 /// OPL3_WriteRegBuffered
1136 public void writeRegBuffered (ref OPL3Chip chip, ushort reg, ubyte v) {
1137 ulong time1, time2;
1139 if (chip.writebuf.ptr[chip.writebuf_last].reg&0x200) {
1140 chip.writeReg(chip.writebuf.ptr[chip.writebuf_last].reg&0x1ff, chip.writebuf.ptr[chip.writebuf_last].data);
1141 chip.writebuf_cur = (chip.writebuf_last+1)%OPL_WRITEBUF_SIZE;
1142 chip.writebuf_samplecnt = chip.writebuf.ptr[chip.writebuf_last].time;
1145 chip.writebuf.ptr[chip.writebuf_last].reg = reg|0x200;
1146 chip.writebuf.ptr[chip.writebuf_last].data = v;
1147 time1 = chip.writebuf_lasttime+OPL_WRITEBUF_DELAY;
1148 time2 = chip.writebuf_samplecnt;
1150 if (time1 < time2) time1 = time2;
1152 chip.writebuf.ptr[chip.writebuf_last].time = time1;
1153 chip.writebuf_lasttime = time1;
1154 chip.writebuf_last = (chip.writebuf_last+1)%OPL_WRITEBUF_SIZE;
1158 /// OPL3_GenerateStream; outputs STEREO stream
1159 public void generateStream (ref OPL3Chip chip, short[] smpbuf) {
1160 auto sndptr = smpbuf.ptr;
1161 foreach (immutable _; 0..smpbuf.length/2) {
1162 chip.generateResampled(sndptr);
1163 sndptr += 2;