Skip to content

Commit a241664

Browse files
committed
Updated libADLMIDI
1 parent d21a5af commit a241664

File tree

12 files changed

+835
-20
lines changed

12 files changed

+835
-20
lines changed

ADLMIDI-Player/src/main/cpp/CMakeLists.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required (VERSION 3.2...3.5)
1+
cmake_minimum_required (VERSION 3.2...3.10)
22
project (libADLMIDI VERSION 1.5.1 LANGUAGES C CXX)
33

44
include(GNUInstallDirs)
@@ -189,6 +189,7 @@ option(USE_DOSBOX_EMULATOR "Use DosBox 0.74 OPL3 emulator (semi-accurate, sugge
189189
option(USE_NUKED_EMULATOR "Use Nuked OPL3 emulator (most accurate, powerful)" ${DEFAULT_HEAVY_EMULATORS})
190190
option(USE_OPAL_EMULATOR "Use Opal emulator (inaccurate)" ${DEFAULT_HEAVY_EMULATORS})
191191
option(USE_JAVA_EMULATOR "Use JavaOPL emulator" ${DEFAULT_HEAVY_EMULATORS})
192+
option(USE_HW_SERIAL "Use the hardware OPL3 chip via Serial on modern systems" OFF)
192193

193194
option(WITH_GENADLDATA "Build and run full rebuild of embedded banks cache" OFF)
194195
option(WITH_GENADLDATA_COMMENTS "Enable comments in a generated embedded instruments cache file" OFF)
@@ -286,6 +287,15 @@ function(handle_options targetLib)
286287
target_compile_definitions(${targetLib} PUBLIC ADLMIDI_DISABLE_JAVA_EMULATOR)
287288
endif()
288289

290+
if(USE_HW_SERIAL)
291+
set(HAS_EMULATOR TRUE)
292+
target_sources(${targetLib} PRIVATE
293+
${libADLMIDI_SOURCE_DIR}/src/chips/opl_serial_port.cpp
294+
)
295+
target_compile_definitions(${targetLib} PRIVATE ENABLE_HW_OPL_SERIAL_PORT)
296+
target_compile_definitions(${targetLib} PUBLIC ADLMIDI_ENABLE_HW_SERIAL)
297+
endif()
298+
289299
if(NOT HAS_EMULATOR)
290300
message(FATAL_ERROR "No emulators enabled! You must enable at least one emulator!")
291301
endif()
@@ -414,6 +424,7 @@ function(libADLMIDI_find_SDL2)
414424
add_library(ADLMIDI_SDL2 INTERFACE)
415425
if(TARGET SDL2::SDL2)
416426
target_link_libraries(ADLMIDI_SDL2 INTERFACE SDL2::SDL2)
427+
target_include_directories(ADLMIDI_SDL2 INTERFACE ${SDL2_INCLUDE_DIRS})
417428
else()
418429
string(STRIP ${SDL2_LIBRARIES} SDL2_LIBRARIES)
419430
target_include_directories(ADLMIDI_SDL2 INTERFACE ${SDL2_INCLUDE_DIRS})
@@ -547,6 +558,7 @@ message("USE_DOSBOX_EMULATOR = ${USE_DOSBOX_EMULATOR}")
547558
message("USE_NUKED_EMULATOR = ${USE_NUKED_EMULATOR}")
548559
message("USE_OPAL_EMULATOR = ${USE_OPAL_EMULATOR}")
549560
message("USE_JAVA_EMULATOR = ${USE_JAVA_EMULATOR}")
561+
message("USE_HW_SERIAL = ${USE_HW_SERIAL}")
550562

551563
message("===== Utils and extras =====")
552564
message("WITH_GENADLDATA = ${WITH_GENADLDATA}")

ADLMIDI-Player/src/main/cpp/include/adlmidi.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,30 @@ typedef struct {
737737
*/
738738
extern ADLMIDI_DECLSPEC int adl_setRunAtPcmRate(struct ADL_MIDIPlayer *device, int enabled);
739739

740+
/**
741+
* @brief The list of serial port protocols
742+
*/
743+
enum ADL_SerialProtocol
744+
{
745+
ADLMIDI_SerialProtocol_Unknown = 0,
746+
ADLMIDI_SerialProtocol_ArduinoOPL2,
747+
ADLMIDI_SerialProtocol_NukeYktOPL3,
748+
ADLMIDI_SerialProtocol_RetroWaveOPL3,
749+
ADLMIDI_SerialProtocol_END
750+
};
751+
752+
/**
753+
* @brief Switch the synthesizer into hardware mode using Serial port
754+
* @param name The name of the serial port device (it may look different on various platforms. On UNIX-like systems don't type the /dev/ prefix: only name).
755+
* @param baud The baud speed of the serial port
756+
* @param protocol The binary protocol used to communicate the device (#ADL_SerialProtocol)
757+
* @return 0 on success, <0 when any error has occurred
758+
*/
759+
extern ADLMIDI_DECLSPEC int adl_switchSerialHW(struct ADL_MIDIPlayer *device,
760+
const char *name,
761+
unsigned baud,
762+
unsigned protocol);
763+
740764
/**
741765
* @brief Set 4-bit device identifier. Used by the SysEx processor.
742766
* @param device Instance of the library
@@ -1152,6 +1176,39 @@ extern ADLMIDI_DECLSPEC int adl_generateFormat(struct ADL_MIDIPlayer *device, i
11521176
*/
11531177
extern ADLMIDI_DECLSPEC double adl_tickEvents(struct ADL_MIDIPlayer *device, double seconds, double granulality);
11541178

1179+
/**
1180+
* @brief Periodic tick handler without iterators.
1181+
*
1182+
* Unlike adl_tickEvents(), it doesn't handles iterators, you need to perform
1183+
* them naually via adl_tickIterators().
1184+
*
1185+
* Notice: The function is provided to use it with Hardware OPL3 mode or for the purpose to iterate
1186+
* MIDI playback without of sound generation.
1187+
*
1188+
* DON'T USE IT TOGETHER WITH adl_play() and adl_playFormat() calls
1189+
* as there are all using this function internally!!!
1190+
*
1191+
* @param device Instance of the library
1192+
* @param seconds Previous delay. On a first moment, pass the `0.0`
1193+
* @param granulality Minimal size of one MIDI tick in seconds.
1194+
* @return desired number of seconds until next call. Pass this value into `seconds` field in next time
1195+
*/
1196+
extern ADLMIDI_DECLSPEC double adl_tickEventsOnly(struct ADL_MIDIPlayer *device, double seconds, double granulality);
1197+
1198+
1199+
/**
1200+
* @brief Periodic tick hander for the real-time hardware output
1201+
*
1202+
* This function runs a single step of vibrato, auto-arpeggio, and the portamento of @seconds duration.
1203+
*
1204+
* When running the libADLMIDI as a real-time driver for the ral hardware, call
1205+
* this function from the timer and specify the @seconds value with a delay of the single cycle.
1206+
*
1207+
* @param device Instance of the library
1208+
* @param seconds Previous delay. On a first moment, pass the `0.0`
1209+
*/
1210+
extern ADLMIDI_DECLSPEC void adl_tickIterators(struct ADL_MIDIPlayer *device, double seconds);
1211+
11551212

11561213

11571214

ADLMIDI-Player/src/main/cpp/src/adlmidi.cpp

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,20 @@ ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numChips)
131131

132132
MidiPlayer *play = GET_MIDI_PLAYER(device);
133133
assert(play);
134+
135+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
136+
if(play->m_setup.serial)
137+
numChips = 1;
138+
#endif
139+
134140
#ifdef ADLMIDI_HW_OPL
135141
ADL_UNUSED(numChips);
136142
play->m_setup.numChips = 1;
137143
#else
138144
play->m_setup.numChips = static_cast<unsigned int>(numChips);
139145
#endif
140-
if(play->m_setup.numChips < 1 || play->m_setup.numChips > ADL_MAX_CHIPS)
146+
147+
if((play->m_setup.numChips < 1) || (play->m_setup.numChips > ADL_MAX_CHIPS))
141148
{
142149
play->setErrorString("number of chips may only be 1.." ADL_MAX_CHIPS_STR ".\n");
143150
return -1;
@@ -618,6 +625,10 @@ ADLMIDI_EXPORT void adl_setSoftPanEnabled(ADL_MIDIPlayer *device, int softPanEn)
618625
MidiPlayer *play = GET_MIDI_PLAYER(device);
619626
assert(play);
620627
play->m_synth->m_softPanning = (softPanEn != 0);
628+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
629+
if(play->m_setup.serial) // Soft-panning won't work while serial is active
630+
play->m_synth->m_softPanning = false;
631+
#endif
621632
}
622633

623634
/* !!!DEPRECATED!!! */
@@ -846,6 +857,9 @@ ADLMIDI_EXPORT int adl_switchEmulator(struct ADL_MIDIPlayer *device, int emulato
846857
if(adl_isEmulatorAvailable(emulator))
847858
{
848859
play->m_setup.emulator = emulator;
860+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
861+
play->m_setup.serial = false;
862+
#endif
849863
play->partialReset();
850864
return 0;
851865
}
@@ -870,6 +884,31 @@ ADLMIDI_EXPORT int adl_setRunAtPcmRate(ADL_MIDIPlayer *device, int enabled)
870884
return -1;
871885
}
872886

887+
ADLMIDI_EXPORT int adl_switchSerialHW(struct ADL_MIDIPlayer *device,
888+
const char *name,
889+
unsigned baud,
890+
unsigned protocol)
891+
{
892+
if(device)
893+
{
894+
MidiPlayer *play = GET_MIDI_PLAYER(device);
895+
assert(play);
896+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
897+
play->m_setup.serial = true;
898+
play->m_setup.serialName = std::string(name);
899+
play->m_setup.serialBaud = baud;
900+
play->m_setup.serialProtocol = protocol;
901+
play->partialReset();
902+
return 0;
903+
#else
904+
(void)name; (void)baud; (void)protocol;
905+
play->setErrorString("ADLMIDI: The hardware serial mode is not enabled in this build");
906+
return -1;
907+
#endif
908+
}
909+
910+
return -1;
911+
}
873912

874913
ADLMIDI_EXPORT const char *adl_linkedLibraryVersion()
875914
{
@@ -1498,7 +1537,10 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
14981537
hasSkipped = setup.tick_skip_samples_delay > 0;
14991538
}
15001539
else
1540+
{
15011541
setup.delay = player->Tick(eat_delay, setup.mindelay);
1542+
player->TickIterators(eat_delay);
1543+
}
15021544
}
15031545

