diff options
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/OPL.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/soundlib/OPL.h | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/OPL.h b/Src/external_dependencies/openmpt-trunk/soundlib/OPL.h new file mode 100644 index 00000000..e8b56bc2 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/soundlib/OPL.h @@ -0,0 +1,125 @@ +/* + * OPL.h + * ----- + * Purpose: Translate data coming from OpenMPT's mixer into OPL commands to be sent to the Opal emulator. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#pragma once + +#include "openmpt/all/BuildSettings.hpp" + +#include "Snd_defs.h" + +class Opal; + +OPENMPT_NAMESPACE_BEGIN + +class OPL +{ +public: + enum OPLRegisters : uint8 + { + // Operators (combine with result of OperatorToRegister) + AM_VIB = 0x20, // AM / VIB / EG / KSR / Multiple (0x20 to 0x35) + KSL_LEVEL = 0x40, // KSL / Total level (0x40 to 0x55) + ATTACK_DECAY = 0x60, // Attack rate / Decay rate (0x60 to 0x75) + SUSTAIN_RELEASE = 0x80, // Sustain level / Release rate (0x80 to 0x95) + WAVE_SELECT = 0xE0, // Wave select (0xE0 to 0xF5) + + // Channels (combine with result of ChannelToRegister) + FNUM_LOW = 0xA0, // F-number low bits (0xA0 to 0xA8) + KEYON_BLOCK = 0xB0, // F-number high bits / Key on / Block (octave) (0xB0 to 0xB8) + FEEDBACK_CONNECTION = 0xC0, // Feedback / Connection (0xC0 to 0xC8) + }; + + enum OPLValues : uint8 + { + // AM_VIB + TREMOLO_ON = 0x80, + VIBRATO_ON = 0x40, + SUSTAIN_ON = 0x20, + KSR = 0x10, // Key scaling rate + MULTIPLE_MASK = 0x0F, // Frequency multiplier + + // KSL_LEVEL + KSL_MASK = 0xC0, // Envelope scaling bits + TOTAL_LEVEL_MASK = 0x3F, // Strength (volume) of OP + + // ATTACK_DECAY + ATTACK_MASK = 0xF0, + DECAY_MASK = 0x0F, + + // SUSTAIN_RELEASE + SUSTAIN_MASK = 0xF0, + RELEASE_MASK = 0x0F, + + // KEYON_BLOCK + KEYON_BIT = 0x20, + + // FEEDBACK_CONNECTION + FEEDBACK_MASK = 0x0E, // Valid just for first OP of a voice + CONNECTION_BIT = 0x01, + VOICE_TO_LEFT = 0x10, + VOICE_TO_RIGHT = 0x20, + STEREO_BITS = VOICE_TO_LEFT | VOICE_TO_RIGHT, + }; + + class IRegisterLogger + { + public: + virtual void Port(CHANNELINDEX c, uint16 reg, uint8 value) = 0; + virtual ~IRegisterLogger() {} + }; + + OPL(uint32 samplerate); + OPL(IRegisterLogger &logger); + ~OPL(); + + void Initialize(uint32 samplerate); + void Mix(int32 *buffer, size_t count, uint32 volumeFactorQ16); + + void NoteOff(CHANNELINDEX c); + void NoteCut(CHANNELINDEX c, bool unassign = true); + void Frequency(CHANNELINDEX c, uint32 milliHertz, bool keyOff, bool beatingOscillators); + void Volume(CHANNELINDEX c, uint8 vol, bool applyToModulator); + int8 Pan(CHANNELINDEX c, int32 pan); + void Patch(CHANNELINDEX c, const OPLPatch &patch); + bool IsActive(CHANNELINDEX c) const { return GetVoice(c) != OPL_CHANNEL_INVALID; } + void MoveChannel(CHANNELINDEX from, CHANNELINDEX to); + void Reset(); + + // A list of all registers for channels and operators + static std::vector<uint16> AllVoiceRegisters(); + +protected: + static uint16 ChannelToRegister(uint8 oplCh); + static uint16 OperatorToRegister(uint8 oplCh); + static uint8 CalcVolume(uint8 trackerVol, uint8 kslVolume); + uint8 GetVoice(CHANNELINDEX c) const; + uint8 AllocateVoice(CHANNELINDEX c); + void Port(CHANNELINDEX c, uint16 reg, uint8 value); + + enum + { + OPL_CHANNELS = 18, // 9 for OPL2 or 18 for OPL3 + OPL_CHANNEL_CUT = 0x80, // Indicates that the channel has been cut and used as a hint to re-use the channel for the same tracker channel if possible + OPL_CHANNEL_MASK = 0x7F, + OPL_CHANNEL_INVALID = 0xFF, + OPL_BASERATE = 49716, + }; + + std::unique_ptr<Opal> m_opl; + IRegisterLogger *m_logger = nullptr; + + std::array<uint8, OPL_CHANNELS> m_KeyOnBlock; + std::array<CHANNELINDEX, OPL_CHANNELS> m_OPLtoChan; + std::array<uint8, MAX_CHANNELS> m_ChanToOPL; + std::array<OPLPatch, OPL_CHANNELS> m_Patches; + + bool m_isActive = false; +}; + +OPENMPT_NAMESPACE_END |