diff options
author | JP Cimalando <jpcima@users.noreply.github.com> | 2018-10-05 19:07:54 +0200 |
---|---|---|
committer | JP Cimalando <jpcima@users.noreply.github.com> | 2018-10-05 19:21:57 +0200 |
commit | 8c33b86d581183c16e5ca32f8775e7994cf25729 (patch) | |
tree | 1891c3c4f402b41583951aab748922e6fac60d6b /src/adlmidi_opl3.hpp | |
parent | 5e9be04e14cca96551cd19f5ee7597a11ad98a8a (diff) | |
download | libADLMIDI-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.hpp | 326 |
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 |