mirror of
https://github.com/ZDoom/ZMusic.git
synced 2024-11-15 00:41:36 +00:00
1d4a016c41
## 1.5.0 2020-09-28 * Drum note length expanding is now supported in real-time mode (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Channels manager has been improved (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Nuked OPL3 1.8 emulator got some optimizations ported from 1.7 where they are was applied previously (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Reworked rhythm-mode percussions system, WOPL banks with rhythm-mode percussions * Added Public Domain Opal OPL3 emulator made by Reality (a team who originally made the Reality Adlib Tracker) (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Added LGPL licensed JavaOPL3 emulator made by Robson Cozendey in Java and later rewritten into C++ for GZDoom (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) * Fully rewritten an embedded bank database format, embedded banks now supports a wider set (more than 127:127 instruments in one bank) * Improved accuracy of the DMX volume model, include the buggy AM interpretation * Improved accuracy of Apogee volume model, include the bug of AM instruments * Improved accuracy of the Win9X volume model * Removed C++ extras. C++-bounded instruments tester is useless since a real-time MIDI API can completely replace it * Added AIL volume model * Added Generic FM variant of Win9X volume model * Fixed an incorrect work of CC-121 (See https://github.com/Wohlstand/libADLMIDI/issues/227 for details) * Added HMI volume model (Thanks to [Alexey Khokholov](https://github.com/nukeykt) for help with research!) * Added frequency models, assigned to every volume model: AIL, HMI, DMX, Apogee, 9X, and the Generic formula
356 lines
11 KiB
C++
356 lines
11 KiB
C++
/*
|
|
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
|
*
|
|
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
|
* ADLMIDI Library API: Copyright (c) 2015-2020 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 "oplinst.h"
|
|
#include "adlmidi_ptr.hpp"
|
|
#include "adlmidi_private.hpp"
|
|
#include "adlmidi_bankmap.h"
|
|
|
|
#define BEND_COEFFICIENT 172.4387
|
|
|
|
#define OPL3_CHANNELS_MELODIC_BASE 0
|
|
#define OPL3_CHANNELS_RHYTHM_BASE 18
|
|
|
|
#define NUM_OF_CHANNELS 23
|
|
#define NUM_OF_4OP_CHANNELS 6
|
|
#define NUM_OF_2OP_CHANNELS 18
|
|
#define NUM_OF_2x2_CHANNELS 9
|
|
#define NUM_OF_RM_CHANNELS 5
|
|
|
|
/**
|
|
* @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<OplTimbre> 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
|
|
OplInstMeta ins[128];
|
|
};
|
|
typedef BasicBankMap<Bank> BankMap;
|
|
//! MIDI bank instruments data
|
|
BankMap m_insBanks;
|
|
//! MIDI bank-wide setup
|
|
OplBankSetup m_insBankSetup;
|
|
|
|
public:
|
|
//! Blank instrument template
|
|
static const OplInstMeta 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;
|
|
//! Master volume, controlled via SysEx (0...127)
|
|
uint8_t m_masterVolume;
|
|
|
|
//! Just a padding. Reserved.
|
|
char _padding2[3];
|
|
|
|
/**
|
|
* @brief Music playing mode
|
|
*/
|
|
enum MusicMode
|
|
{
|
|
//! MIDI mode
|
|
MODE_MIDI,
|
|
//! AIL XMIDI mode
|
|
MODE_XMIDI,
|
|
//! 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 SB16 driver volume scale table
|
|
VOLUME_9X,
|
|
//! DMX model with a fixed bug of AM voices
|
|
VOLUME_DMX_FIXED,
|
|
//! Apogee model with a fixed bug of AM voices
|
|
VOLUME_APOGEE_FIXED,
|
|
//! Audio Interfaces Library volume scaling model
|
|
VOLUME_AIL,
|
|
//! Windows 9x Generic FM driver volume scale table
|
|
VOLUME_9X_GENERIC_FM,
|
|
//! HMI Sound Operating System volume scale table
|
|
VOLUME_HMI,
|
|
//! HMI Sound Operating System volume scale model, older variant
|
|
VOLUME_HMI_OLD
|
|
} m_volumeScale;
|
|
|
|
//! Reserved
|
|
char _padding3[8];
|
|
|
|
/**
|
|
* @brief Channel categiry enumeration
|
|
*/
|
|
enum ChanCat
|
|
{
|
|
//! Regular melodic/percussion channel
|
|
ChanCat_Regular = 0,
|
|
//! Four-op first part
|
|
ChanCat_4op_First = 1,
|
|
//! Four-op second part
|
|
ChanCat_4op_Second = 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 Secondary channel
|
|
ChanCat_Rhythm_Secondary = 8
|
|
};
|
|
|
|
//! Category of the channel
|
|
/*! 1 = quad-first, 2 = quad-second, 0 = regular
|
|
3 = percussion BassDrum
|
|
4 = percussion Snare
|
|
5 = percussion Tom
|
|
6 = percussion Crash cymbal
|
|
7 = percussion Hihat
|
|
8 = percussion Secondary
|
|
*/
|
|
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 Second 4-op channel of chip, unused for 2op (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
|
|
* @param tone The tone to play (integer part - MIDI halftone, decimal part - relative bend offset)
|
|
*/
|
|
void noteOn(size_t c1, size_t c2, double tone);
|
|
|
|
/**
|
|
* @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 velocity Note velocity (from 0 to 127)
|
|
* @param channelVolume Channel volume level (from 0 to 127)
|
|
* @param channelExpression Channel expression level (from 0 to 127)
|
|
* @param brightness CC74 Brightness level (from 0 to 127)
|
|
* @param isDrum Is this a drum note? This flag is needed for some volume model algorithms
|
|
*/
|
|
void touchNote(size_t c,
|
|
uint_fast32_t velocity,
|
|
uint_fast32_t channelVolume = 127,
|
|
uint_fast32_t channelExpression = 127,
|
|
uint_fast32_t brightness = 127,
|
|
bool isDrum = false);
|
|
|
|
/**
|
|
* @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 OplTimbre &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
|