1 /* 2 * libOPNMIDI is a free Software MIDI synthesizer library with OPN2 (YM2612) emulation 3 * 4 * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi> 5 * OPNMIDI Library and YM2612 support: Copyright (c) 2017-2020 Vitaly Novichkov <admin@wohlnet.ru> 6 * 7 * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: 8 * http://iki.fi/bisqwit/source/adlmidi.html 9 * 10 * This program is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation, either version 3 of the License, or 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 #ifndef OPNMIDI_OPN2_HPP 25 #define OPNMIDI_OPN2_HPP 26 27 #include "opnbank.h" 28 #include "opnmidi_ptr.hpp" 29 #include "opnmidi_private.hpp" 30 #include "opnmidi_bankmap.h" 31 #include "chips/opn_chip_family.h" 32 33 /** 34 * @brief OPN2 Chip management class 35 */ 36 class OPN2 37 { 38 friend class OPNMIDIplay; 39 public: 40 enum { PercussionTag = 1 << 15 }; 41 42 //! Total number of chip channels between all running emulators 43 uint32_t m_numChannels; 44 //! Just a padding. Reserved. 45 char _padding[4]; 46 //! Running chip emulators 47 std::vector<AdlMIDI_SPtr<OPNChipBase > > m_chips; 48 #ifdef OPNMIDI_MIDI2VGM 49 //! Loop Start hook 50 void (*m_loopStartHook)(void*); 51 //! Loop Start hook data 52 void *m_loopStartHookData; 53 //! Loop End hook 54 void (*m_loopEndHook)(void*); 55 //! Loop End hook data 56 void *m_loopEndHookData; 57 #endif 58 private: 59 //! Cached patch data, needed by Touch() 60 std::vector<OpnTimbre> m_insCache; 61 //! Cached per-channel LFO sensitivity flags 62 std::vector<uint8_t> m_regLFOSens; 63 //! LFO setup registry cache 64 uint8_t m_regLFOSetup; 65 66 public: 67 /** 68 * @brief MIDI bank entry 69 */ 70 struct Bank 71 { 72 //! MIDI Bank instruments 73 OpnInstMeta ins[128]; 74 }; 75 typedef BasicBankMap<Bank> BankMap; 76 //! MIDI bank instruments data 77 BankMap m_insBanks; 78 //! MIDI bank-wide setup 79 OpnBankSetup m_insBankSetup; 80 81 public: 82 //! Blank instrument template 83 static const OpnInstMeta m_emptyInstrument; 84 85 //! Total number of running concurrent emulated chips 86 uint32_t m_numChips; 87 //! Carriers-only are scaled by default by volume level. This flag will tell to scale modulators too. 88 bool m_scaleModulators; 89 //! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates. 90 bool m_runAtPcmRate; 91 //! Enable soft panning 92 bool m_softPanning; 93 //! Master volume, controlled via SysEx (0...127) 94 uint8_t m_masterVolume; 95 96 //! Just a padding. Reserved. 97 char _padding2[3]; 98 99 /** 100 * @brief Music playing mode 101 */ 102 enum MusicMode 103 { 104 //! MIDI mode 105 MODE_MIDI, 106 //! MIDI mode 107 MODE_XMIDI, 108 //! Id-Software Music mode 109 MODE_IMF, 110 //! Creative Music Files mode 111 MODE_CMF, 112 //! EA-MUS (a.k.a. RSXX) mode 113 MODE_RSXX 114 } m_musicMode; 115 116 /** 117 * @brief Volume models enum 118 */ 119 enum VolumesScale 120 { 121 //! Generic volume model (linearization of logarithmic scale) 122 VOLUME_Generic, 123 //! OPN2 native logarithmic scale 124 VOLUME_NATIVE, 125 //! DMX volume scale logarithmic table 126 VOLUME_DMX, 127 //! Apoge Sound System volume scaling model 128 VOLUME_APOGEE, 129 //! Windows 9x driver volume scale table 130 VOLUME_9X 131 } m_volumeScale; 132 133 //! Reserved 134 bool m_lfoEnable; 135 uint8_t m_lfoFrequency; 136 137 //! Category of the channel 138 /*! 1 = DAC, 0 = regular 139 */ 140 std::vector<char> m_channelCategory; 141 142 //! Chip family 143 OPNFamily m_chipFamily; 144 145 /** 146 * @brief C.O. Constructor 147 */ 148 OPN2(); 149 150 /** 151 * @brief C.O. Destructor 152 */ 153 ~OPN2(); 154 155 /** 156 * @brief Checks are setup locked to be changed on the fly or not 157 * @return true when setup on the fly is locked 158 */ 159 bool setupLocked(); 160 161 /** 162 * @brief Write data to OPN2 chip register 163 * @param chip Index of emulated chip. In hardware OPN2 builds, this parameter is ignored 164 * @param port Port of the chip to write 165 * @param index Register address to write 166 * @param value Value to write 167 */ 168 void writeReg(size_t chip, uint8_t port, uint8_t index, uint8_t value); 169 170 /** 171 * @brief Write data to OPN2 chip register 172 * @param chip Index of emulated chip. In hardware OPN2 builds, this parameter is ignored 173 * @param port Port of the chip to write 174 * @param index Register address to write 175 * @param value Value to write 176 */ 177 void writeRegI(size_t chip, uint8_t port, uint32_t index, uint32_t value); 178 179 /** 180 * @brief Write to soft panning control of OPN2 chip emulator 181 * @param chip Index of emulated chip. 182 * @param address Register of channel to write 183 * @param value Value to write 184 */ 185 void writePan(size_t chip, uint32_t index, uint32_t value); 186 187 /** 188 * @brief Off the note in specified chip channel 189 * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)]) 190 */ 191 void noteOff(size_t c); 192 193 /** 194 * @brief On the note in specified chip channel with specified frequency of the tone 195 * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)]) 196 * @param tone The tone to play (integer part - MIDI halftone, decimal part - relative bend offset) 197 */ 198 void noteOn(size_t c, double tone); 199 200 /** 201 * @brief Change setup of instrument in specified chip channel 202 * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)]) 203 * @param volume Volume level (from 0 to 127) 204 * @param brightness CC74 Brightness level (from 0 to 127) 205 */ 206 void touchNote(size_t c, 207 uint_fast32_t velocity, 208 uint_fast32_t channelVolume = 127, 209 uint_fast32_t channelExpression = 127, 210 uint8_t brightness = 127); 211 212 /** 213 * @brief Set the instrument into specified chip channel 214 * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)]) 215 * @param instrument Instrument data to set into the chip channel 216 */ 217 void setPatch(size_t c, const OpnTimbre &instrument); 218 219 /** 220 * @brief Set panpot position 221 * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)]) 222 * @param value 3-bit panpot value 223 */ 224 void setPan(size_t c, uint8_t value); 225 226 /** 227 * @brief Shut up all chip channels 228 */ 229 void silenceAll(); 230 231 /** 232 * @brief commit LFO enable and frequency 233 */ 234 void commitLFOSetup(); 235 236 /** 237 * @brief Set the volume scaling model 238 * @param volumeModel Type of volume scale model scale 239 */ 240 void setVolumeScaleModel(OPNMIDI_VolumeModels volumeModel); 241 242 /** 243 * @brief Get the volume scaling model 244 */ 245 OPNMIDI_VolumeModels getVolumeScaleModel(); 246 247 /** 248 * @brief Clean up all running emulated chip instances 249 */ 250 void clearChips(); 251 252 /** 253 * @brief Reset chip properties and initialize them 254 * @param emulator Type of chip emulator 255 * @param PCM_RATE Output sample rate to generate on output 256 * @param audioTickHandler PCM-accurate clock hook 257 */ 258 void reset(int emulator, unsigned long PCM_RATE, OPNFamily family, void *audioTickHandler); 259 260 /** 261 * @brief Gets the family of current chips 262 * @return the chip family 263 */ 264 OPNFamily chipFamily() const; 265 }; 266 267 /** 268 * @brief Check emulator availability 269 * @param emulator Emulator ID (Opn2_Emulator) 270 * @return true when emulator is available 271 */ 272 extern bool opn2_isEmulatorAvailable(int emulator); 273 274 /** 275 * @brief Find highest emulator 276 * @return The Opn2_Emulator enum value which contains ID of highest emulator 277 */ 278 extern int opn2_getHighestEmulator(); 279 280 /** 281 * @brief Find lowest emulator 282 * @return The Opn2_Emulator enum value which contains ID of lowest emulator 283 */ 284 extern int opn2_getLowestEmulator(); 285 286 #endif // OPNMIDI_OPN2_HPP 287