OPL.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * OPL.h
  3. * -----
  4. * Purpose: Translate data coming from OpenMPT's mixer into OPL commands to be sent to the Opal emulator.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "Snd_defs.h"
  12. class Opal;
  13. OPENMPT_NAMESPACE_BEGIN
  14. class OPL
  15. {
  16. public:
  17. enum OPLRegisters : uint8
  18. {
  19. // Operators (combine with result of OperatorToRegister)
  20. AM_VIB = 0x20, // AM / VIB / EG / KSR / Multiple (0x20 to 0x35)
  21. KSL_LEVEL = 0x40, // KSL / Total level (0x40 to 0x55)
  22. ATTACK_DECAY = 0x60, // Attack rate / Decay rate (0x60 to 0x75)
  23. SUSTAIN_RELEASE = 0x80, // Sustain level / Release rate (0x80 to 0x95)
  24. WAVE_SELECT = 0xE0, // Wave select (0xE0 to 0xF5)
  25. // Channels (combine with result of ChannelToRegister)
  26. FNUM_LOW = 0xA0, // F-number low bits (0xA0 to 0xA8)
  27. KEYON_BLOCK = 0xB0, // F-number high bits / Key on / Block (octave) (0xB0 to 0xB8)
  28. FEEDBACK_CONNECTION = 0xC0, // Feedback / Connection (0xC0 to 0xC8)
  29. };
  30. enum OPLValues : uint8
  31. {
  32. // AM_VIB
  33. TREMOLO_ON = 0x80,
  34. VIBRATO_ON = 0x40,
  35. SUSTAIN_ON = 0x20,
  36. KSR = 0x10, // Key scaling rate
  37. MULTIPLE_MASK = 0x0F, // Frequency multiplier
  38. // KSL_LEVEL
  39. KSL_MASK = 0xC0, // Envelope scaling bits
  40. TOTAL_LEVEL_MASK = 0x3F, // Strength (volume) of OP
  41. // ATTACK_DECAY
  42. ATTACK_MASK = 0xF0,
  43. DECAY_MASK = 0x0F,
  44. // SUSTAIN_RELEASE
  45. SUSTAIN_MASK = 0xF0,
  46. RELEASE_MASK = 0x0F,
  47. // KEYON_BLOCK
  48. KEYON_BIT = 0x20,
  49. // FEEDBACK_CONNECTION
  50. FEEDBACK_MASK = 0x0E, // Valid just for first OP of a voice
  51. CONNECTION_BIT = 0x01,
  52. VOICE_TO_LEFT = 0x10,
  53. VOICE_TO_RIGHT = 0x20,
  54. STEREO_BITS = VOICE_TO_LEFT | VOICE_TO_RIGHT,
  55. };
  56. class IRegisterLogger
  57. {
  58. public:
  59. virtual void Port(CHANNELINDEX c, uint16 reg, uint8 value) = 0;
  60. virtual ~IRegisterLogger() {}
  61. };
  62. OPL(uint32 samplerate);
  63. OPL(IRegisterLogger &logger);
  64. ~OPL();
  65. void Initialize(uint32 samplerate);
  66. void Mix(int32 *buffer, size_t count, uint32 volumeFactorQ16);
  67. void NoteOff(CHANNELINDEX c);
  68. void NoteCut(CHANNELINDEX c, bool unassign = true);
  69. void Frequency(CHANNELINDEX c, uint32 milliHertz, bool keyOff, bool beatingOscillators);
  70. void Volume(CHANNELINDEX c, uint8 vol, bool applyToModulator);
  71. int8 Pan(CHANNELINDEX c, int32 pan);
  72. void Patch(CHANNELINDEX c, const OPLPatch &patch);
  73. bool IsActive(CHANNELINDEX c) const { return GetVoice(c) != OPL_CHANNEL_INVALID; }
  74. void MoveChannel(CHANNELINDEX from, CHANNELINDEX to);
  75. void Reset();
  76. // A list of all registers for channels and operators
  77. static std::vector<uint16> AllVoiceRegisters();
  78. protected:
  79. static uint16 ChannelToRegister(uint8 oplCh);
  80. static uint16 OperatorToRegister(uint8 oplCh);
  81. static uint8 CalcVolume(uint8 trackerVol, uint8 kslVolume);
  82. uint8 GetVoice(CHANNELINDEX c) const;
  83. uint8 AllocateVoice(CHANNELINDEX c);
  84. void Port(CHANNELINDEX c, uint16 reg, uint8 value);
  85. enum
  86. {
  87. OPL_CHANNELS = 18, // 9 for OPL2 or 18 for OPL3
  88. 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
  89. OPL_CHANNEL_MASK = 0x7F,
  90. OPL_CHANNEL_INVALID = 0xFF,
  91. OPL_BASERATE = 49716,
  92. };
  93. std::unique_ptr<Opal> m_opl;
  94. IRegisterLogger *m_logger = nullptr;
  95. std::array<uint8, OPL_CHANNELS> m_KeyOnBlock;
  96. std::array<CHANNELINDEX, OPL_CHANNELS> m_OPLtoChan;
  97. std::array<uint8, MAX_CHANNELS> m_ChanToOPL;
  98. std::array<OPLPatch, OPL_CHANNELS> m_Patches;
  99. bool m_isActive = false;
  100. };
  101. OPENMPT_NAMESPACE_END