aboutsummaryrefslogtreecommitdiff
path: root/src/adlmidi_opl3.hpp
diff options
context:
space:
mode:
authorJP Cimalando <jpcima@users.noreply.github.com>2018-10-05 19:07:54 +0200
committerJP Cimalando <jpcima@users.noreply.github.com>2018-10-05 19:21:57 +0200
commit8c33b86d581183c16e5ca32f8775e7994cf25729 (patch)
tree1891c3c4f402b41583951aab748922e6fac60d6b /src/adlmidi_opl3.hpp
parent5e9be04e14cca96551cd19f5ee7597a11ad98a8a (diff)
downloadlibADLMIDI-8c33b86d581183c16e5ca32f8775e7994cf25729.tar.gz
libADLMIDI-8c33b86d581183c16e5ca32f8775e7994cf25729.tar.bz2
libADLMIDI-8c33b86d581183c16e5ca32f8775e7994cf25729.zip
reorganize the OPL3 chip manager code
Diffstat (limited to 'src/adlmidi_opl3.hpp')
-rw-r--r--src/adlmidi_opl3.hpp326
1 files changed, 326 insertions, 0 deletions
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