15041546
return static_cast<int>(gotten_len);
@@ -1588,6 +1630,24 @@ ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleC
15881630

15891631
ADLMIDI_EXPORT double adl_tickEvents(struct ADL_MIDIPlayer *device, double seconds, double granulality)
15901632
{
1633+
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
1634+
if(!device)
1635+
return -1.0;
1636+
MidiPlayer *play = GET_MIDI_PLAYER(device);
1637+
assert(play);
1638+
double ret = play->Tick(seconds, granulality);
1639+
play->TickIterators(seconds);
1640+
return ret;
1641+
#else
1642+
ADL_UNUSED(device);
1643+
ADL_UNUSED(seconds);
1644+
ADL_UNUSED(granulality);
1645+
return -1.0;
1646+
#endif
1647+
}
1648+
1649+
ADLMIDI_EXPORT double adl_tickEventsOnly(struct ADL_MIDIPlayer *device, double seconds, double granulality)
1650+
{
15911651
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
15921652
if(!device)
15931653
return -1.0;
@@ -1602,6 +1662,14 @@ ADLMIDI_EXPORT double adl_tickEvents(struct ADL_MIDIPlayer *device, double secon
16021662
#endif
16031663
}
16041664

1665+
ADLMIDI_EXPORT void adl_tickIterators(struct ADL_MIDIPlayer *device, double seconds)
1666+
{
1667+
if(!device)
1668+
return;
1669+
MidiPlayer *play = GET_MIDI_PLAYER(device);
1670+
play->TickIterators(seconds);
1671+
}
1672+
16051673
ADLMIDI_EXPORT int adl_atEnd(struct ADL_MIDIPlayer *device)
16061674
{
16071675
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER

ADLMIDI-Player/src/main/cpp/src/adlmidi_load.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ bool MIDIplay::LoadMIDI_post()
261261
resetMIDIDefaults();
262262

263263
m_setup.tick_skip_samples_delay = 0;
264-
synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip
264+
chipReset(); // Reset OPL3 chip
265265
//opl.Reset(); // ...twice (just in case someone misprogrammed OPL3 previously)
266266
m_chipChannels.clear();
267267
m_chipChannels.resize(synth.m_numChannels);

ADLMIDI-Player/src/main/cpp/src/adlmidi_midiplay.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
7676
m_setup.emulator = adl_getLowestEmulator();
7777
m_setup.runAtPcmRate = false;
7878

79+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
80+
m_setup.serial = false;
81+
m_setup.serialName = std::string();
82+
m_setup.serialBaud = 0;
83+
m_setup.serialProtocol = 0;
84+
#endif
85+
7986
m_setup.PCM_RATE = sampleRate;
8087
m_setup.mindelay = 1.0 / (double)m_setup.PCM_RATE;
8188
m_setup.maxdelay = 512.0 / (double)m_setup.PCM_RATE;
@@ -155,7 +162,7 @@ void MIDIplay::applySetup()
155162
else
156163
adlCalculateFourOpChannels(this, true);
157164

158-
synth.reset(m_setup.emulator, m_setup.PCM_RATE, this);
165+
chipReset();
159166
m_chipChannels.clear();
160167
m_chipChannels.resize(synth.m_numChannels);
161168

@@ -169,7 +176,7 @@ void MIDIplay::partialReset()
169176
realTime_panic();
170177
m_setup.tick_skip_samples_delay = 0;
171178
synth.m_runAtPcmRate = m_setup.runAtPcmRate;
172-
synth.reset(m_setup.emulator, m_setup.PCM_RATE, this);
179+
chipReset();
173180
m_chipChannels.clear();
174181
m_chipChannels.resize((size_t)synth.m_numChannels);
175182
resetMIDIDefaults();
@@ -193,6 +200,21 @@ void MIDIplay::resetMIDI()
193200
caugh_missing_banks_percussion.clear();
194201
}
195202

203+
void MIDIplay::chipReset()
204+
{
205+
Synth &synth = *m_synth;
206+
207+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
208+
if(m_setup.serial)
209+
{
210+
synth.resetSerial(m_setup.serialName, m_setup.serialBaud, m_setup.serialProtocol);
211+
return;
212+
}
213+
#endif
214+
215+
synth.reset(m_setup.emulator, m_setup.PCM_RATE, this);
216+
}
217+
196218
void MIDIplay::resetMIDIDefaults(int offset)
197219
{
198220
Synth &synth = *m_synth;
@@ -252,7 +274,11 @@ void MIDIplay::TickIterators(double s)
252274

253275
updateVibrato(s);
254276
updateArpeggio(s);
277+
255278
#if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
279+
# ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
280+
s *= m_sequencer->getTempoMultiplier(); // Glide will follow the tempo
281+
# endif
256282
updateGlide(s);
257283
#endif
258284
}

ADLMIDI-Player/src/main/cpp/src/adlmidi_midiplay.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class MIDIplay
7676
void resetMIDI();
7777

7878
private:
79+
void chipReset();
7980
void resetMIDIDefaults(int offset = 0);
8081

8182
public:
@@ -526,6 +527,14 @@ class MIDIplay
526527
{
527528
int emulator;
528529
bool runAtPcmRate;
530+
531+
#ifdef ADLMIDI_ENABLE_HW_SERIAL
532+
bool serial;
533+
std::string serialName;
534+
unsigned int serialBaud;
535+
unsigned int serialProtocol;
536+
#endif
537+
529538
unsigned int bankId;
530539
int numFourOps;
531540
unsigned int numChips;

0 commit comments

Comments
 (0)