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_midiplay.hpp"
25 #include "opnmidi_opn2.hpp"
26 #include "opnmidi_private.hpp"
27 #include "chips/opn_chip_base.h"
28 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
29 #include "midi_sequencer.hpp"
30 #endif
31 
32 /* Unify MIDI player casting and interface between ADLMIDI and OPNMIDI */
33 #define GET_MIDI_PLAYER(device) reinterpret_cast<OPNMIDIplay *>((device)->opn2_midiPlayer)
34 typedef OPNMIDIplay MidiPlayer;
35 
36 static OPN2_Version opn2_version = {
37     OPNMIDI_VERSION_MAJOR,
38     OPNMIDI_VERSION_MINOR,
39     OPNMIDI_VERSION_PATCHLEVEL
40 };
41 
42 static const OPNMIDI_AudioFormat opn2_DefaultAudioFormat =
43 {
44     OPNMIDI_SampleType_S16,
45     sizeof(int16_t),
46     2 * sizeof(int16_t),
47 };
48 
49 /*---------------------------EXPORTS---------------------------*/
50 
opn2_init(long sample_rate)51 OPNMIDI_EXPORT struct OPN2_MIDIPlayer *opn2_init(long sample_rate)
52 {
53     OPN2_MIDIPlayer *midi_device;
54     midi_device = (OPN2_MIDIPlayer *)malloc(sizeof(OPN2_MIDIPlayer));
55     if(!midi_device)
56     {
57         OPN2MIDI_ErrorString = "Can't initialize OPNMIDI: out of memory!";
58         return NULL;
59     }
60 
61     OPNMIDIplay *player = new(std::nothrow) OPNMIDIplay(static_cast<unsigned long>(sample_rate));
62     if(!player)
63     {
64         free(midi_device);
65         OPN2MIDI_ErrorString = "Can't initialize OPNMIDI: out of memory!";
66         return NULL;
67     }
68     midi_device->opn2_midiPlayer = player;
69     return midi_device;
70 }
71 
opn2_setDeviceIdentifier(OPN2_MIDIPlayer * device,unsigned id)72 OPNMIDI_EXPORT int opn2_setDeviceIdentifier(OPN2_MIDIPlayer *device, unsigned id)
73 {
74     if(!device || id > 0x0f)
75         return -1;
76     MidiPlayer *play = GET_MIDI_PLAYER(device);
77     assert(play);
78     play->setDeviceId(static_cast<uint8_t>(id));
79     return 0;
80 }
81 
opn2_setNumChips(OPN2_MIDIPlayer * device,int numCards)82 OPNMIDI_EXPORT int opn2_setNumChips(OPN2_MIDIPlayer *device, int numCards)
83 {
84     if(device == NULL)
85         return -2;
86 
87     MidiPlayer *play = GET_MIDI_PLAYER(device);
88     assert(play);
89     play->m_setup.numChips = static_cast<unsigned int>(numCards);
90     if(play->m_setup.numChips < 1 || play->m_setup.numChips > OPN_MAX_CHIPS)
91     {
92         play->setErrorString("number of chips may only be 1.." OPN_MAX_CHIPS_STR ".\n");
93         return -1;
94     }
95 
96     Synth &synth = *play->m_synth;
97     if(!synth.setupLocked())
98     {
99         synth.m_numChips = play->m_setup.numChips;
100         play->partialReset();
101     }
102 
103     return 0;
104 }
105 
opn2_getNumChips(struct OPN2_MIDIPlayer * device)106 OPNMIDI_EXPORT int opn2_getNumChips(struct OPN2_MIDIPlayer *device)
107 {
108     if(device == NULL)
109         return -2;
110     MidiPlayer *play = GET_MIDI_PLAYER(device);
111     assert(play);
112     return (int)play->m_setup.numChips;
113 }
114 
opn2_getNumChipsObtained(struct OPN2_MIDIPlayer * device)115 OPNMIDI_EXPORT int opn2_getNumChipsObtained(struct OPN2_MIDIPlayer *device)
116 {
117     if(device == NULL)
118         return -2;
119     MidiPlayer *play = GET_MIDI_PLAYER(device);
120     assert(play);
121     return (int)play->m_synth->m_numChips;
122 }
123 
124 
opn2_reserveBanks(OPN2_MIDIPlayer * device,unsigned banks)125 OPNMIDI_EXPORT int opn2_reserveBanks(OPN2_MIDIPlayer *device, unsigned banks)
126 {
127     if(!device)
128         return -1;
129     MidiPlayer *play = GET_MIDI_PLAYER(device);
130     assert(play);
131     Synth::BankMap &map = play->m_synth->m_insBanks;
132     map.reserve(banks);
133     return (int)map.capacity();
134 }
135 
opn2_getBank(OPN2_MIDIPlayer * device,const OPN2_BankId * idp,int flags,OPN2_Bank * bank)136 OPNMIDI_EXPORT int opn2_getBank(OPN2_MIDIPlayer *device, const OPN2_BankId *idp, int flags, OPN2_Bank *bank)
137 {
138     if(!device || !idp || !bank)
139         return -1;
140 
141     OPN2_BankId id = *idp;
142     if(id.lsb > 127 || id.msb > 127 || id.percussive > 1)
143         return -1;
144     size_t idnumber = ((id.msb << 8) | id.lsb | (id.percussive ? size_t(Synth::PercussionTag) : 0));
145 
146     MidiPlayer *play = GET_MIDI_PLAYER(device);
147     assert(play);
148     Synth::BankMap &map = play->m_synth->m_insBanks;
149 
150     Synth::BankMap::iterator it;
151     if(!(flags & OPNMIDI_Bank_Create))
152     {
153         it = map.find(idnumber);
154         if(it == map.end())
155             return -1;
156     }
157     else
158     {
159         std::pair<size_t, Synth::Bank> value;
160         value.first = idnumber;
161         memset(&value.second, 0, sizeof(value.second));
162         for (unsigned i = 0; i < 128; ++i)
163             value.second.ins[i].flags = OpnInstMeta::Flag_NoSound;
164 
165         std::pair<Synth::BankMap::iterator, bool> ir;
166         if((flags & OPNMIDI_Bank_CreateRt) == OPNMIDI_Bank_CreateRt)
167         {
168             ir = map.insert(value, Synth::BankMap::do_not_expand_t());
169             if(ir.first == map.end())
170                 return -1;
171         }
172         else
173             ir = map.insert(value);
174         it = ir.first;
175     }
176 
177     it.to_ptrs(bank->pointer);
178     return 0;
179 }
180 
opn2_getBankId(OPN2_MIDIPlayer * device,const OPN2_Bank * bank,OPN2_BankId * id)181 OPNMIDI_EXPORT int opn2_getBankId(OPN2_MIDIPlayer *device, const OPN2_Bank *bank, OPN2_BankId *id)
182 {
183     if(!device || !bank)
184         return -1;
185 
186     Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
187     Synth::BankMap::key_type idnumber = it->first;
188     id->msb = (idnumber >> 8) & 127;
189     id->lsb = idnumber & 127;
190     id->percussive = (idnumber & Synth::PercussionTag) ? 1 : 0;
191     return 0;
192 }
193 
opn2_removeBank(OPN2_MIDIPlayer * device,OPN2_Bank * bank)194 OPNMIDI_EXPORT int opn2_removeBank(OPN2_MIDIPlayer *device, OPN2_Bank *bank)
195 {
196     if(!device || !bank)
197         return -1;
198 
199     MidiPlayer *play = GET_MIDI_PLAYER(device);
200     assert(play);
201     Synth::BankMap &map = play->m_synth->m_insBanks;
202     Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
203     size_t size = map.size();
204     map.erase(it);
205     return (map.size() != size) ? 0 : -1;
206 }
207 
opn2_getFirstBank(OPN2_MIDIPlayer * device,OPN2_Bank * bank)208 OPNMIDI_EXPORT int opn2_getFirstBank(OPN2_MIDIPlayer *device, OPN2_Bank *bank)
209 {
210     if(!device)
211         return -1;
212 
213     MidiPlayer *play = GET_MIDI_PLAYER(device);
214     assert(play);
215     Synth::BankMap &map = play->m_synth->m_insBanks;
216 
217     Synth::BankMap::iterator it = map.begin();
218     if(it == map.end())
219         return -1;
220 
221     it.to_ptrs(bank->pointer);
222     return 0;
223 }
224 
opn2_getNextBank(OPN2_MIDIPlayer * device,OPN2_Bank * bank)225 OPNMIDI_EXPORT int opn2_getNextBank(OPN2_MIDIPlayer *device, OPN2_Bank *bank)
226 {
227     if(!device)
228         return -1;
229 
230     MidiPlayer *play = GET_MIDI_PLAYER(device);
231     assert(play);
232     Synth::BankMap &map = play->m_synth->m_insBanks;
233 
234     Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
235     if(++it == map.end())
236         return -1;
237 
238     it.to_ptrs(bank->pointer);
239     return 0;
240 }
241 
opn2_getInstrument(OPN2_MIDIPlayer * device,const OPN2_Bank * bank,unsigned index,OPN2_Instrument * ins)242 OPNMIDI_EXPORT int opn2_getInstrument(OPN2_MIDIPlayer *device, const OPN2_Bank *bank, unsigned index, OPN2_Instrument *ins)
243 {
244     if(!device || !bank || index > 127 || !ins)
245         return -1;
246 
247     Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
248     cvt_FMIns_to_OPNI(*ins, it->second.ins[index]);
249     ins->version = 0;
250     return 0;
251 }
252 
opn2_setInstrument(OPN2_MIDIPlayer * device,OPN2_Bank * bank,unsigned index,const OPN2_Instrument * ins)253 OPNMIDI_EXPORT int opn2_setInstrument(OPN2_MIDIPlayer *device, OPN2_Bank *bank, unsigned index, const OPN2_Instrument *ins)
254 {
255     if(!device || !bank || index > 127 || !ins)
256         return -1;
257 
258     if(ins->version != 0)
259         return -1;
260 
261     Synth::BankMap::iterator it = Synth::BankMap::iterator::from_ptrs(bank->pointer);
262     cvt_OPNI_to_FMIns(it->second.ins[index], *ins);
263     return 0;
264 }
265 
opn2_openBankFile(OPN2_MIDIPlayer * device,const char * filePath)266 OPNMIDI_EXPORT int opn2_openBankFile(OPN2_MIDIPlayer *device, const char *filePath)
267 {
268     if(device)
269     {
270         MidiPlayer *play = GET_MIDI_PLAYER(device);
271         assert(play);
272         play->m_setup.tick_skip_samples_delay = 0;
273         if(!play->LoadBank(filePath))
274         {
275             std::string err = play->getErrorString();
276             if(err.empty())
277                 play->setErrorString("OPN2 MIDI: Can't load file");
278             return -1;
279         }
280         else
281             return 0;
282     }
283     OPN2MIDI_ErrorString = "Can't load file: OPN2 MIDI is not initialized";
284     return -1;
285 }
286 
opn2_openBankData(OPN2_MIDIPlayer * device,const void * mem,long size)287 OPNMIDI_EXPORT int opn2_openBankData(OPN2_MIDIPlayer *device, const void *mem, long size)
288 {
289     if(device)
290     {
291         MidiPlayer *play = GET_MIDI_PLAYER(device);
292         assert(play);
293         play->m_setup.tick_skip_samples_delay = 0;
294         if(!play->LoadBank(mem, static_cast<size_t>(size)))
295         {
296             std::string err = play->getErrorString();
297             if(err.empty())
298                 play->setErrorString("OPN2 MIDI: Can't load data from memory");
299             return -1;
300         }
301         else return 0;
302     }
303 
304     OPN2MIDI_ErrorString = "Can't load file: OPN2 MIDI is not initialized";
305     return -1;
306 }
307 
opn2_setLfoEnabled(struct OPN2_MIDIPlayer * device,int lfoEnable)308 OPNMIDI_EXPORT void opn2_setLfoEnabled(struct OPN2_MIDIPlayer *device, int lfoEnable)
309 {
310     if(!device) return;
311     MidiPlayer *play = GET_MIDI_PLAYER(device);
312     assert(play);
313     Synth &synth = *play->m_synth;
314     play->m_setup.lfoEnable = lfoEnable;
315     synth.m_lfoEnable = (lfoEnable < 0 ?
316                          synth.m_insBankSetup.lfoEnable :
317                          play->m_setup.lfoEnable) != 0;
318     synth.commitLFOSetup();
319 }
320 
opn2_getLfoEnabled(struct OPN2_MIDIPlayer * device)321 OPNMIDI_EXPORT int opn2_getLfoEnabled(struct OPN2_MIDIPlayer *device)
322 {
323     if(!device) return -1;
324     MidiPlayer *play = GET_MIDI_PLAYER(device);
325     assert(play);
326     return play->m_synth->m_lfoEnable;
327 }
328 
opn2_setLfoFrequency(struct OPN2_MIDIPlayer * device,int lfoFrequency)329 OPNMIDI_EXPORT void opn2_setLfoFrequency(struct OPN2_MIDIPlayer *device, int lfoFrequency)
330 {
331     if(!device) return;
332     MidiPlayer *play = GET_MIDI_PLAYER(device);
333     assert(play);
334     Synth &synth = *play->m_synth;
335     play->m_setup.lfoFrequency = lfoFrequency;
336     synth.m_lfoFrequency = lfoFrequency < 0 ?
337                                    synth.m_insBankSetup.lfoFrequency :
338                                    (uint8_t)play->m_setup.lfoFrequency;
339     synth.commitLFOSetup();
340 }
341 
opn2_getLfoFrequency(struct OPN2_MIDIPlayer * device)342 OPNMIDI_EXPORT int opn2_getLfoFrequency(struct OPN2_MIDIPlayer *device)
343 {
344     if(!device) return -1;
345     MidiPlayer *play = GET_MIDI_PLAYER(device);
346     assert(play);
347     return play->m_synth->m_lfoFrequency;
348 }
349 
350 /*Override chip type. -1 - use bank default state*/
opn2_setChipType(struct OPN2_MIDIPlayer * device,int chipType)351 OPNMIDI_EXPORT void opn2_setChipType(struct OPN2_MIDIPlayer *device, int chipType)
352 {
353     if(!device) return;
354     MidiPlayer *play = GET_MIDI_PLAYER(device);
355     assert(play);
356     play->m_setup.chipType = chipType;
357     play->applySetup();
358 }
359 
360 /*Get the chip type*/
opn2_getChipType(struct OPN2_MIDIPlayer * device)361 OPNMIDI_EXPORT int opn2_getChipType(struct OPN2_MIDIPlayer *device)
362 {
363     if(!device) return -1;
364     MidiPlayer *play = GET_MIDI_PLAYER(device);
365     assert(play);
366     return play->m_synth->chipFamily();
367 }
368 
opn2_setScaleModulators(OPN2_MIDIPlayer * device,int smod)369 OPNMIDI_EXPORT void opn2_setScaleModulators(OPN2_MIDIPlayer *device, int smod)
370 {
371     if(!device)
372         return;
373     MidiPlayer *play = GET_MIDI_PLAYER(device);
374     assert(play);
375     play->m_setup.ScaleModulators = smod;
376     play->m_synth->m_scaleModulators = (play->m_setup.ScaleModulators != 0);
377 }
378 
opn2_setFullRangeBrightness(struct OPN2_MIDIPlayer * device,int fr_brightness)379 OPNMIDI_EXPORT void opn2_setFullRangeBrightness(struct OPN2_MIDIPlayer *device, int fr_brightness)
380 {
381     if(!device)
382         return;
383     MidiPlayer *play = GET_MIDI_PLAYER(device);
384     assert(play);
385     play->m_setup.fullRangeBrightnessCC74 = (fr_brightness != 0);
386 }
387 
opn2_setLoopEnabled(OPN2_MIDIPlayer * device,int loopEn)388 OPNMIDI_EXPORT void opn2_setLoopEnabled(OPN2_MIDIPlayer *device, int loopEn)
389 {
390 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
391     if(!device)
392         return;
393     MidiPlayer *play = GET_MIDI_PLAYER(device);
394     assert(play);
395     play->m_sequencer->setLoopEnabled(loopEn != 0);
396 #else
397     ADL_UNUSED(device);
398     ADL_UNUSED(loopEn);
399 #endif
400 }
401 
opn2_setSoftPanEnabled(OPN2_MIDIPlayer * device,int softPanEn)402 OPNMIDI_EXPORT void opn2_setSoftPanEnabled(OPN2_MIDIPlayer *device, int softPanEn)
403 {
404     if(!device)
405         return;
406     MidiPlayer *play = GET_MIDI_PLAYER(device);
407     assert(play);
408     play->m_synth->m_softPanning = (softPanEn != 0);
409 }
410 
411 /* !!!DEPRECATED!!! */
opn2_setLogarithmicVolumes(struct OPN2_MIDIPlayer * device,int logvol)412 OPNMIDI_EXPORT void opn2_setLogarithmicVolumes(struct OPN2_MIDIPlayer *device, int logvol)
413 {
414     if(!device)
415         return;
416     MidiPlayer *play = GET_MIDI_PLAYER(device);
417     assert(play);
418     Synth &synth = *play->m_synth;
419     play->m_setup.LogarithmicVolumes = static_cast<unsigned int>(logvol);
420     if(!synth.setupLocked())
421     {
422         if(play->m_setup.LogarithmicVolumes != 0)
423             synth.setVolumeScaleModel(OPNMIDI_VolumeModel_NativeOPN2);
424         else
425             synth.setVolumeScaleModel(static_cast<OPNMIDI_VolumeModels>(play->m_setup.VolumeModel));
426     }
427 }
428 
opn2_setVolumeRangeModel(OPN2_MIDIPlayer * device,int volumeModel)429 OPNMIDI_EXPORT void opn2_setVolumeRangeModel(OPN2_MIDIPlayer *device, int volumeModel)
430 {
431     if(!device)
432         return;
433     MidiPlayer *play = GET_MIDI_PLAYER(device);
434     assert(play);
435     Synth &synth = *play->m_synth;
436     play->m_setup.VolumeModel = volumeModel;
437     if(!synth.setupLocked())
438     {
439         if(play->m_setup.VolumeModel == OPNMIDI_VolumeModel_AUTO)//Use bank default volume model
440             synth.m_volumeScale = (Synth::VolumesScale)synth.m_insBankSetup.volumeModel;
441         else
442             synth.setVolumeScaleModel(static_cast<OPNMIDI_VolumeModels>(volumeModel));
443     }
444 }
445 
opn2_getVolumeRangeModel(struct OPN2_MIDIPlayer * device)446 OPNMIDI_EXPORT int opn2_getVolumeRangeModel(struct OPN2_MIDIPlayer *device)
447 {
448     if(!device)
449         return -1;
450     MidiPlayer *play = GET_MIDI_PLAYER(device);
451     assert(play);
452     return play->m_synth->getVolumeScaleModel();
453 }
454 
opn2_openFile(OPN2_MIDIPlayer * device,const char * filePath)455 OPNMIDI_EXPORT int opn2_openFile(OPN2_MIDIPlayer *device, const char *filePath)
456 {
457     if(device)
458     {
459         MidiPlayer *play = GET_MIDI_PLAYER(device);
460         assert(play);
461 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
462         play->m_setup.tick_skip_samples_delay = 0;
463         if(!play->LoadMIDI(filePath))
464         {
465             std::string err = play->getErrorString();
466             if(err.empty())
467                 play->setErrorString("OPN2 MIDI: Can't load file");
468             return -1;
469         }
470         else return 0;
471 #else
472         ADL_UNUSED(filePath);
473         play->setErrorString("OPNMIDI: MIDI Sequencer is not supported in this build of library!");
474         return -1;
475 #endif
476     }
477 
478     OPN2MIDI_ErrorString = "Can't load file: OPN2 MIDI is not initialized";
479     return -1;
480 }
481 
opn2_openData(OPN2_MIDIPlayer * device,const void * mem,unsigned long size)482 OPNMIDI_EXPORT int opn2_openData(OPN2_MIDIPlayer *device, const void *mem, unsigned long size)
483 {
484     if(device)
485     {
486         MidiPlayer *play = GET_MIDI_PLAYER(device);
487         assert(play);
488 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
489         play->m_setup.tick_skip_samples_delay = 0;
490         if(!play->LoadMIDI(mem, static_cast<size_t>(size)))
491         {
492             std::string err = play->getErrorString();
493             if(err.empty())
494                 play->setErrorString("OPN2 MIDI: Can't load data from memory");
495             return -1;
496         }
497         else return 0;
498 #else
499         ADL_UNUSED(mem);
500         ADL_UNUSED(size);
501         play->setErrorString("OPNMIDI: MIDI Sequencer is not supported in this build of library!");
502         return -1;
503 #endif
504     }
505 
506     OPN2MIDI_ErrorString = "Can't load file: OPN2 MIDI is not initialized";
507     return -1;
508 }
509 
opn2_emulatorName()510 OPNMIDI_EXPORT const char *opn2_emulatorName()
511 {
512     return "<opn2_emulatorName() is deprecated! Use opn2_chipEmulatorName() instead!>";
513 }
514 
opn2_chipEmulatorName(struct OPN2_MIDIPlayer * device)515 OPNMIDI_EXPORT const char *opn2_chipEmulatorName(struct OPN2_MIDIPlayer *device)
516 {
517     if(device)
518     {
519         MidiPlayer *play = GET_MIDI_PLAYER(device);
520         assert(play);
521         Synth &synth = *play->m_synth;
522         if(!synth.m_chips.empty())
523             return synth.m_chips[0]->emulatorName();
524     }
525     return "Unknown";
526 }
527 
opn2_switchEmulator(struct OPN2_MIDIPlayer * device,int emulator)528 OPNMIDI_EXPORT int opn2_switchEmulator(struct OPN2_MIDIPlayer *device, int emulator)
529 {
530     if(device)
531     {
532         MidiPlayer *play = GET_MIDI_PLAYER(device);
533         assert(play);
534         if(opn2_isEmulatorAvailable(emulator))
535         {
536             play->m_setup.emulator = emulator;
537             play->partialReset();
538             return 0;
539         }
540         play->setErrorString("OPN2 MIDI: Unknown emulation core!");
541     }
542     return -1;
543 }
544 
545 
opn2_setRunAtPcmRate(OPN2_MIDIPlayer * device,int enabled)546 OPNMIDI_EXPORT int opn2_setRunAtPcmRate(OPN2_MIDIPlayer *device, int enabled)
547 {
548     if(device)
549     {
550         MidiPlayer *play = GET_MIDI_PLAYER(device);
551         assert(play);
552         Synth &synth = *play->m_synth;
553         play->m_setup.runAtPcmRate = (enabled != 0);
554         if(!synth.setupLocked())
555             play->partialReset();
556         return 0;
557     }
558     return -1;
559 }
560 
561 
opn2_linkedLibraryVersion()562 OPNMIDI_EXPORT const char *opn2_linkedLibraryVersion()
563 {
564 #if !defined(OPNMIDI_ENABLE_HQ_RESAMPLER)
565     return OPNMIDI_VERSION;
566 #else
567     return OPNMIDI_VERSION " (HQ)";
568 #endif
569 }
570 
opn2_linkedVersion()571 OPNMIDI_EXPORT const OPN2_Version *opn2_linkedVersion()
572 {
573     return &opn2_version;
574 }
575 
opn2_errorString()576 OPNMIDI_EXPORT const char *opn2_errorString()
577 {
578     return OPN2MIDI_ErrorString.c_str();
579 }
580 
opn2_errorInfo(struct OPN2_MIDIPlayer * device)581 OPNMIDI_EXPORT const char *opn2_errorInfo(struct OPN2_MIDIPlayer *device)
582 {
583     if(!device)
584         return opn2_errorString();
585     MidiPlayer *play = GET_MIDI_PLAYER(device);
586     if(!play)
587         return opn2_errorString();
588     return play->getErrorString().c_str();
589 }
590 
opn2_close(OPN2_MIDIPlayer * device)591 OPNMIDI_EXPORT void opn2_close(OPN2_MIDIPlayer *device)
592 {
593     if(!device)
594         return;
595     MidiPlayer *play = GET_MIDI_PLAYER(device);
596     assert(play);
597     delete play;
598     device->opn2_midiPlayer = NULL;
599     free(device);
600     device = NULL;
601 }
602 
opn2_reset(OPN2_MIDIPlayer * device)603 OPNMIDI_EXPORT void opn2_reset(OPN2_MIDIPlayer *device)
604 {
605     if(!device)
606         return;
607     MidiPlayer *play = GET_MIDI_PLAYER(device);
608     assert(play);
609     play->partialReset();
610     play->resetMIDI();
611 }
612 
opn2_totalTimeLength(struct OPN2_MIDIPlayer * device)613 OPNMIDI_EXPORT double opn2_totalTimeLength(struct OPN2_MIDIPlayer *device)
614 {
615 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
616     if(!device)
617         return -1.0;
618     MidiPlayer *play = GET_MIDI_PLAYER(device);
619     assert(play);
620     return play->m_sequencer->timeLength();
621 #else
622     ADL_UNUSED(device);
623     return -1.0;
624 #endif
625 }
626 
opn2_loopStartTime(struct OPN2_MIDIPlayer * device)627 OPNMIDI_EXPORT double opn2_loopStartTime(struct OPN2_MIDIPlayer *device)
628 {
629 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
630     if(!device)
631         return -1.0;
632     MidiPlayer *play = GET_MIDI_PLAYER(device);
633     assert(play);
634     return play->m_sequencer->getLoopStart();
635 #else
636     ADL_UNUSED(device);
637     return -1.0;
638 #endif
639 }
640 
opn2_loopEndTime(struct OPN2_MIDIPlayer * device)641 OPNMIDI_EXPORT double opn2_loopEndTime(struct OPN2_MIDIPlayer *device)
642 {
643 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
644     if(!device)
645         return -1.0;
646     MidiPlayer *play = GET_MIDI_PLAYER(device);
647     assert(play);
648     return play->m_sequencer->getLoopEnd();
649 #else
650     ADL_UNUSED(device);
651     return -1.0;
652 #endif
653 }
654 
opn2_positionTell(struct OPN2_MIDIPlayer * device)655 OPNMIDI_EXPORT double opn2_positionTell(struct OPN2_MIDIPlayer *device)
656 {
657 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
658     if(!device)
659         return -1.0;
660     MidiPlayer *play = GET_MIDI_PLAYER(device);
661     assert(play);
662     return play->m_sequencer->tell();
663 #else
664     ADL_UNUSED(device);
665     return -1.0;
666 #endif
667 }
668 
opn2_positionSeek(struct OPN2_MIDIPlayer * device,double seconds)669 OPNMIDI_EXPORT void opn2_positionSeek(struct OPN2_MIDIPlayer *device, double seconds)
670 {
671 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
672     if(seconds < 0.0)
673         return;//Seeking negative position is forbidden! :-P
674     if(!device)
675         return;
676     MidiPlayer *play = GET_MIDI_PLAYER(device);
677     assert(play);
678     play->realTime_panic();
679     play->m_setup.delay = play->m_sequencer->seek(seconds, play->m_setup.mindelay);
680     play->m_setup.carry = 0.0;
681 #else
682     ADL_UNUSED(device);
683     ADL_UNUSED(seconds);
684 #endif
685 }
686 
opn2_positionRewind(struct OPN2_MIDIPlayer * device)687 OPNMIDI_EXPORT void opn2_positionRewind(struct OPN2_MIDIPlayer *device)
688 {
689 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
690     if(!device)
691         return;
692     MidiPlayer *play = GET_MIDI_PLAYER(device);
693     assert(play);
694     play->realTime_panic();
695     play->m_sequencer->rewind();
696 #else
697     ADL_UNUSED(device);
698 #endif
699 }
700 
opn2_setTempo(struct OPN2_MIDIPlayer * device,double tempo)701 OPNMIDI_EXPORT void opn2_setTempo(struct OPN2_MIDIPlayer *device, double tempo)
702 {
703 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
704     if(!device || (tempo <= 0.0))
705         return;
706     MidiPlayer *play = GET_MIDI_PLAYER(device);
707     assert(play);
708     play->m_sequencer->setTempo(tempo);
709 #else
710     ADL_UNUSED(device);
711     ADL_UNUSED(tempo);
712 #endif
713 }
714 
715 
opn2_describeChannels(struct OPN2_MIDIPlayer * device,char * str,char * attr,size_t size)716 OPNMIDI_EXPORT int opn2_describeChannels(struct OPN2_MIDIPlayer *device, char *str, char *attr, size_t size)
717 {
718     if(!device)
719         return -1;
720     MidiPlayer *play = GET_MIDI_PLAYER(device);
721     assert(play);
722     play->describeChannels(str, attr, size);
723     return 0;
724 }
725 
726 
opn2_metaMusicTitle(struct OPN2_MIDIPlayer * device)727 OPNMIDI_EXPORT const char *opn2_metaMusicTitle(struct OPN2_MIDIPlayer *device)
728 {
729 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
730     if(!device)
731         return "";
732     MidiPlayer *play = GET_MIDI_PLAYER(device);
733     assert(play);
734     return play->m_sequencer->getMusicTitle().c_str();
735 #else
736     ADL_UNUSED(device);
737     return "";
738 #endif
739 }
740 
741 
opn2_metaMusicCopyright(struct OPN2_MIDIPlayer * device)742 OPNMIDI_EXPORT const char *opn2_metaMusicCopyright(struct OPN2_MIDIPlayer *device)
743 {
744 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
745     if(!device)
746         return "";
747     MidiPlayer *play = GET_MIDI_PLAYER(device);
748     assert(play);
749     return play->m_sequencer->getMusicCopyright().c_str();
750 #else
751     ADL_UNUSED(device);
752     return 0;
753 #endif
754 }
755 
opn2_metaTrackTitleCount(struct OPN2_MIDIPlayer * device)756 OPNMIDI_EXPORT size_t opn2_metaTrackTitleCount(struct OPN2_MIDIPlayer *device)
757 {
758 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
759     if(!device)
760         return 0;
761     MidiPlayer *play = GET_MIDI_PLAYER(device);
762     assert(play);
763     return play->m_sequencer->getTrackTitles().size();
764 #else
765     ADL_UNUSED(device);
766     return 0;
767 #endif
768 }
769 
opn2_metaTrackTitle(struct OPN2_MIDIPlayer * device,size_t index)770 OPNMIDI_EXPORT const char *opn2_metaTrackTitle(struct OPN2_MIDIPlayer *device, size_t index)
771 {
772 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
773     if(!device)
774         return "";
775     MidiPlayer *play = GET_MIDI_PLAYER(device);
776     assert(play);
777     const std::vector<std::string> &titles = play->m_sequencer->getTrackTitles();
778     if(index >= titles.size())
779         return "INVALID";
780     return titles[index].c_str();
781 #else
782     ADL_UNUSED(device);
783     ADL_UNUSED(index);
784     return "NOT SUPPORTED";
785 #endif
786 }
787 
788 
opn2_metaMarkerCount(struct OPN2_MIDIPlayer * device)789 OPNMIDI_EXPORT size_t opn2_metaMarkerCount(struct OPN2_MIDIPlayer *device)
790 {
791 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
792     if(!device)
793         return 0;
794     MidiPlayer *play = GET_MIDI_PLAYER(device);
795     assert(play);
796     return play->m_sequencer->getMarkers().size();
797 #else
798     ADL_UNUSED(device);
799     return 0;
800 #endif
801 }
802 
opn2_metaMarker(struct OPN2_MIDIPlayer * device,size_t index)803 OPNMIDI_EXPORT Opn2_MarkerEntry opn2_metaMarker(struct OPN2_MIDIPlayer *device, size_t index)
804 {
805     struct Opn2_MarkerEntry marker;
806 
807 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
808     if(!device)
809     {
810         marker.label = "INVALID";
811         marker.pos_time = 0.0;
812         marker.pos_ticks = 0;
813         return marker;
814     }
815 
816     MidiPlayer *play = GET_MIDI_PLAYER(device);
817     assert(play);
818 
819     const std::vector<MidiSequencer::MIDI_MarkerEntry> &markers = play->m_sequencer->getMarkers();
820     if(index >= markers.size())
821     {
822         marker.label = "INVALID";
823         marker.pos_time = 0.0;
824         marker.pos_ticks = 0;
825         return marker;
826     }
827 
828     const MidiSequencer::MIDI_MarkerEntry &mk = markers[index];
829     marker.label = mk.label.c_str();
830     marker.pos_time = mk.pos_time;
831     marker.pos_ticks = (unsigned long)mk.pos_ticks;
832 #else
833     (void)device; (void)index;
834     marker.label = "NOT SUPPORTED";
835     marker.pos_time = 0.0;
836     marker.pos_ticks = 0;
837 #endif
838     return marker;
839 }
840 
opn2_setRawEventHook(struct OPN2_MIDIPlayer * device,OPN2_RawEventHook rawEventHook,void * userData)841 OPNMIDI_EXPORT void opn2_setRawEventHook(struct OPN2_MIDIPlayer *device, OPN2_RawEventHook rawEventHook, void *userData)
842 {
843 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
844     if(!device)
845         return;
846     MidiPlayer *play = GET_MIDI_PLAYER(device);
847     assert(play);
848     play->m_sequencerInterface->onEvent = rawEventHook;
849     play->m_sequencerInterface->onEvent_userData = userData;
850 #else
851     ADL_UNUSED(device);
852     ADL_UNUSED(rawEventHook);
853     ADL_UNUSED(userData);
854 #endif
855 }
856 
857 /* Set note hook */
opn2_setNoteHook(struct OPN2_MIDIPlayer * device,OPN2_NoteHook noteHook,void * userData)858 OPNMIDI_EXPORT void opn2_setNoteHook(struct OPN2_MIDIPlayer *device, OPN2_NoteHook noteHook, void *userData)
859 {
860     if(!device)
861         return;
862     MidiPlayer *play = GET_MIDI_PLAYER(device);
863     assert(play);
864     play->hooks.onNote = noteHook;
865     play->hooks.onNote_userData = userData;
866 }
867 
868 /* Set debug message hook */
opn2_setDebugMessageHook(struct OPN2_MIDIPlayer * device,OPN2_DebugMessageHook debugMessageHook,void * userData)869 OPNMIDI_EXPORT void opn2_setDebugMessageHook(struct OPN2_MIDIPlayer *device, OPN2_DebugMessageHook debugMessageHook, void *userData)
870 {
871     if(!device)
872         return;
873     MidiPlayer *play = GET_MIDI_PLAYER(device);
874     assert(play);
875     play->hooks.onDebugMessage = debugMessageHook;
876     play->hooks.onDebugMessage_userData = userData;
877 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
878     play->m_sequencerInterface->onDebugMessage = debugMessageHook;
879     play->m_sequencerInterface->onDebugMessage_userData = userData;
880 #endif
881 }
882 
883 
884 template <class Dst>
CopySamplesRaw(OPN2_UInt8 * dstLeft,OPN2_UInt8 * dstRight,const int32_t * src,size_t frameCount,unsigned sampleOffset)885 static void CopySamplesRaw(OPN2_UInt8 *dstLeft, OPN2_UInt8 *dstRight, const int32_t *src,
886                            size_t frameCount, unsigned sampleOffset)
887 {
888     for(size_t i = 0; i < frameCount; ++i) {
889         *(Dst *)(dstLeft + (i * sampleOffset)) = src[2 * i];
890         *(Dst *)(dstRight + (i * sampleOffset)) = src[(2 * i) + 1];
891     }
892 }
893 
894 template <class Dst, class Ret>
CopySamplesTransformed(OPN2_UInt8 * dstLeft,OPN2_UInt8 * dstRight,const int32_t * src,size_t frameCount,unsigned sampleOffset,Ret (& transform)(int32_t))895 static void CopySamplesTransformed(OPN2_UInt8 *dstLeft, OPN2_UInt8 *dstRight, const int32_t *src,
896                                    size_t frameCount, unsigned sampleOffset,
897                                    Ret(&transform)(int32_t))
898 {
899     for(size_t i = 0; i < frameCount; ++i) {
900         *(Dst *)(dstLeft + (i * sampleOffset)) = static_cast<Dst>(transform(src[2 * i]));
901         *(Dst *)(dstRight + (i * sampleOffset)) = static_cast<Dst>(transform(src[(2 * i) + 1]));
902     }
903 }
904 
SendStereoAudio(int samples_requested,ssize_t in_size,int32_t * _in,ssize_t out_pos,OPN2_UInt8 * left,OPN2_UInt8 * right,const OPNMIDI_AudioFormat * format)905 static int SendStereoAudio(int         samples_requested,
906                            ssize_t     in_size,
907                            int32_t    *_in,
908                            ssize_t     out_pos,
909                            OPN2_UInt8 *left,
910                            OPN2_UInt8 *right,
911                            const OPNMIDI_AudioFormat *format)
912 {
913     if(!in_size)
914         return 0;
915     size_t outputOffset = static_cast<size_t>(out_pos);
916     size_t inSamples    = static_cast<size_t>(in_size * 2);
917     size_t maxSamples   = static_cast<size_t>(samples_requested) - outputOffset;
918     size_t toCopy       = std::min(maxSamples, inSamples);
919 
920     OPNMIDI_SampleType sampleType = format->type;
921     const unsigned containerSize = format->containerSize;
922     const unsigned sampleOffset = format->sampleOffset;
923 
924     left  += (outputOffset / 2) * sampleOffset;
925     right += (outputOffset / 2) * sampleOffset;
926 
927     typedef int32_t(&pfnConvert)(int32_t);
928 
929     switch(sampleType) {
930     case OPNMIDI_SampleType_S8:
931     case OPNMIDI_SampleType_U8:
932     {
933         pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S8) ? opn2_cvtS8 : opn2_cvtU8;
934         switch(containerSize) {
935         case sizeof(int8_t):
936             CopySamplesTransformed<int8_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
937             break;
938         case sizeof(int16_t):
939             CopySamplesTransformed<int16_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
940             break;
941         case sizeof(int32_t):
942             CopySamplesTransformed<int32_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
943             break;
944         default:
945             return -1;
946         }
947         break;
948     }
949     case OPNMIDI_SampleType_S16:
950     case OPNMIDI_SampleType_U16:
951     {
952         pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S16) ? opn2_cvtS16 : opn2_cvtU16;
953         switch(containerSize) {
954         case sizeof(int16_t):
955             CopySamplesTransformed<int16_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
956             break;
957         case sizeof(int32_t):
958             CopySamplesRaw<int32_t>(left, right, _in, toCopy / 2, sampleOffset);
959             break;
960         default:
961             return -1;
962         }
963         break;
964     }
965     case OPNMIDI_SampleType_S24:
966     case OPNMIDI_SampleType_U24:
967     {
968         pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S24) ? opn2_cvtS24 : opn2_cvtU24;
969         switch(containerSize) {
970         case sizeof(int32_t):
971             CopySamplesTransformed<int32_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
972             break;
973         default:
974             return -1;
975         }
976         break;
977     }
978     case OPNMIDI_SampleType_S32:
979     case OPNMIDI_SampleType_U32:
980     {
981         pfnConvert cvt = (sampleType == OPNMIDI_SampleType_S32) ? opn2_cvtS32 : opn2_cvtU32;
982         switch(containerSize) {
983         case sizeof(int32_t):
984             CopySamplesTransformed<int32_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
985             break;
986         default:
987             return -1;
988         }
989         break;
990     }
991     case OPNMIDI_SampleType_F32:
992         if(containerSize != sizeof(float))
993             return -1;
994         CopySamplesTransformed<float>(left, right, _in, toCopy / 2, sampleOffset, opn2_cvtReal<float>);
995         break;
996     case OPNMIDI_SampleType_F64:
997         if(containerSize != sizeof(double))
998             return -1;
999         CopySamplesTransformed<double>(left, right, _in, toCopy / 2, sampleOffset, opn2_cvtReal<double>);
1000         break;
1001     default:
1002         return -1;
1003     }
1004 
1005     return 0;
1006 }
1007 
1008 
opn2_play(struct OPN2_MIDIPlayer * device,int sampleCount,short * out)1009 OPNMIDI_EXPORT int opn2_play(struct OPN2_MIDIPlayer *device, int sampleCount, short *out)
1010 {
1011     return opn2_playFormat(device, sampleCount, (OPN2_UInt8 *)out, (OPN2_UInt8 *)(out + 1), &opn2_DefaultAudioFormat);
1012 }
1013 
opn2_playFormat(OPN2_MIDIPlayer * device,int sampleCount,OPN2_UInt8 * out_left,OPN2_UInt8 * out_right,const OPNMIDI_AudioFormat * format)1014 OPNMIDI_EXPORT int opn2_playFormat(OPN2_MIDIPlayer *device, int sampleCount,
1015                                    OPN2_UInt8 *out_left, OPN2_UInt8 *out_right,
1016                                    const OPNMIDI_AudioFormat *format)
1017 {
1018 #if defined(OPNMIDI_DISABLE_MIDI_SEQUENCER)
1019     ADL_UNUSED(device);
1020     ADL_UNUSED(sampleCount);
1021     ADL_UNUSED(out_left);
1022     ADL_UNUSED(out_right);
1023     ADL_UNUSED(format);
1024     return 0;
1025 #endif
1026 
1027 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
1028     sampleCount -= sampleCount % 2; //Avoid even sample requests
1029     if(sampleCount < 0)
1030         return 0;
1031     if(!device)
1032         return 0;
1033 
1034     MidiPlayer *player = GET_MIDI_PLAYER(device);
1035     assert(player);
1036     MidiPlayer::Setup &setup = player->m_setup;
1037 
1038     ssize_t gotten_len = 0;
1039     ssize_t n_periodCountStereo = 512;
1040     //ssize_t n_periodCountPhys = n_periodCountStereo * 2;
1041     int left = sampleCount;
1042     bool hasSkipped = setup.tick_skip_samples_delay > 0;
1043 
1044     while(left > 0)
1045     {
1046         {//
1047             if(setup.delay <= 0.0)
1048                 setup.delay = double(left / 2) / double(setup.PCM_RATE);
1049             const double eat_delay = setup.delay < setup.maxdelay ? setup.delay : setup.maxdelay;
1050             if(hasSkipped)
1051             {
1052                 size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay;
1053                 n_periodCountStereo = samples / 2;
1054             }
1055             else
1056             {
1057                 setup.delay -= eat_delay;
1058                 setup.carry += double(setup.PCM_RATE) * eat_delay;
1059                 n_periodCountStereo = static_cast<ssize_t>(setup.carry);
1060                 setup.carry -= double(n_periodCountStereo);
1061             }
1062 
1063             //if(setup.SkipForward > 0)
1064             //    setup.SkipForward -= 1;
1065             //else
1066             {
1067                 if((player->m_sequencer->positionAtEnd()) && (setup.delay <= 0.0))
1068                     break;//Stop to fetch samples at reaching the song end with disabled loop
1069 
1070                 ssize_t leftSamples = left / 2;
1071                 if(n_periodCountStereo > leftSamples)
1072                 {
1073                     setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2;
1074                     n_periodCountStereo = leftSamples;
1075                 }
1076                 //! Count of stereo samples
1077                 ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
1078                 //! Total count of samples
1079                 ssize_t in_generatedPhys = in_generatedStereo * 2;
1080                 //! Unsigned total sample count
1081                 //fill buffer with zeros
1082                 int32_t *out_buf = player->m_outBuf;
1083                 std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
1084                 Synth &synth = *player->m_synth;
1085                 unsigned int chips = synth.m_numChips;
1086                 if(chips == 1)
1087                     synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
1088                 else/* if(n_periodCountStereo > 0)*/
1089                 {
1090                     /* Generate data from every chip and mix result */
1091                     for(size_t card = 0; card < chips; ++card)
1092                         synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
1093                 }
1094                 /* Process it */
1095                 if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
1096                     return 0;
1097 
1098                 left -= (int)in_generatedPhys;
1099                 gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
1100             }
1101             if(hasSkipped)
1102             {
1103                 setup.tick_skip_samples_delay -= n_periodCountStereo * 2;
1104                 hasSkipped = setup.tick_skip_samples_delay > 0;
1105             }
1106             else
1107                 setup.delay = player->Tick(eat_delay, setup.mindelay);
1108         }//
1109     }
1110 
1111     return static_cast<int>(gotten_len);
1112 #endif //OPNMIDI_DISABLE_MIDI_SEQUENCER
1113 }
1114 
1115 
opn2_generate(struct OPN2_MIDIPlayer * device,int sampleCount,short * out)1116 OPNMIDI_EXPORT int opn2_generate(struct OPN2_MIDIPlayer *device, int sampleCount, short *out)
1117 {
1118     return opn2_generateFormat(device, sampleCount, (OPN2_UInt8 *)out, (OPN2_UInt8 *)(out + 1), &opn2_DefaultAudioFormat);
1119 }
1120 
opn2_generateFormat(struct OPN2_MIDIPlayer * device,int sampleCount,OPN2_UInt8 * out_left,OPN2_UInt8 * out_right,const OPNMIDI_AudioFormat * format)1121 OPNMIDI_EXPORT int opn2_generateFormat(struct OPN2_MIDIPlayer *device, int sampleCount,
1122                                        OPN2_UInt8 *out_left, OPN2_UInt8 *out_right,
1123                                        const OPNMIDI_AudioFormat *format)
1124 {
1125     sampleCount -= sampleCount % 2; //Avoid even sample requests
1126     if(sampleCount < 0)
1127         return 0;
1128     if(!device)
1129         return 0;
1130 
1131     MidiPlayer *player = GET_MIDI_PLAYER(device);
1132     assert(player);
1133     MidiPlayer::Setup &setup = player->m_setup;
1134 
1135     ssize_t gotten_len = 0;
1136     ssize_t n_periodCountStereo = 512;
1137 
1138     int     left = sampleCount;
1139     double  delay = double(sampleCount / 2) / double(setup.PCM_RATE);
1140 
1141     while(left > 0)
1142     {
1143         {//
1144             if(delay <= 0.0)
1145                 delay = double(left / 2) / double(setup.PCM_RATE);
1146             const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
1147             delay -= eat_delay;
1148             setup.carry += double(setup.PCM_RATE) * eat_delay;
1149             n_periodCountStereo = static_cast<ssize_t>(setup.carry);
1150             setup.carry -= double(n_periodCountStereo);
1151 
1152             {
1153                 ssize_t leftSamples = left / 2;
1154                 if(n_periodCountStereo > leftSamples)
1155                     n_periodCountStereo = leftSamples;
1156                 //! Count of stereo samples
1157                 ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
1158                 //! Total count of samples
1159                 ssize_t in_generatedPhys = in_generatedStereo * 2;
1160                 //! Unsigned total sample count
1161                 //fill buffer with zeros
1162                 int32_t *out_buf = player->m_outBuf;
1163                 std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
1164                 Synth &synth = *player->m_synth;
1165                 unsigned int chips = synth.m_numChips;
1166                 if(chips == 1)
1167                     synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
1168                 else/* if(n_periodCountStereo > 0)*/
1169                 {
1170                     /* Generate data from every chip and mix result */
1171                     for(size_t card = 0; card < chips; ++card)
1172                         synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
1173                 }
1174                 /* Process it */
1175                 if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
1176                     return 0;
1177 
1178                 left -= (int)in_generatedPhys;
1179                 gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
1180             }
1181 
1182             player->TickIterators(eat_delay);
1183         }//...
1184     }
1185 
1186     return static_cast<int>(gotten_len);
1187 }
1188 
opn2_tickEvents(struct OPN2_MIDIPlayer * device,double seconds,double granuality)1189 OPNMIDI_EXPORT double opn2_tickEvents(struct OPN2_MIDIPlayer *device, double seconds, double granuality)
1190 {
1191 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
1192     if(!device)
1193         return -1.0;
1194     MidiPlayer *play = GET_MIDI_PLAYER(device);
1195     assert(play);
1196     return play->Tick(seconds, granuality);
1197 #else
1198     ADL_UNUSED(device);
1199     ADL_UNUSED(seconds);
1200     ADL_UNUSED(granuality);
1201     return -1.0;
1202 #endif
1203 }
1204 
opn2_atEnd(struct OPN2_MIDIPlayer * device)1205 OPNMIDI_EXPORT int opn2_atEnd(struct OPN2_MIDIPlayer *device)
1206 {
1207 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
1208     if(!device)
1209         return 1;
1210     MidiPlayer *play = GET_MIDI_PLAYER(device);
1211     assert(play);
1212     return (int)play->m_sequencer->positionAtEnd();
1213 #else
1214     ADL_UNUSED(device);
1215     return 1;
1216 #endif
1217 }
1218 
opn2_trackCount(struct OPN2_MIDIPlayer * device)1219 OPNMIDI_EXPORT size_t opn2_trackCount(struct OPN2_MIDIPlayer *device)
1220 {
1221 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
1222     if(!device)
1223         return 0;
1224     MidiPlayer *play = GET_MIDI_PLAYER(device);
1225     assert(play);
1226     return play->m_sequencer->getTrackCount();
1227 #else
1228     ADL_UNUSED(device);
1229     return 0;
1230 #endif
1231 }
1232 
opn2_setTrackOptions(struct OPN2_MIDIPlayer * device,size_t trackNumber,unsigned trackOptions)1233 OPNMIDI_EXPORT int opn2_setTrackOptions(struct OPN2_MIDIPlayer *device, size_t trackNumber, unsigned trackOptions)
1234 {
1235 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER
1236     if(!device)
1237         return -1;
1238     MidiPlayer *play = GET_MIDI_PLAYER(device);
1239     assert(play);
1240     MidiSequencer &seq = *play->m_sequencer;
1241 
1242     unsigned enableFlag = trackOptions & 3;
1243     trackOptions &= ~3u;
1244 
1245     // handle on/off/solo
1246     switch(enableFlag)
1247     {
1248     default:
1249         break;
1250     case OPNMIDI_TrackOption_On:
1251     case OPNMIDI_TrackOption_Off:
1252         if(!seq.setTrackEnabled(trackNumber, enableFlag == OPNMIDI_TrackOption_On))
1253             return -1;
1254         break;
1255     case OPNMIDI_TrackOption_Solo:
1256         seq.setSoloTrack(trackNumber);
1257         break;
1258     }
1259 
1260     // handle others...
1261     if(trackOptions != 0)
1262         return -1;
1263 
1264     return 0;
1265 
1266 #else
1267     ADL_UNUSED(device);
1268     ADL_UNUSED(trackNumber);
1269     ADL_UNUSED(trackOptions);
1270     return -1;
1271 #endif
1272 }
1273 
opn2_panic(struct OPN2_MIDIPlayer * device)1274 OPNMIDI_EXPORT void opn2_panic(struct OPN2_MIDIPlayer *device)
1275 {
1276     if(!device)
1277         return;
1278     MidiPlayer *play = GET_MIDI_PLAYER(device);
1279     assert(play);
1280     play->realTime_panic();
1281 }
1282 
opn2_rt_resetState(struct OPN2_MIDIPlayer * device)1283 OPNMIDI_EXPORT void opn2_rt_resetState(struct OPN2_MIDIPlayer *device)
1284 {
1285     if(!device)
1286         return;
1287     MidiPlayer *play = GET_MIDI_PLAYER(device);
1288     assert(play);
1289     play->realTime_ResetState();
1290 }
1291 
opn2_rt_noteOn(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 note,OPN2_UInt8 velocity)1292 OPNMIDI_EXPORT int opn2_rt_noteOn(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 note, OPN2_UInt8 velocity)
1293 {
1294     if(!device)
1295         return 0;
1296     MidiPlayer *play = GET_MIDI_PLAYER(device);
1297     assert(play);
1298     return (int)play->realTime_NoteOn(channel, note, velocity);
1299 }
1300 
opn2_rt_noteOff(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 note)1301 OPNMIDI_EXPORT void opn2_rt_noteOff(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 note)
1302 {
1303     if(!device)
1304         return;
1305     MidiPlayer *play = GET_MIDI_PLAYER(device);
1306     assert(play);
1307     play->realTime_NoteOff(channel, note);
1308 }
1309 
opn2_rt_noteAfterTouch(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 note,OPN2_UInt8 atVal)1310 OPNMIDI_EXPORT void opn2_rt_noteAfterTouch(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 note, OPN2_UInt8 atVal)
1311 {
1312     if(!device)
1313         return;
1314     MidiPlayer *play = GET_MIDI_PLAYER(device);
1315     assert(play);
1316     play->realTime_NoteAfterTouch(channel, note, atVal);
1317 }
1318 
opn2_rt_channelAfterTouch(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 atVal)1319 OPNMIDI_EXPORT void opn2_rt_channelAfterTouch(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 atVal)
1320 {
1321     if(!device)
1322         return;
1323     MidiPlayer *play = GET_MIDI_PLAYER(device);
1324     assert(play);
1325     play->realTime_ChannelAfterTouch(channel, atVal);
1326 }
1327 
opn2_rt_controllerChange(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 type,OPN2_UInt8 value)1328 OPNMIDI_EXPORT void opn2_rt_controllerChange(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 type, OPN2_UInt8 value)
1329 {
1330     if(!device)
1331         return;
1332     MidiPlayer *play = GET_MIDI_PLAYER(device);
1333     assert(play);
1334     play->realTime_Controller(channel, type, value);
1335 }
1336 
opn2_rt_patchChange(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 patch)1337 OPNMIDI_EXPORT void opn2_rt_patchChange(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 patch)
1338 {
1339     if(!device)
1340         return;
1341     MidiPlayer *play = GET_MIDI_PLAYER(device);
1342     assert(play);
1343     play->realTime_PatchChange(channel, patch);
1344 }
1345 
opn2_rt_pitchBend(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt16 pitch)1346 OPNMIDI_EXPORT void opn2_rt_pitchBend(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt16 pitch)
1347 {
1348     if(!device)
1349         return;
1350     MidiPlayer *play = GET_MIDI_PLAYER(device);
1351     assert(play);
1352     play->realTime_PitchBend(channel, pitch);
1353 }
1354 
opn2_rt_pitchBendML(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 msb,OPN2_UInt8 lsb)1355 OPNMIDI_EXPORT void opn2_rt_pitchBendML(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 msb, OPN2_UInt8 lsb)
1356 {
1357     if(!device)
1358         return;
1359     MidiPlayer *play = GET_MIDI_PLAYER(device);
1360     assert(play);
1361     play->realTime_PitchBend(channel, msb, lsb);
1362 }
1363 
opn2_rt_bankChangeLSB(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 lsb)1364 OPNMIDI_EXPORT void opn2_rt_bankChangeLSB(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 lsb)
1365 {
1366     if(!device)
1367         return;
1368     MidiPlayer *play = GET_MIDI_PLAYER(device);
1369     assert(play);
1370     play->realTime_BankChangeLSB(channel, lsb);
1371 }
1372 
opn2_rt_bankChangeMSB(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_UInt8 msb)1373 OPNMIDI_EXPORT void opn2_rt_bankChangeMSB(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_UInt8 msb)
1374 {
1375     if(!device)
1376         return;
1377     MidiPlayer *play = GET_MIDI_PLAYER(device);
1378     assert(play);
1379     play->realTime_BankChangeMSB(channel, msb);
1380 }
1381 
opn2_rt_bankChange(struct OPN2_MIDIPlayer * device,OPN2_UInt8 channel,OPN2_SInt16 bank)1382 OPNMIDI_EXPORT void opn2_rt_bankChange(struct OPN2_MIDIPlayer *device, OPN2_UInt8 channel, OPN2_SInt16 bank)
1383 {
1384     if(!device)
1385         return;
1386     MidiPlayer *play = GET_MIDI_PLAYER(device);
1387     assert(play);
1388     play->realTime_BankChange(channel, (uint16_t)bank);
1389 }
1390 
opn2_rt_systemExclusive(struct OPN2_MIDIPlayer * device,const OPN2_UInt8 * msg,size_t size)1391 OPNMIDI_EXPORT int opn2_rt_systemExclusive(struct OPN2_MIDIPlayer *device, const OPN2_UInt8 *msg, size_t size)
1392 {
1393     if(!device)
1394         return -1;
1395     MidiPlayer *play = GET_MIDI_PLAYER(device);
1396     assert(play);
1397     return play->realTime_SysEx(msg, size);
1398 }
1399