aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/adlmidi_opl3.cpp12
-rw-r--r--src/adlmidi_opl3.hpp326
-rw-r--r--src/adlmidi_private.hpp292
3 files changed, 339 insertions, 291 deletions
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index f3672d3..0f977e2 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -21,6 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "adlmidi_opl3.hpp"
#include "adlmidi_private.hpp"
#include <stdlib.h>
#include <cassert>
@@ -148,6 +149,13 @@ static const uint16_t g_channelsMap[23] =
Ports: ???
*/
+enum
+{
+ OPL_PANNING_LEFT = 0x10,
+ OPL_PANNING_RIGHT = 0x20,
+ OPL_PANNING_BOTH = 0x30
+};
+
static adlinsdata2 makeEmptyInstrument()
{
adlinsdata2 ins;
@@ -181,6 +189,10 @@ OPL3::OPL3() :
#endif
}
+OPL3::~OPL3()
+{
+}
+
bool OPL3::setupLocked()
{
return (m_musicMode == MODE_CMF ||
diff --git a/src/adlmidi_opl3.hpp b/src/adlmidi_opl3.hpp
new file mode 100644
index 0000000..7282de4
--- /dev/null
+++ b/src/adlmidi_opl3.hpp
@@ -0,0 +1,326 @@
+/*
+ * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
+ *
+ * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
+ * ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru>
+ *
+ * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
+ * http://iki.fi/bisqwit/source/adlmidi.html
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ADLMIDI_OPL3_HPP
+#define ADLMIDI_OPL3_HPP
+
+#include "adldata.hh"
+#include "adlmidi_ptr.hpp"
+#include "adlmidi_bankmap.h"
+#include "adlmidi.h"
+#include <vector>
+#include <stdint.h>
+
+class MIDIplay;
+class OPLChipBase;
+
+/**
+ * @brief OPL3 Chip management class
+ */
+class OPL3
+{
+ friend class MIDIplay;
+ friend class AdlInstrumentTester;
+ friend int adlCalculateFourOpChannels(MIDIplay *play, bool silent);
+public:
+ enum
+ {
+ PercussionTag = 1 << 15,
+ CustomBankTag = 0xFFFFFFFF
+ };
+
+ //! Total number of chip channels between all running emulators
+ 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()
+ std::vector<adldata> m_insCache;
+ //! Value written to B0, cached, needed by NoteOff.
+ /*! Contains Key on/off state, octave block and frequency number values
+ */
+ std::vector<uint32_t> m_keyBlockFNumCache;
+ //! Cached BD registry value (flags register: DeepTremolo, DeepVibrato, and RhythmMode)
+ std::vector<uint32_t> m_regBD;
+
+public:
+ /**
+ * @brief MIDI bank entry
+ */
+ struct Bank
+ {
+ //! MIDI Bank instruments
+ adlinsdata2 ins[128];
+ };
+ typedef BasicBankMap<Bank> BankMap;
+ //! MIDI bank instruments data
+ BankMap m_insBanks;
+ //! MIDI bank-wide setup
+ AdlBankSetup m_insBankSetup;
+
+public:
+ //! Blank instrument template
+ static const adlinsdata2 m_emptyInstrument;
+ //! Total number of running concurrent emulated chips
+ uint32_t m_numChips;
+ //! Currently running embedded bank number. "CustomBankTag" means usign of the custom bank.
+ uint32_t m_embeddedBank;
+ //! Total number of needed four-operator channels in all running chips
+ uint32_t m_numFourOps;
+ //! Turn global Deep Tremolo mode on
+ bool m_deepTremoloMode;
+ //! Turn global Deep Vibrato mode on
+ bool m_deepVibratoMode;
+ //! Use Rhythm Mode percussions
+ bool m_rhythmMode;
+ //! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too.
+ bool m_scaleModulators;
+ //! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates.
+ bool m_runAtPcmRate;
+ //! Enable soft panning
+ bool m_softPanning;
+
+ //! Just a padding. Reserved.
+ char _padding2[3];
+
+ /**
+ * @brief Music playing mode
+ */
+ enum MusicMode
+ {
+ //! MIDI mode
+ MODE_MIDI,
+ //! Id-Software Music mode
+ MODE_IMF,
+ //! Creative Music Files mode
+ MODE_CMF,
+ //! EA-MUS (a.k.a. RSXX) mode
+ MODE_RSXX
+ } m_musicMode;
+
+ /**
+ * @brief Volume models enum
+ */
+ enum VolumesScale
+ {
+ //! Generic volume model (linearization of logarithmic scale)
+ VOLUME_Generic,
+ //! OPL3 native logarithmic scale
+ VOLUME_NATIVE,
+ //! DMX volume scale logarithmic table
+ VOLUME_DMX,
+ //! Apoge Sound System volume scaling model
+ VOLUME_APOGEE,
+ //! Windows 9x driver volume scale table
+ VOLUME_9X
+ } m_volumeScale;
+
+ //! Reserved
+ char _padding3[8];
+
+ /**
+ * @brief Channel categiry enumeration
+ */
+ enum ChanCat
+ {
+ //! Regular melodic/percussion channel
+ ChanCat_Regular = 0,
+ //! Four-op master
+ ChanCat_4op_Master = 1,
+ //! Four-op slave
+ ChanCat_4op_Slave = 2,
+ //! Rhythm-mode Bass drum
+ ChanCat_Rhythm_Bass = 3,
+ //! Rhythm-mode Snare drum
+ ChanCat_Rhythm_Snare = 4,
+ //! Rhythm-mode Tom-Tom
+ ChanCat_Rhythm_Tom = 5,
+ //! Rhythm-mode Cymbal
+ ChanCat_Rhythm_Cymbal = 6,
+ //! Rhythm-mode Hi-Hat
+ ChanCat_Rhythm_HiHat = 7,
+ //! Rhythm-mode Slave channel
+ ChanCat_Rhythm_Slave = 8
+ };
+
+ //! Category of the channel
+ /*! 1 = quad-master, 2 = quad-slave, 0 = regular
+ 3 = percussion BassDrum
+ 4 = percussion Snare
+ 5 = percussion Tom
+ 6 = percussion Crash cymbal
+ 7 = percussion Hihat
+ 8 = percussion slave
+ */
+ std::vector<uint32_t> m_channelCategory;
+
+
+ /**
+ * @brief C.O. Constructor
+ */
+ OPL3();
+
+ /**
+ * @brief C.O. Destructor
+ */
+ ~OPL3();
+
+ /**
+ * @brief Checks are setup locked to be changed on the fly or not
+ * @return true when setup on the fly is locked
+ */
+ bool setupLocked();
+
+ /**
+ * @brief Choose one of embedded banks
+ * @param bank ID of the bank
+ */
+ void setEmbeddedBank(uint32_t bank);
+
+ /**
+ * @brief Write data to OPL3 chip register
+ * @param chip Index of emulated chip. In hardware OPL3 builds, this parameter is ignored
+ * @param address Register address to write
+ * @param value Value to write
+ */
+ void writeReg(size_t chip, uint16_t address, uint8_t value);
+
+ /**
+ * @brief Write data to OPL3 chip register
+ * @param chip Index of emulated chip. In hardware OPL3 builds, this parameter is ignored
+ * @param address Register address to write
+ * @param value Value to write
+ */
+ void writeRegI(size_t chip, uint32_t address, uint32_t value);
+
+ /**
+ * @brief Write to soft panning control of OPL3 chip emulator
+ * @param chip Index of emulated chip.
+ * @param address Register of channel to write
+ * @param value Value to write
+ */
+ void writePan(size_t chip, uint32_t address, uint32_t value);
+
+ /**
+ * @brief Off the note in specified chip channel
+ * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ */
+ void noteOff(size_t c);
+
+ /**
+ * @brief On the note in specified chip channel with specified frequency of the tone
+ * @param c1 Channel of chip [or master 4-op channel] (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param c2 Slave 4-op channel of chip, unused for 2op (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param hertz Frequency of the tone in hertzes
+ */
+ void noteOn(size_t c1, size_t c2, double hertz);
+
+ /**
+ * @brief Change setup of instrument in specified chip channel
+ * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param volume Volume level (from 0 to 63)
+ * @param brightness CC74 Brightness level (from 0 to 127)
+ */
+ void touchNote(size_t c, uint8_t volume, uint8_t brightness = 127);
+
+ /**
+ * @brief Set the instrument into specified chip channel
+ * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param instrument Instrument data to set into the chip channel
+ */
+ void setPatch(size_t c, const adldata &instrument);
+
+ /**
+ * @brief Set panpot position
+ * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param value 3-bit panpot value
+ */
+ void setPan(size_t c, uint8_t value);
+
+ /**
+ * @brief Shut up all chip channels
+ */
+ void silenceAll();
+
+ /**
+ * @brief Commit updated flag states to chip registers
+ */
+ void updateChannelCategories();
+
+ /**
+ * @brief commit deepTremolo and deepVibrato flags
+ */
+ void commitDeepFlags();
+
+ /**
+ * @brief Set the volume scaling model
+ * @param volumeModel Type of volume scale model scale
+ */
+ void setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel);
+
+ /**
+ * @brief Get the volume scaling model
+ */
+ 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
+ * @param emulator Type of chip emulator
+ * @param PCM_RATE Output sample rate to generate on output
+ * @param audioTickHandler PCM-accurate clock hook
+ */
+ void reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler);
+};
+
+/**
+ * @brief Check emulator availability
+ * @param emulator Emulator ID (ADL_Emulator)
+ * @return true when emulator is available
+ */
+extern bool adl_isEmulatorAvailable(int emulator);
+
+/**
+ * @brief Find highest emulator
+ * @return The ADL_Emulator enum value which contains ID of highest emulator
+ */
+extern int adl_getHighestEmulator();
+
+/**
+ * @brief Find lowest emulator
+ * @return The ADL_Emulator enum value which contains ID of lowest emulator
+ */
+extern int adl_getLowestEmulator();
+
+#endif // ADLMIDI_OPL3_HPP
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index 59ba555..95e6ea9 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -153,14 +153,10 @@ typedef BW_MidiSequencer MidiSequencer;
#endif
#include "adlmidi_ptr.hpp"
-#include "adlmidi_bankmap.h"
+#include "adlmidi_opl3.hpp"
#define ADL_UNUSED(x) (void)x
-#define OPL_PANNING_LEFT 0x10
-#define OPL_PANNING_RIGHT 0x20
-#define OPL_PANNING_BOTH 0x30
-
#ifdef ADLMIDI_HW_OPL
#define ADL_MAX_CHIPS 1
#define ADL_MAX_CHIPS_STR "1" //Why not just "#MaxCards" ? Watcom fails to pass this with "syntax error" :-P
@@ -218,273 +214,6 @@ inline int32_t adl_cvtU32(int32_t x)
return (uint32_t)adl_cvtS32(x) - (uint32_t)INT32_MIN;
}
-struct ADL_MIDIPlayer;
-class MIDIplay;
-/**
- * @brief OPL3 Chip management class
- */
-class OPL3
-{
- friend class MIDIplay;
- friend class AdlInstrumentTester;
- friend int adlCalculateFourOpChannels(MIDIplay *play, bool silent);
-public:
- enum
- {
- PercussionTag = 1 << 15,
- CustomBankTag = 0xFFFFFFFF
- };
-
- //! Total number of chip channels between all running emulators
- 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()
- std::vector<adldata> m_insCache;
- //! Value written to B0, cached, needed by NoteOff.
- /*! Contains Key on/off state, octave block and frequency number values
- */
- std::vector<uint32_t> m_keyBlockFNumCache;
- //! Cached BD registry value (flags register: DeepTremolo, DeepVibrato, and RhythmMode)
- std::vector<uint32_t> m_regBD;
-
-public:
- /**
- * @brief MIDI bank entry
- */
- struct Bank
- {
- //! MIDI Bank instruments
- adlinsdata2 ins[128];
- };
- typedef BasicBankMap<Bank> BankMap;
- //! MIDI bank instruments data
- BankMap m_insBanks;
- //! MIDI bank-wide setup
- AdlBankSetup m_insBankSetup;
-
-public:
- //! Blank instrument template
- static const adlinsdata2 m_emptyInstrument;
- //! Total number of running concurrent emulated chips
- uint32_t m_numChips;
- //! Currently running embedded bank number. "CustomBankTag" means usign of the custom bank.
- uint32_t m_embeddedBank;
- //! Total number of needed four-operator channels in all running chips
- uint32_t m_numFourOps;
- //! Turn global Deep Tremolo mode on
- bool m_deepTremoloMode;
- //! Turn global Deep Vibrato mode on
- bool m_deepVibratoMode;
- //! Use Rhythm Mode percussions
- bool m_rhythmMode;
- //! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too.
- bool m_scaleModulators;
- //! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates.
- bool m_runAtPcmRate;
- //! Enable soft panning
- bool m_softPanning;
-
- //! Just a padding. Reserved.
- char _padding2[3];
-
- /**
- * @brief Music playing mode
- */
- enum MusicMode
- {
- //! MIDI mode
- MODE_MIDI,
- //! Id-Software Music mode
- MODE_IMF,
- //! Creative Music Files mode
- MODE_CMF,
- //! EA-MUS (a.k.a. RSXX) mode
- MODE_RSXX
- } m_musicMode;
-
- /**
- * @brief Volume models enum
- */
- enum VolumesScale
- {
- //! Generic volume model (linearization of logarithmic scale)
- VOLUME_Generic,
- //! OPL3 native logarithmic scale
- VOLUME_NATIVE,
- //! DMX volume scale logarithmic table
- VOLUME_DMX,
- //! Apoge Sound System volume scaling model
- VOLUME_APOGEE,
- //! Windows 9x driver volume scale table
- VOLUME_9X
- } m_volumeScale;
-
- //! Reserved
- char _padding3[8];
-
- /**
- * @brief Channel categiry enumeration
- */
- enum ChanCat
- {
- //! Regular melodic/percussion channel
- ChanCat_Regular = 0,
- //! Four-op master
- ChanCat_4op_Master = 1,
- //! Four-op slave
- ChanCat_4op_Slave = 2,
- //! Rhythm-mode Bass drum
- ChanCat_Rhythm_Bass = 3,
- //! Rhythm-mode Snare drum
- ChanCat_Rhythm_Snare = 4,
- //! Rhythm-mode Tom-Tom
- ChanCat_Rhythm_Tom = 5,
- //! Rhythm-mode Cymbal
- ChanCat_Rhythm_Cymbal = 6,
- //! Rhythm-mode Hi-Hat
- ChanCat_Rhythm_HiHat = 7,
- //! Rhythm-mode Slave channel
- ChanCat_Rhythm_Slave = 8
- };
-
- //! Category of the channel
- /*! 1 = quad-master, 2 = quad-slave, 0 = regular
- 3 = percussion BassDrum
- 4 = percussion Snare
- 5 = percussion Tom
- 6 = percussion Crash cymbal
- 7 = percussion Hihat
- 8 = percussion slave
- */
- std::vector<uint32_t> m_channelCategory;
-
-
- /**
- * @brief C.O. Constructor
- */
- OPL3();
-
- /**
- * @brief Checks are setup locked to be changed on the fly or not
- * @return true when setup on the fly is locked
- */
- bool setupLocked();
-
- /**
- * @brief Choose one of embedded banks
- * @param bank ID of the bank
- */
- void setEmbeddedBank(uint32_t bank);
-
- /**
- * @brief Write data to OPL3 chip register
- * @param chip Index of emulated chip. In hardware OPL3 builds, this parameter is ignored
- * @param address Register address to write
- * @param value Value to write
- */
- void writeReg(size_t chip, uint16_t address, uint8_t value);
-
- /**
- * @brief Write data to OPL3 chip register
- * @param chip Index of emulated chip. In hardware OPL3 builds, this parameter is ignored
- * @param address Register address to write
- * @param value Value to write
- */
- void writeRegI(size_t chip, uint32_t address, uint32_t value);
-
- /**
- * @brief Write to soft panning control of OPL3 chip emulator
- * @param chip Index of emulated chip.
- * @param address Register of channel to write
- * @param value Value to write
- */
- void writePan(size_t chip, uint32_t address, uint32_t value);
-
- /**
- * @brief Off the note in specified chip channel
- * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
- */
- void noteOff(size_t c);
-
- /**
- * @brief On the note in specified chip channel with specified frequency of the tone
- * @param c1 Channel of chip [or master 4-op channel] (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
- * @param c2 Slave 4-op channel of chip, unused for 2op (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
- * @param hertz Frequency of the tone in hertzes
- */
- void noteOn(size_t c1, size_t c2, double hertz);
-
- /**
- * @brief Change setup of instrument in specified chip channel
- * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
- * @param volume Volume level (from 0 to 63)
- * @param brightness CC74 Brightness level (from 0 to 127)
- */
- void touchNote(size_t c, uint8_t volume, uint8_t brightness = 127);
-
- /**
- * @brief Set the instrument into specified chip channel
- * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
- * @param instrument Instrument data to set into the chip channel
- */
- void setPatch(size_t c, const adldata &instrument);
-
- /**
- * @brief Set panpot position
- * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
- * @param value 3-bit panpot value
- */
- void setPan(size_t c, uint8_t value);
-
- /**
- * @brief Shut up all chip channels
- */
- void silenceAll();
-
- /**
- * @brief Commit updated flag states to chip registers
- */
- void updateChannelCategories();
-
- /**
- * @brief commit deepTremolo and deepVibrato flags
- */
- void commitDeepFlags();
-
- /**
- * @brief Set the volume scaling model
- * @param volumeModel Type of volume scale model scale
- */
- void setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel);
-
- /**
- * @brief Get the volume scaling model
- */
- 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
- * @param emulator Type of chip emulator
- * @param PCM_RATE Output sample rate to generate on output
- * @param audioTickHandler PCM-accurate clock hook
- */
- void reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler);
-};
-
/**
* @brief Hooks of the internal events
@@ -1505,23 +1234,4 @@ extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate)
*/
extern int adlCalculateFourOpChannels(MIDIplay *play, bool silent = false);
-/**
- * @brief Check emulator availability
- * @param emulator Emulator ID (ADL_Emulator)
- * @return true when emulator is available
- */
-extern bool adl_isEmulatorAvailable(int emulator);
-
-/**
- * @brief Find highest emulator
- * @return The ADL_Emulator enum value which contains ID of highest emulator
- */
-extern int adl_getHighestEmulator();
-
-/**
- * @brief Find lowest emulator
- * @return The ADL_Emulator enum value which contains ID of lowest emulator
- */
-extern int adl_getLowestEmulator();
-
#endif // ADLMIDI_PRIVATE_HPP