aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWohlstand <admin@wohlnet.ru>2025-03-29 00:44:52 +0300
committerWohlstand <admin@wohlnet.ru>2025-03-29 00:44:52 +0300
commite92a4d7285197ab2868aa36f975d73ceee915bea (patch)
treeb5e3af6e6c58145a62ec6394a40e9e65d26a5fcf
parent7afda0483ab0af9db624052321b42c3d2a245e75 (diff)
downloadlibADLMIDI-e92a4d7285197ab2868aa36f975d73ceee915bea.tar.gz
libADLMIDI-e92a4d7285197ab2868aa36f975d73ceee915bea.tar.bz2
libADLMIDI-e92a4d7285197ab2868aa36f975d73ceee915bea.zip
Refactored DOS support
-rw-r--r--CMakeLists.txt10
-rw-r--r--README.md3
-rw-r--r--include/adlmidi.h21
-rw-r--r--src/adlmidi.cpp39
-rw-r--r--src/adlmidi_midiplay.cpp4
-rw-r--r--src/adlmidi_opl3.cpp127
-rw-r--r--src/adlmidi_opl3.hpp49
-rw-r--r--src/adlmidi_private.hpp11
-rw-r--r--src/chips/dos_hw_opl.cpp163
-rw-r--r--src/chips/dos_hw_opl.h48
-rw-r--r--utils/midiplay/adlmidiplay.cpp972
11 files changed, 989 insertions, 458 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 06896b7..2daa858 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -278,7 +278,15 @@ function(handle_options targetLib)
target_compile_definitions(${targetLib} PUBLIC BWMIDI_DISABLE_XMI_SUPPORT)
endif()
- if(NOT ADLMIDI_DOS)
+ if(ADLMIDI_DOS)
+ set(HAS_EMULATOR TRUE)
+ target_sources(${targetLib} PRIVATE
+ ${libADLMIDI_SOURCE_DIR}/src/chips/dos_hw_opl.cpp
+ ${libADLMIDI_SOURCE_DIR}/src/chips/dos_hw_opl.h
+ )
+ target_compile_definitions(${targetLib} PRIVATE ENABLE_HW_OPL_DOS)
+ target_compile_definitions(${targetLib} PUBLIC ADLMIDI_ENABLE_HW_DOS)
+ else()
if(USE_DOSBOX_EMULATOR)
set(HAS_EMULATOR TRUE)
target_sources(${targetLib} PRIVATE
diff --git a/README.md b/README.md
index e88e20f..a333239 100644
--- a/README.md
+++ b/README.md
@@ -194,6 +194,9 @@ To build that example you will need to have installed SDL2 library.
* Added ESFMu emulator for the future ESFM support (Currently used as one another OPL3 emulator and without panned stereo support yet).
* Added YMFM emulator support (OPL3 and OPL2).
* Added support for OPL2 mode when some emulators enabled.
+ * Added ability to change the hardware address at the DOS version of MIDI player.
+ * Added an ability to manually specify the chip type (OPL2 or OPL3) at the DOS version of MIDI player.
+ * Added an automatical detection of OPL2 or OPL3 chip depending on the BLASTER environment variable's value at the DOS version of MIDI player.
## 1.5.1 2022-10-31
* Added an ability to disable the automatical arpeggio
diff --git a/include/adlmidi.h b/include/adlmidi.h
index 13e39d9..27239e0 100644
--- a/include/adlmidi.h
+++ b/include/adlmidi.h
@@ -769,6 +769,27 @@ extern ADLMIDI_DECLSPEC int adl_switchSerialHW(struct ADL_MIDIPlayer *device,
unsigned baud,
unsigned protocol);
+
+/**
+ * \brief The list of possible chip types for DOS hardware interface
+ */
+enum ADL_DOS_ChipType
+{
+ ADLMIDI_DOS_ChipAuto = 0,
+ ADLMIDI_DOS_ChipOPL2,
+ ADLMIDI_DOS_ChipOPL3
+};
+
+/**
+ * @brief Specify the chip type and the base address before initialization.
+ * This function has no effect if library didn't built for DOS with hardware OPL mode
+ * Important: Run this BEFORE creating the instance of the library.
+ * @param chipType
+ * @param baseAddress
+ * @return 0 on success, <0 when any error has occurred
+ */
+extern ADLMIDI_DECLSPEC int adl_switchDOSHW(int chipType, ADL_UInt16 baseAddress);
+
/**
* @brief Set 4-bit device identifier. Used by the SysEx processor.
* @param device Instance of the library
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp
index 7fbf134..b81a342 100644
--- a/src/adlmidi.cpp
+++ b/src/adlmidi.cpp
@@ -24,11 +24,12 @@
#include "adlmidi_midiplay.hpp"
#include "adlmidi_opl3.hpp"
#include "adlmidi_private.hpp"
-#ifndef ADLMIDI_HW_OPL
#include "chips/opl_chip_base.h"
-#endif
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
-#include "midi_sequencer.hpp"
+# include "midi_sequencer.hpp"
+#endif
+#ifdef ENABLE_HW_OPL_DOS
+# include "chips/dos_hw_opl.h"
#endif
#if defined(_MSC_VER) && _MSC_VER < 1900
@@ -138,8 +139,7 @@ ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numChips)
#endif
#ifdef ADLMIDI_HW_OPL
- ADL_UNUSED(numChips);
- play->m_setup.numChips = 1;
+ play->m_setup.numChips = numChips > 2 ? 1 : static_cast<unsigned int>(numChips);
#else
play->m_setup.numChips = static_cast<unsigned int>(numChips);
#endif
@@ -835,15 +835,11 @@ ADLMIDI_EXPORT const char *adl_chipEmulatorName(struct ADL_MIDIPlayer *device)
{
if(device)
{
-#ifndef ADLMIDI_HW_OPL
MidiPlayer *play = GET_MIDI_PLAYER(device);
assert(play);
Synth &synth = *play->m_synth;
if(!synth.m_chips.empty())
return synth.m_chips[0]->emulatorName();
-#else
- return "Hardware OPL3 chip on 0x330";
-#endif
}
return "Unknown";
}
@@ -910,6 +906,31 @@ ADLMIDI_EXPORT int adl_switchSerialHW(struct ADL_MIDIPlayer *device,
return -1;
}
+int adl_switchDOSHW(int chipType, ADL_UInt16 baseAddress)
+{
+#ifdef ENABLE_HW_OPL_DOS
+ if(baseAddress > 0)
+ DOS_HW_OPL::setOplAddress(baseAddress);
+
+ switch(chipType)
+ {
+ case ADLMIDI_DOS_ChipAuto:
+ break;
+
+ case ADLMIDI_DOS_ChipOPL2:
+ DOS_HW_OPL::setChipType(OPLChipBase::CHIPTYPE_OPL2);
+ break;
+ case ADLMIDI_DOS_ChipOPL3:
+ DOS_HW_OPL::setChipType(OPLChipBase::CHIPTYPE_OPL3);
+ break;
+ }
+#else
+ (void)chipType;
+ (void)baseAddress;
+#endif
+ return -1;
+}
+
ADLMIDI_EXPORT const char *adl_linkedLibraryVersion()
{
#if !defined(ADLMIDI_ENABLE_HQ_RESAMPLER)
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index 0bc0191..9db4b67 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -89,7 +89,11 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
m_setup.bankId = 0;
m_setup.numFourOps = -1;
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ m_setup.numChips = 1;
+#else
m_setup.numChips = 2;
+#endif
m_setup.deepTremoloMode = -1;
m_setup.deepVibratoMode = -1;
m_setup.rhythmMode = -1;
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index c612637..97760cf 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -26,12 +26,9 @@
#include <stdlib.h>
#include <cassert>
-#ifndef DISABLE_EMBEDDED_BANKS
-#include "wopl/wopl_file.h"
-#endif
-#ifdef ADLMIDI_HW_OPL
-static const unsigned OPLBase = 0x388;
+#ifdef ENABLE_HW_OPL_DOS
+# include "chips/dos_hw_opl.h"
#else
# if defined(ADLMIDI_DISABLE_NUKED_EMULATOR) && \
defined(ADLMIDI_DISABLE_DOSBOX_EMULATOR) && \
@@ -84,7 +81,7 @@ static const unsigned OPLBase = 0x388;
#endif
static const unsigned adl_emulatorSupport = 0
-#ifndef ADLMIDI_HW_OPL
+#ifndef ENABLE_HW_OPL_DOS
# ifndef ADLMIDI_DISABLE_NUKED_EMULATOR
| (1u << ADLMIDI_EMU_NUKED) | (1u << ADLMIDI_EMU_NUKED_174)
# endif
@@ -936,7 +933,9 @@ OPL3::OPL3() :
OPL3::~OPL3()
{
-#ifdef ADLMIDI_HW_OPL
+ m_curState.clear();
+
+#ifdef ENABLE_HW_OPL_DOS
silenceAll();
writeRegI(0, 0x0BD, 0);
writeRegI(0, 0x104, 0);
@@ -1004,48 +1003,17 @@ void OPL3::setEmbeddedBank(uint32_t bank)
void OPL3::writeReg(size_t chip, uint16_t address, uint8_t value)
{
-#ifdef ADLMIDI_HW_OPL
- ADL_UNUSED(chip);
- unsigned o = address >> 8;
- unsigned port = OPLBase + o * 2;
-
-# ifdef __DJGPP__
- outportb(port, address);
- for(unsigned c = 0; c < 6; ++c) inportb(port);
- outportb(port + 1, value);
- for(unsigned c = 0; c < 35; ++c) inportb(port);
-# endif
-
-# ifdef __WATCOMC__
- outp(port, address);
- for(uint16_t c = 0; c < 6; ++c) inp(port);
- outp(port + 1, value);
- for(uint16_t c = 0; c < 35; ++c) inp(port);
-# endif//__WATCOMC__
-
-#else//ADLMIDI_HW_OPL
m_chips[chip]->writeReg(address, value);
-#endif
}
void OPL3::writeRegI(size_t chip, uint32_t address, uint32_t value)
{
-#ifdef ADLMIDI_HW_OPL
- writeReg(chip, static_cast<uint16_t>(address), static_cast<uint8_t>(value));
-#else//ADLMIDI_HW_OPL
m_chips[chip]->writeReg(static_cast<uint16_t>(address), static_cast<uint8_t>(value));
-#endif
}
void OPL3::writePan(size_t chip, uint32_t address, uint32_t value)
{
-#ifndef ADLMIDI_HW_OPL
m_chips[chip]->writePan(static_cast<uint16_t>(address), static_cast<uint8_t>(value));
-#else
- ADL_UNUSED(chip);
- ADL_UNUSED(address);
- ADL_UNUSED(value);
-#endif
}
@@ -1579,7 +1547,7 @@ void OPL3::setPan(size_t c, uint8_t value)
if(g_channelsMapPan[cc] != 0xFFF)
{
-#ifndef ADLMIDI_HW_OPL
+#ifndef ENABLE_HW_OPL_DOS
if (m_softPanningSup && m_softPanning)
{
writePan(chip, g_channelsMapPan[cc], value);
@@ -1595,7 +1563,7 @@ void OPL3::setPan(size_t c, uint8_t value)
m_regC0[c] = panning;
writePan(chip, g_channelsMapPan[cc], 64);
writeRegI(chip, 0xC0 + g_channelsMapPan[cc], m_insCache[c].feedconn | panning);
-#ifndef ADLMIDI_HW_OPL
+#ifndef ENABLE_HW_OPL_DOS
}
#endif
}
@@ -1795,48 +1763,72 @@ ADLMIDI_VolumeModels OPL3::getVolumeScaleModel()
}
}
-#ifndef ADLMIDI_HW_OPL
void OPL3::clearChips()
{
for(size_t i = 0; i < m_chips.size(); i++)
m_chips[i].reset(NULL);
m_chips.clear();
}
-#endif
void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
{
-#ifndef ADLMIDI_HW_OPL
- clearChips();
-#else
- (void)emulator;
- (void)PCM_RATE;
-#endif
+ bool rebuild_needed = m_curState.cmp(emulator, m_numChips);
+
+ if(rebuild_needed)
+ clearChips();
+
#if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
(void)audioTickHandler;
#endif
- m_insCache.clear();
- m_keyBlockFNumCache.clear();
- m_regBD.clear();
-#ifndef ADLMIDI_HW_OPL
- m_chips.resize(m_numChips, AdlMIDI_SPtr<OPLChipBase>());
-#endif
+ const struct OplTimbre defaultInsCache = { 0x1557403,0x005B381, 0x49,0x80, 0x4, +0 };
+
+ if(rebuild_needed)
+ {
+ m_insCache.clear();
+ m_keyBlockFNumCache.clear();
+ m_regBD.clear();
+ m_regC0.clear();
+ m_channelCategory.clear();
+ m_chips.resize(m_numChips, AdlMIDI_SPtr<OPLChipBase>());
+ }
+ else
+ {
+ adl_fill_vector<OplTimbre>(m_insCache, defaultInsCache);
+ adl_fill_vector<uint32_t>(m_channelCategory, 0);
+ adl_fill_vector<uint32_t>(m_keyBlockFNumCache, 0);
+ adl_fill_vector<uint32_t>(m_regBD, 0);
+ adl_fill_vector<uint8_t>(m_regC0, OPL_PANNING_BOTH);
+ }
#ifdef ADLMIDI_ENABLE_HW_SERIAL
if(emulator >= 0) // If less than zero - it's hardware synth!
m_serial = false;
#endif
- const struct OplTimbre defaultInsCache = { 0x1557403,0x005B381, 0x49,0x80, 0x4, +0 };
- m_numChannels = m_numChips * NUM_OF_CHANNELS;
- m_insCache.resize(m_numChannels, defaultInsCache);
- m_keyBlockFNumCache.resize(m_numChannels, 0);
- m_regBD.resize(m_numChips, 0);
- m_regC0.resize(m_numChips * m_numChannels, OPL_PANNING_BOTH);
- m_channelCategory.resize(m_numChannels, 0);
+ if(rebuild_needed)
+ {
+ m_numChannels = m_numChips * NUM_OF_CHANNELS;
+ m_insCache.resize(m_numChannels, defaultInsCache);
+ m_channelCategory.resize(m_numChannels, 0);
+ m_keyBlockFNumCache.resize(m_numChannels, 0);
+ m_regBD.resize(m_numChips, 0);
+ m_regC0.resize(m_numChips * m_numChannels, OPL_PANNING_BOTH);
+ }
- for(size_t i = 0; i < m_numChips; ++i)
+ if(!rebuild_needed)
+ {
+ bool newRate = m_curState.cmp_rate(PCM_RATE);
+
+ for(size_t i = 0; i < m_numChips; ++i)
+ {
+ if(newRate)
+ m_chips[i]->setRate(PCM_RATE);
+
+ initChip(i);
+ }
+ }
+ else for(size_t i = 0; i < m_numChips; ++i)
{
#ifdef ADLMIDI_ENABLE_HW_SERIAL
if(emulator < 0)
@@ -1849,8 +1841,11 @@ void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
}
#endif
-#ifndef ADLMIDI_HW_OPL
OPLChipBase *chip;
+#ifdef ENABLE_HW_OPL_DOS
+ chip = new DOS_HW_OPL();
+
+#else // ENABLE_HW_OPL_DOS
switch(emulator)
{
default:
@@ -1898,18 +1893,20 @@ void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
break;
#endif
}
+#endif // ENABLE_HW_OPL_DOS
m_chips[i].reset(chip);
chip->setChipId((uint32_t)i);
chip->setRate((uint32_t)PCM_RATE);
+#ifndef ENABLE_HW_OPL_DOS
if(m_runAtPcmRate)
chip->setRunningAtPcmRate(true);
+#endif
-# if defined(ADLMIDI_AUDIO_TICK_HANDLER)
+# if defined(ADLMIDI_AUDIO_TICK_HANDLER) && !defined(ENABLE_HW_OPL_DOS)
chip->setAudioTickHandlerInstance(audioTickHandler);
# endif
-#endif // ADLMIDI_HW_OPL
initChip(i);
}
diff --git a/src/adlmidi_opl3.hpp b/src/adlmidi_opl3.hpp
index 362b301..aee049f 100644
--- a/src/adlmidi_opl3.hpp
+++ b/src/adlmidi_opl3.hpp
@@ -60,10 +60,8 @@ public:
uint32_t m_numChannels;
//! Just a padding. Reserved.
char _padding[4];
-#ifndef ADLMIDI_HW_OPL
//! Running chip emulators
std::vector<AdlMIDI_SPtr<OPLChipBase > > m_chips;
-#endif
private:
//! Cached patch data, needed by Touch()
@@ -90,6 +88,51 @@ private:
//! Number channels per chip
size_t m_perChipChannels;
+ /*!
+ * \brief Current state of the synth (if values matched to setup, chips and arrays won't be fully re-created)
+ */
+ struct State
+ {
+ int emulator;
+ uint32_t numChips;
+ unsigned long pcm_rate;
+
+ State()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ emulator = -2;
+ numChips = 0;
+ pcm_rate = 0;
+ }
+
+ bool cmp_rate(unsigned long rate)
+ {
+ bool ret = pcm_rate != rate;
+
+ if(ret)
+ pcm_rate = rate;
+
+ return ret;
+ }
+
+ bool cmp(int emu, uint32_t chips)
+ {
+ bool ret = emu != emulator || chips != numChips;
+
+ if(ret)
+ {
+ emulator = emu;
+ numChips = chips;
+ }
+
+ return ret;
+ }
+ } m_curState;
+
public:
/**
* @brief MIDI bank entry
@@ -339,12 +382,10 @@ public:
*/
ADLMIDI_VolumeModels getVolumeScaleModel();
-#ifndef ADLMIDI_HW_OPL
/**
* @brief Clean up all running emulated chip instances
*/
void clearChips();
-#endif
/**
* @brief Reset chip properties and initialize them
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index 0b1e92f..dcd0d03 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -60,9 +60,6 @@ typedef int32_t ssize_t;
#endif
#if defined(__DJGPP__) || (defined(__WATCOMC__) && (defined(__DOS__) || defined(__DOS4G__) || defined(__DOS4GNZ__)))
-# ifndef ADLMIDI_HW_OPL
-# define ADLMIDI_HW_OPL
-# endif
# include <conio.h>
# ifdef __DJGPP__
# include <pc.h>
@@ -157,7 +154,7 @@ class MIDIplay;
#define ADL_UNUSED(x) (void)x
-#ifdef ADLMIDI_HW_OPL
+#ifdef ENABLE_HW_OPL_DOS
#define ADL_MAX_CHIPS 1
#define ADL_MAX_CHIPS_STR "1" //Why not just "#MaxCards" ? Watcom fails to pass this with "syntax error" :-P
#else
@@ -214,6 +211,12 @@ inline int32_t adl_cvtU32(int32_t x)
return (uint32_t)adl_cvtS32(x) - (uint32_t)INT32_MIN;
}
+template<typename T>
+void adl_fill_vector(std::vector<T > &v, const T &value)
+{
+ for(typename std::vector<T>::iterator it = v.begin(); it != v.end(); ++it)
+ *it = value;
+}
#if defined(ADLMIDI_AUDIO_TICK_HANDLER)
extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate);
diff --git a/src/chips/dos_hw_opl.cpp b/src/chips/dos_hw_opl.cpp
new file mode 100644
index 0000000..a9f4765
--- /dev/null
+++ b/src/chips/dos_hw_opl.cpp
@@ -0,0 +1,163 @@
+/*
+ * Interfaces over Yamaha OPL3 (YMF262) chip emulators
+ *
+ * Copyright (c) 2017-2025 Vitaly Novichkov (Wohlstand)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#ifdef __DJGPP__
+# include <pc.h>
+#endif
+
+#include "dos_hw_opl.h"
+
+static uint16_t s_OPLBase[2] = {0x388, 0x38A};
+static char s_devName[80] = {0};
+static OPLChipBase::ChipType s_type = OPLChipBase::CHIPTYPE_OPL3;
+static bool s_detected = false;
+
+static void s_updateDevName()
+{
+ const char *oplName = (s_type == OPLChipBase::CHIPTYPE_OPL3) ? "OPL3" : "OPL2";
+ memset(s_devName, 0, sizeof(s_devName));
+ snprintf(s_devName, 80, "%s at 0x%03X", oplName, s_OPLBase[0]);
+}
+
+static void s_detect()
+{
+ if(s_detected)
+ return;
+
+ const char *blaster = getenv("BLASTER");
+ if(blaster)
+ {
+ size_t len = strlen(blaster);
+ for(size_t i = 0; i < len - 1; ++i)
+ {
+ if(blaster[i] == 'T')
+ {
+ switch(blaster[i + 1])
+ {
+ case '1':
+ case '2':
+ s_type = OPLChipBase::CHIPTYPE_OPL2;
+ break;
+ case '3':
+ case '4':
+ case '6':
+ s_type = OPLChipBase::CHIPTYPE_OPL3;
+ break;
+ default:
+ s_type = OPLChipBase::CHIPTYPE_OPL2;
+ break;
+ }
+
+ // printf("-- Detected BLASTER T%c\n", blaster[i + 1]);
+
+ break;
+ }
+ }
+ }
+ else
+ s_type = OPLChipBase::CHIPTYPE_OPL2;
+
+ s_detected = true;
+}
+
+DOS_HW_OPL::DOS_HW_OPL()
+{
+ s_detect();
+ s_updateDevName();
+}
+
+void DOS_HW_OPL::setOplAddress(uint16_t address)
+{
+ s_OPLBase[0] = address;
+ s_OPLBase[1] = address + 2;
+ s_updateDevName();
+}
+
+void DOS_HW_OPL::setChipType(ChipType type)
+{
+ s_type = type;
+ s_detected = true; // Assignd manually, no need to detect
+}
+
+DOS_HW_OPL::~DOS_HW_OPL()
+{
+ DOS_HW_OPL::writeReg(0x0BD, 0);
+ if(s_type == CHIPTYPE_OPL3)
+ {
+ DOS_HW_OPL::writeReg(0x104, 0);
+ DOS_HW_OPL::writeReg(0x105, 0);
+ }
+}
+
+void DOS_HW_OPL::writeReg(uint16_t addr, uint8_t data)
+{
+ assert(m_id <= 1);
+ unsigned o = addr >> 8;
+ unsigned port = s_OPLBase[m_id] + o * 2;
+
+# ifdef __DJGPP__
+ outportb(port, addr);
+
+ for(unsigned c = 0; c < 6; ++c)
+ inportb(port);
+
+ outportb(port + 1, data);
+
+ for(unsigned c = 0; c < 35; ++c)
+ inportb(port);
+# endif
+
+# ifdef __WATCOMC__
+ outp(port, addr);
+
+ for(uint16_t c = 0; c < 6; ++c)
+ inp(port);
+
+ outp(port + 1, data);
+
+ for(uint16_t c = 0; c < 35; ++c)
+ inp(port);
+# endif//__WATCOMC__
+}
+
+void DOS_HW_OPL::nativeGenerate(int16_t *frame)
+{
+ frame[0] = 0;
+ frame[1] = 0;
+}
+
+const char *DOS_HW_OPL::emulatorName()
+{
+ return s_devName;
+}
+
+bool DOS_HW_OPL::hasFullPanning()
+{
+ return false;
+}
+
+OPLChipBase::ChipType DOS_HW_OPL::chipType()
+{
+ return s_type;
+}
diff --git a/src/chips/dos_hw_opl.h b/src/chips/dos_hw_opl.h
new file mode 100644
index 0000000..5e3750b
--- /dev/null
+++ b/src/chips/dos_hw_opl.h
@@ -0,0 +1,48 @@
+/*
+ * Interfaces over Yamaha OPL3 (YMF262) chip emulators
+ *
+ * Copyright (c) 2017-2025 Vitaly Novichkov (Wohlstand)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef DOS_HW_OPL_H
+#define DOS_HW_OPL_H
+
+#include "opl_chip_base.h"
+
+class DOS_HW_OPL : public OPLChipBaseT<DOS_HW_OPL>
+{
+public:
+ DOS_HW_OPL();
+ virtual ~DOS_HW_OPL() override;
+
+ static void setChipType(ChipType type);
+ static void setOplAddress(uint16_t address);
+
+ bool canRunAtPcmRate() const override { return false; }
+ void setRate(uint32_t /*rate*/) override {}
+ void reset() override {}
+ void writeReg(uint16_t addr, uint8_t data) override;
+ void nativePreGenerate() override {}
+ void nativePostGenerate() override {}
+ void nativeGenerate(int16_t *frame) override;
+ const char *emulatorName() override;
+ ChipType chipType() override;
+ bool hasFullPanning() override;
+};
+
+#endif // DOS_HW_OPL_H
diff --git a/utils/midiplay/adlmidiplay.cpp b/utils/midiplay/adlmidiplay.cpp
index f5f30d8..fff74d5 100644
--- a/utils/midiplay/adlmidiplay.cpp
+++ b/utils/midiplay/adlmidiplay.cpp
@@ -29,12 +29,14 @@
#include <cstdlib>
#include <cstring>
#include <cstdarg>
-#include <deque>
#include <vector>
#include <algorithm>
-#include <signal.h>
#include <stdint.h>
-#include "utf8main.h"
+#ifndef ADLMIDI_ENABLE_HW_DOS
+# include <deque>
+# include <signal.h>
+# include "utf8main.h"
+#endif
#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
# ifdef ADLMIDI_USE_SDL2
@@ -265,7 +267,7 @@ void mch_delay(int32_t msec)
#include <adlmidi.h>
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
#ifndef OUTPUT_WAVE_ONLY
# include "audio.h"
@@ -406,7 +408,7 @@ const char* audio_format_to_str(int format, int is_msb)
return "UNK";
}
-#endif //HARDWARE_OPL3
+#endif //ADLMIDI_ENABLE_HW_DOS
const char* volume_model_to_str(int vm)
{
@@ -475,7 +477,7 @@ static void printError(const char *err, const char *what = NULL)
}
static int stop = 0;
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
static void sighandler(int dum)
{
switch(dum)
@@ -528,7 +530,7 @@ static void debugPrint(void * /*userdata*/, const char *fmt, ...)
}
}
-#ifdef HARDWARE_OPL3
+#ifdef ADLMIDI_ENABLE_HW_DOS
static inline void keyWait()
{
std::printf("\n<press any key to continue...>");
@@ -551,7 +553,7 @@ static void printBanks()
for(int a = 0; a < banksCount; ++a)
{
std::printf("%10s%2u = %s\n", a ? "" : "Banks:", a, banknames[a]);
-#ifdef HARDWARE_OPL3
+#ifdef ADLMIDI_ENABLE_HW_DOS
if(((a - 15) % 23 == 0 && a != 0))
keyWait();
#endif
@@ -624,7 +626,7 @@ static struct TimeCounter
double realTimeStart;
#endif
-#ifdef HARDWARE_OPL3
+#ifdef ADLMIDI_ENABLE_HW_DOS
unsigned newTimerFreq;
unsigned timerPeriod;
int haveYield;
@@ -652,7 +654,7 @@ static struct TimeCounter
printsCounter = 0;
complete_prev = -1;
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
printsCounterPeriod = 1;
#else
printsCounterPeriod = 20;
@@ -666,7 +668,7 @@ static struct TimeCounter
#endif
}
-#ifdef HARDWARE_OPL3
+#ifdef ADLMIDI_ENABLE_HW_DOS
void initDosTimer()
{
# ifdef __DJGPP__
@@ -986,7 +988,7 @@ static void runHWSerialLoop(ADL_MIDIPlayer *myDevice)
#endif // ADLMIDI_ENABLE_HW_SERIAL
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
# ifndef OUTPUT_WAVE_ONLY
static int runAudioLoop(ADL_MIDIPlayer *myDevice, AudioOutputSpec &spec)
{
@@ -1233,7 +1235,7 @@ static int runWaveOutLoopLoop(ADL_MIDIPlayer *myDevice, const std::string &musPa
return 0;
}
-#else // HARDWARE_OPL3
+#else // ADLMIDI_ENABLE_HW_DOS
static void runDOSLoop(ADL_MIDIPlayer *myDevice)
{
double tick_delay = 0.0;
@@ -1272,374 +1274,592 @@ static void runDOSLoop(ADL_MIDIPlayer *myDevice)
adl_panic(myDevice); //Shut up all sustaining notes
}
-#endif // HARDWARE_OPL3
+#endif // ADLMIDI_ENABLE_HW_DOS
-int main(int argc, char **argv)
+
+
+static struct Args
{
- std::fprintf(stdout, "==========================================\n"
- #ifdef HARDWARE_OPL3
- " libADLMIDI demo utility (HW OPL)\n"
- #else
- " libADLMIDI demo utility\n"
- #endif
- "==========================================\n\n");
- flushout(stdout);
+ int setHwVibrato;
+ int setHwTremolo;
+ int setScaleMods;
- if(argc >= 2 && std::string(argv[1]) == "--list-banks")
- {
- printBanks();
- return 0;
- }
+ int setBankNo;
+ std::string setBankFile;
+ int setNum4op;
+ int setNumChips;
- if(argc < 2 || std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h")
- {
- std::printf(
- "Usage: adlmidi <midifilename> [ <options> ] \n"
- " [ <bank> [ <numchips> [ <numfourops>] ] ]\n"
- // " -p Enables adlib percussion instrument mode\n"
- " -t Enables tremolo amplification mode\n"
- " -v Enables vibrato amplification mode\n"
- " -s Enables scaling of modulator volumes\n"
- " -vm <num> Chooses one of volume models: \n"
- " 0 auto (default)\n"
- " 1 Generic\n"
- " 2 Native OPL3\n"
- " 3 DMX\n"
- " 4 Apogee Sound System\n"
- " 5 9x SB16\n"
- " 6 DMX (Fixed AM voices)\n"
- " 7 Apogee Sound System (Fixed AM voices)\n"
- " 8 Audio Interface Library (AIL)\n"
- " 9 9x Generic FM\n"
- " 10 HMI Sound Operating System\n"
- );
-#ifdef HARDWARE_OPL3
- keyWait();
-#endif
- std::printf(
- " -frb Enables full-ranged CC74 XG Brightness controller\n"
- " -nl Quit without looping\n"
- " -w Write WAV file rather than playing\n"
- " -mb Run the test of multibank over embedded. 62, 14, 68, and 74'th banks\n"
- " will be combined into one\n"
- " --solo <track> Selects a solo track to play\n"
- " --only <track1,...,trackN> Selects a subset of tracks to play\n"
- " --song <song ID 0...N-1> Selects a song to play (if XMI)\n"
- " -ea Enable the auto-arpeggio\n"
-#ifndef HARDWARE_OPL3
- " -fp Enables full-panning stereo support\n"
- " --gain <value> Set the gaining factor (default 2.0)\n"
- " --emu-nuked Uses Nuked OPL3 v 1.8 emulator\n"
- " --emu-nuked7 Uses Nuked OPL3 v 1.7.4 emulator\n"
- " --emu-dosbox Uses DosBox 0.74 OPL3 emulator\n"
- " --emu-opal Uses Opal OPL3 emulator\n"
- " --emu-java Uses Java OPL3 emulator\n"
- " --emu-esfmu Uses ESFMu OPL3/ESFM emulator\n"
-#endif
-#ifdef HARDWARE_OPL3
- "\n"
- " --time-freq <hz> Uses a different time value, DEFAULT 209\n"
- " --list-banks Print a lost of all built-in FM banks\n"
-#endif
- "\n"
- "Where <bank> - number of embeeded bank or filepath to custom WOPL bank file\n"
- "\n"
- "Note: To create WOPL bank files use OPL Bank Editor you can get here: \n"
- "https://github.com/Wohlstand/OPL3BankEditor\n"
- "\n"
- );
+ std::string musPath;
+
+ int setFullRangeBright;
-#ifndef HARDWARE_OPL3
- printBanks();
+ int enableFullPanning;
+
+#ifndef OUTPUT_WAVE_ONLY
+ bool recordWave;
+ int loopEnabled;
#endif
- return 0;
- }
- unsigned int sampleRate = 44100;
-#if !defined(HARDWARE_OPL3) && !defined(OUTPUT_WAVE_ONLY)
+ unsigned int sampleRate;
+
+#if !defined(ADLMIDI_ENABLE_HW_DOS) && !defined(OUTPUT_WAVE_ONLY)
//const unsigned MaxSamplesAtTime = 512; // 512=dbopl limitation
// How long is SDL buffer, in seconds?
// The smaller the value, the more often SDL_AudioCallBack()
// is called.
- const double AudioBufferLength = 0.08;
+ const double AudioBufferLength;
AudioOutputSpec spec;
- spec.freq = sampleRate;
- spec.format = ADLMIDI_SampleType_S16;
- spec.is_msb = 0;
- spec.channels = 2;
- spec.samples = uint16_t((double)spec.freq * AudioBufferLength);
-#endif // !HARDWARE_OPL3 && !OUTPUT_WAVE_ONLY
-
-#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
- bool hwSerial = false;
- std::string serialName;
- unsigned serialBaud = 115200;
- unsigned serialProto = ADLMIDI_SerialProtocol_RetroWaveOPL3;
#endif
- ADL_MIDIPlayer *myDevice;
-
- //Initialize libADLMIDI and create the instance (you can initialize multiple of them!)
- myDevice = adl_init(sampleRate);
- if(myDevice == NULL)
- {
- printError("Failed to init MIDI device!\n");
- return 1;
- }
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ ADL_UInt16 setHwAddress;
+ int setChipType;
+#endif
- //Set internal debug messages hook to print all libADLMIDI's internal debug messages
- adl_setDebugMessageHook(myDevice, debugPrint, NULL);
+#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
+ bool hwSerial;
+ std::string serialName;
+ unsigned serialBaud;
+ unsigned serialProto;
+#endif
/*
* Set library options by parsing of command line arguments
*/
- bool multibankFromEnbededTest = false;
+ bool multibankFromEnbededTest;
+
+ int autoArpeggioEnabled;
+ int chanAlloc;
+
+#ifndef ADLMIDI_ENABLE_HW_DOS
+ int emulator;
+#endif
+ int volumeModel;
+
+ size_t soloTrack;
+ int songNumLoad;
+ std::vector<size_t> onlyTracks;
+
+
+ Args() :
+ setHwVibrato(-1)
+ , setHwTremolo(-1)
+ , setScaleMods(-1)
+ , setBankNo(-1)
+ , setNum4op(-1)
+ , setNumChips(-1)
+
+ , setFullRangeBright(-1)
+ , enableFullPanning(-1)
#ifndef OUTPUT_WAVE_ONLY
- bool recordWave = false;
- int loopEnabled = 1;
+ , recordWave(false)
+ , loopEnabled(1)
#endif
- int autoArpeggioEnabled = 0;
- int chanAlloc = ADLMIDI_ChanAlloc_AUTO;
-#ifndef HARDWARE_OPL3
- int emulator = ADLMIDI_EMU_NUKED;
+ , sampleRate(44100)
+
+#if !defined(ADLMIDI_ENABLE_HW_DOS) && !defined(OUTPUT_WAVE_ONLY)
+ , AudioBufferLength(0.08)
#endif
- int volumeModel = ADLMIDI_VolumeModel_AUTO;
- size_t soloTrack = ~(size_t)0;
- int songNumLoad = -1;
- std::vector<size_t> onlyTracks;
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ , setHwAddress(0)
+ , setChipType(ADLMIDI_DOS_ChipAuto)
+#endif
-#if !defined(HARDWARE_OPL3) && !defined(OUTPUT_WAVE_ONLY)
- g_audioFormat.type = ADLMIDI_SampleType_S16;
- g_audioFormat.containerSize = sizeof(int16_t);
- g_audioFormat.sampleOffset = sizeof(int16_t) * 2;
+#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
+ , hwSerial(false)
+ , serialBaud(115200)
+ , serialProto(ADLMIDI_SerialProtocol_RetroWaveOPL3)
#endif
+ , multibankFromEnbededTest(false)
+ , autoArpeggioEnabled(0)
+ , chanAlloc(ADLMIDI_ChanAlloc_AUTO)
- while(argc > 2)
+#ifndef ADLMIDI_ENABLE_HW_DOS
+ , emulator(ADLMIDI_EMU_NUKED)
+#endif
+ , volumeModel(ADLMIDI_VolumeModel_AUTO)
+ , soloTrack(~(size_t)0)
+ , songNumLoad(-1)
{
- bool had_option = false;
+#if !defined(ADLMIDI_ENABLE_HW_DOS) && !defined(OUTPUT_WAVE_ONLY)
+ spec.freq = sampleRate;
+ spec.format = ADLMIDI_SampleType_S16;
+ spec.is_msb = 0;
+ spec.channels = 2;
+ spec.samples = uint16_t((double)spec.freq * AudioBufferLength);
+#endif
+ }
- if(!std::strcmp("-p", argv[2]))
- fprintf(stderr, "Warning: -p argument is deprecated and useless!\n"); //adl_setPercMode(myDevice, 1);//Turn on AdLib percussion mode
- else if(!std::strcmp("-v", argv[2]))
- adl_setHVibrato(myDevice, 1);//Force turn on deep vibrato
-#if !defined(OUTPUT_WAVE_ONLY) && !defined(HARDWARE_OPL3)
- else if(!std::strcmp("-w", argv[2]))
+ int parseArgs(int argc, char **argv_arr, bool *quit)
+ {
+ const char* const* argv = argv_arr;
+
+ if(argc >= 2 && std::string(argv[1]) == "--list-banks")
{
- //Current Wave output implementation allows only SINT16 output
- g_audioFormat.type = ADLMIDI_SampleType_S16;
- g_audioFormat.containerSize = sizeof(int16_t);
- g_audioFormat.sampleOffset = sizeof(int16_t) * 2;
- recordWave = true;//Record library output into WAV file
+ printBanks();
+ *quit = true;
+ return 0;
}
- else if(!std::strcmp("-s8", argv[2]) && !recordWave)
- spec.format = ADLMIDI_SampleType_S8;
- else if(!std::strcmp("-u8", argv[2]) && !recordWave)
- spec.format = ADLMIDI_SampleType_U8;
- else if(!std::strcmp("-s16", argv[2]) && !recordWave)
- spec.format = ADLMIDI_SampleType_S16;
- else if(!std::strcmp("-u16", argv[2]) && !recordWave)
- spec.format = ADLMIDI_SampleType_U16;
- else if(!std::strcmp("-s32", argv[2]) && !recordWave)
- spec.format = ADLMIDI_SampleType_S32;
- else if(!std::strcmp("-f32", argv[2]) && !recordWave)
- spec.format = ADLMIDI_SampleType_F32;
-#endif
-
- else if(!std::strcmp("-t", argv[2]))
- adl_setHTremolo(myDevice, 1);//Force turn on deep tremolo
-
- else if(!std::strcmp("-frb", argv[2]))
- adl_setFullRangeBrightness(myDevice, 1);//Turn on a full-ranged XG CC74 Brightness
-#ifndef OUTPUT_WAVE_ONLY
- else if(!std::strcmp("-nl", argv[2]))
- loopEnabled = 0; //Enable loop
-#endif
- else if(!std::strcmp("-na", argv[2])) // Deprecated
- autoArpeggioEnabled = 0; //Enable auto-arpeggio
- else if(!std::strcmp("-ea", argv[2]))
- autoArpeggioEnabled = 1; //Enable auto-arpeggio
-
-#ifndef HARDWARE_OPL3
- else if(!std::strcmp("--emu-nuked", argv[2]))
- emulator = ADLMIDI_EMU_NUKED;
- else if(!std::strcmp("--emu-nuked7", argv[2]))
- emulator = ADLMIDI_EMU_NUKED_174;
- else if(!std::strcmp("--emu-dosbox", argv[2]))
- emulator = ADLMIDI_EMU_DOSBOX;
- else if(!std::strcmp("--emu-opal", argv[2]))
- emulator = ADLMIDI_EMU_OPAL;
- else if(!std::strcmp("--emu-java", argv[2]))
- emulator = ADLMIDI_EMU_JAVA;
- else if(!std::strcmp("--emu-esfmu", argv[2]))
- emulator = ADLMIDI_EMU_ESFMu;
- else if(!std::strcmp("--emu-mame-opl2", argv[2]))
- emulator = ADLMIDI_EMU_MAME_OPL2;
- else if(!std::strcmp("--emu-ymfm-opl2", argv[2]))
- emulator = ADLMIDI_EMU_YMFM_OPL2;
- else if(!std::strcmp("--emu-ymfm-opl3", argv[2]))
- emulator = ADLMIDI_EMU_YMFM_OPL3;
-#endif
-#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
- else if(!std::strcmp("--serial", argv[2]))
+ if(argc < 2 || std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h")
{
- if(argc <= 3)
+ const char *help_text =
+ "Usage: adlmidi <midifilename> [ <options> ] \n"
+ " [ <bank> [ <numchips> [ <numfourops>] ] ]\n"
+ "\n"
+ //------------------------------------------------------------------------------|
+ "Where <bank> - number of embeeded bank or filepath to custom WOPL bank file\n"
+ "Where <numchips> - total number of parallel emulated chips running to\n"
+ " extend poliphony (on hardware 1 chip can only be used)\n"
+ "Where <numfourops> - total number of 4-operator channels on OPL3 chips.\n"
+ " By defaullt value depends on the used bank.\n"
+ "\n"
+ // " -p Enables adlib percussion instrument mode\n"
+ " -t Enables force deep tremolo mode (Default: depens on bank)\n"
+ " -v Enables force deep vibrato mode (Default: depens on bank)\n"
+ " -s Enables scaling of modulator volumes\n"
+ " -vm <num> Chooses one of volume models: \n"
+ " 0 auto (default)\n"
+ " 1 Generic\n"
+ " 2 Native OPL3\n"
+ " 3 DMX\n"
+ " 4 Apogee Sound System\n"
+ " 5 9x SB16\n"
+ " 6 DMX (Fixed AM voices)\n"
+ " 7 Apogee Sound System (Fixed AM voices)\n"
+ " 8 Audio Interface Library (AIL)\n"
+ " 9 9x Generic FM\n"
+ " 10 HMI Sound Operating System\n"
+ " -frb Enables full-ranged CC74 XG Brightness controller\n"
+ " -nl Quit without looping\n"
+ " -w Write WAV file rather than playing\n"
+ //------------------------------------------------------------------------------|
+ " -mb Run the test of multibank over embedded. 62, 14, 68, and 74'th banks\n"
+ " will be combined into one\n"
+ " --solo <track> Selects a solo track to play\n"
+ " --only <track1,...,trackN> Selects a subset of tracks to play\n"
+ " --song <song ID 0...N-1> Selects a song to play (if XMI)\n"
+ " -ea Enable the auto-arpeggio\n"
+#ifndef ADLMIDI_ENABLE_HW_DOS
+ " -fp Enables full-panning stereo support\n"
+ " --gain <value> Set the gaining factor (default 2.0)\n"
+ " --emu-nuked Uses Nuked OPL3 v 1.8 emulator\n"
+ " --emu-nuked7 Uses Nuked OPL3 v 1.7.4 emulator\n"
+ " --emu-dosbox Uses DosBox 0.74 OPL3 emulator\n"
+ " --emu-opal Uses Opal OPL3 emulator\n"
+ " --emu-java Uses Java OPL3 emulator\n"
+ " --emu-esfmu Uses ESFMu OPL3/ESFM emulator\n"
+#else
+ "\n"
+ //------------------------------------------------------------------------------|
+ " --time-freq <hz> Uses a different time value, DEFAULT 209\n"
+ " --type <opl2|opl3> Type of hardware chip ('opl2' or 'opl3'), default AUTO\n"
+ " --addr <hex> Hardware address of the chip, DEFAULT 0x388\n"
+ " --list-banks Print a lost of all built-in FM banks\n"
+#endif
+ "\n"
+ //------------------------------------------------------------------------------|
+ "Note: To create WOPL bank files use OPL Bank Editor you can get here: \n"
+ "https://github.com/Wohlstand/OPL3BankEditor\n"
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ "\n\n"
+ //------------------------------------------------------------------------------|
+ "TIP: If you have the SoundBlaster Pro with Dual OPL2, you can use two cips\n"
+ "if you specify the base address of sound card itself (for example 0x220) and\n"
+ "set two chips. However, keep a note that SBPro's chips were designed for the\n"
+ "Stereo, not for polyphony, and therefore, you will hear voices randomly going\n"
+ "between left and right speaker.\n"
+#endif
+ "\n"
+ ;
+
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ int lines = 5;
+ const char *cur = help_text;
+
+ for(; *cur != '\0'; ++cur)
{
- printError("The option --serial requires an argument!\n");
- return 1;
+ char c = *cur;
+ std::putc(c, stdout);
+ if(c == '\n')
+ lines++;
+
+ if(lines >= 23)
+ {
+ keyWait();
+ lines = 0;
+ }
}
- had_option = true;
- hwSerial = true;
- serialName = argv[3];
+#else
+ std::printf("%s", help_text);
+ flushout(stdout);
+#endif
+
+#ifndef ADLMIDI_ENABLE_HW_DOS
+ printBanks();
+#endif
+ *quit = true;
+ return 0;
}
- else if(!std::strcmp("--serial-baud", argv[2]))
+
+ musPath = argv[1];
+
+ while(argc > 2)
{
- if(argc <= 3)
+ bool had_option = false;
+
+ if(!std::strcmp("-p", argv[2]))
+ fprintf(stderr, "Warning: -p argument is deprecated and useless!\n"); //adl_setPercMode(myDevice, 1);//Turn on AdLib percussion mode
+ else if(!std::strcmp("-v", argv[2]))
+ setHwVibrato = 1;
+
+#if !defined(OUTPUT_WAVE_ONLY) && !defined(ADLMIDI_ENABLE_HW_DOS)
+ else if(!std::strcmp("-w", argv[2]))
{
- printError("The option --serial-baud requires an argument!\n");
- return 1;
+ //Current Wave output implementation allows only SINT16 output
+ g_audioFormat.type = ADLMIDI_SampleType_S16;
+ g_audioFormat.containerSize = sizeof(int16_t);
+ g_audioFormat.sampleOffset = sizeof(int16_t) * 2;
+ recordWave = true;//Record library output into WAV file
}
- had_option = true;
- serialBaud = std::strtol(argv[3], NULL, 10);
- }
- else if(!std::strcmp("--serial-proto", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("-s8", argv[2]) && !recordWave)
+ spec.format = ADLMIDI_SampleType_S8;
+ else if(!std::strcmp("-u8", argv[2]) && !recordWave)
+ spec.format = ADLMIDI_SampleType_U8;
+ else if(!std::strcmp("-s16", argv[2]) && !recordWave)
+ spec.format = ADLMIDI_SampleType_S16;
+ else if(!std::strcmp("-u16", argv[2]) && !recordWave)
+ spec.format = ADLMIDI_SampleType_U16;
+ else if(!std::strcmp("-s32", argv[2]) && !recordWave)
+ spec.format = ADLMIDI_SampleType_S32;
+ else if(!std::strcmp("-f32", argv[2]) && !recordWave)
+ spec.format = ADLMIDI_SampleType_F32;
+#endif
+
+ else if(!std::strcmp("-t", argv[2]))
+ setHwTremolo = 1;
+
+ else if(!std::strcmp("-frb", argv[2]))
+ setFullRangeBright = 1;
+
+#ifndef OUTPUT_WAVE_ONLY
+ else if(!std::strcmp("-nl", argv[2]))
+ loopEnabled = 0; //Enable loop
+#endif
+ else if(!std::strcmp("-na", argv[2])) // Deprecated
+ autoArpeggioEnabled = 0; //Enable auto-arpeggio
+ else if(!std::strcmp("-ea", argv[2]))
+ autoArpeggioEnabled = 1; //Enable auto-arpeggio
+
+#ifndef ADLMIDI_ENABLE_HW_DOS
+ else if(!std::strcmp("--emu-nuked", argv[2]))
+ emulator = ADLMIDI_EMU_NUKED;
+ else if(!std::strcmp("--emu-nuked7", argv[2]))
+ emulator = ADLMIDI_EMU_NUKED_174;
+ else if(!std::strcmp("--emu-dosbox", argv[2]))
+ emulator = ADLMIDI_EMU_DOSBOX;
+ else if(!std::strcmp("--emu-opal", argv[2]))
+ emulator = ADLMIDI_EMU_OPAL;
+ else if(!std::strcmp("--emu-java", argv[2]))
+ emulator = ADLMIDI_EMU_JAVA;
+ else if(!std::strcmp("--emu-esfmu", argv[2]))
+ emulator = ADLMIDI_EMU_ESFMu;
+ else if(!std::strcmp("--emu-mame-opl2", argv[2]))
+ emulator = ADLMIDI_EMU_MAME_OPL2;
+ else if(!std::strcmp("--emu-ymfm-opl2", argv[2]))
+ emulator = ADLMIDI_EMU_YMFM_OPL2;
+ else if(!std::strcmp("--emu-ymfm-opl3", argv[2]))
+ emulator = ADLMIDI_EMU_YMFM_OPL3;
+#endif
+
+#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
+ else if(!std::strcmp("--serial", argv[2]))
{
- printError("The option --serial-proto requires an argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option --serial requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ had_option = true;
+ hwSerial = true;
+ serialName = argv[3];
+ }
+ else if(!std::strcmp("--serial-baud", argv[2]))
+ {
+ if(argc <= 3)
+ {
+ printError("The option --serial-baud requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ had_option = true;
+ serialBaud = std::strtol(argv[3], NULL, 10);
+ }
+ else if(!std::strcmp("--serial-proto", argv[2]))
+ {
+ if(argc <= 3)
+ {
+ printError("The option --serial-proto requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ had_option = true;
+ serialProto = std::strtol(argv[3], NULL, 10);
}
- had_option = true;
- serialProto = std::strtol(argv[3], NULL, 10);
- }
#endif
- else if(!std::strcmp("-fp", argv[2]))
- adl_setSoftPanEnabled(myDevice, 1);
- else if(!std::strcmp("-mb", argv[2]))
- multibankFromEnbededTest = true;
- else if(!std::strcmp("-s", argv[2]))
- adl_setScaleModulators(myDevice, 1);//Turn on modulators scaling by volume
+ else if(!std::strcmp("-fp", argv[2]))
+ enableFullPanning = 1;
+ else if(!std::strcmp("-mb", argv[2]))
+ multibankFromEnbededTest = true;
+ else if(!std::strcmp("-s", argv[2]))
+ setScaleMods = 1;
#ifndef ADLMIDI_HW_OPL
- else if(!std::strcmp("--gain", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("--gain", argv[2]))
{
- printError("The option --gain requires an argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option --gain requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ had_option = true;
+ g_gaining = std::atof(argv[3]);
}
- had_option = true;
- g_gaining = std::atof(argv[3]);
- }
-#endif // HARDWARE_OPL3
+#endif // ADLMIDI_ENABLE_HW_DOS
-#ifdef HARDWARE_OPL3
- else if(!std::strcmp("--time-freq", argv[2]))
- {
- if(argc <= 3)
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ else if(!std::strcmp("--time-freq", argv[2]))
{
- printError("The option --time-freq requires an argument!\n");
- return 1;
- }
+ if(argc <= 3)
+ {
+ printError("The option --time-freq requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+
+ unsigned timerFreq = std::strtoul(argv[3], NULL, 0);
+ if(timerFreq == 0)
+ {
+ printError("The option --time-freq requires a non-zero integer argument!\n");
+ *quit = true;
+ return 1;
+ }
+
+ s_timeCounter.setDosTimerHZ(timerFreq);
- unsigned timerFreq = std::strtoul(argv[3], NULL, 0);
- if(timerFreq == 0)
+ had_option = true;
+ }
+ else if(!std::strcmp("--type", argv[2]))
{
- printError("The option --time-freq requires a non-zero integer argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option --type requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+
+ if(!std::strcmp(argv[3], "opl3") || !std::strcmp(argv[3], "OPL3"))
+ setChipType = ADLMIDI_DOS_ChipOPL3;
+ else if(!std::strcmp(argv[3], "opl2") || !std::strcmp(argv[3], "OPL2"))
+ setChipType = ADLMIDI_DOS_ChipOPL2;
+ else
+ {
+ printError("Given invalid option for --type: accepted 'opl2' or 'opl3'!\n");
+ *quit = true;
+ return 1;
+ }
+
+ had_option = true;
}
+ else if(!std::strcmp("--addr", argv[2]))
+ {
+ if(argc <= 3)
+ {
+ printError("The option --addr requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
- s_timeCounter.setDosTimerHZ(timerFreq);
+ setHwAddress = std::strtoul(argv[3], NULL, 0);
+ if(setHwAddress == 0)
+ {
+ printError("The option --time-freq requires a non-zero integer argument!\n");
+ *quit = true;
+ return 1;
+ }
- had_option = true;
- }
+ had_option = true;
+ }
#endif
- else if(!std::strcmp("-vm", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("-vm", argv[2]))
{
- printError("The option -vm requires an argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option -vm requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ volumeModel = std::strtol(argv[3], NULL, 10);
+ had_option = true;
}
- volumeModel = std::strtol(argv[3], NULL, 10);
- had_option = true;
- }
- else if(!std::strcmp("-ca", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("-ca", argv[2]))
{
- printError("The option -carequires an argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option -carequires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+
+ chanAlloc = std::strtol(argv[3], NULL, 10);
+ had_option = true;
}
- chanAlloc = std::strtol(argv[3], NULL, 10);
- had_option = true;
- }
- else if(!std::strcmp("--solo", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("--solo", argv[2]))
{
- printError("The option --solo requires an argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option --solo requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ soloTrack = std::strtoul(argv[3], NULL, 10);
+ had_option = true;
}
- soloTrack = std::strtoul(argv[3], NULL, 10);
- had_option = true;
- }
- else if(!std::strcmp("--song", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("--song", argv[2]))
{
- printError("The option --song requires an argument!\n");
- return 1;
+ if(argc <= 3)
+ {
+ printError("The option --song requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
+ songNumLoad = std::strtol(argv[3], NULL, 10);
+ had_option = true;
}
- songNumLoad = std::strtol(argv[3], NULL, 10);
- had_option = true;
- }
- else if(!std::strcmp("--only", argv[2]))
- {
- if(argc <= 3)
+ else if(!std::strcmp("--only", argv[2]))
{
- printError("The option --only requires an argument!\n");
- return 1;
- }
+ if(argc <= 3)
+ {
+ printError("The option --only requires an argument!\n");
+ *quit = true;
+ return 1;
+ }
- const char *strp = argv[3];
- unsigned long value;
- unsigned size;
- bool err = std::sscanf(strp, "%lu%n", &value, &size) != 1;
- while(!err && *(strp += size))
- {
+ const char *strp = argv[3];
+ unsigned long value;
+ unsigned size;
+ bool err = std::sscanf(strp, "%lu%n", &value, &size) != 1;
+ while(!err && *(strp += size))
+ {
+ onlyTracks.push_back(value);
+ err = std::sscanf(strp, ",%lu%n", &value, &size) != 1;
+ }
+ if(err)
+ {
+ printError("Invalid argument to --only!\n");
+ *quit = true;
+ return 1;
+ }
onlyTracks.push_back(value);
- err = std::sscanf(strp, ",%lu%n", &value, &size) != 1;
- }
- if(err)
- {
- printError("Invalid argument to --only!\n");
- return 1;
+ had_option = true;
}
- onlyTracks.push_back(value);
- had_option = true;
+ else
+ break;
+
+ argv += (had_option ? 2 : 1);
+ argc -= (had_option ? 2 : 1);
}
- else break;
+ if(argc >= 3)
+ {
+ if(is_number(argv[2]))
+ setBankNo = std::atoi(argv[2]);
+ else
+ setBankFile = argv[2];
+ }
+
+ if(argc >= 4)
+ setNumChips = std::atoi(argv[3]);
- std::copy(argv + (had_option ? 4 : 3),
- argv + argc,
- argv + 2);
- argc -= (had_option ? 2 : 1);
+ if(argc >= 5)
+ setNum4op = std::atoi(argv[4]);
+
+ *quit = false;
+ return 0;
}
+} s_devSetup;
+
+
+int main(int argc, char **argv)
+{
+ std::fprintf(stdout, "==========================================\n"
+ #ifdef ADLMIDI_ENABLE_HW_DOS
+ " libADLMIDI demo utility (HW OPL)\n"
+ #else
+ " libADLMIDI demo utility\n"
+ #endif
+ "==========================================\n\n");
+ flushout(stdout);
+
+ bool doQuit = false;
+ int parseRet = s_devSetup.parseArgs(argc, argv, &doQuit);
+
+ if(doQuit)
+ return parseRet;
+
+ ADL_MIDIPlayer *myDevice;
+
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ if(s_devSetup.setHwAddress > 0 || s_devSetup.setChipType != ADLMIDI_DOS_ChipAuto)
+ adl_switchDOSHW(s_devSetup.setChipType, s_devSetup.setHwAddress);
+#endif
+
+ //Initialize libADLMIDI and create the instance (you can initialize multiple of them!)
+ myDevice = adl_init(s_devSetup.sampleRate);
+ if(myDevice == NULL)
+ {
+ printError("Failed to init MIDI device!\n");
+ return 1;
+ }
+
+ //Set internal debug messages hook to print all libADLMIDI's internal debug messages
+ adl_setDebugMessageHook(myDevice, debugPrint, NULL);
+
+#if !defined(ADLMIDI_ENABLE_HW_DOS) && !defined(OUTPUT_WAVE_ONLY)
+ g_audioFormat.type = ADLMIDI_SampleType_S16;
+ g_audioFormat.containerSize = sizeof(int16_t);
+ g_audioFormat.sampleOffset = sizeof(int16_t) * 2;
+#endif
+
+ if(s_devSetup.setHwVibrato >= 0)
+ adl_setHVibrato(myDevice, s_devSetup.setHwVibrato);//Force turn on deep vibrato
+
+ if(s_devSetup.setHwTremolo >= 0)
+ adl_setHTremolo(myDevice, s_devSetup.setHwTremolo);//Force turn on deep tremolo
+
+ if(s_devSetup.setScaleMods >= 0)
+ adl_setScaleModulators(myDevice, s_devSetup.setScaleMods);//Turn on modulators scaling by volume
+
+ if(s_devSetup.setFullRangeBright >= 0)
+ adl_setFullRangeBrightness(myDevice, s_devSetup.setFullRangeBright);//Turn on a full-ranged XG CC74 Brightness
+
+ if(s_devSetup.enableFullPanning >= 0)
+ adl_setSoftPanEnabled(myDevice, s_devSetup.enableFullPanning);
#ifndef OUTPUT_WAVE_ONLY
//Turn loop on/off (for WAV recording loop must be disabled!)
- adl_setLoopEnabled(myDevice, recordWave ? 0 : loopEnabled);
+ adl_setLoopEnabled(myDevice, s_devSetup.recordWave ? 0 : s_devSetup.loopEnabled);
#endif
- adl_setAutoArpeggio(myDevice, autoArpeggioEnabled);
- adl_setChannelAllocMode(myDevice, chanAlloc);
+ adl_setAutoArpeggio(myDevice, s_devSetup.autoArpeggioEnabled);
+ adl_setChannelAllocMode(myDevice, s_devSetup.chanAlloc);
#ifdef DEBUG_TRACE_ALL_EVENTS
//Hook all MIDI events are ticking while generating an output buffer
@@ -1648,60 +1868,59 @@ int main(int argc, char **argv)
#endif
#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
- if(hwSerial)
- adl_switchSerialHW(myDevice, serialName.c_str(), serialBaud, serialProto);
+ if(s_devSetup.hwSerial)
+ adl_switchSerialHW(myDevice, s_devSetup.serialName.c_str(), s_devSetup.serialBaud, s_devSetup.serialProto);
else
#endif
-#ifndef HARDWARE_OPL3
- adl_switchEmulator(myDevice, emulator);
+#ifndef ADLMIDI_ENABLE_HW_DOS
+ adl_switchEmulator(myDevice, s_devSetup.emulator);
#endif
std::fprintf(stdout, " - Library version %s\n", adl_linkedLibraryVersion());
-#ifdef HARDWARE_OPL3
- std::fprintf(stdout, " - Hardware OPL3 chip in use\n");
+#ifdef ADLMIDI_ENABLE_HW_DOS
+ std::fprintf(stdout, " - Hardware chip in use: %s\n", adl_chipEmulatorName(myDevice));
#elif defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
- if(hwSerial)
- std::fprintf(stdout, " - %s [device %s] in use\n", adl_chipEmulatorName(myDevice), serialName.c_str());
+ if(s_devSetup.hwSerial)
+ std::fprintf(stdout, " - %s [device %s] in use\n", adl_chipEmulatorName(myDevice), s_devSetup.serialName.c_str());
else
std::fprintf(stdout, " - %s Emulator in use\n", adl_chipEmulatorName(myDevice));
#else
std::fprintf(stdout, " - %s Emulator in use\n", adl_chipEmulatorName(myDevice));
#endif
- if(argc >= 3)
+ if(s_devSetup.setBankNo >= 0)
{
- if(is_number(argv[2]))
+ //Choose one of embedded banks
+ if(adl_setBank(myDevice, s_devSetup.setBankNo) != 0)
{
- int bankno = std::atoi(argv[2]);
- //Choose one of embedded banks
- if(adl_setBank(myDevice, bankno) != 0)
- {
- printError(adl_errorInfo(myDevice), "Can't set an embedded bank");
- adl_close(myDevice);
- return 1;
- }
- std::fprintf(stdout, " - Use embedded bank #%d [%s]\n", bankno, adl_getBankNames()[bankno]);
+ printError(adl_errorInfo(myDevice), "Can't set an embedded bank");
+ adl_close(myDevice);
+ return 1;
}
- else
+
+ std::fprintf(stdout, " - Use embedded bank #%d [%s]\n", s_devSetup.setBankNo, adl_getBankNames()[s_devSetup.setBankNo]);
+ }
+ else if(!s_devSetup.setBankFile.empty())
+ {
+ std::fprintf(stdout, " - Use custom bank [%s]...", s_devSetup.setBankFile.c_str());
+ flushout(stdout);
+
+ //Open external bank file (WOPL format is supported)
+ //to create or edit them, use OPL3 Bank Editor you can take here https://github.com/Wohlstand/OPL3BankEditor
+ if(adl_openBankFile(myDevice, s_devSetup.setBankFile.c_str()) != 0)
{
- std::string bankPath = argv[2];
- std::fprintf(stdout, " - Use custom bank [%s]...", bankPath.c_str());
+ std::fprintf(stdout, "FAILED!\n");
flushout(stdout);
- //Open external bank file (WOPL format is supported)
- //to create or edit them, use OPL3 Bank Editor you can take here https://github.com/Wohlstand/OPL3BankEditor
- if(adl_openBankFile(myDevice, bankPath.c_str()) != 0)
- {
- std::fprintf(stdout, "FAILED!\n");
- flushout(stdout);
- printError(adl_errorInfo(myDevice), "Can't open a custom bank file");
- adl_close(myDevice);
- return 1;
- }
- std::fprintf(stdout, "OK!\n");
+ printError(adl_errorInfo(myDevice), "Can't open a custom bank file");
+ adl_close(myDevice);
+ return 1;
}
+
+ std::fprintf(stdout, "OK!\n");
}
- if(multibankFromEnbededTest)
+
+ if(s_devSetup.multibankFromEnbededTest)
{
ADL_BankId id[] =
{
@@ -1736,13 +1955,14 @@ int main(int argc, char **argv)
std::fprintf(stdout, " - Ran a test of multibank over embedded\n");
}
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
int numOfChips = 4;
- if(argc >= 4)
- numOfChips = std::atoi(argv[3]);
+
+ if(s_devSetup.setNumChips >= 0)
+ numOfChips = s_devSetup.setNumChips;
#if defined(ADLMIDI_ENABLE_HW_SERIAL) && !defined(OUTPUT_WAVE_ONLY)
- if(hwSerial)
+ if(s_devSetup.hwSerial)
numOfChips = 1;
#endif
@@ -1753,18 +1973,19 @@ int main(int argc, char **argv)
adl_close(myDevice);
return 1;
}
+
#else
- int numOfChips = 1;
- adl_setNumChips(myDevice, numOfChips);
+ if(s_devSetup.setNumChips >= 0 && s_devSetup.setNumChips <= 2 && s_devSetup.setChipType == ADLMIDI_DOS_ChipOPL2)
+ adl_setNumChips(myDevice, s_devSetup.setNumChips);
#endif
- if(volumeModel != ADLMIDI_VolumeModel_AUTO)
- adl_setVolumeRangeModel(myDevice, volumeModel);
+ if(s_devSetup.volumeModel != ADLMIDI_VolumeModel_AUTO)
+ adl_setVolumeRangeModel(myDevice, s_devSetup.volumeModel);
- if(argc >= 5)
+ if(s_devSetup.setNum4op >= 0)
{
//Set total count of 4-operator channels between all emulated chips
- if(adl_setNumFourOpsChn(myDevice, std::atoi(argv[4])) != 0)
+ if(adl_setNumFourOpsChn(myDevice, s_devSetup.setNum4op) != 0)
{
printError(adl_errorInfo(myDevice), "Can't set number of 4-op channels");
adl_close(myDevice);
@@ -1778,8 +1999,8 @@ int main(int argc, char **argv)
adl_setLoopHooksOnly(myDevice, 1);
#endif
- if(songNumLoad >= 0)
- adl_selectSongNum(myDevice, songNumLoad);
+ if(s_devSetup.songNumLoad >= 0)
+ adl_selectSongNum(myDevice, s_devSetup.songNumLoad);
#if defined(DEBUG_SONG_SWITCHING) || defined(ENABLE_TERMINAL_HOTKEYS)
set_conio_terminal_mode();
@@ -1789,10 +2010,11 @@ int main(int argc, char **argv)
# endif
#endif
- std::string musPath = argv[1];
//Open MIDI file to play
- if(adl_openFile(myDevice, musPath.c_str()) != 0)
+ if(adl_openFile(myDevice, s_devSetup.musPath.c_str()) != 0)
{
+ std::fprintf(stdout, " - File [%s] failed!\n", s_devSetup.musPath.c_str());
+ flushout(stdout);
printError(adl_errorInfo(myDevice), "Can't open MIDI file");
adl_close(myDevice);
return 2;
@@ -1804,9 +2026,9 @@ int main(int argc, char **argv)
std::fprintf(stdout, " - Volume model: %s\n", volume_model_to_str(adl_getVolumeRangeModel(myDevice)));
std::fprintf(stdout, " - Channel allocation mode: %s\n", chanalloc_to_str(adl_getChannelAllocMode(myDevice)));
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
# ifdef ADLMIDI_ENABLE_HW_SERIAL
- if(!hwSerial)
+ if(!s_devSetup.hwSerial)
# endif
{
std::fprintf(stdout, " - Gain level: %g\n", g_gaining);
@@ -1814,26 +2036,26 @@ int main(int argc, char **argv)
#endif
int songsCount = adl_getSongsCount(myDevice);
- if(songNumLoad >= 0)
- std::fprintf(stdout, " - Attempt to load song number: %d / %d\n", songNumLoad, songsCount);
+ if(s_devSetup.songNumLoad >= 0)
+ std::fprintf(stdout, " - Attempt to load song number: %d / %d\n", s_devSetup.songNumLoad, songsCount);
else if(songsCount > 0)
std::fprintf(stdout, " - File contains %d song(s)\n", songsCount);
- if(soloTrack != ~static_cast<size_t>(0))
+ if(s_devSetup.soloTrack != ~static_cast<size_t>(0))
{
- std::fprintf(stdout, " - Solo track: %lu\n", static_cast<unsigned long>(soloTrack));
- adl_setTrackOptions(myDevice, soloTrack, ADLMIDI_TrackOption_Solo);
+ std::fprintf(stdout, " - Solo track: %lu\n", static_cast<unsigned long>(s_devSetup.soloTrack));
+ adl_setTrackOptions(myDevice, s_devSetup.soloTrack, ADLMIDI_TrackOption_Solo);
}
- if(!onlyTracks.empty())
+ if(!s_devSetup.onlyTracks.empty())
{
size_t count = adl_trackCount(myDevice);
for(size_t track = 0; track < count; ++track)
adl_setTrackOptions(myDevice, track, ADLMIDI_TrackOption_Off);
std::fprintf(stdout, " - Only tracks:");
- for(size_t i = 0, n = onlyTracks.size(); i < n; ++i)
+ for(size_t i = 0, n = s_devSetup.onlyTracks.size(); i < n; ++i)
{
- size_t track = onlyTracks[i];
+ size_t track = s_devSetup.onlyTracks[i];
adl_setTrackOptions(myDevice, track, ADLMIDI_TrackOption_On);
std::fprintf(stdout, " %lu", static_cast<unsigned long>(track));
}
@@ -1842,46 +2064,46 @@ int main(int argc, char **argv)
std::fprintf(stdout, " - Automatic arpeggio is turned %s\n", adl_getAutoArpeggio(myDevice) ? "ON" : "OFF");
- std::fprintf(stdout, " - File [%s] opened!\n", musPath.c_str());
+ std::fprintf(stdout, " - File [%s] opened!\n", s_devSetup.musPath.c_str());
flushout(stdout);
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
# if !defined(_WIN32) && !defined(__WATCOMC__)
signal(SIGHUP, sighandler);
# endif
-#else // HARDWARE_OPL3
+#else // ADLMIDI_ENABLE_HW_DOS
//disable();
s_timeCounter.initDosTimer();
s_timeCounter.flushDosTimer();
//enable();
-#endif//HARDWARE_OPL3
+#endif//ADLMIDI_ENABLE_HW_DOS
s_timeCounter.setTotal(adl_totalTimeLength(myDevice));
#ifndef OUTPUT_WAVE_ONLY
s_timeCounter.setLoop(adl_loopStartTime(myDevice), adl_loopEndTime(myDevice));
-# ifndef HARDWARE_OPL3
- if(!recordWave)
+# ifndef ADLMIDI_ENABLE_HW_DOS
+ if(!s_devSetup.recordWave)
# endif
{
- std::fprintf(stdout, " - Loop is turned %s\n", loopEnabled ? "ON" : "OFF");
+ std::fprintf(stdout, " - Loop is turned %s\n", s_devSetup.loopEnabled ? "ON" : "OFF");
if(s_timeCounter.hasLoop)
std::fprintf(stdout, " - Has loop points: %s ... %s\n", s_timeCounter.loopStartHMS, s_timeCounter.loopEndHMS);
std::fprintf(stdout, "\n==========================================\n");
flushout(stdout);
-# ifndef HARDWARE_OPL3
+# ifndef ADLMIDI_ENABLE_HW_DOS
# ifdef ADLMIDI_ENABLE_HW_SERIAL
- if(hwSerial)
+ if(s_devSetup.hwSerial)
runHWSerialLoop(myDevice);
else
# endif
{
- int ret = runAudioLoop(myDevice, spec);
+ int ret = runAudioLoop(myDevice, s_devSetup.spec);
if (ret != 0)
{
adl_close(myDevice);
@@ -1896,22 +2118,22 @@ int main(int argc, char **argv)
}
#endif //OUTPUT_WAVE_ONLY
-#ifndef HARDWARE_OPL3
+#ifndef ADLMIDI_ENABLE_HW_DOS
# ifndef OUTPUT_WAVE_ONLY
else
# endif //OUTPUT_WAVE_ONLY
{
- int ret = runWaveOutLoopLoop(myDevice, musPath, sampleRate);
+ int ret = runWaveOutLoopLoop(myDevice, s_devSetup.musPath, s_devSetup.sampleRate);
if(ret != 0)
{
adl_close(myDevice);
return ret;
}
}
-#endif //HARDWARE_OPL3
+#endif //ADLMIDI_ENABLE_HW_DOS
-#ifdef HARDWARE_OPL3
+#ifdef ADLMIDI_ENABLE_HW_DOS
s_timeCounter.restoreDosTimer();
#endif