1 /*
2  * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
3  *
4  * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
5  * ADLMIDI Library API:   Copyright (c) 2015-2018 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 "adlmidi_private.hpp"
25 
26 #ifdef ADLMIDI_HW_OPL
27 #define MaxChips 1
28 #define MaxChips_STR "1" //Why not just "#MaxCards" ? Watcom fails to pass this with "syntax error" :-P
29 #else
30 #define MaxChips 100
31 #define MaxChips_STR "100"
32 #endif
33 
34 /* Unify MIDI player casting and interface between ADLMIDI and OPNMIDI */
35 #define GET_MIDI_PLAYER(device) reinterpret_cast<MIDIplay *>((device)->adl_midiPlayer)
36 typedef MIDIplay MidiPlayer;
37 
38 static ADL_Version adl_version = {
39     ADLMIDI_VERSION_MAJOR,
40     ADLMIDI_VERSION_MINOR,
41     ADLMIDI_VERSION_PATCHLEVEL
42 };
43 
44 static const ADLMIDI_AudioFormat adl_DefaultAudioFormat =
45 {
46     ADLMIDI_SampleType_S16,
47     sizeof(int16_t),
48     2 * sizeof(int16_t),
49 };
50 
51 /*---------------------------EXPORTS---------------------------*/
52 
adl_init(long sample_rate)53 ADLMIDI_EXPORT struct ADL_MIDIPlayer *adl_init(long sample_rate)
54 {
55     ADL_MIDIPlayer *midi_device;
56     midi_device = (ADL_MIDIPlayer *)malloc(sizeof(ADL_MIDIPlayer));
57     if(!midi_device)
58     {
59         ADLMIDI_ErrorString = "Can't initialize ADLMIDI: out of memory!";
60         return NULL;
61     }
62 
63     MIDIplay *player = new MIDIplay(static_cast<unsigned long>(sample_rate));
64     if(!player)
65     {
66         free(midi_device);
67         ADLMIDI_ErrorString = "Can't initialize ADLMIDI: out of memory!";
68         return NULL;
69     }
70     midi_device->adl_midiPlayer = player;
71     adlRefreshNumCards(midi_device);
72     return midi_device;
73 }
74 
adl_close(struct ADL_MIDIPlayer * device)75 ADLMIDI_EXPORT void adl_close(struct ADL_MIDIPlayer *device)
76 {
77     if(!device)
78         return;
79     MIDIplay * play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
80     if(play)
81         delete play;
82     device->adl_midiPlayer = NULL;
83     free(device);
84     device = NULL;
85 }
86 
adl_setCallback(ADL_MIDIPlayer * device,void (* AdlMidiCallback)(void))87 ADLMIDI_EXPORT void adl_setCallback(ADL_MIDIPlayer *device, void (*AdlMidiCallback)(void)) {
88     MidiPlayer *play = GET_MIDI_PLAYER(device);
89     if(play) {
90         MidiSequencer &seq = play->m_sequencer;
91         seq.MidiCallback = AdlMidiCallback;
92     }
93 }
94 
adl_setDeviceIdentifier(ADL_MIDIPlayer * device,unsigned id)95 ADLMIDI_EXPORT int adl_setDeviceIdentifier(ADL_MIDIPlayer *device, unsigned id)
96 {
97     if(!device || id > 0x0f)
98         return -1;
99     MidiPlayer *play = GET_MIDI_PLAYER(device);
100     if(!play)
101         return -1;
102     play->setDeviceId(static_cast<uint8_t>(id));
103     return 0;
104 }
105 
adl_setNumChips(ADL_MIDIPlayer * device,int numChips)106 ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numChips)
107 {
108     if(device == NULL)
109         return -2;
110 
111     MidiPlayer *play = GET_MIDI_PLAYER(device);
112 #ifdef ADLMIDI_HW_OPL
113     ADL_UNUSED(numChips);
114     play->m_setup.numChips = 1;
115 #else
116     play->m_setup.numChips = static_cast<unsigned int>(numChips);
117 #endif
118     if(play->m_setup.numChips < 1 || play->m_setup.numChips > MaxChips)
119     {
120         play->setErrorString("number of chips may only be 1.." MaxChips_STR ".\n");
121         return -1;
122     }
123 
124     play->m_synth.m_numChips = play->m_setup.numChips;
125     adl_reset(device);
126 
127     return adlRefreshNumCards(device);
128 }
129 
adl_getNumChips(struct ADL_MIDIPlayer * device)130 ADLMIDI_EXPORT int adl_getNumChips(struct ADL_MIDIPlayer *device)
131 {
132     if(device == NULL)
133         return -2;
134     MidiPlayer *play = GET_MIDI_PLAYER(device);
135     if(play)
136         return (int)play->m_setup.numChips;
137     return -2;
138 }
139 
adl_setBank(ADL_MIDIPlayer * device,int bank)140 ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
141 {
142 #ifdef DISABLE_EMBEDDED_BANKS
143     ADL_UNUSED(bank);
144     MidiPlayer *play = GET_MIDI_PLAYER(device);
145     play->setErrorString("This build of libADLMIDI has no embedded banks. "
146                          "Please load banks by using adl_openBankFile() or "
147                          "adl_openBankData() functions instead of adl_setBank().");
148     return -1;
149 #else
150     const uint32_t NumBanks = static_cast<uint32_t>(maxAdlBanks());
151     int32_t bankno = bank;
152 
153     if(bankno < 0)
154         bankno = 0;
155 
156     MidiPlayer *play = GET_MIDI_PLAYER(device);
157     if(static_cast<uint32_t>(bankno) >= NumBanks)
158     {
159         char errBuf[150];
160         snprintf(errBuf, 150, "Embedded bank number may only be 0..%u!\n", static_cast<unsigned int>(NumBanks - 1));
161         play->setErrorString(errBuf);
162         return -1;
163     }
164 
165     play->m_setup.bankId = static_cast<uint32_t>(bankno);
166     play->m_synth.setEmbeddedBank(play->m_setup.bankId);
167     play->applySetup();
168 
169     return adlRefreshNumCards(device);
170 #endif
171 }
172 
adl_getBanksCount()173 ADLMIDI_EXPORT int adl_getBanksCount()
174 {
175 #ifndef DISABLE_EMBEDDED_BANKS
176     return maxAdlBanks();
177 #else
178     return 0;
179 #endif
180 }
181 
adl_getBankNames()182 ADLMIDI_EXPORT const char *const *adl_getBankNames()
183 {
184 #ifndef DISABLE_EMBEDDED_BANKS
185     return banknames;
186 #else
187     return NULL;
188 #endif
189 }
190 
adl_reserveBanks(ADL_MIDIPlayer * device,unsigned banks)191 ADLMIDI_EXPORT int adl_reserveBanks(ADL_MIDIPlayer *device, unsigned banks)
192 {
193     if(!device)
194         return -1;
195     MidiPlayer *play = GET_MIDI_PLAYER(device);
196     OPL3::BankMap &map = play->m_synth.m_insBanks;
197     map.reserve(banks);
198     return (int)map.capacity();
199 }
200 
adl_getBank(ADL_MIDIPlayer * device,const ADL_BankId * idp,int flags,ADL_Bank * bank)201 ADLMIDI_EXPORT int adl_getBank(ADL_MIDIPlayer *device, const ADL_BankId *idp, int flags, ADL_Bank *bank)
202 {
203     if(!device || !idp || !bank)
204         return -1;
205 
206     ADL_BankId id = *idp;
207     if(id.lsb > 127 || id.msb > 127 || id.percussive > 1)
208         return -1;
209     size_t idnumber = ((id.msb << 8) | id.lsb | (id.percussive ? size_t(OPL3::PercussionTag) : 0));
210 
211     MidiPlayer *play = GET_MIDI_PLAYER(device);
212     OPL3::BankMap &map = play->m_synth.m_insBanks;
213 
214     OPL3::BankMap::iterator it;
215     if(!(flags & ADLMIDI_Bank_Create))
216     {
217         it = map.find(idnumber);
218         if(it == map.end())
219             return -1;
220     }
221     else
222     {
223         std::pair<size_t, OPL3::Bank> value;
224         value.first = idnumber;
225         memset(&value.second, 0, sizeof(value.second));
226         for (unsigned i = 0; i < 128; ++i)
227             value.second.ins[i].flags = adlinsdata::Flag_NoSound;
228 
229         std::pair<OPL3::BankMap::iterator, bool> ir;
230         if(flags & ADLMIDI_Bank_CreateRt)
231         {
232             ir = map.insert(value, OPL3::BankMap::do_not_expand_t());
233             if(ir.first == map.end())
234                 return -1;
235         }
236         else
237             ir = map.insert(value);
238         it = ir.first;
239     }
240 
241     it.to_ptrs(bank->pointer);
242     return 0;
243 }
244 
adl_getBankId(ADL_MIDIPlayer * device,const ADL_Bank * bank,ADL_BankId * id)245 ADLMIDI_EXPORT int adl_getBankId(ADL_MIDIPlayer *device, const ADL_Bank *bank, ADL_BankId *id)
246 {
247     if(!device || !bank)
248         return -1;
249 
250     OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
251     OPL3::BankMap::key_type idnumber = it->first;
252     id->msb = (idnumber >> 8) & 127;
253     id->lsb = idnumber & 127;
254     id->percussive = (idnumber & OPL3::PercussionTag) ? 1 : 0;
255     return 0;
256 }
257 
adl_removeBank(ADL_MIDIPlayer * device,ADL_Bank * bank)258 ADLMIDI_EXPORT int adl_removeBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
259 {
260     if(!device || !bank)
261         return -1;
262 
263     MidiPlayer *play = GET_MIDI_PLAYER(device);
264     OPL3::BankMap &map = play->m_synth.m_insBanks;
265     OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
266     size_t size = map.size();
267     map.erase(it);
268     return (map.size() != size) ? 0 : -1;
269 }
270 
adl_getFirstBank(ADL_MIDIPlayer * device,ADL_Bank * bank)271 ADLMIDI_EXPORT int adl_getFirstBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
272 {
273     if(!device)
274         return -1;
275 
276     MidiPlayer *play = GET_MIDI_PLAYER(device);
277     OPL3::BankMap &map = play->m_synth.m_insBanks;
278 
279     OPL3::BankMap::iterator it = map.begin();
280     if(it == map.end())
281         return -1;
282 
283     it.to_ptrs(bank->pointer);
284     return 0;
285 }
286 
adl_getNextBank(ADL_MIDIPlayer * device,ADL_Bank * bank)287 ADLMIDI_EXPORT int adl_getNextBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
288 {
289     if(!device)
290         return -1;
291 
292     MidiPlayer *play = GET_MIDI_PLAYER(device);
293     OPL3::BankMap &map = play->m_synth.m_insBanks;
294 
295     OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
296     if(++it == map.end())
297         return -1;
298 
299     it.to_ptrs(bank->pointer);
300     return 0;
301 }
302 
adl_getInstrument(ADL_MIDIPlayer * device,const ADL_Bank * bank,unsigned index,ADL_Instrument * ins)303 ADLMIDI_EXPORT int adl_getInstrument(ADL_MIDIPlayer *device, const ADL_Bank *bank, unsigned index, ADL_Instrument *ins)
304 {
305     if(!device || !bank || index > 127 || !ins)
306         return 1;
307 
308     OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
309     cvt_FMIns_to_ADLI(*ins, it->second.ins[index]);
310     ins->version = 0;
311     return 0;
312 }
313 
adl_setInstrument(ADL_MIDIPlayer * device,ADL_Bank * bank,unsigned index,const ADL_Instrument * ins)314 ADLMIDI_EXPORT int adl_setInstrument(ADL_MIDIPlayer *device, ADL_Bank *bank, unsigned index, const ADL_Instrument *ins)
315 {
316     if(!device || !bank || index > 127 || !ins)
317         return 1;
318 
319     if(ins->version != 0)
320         return 1;
321 
322     OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
323     cvt_ADLI_to_FMIns(it->second.ins[index], *ins);
324     return 0;
325 }
326 
adl_loadEmbeddedBank(struct ADL_MIDIPlayer * device,ADL_Bank * bank,int num)327 ADLMIDI_EXPORT int adl_loadEmbeddedBank(struct ADL_MIDIPlayer *device, ADL_Bank *bank, int num)
328 {
329     if(!device)
330         return -1;
331     MidiPlayer *play = GET_MIDI_PLAYER(device);
332     if (!play)
333         return -1;
334 
335 #ifdef DISABLE_EMBEDDED_BANKS
336     ADL_UNUSED(bank);
337     ADL_UNUSED(num);
338     play->setErrorString("This build of libADLMIDI has no embedded banks. "
339                          "Please load banks by using adl_openBankFile() or "
340                          "adl_openBankData() functions instead of adl_loadEmbeddedBank().");
341     return -1;
342 #else
343     if(num < 0 || num >= maxAdlBanks())
344         return -1;
345 
346     OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
347     size_t id = it->first;
348 
349     for (unsigned i = 0; i < 128; ++i) {
350         size_t insno = i + ((id & OPL3::PercussionTag) ? 128 : 0);
351         size_t adlmeta = ::banks[num][insno];
352         it->second.ins[i] = adlinsdata2(::adlins[adlmeta]);
353     }
354     return 0;
355 #endif
356 }
357 
adl_setNumFourOpsChn(ADL_MIDIPlayer * device,int ops4)358 ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4)
359 {
360     if(!device)
361         return -1;
362     MidiPlayer *play = GET_MIDI_PLAYER(device);
363     if((unsigned int)ops4 > 6 * play->m_setup.numChips)
364     {
365         char errBuff[250];
366         snprintf(errBuff, 250, "number of four-op channels may only be 0..%u when %u OPL3 cards are used.\n", (6 * (play->m_setup.numChips)), play->m_setup.numChips);
367         play->setErrorString(errBuff);
368         return -1;
369     }
370 
371     play->m_setup.numFourOps = static_cast<unsigned int>(ops4);
372     play->m_synth.m_numFourOps = play->m_setup.numFourOps;
373     play->m_synth.updateChannelCategories();
374 
375     return 0; //adlRefreshNumCards(device);
376 }
377 
adl_getNumFourOpsChn(struct ADL_MIDIPlayer * device)378 ADLMIDI_EXPORT int adl_getNumFourOpsChn(struct ADL_MIDIPlayer *device)
379 {
380     if(!device)
381         return -1;
382     MidiPlayer *play = GET_MIDI_PLAYER(device);
383     if(play)
384         return (int)play->m_setup.numFourOps;
385     return -1;
386 }
387 
adl_setPercMode(ADL_MIDIPlayer * device,int percmod)388 ADLMIDI_EXPORT void adl_setPercMode(ADL_MIDIPlayer *device, int percmod)
389 {
390     if(!device) return;
391     MidiPlayer *play = GET_MIDI_PLAYER(device);
392     play->m_setup.rhythmMode = percmod;
393     play->m_synth.m_rhythmMode   = play->m_setup.rhythmMode < 0 ?
394                               (play->m_synth.m_insBankSetup.adLibPercussions) :
395                               (play->m_setup.rhythmMode != 0);
396     play->m_synth.updateChannelCategories();
397 }
398 
adl_setHVibrato(ADL_MIDIPlayer * device,int hvibro)399 ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro)
400 {
401     if(!device) return;
402     MidiPlayer *play = GET_MIDI_PLAYER(device);
403     play->m_setup.deepVibratoMode = hvibro;
404     play->m_synth.m_deepVibratoMode     = play->m_setup.deepVibratoMode < 0 ?
405                                     play->m_synth.m_insBankSetup.deepVibrato :
406                                     (play->m_setup.deepVibratoMode != 0);
407     play->m_synth.commitDeepFlags();
408 }
409 
adl_setHTremolo(ADL_MIDIPlayer * device,int htremo)410 ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo)
411 {
412     if(!device) return;
413     MidiPlayer *play = GET_MIDI_PLAYER(device);
414     play->m_setup.deepTremoloMode = htremo;
415     play->m_synth.m_deepTremoloMode     = play->m_setup.deepTremoloMode < 0 ?
416                                     play->m_synth.m_insBankSetup.deepTremolo :
417                                     (play->m_setup.deepTremoloMode != 0);
418     play->m_synth.commitDeepFlags();
419 }
420 
adl_setScaleModulators(ADL_MIDIPlayer * device,int smod)421 ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod)
422 {
423     if(!device)
424         return;
425     MidiPlayer *play = GET_MIDI_PLAYER(device);
426     if(!play)
427         return;
428     play->m_setup.scaleModulators = smod;
429     play->m_synth.m_scaleModulators     = play->m_setup.scaleModulators < 0 ?
430                                     play->m_synth.m_insBankSetup.scaleModulators :
431                                     (play->m_setup.scaleModulators != 0);
432 }
433 
adl_setFullRangeBrightness(struct ADL_MIDIPlayer * device,int fr_brightness)434 ADLMIDI_EXPORT void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, int fr_brightness)
435 {
436     if(!device)
437         return;
438     MidiPlayer *play = GET_MIDI_PLAYER(device);
439     if(!play)
440         return;
441     play->m_setup.fullRangeBrightnessCC74 = (fr_brightness != 0);
442 }
443 
adl_setLoopEnabled(ADL_MIDIPlayer * device,int loopEn)444 ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn)
445 {
446     if(!device)
447         return;
448     MidiPlayer *play = GET_MIDI_PLAYER(device);
449     if(!play)
450         return;
451 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
452     play->m_sequencer.setLoopEnabled(loopEn != 0);
453 #else
454     ADL_UNUSED(loopEn);
455 #endif
456 }
457 
458 /* !!!DEPRECATED!!! */
adl_setLogarithmicVolumes(struct ADL_MIDIPlayer * device,int logvol)459 ADLMIDI_EXPORT void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int logvol)
460 {
461     if(!device)
462         return;
463     MidiPlayer *play = GET_MIDI_PLAYER(device);
464     if(!play)
465         return;
466     play->m_setup.logarithmicVolumes = (logvol != 0);
467     if(play->m_setup.logarithmicVolumes)
468         play->m_synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3);
469     else
470         play->m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(play->m_synth.m_volumeScale));
471 }
472 
adl_setVolumeRangeModel(struct ADL_MIDIPlayer * device,int volumeModel)473 ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int volumeModel)
474 {
475     if(!device)
476         return;
477     MidiPlayer *play = GET_MIDI_PLAYER(device);
478     if(!play)
479         return;
480     play->m_setup.volumeScaleModel = volumeModel;
481     if(play->m_setup.volumeScaleModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
482         play->m_synth.m_volumeScale = (OPL3::VolumesScale)play->m_synth.m_insBankSetup.volumeModel;
483     else
484         play->m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(volumeModel));
485 }
486 
adl_openBankFile(struct ADL_MIDIPlayer * device,const char * filePath)487 ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath)
488 {
489     if(device && device->adl_midiPlayer)
490     {
491         MidiPlayer *play = GET_MIDI_PLAYER(device);
492         play->m_setup.tick_skip_samples_delay = 0;
493         if(!play->LoadBank(filePath))
494         {
495             std::string err = play->getErrorString();
496             if(err.empty())
497                 play->setErrorString("ADL MIDI: Can't load file");
498             return -1;
499         }
500         else return adlRefreshNumCards(device);
501     }
502 
503     ADLMIDI_ErrorString = "Can't load file: ADLMIDI is not initialized";
504     return -1;
505 }
506 
adl_openBankData(struct ADL_MIDIPlayer * device,const void * mem,unsigned long size)507 ADLMIDI_EXPORT int adl_openBankData(struct ADL_MIDIPlayer *device, const void *mem, unsigned long size)
508 {
509     if(device && device->adl_midiPlayer)
510     {
511         MidiPlayer *play = GET_MIDI_PLAYER(device);
512         if(!play)
513             return -1;
514         play->m_setup.tick_skip_samples_delay = 0;
515         if(!play->LoadBank(mem, static_cast<size_t>(size)))
516         {
517             std::string err = play->getErrorString();
518             if(err.empty())
519                 play->setErrorString("ADL MIDI: Can't load data from memory");
520             return -1;
521         }
522         else return adlRefreshNumCards(device);
523     }
524 
525     ADLMIDI_ErrorString = "Can't load file: ADL MIDI is not initialized";
526     return -1;
527 }
528 
adl_openFile(ADL_MIDIPlayer * device,const char * filePath)529 ADLMIDI_EXPORT int adl_openFile(ADL_MIDIPlayer *device, const char *filePath)
530 {
531     if(device && device->adl_midiPlayer)
532     {
533         MidiPlayer *play = GET_MIDI_PLAYER(device);
534         if(!play)
535             return -1;
536 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
537         play->m_setup.tick_skip_samples_delay = 0;
538         if(!play->LoadMIDI(filePath))
539         {
540             std::string err = play->getErrorString();
541             if(err.empty())
542                 play->setErrorString("ADL MIDI: Can't load file");
543             return -1;
544         }
545         else return 0;
546 #else
547         ADL_UNUSED(filePath);
548         play->setErrorString("ADLMIDI: MIDI Sequencer is not supported in this build of library!");
549         return -1;
550 #endif //ADLMIDI_DISABLE_MIDI_SEQUENCER
551     }
552 
553     ADLMIDI_ErrorString = "Can't load file: ADL MIDI is not initialized";
554     return -1;
555 }
556 
adl_openData(ADL_MIDIPlayer * device,const void * mem,unsigned long size)557 ADLMIDI_EXPORT int adl_openData(ADL_MIDIPlayer *device, const void *mem, unsigned long size)
558 {
559     if(device && device->adl_midiPlayer)
560     {
561         MidiPlayer *play = GET_MIDI_PLAYER(device);
562         if(!play)
563             return -1;
564 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
565         play->m_setup.tick_skip_samples_delay = 0;
566         if(!play->LoadMIDI(mem, static_cast<size_t>(size)))
567         {
568             std::string err = play->getErrorString();
569             if(err.empty())
570                 play->setErrorString("ADL MIDI: Can't load data from memory");
571             return -1;
572         }
573         else return 0;
574 #else
575         ADL_UNUSED(mem);
576         ADL_UNUSED(size);
577         play->setErrorString("ADLMIDI: MIDI Sequencer is not supported in this build of library!");
578         return -1;
579 #endif //ADLMIDI_DISABLE_MIDI_SEQUENCER
580     }
581     ADLMIDI_ErrorString = "Can't load file: ADL MIDI is not initialized";
582     return -1;
583 }
584 
585 
adl_emulatorName()586 ADLMIDI_EXPORT const char *adl_emulatorName()
587 {
588     return "<adl_emulatorName() is deprecated! Use adl_chipEmulatorName() instead!>";
589 }
590 
adl_chipEmulatorName(struct ADL_MIDIPlayer * device)591 ADLMIDI_EXPORT const char *adl_chipEmulatorName(struct ADL_MIDIPlayer *device)
592 {
593     if(device)
594     {
595 #ifndef ADLMIDI_HW_OPL
596         MidiPlayer *play = GET_MIDI_PLAYER(device);
597         if(play && !play->m_synth.m_chips.empty())
598             return play->m_synth.m_chips[0]->emulatorName();
599         #else
600         return "Hardware OPL3 chip on 0x330";
601 #endif
602     }
603     return "Unknown";
604 }
605 
adl_switchEmulator(struct ADL_MIDIPlayer * device,int emulator)606 ADLMIDI_EXPORT int adl_switchEmulator(struct ADL_MIDIPlayer *device, int emulator)
607 {
608     if(device)
609     {
610         MidiPlayer *play = GET_MIDI_PLAYER(device);
611         assert(play);
612         if(!play)
613             return -1;
614         if((emulator >= 0) && (emulator < ADLMIDI_EMU_end))
615         {
616             play->m_setup.emulator = emulator;
617             adl_reset(device);
618             return 0;
619         }
620         play->setErrorString("OPL3 MIDI: Unknown emulation core!");
621     }
622     return -1;
623 }
624 
625 
adl_setRunAtPcmRate(ADL_MIDIPlayer * device,int enabled)626 ADLMIDI_EXPORT int adl_setRunAtPcmRate(ADL_MIDIPlayer *device, int enabled)
627 {
628     if(device)
629     {
630         MidiPlayer *play = GET_MIDI_PLAYER(device);
631         if(play)
632         {
633             play->m_setup.runAtPcmRate = (enabled != 0);
634             adl_reset(device);
635             return 0;
636         }
637     }
638     return -1;
639 }
640 
641 
adl_linkedLibraryVersion()642 ADLMIDI_EXPORT const char *adl_linkedLibraryVersion()
643 {
644 #if !defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
645     return ADLMIDI_VERSION;
646 #else
647     return ADLMIDI_VERSION " (HQ)";
648 #endif
649 }
650 
adl_linkedVersion()651 ADLMIDI_EXPORT const ADL_Version *adl_linkedVersion()
652 {
653     return &adl_version;
654 }
655 
adl_errorString()656 ADLMIDI_EXPORT const char *adl_errorString()
657 {
658     return ADLMIDI_ErrorString.c_str();
659 }
660 
adl_errorInfo(struct ADL_MIDIPlayer * device)661 ADLMIDI_EXPORT const char *adl_errorInfo(struct ADL_MIDIPlayer *device)
662 {
663     if(!device)
664         return adl_errorString();
665     MidiPlayer *play = GET_MIDI_PLAYER(device);
666     if(!play)
667         return adl_errorString();
668     return play->getErrorString().c_str();
669 }
670 
adl_getMusicTitle(struct ADL_MIDIPlayer * device)671 ADLMIDI_EXPORT const char *adl_getMusicTitle(struct ADL_MIDIPlayer *device)
672 {
673     return adl_metaMusicTitle(device);
674 }
675 
adl_reset(struct ADL_MIDIPlayer * device)676 ADLMIDI_EXPORT void adl_reset(struct ADL_MIDIPlayer *device)
677 {
678     if(!device)
679         return;
680     MidiPlayer *play = GET_MIDI_PLAYER(device);
681     play->m_setup.tick_skip_samples_delay = 0;
682     play->m_synth.m_runAtPcmRate = play->m_setup.runAtPcmRate;
683     play->m_synth.reset(play->m_setup.emulator, play->m_setup.PCM_RATE, play);
684     play->m_chipChannels.clear();
685     play->m_chipChannels.resize((size_t)play->m_synth.m_numChannels);
686     play->resetMIDI();
687 }
688 
adl_totalTimeLength(struct ADL_MIDIPlayer * device)689 ADLMIDI_EXPORT double adl_totalTimeLength(struct ADL_MIDIPlayer *device)
690 {
691 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
692     if(!device)
693         return -1.0;
694     MidiPlayer *play = GET_MIDI_PLAYER(device);
695     if(!play)
696         return -1.0;
697     return play->m_sequencer.timeLength();
698 #else
699     ADL_UNUSED(device);
700     return -1.0;
701 #endif
702 }
703 
adl_loopStartTime(struct ADL_MIDIPlayer * device)704 ADLMIDI_EXPORT double adl_loopStartTime(struct ADL_MIDIPlayer *device)
705 {
706 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
707     if(!device)
708         return -1.0;
709     MidiPlayer *play = GET_MIDI_PLAYER(device);
710     if(!play)
711         return -1.0;
712     return play->m_sequencer.getLoopStart();
713 #else
714     ADL_UNUSED(device);
715     return -1.0;
716 #endif
717 }
718 
adl_loopEndTime(struct ADL_MIDIPlayer * device)719 ADLMIDI_EXPORT double adl_loopEndTime(struct ADL_MIDIPlayer *device)
720 {
721 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
722     if(!device)
723         return -1.0;
724     MidiPlayer *play = GET_MIDI_PLAYER(device);
725     if(!play)
726         return -1.0;
727     return play->m_sequencer.getLoopEnd();
728 #else
729     ADL_UNUSED(device);
730     return -1.0;
731 #endif
732 }
733 
adl_positionTell(struct ADL_MIDIPlayer * device)734 ADLMIDI_EXPORT double adl_positionTell(struct ADL_MIDIPlayer *device)
735 {
736 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
737     if(!device)
738         return -1.0;
739     MidiPlayer *play = GET_MIDI_PLAYER(device);
740     if(!play)
741         return -1.0;
742     return play->m_sequencer.tell();
743 #else
744     ADL_UNUSED(device);
745     return -1.0;
746 #endif
747 }
748 
adl_positionSeek(struct ADL_MIDIPlayer * device,double seconds)749 ADLMIDI_EXPORT void adl_positionSeek(struct ADL_MIDIPlayer *device, double seconds)
750 {
751 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
752     if(seconds < 0.0)
753         return;//Seeking negative position is forbidden! :-P
754     if(!device)
755         return;
756     MidiPlayer *play = GET_MIDI_PLAYER(device);
757     if(!play)
758         return;
759     play->realTime_panic();
760     play->m_setup.delay = play->m_sequencer.seek(seconds, play->m_setup.mindelay);
761     play->m_setup.carry = 0.0;
762 #else
763     ADL_UNUSED(device);
764     ADL_UNUSED(seconds);
765 #endif
766 }
767 
adl_positionRewind(struct ADL_MIDIPlayer * device)768 ADLMIDI_EXPORT void adl_positionRewind(struct ADL_MIDIPlayer *device)
769 {
770 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
771     if(!device)
772         return;
773     MidiPlayer *play = GET_MIDI_PLAYER(device);
774     if(!play)
775         return;
776     play->realTime_panic();
777     play->m_sequencer.rewind();
778 #else
779     ADL_UNUSED(device);
780 #endif
781 }
782 
adl_setTempo(struct ADL_MIDIPlayer * device,double tempo)783 ADLMIDI_EXPORT void adl_setTempo(struct ADL_MIDIPlayer *device, double tempo)
784 {
785 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
786     if(!device || (tempo <= 0.0))
787         return;
788     MidiPlayer *play = GET_MIDI_PLAYER(device);
789     if(!play)
790         return;
791     play->m_sequencer.setTempo(tempo);
792 #else
793     ADL_UNUSED(device);
794     ADL_UNUSED(tempo);
795 #endif
796 }
797 
798 
adl_describeChannels(struct ADL_MIDIPlayer * device,char * str,char * attr,size_t size)799 ADLMIDI_EXPORT int adl_describeChannels(struct ADL_MIDIPlayer *device, char *str, char *attr, size_t size)
800 {
801     if(!device)
802         return -1;
803     MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
804     if(!play)
805         return -1;
806     play->describeChannels(str, attr, size);
807     return 0;
808 }
809 
810 
adl_metaMusicTitle(struct ADL_MIDIPlayer * device)811 ADLMIDI_EXPORT const char *adl_metaMusicTitle(struct ADL_MIDIPlayer *device)
812 {
813 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
814     if(!device)
815         return "";
816     MidiPlayer *play = GET_MIDI_PLAYER(device);
817     if(!play)
818         return "";
819     return play->m_sequencer.getMusicTitle().c_str();
820 #else
821     ADL_UNUSED(device);
822     return "";
823 #endif
824 }
825 
826 
adl_metaMusicCopyright(struct ADL_MIDIPlayer * device)827 ADLMIDI_EXPORT const char *adl_metaMusicCopyright(struct ADL_MIDIPlayer *device)
828 {
829 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
830     if(!device)
831         return "";
832     MidiPlayer *play = GET_MIDI_PLAYER(device);
833     if(!play)
834         return "";
835     return play->m_sequencer.getMusicCopyright().c_str();
836 #else
837     ADL_UNUSED(device);
838     return "";
839 #endif
840 }
841 
adl_metaTrackTitleCount(struct ADL_MIDIPlayer * device)842 ADLMIDI_EXPORT size_t adl_metaTrackTitleCount(struct ADL_MIDIPlayer *device)
843 {
844 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
845     if(!device)
846         return 0;
847     MidiPlayer *play = GET_MIDI_PLAYER(device);
848     if(!play)
849         return 0;
850     return play->m_sequencer.getTrackTitles().size();
851 #else
852     ADL_UNUSED(device);
853     return 0;
854 #endif
855 }
856 
adl_metaTrackTitle(struct ADL_MIDIPlayer * device,size_t index)857 ADLMIDI_EXPORT const char *adl_metaTrackTitle(struct ADL_MIDIPlayer *device, size_t index)
858 {
859 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
860     if(!device)
861         return "";
862     MidiPlayer *play = GET_MIDI_PLAYER(device);
863     const std::vector<std::string> &titles = play->m_sequencer.getTrackTitles();
864     if(index >= titles.size())
865         return "INVALID";
866     return titles[index].c_str();
867 #else
868     ADL_UNUSED(device);
869     ADL_UNUSED(index);
870     return "NOT SUPPORTED";
871 #endif
872 }
873 
874 
adl_metaMarkerCount(struct ADL_MIDIPlayer * device)875 ADLMIDI_EXPORT size_t adl_metaMarkerCount(struct ADL_MIDIPlayer *device)
876 {
877 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
878     if(!device)
879         return 0;
880     MidiPlayer *play = GET_MIDI_PLAYER(device);
881     if(!play)
882         return 0;
883     return play->m_sequencer.getMarkers().size();
884 #else
885     ADL_UNUSED(device);
886     return 0;
887 #endif
888 }
889 
adl_metaMarker(struct ADL_MIDIPlayer * device,size_t index)890 ADLMIDI_EXPORT Adl_MarkerEntry adl_metaMarker(struct ADL_MIDIPlayer *device, size_t index)
891 {
892     struct Adl_MarkerEntry marker;
893 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
894     MidiPlayer *play = GET_MIDI_PLAYER(device);
895     const std::vector<MidiSequencer::MIDI_MarkerEntry> &markers = play->m_sequencer.getMarkers();
896     if(!device || !play || (index >= markers.size()))
897     {
898         marker.label = "INVALID";
899         marker.pos_time = 0.0;
900         marker.pos_ticks = 0;
901         return marker;
902     }
903     else
904     {
905         const MidiSequencer::MIDI_MarkerEntry &mk = markers[index];
906         marker.label = mk.label.c_str();
907         marker.pos_time = mk.pos_time;
908         marker.pos_ticks = (unsigned long)mk.pos_ticks;
909     }
910 #else
911     ADL_UNUSED(device);
912     ADL_UNUSED(index);
913     marker.label = "NOT SUPPORTED";
914     marker.pos_time = 0.0;
915     marker.pos_ticks = 0;
916 #endif
917     return marker;
918 }
919 
adl_setRawEventHook(struct ADL_MIDIPlayer * device,ADL_RawEventHook rawEventHook,void * userData)920 ADLMIDI_EXPORT void adl_setRawEventHook(struct ADL_MIDIPlayer *device, ADL_RawEventHook rawEventHook, void *userData)
921 {
922 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
923     if(!device)
924         return;
925     MidiPlayer *play = GET_MIDI_PLAYER(device);
926     play->m_sequencerInterface.onEvent = rawEventHook;
927     play->m_sequencerInterface.onEvent_userData = userData;
928 #else
929     ADL_UNUSED(device);
930     ADL_UNUSED(rawEventHook);
931     ADL_UNUSED(userData);
932 #endif
933 }
934 
935 /* Set note hook */
adl_setNoteHook(struct ADL_MIDIPlayer * device,ADL_NoteHook noteHook,void * userData)936 ADLMIDI_EXPORT void adl_setNoteHook(struct ADL_MIDIPlayer *device, ADL_NoteHook noteHook, void *userData)
937 {
938     if(!device)
939         return;
940     MidiPlayer *play = GET_MIDI_PLAYER(device);
941     play->hooks.onNote = noteHook;
942     play->hooks.onNote_userData = userData;
943 }
944 
945 /* Set debug message hook */
adl_setDebugMessageHook(struct ADL_MIDIPlayer * device,ADL_DebugMessageHook debugMessageHook,void * userData)946 ADLMIDI_EXPORT void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_DebugMessageHook debugMessageHook, void *userData)
947 {
948     if(!device)
949         return;
950     MidiPlayer *play = GET_MIDI_PLAYER(device);
951     play->hooks.onDebugMessage = debugMessageHook;
952     play->hooks.onDebugMessage_userData = userData;
953 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
954     play->m_sequencerInterface.onDebugMessage = debugMessageHook;
955     play->m_sequencerInterface.onDebugMessage_userData = userData;
956 #endif
957 }
958 
959 #ifndef ADLMIDI_HW_OPL
960 
961 #   ifndef __WATCOMC__
962 template <class Dst>
CopySamplesRaw(ADL_UInt8 * dstLeft,ADL_UInt8 * dstRight,const int32_t * src,size_t frameCount,unsigned sampleOffset)963 static void CopySamplesRaw(ADL_UInt8 *dstLeft, ADL_UInt8 *dstRight, const int32_t *src,
964                            size_t frameCount, unsigned sampleOffset)
965 {
966     for(size_t i = 0; i < frameCount; ++i) {
967         *(Dst *)(dstLeft + (i * sampleOffset)) = src[2 * i];
968         *(Dst *)(dstRight + (i * sampleOffset)) = src[(2 * i) + 1];
969     }
970 }
971 
972 template <class Dst, class Ret>
CopySamplesTransformed(ADL_UInt8 * dstLeft,ADL_UInt8 * dstRight,const int32_t * src,size_t frameCount,unsigned sampleOffset,Ret (& transform)(int32_t))973 static void CopySamplesTransformed(ADL_UInt8 *dstLeft, ADL_UInt8 *dstRight, const int32_t *src,
974                                    size_t frameCount, unsigned sampleOffset,
975                                    Ret(&transform)(int32_t))
976 {
977     for(size_t i = 0; i < frameCount; ++i) {
978         *(Dst *)(dstLeft + (i * sampleOffset)) = static_cast<Dst>(transform(src[2 * i]));
979         *(Dst *)(dstRight + (i * sampleOffset)) = static_cast<Dst>(transform(src[(2 * i) + 1]));
980     }
981 }
982 
SendStereoAudio(int samples_requested,ssize_t in_size,int32_t * _in,ssize_t out_pos,ADL_UInt8 * left,ADL_UInt8 * right,const ADLMIDI_AudioFormat * format)983 static int SendStereoAudio(int        samples_requested,
984                            ssize_t    in_size,
985                            int32_t   *_in,
986                            ssize_t    out_pos,
987                            ADL_UInt8 *left,
988                            ADL_UInt8 *right,
989                            const ADLMIDI_AudioFormat *format)
990 {
991     if(!in_size)
992         return 0;
993     size_t outputOffset = static_cast<size_t>(out_pos);
994     size_t inSamples    = static_cast<size_t>(in_size * 2);
995     size_t maxSamples   = static_cast<size_t>(samples_requested) - outputOffset;
996     size_t toCopy       = std::min(maxSamples, inSamples);
997 
998     ADLMIDI_SampleType sampleType = format->type;
999     const unsigned containerSize = format->containerSize;
1000     const unsigned sampleOffset = format->sampleOffset;
1001 
1002     left  += (outputOffset / 2) * sampleOffset;
1003     right += (outputOffset / 2) * sampleOffset;
1004 
1005     typedef int32_t(&pfnConvert)(int32_t);
1006     typedef float(&ffnConvert)(int32_t);
1007     typedef double(&dfnConvert)(int32_t);
1008 
1009     switch(sampleType) {
1010     case ADLMIDI_SampleType_S8:
1011     case ADLMIDI_SampleType_U8:
1012     {
1013         pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S8) ? adl_cvtS8 : adl_cvtU8;
1014         switch(containerSize) {
1015         case sizeof(int8_t):
1016             CopySamplesTransformed<int8_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1017             break;
1018         case sizeof(int16_t):
1019             CopySamplesTransformed<int16_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1020             break;
1021         case sizeof(int32_t):
1022             CopySamplesTransformed<int32_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1023             break;
1024         default:
1025             return -1;
1026         }
1027         break;
1028     }
1029     case ADLMIDI_SampleType_S16:
1030     case ADLMIDI_SampleType_U16:
1031     {
1032         pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S16) ? adl_cvtS16 : adl_cvtU16;
1033         switch(containerSize) {
1034         case sizeof(int16_t):
1035             CopySamplesTransformed<int16_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1036             break;
1037         case sizeof(int32_t):
1038             CopySamplesRaw<int32_t>(left, right, _in, toCopy / 2, sampleOffset);
1039             break;
1040         default:
1041             return -1;
1042         }
1043         break;
1044     }
1045     case ADLMIDI_SampleType_S24:
1046     case ADLMIDI_SampleType_U24:
1047     {
1048         pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S24) ? adl_cvtS24 : adl_cvtU24;
1049         switch(containerSize) {
1050         case sizeof(int32_t):
1051             CopySamplesTransformed<int32_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1052             break;
1053         default:
1054             return -1;
1055         }
1056         break;
1057     }
1058     case ADLMIDI_SampleType_S32:
1059     case ADLMIDI_SampleType_U32:
1060     {
1061         pfnConvert cvt = (sampleType == ADLMIDI_SampleType_S32) ? adl_cvtS32 : adl_cvtU32;
1062         switch(containerSize) {
1063         case sizeof(int32_t):
1064             CopySamplesTransformed<int32_t>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1065             break;
1066         default:
1067             return -1;
1068         }
1069         break;
1070     }
1071     case ADLMIDI_SampleType_F32:
1072     {
1073         if(containerSize != sizeof(float))
1074             return -1;
1075         ffnConvert cvt = adl_cvtReal<float>;
1076         CopySamplesTransformed<float>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1077         break;
1078     }
1079     case ADLMIDI_SampleType_F64:
1080     {
1081         if(containerSize != sizeof(double))
1082             return -1;
1083         dfnConvert cvt = adl_cvtReal<double>;
1084         CopySamplesTransformed<double>(left, right, _in, toCopy / 2, sampleOffset, cvt);
1085         break;
1086     }
1087     default:
1088         return -1;
1089     }
1090 
1091     return 0;
1092 }
1093 #   else // __WATCOMC__
1094 
1095 /*
1096     Workaround for OpenWattcom where templates are declared above are causing compiler to be crashed
1097 */
CopySamplesTransformed(ADL_UInt8 * dstLeft,ADL_UInt8 * dstRight,const int32_t * src,size_t frameCount,unsigned sampleOffset,int32_t (& transform)(int32_t))1098 static void CopySamplesTransformed(ADL_UInt8 *dstLeft, ADL_UInt8 *dstRight, const int32_t *src,
1099                                    size_t frameCount, unsigned sampleOffset,
1100                                    int32_t(&transform)(int32_t))
1101 {
1102     for(size_t i = 0; i < frameCount; ++i) {
1103         *(int16_t *)(dstLeft + (i * sampleOffset)) = (int16_t)transform(src[2 * i]);
1104         *(int16_t *)(dstRight + (i * sampleOffset)) = (int16_t)transform(src[(2 * i) + 1]);
1105     }
1106 }
1107 
SendStereoAudio(int samples_requested,ssize_t in_size,int32_t * _in,ssize_t out_pos,ADL_UInt8 * left,ADL_UInt8 * right,const ADLMIDI_AudioFormat * format)1108 static int SendStereoAudio(int        samples_requested,
1109                            ssize_t    in_size,
1110                            int32_t   *_in,
1111                            ssize_t    out_pos,
1112                            ADL_UInt8 *left,
1113                            ADL_UInt8 *right,
1114                            const ADLMIDI_AudioFormat *format)
1115 {
1116     if(!in_size)
1117         return 0;
1118     size_t outputOffset = static_cast<size_t>(out_pos);
1119     size_t inSamples    = static_cast<size_t>(in_size * 2);
1120     size_t maxSamples   = static_cast<size_t>(samples_requested) - outputOffset;
1121     size_t toCopy       = std::min(maxSamples, inSamples);
1122 
1123     ADLMIDI_SampleType sampleType = format->type;
1124     const unsigned containerSize = format->containerSize;
1125     const unsigned sampleOffset = format->sampleOffset;
1126 
1127     left  += (outputOffset / 2) * sampleOffset;
1128     right += (outputOffset / 2) * sampleOffset;
1129 
1130     if(sampleType == ADLMIDI_SampleType_U16)
1131     {
1132         switch(containerSize) {
1133         case sizeof(int16_t):
1134             CopySamplesTransformed(left, right, _in, toCopy / 2, sampleOffset, adl_cvtS16);
1135             break;
1136         default:
1137             return -1;
1138         }
1139     }
1140     else
1141         return -1;
1142     return 0;
1143 }
1144 #   endif // __WATCOM__
1145 
1146 #endif // ADLMIDI_HW_OPL
1147 
1148 
adl_play(struct ADL_MIDIPlayer * device,int sampleCount,short * out)1149 ADLMIDI_EXPORT int adl_play(struct ADL_MIDIPlayer *device, int sampleCount, short *out)
1150 {
1151     return adl_playFormat(device, sampleCount, (ADL_UInt8 *)out, (ADL_UInt8 *)(out + 1), &adl_DefaultAudioFormat);
1152 }
1153 
adl_playFormat(ADL_MIDIPlayer * device,int sampleCount,ADL_UInt8 * out_left,ADL_UInt8 * out_right,const ADLMIDI_AudioFormat * format)1154 ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
1155                                   ADL_UInt8 *out_left, ADL_UInt8 *out_right,
1156                                   const ADLMIDI_AudioFormat *format)
1157 {
1158 #if defined(ADLMIDI_DISABLE_MIDI_SEQUENCER) || defined(ADLMIDI_HW_OPL)
1159     ADL_UNUSED(device);
1160     ADL_UNUSED(sampleCount);
1161     ADL_UNUSED(out_left);
1162     ADL_UNUSED(out_right);
1163     ADL_UNUSED(format);
1164     return 0;
1165 #endif
1166 
1167 #if !defined(ADLMIDI_DISABLE_MIDI_SEQUENCER) && !defined(ADLMIDI_HW_OPL)
1168     sampleCount -= sampleCount % 2; //Avoid even sample requests
1169     if(sampleCount < 0)
1170         return 0;
1171     if(!device)
1172         return 0;
1173 
1174     MidiPlayer *player = GET_MIDI_PLAYER(device);
1175     MidiPlayer::Setup &setup = player->m_setup;
1176 
1177     ssize_t gotten_len = 0;
1178     ssize_t n_periodCountStereo = 512;
1179     //ssize_t n_periodCountPhys = n_periodCountStereo * 2;
1180     int left = sampleCount;
1181     bool hasSkipped = setup.tick_skip_samples_delay > 0;
1182 
1183     while(left > 0)
1184     {
1185         {//...
1186             const double eat_delay = setup.delay < setup.maxdelay ? setup.delay : setup.maxdelay;
1187             if(hasSkipped)
1188             {
1189                 size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay;
1190                 n_periodCountStereo = samples / 2;
1191             }
1192             else
1193             {
1194                 setup.delay -= eat_delay;
1195                 setup.carry += double(setup.PCM_RATE) * eat_delay;
1196                 n_periodCountStereo = static_cast<ssize_t>(setup.carry);
1197                 setup.carry -= double(n_periodCountStereo);
1198             }
1199 
1200             //if(setup.SkipForward > 0)
1201             //    setup.SkipForward -= 1;
1202             //else
1203             {
1204                 if((player->m_sequencer.positionAtEnd()) && (setup.delay <= 0.0))
1205                     break;//Stop to fetch samples at reaching the song end with disabled loop
1206 
1207                 ssize_t leftSamples = left / 2;
1208                 if(n_periodCountStereo > leftSamples)
1209                 {
1210                     setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2;
1211                     n_periodCountStereo = leftSamples;
1212                 }
1213                 //! Count of stereo samples
1214                 ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
1215                 //! Total count of samples
1216                 ssize_t in_generatedPhys = in_generatedStereo * 2;
1217                 //! Unsigned total sample count
1218                 //fill buffer with zeros
1219                 int32_t *out_buf = player->m_outBuf;
1220                 std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
1221                 unsigned int chips = player->m_synth.m_numChips;
1222                 if(chips == 1)
1223                 {
1224                     player->m_synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
1225                 }
1226                 else if(n_periodCountStereo > 0)
1227                 {
1228                     /* Generate data from every chip and mix result */
1229                     for(size_t card = 0; card < chips; ++card)
1230                         player->m_synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
1231                 }
1232 
1233                 /* Process it */
1234                 if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
1235                     return 0;
1236 
1237                 left -= (int)in_generatedPhys;
1238                 gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
1239             }
1240 
1241             if(hasSkipped)
1242             {
1243                 setup.tick_skip_samples_delay -= n_periodCountStereo * 2;
1244                 hasSkipped = setup.tick_skip_samples_delay > 0;
1245             }
1246             else
1247                 setup.delay = player->Tick(eat_delay, setup.mindelay);
1248 
1249         }//...
1250     }
1251 
1252     return static_cast<int>(gotten_len);
1253 #endif //ADLMIDI_DISABLE_MIDI_SEQUENCER
1254 }
1255 
1256 
adl_generate(struct ADL_MIDIPlayer * device,int sampleCount,short * out)1257 ADLMIDI_EXPORT int adl_generate(struct ADL_MIDIPlayer *device, int sampleCount, short *out)
1258 {
1259     return adl_generateFormat(device, sampleCount, (ADL_UInt8 *)out, (ADL_UInt8 *)(out + 1), &adl_DefaultAudioFormat);
1260 }
1261 
adl_generateFormat(struct ADL_MIDIPlayer * device,int sampleCount,ADL_UInt8 * out_left,ADL_UInt8 * out_right,const ADLMIDI_AudioFormat * format)1262 ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleCount,
1263                                       ADL_UInt8 *out_left, ADL_UInt8 *out_right,
1264                                       const ADLMIDI_AudioFormat *format)
1265 {
1266 #ifdef ADLMIDI_HW_OPL
1267     ADL_UNUSED(device);
1268     ADL_UNUSED(sampleCount);
1269     ADL_UNUSED(out_left);
1270     ADL_UNUSED(out_right);
1271     ADL_UNUSED(format);
1272     return 0;
1273 #else
1274     sampleCount -= sampleCount % 2; //Avoid even sample requests
1275     if(sampleCount < 0)
1276         return 0;
1277     if(!device)
1278         return 0;
1279 
1280     MidiPlayer *player = GET_MIDI_PLAYER(device);
1281     MidiPlayer::Setup &setup = player->m_setup;
1282 
1283     ssize_t gotten_len = 0;
1284     ssize_t n_periodCountStereo = 512;
1285 
1286     int     left = sampleCount;
1287     double  delay = double(sampleCount) / double(setup.PCM_RATE);
1288 
1289     while(left > 0)
1290     {
1291         {//...
1292             const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
1293             delay -= eat_delay;
1294             setup.carry += double(setup.PCM_RATE) * eat_delay;
1295             n_periodCountStereo = static_cast<ssize_t>(setup.carry);
1296             setup.carry -= double(n_periodCountStereo);
1297 
1298             {
1299                 ssize_t leftSamples = left / 2;
1300                 if(n_periodCountStereo > leftSamples)
1301                     n_periodCountStereo = leftSamples;
1302                 //! Count of stereo samples
1303                 ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
1304                 //! Total count of samples
1305                 ssize_t in_generatedPhys = in_generatedStereo * 2;
1306                 //! Unsigned total sample count
1307                 //fill buffer with zeros
1308                 int32_t *out_buf = player->m_outBuf;
1309                 std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
1310                 unsigned int chips = player->m_synth.m_numChips;
1311                 if(chips == 1)
1312                     player->m_synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
1313                 else if(n_periodCountStereo > 0)
1314                 {
1315                     /* Generate data from every chip and mix result */
1316                     for(unsigned card = 0; card < chips; ++card)
1317                         player->m_synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
1318                 }
1319                 /* Process it */
1320                 if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
1321                     return 0;
1322 
1323                 left -= (int)in_generatedPhys;
1324                 gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
1325             }
1326 
1327             player->TickIterators(eat_delay);
1328         }//...
1329     }
1330 
1331     return static_cast<int>(gotten_len);
1332 #endif
1333 }
1334 
adl_tickEvents(struct ADL_MIDIPlayer * device,double seconds,double granulality)1335 ADLMIDI_EXPORT double adl_tickEvents(struct ADL_MIDIPlayer *device, double seconds, double granulality)
1336 {
1337 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
1338     if(!device)
1339         return -1.0;
1340     MidiPlayer *play = GET_MIDI_PLAYER(device);
1341     if(!play)
1342         return -1.0;
1343     return play->Tick(seconds, granulality);
1344 #else
1345     ADL_UNUSED(device);
1346     ADL_UNUSED(seconds);
1347     ADL_UNUSED(granulality);
1348     return -1.0;
1349 #endif
1350 }
1351 
adl_atEnd(struct ADL_MIDIPlayer * device)1352 ADLMIDI_EXPORT int adl_atEnd(struct ADL_MIDIPlayer *device)
1353 {
1354 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
1355     if(!device)
1356         return 1;
1357     MidiPlayer *play = GET_MIDI_PLAYER(device);
1358     if(!play)
1359         return 1;
1360     return (int)play->m_sequencer.positionAtEnd();
1361 #else
1362     ADL_UNUSED(device);
1363     return 1;
1364 #endif
1365 }
1366 
adl_trackCount(struct ADL_MIDIPlayer * device)1367 ADLMIDI_EXPORT size_t adl_trackCount(struct ADL_MIDIPlayer *device)
1368 {
1369 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
1370     if(!device)
1371         return 0;
1372     MidiPlayer *play = GET_MIDI_PLAYER(device);
1373     if(!play)
1374         return 0;
1375     return play->m_sequencer.getTrackCount();
1376 #else
1377     ADL_UNUSED(device);
1378     return 0;
1379 #endif
1380 }
1381 
adl_setTrackOptions(struct ADL_MIDIPlayer * device,size_t trackNumber,unsigned trackOptions)1382 ADLMIDI_EXPORT int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t trackNumber, unsigned trackOptions)
1383 {
1384 #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
1385     if(!device)
1386         return -1;
1387     MidiPlayer *play = GET_MIDI_PLAYER(device);
1388     if(!play)
1389         return -1;
1390     MidiSequencer &seq = play->m_sequencer;
1391 
1392     unsigned enableFlag = trackOptions & 3;
1393     trackOptions &= ~3u;
1394 
1395     // handle on/off/solo
1396     switch(enableFlag)
1397     {
1398     default:
1399         break;
1400     case ADLMIDI_TrackOption_On:
1401     case ADLMIDI_TrackOption_Off:
1402         if(!seq.setTrackEnabled(trackNumber, enableFlag == ADLMIDI_TrackOption_On))
1403             return -1;
1404         break;
1405     case ADLMIDI_TrackOption_Solo:
1406         seq.setSoloTrack(trackNumber);
1407         break;
1408     }
1409 
1410     // handle others...
1411     if(trackOptions != 0)
1412         return -1;
1413 
1414     return 0;
1415 
1416 #else
1417     ADL_UNUSED(device);
1418     ADL_UNUSED(trackNumber);
1419     ADL_UNUSED(trackOptions);
1420     return -1;
1421 #endif
1422 }
1423 
adl_panic(struct ADL_MIDIPlayer * device)1424 ADLMIDI_EXPORT void adl_panic(struct ADL_MIDIPlayer *device)
1425 {
1426     if(!device)
1427         return;
1428     MidiPlayer *play = GET_MIDI_PLAYER(device);
1429     if(!play)
1430         return;
1431     play->realTime_panic();
1432 }
1433 
adl_rt_resetState(struct ADL_MIDIPlayer * device)1434 ADLMIDI_EXPORT void adl_rt_resetState(struct ADL_MIDIPlayer *device)
1435 {
1436     if(!device)
1437         return;
1438     MidiPlayer *play = GET_MIDI_PLAYER(device);
1439     if(!play)
1440         return;
1441     play->realTime_ResetState();
1442 }
1443 
adl_rt_noteOn(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 note,ADL_UInt8 velocity)1444 ADLMIDI_EXPORT int adl_rt_noteOn(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note, ADL_UInt8 velocity)
1445 {
1446     if(!device)
1447         return 0;
1448     MidiPlayer *play = GET_MIDI_PLAYER(device);
1449     if(!play)
1450         return 0;
1451     return (int)play->realTime_NoteOn(channel, note, velocity);
1452 }
1453 
adl_rt_noteOff(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 note)1454 ADLMIDI_EXPORT void adl_rt_noteOff(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note)
1455 {
1456     if(!device)
1457         return;
1458     MidiPlayer *play = GET_MIDI_PLAYER(device);
1459     if(!play)
1460         return;
1461     play->realTime_NoteOff(channel, note);
1462 }
1463 
adl_rt_noteAfterTouch(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 note,ADL_UInt8 atVal)1464 ADLMIDI_EXPORT void adl_rt_noteAfterTouch(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 note, ADL_UInt8 atVal)
1465 {
1466     if(!device)
1467         return;
1468     MidiPlayer *play = GET_MIDI_PLAYER(device);
1469     if(!play)
1470         return;
1471     play->realTime_NoteAfterTouch(channel, note, atVal);
1472 }
1473 
adl_rt_channelAfterTouch(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 atVal)1474 ADLMIDI_EXPORT void adl_rt_channelAfterTouch(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 atVal)
1475 {
1476     if(!device)
1477         return;
1478     MidiPlayer *play = GET_MIDI_PLAYER(device);
1479     if(!play)
1480         return;
1481     play->realTime_ChannelAfterTouch(channel, atVal);
1482 }
1483 
adl_rt_controllerChange(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 type,ADL_UInt8 value)1484 ADLMIDI_EXPORT void adl_rt_controllerChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 type, ADL_UInt8 value)
1485 {
1486     if(!device)
1487         return;
1488     MidiPlayer *play = GET_MIDI_PLAYER(device);
1489     if(!play)
1490         return;
1491     play->realTime_Controller(channel, type, value);
1492 }
1493 
adl_rt_patchChange(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 patch)1494 ADLMIDI_EXPORT void adl_rt_patchChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 patch)
1495 {
1496     if(!device)
1497         return;
1498     MidiPlayer *play = GET_MIDI_PLAYER(device);
1499     if(!play)
1500         return;
1501     play->realTime_PatchChange(channel, patch);
1502 }
1503 
adl_rt_pitchBend(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt16 pitch)1504 ADLMIDI_EXPORT void adl_rt_pitchBend(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt16 pitch)
1505 {
1506     if(!device)
1507         return;
1508     MidiPlayer *play = GET_MIDI_PLAYER(device);
1509     if(!play)
1510         return;
1511     play->realTime_PitchBend(channel, pitch);
1512 }
1513 
adl_rt_pitchBendML(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 msb,ADL_UInt8 lsb)1514 ADLMIDI_EXPORT void adl_rt_pitchBendML(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb, ADL_UInt8 lsb)
1515 {
1516     if(!device)
1517         return;
1518     MidiPlayer *play = GET_MIDI_PLAYER(device);
1519     if(!play)
1520         return;
1521     play->realTime_PitchBend(channel, msb, lsb);
1522 }
1523 
adl_rt_bankChangeLSB(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 lsb)1524 ADLMIDI_EXPORT void adl_rt_bankChangeLSB(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 lsb)
1525 {
1526     if(!device)
1527         return;
1528     MidiPlayer *play = GET_MIDI_PLAYER(device);
1529     if(!play)
1530         return;
1531     play->realTime_BankChangeLSB(channel, lsb);
1532 }
1533 
adl_rt_bankChangeMSB(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_UInt8 msb)1534 ADLMIDI_EXPORT void adl_rt_bankChangeMSB(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_UInt8 msb)
1535 {
1536     if(!device)
1537         return;
1538     MidiPlayer *play = GET_MIDI_PLAYER(device);
1539     if(!play)
1540         return;
1541     play->realTime_BankChangeMSB(channel, msb);
1542 }
1543 
adl_rt_bankChange(struct ADL_MIDIPlayer * device,ADL_UInt8 channel,ADL_SInt16 bank)1544 ADLMIDI_EXPORT void adl_rt_bankChange(struct ADL_MIDIPlayer *device, ADL_UInt8 channel, ADL_SInt16 bank)
1545 {
1546     if(!device)
1547         return;
1548     MidiPlayer *play = GET_MIDI_PLAYER(device);
1549     if(!play)
1550         return;
1551     play->realTime_BankChange(channel, (uint16_t)bank);
1552 }
1553 
adl_rt_systemExclusive(struct ADL_MIDIPlayer * device,const ADL_UInt8 * msg,size_t size)1554 ADLMIDI_EXPORT int adl_rt_systemExclusive(struct ADL_MIDIPlayer *device, const ADL_UInt8 *msg, size_t size)
1555 {
1556     if(!device)
1557         return -1;
1558     MidiPlayer *play = GET_MIDI_PLAYER(device);
1559     if(!play)
1560         return -1;
1561     return play->realTime_SysEx(msg, size);
1562 }
1563