1 /*
2 * libOPNMIDI is a free Software MIDI synthesizer library with OPN2 (YM2612) emulation
3 *
4 * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
5 * OPNMIDI Library and YM2612 support: Copyright (c) 2017-2020 Vitaly Novichkov <admin@wohlnet.ru>
6 *
7 * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
8 * http://iki.fi/bisqwit/source/adlmidi.html
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "opnmidi_opn2.hpp"
25 #include "opnmidi_private.hpp"
26
27 #if defined(OPNMIDI_DISABLE_NUKED_EMULATOR) && defined(OPNMIDI_DISABLE_MAME_EMULATOR) && \
28 defined(OPNMIDI_DISABLE_GENS_EMULATOR) && defined(OPNMIDI_DISABLE_GX_EMULATOR) && \
29 defined(OPNMIDI_DISABLE_NP2_EMULATOR) && defined(OPNMIDI_DISABLE_MAME_2608_EMULATOR) && \
30 defined(OPNMIDI_DISABLE_PMDWIN_EMULATOR)
31 #error "No emulators enabled. You must enable at least one emulator to use this library!"
32 #endif
33
34 // Nuked OPN2 emulator, Most accurate, but requires the powerful CPU
35 #ifndef OPNMIDI_DISABLE_NUKED_EMULATOR
36 #include "chips/nuked_opn2.h"
37 #endif
38
39 // MAME YM2612 emulator, Well-accurate and fast
40 #ifndef OPNMIDI_DISABLE_MAME_EMULATOR
41 #include "chips/mame_opn2.h"
42 #endif
43
44 // GENS 2.10 emulator, very outdated and inaccurate, but gives the best performance
45 #ifndef OPNMIDI_DISABLE_GENS_EMULATOR
46 #include "chips/gens_opn2.h"
47 #endif
48
49 // Genesis Plus GX emulator, Variant of MAME with enhancements
50 #ifndef OPNMIDI_DISABLE_GX_EMULATOR
51 #include "chips/gx_opn2.h"
52 #endif
53
54 // Neko Project II OPNA emulator
55 #ifndef OPNMIDI_DISABLE_NP2_EMULATOR
56 #include "chips/np2_opna.h"
57 #endif
58
59 // MAME YM2608 emulator
60 #ifndef OPNMIDI_DISABLE_MAME_2608_EMULATOR
61 #include "chips/mame_opna.h"
62 #endif
63
64 // PMDWin OPNA emulator
65 #ifndef OPNMIDI_DISABLE_PMDWIN_EMULATOR
66 #include "chips/pmdwin_opna.h"
67 #endif
68
69 // VGM File dumper
70 #ifdef OPNMIDI_MIDI2VGM
71 #include "chips/vgm_file_dumper.h"
72 #endif
73
74 static const unsigned opn2_emulatorSupport = 0
75 #ifndef OPNMIDI_DISABLE_NUKED_EMULATOR
76 | (1u << OPNMIDI_EMU_NUKED)
77 #endif
78 #ifndef OPNMIDI_DISABLE_MAME_EMULATOR
79 | (1u << OPNMIDI_EMU_MAME)
80 #endif
81 #ifndef OPNMIDI_DISABLE_GENS_EMULATOR
82 | (1u << OPNMIDI_EMU_GENS)
83 #endif
84 #ifndef OPNMIDI_DISABLE_GX_EMULATOR
85 | (1u << OPNMIDI_EMU_GX)
86 #endif
87 #ifndef OPNMIDI_DISABLE_NP2_EMULATOR
88 | (1u << OPNMIDI_EMU_NP2)
89 #endif
90 #ifndef OPNMIDI_DISABLE_MAME_2608_EMULATOR
91 | (1u << OPNMIDI_EMU_MAME_2608)
92 #endif
93 #ifndef OPNMIDI_DISABLE_PMDWIN_EMULATOR
94 | (1u << OPNMIDI_EMU_PMDWIN)
95 #endif
96 #ifdef OPNMIDI_MIDI2VGM
97 | (1u << OPNMIDI_VGM_DUMPER)
98 #endif
99 ;
100
101 //! Check emulator availability
opn2_isEmulatorAvailable(int emulator)102 bool opn2_isEmulatorAvailable(int emulator)
103 {
104 return (opn2_emulatorSupport & (1u << (unsigned)emulator)) != 0;
105 }
106
107 //! Find highest emulator
opn2_getHighestEmulator()108 int opn2_getHighestEmulator()
109 {
110 int emu = -1;
111 for(unsigned m = opn2_emulatorSupport; m > 0; m >>= 1)
112 ++emu;
113 return emu;
114 }
115
116 //! Find lowest emulator
opn2_getLowestEmulator()117 int opn2_getLowestEmulator()
118 {
119 int emu = -1;
120 unsigned m = opn2_emulatorSupport;
121 if(m > 0)
122 {
123 for(emu = 0; (m & 1) == 0; m >>= 1)
124 ++emu;
125 }
126 return emu;
127 }
128
129
130
131 /***************************************************************
132 * Volume model tables *
133 ***************************************************************/
134
135 // Mapping from MIDI volume level to OPL level value.
136
137 static const uint_fast32_t s_dmx_volume_model[128] =
138 {
139 0, 1, 3, 5, 6, 8, 10, 11,
140 13, 14, 16, 17, 19, 20, 22, 23,
141 25, 26, 27, 29, 30, 32, 33, 34,
142 36, 37, 39, 41, 43, 45, 47, 49,
143 50, 52, 54, 55, 57, 59, 60, 61,
144 63, 64, 66, 67, 68, 69, 71, 72,
145 73, 74, 75, 76, 77, 79, 80, 81,
146 82, 83, 84, 84, 85, 86, 87, 88,
147 89, 90, 91, 92, 92, 93, 94, 95,
148 96, 96, 97, 98, 99, 99, 100, 101,
149 101, 102, 103, 103, 104, 105, 105, 106,
150 107, 107, 108, 109, 109, 110, 110, 111,
151 112, 112, 113, 113, 114, 114, 115, 115,
152 116, 117, 117, 118, 118, 119, 119, 120,
153 120, 121, 121, 122, 122, 123, 123, 123,
154 124, 124, 125, 125, 126, 126, 127, 127,
155 };
156
157 static const uint_fast32_t W9X_volume_mapping_table[32] =
158 {
159 63, 63, 40, 36, 32, 28, 23, 21,
160 19, 17, 15, 14, 13, 12, 11, 10,
161 9, 8, 7, 6, 5, 5, 4, 4,
162 3, 3, 2, 2, 1, 1, 0, 0
163 };
164
165 static const uint32_t g_noteChannelsMap[6] = { 0, 1, 2, 4, 5, 6 };
166
getOpnChannel(size_t in_channel,size_t & out_chip,uint8_t & out_port,uint32_t & out_ch)167 static inline void getOpnChannel(size_t in_channel,
168 size_t &out_chip,
169 uint8_t &out_port,
170 uint32_t &out_ch)
171 {
172 out_chip = in_channel / 6;
173 size_t ch4 = in_channel % 6;
174 out_port = ((ch4 < 3) ? 0 : 1);
175 out_ch = static_cast<uint32_t>(ch4 % 3);
176 }
177
178
179 /***************************************************************
180 * Standard frequency formula *
181 * *************************************************************/
182
s_commonFreq(double tone)183 static inline double s_commonFreq(double tone)
184 {
185 return std::exp(0.057762265 * tone);
186 }
187
188
189
190 enum
191 {
192 MasterVolumeDefault = 127
193 };
194
195 enum
196 {
197 OPN_PANNING_LEFT = 0x80,
198 OPN_PANNING_RIGHT = 0x40,
199 OPN_PANNING_BOTH = 0xC0
200 };
201
makeEmptyInstrument()202 static OpnInstMeta makeEmptyInstrument()
203 {
204 OpnInstMeta ins;
205 memset(&ins, 0, sizeof(OpnInstMeta));
206 ins.flags = OpnInstMeta::Flag_NoSound;
207 return ins;
208 }
209
210 const OpnInstMeta OPN2::m_emptyInstrument = makeEmptyInstrument();
211
OPN2()212 OPN2::OPN2() :
213 m_regLFOSetup(0),
214 m_numChips(1),
215 m_scaleModulators(false),
216 m_runAtPcmRate(false),
217 m_softPanning(false),
218 m_masterVolume(MasterVolumeDefault),
219 m_musicMode(MODE_MIDI),
220 m_volumeScale(VOLUME_Generic),
221 m_lfoEnable(false),
222 m_lfoFrequency(0),
223 m_chipFamily(OPNChip_OPN2)
224 {
225 m_insBankSetup.volumeModel = OPN2::VOLUME_Generic;
226 m_insBankSetup.lfoEnable = false;
227 m_insBankSetup.lfoFrequency = 0;
228 m_insBankSetup.chipType = OPNChip_OPN2;
229
230 // Initialize blank instruments banks
231 m_insBanks.clear();
232 }
233
~OPN2()234 OPN2::~OPN2()
235 {
236 clearChips();
237 }
238
setupLocked()239 bool OPN2::setupLocked()
240 {
241 return (m_musicMode == MODE_CMF ||
242 m_musicMode == MODE_IMF ||
243 m_musicMode == MODE_RSXX);
244 }
245
writeReg(size_t chip,uint8_t port,uint8_t index,uint8_t value)246 void OPN2::writeReg(size_t chip, uint8_t port, uint8_t index, uint8_t value)
247 {
248 m_chips[chip]->writeReg(port, index, value);
249 }
250
writeRegI(size_t chip,uint8_t port,uint32_t index,uint32_t value)251 void OPN2::writeRegI(size_t chip, uint8_t port, uint32_t index, uint32_t value)
252 {
253 m_chips[chip]->writeReg(port, static_cast<uint8_t>(index), static_cast<uint8_t>(value));
254 }
255
writePan(size_t chip,uint32_t index,uint32_t value)256 void OPN2::writePan(size_t chip, uint32_t index, uint32_t value)
257 {
258 m_chips[chip]->writePan(static_cast<uint16_t>(index), static_cast<uint8_t>(value));
259 }
260
noteOff(size_t c)261 void OPN2::noteOff(size_t c)
262 {
263 size_t chip;
264 uint8_t port;
265 uint32_t cc;
266 size_t ch4 = c % 6;
267 getOpnChannel(c, chip, port, cc);
268 writeRegI(chip, 0, 0x28, g_noteChannelsMap[ch4]);
269 }
270
noteOn(size_t c,double tone)271 void OPN2::noteOn(size_t c, double tone)
272 {
273 // Hertz range: 0..131071
274 double hertz = s_commonFreq(tone);
275
276 if(hertz < 0) // Avoid infinite loop
277 return;
278
279 double coef;
280 switch(m_chipFamily)
281 {
282 case OPNChip_OPN2: default:
283 coef = 321.88557; break;
284 case OPNChip_OPNA:
285 coef = 309.12412; break;
286 }
287 hertz *= coef;
288
289 size_t chip;
290 uint8_t port;
291 uint32_t cc;
292 size_t ch4 = c % 6;
293 getOpnChannel(c, chip, port, cc);
294
295 uint32_t octave = 0, ftone = 0, mul_offset = 0;
296 const OpnTimbre &adli = m_insCache[c];
297
298 //Basic range until max of octaves reaching
299 while((hertz >= 1023.75) && (octave < 0x3800))
300 {
301 hertz /= 2.0; // Calculate octave
302 octave += 0x800;
303 }
304 //Extended range, rely on frequency multiplication increment
305 while(hertz >= 2036.75)
306 {
307 hertz /= 2.0; // Calculate octave
308 mul_offset++;
309 }
310 ftone = octave + static_cast<uint32_t>(hertz + 0.5);
311
312 for(size_t op = 0; op < 4; op++)
313 {
314 uint32_t reg = adli.OPS[op].data[0];
315 uint16_t address = static_cast<uint16_t>(0x30 + (op * 4) + cc);
316 if(mul_offset > 0) // Increase frequency multiplication value
317 {
318 uint32_t dt = reg & 0xF0;
319 uint32_t mul = reg & 0x0F;
320 if((mul + mul_offset) > 0x0F)
321 {
322 mul_offset = 0;
323 mul = 0x0F;
324 }
325 writeRegI(chip, port, address, uint8_t(dt | (mul + mul_offset)));
326 }
327 else
328 {
329 writeRegI(chip, port, address, uint8_t(reg));
330 }
331 }
332
333 writeRegI(chip, port, 0xA4 + cc, (ftone>>8) & 0xFF);//Set frequency and octave
334 writeRegI(chip, port, 0xA0 + cc, ftone & 0xFF);
335 writeRegI(chip, 0, 0x28, 0xF0 + g_noteChannelsMap[ch4]);
336 }
337
touchNote(size_t c,uint_fast32_t velocity,uint_fast32_t channelVolume,uint_fast32_t channelExpression,uint8_t brightness)338 void OPN2::touchNote(size_t c,
339 uint_fast32_t velocity,
340 uint_fast32_t channelVolume,
341 uint_fast32_t channelExpression,
342 uint8_t brightness)
343 {
344 size_t chip;
345 uint8_t port;
346 uint32_t cc;
347 getOpnChannel(c, chip, port, cc);
348
349 const OpnTimbre &adli = m_insCache[c];
350
351 uint_fast32_t volume = 0;
352
353 uint8_t op_vol[4] =
354 {
355 adli.OPS[OPERATOR1].data[1],
356 adli.OPS[OPERATOR2].data[1],
357 adli.OPS[OPERATOR3].data[1],
358 adli.OPS[OPERATOR4].data[1],
359 };
360
361 bool alg_do[8][4] =
362 {
363 /*
364 * Yeah, Operator 2 and 3 are seems swapped
365 * which we can see in the algorithm 4
366 */
367 //OP1 OP3 OP2 OP4
368 //30 34 38 3C
369 {false,false,false,true},//Algorithm #0: W = 1 * 2 * 3 * 4
370 {false,false,false,true},//Algorithm #1: W = (1 + 2) * 3 * 4
371 {false,false,false,true},//Algorithm #2: W = (1 + (2 * 3)) * 4
372 {false,false,false,true},//Algorithm #3: W = ((1 * 2) + 3) * 4
373 {false,false,true, true},//Algorithm #4: W = (1 * 2) + (3 * 4)
374 {false,true ,true ,true},//Algorithm #5: W = (1 * (2 + 3 + 4)
375 {false,true ,true ,true},//Algorithm #6: W = (1 * 2) + 3 + 4
376 {true ,true ,true ,true},//Algorithm #7: W = 1 + 2 + 3 + 4
377 };
378
379 switch(m_volumeScale)
380 {
381 default:
382 case Synth::VOLUME_Generic:
383 {
384 volume = velocity * m_masterVolume *
385 channelVolume * channelExpression;
386
387 /* If the channel has arpeggio, the effective volume of
388 * *this* instrument is actually lower due to timesharing.
389 * To compensate, add extra volume that corresponds to the
390 * time this note is *not* heard.
391 * Empirical tests however show that a full equal-proportion
392 * increment sounds wrong. Therefore, using the square root.
393 */
394 //volume = (int)(volume * std::sqrt( (double) ch[c].users.size() ));
395 const double c1 = 11.541560327111707;
396 const double c2 = 1.601379199767093e+02;
397 const uint_fast32_t minVolume = 1108075; // 8725 * 127
398
399 // The formula below: SOLVE(V=127^4 * 2^( (A-63.49999) / 8), A)
400 if(volume > minVolume)
401 {
402 double lv = std::log(static_cast<double>(volume));
403 volume = static_cast<uint_fast32_t>(lv * c1 - c2) * 2;
404 }
405 else
406 volume = 0;
407 }
408 break;
409
410 case Synth::VOLUME_NATIVE:
411 {
412 volume = velocity * channelVolume * channelExpression;
413 //volume = volume * m_masterVolume / (127 * 127 * 127) / 2;
414 volume = (volume * m_masterVolume) / 4096766;
415 }
416 break;
417
418 case Synth::VOLUME_DMX:
419 {
420 volume = (channelVolume * channelExpression * m_masterVolume) / 16129;
421 volume = (s_dmx_volume_model[volume] + 1) << 1;
422 volume = (s_dmx_volume_model[(velocity < 128) ? velocity : 127] * volume) >> 9;
423
424 if(volume > 0)
425 volume += 64;//OPN has 0~127 range. As 0...63 is almost full silence, but at 64 to 127 is very closed to OPL3, just add 64.
426 }
427 break;
428
429 case Synth::VOLUME_APOGEE:
430 {
431 volume = (channelVolume * channelExpression * m_masterVolume / 16129);
432 volume = ((64 * (velocity + 0x80)) * volume) >> 15;
433 //volume = ((63 * (vol + 0x80)) * Ch[MidCh].volume) >> 15;
434 if(volume > 0)
435 volume += 64;//OPN has 0~127 range. As 0...63 is almost full silence, but at 64 to 127 is very closed to OPL3, just add 64.
436 }
437 break;
438
439 case Synth::VOLUME_9X:
440 {
441 //volume = 63 - W9X_volume_mapping_table[(((vol * Ch[MidCh].volume /** Ch[MidCh].expression*/) * 127 / 16129 /*2048383*/) >> 2)];
442 volume = 63 - W9X_volume_mapping_table[((velocity * channelVolume * channelExpression * m_masterVolume / 2048383) >> 2)];
443 //volume = W9X_volume_mapping_table[vol >> 2] + volume;
444 if(volume > 0)
445 volume += 64;//OPN has 0~127 range. As 0...63 is almost full silence, but at 64 to 127 is very closed to OPL3, just add 64.
446 }
447 break;
448 }
449
450
451 if(volume > 127)
452 volume = 127;
453
454 uint8_t alg = adli.fbalg & 0x07;
455 for(uint8_t op = 0; op < 4; op++)
456 {
457 bool do_op = alg_do[alg][op] || m_scaleModulators;
458 uint32_t x = op_vol[op];
459 uint32_t vol_res = do_op ? (127 - (static_cast<uint32_t>(volume) * (127 - (x & 127))) / 127) : x;
460 if(brightness != 127)
461 {
462 brightness = static_cast<uint32_t>(::round(127.0 * ::sqrt((static_cast<double>(brightness)) * (1.0 / 127.0))));
463 if(!do_op)
464 vol_res = (127 - (brightness * (127 - (static_cast<uint32_t>(vol_res) & 127))) / 127);
465 }
466 writeRegI(chip, port, 0x40 + cc + (4 * op), vol_res);
467 }
468 // Correct formula (ST3, AdPlug):
469 // 63-((63-(instrvol))/63)*chanvol
470 // Reduces to (tested identical):
471 // 63 - chanvol + chanvol*instrvol/63
472 // Also (slower, floats):
473 // 63 + chanvol * (instrvol / 63.0 - 1)
474 }
475
setPatch(size_t c,const OpnTimbre & instrument)476 void OPN2::setPatch(size_t c, const OpnTimbre &instrument)
477 {
478 size_t chip;
479 uint8_t port;
480 uint32_t cc;
481 getOpnChannel(c, chip, port, cc);
482 m_insCache[c] = instrument;
483 for(uint8_t d = 0; d < 7; d++)
484 {
485 for(uint8_t op = 0; op < 4; op++)
486 writeRegI(chip, port, 0x30 + (0x10 * d) + (op * 4) + cc, instrument.OPS[op].data[d]);
487 }
488
489 writeRegI(chip, port, 0xB0 + cc, instrument.fbalg);//Feedback/Algorithm
490 m_regLFOSens[c] = (m_regLFOSens[c] & 0xC0) | (instrument.lfosens & 0x3F);
491 writeRegI(chip, port, 0xB4 + cc, m_regLFOSens[c]);//Panorame and LFO bits
492 }
493
setPan(size_t c,uint8_t value)494 void OPN2::setPan(size_t c, uint8_t value)
495 {
496 size_t chip;
497 uint8_t port;
498 uint32_t cc;
499 getOpnChannel(c, chip, port, cc);
500 const OpnTimbre &adli = m_insCache[c];
501 uint8_t val = 0;
502 if(m_softPanning)
503 {
504 val = (OPN_PANNING_BOTH & 0xC0) | (adli.lfosens & 0x3F);
505 writePan(chip, c % 6, value);
506 writeRegI(chip, port, 0xB4 + cc, val);
507 }
508 else
509 {
510 int panning = 0;
511 if(value < 64 + 32) panning |= OPN_PANNING_LEFT;
512 if(value >= 64 - 32) panning |= OPN_PANNING_RIGHT;
513 val = (panning & 0xC0) | (adli.lfosens & 0x3F);
514 writePan(chip, c % 6, 64);
515 writeRegI(chip, port, 0xB4 + cc, val);
516 }
517 m_regLFOSens[c] = val;
518 }
519
silenceAll()520 void OPN2::silenceAll() // Silence all OPL channels.
521 {
522 for(size_t c = 0; c < m_numChannels; ++c)
523 {
524 noteOff(c);
525 touchNote(c, 0);
526 }
527 }
528
commitLFOSetup()529 void OPN2::commitLFOSetup()
530 {
531 uint8_t regLFOSetup = (m_lfoEnable ? 8 : 0) | (m_lfoFrequency & 7);
532 m_regLFOSetup = regLFOSetup;
533 for(size_t chip = 0; chip < m_numChips; ++chip)
534 writeReg(chip, 0, 0x22, regLFOSetup);
535 }
536
setVolumeScaleModel(OPNMIDI_VolumeModels volumeModel)537 void OPN2::setVolumeScaleModel(OPNMIDI_VolumeModels volumeModel)
538 {
539 switch(volumeModel)
540 {
541 case OPNMIDI_VolumeModel_AUTO://Do nothing until restart playing
542 break;
543
544 case OPNMIDI_VolumeModel_Generic:
545 m_volumeScale = OPN2::VOLUME_Generic;
546 break;
547
548 case OPNMIDI_VolumeModel_NativeOPN2:
549 m_volumeScale = OPN2::VOLUME_NATIVE;
550 break;
551
552 case OPNMIDI_VolumeModel_DMX:
553 m_volumeScale = OPN2::VOLUME_DMX;
554 break;
555
556 case OPNMIDI_VolumeModel_APOGEE:
557 m_volumeScale = OPN2::VOLUME_APOGEE;
558 break;
559
560 case OPNMIDI_VolumeModel_9X:
561 m_volumeScale = OPN2::VOLUME_9X;
562 break;
563 }
564 }
565
getVolumeScaleModel()566 OPNMIDI_VolumeModels OPN2::getVolumeScaleModel()
567 {
568 switch(m_volumeScale)
569 {
570 default:
571 case OPN2::VOLUME_Generic:
572 return OPNMIDI_VolumeModel_Generic;
573 case OPN2::VOLUME_NATIVE:
574 return OPNMIDI_VolumeModel_NativeOPN2;
575 case OPN2::VOLUME_DMX:
576 return OPNMIDI_VolumeModel_DMX;
577 case OPN2::VOLUME_APOGEE:
578 return OPNMIDI_VolumeModel_APOGEE;
579 case OPN2::VOLUME_9X:
580 return OPNMIDI_VolumeModel_9X;
581 }
582 }
583
clearChips()584 void OPN2::clearChips()
585 {
586 for(size_t i = 0; i < m_chips.size(); i++)
587 m_chips[i].reset(NULL);
588 m_chips.clear();
589 }
590
reset(int emulator,unsigned long PCM_RATE,OPNFamily family,void * audioTickHandler)591 void OPN2::reset(int emulator, unsigned long PCM_RATE, OPNFamily family, void *audioTickHandler)
592 {
593 #if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
594 ADL_UNUSED(audioTickHandler);
595 #endif
596 clearChips();
597 m_insCache.clear();
598 m_regLFOSens.clear();
599 #ifdef OPNMIDI_MIDI2VGM
600 if(emulator == OPNMIDI_VGM_DUMPER && (m_numChips > 2))
601 m_numChips = 2;// VGM Dumper can't work in multichip mode
602 #endif
603 m_chips.resize(m_numChips, AdlMIDI_SPtr<OPNChipBase>());
604
605 #ifdef OPNMIDI_MIDI2VGM
606 m_loopStartHook = NULL;
607 m_loopStartHookData = NULL;
608 m_loopEndHook = NULL;
609 m_loopEndHookData = NULL;
610 #endif
611
612 for(size_t i = 0; i < m_chips.size(); i++)
613 {
614 OPNChipBase *chip;
615
616 switch(emulator)
617 {
618 default:
619 assert(false);
620 abort();
621 #ifndef OPNMIDI_DISABLE_MAME_EMULATOR
622 case OPNMIDI_EMU_MAME:
623 chip = new MameOPN2(family);
624 break;
625 #endif
626 #ifndef OPNMIDI_DISABLE_NUKED_EMULATOR
627 case OPNMIDI_EMU_NUKED:
628 chip = new NukedOPN2(family);
629 break;
630 #endif
631 #ifndef OPNMIDI_DISABLE_GENS_EMULATOR
632 case OPNMIDI_EMU_GENS:
633 chip = new GensOPN2(family);
634 break;
635 #endif
636 #ifndef OPNMIDI_DISABLE_GX_EMULATOR
637 case OPNMIDI_EMU_GX:
638 chip = new GXOPN2(family);
639 break;
640 #endif
641 #ifndef OPNMIDI_DISABLE_NP2_EMULATOR
642 case OPNMIDI_EMU_NP2:
643 chip = new NP2OPNA<>(family);
644 break;
645 #endif
646 #ifndef OPNMIDI_DISABLE_MAME_2608_EMULATOR
647 case OPNMIDI_EMU_MAME_2608:
648 chip = new MameOPNA(family);
649 break;
650 #endif
651 #ifndef OPNMIDI_DISABLE_PMDWIN_EMULATOR
652 case OPNMIDI_EMU_PMDWIN:
653 chip = new PMDWinOPNA(family);
654 break;
655 #endif
656 #ifdef OPNMIDI_MIDI2VGM
657 case OPNMIDI_VGM_DUMPER:
658 chip = new VGMFileDumper(family);
659 if(i == 0)//Set hooks for first chip only
660 {
661 m_loopStartHook = &VGMFileDumper::loopStartHook;
662 m_loopStartHookData = chip;
663 m_loopEndHook = &VGMFileDumper::loopEndHook;
664 m_loopEndHookData = chip;
665 }
666 break;
667 #endif
668 }
669 m_chips[i].reset(chip);
670 chip->setChipId(static_cast<uint32_t>(i));
671 chip->setRate(static_cast<uint32_t>(PCM_RATE), chip->nativeClockRate());
672 if(m_runAtPcmRate)
673 chip->setRunningAtPcmRate(true);
674 #if defined(ADLMIDI_AUDIO_TICK_HANDLER)
675 chip->setAudioTickHandlerInstance(audioTickHandler);
676 #endif
677 family = chip->family();
678 }
679
680 m_chipFamily = family;
681 m_numChannels = m_numChips * 6;
682 m_insCache.resize(m_numChannels, m_emptyInstrument.op[0]);
683 m_regLFOSens.resize(m_numChannels, 0);
684
685 uint8_t regLFOSetup = (m_lfoEnable ? 8 : 0) | (m_lfoFrequency & 7);
686 m_regLFOSetup = regLFOSetup;
687
688 for(size_t card = 0; card < m_numChips; ++card)
689 {
690 writeReg(card, 0, 0x22, regLFOSetup);//push current LFO state
691 writeReg(card, 0, 0x27, 0x00); //set Channel 3 normal mode
692 writeReg(card, 0, 0x2B, 0x00); //Disable DAC
693 //Shut up all channels
694 writeReg(card, 0, 0x28, 0x00 ); //Note Off 0 channel
695 writeReg(card, 0, 0x28, 0x01 ); //Note Off 1 channel
696 writeReg(card, 0, 0x28, 0x02 ); //Note Off 2 channel
697 writeReg(card, 0, 0x28, 0x04 ); //Note Off 3 channel
698 writeReg(card, 0, 0x28, 0x05 ); //Note Off 4 channel
699 writeReg(card, 0, 0x28, 0x06 ); //Note Off 5 channel
700 }
701
702 silenceAll();
703 #ifdef OPNMIDI_MIDI2VGM
704 if(m_loopStartHook) // Post-initialization Loop Start hook (fix for loop edge passing clicks)
705 m_loopStartHook(m_loopStartHookData);
706 #endif
707 }
708
chipFamily() const709 OPNFamily OPN2::chipFamily() const
710 {
711 return m_chipFamily;
712 }
713