aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/adlmidi.h4
-rw-r--r--src/adldata.hh30
-rw-r--r--src/adlmidi.cpp156
-rw-r--r--src/adlmidi_bankmap.tcc2
-rw-r--r--src/adlmidi_load.cpp61
-rw-r--r--src/adlmidi_midiplay.cpp572
-rw-r--r--src/adlmidi_opl3.cpp402
-rw-r--r--src/adlmidi_private.cpp14
-rw-r--r--src/adlmidi_private.hpp581
-rw-r--r--src/adlmidi_sequencer.cpp10
-rw-r--r--src/chips/opl_chip_base.tcc4
11 files changed, 1102 insertions, 734 deletions
diff --git a/include/adlmidi.h b/include/adlmidi.h
index 8bb0bf1..9b7a6d9 100644
--- a/include/adlmidi.h
+++ b/include/adlmidi.h
@@ -97,7 +97,7 @@ struct ADL_MIDIPlayer
#define adl_setNumCards adl_setNumChips
/* Sets number of emulated chips (from 1 to 100). Emulation of multiple chips exchanges polyphony limits*/
-extern int adl_setNumChips(struct ADL_MIDIPlayer *device, int numCards);
+extern int adl_setNumChips(struct ADL_MIDIPlayer *device, int numChips);
/* Get current number of emulated chips */
extern int adl_getNumChips(struct ADL_MIDIPlayer *device);
@@ -238,7 +238,7 @@ extern const char *adl_errorInfo(struct ADL_MIDIPlayer *device);
extern struct ADL_MIDIPlayer *adl_init(long sample_rate);
/*Set 4-bit device identifier*/
-extern int adl_setDeviceIdentifier(struct ADL_MIDIPlayer *device, unsigned id);
+extern int adl_setDeviceIdentifier(struct ADL_MIDIPlayer *device, ADL_UInt8 id);
/*Load MIDI file from File System*/
extern int adl_openFile(struct ADL_MIDIPlayer *device, const char *filePath);
diff --git a/src/adldata.hh b/src/adldata.hh
index 104db82..73c3d94 100644
--- a/src/adldata.hh
+++ b/src/adldata.hh
@@ -26,6 +26,7 @@
#include <string.h>
#include <stdint.h>
+#include <cstring>
#pragma pack(push, 1)
#define ADLDATA_BYTE_COMPARABLE(T) \
@@ -34,18 +35,17 @@
inline bool operator!=(const T &a, const T &b) \
{ return !operator==(a, b); }
-extern const struct adldata
+struct adldata
{
uint32_t modulator_E862, carrier_E862; // See below
uint8_t modulator_40, carrier_40; // KSL/attenuation settings
uint8_t feedconn; // Feedback/connection bits for the channel
int8_t finetune;
-} adl[];
+};
ADLDATA_BYTE_COMPARABLE(struct adldata)
-enum { adlDefaultNumber = 189 };
-extern const struct adlinsdata
+struct adlinsdata
{
enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02, Flag_Real4op = 0x04 };
@@ -55,11 +55,8 @@ extern const struct adlinsdata
uint16_t ms_sound_kon; // Number of milliseconds it produces sound;
uint16_t ms_sound_koff;
double voice2_fine_tune;
-} adlins[];
+};
ADLDATA_BYTE_COMPARABLE(struct adlinsdata)
-int maxAdlBanks();
-extern const unsigned short banks[][256];
-extern const char* const banknames[];
enum { adlNoteOnMaxTime = 40000 };
@@ -85,14 +82,23 @@ ADLDATA_BYTE_COMPARABLE(struct adlinsdata2)
/**
* @brief Bank global setup
*/
-extern const struct AdlBankSetup
+struct AdlBankSetup
{
int volumeModel;
bool deepTremolo;
bool deepVibrato;
bool adLibPercussions;
bool scaleModulators;
-} adlbanksetup[];
+};
+
+#ifndef DISABLE_EMBEDDED_BANKS
+int maxAdlBanks();
+extern const adldata adl[];
+extern const adlinsdata adlins[];
+extern const unsigned short banks[][256];
+extern const char* const banknames[];
+extern const AdlBankSetup adlbanksetup[];
+#endif
/**
* @brief Conversion of storage formats
@@ -102,8 +108,12 @@ inline adlinsdata2::adlinsdata2(const adlinsdata &d)
ms_sound_kon(d.ms_sound_kon), ms_sound_koff(d.ms_sound_koff),
voice2_fine_tune(d.voice2_fine_tune)
{
+#ifdef DISABLE_EMBEDDED_BANKS
+ std::memset(adl, 0, sizeof(adldata) * 2);
+#else
adl[0] = ::adl[d.adlno1];
adl[1] = ::adl[d.adlno2];
+#endif
}
/**
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp
index f627ce3..1027aef 100644
--- a/src/adlmidi.cpp
+++ b/src/adlmidi.cpp
@@ -24,11 +24,11 @@
#include "adlmidi_private.hpp"
#ifdef ADLMIDI_HW_OPL
-#define MaxCards 1
-#define MaxCards_STR "1" //Why not just "#MaxCards" ? Watcom fails to pass this with "syntax error" :-P
+#define MaxChips 1
+#define MaxChips_STR "1" //Why not just "#MaxCards" ? Watcom fails to pass this with "syntax error" :-P
#else
-#define MaxCards 100
-#define MaxCards_STR "100"
+#define MaxChips 100
+#define MaxChips_STR "100"
#endif
/* Unify MIDI player casting and interface between ADLMIDI and OPNMIDI */
@@ -72,7 +72,7 @@ ADLMIDI_EXPORT struct ADL_MIDIPlayer *adl_init(long sample_rate)
return midi_device;
}
-ADLMIDI_EXPORT int adl_setDeviceIdentifier(ADL_MIDIPlayer *device, unsigned id)
+ADLMIDI_EXPORT int adl_setDeviceIdentifier(ADL_MIDIPlayer *device, ADL_UInt8 id)
{
if(!device || id > 0x0f)
return -1;
@@ -83,25 +83,25 @@ ADLMIDI_EXPORT int adl_setDeviceIdentifier(ADL_MIDIPlayer *device, unsigned id)
return 0;
}
-ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numCards)
+ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numChips)
{
if(device == NULL)
return -2;
MidiPlayer *play = GET_MIDI_PLAYER(device);
#ifdef ADLMIDI_HW_OPL
- (void)numCards;
- play->m_setup.NumCards = 1;
+ ADL_UNUSED(numChips);
+ play->m_setup.numChips = 1;
#else
- play->m_setup.NumCards = static_cast<unsigned int>(numCards);
+ play->m_setup.numChips = static_cast<unsigned int>(numChips);
#endif
- if(play->m_setup.NumCards < 1 || play->m_setup.NumCards > MaxCards)
+ if(play->m_setup.numChips < 1 || play->m_setup.numChips > MaxChips)
{
- play->setErrorString("number of chips may only be 1.." MaxCards_STR ".\n");
+ play->setErrorString("number of chips may only be 1.." MaxChips_STR ".\n");
return -1;
}
- play->opl.NumCards = play->m_setup.NumCards;
+ play->m_synth.m_numChips = play->m_setup.numChips;
adl_reset(device);
return adlRefreshNumCards(device);
@@ -113,16 +113,18 @@ ADLMIDI_EXPORT int adl_getNumChips(struct ADL_MIDIPlayer *device)
return -2;
MidiPlayer *play = GET_MIDI_PLAYER(device);
if(play)
- return (int)play->m_setup.NumCards;
+ return (int)play->m_setup.numChips;
return -2;
}
ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
{
#ifdef DISABLE_EMBEDDED_BANKS
- ADL_UNUSED(device);
ADL_UNUSED(bank);
- ADLMIDI_ErrorString = "This build of libADLMIDI has no embedded banks. Please load bank by using of adl_openBankFile() or adl_openBankData() functions instead of adl_setBank()";
+ MidiPlayer *play = GET_MIDI_PLAYER(device);
+ play->setErrorString("This build of libADLMIDI has no embedded banks. "
+ "Please load bank by using of adl_openBankFile() or "
+ "adl_openBankData() functions instead of adl_setBank()");
return -1;
#else
const uint32_t NumBanks = static_cast<uint32_t>(maxAdlBanks());
@@ -140,8 +142,8 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
return -1;
}
- play->m_setup.AdlBank = static_cast<uint32_t>(bankno);
- play->opl.setEmbeddedBank(play->m_setup.AdlBank);
+ play->m_setup.bankId = static_cast<uint32_t>(bankno);
+ play->m_synth.setEmbeddedBank(play->m_setup.bankId);
play->applySetup();
return adlRefreshNumCards(device);
@@ -150,12 +152,20 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank)
ADLMIDI_EXPORT int adl_getBanksCount()
{
+#ifndef DISABLE_EMBEDDED_BANKS
return maxAdlBanks();
+#else
+ return 0;
+#endif
}
ADLMIDI_EXPORT const char *const *adl_getBankNames()
{
+#ifndef DISABLE_EMBEDDED_BANKS
return banknames;
+#else
+ return NULL;
+#endif
}
ADLMIDI_EXPORT int adl_reserveBanks(ADL_MIDIPlayer *device, unsigned banks)
@@ -163,7 +173,7 @@ ADLMIDI_EXPORT int adl_reserveBanks(ADL_MIDIPlayer *device, unsigned banks)
if(!device)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- OPL3::BankMap &map = play->opl.dynamic_banks;
+ OPL3::BankMap &map = play->m_synth.m_insBanks;
map.reserve(banks);
return (int)map.capacity();
}
@@ -176,10 +186,10 @@ ADLMIDI_EXPORT int adl_getBank(ADL_MIDIPlayer *device, const ADL_BankId *idp, in
ADL_BankId id = *idp;
if(id.lsb > 127 || id.msb > 127 || id.percussive > 1)
return -1;
- unsigned idnumber = (id.msb << 8) | id.lsb | (id.percussive ? OPL3::PercussionTag : 0);
+ uint16_t idnumber = uint16_t((id.msb << 8) | id.lsb | (id.percussive ? OPL3::PercussionTag : 0));
MidiPlayer *play = GET_MIDI_PLAYER(device);
- OPL3::BankMap &map = play->opl.dynamic_banks;
+ OPL3::BankMap &map = play->m_synth.m_insBanks;
OPL3::BankMap::iterator it;
if(!(flags & ADLMIDI_Bank_Create))
@@ -231,7 +241,7 @@ ADLMIDI_EXPORT int adl_removeBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- OPL3::BankMap &map = play->opl.dynamic_banks;
+ OPL3::BankMap &map = play->m_synth.m_insBanks;
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
size_t size = map.size();
map.erase(it);
@@ -244,7 +254,7 @@ ADLMIDI_EXPORT int adl_getFirstBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- OPL3::BankMap &map = play->opl.dynamic_banks;
+ OPL3::BankMap &map = play->m_synth.m_insBanks;
OPL3::BankMap::iterator it = map.begin();
if(it == map.end())
@@ -260,7 +270,7 @@ ADLMIDI_EXPORT int adl_getNextBank(ADL_MIDIPlayer *device, ADL_Bank *bank)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- OPL3::BankMap &map = play->opl.dynamic_banks;
+ OPL3::BankMap &map = play->m_synth.m_insBanks;
OPL3::BankMap::iterator it = OPL3::BankMap::iterator::from_ptrs(bank->pointer);
if(++it == map.end())
@@ -299,16 +309,16 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4)
if(!device)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- if((unsigned int)ops4 > 6 * play->m_setup.NumCards)
+ if((unsigned int)ops4 > 6 * play->m_setup.numChips)
{
char errBuff[250];
- snprintf(errBuff, 250, "number of four-op channels may only be 0..%u when %u OPL3 cards are used.\n", (6 * (play->m_setup.NumCards)), play->m_setup.NumCards);
+ snprintf(errBuff, 250, "number of four-op channels may only be 0..%u when %u OPL3 cards are used.\n", (6 * (play->m_setup.numChips)), play->m_setup.numChips);
play->setErrorString(errBuff);
return -1;
}
- play->m_setup.NumFourOps = static_cast<unsigned int>(ops4);
- play->opl.NumFourOps = play->m_setup.NumFourOps;
+ play->m_setup.numFourOps = static_cast<unsigned int>(ops4);
+ play->m_synth.m_numFourOps = play->m_setup.numFourOps;
return 0; //adlRefreshNumCards(device);
}
@@ -319,7 +329,7 @@ ADLMIDI_EXPORT int adl_getNumFourOpsChn(struct ADL_MIDIPlayer *device)
return -1;
MidiPlayer *play = GET_MIDI_PLAYER(device);
if(play)
- return (int)play->m_setup.NumFourOps;
+ return (int)play->m_setup.numFourOps;
return -1;
}
@@ -327,33 +337,33 @@ ADLMIDI_EXPORT void adl_setPercMode(ADL_MIDIPlayer *device, int percmod)
{
if(!device) return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- play->m_setup.AdlPercussionMode = percmod;
- play->opl.AdlPercussionMode = play->m_setup.AdlPercussionMode < 0 ?
- play->opl.dynamic_bank_setup.adLibPercussions :
- (play->m_setup.AdlPercussionMode != 0);
- play->opl.updateFlags();
+ play->m_setup.rhythmMode = percmod;
+ play->m_synth.m_rhythmMode = play->m_setup.rhythmMode < 0 ?
+ (play->m_synth.m_insBankSetup.adLibPercussions) :
+ (play->m_setup.rhythmMode != 0);
+ play->m_synth.updateChannelCategories();
}
ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro)
{
if(!device) return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- play->m_setup.HighVibratoMode = hvibro;
- play->opl.HighVibratoMode = play->m_setup.HighVibratoMode < 0 ?
- play->opl.dynamic_bank_setup.deepVibrato :
- (play->m_setup.HighVibratoMode != 0);
- play->opl.updateDeepFlags();
+ play->m_setup.deepVibratoMode = hvibro;
+ play->m_synth.m_deepVibratoMode = play->m_setup.deepVibratoMode < 0 ?
+ play->m_synth.m_insBankSetup.deepVibrato :
+ (play->m_setup.deepVibratoMode != 0);
+ play->m_synth.commitDeepFlags();
}
ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo)
{
if(!device) return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
- play->m_setup.HighTremoloMode = htremo;
- play->opl.HighTremoloMode = play->m_setup.HighTremoloMode < 0 ?
- play->opl.dynamic_bank_setup.deepTremolo :
- (play->m_setup.HighTremoloMode != 0);
- play->opl.updateDeepFlags();
+ play->m_setup.deepTremoloMode = htremo;
+ play->m_synth.m_deepTremoloMode = play->m_setup.deepTremoloMode < 0 ?
+ play->m_synth.m_insBankSetup.deepTremolo :
+ (play->m_setup.deepTremoloMode != 0);
+ play->m_synth.commitDeepFlags();
}
ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod)
@@ -363,10 +373,10 @@ ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod)
MidiPlayer *play = GET_MIDI_PLAYER(device);
if(!play)
return;
- play->m_setup.ScaleModulators = smod;
- play->opl.ScaleModulators = play->m_setup.ScaleModulators < 0 ?
- play->opl.dynamic_bank_setup.scaleModulators :
- (play->m_setup.ScaleModulators != 0);
+ play->m_setup.scaleModulators = smod;
+ play->m_synth.m_scaleModulators = play->m_setup.scaleModulators < 0 ?
+ play->m_synth.m_insBankSetup.scaleModulators :
+ (play->m_setup.scaleModulators != 0);
}
ADLMIDI_EXPORT void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, int fr_brightness)
@@ -401,11 +411,11 @@ ADLMIDI_EXPORT void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int
MidiPlayer *play = GET_MIDI_PLAYER(device);
if(!play)
return;
- play->m_setup.LogarithmicVolumes = (logvol != 0);
- if(play->m_setup.LogarithmicVolumes)
- play->opl.ChangeVolumeRangesModel(ADLMIDI_VolumeModel_NativeOPL3);
+ play->m_setup.logarithmicVolumes = (logvol != 0);
+ if(play->m_setup.logarithmicVolumes)
+ play->m_synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3);
else
- play->opl.ChangeVolumeRangesModel(static_cast<ADLMIDI_VolumeModels>(play->opl.m_volumeScale));
+ play->m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(play->m_synth.m_volumeScale));
}
ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int volumeModel)
@@ -415,11 +425,11 @@ ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int v
MidiPlayer *play = GET_MIDI_PLAYER(device);
if(!play)
return;
- play->m_setup.VolumeModel = volumeModel;
- if(play->m_setup.VolumeModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
- play->opl.m_volumeScale = (OPL3::VolumesScale)play->opl.dynamic_bank_setup.volumeModel;
+ play->m_setup.volumeScaleModel = volumeModel;
+ if(play->m_setup.volumeScaleModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
+ play->m_synth.m_volumeScale = (OPL3::VolumesScale)play->m_synth.m_insBankSetup.volumeModel;
else
- play->opl.ChangeVolumeRangesModel(static_cast<ADLMIDI_VolumeModels>(volumeModel));
+ play->m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(volumeModel));
}
ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath)
@@ -532,8 +542,8 @@ ADLMIDI_EXPORT const char *adl_chipEmulatorName(struct ADL_MIDIPlayer *device)
{
#ifndef ADLMIDI_HW_OPL
MidiPlayer *play = GET_MIDI_PLAYER(device);
- if(play && !play->opl.cardsOP2.empty())
- return play->opl.cardsOP2[0]->emulatorName();
+ if(play && !play->m_synth.m_chips.empty())
+ return play->m_synth.m_chips[0]->emulatorName();
#else
return "Hardware OPL3 chip on 0x330";
#endif
@@ -629,10 +639,10 @@ ADLMIDI_EXPORT void adl_reset(struct ADL_MIDIPlayer *device)
return;
MidiPlayer *play = GET_MIDI_PLAYER(device);
play->m_setup.tick_skip_samples_delay = 0;
- play->opl.runAtPcmRate = play->m_setup.runAtPcmRate;
- play->opl.Reset(play->m_setup.emulator, play->m_setup.PCM_RATE, play);
- play->ch.clear();
- play->ch.resize((size_t)play->opl.NumChannels);
+ play->m_synth.m_runAtPcmRate = play->m_setup.runAtPcmRate;
+ play->m_synth.reset(play->m_setup.emulator, play->m_setup.PCM_RATE, play);
+ play->m_chipChannels.clear();
+ play->m_chipChannels.resize((size_t)play->m_synth.m_numChannels);
}
ADLMIDI_EXPORT double adl_totalTimeLength(struct ADL_MIDIPlayer *device)
@@ -1129,9 +1139,9 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
else
{
setup.delay -= eat_delay;
- setup.carry += setup.PCM_RATE * eat_delay;
+ setup.carry += double(setup.PCM_RATE) * eat_delay;
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
- setup.carry -= n_periodCountStereo;
+ setup.carry -= double(n_periodCountStereo);
}
//if(setup.SkipForward > 0)
@@ -1153,18 +1163,18 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
ssize_t in_generatedPhys = in_generatedStereo * 2;
//! Unsigned total sample count
//fill buffer with zeros
- int32_t *out_buf = player->outBuf;
+ int32_t *out_buf = player->m_outBuf;
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
- unsigned int chips = player->opl.NumCards;
+ unsigned int chips = player->m_synth.m_numChips;
if(chips == 1)
{
- player->opl.cardsOP2[0]->generate32(out_buf, (size_t)in_generatedStereo);
+ player->m_synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
}
else if(n_periodCountStereo > 0)
{
/* Generate data from every chip and mix result */
for(size_t card = 0; card < chips; ++card)
- player->opl.cardsOP2[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
+ player->m_synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
}
/* Process it */
@@ -1228,9 +1238,9 @@ ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleC
{//...
const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
delay -= eat_delay;
- setup.carry += setup.PCM_RATE * eat_delay;
+ setup.carry += double(setup.PCM_RATE) * eat_delay;
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
- setup.carry -= n_periodCountStereo;
+ setup.carry -= double(n_periodCountStereo);
{
ssize_t leftSamples = left / 2;
@@ -1242,16 +1252,16 @@ ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleC
ssize_t in_generatedPhys = in_generatedStereo * 2;
//! Unsigned total sample count
//fill buffer with zeros
- int32_t *out_buf = player->outBuf;
+ int32_t *out_buf = player->m_outBuf;
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
- unsigned int chips = player->opl.NumCards;
+ unsigned int chips = player->m_synth.m_numChips;
if(chips == 1)
- player->opl.cardsOP2[0]->generate32(out_buf, (size_t)in_generatedStereo);
+ player->m_synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
else if(n_periodCountStereo > 0)
{
/* Generate data from every chip and mix result */
for(unsigned card = 0; card < chips; ++card)
- player->opl.cardsOP2[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
+ player->m_synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
}
/* Process it */
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
diff --git a/src/adlmidi_bankmap.tcc b/src/adlmidi_bankmap.tcc
index 76e7001..90d8894 100644
--- a/src/adlmidi_bankmap.tcc
+++ b/src/adlmidi_bankmap.tcc
@@ -37,7 +37,7 @@ template <class T>
inline size_t BasicBankMap<T>::hash(key_type key)
{
// disregard the 0 high bit in LSB
- key = (key & 127) | ((key >> 8) << 7);
+ key = key_type(key & 127) | key_type((key >> 8) << 7);
// take low part as hash value
return key & (hash_buckets - 1);
}
diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp
index 9487188..43b74f2 100644
--- a/src/adlmidi_load.cpp
+++ b/src/adlmidi_load.cpp
@@ -215,29 +215,30 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
}
}
- opl.dynamic_bank_setup.adLibPercussions = false;
- opl.dynamic_bank_setup.scaleModulators = false;
- opl.dynamic_bank_setup.deepTremolo = (wopl->opl_flags & WOPL_FLAG_DEEP_TREMOLO) != 0;
- opl.dynamic_bank_setup.deepVibrato = (wopl->opl_flags & WOPL_FLAG_DEEP_VIBRATO) != 0;
- opl.dynamic_bank_setup.volumeModel = wopl->volume_model;
- m_setup.HighTremoloMode = -1;
- m_setup.HighVibratoMode = -1;
- m_setup.VolumeModel = ADLMIDI_VolumeModel_AUTO;
+ m_synth.m_insBankSetup.adLibPercussions = false;
+ m_synth.m_insBankSetup.scaleModulators = false;
+ m_synth.m_insBankSetup.deepTremolo = (wopl->opl_flags & WOPL_FLAG_DEEP_TREMOLO) != 0;
+ m_synth.m_insBankSetup.deepVibrato = (wopl->opl_flags & WOPL_FLAG_DEEP_VIBRATO) != 0;
+ m_synth.m_insBankSetup.volumeModel = wopl->volume_model;
+ m_setup.deepTremoloMode = -1;
+ m_setup.deepVibratoMode = -1;
+ m_setup.volumeScaleModel = ADLMIDI_VolumeModel_AUTO;
- opl.setEmbeddedBank(m_setup.AdlBank);
+ m_synth.setEmbeddedBank(m_setup.bankId);
uint16_t slots_counts[2] = {wopl->banks_count_melodic, wopl->banks_count_percussion};
WOPLBank *slots_src_ins[2] = { wopl->banks_melodic, wopl->banks_percussive };
- for(unsigned ss = 0; ss < 2; ss++)
+ for(size_t ss = 0; ss < 2; ss++)
{
- for(unsigned i = 0; i < slots_counts[ss]; i++)
+ for(size_t i = 0; i < slots_counts[ss]; i++)
{
- unsigned bankno =
+ uint16_t bankno = uint16_t(
(slots_src_ins[ss][i].bank_midi_msb * 256) +
slots_src_ins[ss][i].bank_midi_lsb +
- (ss ? OPL3::PercussionTag : 0);
- OPL3::Bank &bank = opl.dynamic_banks[bankno];
+ (ss ? OPL3::PercussionTag : 0)
+ );
+ OPL3::Bank &bank = m_synth.m_insBanks[bankno];
for(int j = 0; j < 128; j++)
{
adlinsdata2 &ins = bank.ins[j];
@@ -248,7 +249,7 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
}
}
- opl.AdlBank = ~0u; // Use dynamic banks!
+ m_synth.m_embeddedBank = ~0u; // Use dynamic banks!
//Percussion offset is count of instruments multipled to count of melodic banks
applySetup();
@@ -262,7 +263,7 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
bool MIDIplay::LoadMIDI_pre()
{
#ifdef DISABLE_EMBEDDED_BANKS
- if((opl.AdlBank != ~0u) || opl.dynamic_banks.empty())
+ if((m_synth.m_embeddedBank != ~0u) || m_synth.m_insBanks.empty())
{
errorStringOut = "Bank is not set! Please load any instruments bank by using of adl_openBankFile() or adl_openBankData() functions!";
return false;
@@ -284,14 +285,14 @@ bool MIDIplay::LoadMIDI_post()
if(format == MidiSequencer::Format_CMF)
{
const std::vector<MidiSequencer::CmfInstrument> &instruments = m_sequencer.getRawCmfInstruments();
- opl.dynamic_banks.clear();//Clean up old banks
+ m_synth.m_insBanks.clear();//Clean up old banks
uint16_t ins_count = static_cast<uint16_t>(instruments.size());
for(uint16_t i = 0; i < ins_count; ++i)
{
const uint8_t *InsData = instruments[i].data;
uint16_t bank = i / 256;
- bank = (bank & 127) + ((bank >> 7) << 8);
+ bank = uint16_t((bank & 127) + ((bank >> 7) << 8));
if(bank > 127 + (127 << 8))
break;
bank += (i % 256 < 128) ? 0 : OPL3::PercussionTag;
@@ -299,7 +300,7 @@ bool MIDIplay::LoadMIDI_post()
/*std::printf("Ins %3u: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
i, InsData[0],InsData[1],InsData[2],InsData[3], InsData[4],InsData[5],InsData[6],InsData[7],
InsData[8],InsData[9],InsData[10],InsData[11], InsData[12],InsData[13],InsData[14],InsData[15]);*/
- adlinsdata2 &adlins = opl.dynamic_banks[bank].ins[i % 128];
+ adlinsdata2 &adlins = m_synth.m_insBanks[bank].ins[i % 128];
adldata adl;
adl.modulator_E862 =
((static_cast<uint32_t>(InsData[8] & 0x07) << 24) & 0xFF000000) //WaveForm
@@ -324,29 +325,29 @@ bool MIDIplay::LoadMIDI_post()
adlins.voice2_fine_tune = 0.0;
}
- opl.AdlBank = ~0u; // Ignore AdlBank number, use dynamic banks instead
+ m_synth.m_embeddedBank = ~0u; // Ignore AdlBank number, use dynamic banks instead
//std::printf("CMF deltas %u ticks %u, basictempo = %u\n", deltas, ticks, basictempo);
- opl.AdlPercussionMode = true;
- opl.m_musicMode = OPL3::MODE_CMF;
- opl.m_volumeScale = OPL3::VOLUME_NATIVE;
+ m_synth.m_rhythmMode = true;
+ m_synth.m_musicMode = OPL3::MODE_CMF;
+ m_synth.m_volumeScale = OPL3::VOLUME_NATIVE;
}
else if(format == MidiSequencer::Format_RSXX)
{
//opl.CartoonersVolumes = true;
- opl.m_musicMode = OPL3::MODE_RSXX;
- opl.m_volumeScale = OPL3::VOLUME_NATIVE;
+ m_synth.m_musicMode = OPL3::MODE_RSXX;
+ m_synth.m_volumeScale = OPL3::VOLUME_NATIVE;
}
else if(format == MidiSequencer::Format_IMF)
{
//std::fprintf(stderr, "Done reading IMF file\n");
- opl.NumFourOps = 0; //Don't use 4-operator channels for IMF playing!
- opl.m_musicMode = OPL3::MODE_IMF;
+ m_synth.m_numFourOps = 0; //Don't use 4-operator channels for IMF playing!
+ m_synth.m_musicMode = OPL3::MODE_IMF;
}
- opl.Reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip
+ m_synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip
//opl.Reset(); // ...twice (just in case someone misprogrammed OPL3 previously)
- ch.clear();
- ch.resize(opl.NumChannels);
+ m_chipChannels.clear();
+ m_chipChannels.resize(m_synth.m_numChannels);
return true;
}
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index 190a521..ecf2732 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -100,7 +100,7 @@ inline bool isXgPercChannel(uint8_t msb, uint8_t lsb)
return (msb == 0x7E || msb == 0x7F) && (lsb == 0);
}
-void MIDIplay::AdlChannel::AddAge(int64_t ms)
+void MIDIplay::AdlChannel::addAge(int64_t ms)
{
const int64_t neg = static_cast<int64_t>(-0x1FFFFFFFl);
if(users_empty())
@@ -118,7 +118,7 @@ void MIDIplay::AdlChannel::AddAge(int64_t ms)
}
MIDIplay::MIDIplay(unsigned long sampleRate):
- cmf_percussion_mode(false),
+ m_cmfPercussionMode(false),
m_masterVolume(MasterVolumeDefault),
m_sysExDeviceId(0),
m_synthMode(Mode_XG),
@@ -127,7 +127,7 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
, m_audioTickCounter(0)
#endif
{
- devices.clear();
+ m_midiDevices.clear();
m_setup.emulator = ADLMIDI_EMU_NUKED;
m_setup.runAtPcmRate = false;
@@ -136,16 +136,16 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
m_setup.mindelay = 1.0 / (double)m_setup.PCM_RATE;
m_setup.maxdelay = 512.0 / (double)m_setup.PCM_RATE;
- m_setup.AdlBank = 0;
- m_setup.NumFourOps = 7;
- m_setup.NumCards = 2;
- m_setup.HighTremoloMode = -1;
- m_setup.HighVibratoMode = -1;
- m_setup.AdlPercussionMode = -1;
- m_setup.LogarithmicVolumes = false;
- m_setup.VolumeModel = ADLMIDI_VolumeModel_AUTO;
+ m_setup.bankId = 0;
+ m_setup.numFourOps = 7;
+ m_setup.numChips = 2;
+ m_setup.deepTremoloMode = -1;
+ m_setup.deepVibratoMode = -1;
+ m_setup.rhythmMode = -1;
+ m_setup.logarithmicVolumes = false;
+ m_setup.volumeScaleModel = ADLMIDI_VolumeModel_AUTO;
//m_setup.SkipForward = 0;
- m_setup.ScaleModulators = -1;
+ m_setup.scaleModulators = -1;
m_setup.fullRangeBrightnessCC74 = false;
m_setup.delay = 0.0;
m_setup.carry = 0.0;
@@ -155,49 +155,51 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
initSequencerInterface();
#endif
applySetup();
- ChooseDevice("none");
+ chooseDevice("none");
realTime_ResetState();
}
void MIDIplay::applySetup()
{
- opl.m_musicMode = OPL3::MODE_MIDI;
+ m_synth.m_musicMode = OPL3::MODE_MIDI;
m_setup.tick_skip_samples_delay = 0;
- opl.runAtPcmRate = m_setup.runAtPcmRate;
-
- if(opl.AdlBank != ~0u)
- opl.dynamic_bank_setup = adlbanksetup[m_setup.AdlBank];
-
- opl.HighTremoloMode = m_setup.HighTremoloMode < 0 ?
- opl.dynamic_bank_setup.deepTremolo :
- (m_setup.HighTremoloMode != 0);
- opl.HighVibratoMode = m_setup.HighVibratoMode < 0 ?
- opl.dynamic_bank_setup.deepVibrato :
- (m_setup.HighVibratoMode != 0);
- opl.AdlPercussionMode = m_setup.AdlPercussionMode < 0 ?
- opl.dynamic_bank_setup.adLibPercussions :
- (m_setup.AdlPercussionMode != 0);
- opl.ScaleModulators = m_setup.ScaleModulators < 0 ?
- opl.dynamic_bank_setup.scaleModulators :
- (m_setup.ScaleModulators != 0);
-
- if(m_setup.LogarithmicVolumes)
- opl.ChangeVolumeRangesModel(ADLMIDI_VolumeModel_NativeOPL3);
+ m_synth.m_runAtPcmRate = m_setup.runAtPcmRate;
+
+#ifndef DISABLE_EMBEDDED_BANKS
+ if(m_synth.m_embeddedBank != ~0u)
+ m_synth.m_insBankSetup = adlbanksetup[m_setup.bankId];
+#endif
+
+ m_synth.m_deepTremoloMode = m_setup.deepTremoloMode < 0 ?
+ m_synth.m_insBankSetup.deepTremolo :
+ (m_setup.deepTremoloMode != 0);
+ m_synth.m_deepVibratoMode = m_setup.deepVibratoMode < 0 ?
+ m_synth.m_insBankSetup.deepVibrato :
+ (m_setup.deepVibratoMode != 0);
+ m_synth.m_rhythmMode = m_setup.rhythmMode < 0 ?
+ m_synth.m_insBankSetup.adLibPercussions :
+ (m_setup.rhythmMode != 0);
+ m_synth.m_scaleModulators = m_setup.scaleModulators < 0 ?
+ m_synth.m_insBankSetup.scaleModulators :
+ (m_setup.scaleModulators != 0);
+
+ if(m_setup.logarithmicVolumes)
+ m_synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3);
else
- opl.ChangeVolumeRangesModel(static_cast<ADLMIDI_VolumeModels>(m_setup.VolumeModel));
+ m_synth.setVolumeScaleModel(static_cast<ADLMIDI_VolumeModels>(m_setup.volumeScaleModel));
- if(m_setup.VolumeModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
- opl.m_volumeScale = (OPL3::VolumesScale)opl.dynamic_bank_setup.volumeModel;
+ if(m_setup.volumeScaleModel == ADLMIDI_VolumeModel_AUTO)//Use bank default volume model
+ m_synth.m_volumeScale = (OPL3::VolumesScale)m_synth.m_insBankSetup.volumeModel;
- opl.NumCards = m_setup.NumCards;
- opl.NumFourOps = m_setup.NumFourOps;
- cmf_percussion_mode = false;
+ m_synth.m_numChips = m_setup.numChips;
+ m_synth.m_numFourOps = m_setup.numFourOps;
+ m_cmfPercussionMode = false;
- opl.Reset(m_setup.emulator, m_setup.PCM_RATE, this);
- ch.clear();
- ch.resize(opl.NumChannels);
+ m_synth.reset(m_setup.emulator, m_setup.PCM_RATE, this);
+ m_chipChannels.clear();
+ m_chipChannels.resize(m_synth.m_numChannels);
// Reset the arpeggio counter
m_arpeggioCounter = 0;
@@ -205,30 +207,30 @@ void MIDIplay::applySetup()
void MIDIplay::TickIterators(double s)
{
- for(uint16_t c = 0; c < opl.NumChannels; ++c)
- ch[c].AddAge(static_cast<int64_t>(s * 1000.0));
- UpdateVibrato(s);
- UpdateArpeggio(s);
+ for(uint16_t c = 0; c < m_synth.m_numChannels; ++c)
+ m_chipChannels[c].addAge(static_cast<int64_t>(s * 1000.0));
+ updateVibrato(s);
+ updateArpeggio(s);
#if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
- UpdateGlide(s);
+ updateGlide(s);
#endif
}
void MIDIplay::realTime_ResetState()
{
- for(size_t ch = 0; ch < Ch.size(); ch++)
+ for(size_t ch = 0; ch < m_midiChannels.size(); ch++)
{
- MIDIchannel &chan = Ch[ch];
+ MIDIchannel &chan = m_midiChannels[ch];
chan.resetAllControllers();
- chan.volume = (opl.m_musicMode == OPL3::MODE_RSXX) ? 127 : 100;
+ chan.volume = (m_synth.m_musicMode == OPL3::MODE_RSXX) ? 127 : 100;
chan.vibpos = 0.0;
chan.lastlrpn = 0;
chan.lastmrpn = 0;
chan.nrpn = false;
if((m_synthMode & Mode_GS) != 0)// Reset custom drum channels on GS
chan.is_xg_percussion = false;
- NoteUpdate_All(uint16_t(ch), Upd_All);
- NoteUpdate_All(uint16_t(ch), Upd_Off);
+ noteUpdateAll(uint16_t(ch), Upd_All);
+ noteUpdateAll(uint16_t(ch), Upd_Off);
}
m_masterVolume = MasterVolumeDefault;
}
@@ -238,20 +240,20 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(note >= 128)
note = 127;
- if((opl.m_musicMode == OPL3::MODE_RSXX) && (velocity != 0))
+ if((m_synth.m_musicMode == OPL3::MODE_RSXX) && (velocity != 0))
{
// Check if this is just a note after-touch
- MIDIchannel::activenoteiterator i = Ch[channel].activenotes_find(note);
+ MIDIchannel::activenoteiterator i = m_midiChannels[channel].activenotes_find(note);
if(i)
{
i->vol = velocity;
- NoteUpdate(channel, i, Upd_Volume);
+ noteUpdate(channel, i, Upd_Volume);
return false;
}
}
channel = channel % 16;
- NoteOff(channel, note);
+ noteOff(channel, note);
// On Note on, Keyoff the note first, just in case keyoff
// was omitted; this fixes Dance of sugar-plum fairy
// by Microsoft. Now that we've done a Keyoff,
@@ -260,7 +262,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(velocity == 0)
return false;
- MIDIchannel &midiChan = Ch[channel];
+ MIDIchannel &midiChan = m_midiChannels[channel];
size_t midiins = midiChan.patch;
bool isPercussion = (channel % 16 == 9) || midiChan.is_xg_percussion;
@@ -299,14 +301,14 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(isPercussion)
bank += OPL3::PercussionTag;
- const adlinsdata2 *ains = &OPL3::emptyInstrument;
+ const adlinsdata2 *ains = &OPL3::m_emptyInstrument;
//Set bank bank
const OPL3::Bank *bnk = NULL;
if((bank & ~(uint16_t)OPL3::PercussionTag) > 0)
{
- OPL3::BankMap::iterator b = opl.dynamic_banks.find(bank);
- if(b != opl.dynamic_banks.end())
+ OPL3::BankMap::iterator b = m_synth.m_insBanks.find(bank);
+ if(b != m_synth.m_insBanks.end())
bnk = &b->second;
if(bnk)
@@ -324,8 +326,8 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
//Or fall back to first bank
if(ains->flags & adlinsdata::Flag_NoSound)
{
- OPL3::BankMap::iterator b = opl.dynamic_banks.find(bank & OPL3::PercussionTag);
- if(b != opl.dynamic_banks.end())
+ OPL3::BankMap::iterator b = m_synth.m_insBanks.find(bank & OPL3::PercussionTag);
+ if(b != m_synth.m_insBanks.end())
bnk = &b->second;
if(bnk)
@@ -340,7 +342,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(hooks.onDebugMessage)
{
if(caugh_missing_instruments.insert(static_cast<uint8_t>(midiins)).second)
- hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caught a blank instrument %i (offset %i) in the MIDI bank %u", channel, Ch[channel].patch, midiins, bank);
+ hooks.onDebugMessage(hooks.onDebugMessage_userData, "[%i] Caught a blank instrument %i (offset %i) in the MIDI bank %u", channel, m_midiChannels[channel].patch, midiins, bank);
}
bank = 0;
midiins = midiChan.patch;
@@ -376,7 +378,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
voices[1].pseudo4op = pseudo_4op;
#endif /* __WATCOMC__ */
- if((opl.AdlPercussionMode == 1) && PercussionMap[midiins & 0xFF])
+ if((m_synth.m_rhythmMode == 1) && PercussionMap[midiins & 0xFF])
voices[1] = voices[0];//i[1] = i[0];
if(hooks.onDebugMessage)
@@ -402,7 +404,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
int32_t c = -1;
int32_t bs = -0x7FFFFFFFl;
- for(size_t a = 0; a < (size_t)opl.NumChannels; ++a)
+ for(size_t a = 0; a < (size_t)m_synth.m_numChannels; ++a)
{
if(ccount == 1 && static_cast<int32_t>(a) == adlchannel[0]) continue;
// ^ Don't use the same channel for primary&secondary
@@ -412,15 +414,15 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
// Only use regular channels
uint8_t expected_mode = 0;
- if(opl.AdlPercussionMode == 1)
+ if(m_synth.m_rhythmMode == 1)
{
- if(cmf_percussion_mode)
+ if(m_cmfPercussionMode)
expected_mode = channel < 11 ? 0 : (3 + channel - 11); // CMF
else
expected_mode = PercussionMap[midiins & 0xFF];
}
- if(opl.four_op_category[a] != expected_mode)
+ if(m_synth.m_channelCategory[a] != expected_mode)
continue;
}
else
@@ -428,7 +430,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
if(ccount == 0)
{
// Only use four-op master channels
- if(opl.four_op_category[a] != 1)
+ if(m_synth.m_channelCategory[a] != 1)
continue;
}
else
@@ -439,7 +441,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
}
}
- int64_t s = CalculateAdlChannelGoodness(a, voices[ccount], channel);
+ int64_t s = calculateAdlChannelGoodness(a, voices[ccount]);
if(s > bs)
{
bs = (int32_t)s; // Best candidate wins
@@ -456,7 +458,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
continue; // Could not play this note. Ignore it.
}
- PrepareAdlChannelForNewNote(static_cast<size_t>(c), voices[ccount]);
+ prepareAdlChannelForNewNote(static_cast<size_t>(c), voices[ccount]);
adlchannel[ccount] = c;
}
@@ -509,21 +511,21 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
ir.first->phys_ensure_find_or_create(chipChan)->assign(voices[ccount]);
}
- NoteUpdate(channel, ir.first, Upd_All | Upd_Patch);
+ noteUpdate(channel, ir.first, Upd_All | Upd_Patch);
return true;
}
void MIDIplay::realTime_NoteOff(uint8_t channel, uint8_t note)
{
channel = channel % 16;
- NoteOff(channel, note);
+ noteOff(channel, note);
}
void MIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal)
{
channel = channel % 16;
- MIDIchannel &chan = Ch[channel];
- MIDIchannel::activenoteiterator i = Ch[channel].activenotes_find(note);
+ MIDIchannel &chan = m_midiChannels[channel];
+ MIDIchannel::activenoteiterator i = m_midiChannels[channel].activenotes_find(note);
if(i)
{
i->vibrato = atVal;
@@ -543,7 +545,7 @@ void MIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t at
void MIDIplay::realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal)
{
channel = channel % 16;
- Ch[channel].aftertouch = atVal;
+ m_midiChannels[channel].aftertouch = atVal;
}
void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
@@ -553,89 +555,89 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
{
case 1: // Adjust vibrato
//UI.PrintLn("%u:vibrato %d", MidCh,value);
- Ch[channel].vibrato = value;
+ m_midiChannels[channel].vibrato = value;
break;
case 0: // Set bank msb (GM bank)
- Ch[channel].bank_msb = value;
+ m_midiChannels[channel].bank_msb = value;
if((m_synthMode & Mode_GS) == 0)// Don't use XG drums on GS synth mode
- Ch[channel].is_xg_percussion = isXgPercChannel(Ch[channel].bank_msb, Ch[channel].bank_lsb);
+ m_midiChannels[channel].is_xg_percussion = isXgPercChannel(m_midiChannels[channel].bank_msb, m_midiChannels[channel].bank_lsb);
break;
case 32: // Set bank lsb (XG bank)
- Ch[channel].bank_lsb = value;
+ m_midiChannels[channel].bank_lsb = value;
if((m_synthMode & Mode_GS) == 0)// Don't use XG drums on GS synth mode
- Ch[channel].is_xg_percussion = isXgPercChannel(Ch[channel].bank_msb, Ch[channel].bank_lsb);
+ m_midiChannels[channel].is_xg_percussion = isXgPercChannel(m_midiChannels[channel].bank_msb, m_midiChannels[channel].bank_lsb);
break;
case 5: // Set portamento msb
- Ch[channel].portamento = static_cast<uint16_t>((Ch[channel].portamento & 0x7F) | (value << 7));
- UpdatePortamento(channel);
+ m_midiChannels[channel].portamento = static_cast<uint16_t>((m_midiChannels[channel].portamento & 0x7F) | (value << 7));
+ updatePortamento(channel);
break;
case 37: // Set portamento lsb
- Ch[channel].portamento = (Ch[channel].portamento & 0x3F80) | (value);
- UpdatePortamento(channel);
+ m_midiChannels[channel].portamento = (m_midiChannels[channel].portamento & 0x3F80) | (value);
+ updatePortamento(channel);
break;
case 65: // Enable/disable portamento
- Ch[channel].portamentoEnable = value >= 64;
- UpdatePortamento(channel);
+ m_midiChannels[channel].portamentoEnable = value >= 64;
+ updatePortamento(channel);
break;
case 7: // Change volume
- Ch[channel].volume = value;
- NoteUpdate_All(channel, Upd_Volume);
+ m_midiChannels[channel].volume = value;
+ noteUpdateAll(channel, Upd_Volume);
break;
case 74: // Change brightness
- Ch[channel].brightness = value;
- NoteUpdate_All(channel, Upd_Volume);
+ m_midiChannels[channel].brightness = value;
+ noteUpdateAll(channel, Upd_Volume);
break;
case 64: // Enable/disable sustain
- Ch[channel].sustain = (value >= 64);
- if(!Ch[channel].sustain)
- KillSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_Pedal);
+ m_midiChannels[channel].sustain = (value >= 64);
+ if(!m_midiChannels[channel].sustain)
+ killSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_Pedal);
break;
case 66: // Enable/disable sostenuto
if(value >= 64) //Find notes and mark them as sostenutoed
- MarkSostenutoNotes(channel);
+ markSostenutoNotes(channel);
else
- KillSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_Sostenuto);
+ killSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_Sostenuto);
break;
case 67: // Enable/disable soft-pedal
- Ch[channel].softPedal = (value >= 64);
+ m_midiChannels[channel].softPedal = (value >= 64);
break;
case 11: // Change expression (another volume factor)
- Ch[channel].expression = value;
- NoteUpdate_All(channel, Upd_Volume);
+ m_midiChannels[channel].expression = value;
+ noteUpdateAll(channel, Upd_Volume);
break;
case 10: // Change panning
- Ch[channel].panning = 0x00;
- if(value < 64 + 32) Ch[channel].panning |= OPL_PANNING_LEFT;
- if(value >= 64 - 32) Ch[channel].panning |= OPL_PANNING_RIGHT;
+ m_midiChannels[channel].panning = 0x00;
+ if(value < 64 + 32) m_midiChannels[channel].panning |= OPL_PANNING_LEFT;
+ if(value >= 64 - 32) m_midiChannels[channel].panning |= OPL_PANNING_RIGHT;
- NoteUpdate_All(channel, Upd_Pan);
+ noteUpdateAll(channel, Upd_Pan);
break;
case 121: // Reset all controllers
- Ch[channel].resetAllControllers();
- NoteUpdate_All(channel, Upd_Pan + Upd_Volume + Upd_Pitch);
+ m_midiChannels[channel].resetAllControllers();
+ noteUpdateAll(channel, Upd_Pan + Upd_Volume + Upd_Pitch);
// Kill all sustained notes
- KillSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_ANY);
+ killSustainingNotes(channel, -1, AdlChannel::LocationData::Sustain_ANY);
break;
case 120: // All sounds off
- NoteUpdate_All(channel, Upd_OffMute);
+ noteUpdateAll(channel, Upd_OffMute);
break;
case 123: // All notes off
- NoteUpdate_All(channel, Upd_Off);
+ noteUpdateAll(channel, Upd_Off);
break;
case 91:
@@ -654,38 +656,39 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
break; // Phaser effect depth. We don't do.
case 98:
- Ch[channel].lastlrpn = value;
- Ch[channel].nrpn = true;
+ m_midiChannels[channel].lastlrpn = value;
+ m_midiChannels[channel].nrpn = true;
break;
case 99:
- Ch[channel].lastmrpn = value;
- Ch[channel].nrpn = true;
+ m_midiChannels[channel].lastmrpn = value;
+ m_midiChannels[channel].nrpn = true;
break;
case 100:
- Ch[channel].lastlrpn = value;
- Ch[channel].nrpn = false;
+ m_midiChannels[channel].lastlrpn = value;
+ m_midiChannels[channel].nrpn = false;
break;
case 101:
- Ch[channel].lastmrpn = value;
- Ch[channel].nrpn = false;
+ m_midiChannels[channel].lastmrpn = value;
+ m_midiChannels[channel].nrpn = false;
break;
case 113:
break; // Related to pitch-bender, used by missimp.mid in Duke3D
case 6:
- SetRPN(channel, value, true);
+ setRPN(channel, value, true);
break;
case 38:
- SetRPN(channel, value, false);
+ setRPN(channel, value, false);
break;
case 103:
- cmf_percussion_mode = (value != 0);
+ if(m_synth.m_musicMode == OPL3::MODE_CMF)
+ m_cmfPercussionMode = (value != 0);
break; // CMF (ctrl 0x67) rhythm mode
default:
@@ -697,40 +700,40 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
void MIDIplay::realTime_PatchChange(uint8_t channel, uint8_t patch)
{
channel = channel % 16;
- Ch[channel].patch = patch;
+ m_midiChannels[channel].patch = patch;
}
void MIDIplay::realTime_PitchBend(uint8_t channel, uint16_t pitch)
{
channel = channel % 16;
- Ch[channel].bend = int(pitch) - 8192;
- NoteUpdate_All(channel, Upd_Pitch);
+ m_midiChannels[channel].bend = int(pitch) - 8192;
+ noteUpdateAll(channel, Upd_Pitch);
}
void MIDIplay::realTime_PitchBend(uint8_t channel, uint8_t msb, uint8_t lsb)
{
channel = channel % 16;
- Ch[channel].bend = int(lsb) + int(msb) * 128 - 8192;
- NoteUpdate_All(channel, Upd_Pitch);
+ m_midiChannels[channel].bend = int(lsb) + int(msb) * 128 - 8192;
+ noteUpdateAll(channel, Upd_Pitch);
}
void MIDIplay::realTime_BankChangeLSB(uint8_t channel, uint8_t lsb)
{
channel = channel % 16;
- Ch[channel].bank_lsb = lsb;
+ m_midiChannels[channel].bank_lsb = lsb;
}
void MIDIplay::realTime_BankChangeMSB(uint8_t channel, uint8_t msb)
{
channel = channel % 16;
- Ch[channel].bank_msb = msb;
+ m_midiChannels[channel].bank_msb = msb;
}
void MIDIplay::realTime_BankChange(uint8_t channel, uint16_t bank)
{
channel = channel % 16;
- Ch[channel].bank_lsb = uint8_t(bank & 0xFF);
- Ch[channel].bank_msb = uint8_t((bank >> 8) & 0xFF);
+ m_midiChannels[channel].bank_lsb = uint8_t(bank & 0xFF);
+ m_midiChannels[channel].bank_msb = uint8_t((bank >> 8) & 0xFF);
}
void MIDIplay::setDeviceId(uint8_t id)
@@ -798,8 +801,8 @@ bool MIDIplay::doUniversalSysEx(unsigned dev, bool realtime, const uint8_t *data
(((unsigned)data[0] & 0x7F)) |
(((unsigned)data[1] & 0x7F) << 7);
m_masterVolume = volume >> 7;
- for(size_t ch = 0; ch < Ch.size(); ch++)
- NoteUpdate_All(uint16_t(ch), Upd_Volume);
+ for(size_t ch = 0; ch < m_midiChannels.size(); ch++)
+ noteUpdateAll(uint16_t(ch), Upd_Volume);
return true;
}
@@ -889,7 +892,7 @@ bool MIDIplay::doRolandSysEx(unsigned dev, const uint8_t *data, size_t size)
{
if(size != 1 || (dev & 0xF0) != 0x10)
break;
- if(Ch.size() < 16)
+ if(m_midiChannels.size() < 16)
break;
unsigned value = data[0] & 0x7F;
const uint8_t channels_map[16] =
@@ -900,7 +903,7 @@ bool MIDIplay::doRolandSysEx(unsigned dev, const uint8_t *data, size_t size)
hooks.onDebugMessage(hooks.onDebugMessage_userData,
"SysEx: Caught Roland Percussion set: %02X on channel %u (from %X)",
value, channels_map[target_channel], target_channel);
- Ch[channels_map[target_channel]].is_xg_percussion = ((value == 0x01)) || ((value == 0x02));
+ m_midiChannels[channels_map[target_channel]].is_xg_percussion = ((value == 0x01)) || ((value == 0x02));
return true;
}
}
@@ -955,19 +958,19 @@ bool MIDIplay::doYamahaSysEx(unsigned dev, const uint8_t *data, size_t size)
void MIDIplay::realTime_panic()
{
- Panic();
- KillSustainingNotes(-1, -1, AdlChannel::LocationData::Sustain_ANY);
+ panic();
+ killSustainingNotes(-1, -1, AdlChannel::LocationData::Sustain_ANY);
}
void MIDIplay::realTime_deviceSwitch(size_t track, const char *data, size_t length)
{
const std::string indata(data, length);
- current_device[track] = ChooseDevice(indata);
+ m_currentMidiDevice[track] = chooseDevice(indata);
}
uint64_t MIDIplay::realTime_currentDevice(size_t track)
{
- return current_device[track];
+ return m_currentMidiDevice[track];
}
void MIDIplay::realTime_rawOPL(uint8_t reg, uint8_t value)
@@ -976,7 +979,7 @@ void MIDIplay::realTime_rawOPL(uint8_t reg, uint8_t value)
value |= 0x30;
//std::printf("OPL poke %02X, %02X\n", reg, value);
//std::fflush(stdout);
- opl.Poke(0, reg, value);
+ m_synth.writeReg(0, reg, value);
}
#if defined(ADLMIDI_AUDIO_TICK_HANDLER)
@@ -993,12 +996,12 @@ void MIDIplay::AudioTick(uint32_t chipId, uint32_t rate)
if(tickNumber % portamentoInterval == 0)
{
double portamentoDelta = timeDelta * portamentoInterval;
- UpdateGlide(portamentoDelta);
+ updateGlide(portamentoDelta);
}
}
#endif
-void MIDIplay::NoteUpdate(uint16_t MidCh,
+void MIDIplay::noteUpdate(uint16_t midCh,
MIDIplay::MIDIchannel::activenoteiterator i,
unsigned props_mask,
int32_t select_adlchn)
@@ -1010,7 +1013,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
const int midiins = static_cast<int>(info.midiins);
const adlinsdata2 &ains = *info.ains;
AdlChannel::Location my_loc;
- my_loc.MidCh = MidCh;
+ my_loc.MidCh = midCh;
my_loc.note = info.note;
for(unsigned ccount = 0, ctotal = info.chip_channels_count; ccount < ctotal; ccount++)
@@ -1022,8 +1025,8 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(props_mask & Upd_Patch)
{
- opl.Patch(c, ins.ains);
- AdlChannel::LocationData *d = ch[c].users_find_or_create(my_loc);
+ m_synth.setPatch(c, ins.ains);
+ AdlChannel::LocationData *d = m_chipChannels[c].users_find_or_create(my_loc);
if(d) // inserts if necessary
{
d->sustained = AdlChannel::LocationData::Sustain_None;
@@ -1045,27 +1048,27 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(props_mask & Upd_Off) // note off
{
- if(!Ch[MidCh].sustain)
+ if(!m_midiChannels[midCh].sustain)
{
- AdlChannel::LocationData *k = ch[c].users_find(my_loc);
+ AdlChannel::LocationData *k = m_chipChannels[c].users_find(my_loc);
bool do_erase_user = (k && ((k->sustained & AdlChannel::LocationData::Sustain_Sostenuto) == 0));
if(do_erase_user)
- ch[c].users_erase(k);
+ m_chipChannels[c].users_erase(k);
if(hooks.onNote)
hooks.onNote(hooks.onNote_userData, c, noteTone, midiins, 0, 0.0);
- if(do_erase_user && ch[c].users_empty())
+ if(do_erase_user && m_chipChannels[c].users_empty())
{
- opl.NoteOff(c);
+ m_synth.noteOff(c);
if(props_mask & Upd_Mute) // Mute the note
{
- opl.Touch_Real(c, 0);
- ch[c].koff_time_until_neglible = 0;
+ m_synth.touchReal(c, 0);
+ m_chipChannels[c].koff_time_until_neglible = 0;
}
else
{
- ch[c].koff_time_until_neglible = ains.ms_sound_koff;
+ m_chipChannels[c].koff_time_until_neglible = ains.ms_sound_koff;
}
}
}
@@ -1073,7 +1076,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
{
// Sustain: Forget about the note, but don't key it off.
// Also will avoid overwriting it very soon.
- AdlChannel::LocationData *d = ch[c].users_find_or_create(my_loc);
+ AdlChannel::LocationData *d = m_chipChannels[c].users_find_or_create(my_loc);
if(d)
d->sustained |= AdlChannel::LocationData::Sustain_Pedal; // note: not erased!
if(hooks.onNote)
@@ -1086,13 +1089,13 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
}
if(props_mask & Upd_Pan)
- opl.Pan(c, Ch[MidCh].panning);
+ m_synth.setPan(c, m_midiChannels[midCh].panning);
if(props_mask & Upd_Volume)
{
uint32_t volume;
- bool is_percussion = (MidCh == 9) || Ch[MidCh].is_xg_percussion;
- uint8_t brightness = is_percussion ? 127 : Ch[MidCh].brightness;
+ bool is_percussion = (midCh == 9) || m_midiChannels[midCh].is_xg_percussion;
+ uint8_t brightness = is_percussion ? 127 : m_midiChannels[midCh].brightness;
if(!m_setup.fullRangeBrightnessCC74)
{
@@ -1103,12 +1106,12 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
brightness *= 2;
}
- switch(opl.m_volumeScale)
+ switch(m_synth.m_volumeScale)
{
default:
case OPL3::VOLUME_Generic:
{
- volume = vol * m_masterVolume * Ch[MidCh].volume * Ch[MidCh].expression;
+ volume = vol * m_masterVolume * m_midiChannels[midCh].volume * m_midiChannels[midCh].expression;
/* If the channel has arpeggio, the effective volume of
* *this* instrument is actually lower due to timesharing.
@@ -1128,7 +1131,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
case OPL3::VOLUME_NATIVE:
{
- volume = vol * Ch[MidCh].volume * Ch[MidCh].expression;
+ volume = vol * m_midiChannels[midCh].volume * m_midiChannels[midCh].expression;
// volume = volume * m_masterVolume / (127 * 127 * 127) / 2;
volume = (volume * m_masterVolume) / 4096766;
}
@@ -1136,7 +1139,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
case OPL3::VOLUME_DMX:
{
- volume = 2 * (Ch[MidCh].volume * Ch[MidCh].expression * m_masterVolume / 16129) + 1;
+ volume = 2 * (m_midiChannels[midCh].volume * m_midiChannels[midCh].expression * m_masterVolume / 16129) + 1;
//volume = 2 * (Ch[MidCh].volume) + 1;
volume = (DMX_volume_mapping_table[(vol < 128) ? vol : 127] * volume) >> 9;
}
@@ -1144,7 +1147,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
case OPL3::VOLUME_APOGEE:
{
- volume = (Ch[MidCh].volume * Ch[MidCh].expression * m_masterVolume / 16129);
+ volume = (m_midiChannels[midCh].volume * m_midiChannels[midCh].expression * m_masterVolume / 16129);
volume = ((64 * (vol + 0x80)) * volume) >> 15;
//volume = ((63 * (vol + 0x80)) * Ch[MidCh].volume) >> 15;
}
@@ -1153,13 +1156,13 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
case OPL3::VOLUME_9X:
{
//volume = 63 - W9X_volume_mapping_table[(((vol * Ch[MidCh].volume /** Ch[MidCh].expression*/) * m_masterVolume / 16129 /*2048383*/) >> 2)];
- volume = 63 - W9X_volume_mapping_table[((vol * Ch[MidCh].volume * Ch[MidCh].expression * m_masterVolume / 2048383) >> 2)];
+ volume = 63 - W9X_volume_mapping_table[((vol * m_midiChannels[midCh].volume * m_midiChannels[midCh].expression * m_masterVolume / 2048383) >> 2)];
//volume = W9X_volume_mapping_table[vol >> 2] + volume;
}
break;
}
- opl.Touch_Real(c, volume, brightness);
+ m_synth.touchReal(c, volume, brightness);
/* DEBUG ONLY!!!
static uint32_t max = 0;
@@ -1177,15 +1180,15 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(props_mask & Upd_Pitch)
{
- AdlChannel::LocationData *d = ch[c].users_find(my_loc);
+ AdlChannel::LocationData *d = m_chipChannels[c].users_find(my_loc);
// Don't bend a sustained note
if(!d || (d->sustained == AdlChannel::LocationData::Sustain_None))
{
- double midibend = Ch[MidCh].bend * Ch[MidCh].bendsense;
+ double midibend = m_midiChannels[midCh].bend * m_midiChannels[midCh].bendsense;
double bend = midibend + ins.ains.finetune;
double phase = 0.0;
- uint8_t vibrato = std::max(Ch[MidCh].vibrato, Ch[MidCh].aftertouch);
+ uint8_t vibrato = std::max(m_midiChannels[midCh].vibrato, m_midiChannels[midCh].aftertouch);
vibrato = std::max(vibrato, i->vibrato);
if((ains.flags & adlinsdata::Flag_Pseudo4op) && ins.pseudo4op)
@@ -1193,11 +1196,11 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
phase = ains.voice2_fine_tune;//0.125; // Detune the note slightly (this is what Doom does)
}
- if(vibrato && (!d || d->vibdelay >= Ch[MidCh].vibdelay))
- bend += static_cast<double>(vibrato) * Ch[MidCh].vibdepth * std::sin(Ch[MidCh].vibpos);
+ if(vibrato && (!d || d->vibdelay >= m_midiChannels[midCh].vibdelay))
+ bend += static_cast<double>(vibrato) * m_midiChannels[midCh].vibdepth * std::sin(m_midiChannels[midCh].vibpos);
#define BEND_COEFFICIENT 172.4387
- opl.NoteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (currentTone + bend + phase)));
+ m_synth.noteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (currentTone + bend + phase)));
#undef BEND_COEFFICIENT
if(hooks.onNote)
hooks.onNote(hooks.onNote_userData, c, noteTone, midiins, vol, midibend);
@@ -1208,8 +1211,18 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(info.chip_channels_count == 0)
{
if(i->glideRate != HUGE_VAL)
- --Ch[MidCh].gliding_note_count;
- Ch[MidCh].activenotes_erase(i);
+ --m_midiChannels[midCh].gliding_note_count;
+ m_midiChannels[midCh].activenotes_erase(i);
+ }
+}
+
+void MIDIplay::noteUpdateAll(size_t midCh, unsigned props_mask)
+{
+ for(MIDIchannel::activenoteiterator
+ i = m_midiChannels[midCh].activenotes_begin(); i;)
+ {
+ MIDIchannel::activenoteiterator j(i++);
+ noteUpdate(midCh, j, props_mask);
}
}
@@ -1223,13 +1236,13 @@ void MIDIplay::setErrorString(const std::string &err)
errorStringOut = err;
}
-int64_t MIDIplay::CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t) const
+int64_t MIDIplay::calculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const
{
- int64_t s = (opl.m_musicMode != OPL3::MODE_CMF) ? -ch[c].koff_time_until_neglible : 0;
+ int64_t s = (m_synth.m_musicMode != OPL3::MODE_CMF) ? -m_chipChannels[c].koff_time_until_neglible : 0;
// Same midi-instrument = some stability
//if(c == MidCh) s += 4;
- for(AdlChannel::LocationData *j = ch[c].users_first; j; j = j->next)
+ for(AdlChannel::LocationData *j = m_chipChannels[c].users_first; j; j = j->next)
{
s -= 4000;
@@ -1239,7 +1252,7 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteI
s -= (j->kon_time_until_neglible / 2);
MIDIchannel::activenoteiterator
- k = const_cast<MIDIchannel &>(Ch[j->loc.MidCh]).activenotes_find(j->loc.note);
+ k = const_cast<MIDIchannel &>(m_midiChannels[j->loc.MidCh]).activenotes_find(j->loc.note);
if(k)
{
@@ -1270,14 +1283,14 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteI
// increase the score slightly.
unsigned n_evacuation_stations = 0;
- for(size_t c2 = 0; c2 < static_cast<size_t>(opl.NumChannels); ++c2)
+ for(size_t c2 = 0; c2 < static_cast<size_t>(m_synth.m_numChannels); ++c2)
{
if(c2 == c) continue;
- if(opl.four_op_category[c2]
- != opl.four_op_category[c]) continue;
+ if(m_synth.m_channelCategory[c2]
+ != m_synth.m_channelCategory[c]) continue;
- for(AdlChannel::LocationData *m = ch[c2].users_first; m; m = m->next)
+ for(AdlChannel::LocationData *m = m_chipChannels[c2].users_first; m; m = m->next)
{
if(m->sustained != AdlChannel::LocationData::Sustain_None) continue;
if(m->vibdelay >= 200) continue;
@@ -1293,12 +1306,12 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteI
}
-void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins)
+void MIDIplay::prepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins)
{
- if(ch[c].users_empty()) return; // Nothing to do
+ if(m_chipChannels[c].users_empty()) return; // Nothing to do
//bool doing_arpeggio = false;
- for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;)
+ for(AdlChannel::LocationData *jnext = m_chipChannels[c].users_first; jnext;)
{
AdlChannel::LocationData *j = jnext;
jnext = jnext->next;
@@ -1308,7 +1321,7 @@ void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo
// Collision: Kill old note,
// UNLESS we're going to do arpeggio
MIDIchannel::activenoteiterator i
- (Ch[j->loc.MidCh].activenotes_ensure_find(j->loc.note));
+ (m_midiChannels[j->loc.MidCh].activenotes_ensure_find(j->loc.note));
// Check if we can do arpeggio.
if((j->vibdelay < 70
@@ -1320,7 +1333,7 @@ void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo
continue;
}
- KillOrEvacuate(c, j, i);
+ killOrEvacuate(c, j, i);
// ^ will also erase j from ch[c].users.
}
}
@@ -1328,15 +1341,15 @@ void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo
// Kill all sustained notes on this channel
// Don't keep them for arpeggio, because arpeggio requires
// an intact "activenotes" record. This is a design flaw.
- KillSustainingNotes(-1, static_cast<int32_t>(c), AdlChannel::LocationData::Sustain_ANY);
+ killSustainingNotes(-1, static_cast<int32_t>(c), AdlChannel::LocationData::Sustain_ANY);
// Keyoff the channel so that it can be retriggered,
// unless the new note will be introduced as just an arpeggio.
- if(ch[c].users_empty())
- opl.NoteOff(c);
+ if(m_chipChannels[c].users_empty())
+ m_synth.noteOff(c);
}
-void MIDIplay::KillOrEvacuate(size_t from_channel,
+void MIDIplay::killOrEvacuate(size_t from_channel,
AdlChannel::LocationData *j,
MIDIplay::MIDIchannel::activenoteiterator i)
{
@@ -1345,7 +1358,7 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
// instrument. This helps if e.g. all channels
// are full of strings and we want to do percussion.
// FIXME: This does not care about four-op entanglements.
- for(uint32_t c = 0; c < opl.NumChannels; ++c)
+ for(uint32_t c = 0; c < m_synth.m_numChannels; ++c)
{
uint16_t cs = static_cast<uint16_t>(c);
@@ -1353,10 +1366,10 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
break;
if(c == from_channel)
continue;
- if(opl.four_op_category[c] != opl.four_op_category[from_channel])
+ if(m_synth.m_channelCategory[c] != m_synth.m_channelCategory[from_channel])
continue;
- AdlChannel &adlch = ch[c];
+ AdlChannel &adlch = m_chipChannels[c];
if(adlch.users_size == AdlChannel::users_max)
continue; // no room for more arpeggio on channel
@@ -1381,9 +1394,9 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
i->phys_erase(static_cast<uint16_t>(from_channel));
i->phys_ensure_find_or_create(cs)->assign(j->ins);
- if(!ch[cs].users_insert(*j))
+ if(!m_chipChannels[cs].users_insert(*j))
assert(false);
- ch[from_channel].users_erase(j);
+ m_chipChannels[from_channel].users_erase(j);
return;
}
}
@@ -1396,24 +1409,24 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
ins
);*/
// Kill it
- NoteUpdate(j->loc.MidCh,
+ noteUpdate(j->loc.MidCh,
i,
Upd_Off,
static_cast<int32_t>(from_channel));
}
-void MIDIplay::Panic()
+void MIDIplay::panic()
{
- for(uint8_t chan = 0; chan < Ch.size(); chan++)
+ for(uint8_t chan = 0; chan < m_midiChannels.size(); chan++)
{
for(uint8_t note = 0; note < 128; note++)
realTime_NoteOff(chan, note);
}
}
-void MIDIplay::KillSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t sustain_type)
+void MIDIplay::killSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t sustain_type)
{
- uint32_t first = 0, last = opl.NumChannels;
+ uint32_t first = 0, last = m_synth.m_numChannels;
if(this_adlchn >= 0)
{
@@ -1423,10 +1436,10 @@ void MIDIplay::KillSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t s
for(uint32_t c = first; c < last; ++c)
{
- if(ch[c].users_empty())
+ if(m_chipChannels[c].users_empty())
continue; // Nothing to do
- for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;)
+ for(AdlChannel::LocationData *jnext = m_chipChannels[c].users_first; jnext;)
{
AdlChannel::LocationData *j = jnext;
jnext = jnext->next;
@@ -1439,25 +1452,25 @@ void MIDIplay::KillSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t s
hooks.onNote(hooks.onNote_userData, (int)c, j->loc.note, midiins, 0, 0.0);
j->sustained &= ~sustain_type;
if((j->sustained == AdlChannel::LocationData::Sustain_None))
- ch[c].users_erase(j);//Remove only when note is clean from any holders
+ m_chipChannels[c].users_erase(j);//Remove only when note is clean from any holders
}
}
// Keyoff the channel, if there are no users left.
- if(ch[c].users_empty())
- opl.NoteOff(c);
+ if(m_chipChannels[c].users_empty())
+ m_synth.noteOff(c);
}
}
-void MIDIplay::MarkSostenutoNotes(int32_t MidCh)
+void MIDIplay::markSostenutoNotes(int32_t MidCh)
{
- uint32_t first = 0, last = opl.NumChannels;
+ uint32_t first = 0, last = m_synth.m_numChannels;
for(uint32_t c = first; c < last; ++c)
{
- if(ch[c].users_empty())
+ if(m_chipChannels[c].users_empty())
continue; // Nothing to do
- for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;)
+ for(AdlChannel::LocationData *jnext = m_chipChannels[c].users_first; jnext;)
{
AdlChannel::LocationData *j = jnext;
jnext = jnext->next;
@@ -1467,40 +1480,40 @@ void MIDIplay::MarkSostenutoNotes(int32_t MidCh)
}
}
-void MIDIplay::SetRPN(unsigned MidCh, unsigned value, bool MSB)
+void MIDIplay::setRPN(unsigned MidCh, unsigned value, bool MSB)
{
- bool nrpn = Ch[MidCh].nrpn;
- unsigned addr = Ch[MidCh].lastmrpn * 0x100 + Ch[MidCh].lastlrpn;
+ bool nrpn = m_midiChannels[MidCh].nrpn;
+ unsigned addr = m_midiChannels[MidCh].lastmrpn * 0x100 + m_midiChannels[MidCh].lastlrpn;
switch(addr + nrpn * 0x10000 + MSB * 0x20000)
{
case 0x0000 + 0*0x10000 + 1*0x20000: // Pitch-bender sensitivity
- Ch[MidCh].bendsense_msb = value;
- Ch[MidCh].updateBendSensitivity();
+ m_midiChannels[MidCh].bendsense_msb = value;
+ m_midiChannels[MidCh].updateBendSensitivity();
break;
case 0x0000 + 0*0x10000 + 0*0x20000: // Pitch-bender sensitivity LSB
- Ch[MidCh].bendsense_lsb = value;
- Ch[MidCh].updateBendSensitivity();
+ m_midiChannels[MidCh].bendsense_lsb = value;
+ m_midiChannels[MidCh].updateBendSensitivity();
break;
case 0x0108 + 1*0x10000 + 1*0x20000:
if((m_synthMode & Mode_XG) != 0) // Vibrato speed
{
- if(value == 64) Ch[MidCh].vibspeed = 1.0;
- else if(value < 100) Ch[MidCh].vibspeed = 1.0 / (1.6e-2 * (value ? value : 1));
- else Ch[MidCh].vibspeed = 1.0 / (0.051153846 * value - 3.4965385);
- Ch[MidCh].vibspeed *= 2 * 3.141592653 * 5.0;
+ if(value == 64) m_midiChannels[MidCh].vibspeed = 1.0;
+ else if(value < 100) m_midiChannels[MidCh].vibspeed = 1.0 / (1.6e-2 * (value ? value : 1));
+ else m_midiChannels[MidCh].vibspeed = 1.0 / (0.051153846 * value - 3.4965385);
+ m_midiChannels[MidCh].vibspeed *= 2 * 3.141592653 * 5.0;
}
break;
case 0x0109 + 1*0x10000 + 1*0x20000:
if((m_synthMode & Mode_XG) != 0) // Vibrato depth
{
- Ch[MidCh].vibdepth = ((value - 64) * 0.15) * 0.01;
+ m_midiChannels[MidCh].vibdepth = ((value - 64) * 0.15) * 0.01;
}
break;
case 0x010A + 1*0x10000 + 1*0x20000:
if((m_synthMode & Mode_XG) != 0) // Vibrato delay in millisecons
{
- Ch[MidCh].vibdelay = value ? int64_t(0.2092 * std::exp(0.0795 * (double)value)) : 0;
+ m_midiChannels[MidCh].vibdelay = value ? int64_t(0.2092 * std::exp(0.0795 * (double)value)) : 0;
}
break;
default:/* UI.PrintLn("%s %04X <- %d (%cSB) (ch %u)",
@@ -1509,63 +1522,53 @@ void MIDIplay::SetRPN(unsigned MidCh, unsigned value, bool MSB)
}
}
-void MIDIplay::UpdatePortamento(unsigned MidCh)
+void MIDIplay::updatePortamento(size_t midCh)
{
double rate = HUGE_VAL;
- uint16_t midival = Ch[MidCh].portamento;
- if(Ch[MidCh].portamentoEnable && midival > 0)
+ uint16_t midival = m_midiChannels[midCh].portamento;
+ if(m_midiChannels[midCh].portamentoEnable && midival > 0)
rate = 350.0 * std::pow(2.0, -0.062 * (1.0 / 128) * midival);
- Ch[MidCh].portamentoRate = rate;
+ m_midiChannels[midCh].portamentoRate = rate;
}
-void MIDIplay::NoteUpdate_All(uint16_t MidCh, unsigned props_mask)
-{
- for(MIDIchannel::activenoteiterator
- i = Ch[MidCh].activenotes_begin(); i;)
- {
- MIDIchannel::activenoteiterator j(i++);
- NoteUpdate(MidCh, j, props_mask);
- }
-}
-void MIDIplay::NoteOff(uint16_t MidCh, uint8_t note)
+void MIDIplay::noteOff(uint16_t midCh, uint8_t note)
{
MIDIchannel::activenoteiterator
- i = Ch[MidCh].activenotes_find(note);
-
+ i = m_midiChannels[midCh].activenotes_find(note);
if(i)
- NoteUpdate(MidCh, i, Upd_Off);
+ noteUpdate(midCh, i, Upd_Off);
}
-void MIDIplay::UpdateVibrato(double amount)
+void MIDIplay::updateVibrato(double amount)
{
- for(size_t a = 0, b = Ch.size(); a < b; ++a)
+ for(size_t a = 0, b = m_midiChannels.size(); a < b; ++a)
{
- if(Ch[a].hasVibrato() && !Ch[a].activenotes_empty())
+ if(m_midiChannels[a].hasVibrato() && !m_midiChannels[a].activenotes_empty())
{
- NoteUpdate_All(static_cast<uint16_t>(a), Upd_Pitch);
- Ch[a].vibpos += amount * Ch[a].vibspeed;
+ noteUpdateAll(static_cast<uint16_t>(a), Upd_Pitch);
+ m_midiChannels[a].vibpos += amount * m_midiChannels[a].vibspeed;
}
else
- Ch[a].vibpos = 0.0;
+ m_midiChannels[a].vibpos = 0.0;
}
}
-uint64_t MIDIplay::ChooseDevice(const std::string &name)
+uint64_t MIDIplay::chooseDevice(const std::string &name)
{
- std::map<std::string, uint64_t>::iterator i = devices.find(name);
+ std::map<std::string, uint64_t>::iterator i = m_midiDevices.find(name);
- if(i != devices.end())
+ if(i != m_midiDevices.end())
return i->second;
- size_t n = devices.size() * 16;
- devices.insert(std::make_pair(name, n));
- Ch.resize(n + 16);
+ size_t n = m_midiDevices.size() * 16;
+ m_midiDevices.insert(std::make_pair(name, n));
+ m_midiChannels.resize(n + 16);
return n;
}
-void MIDIplay::UpdateArpeggio(double) // amount = amount of time passed
+void MIDIplay::updateArpeggio(double) // amount = amount of time passed
{
// If there is an adlib channel that has multiple notes
// simulated on the same channel, arpeggio them.
@@ -1591,17 +1594,17 @@ void MIDIplay::UpdateArpeggio(double) // amount = amount of time passed
++m_arpeggioCounter;
- for(uint32_t c = 0; c < opl.NumChannels; ++c)
+ for(uint32_t c = 0; c < m_synth.m_numChannels; ++c)
{
retry_arpeggio:
if(c > uint32_t(std::numeric_limits<int32_t>::max()))
break;
- size_t n_users = ch[c].users_size;
+ size_t n_users = m_chipChannels[c].users_size;
if(n_users > 1)
{
- AdlChannel::LocationData *i = ch[c].users_first;
+ AdlChannel::LocationData *i = m_chipChannels[c].users_first;
size_t rate_reduction = 3;
if(n_users >= 3)
@@ -1618,17 +1621,17 @@ retry_arpeggio:
{
if(i->kon_time_until_neglible <= 0l)
{
- NoteUpdate(
+ noteUpdate(
i->loc.MidCh,
- Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note),
+ m_midiChannels[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note),
Upd_Off,
static_cast<int32_t>(c));
goto retry_arpeggio;
}
- NoteUpdate(
+ noteUpdate(
i->loc.MidCh,
- Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note),
+ m_midiChannels[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note),
Upd_Pitch | Upd_Volume | Upd_Pan,
static_cast<int32_t>(c));
}
@@ -1636,13 +1639,13 @@ retry_arpeggio:
}
}
-void MIDIplay::UpdateGlide(double amount)
+void MIDIplay::updateGlide(double amount)
{
- size_t num_channels = Ch.size();
+ size_t num_channels = m_midiChannels.size();
for(size_t channel = 0; channel < num_channels; ++channel)
{
- MIDIchannel &midiChan = Ch[channel];
+ MIDIchannel &midiChan = m_midiChannels[channel];
if(midiChan.gliding_note_count == 0)
continue;
@@ -1662,7 +1665,7 @@ void MIDIplay::UpdateGlide(double amount)
if(currentTone != previousTone)
{
it->currentTone = currentTone;
- NoteUpdate(static_cast<uint16_t>(channel), it, Upd_Pitch);
+ noteUpdate(static_cast<uint16_t>(channel), it, Upd_Pitch);
}
}
}
@@ -1683,11 +1686,15 @@ struct AdlInstrumentTester::Impl
ADLMIDI_EXPORT AdlInstrumentTester::AdlInstrumentTester(ADL_MIDIPlayer *device)
: P(new Impl)
{
+#ifndef DISABLE_EMBEDDED_BANKS
MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
P->cur_gm = 0;
P->ins_idx = 0;
P->play = play;
- P->opl = play ? &play->opl : NULL;
+ P->opl = play ? &play->m_synth : NULL;
+#else
+ ADL_UNUSED(device);
+#endif
}
ADLMIDI_EXPORT AdlInstrumentTester::~AdlInstrumentTester()
@@ -1697,6 +1704,7 @@ ADLMIDI_EXPORT AdlInstrumentTester::~AdlInstrumentTester()
ADLMIDI_EXPORT void AdlInstrumentTester::FindAdlList()
{
+#ifndef DISABLE_EMBEDDED_BANKS
const unsigned NumBanks = (unsigned)adl_getBanksCount();
std::set<unsigned> adl_ins_set;
for(unsigned bankno = 0; bankno < NumBanks; ++bankno)
@@ -1704,27 +1712,34 @@ ADLMIDI_EXPORT void AdlInstrumentTester::FindAdlList()
P->adl_ins_list.assign(adl_ins_set.begin(), adl_ins_set.end());
P->ins_idx = 0;
NextAdl(0);
- P->opl->Silence();
+ P->opl->silenceAll();
+#endif
}
ADLMIDI_EXPORT void AdlInstrumentTester::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127
{
+#ifndef DISABLE_EMBEDDED_BANKS
OPL3 *opl = P->opl;
if(opl->m_volumeScale == OPL3::VOLUME_NATIVE)
- opl->Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2);
+ opl->touchReal(c, volume * 127 / (127 * 127 * 127) / 2);
else
{
// The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A)
- opl->Touch_Real(c, volume > 8725 ? static_cast<unsigned int>(std::log((double)volume) * 11.541561 + (0.5 - 104.22845)) : 0);
+ opl->touchReal(c, volume > 8725 ? static_cast<unsigned int>(std::log((double)volume) * 11.541561 + (0.5 - 104.22845)) : 0);
// The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A)
//Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0);
}
+#else
+ ADL_UNUSED(c);
+ ADL_UNUSED(volume);
+#endif
}
ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note)
{
+#ifndef DISABLE_EMBEDDED_BANKS
MIDIplay *play = P->play;
OPL3 *opl = P->opl;
if(P->adl_ins_list.empty()) FindAdlList();
@@ -1763,27 +1778,35 @@ ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note)
}
}
- opl->NoteOff(0);
- opl->NoteOff(3);
- opl->NoteOff(6);
+ opl->noteOff(0);
+ opl->noteOff(3);
+ opl->noteOff(6);
for(unsigned c = 0; c < 2; ++c)
{
if(adlchannel[c] < 0) continue;
- opl->Patch((uint16_t)adlchannel[c], ains.adl[c]);
- opl->Touch_Real((uint16_t)adlchannel[c], 127 * 127 * 100);
- opl->Pan((uint16_t)adlchannel[c], 0x30);
- opl->NoteOn((uint16_t)adlchannel[c], hertz);
+ opl->setPatch(static_cast<size_t>(adlchannel[c]), ains.adl[c]);
+ opl->touchReal(static_cast<size_t>(adlchannel[c]), 63);
+ opl->setPan(static_cast<size_t>(adlchannel[c]), 0x30);
+ opl->noteOn(static_cast<size_t>(adlchannel[c]), hertz);
}
+#else
+ ADL_UNUSED(note);
+#endif
}
ADLMIDI_EXPORT void AdlInstrumentTester::NextGM(int offset)
{
+#ifndef DISABLE_EMBEDDED_BANKS
P->cur_gm = (P->cur_gm + 256 + (uint32_t)offset) & 0xFF;
FindAdlList();
+#else
+ ADL_UNUSED(offset);
+#endif
}
ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset)
{
+#ifndef DISABLE_EMBEDDED_BANKS
//OPL3 *opl = P->opl;
if(P->adl_ins_list.empty()) FindAdlList();
const unsigned NumBanks = (unsigned)adl_getBanksCount();
@@ -1829,10 +1852,14 @@ ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset)
std::printf("\n");
}
+#else
+ ADL_UNUSED(offset);
+#endif
}
ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch)
{
+#ifndef DISABLE_EMBEDDED_BANKS
static const char notes[] = "zsxdcvgbhnjmq2w3er5t6y7ui9o0p";
// c'd'ef'g'a'bC'D'EF'G'A'Bc'd'e
switch(ch)
@@ -1867,6 +1894,9 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch)
if(p && *p)
DoNote((int)(p - notes) - 12);
}
+#else
+ ADL_UNUSED(ch);
+#endif
return true;
}
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index 5d15d00..2d2bc78 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -42,32 +42,8 @@ static const unsigned OPLBase = 0x388;
# endif
#endif
-#ifdef DISABLE_EMBEDDED_BANKS
-/*
- Dummy data which replaces adldata.cpp banks database
-*/
-
-const struct adldata adl[] =
-{
- {0, 0, (unsigned char)'\0', (unsigned char)'\0', (unsigned char)'\0', 0}
-};
-
-const struct adlinsdata adlins[] =
-{
- {0, 0, 0, 0, 0, 0, 0.0}
-};
-
-int maxAdlBanks()
-{
- return 0;
-}
-
-const unsigned short banks[][256] = {{0}};
-const char *const banknames[] = {"<Embedded banks are disabled>"};
-const AdlBankSetup adlbanksetup[] = {{0, 1, 1, 0, 0}};
-#endif
-
-static const unsigned short Operators[23 * 2] =
+//! Per-channel and per-operator registers map
+static const uint16_t g_operatorsMap[23 * 2] =
{
// Channels 0-2
0x000, 0x003, 0x001, 0x004, 0x002, 0x005, // operators 0, 3, 1, 4, 2, 5
@@ -91,7 +67,8 @@ static const unsigned short Operators[23 * 2] =
0x011, 0xFFF
}; // operator 13
-static const unsigned short Channels[23] =
+//! Channel map to regoster offsets
+static const uint16_t g_channelsMap[23] =
{
0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, // 0..8
0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, // 9..17 (secondary set)
@@ -129,19 +106,46 @@ static const unsigned short Channels[23] =
Ports: ???
*/
-void OPL3::setEmbeddedBank(unsigned int bank)
+static adlinsdata2 makeEmptyInstrument()
+{
+ adlinsdata2 ins;
+ memset(&ins, 0, sizeof(adlinsdata2));
+ ins.flags = adlinsdata::Flag_NoSound;
+ return ins;
+}
+
+const adlinsdata2 OPL3::m_emptyInstrument = makeEmptyInstrument();
+
+OPL3::OPL3() :
+ m_numChips(1),
+ m_numFourOps(0),
+ m_deepTremoloMode(false),
+ m_deepVibratoMode(false),
+ m_rhythmMode(false),
+ m_musicMode(MODE_MIDI),
+ m_volumeScale(VOLUME_Generic)
{
- AdlBank = bank;
+#ifdef DISABLE_EMBEDDED_BANKS
+ m_embeddedBank = ~0u;
+#else
+ setEmbeddedBank(0);
+#endif
+}
+
+void OPL3::setEmbeddedBank(uint32_t bank)
+{
+#ifndef DISABLE_EMBEDDED_BANKS
+ m_embeddedBank = bank;
//Embedded banks are supports 128:128 GM set only
- dynamic_banks.clear();
+ m_insBanks.clear();
if(bank >= static_cast<unsigned int>(maxAdlBanks()))
return;
Bank *bank_pair[2] =
{
- &dynamic_banks[0],
- &dynamic_banks[PercussionTag]
+ &m_insBanks[0],
+ &m_insBanks[PercussionTag]
};
for(unsigned i = 0; i < 256; ++i)
@@ -150,79 +154,56 @@ void OPL3::setEmbeddedBank(unsigned int bank)
adlinsdata2 &ins = bank_pair[i / 128]->ins[i % 128];
ins = adlinsdata2(adlins[meta]);
}
-}
-
-static adlinsdata2 makeEmptyInstrument()
-{
- adlinsdata2 ins;
- memset(&ins, 0, sizeof(adlinsdata2));
- ins.flags = adlinsdata::Flag_NoSound;
- return ins;
-}
-
-const adlinsdata2 OPL3::emptyInstrument = makeEmptyInstrument();
-
-OPL3::OPL3() :
- NumCards(1),
- NumFourOps(0),
- HighTremoloMode(false),
- HighVibratoMode(false),
- AdlPercussionMode(false),
- m_musicMode(MODE_MIDI),
- m_volumeScale(VOLUME_Generic)
-{
-#ifdef DISABLE_EMBEDDED_BANKS
- AdlBank = ~0u;
#else
- setEmbeddedBank(0);
+ ADL_UNUSED(bank);
#endif
}
-void OPL3::Poke(size_t card, uint16_t index, uint8_t value)
+void OPL3::writeReg(size_t chip, uint16_t address, uint8_t value)
{
#ifdef ADLMIDI_HW_OPL
- (void)card;
- unsigned o = index >> 8;
+ ADL_UNUSED(chip);
+ unsigned o = address >> 8;
unsigned port = OPLBase + o * 2;
#ifdef __DJGPP__
- outportb(port, index);
+ outportb(port, address);
for(unsigned c = 0; c < 6; ++c) inportb(port);
outportb(port + 1, value);
for(unsigned c = 0; c < 35; ++c) inportb(port);
#endif
#ifdef __WATCOMC__
- outp(port, index);
+ outp(port, address);
for(uint16_t c = 0; c < 6; ++c) inp(port);
outp(port + 1, value);
for(uint16_t c = 0; c < 35; ++c) inp(port);
#endif//__WATCOMC__
- #else
- cardsOP2[card]->writeReg(index, value);
+ #else//ADLMIDI_HW_OPL
+ m_chips[chip]->writeReg(address, value);
#endif
}
-void OPL3::NoteOff(size_t c)
+void OPL3::noteOff(size_t c)
{
size_t card = c / 23, cc = c % 23;
if(cc >= 18)
{
- regBD[card] &= ~(0x10 >> (cc - 18));
- Poke(card, 0xBD, regBD[card]);
+ m_regBD[card] &= ~(0x10 >> (cc - 18));
+ writeReg(card, 0xBD, m_regBD[card]);
return;
}
- Poke(card, 0xB0 + Channels[cc], pit[c] & 0xDF);
+ writeReg(card, 0xB0 + g_channelsMap[cc], m_pit[c] & 0xDF);
}
-void OPL3::NoteOn(unsigned c, double hertz) // Hertz range: 0..131071
+void OPL3::noteOn(size_t c, double hertz) // Hertz range: 0..131071
{
- unsigned card = c / 23, cc = c % 23;
- unsigned x = 0x2000;
+ size_t card = c / 23, cc = c % 23;
+ uint32_t x = 0x2000;
if(hertz < 0 || hertz > 131071) // Avoid infinite loop
return;
@@ -233,53 +214,54 @@ void OPL3::NoteOn(unsigned c, double hertz) // Hertz range: 0..131071
x += 0x400;
}
- x += static_cast<unsigned int>(hertz + 0.5);
- unsigned chn = Channels[cc];
+ x += static_cast<uint32_t>(hertz + 0.5);
+ uint32_t chn = g_channelsMap[cc];
if(cc >= 18)
{
- regBD[card] |= (0x10 >> (cc - 18));
- Poke(card, 0x0BD, regBD[card]);
+ m_regBD[card] |= (0x10 >> (cc - 18));
+ writeReg(card, 0x0BD, m_regBD[card]);
x &= ~0x2000u;
//x |= 0x800; // for test
}
if(chn != 0xFFF)
{
- Poke(card, 0xA0 + chn, x & 0xFF);
- Poke(card, 0xB0 + chn, pit[c] = static_cast<uint8_t>(x >> 8));
+ writeReg(card, 0xA0 + chn, static_cast<uint8_t>(x & 0xFF));
+ writeReg(card, 0xB0 + chn, static_cast<uint8_t>(x >> 8));
+ m_pit[c] = static_cast<uint8_t>(x >> 8);
}
}
-void OPL3::Touch_Real(unsigned c, unsigned volume, uint8_t brightness)
+void OPL3::touchReal(uint32_t c, uint8_t volume, uint8_t brightness)
{
if(volume > 63)
volume = 63;
size_t card = c / 23, cc = c % 23;
- const adldata &adli = ins[c];
- uint16_t o1 = Operators[cc * 2 + 0];
- uint16_t o2 = Operators[cc * 2 + 1];
+ const adldata &adli = m_ins[c];
+ uint16_t o1 = g_operatorsMap[cc * 2 + 0];
+ uint16_t o2 = g_operatorsMap[cc * 2 + 1];
uint8_t x = adli.modulator_40, y = adli.carrier_40;
uint16_t mode = 1; // 2-op AM
- if(four_op_category[c] == 0 || four_op_category[c] == 3)
+ if(m_channelCategory[c] == 0 || m_channelCategory[c] == 3)
{
mode = adli.feedconn & 1; // 2-op FM or 2-op AM
}
- else if(four_op_category[c] == 1 || four_op_category[c] == 2)
+ else if(m_channelCategory[c] == 1 || m_channelCategory[c] == 2)
{
const adldata *i0, *i1;
- if(four_op_category[c] == 1)
+ if(m_channelCategory[c] == 1)
{
i0 = &adli;
- i1 = &ins[c + 3];
+ i1 = &m_ins[c + 3];
mode = 2; // 4-op xx-xx ops 1&2
}
else
{
- i0 = &ins[c - 3];
+ i0 = &m_ins[c - 3];
i1 = &adli;
mode = 6; // 4-op xx-xx ops 3&4
}
@@ -303,14 +285,14 @@ void OPL3::Touch_Real(unsigned c, unsigned volume, uint8_t brightness)
if(m_musicMode == MODE_RSXX)
{
- Poke(card, 0x40 + o1, x);
+ writeReg(card, 0x40 + o1, x);
if(o2 != 0xFFF)
- Poke(card, 0x40 + o2, y - volume / 2);
+ writeReg(card, 0x40 + o2, y - volume / 2);
}
else
{
- bool do_modulator = do_ops[ mode ][ 0 ] || ScaleModulators;
- bool do_carrier = do_ops[ mode ][ 1 ] || ScaleModulators;
+ bool do_modulator = do_ops[ mode ][ 0 ] || m_scaleModulators;
+ bool do_carrier = do_ops[ mode ][ 1 ] || m_scaleModulators;
uint32_t modulator = do_modulator ? (x | 63) - volume + volume * (x & 63) / 63 : x;
uint32_t carrier = do_carrier ? (y | 63) - volume + volume * (y & 63) / 63 : y;
@@ -324,9 +306,9 @@ void OPL3::Touch_Real(unsigned c, unsigned volume, uint8_t brightness)
carrier = (carrier | 63) - brightness + brightness * (carrier & 63) / 63;
}
- Poke(card, 0x40 + o1, modulator);
+ writeReg(card, 0x40 + o1, modulator);
if(o2 != 0xFFF)
- Poke(card, 0x40 + o2, carrier);
+ writeReg(card, 0x40 + o2, carrier);
}
// Correct formula (ST3, AdPlug):
@@ -351,70 +333,69 @@ void OPL3::Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127
}
}*/
-void OPL3::Patch(uint16_t c, const adldata &adli)
+void OPL3::setPatch(uint16_t c, const adldata &instrument)
{
uint16_t card = c / 23, cc = c % 23;
static const uint8_t data[4] = {0x20, 0x60, 0x80, 0xE0};
- ins[c] = adli;
- uint16_t o1 = Operators[cc * 2 + 0];
- uint16_t o2 = Operators[cc * 2 + 1];
- unsigned x = adli.modulator_E862, y = adli.carrier_E862;
+ m_ins[c] = instrument;
+ uint16_t o1 = g_operatorsMap[cc * 2 + 0];
+ uint16_t o2 = g_operatorsMap[cc * 2 + 1];
+ unsigned x = instrument.modulator_E862, y = instrument.carrier_E862;
for(unsigned a = 0; a < 4; ++a, x >>= 8, y >>= 8)
{
- Poke(card, data[a] + o1, x & 0xFF);
+ writeReg(card, data[a] + o1, x & 0xFF);
if(o2 != 0xFFF)
- Poke(card, data[a] + o2, y & 0xFF);
+ writeReg(card, data[a] + o2, y & 0xFF);
}
}
-void OPL3::Pan(unsigned c, unsigned value)
+void OPL3::setPan(size_t c, uint8_t value)
{
- unsigned card = c / 23, cc = c % 23;
-
- if(Channels[cc] != 0xFFF)
- Poke(card, 0xC0 + Channels[cc], ins[c].feedconn | value);
+ size_t card = c / 23, cc = c % 23;
+ if(g_channelsMap[cc] != 0xFFF)
+ writeReg(card, 0xC0 + g_channelsMap[cc], m_ins[c].feedconn | value);
}
-void OPL3::Silence() // Silence all OPL channels.
+void OPL3::silenceAll() // Silence all OPL channels.
{
- for(unsigned c = 0; c < NumChannels; ++c)
+ for(size_t c = 0; c < m_numChannels; ++c)
{
- NoteOff(c);
- Touch_Real(c, 0);
+ noteOff(c);
+ touchReal(c, 0);
}
}
-void OPL3::updateFlags()
+void OPL3::updateChannelCategories()
{
- unsigned fours = NumFourOps;
+ uint32_t fours = m_numFourOps;
- for(unsigned card = 0; card < NumCards; ++card)
+ for(size_t chip = 0; chip < m_numChips; ++chip)
{
- Poke(card, 0x0BD, regBD[card] = (HighTremoloMode * 0x80
- + HighVibratoMode * 0x40
- + AdlPercussionMode * 0x20));
- unsigned fours_this_card = std::min(fours, 6u);
- Poke(card, 0x104, (1 << fours_this_card) - 1);
- fours -= fours_this_card;
+ m_regBD[chip] = (m_deepTremoloMode * 0x80 + m_deepVibratoMode * 0x40 + m_rhythmMode * 0x20);
+ writeReg(chip, 0x0BD, m_regBD[chip]);
+ uint8_t fours_this_chip = std::min(fours, static_cast<uint32_t>(6u));
+ writeReg(chip, 0x104, (1 << fours_this_chip) - 1);
+ fours -= fours_this_chip;
}
// Mark all channels that are reserved for four-operator function
- if(AdlPercussionMode == 1)
- for(unsigned a = 0; a < NumCards; ++a)
+ if(m_rhythmMode == 1)
+ {
+ for(size_t a = 0; a < m_numChips; ++a)
{
- for(unsigned b = 0; b < 5; ++b)
- four_op_category[a * 23 + 18 + b] = static_cast<char>(b + 3);
- for(unsigned b = 0; b < 3; ++b)
- four_op_category[a * 23 + 6 + b] = 8;
+ for(size_t b = 0; b < 5; ++b)
+ m_channelCategory[a * 23 + 18 + b] = static_cast<char>(b + 3);
+ for(size_t b = 0; b < 3; ++b)
+ m_channelCategory[a * 23 + 6 + b] = ChanCat_Rhythm_Slave;
}
+ }
- unsigned nextfour = 0;
-
- for(unsigned a = 0; a < NumFourOps; ++a)
+ size_t nextfour = 0;
+ for(size_t a = 0; a < m_numFourOps; ++a)
{
- four_op_category[nextfour ] = 1;
- four_op_category[nextfour + 3] = 2;
+ m_channelCategory[nextfour] = ChanCat_4op_Master;
+ m_channelCategory[nextfour + 3] = ChanCat_4op_Slave;
switch(a % 6)
{
@@ -434,19 +415,45 @@ void OPL3::updateFlags()
break;
}
}
+
+/**/
+/*
+ In two-op mode, channels 0..8 go as follows:
+ Op1[port] Op2[port]
+ Channel 0: 00 00 03 03
+ Channel 1: 01 01 04 04
+ Channel 2: 02 02 05 05
+ Channel 3: 06 08 09 0B
+ Channel 4: 07 09 10 0C
+ Channel 5: 08 0A 11 0D
+ Channel 6: 12 10 15 13
+ Channel 7: 13 11 16 14
+ Channel 8: 14 12 17 15
+ In four-op mode, channels 0..8 go as follows:
+ Op1[port] Op2[port] Op3[port] Op4[port]
+ Channel 0: 00 00 03 03 06 08 09 0B
+ Channel 1: 01 01 04 04 07 09 10 0C
+ Channel 2: 02 02 05 05 08 0A 11 0D
+ Channel 3: CHANNEL 0 SLAVE
+ Channel 4: CHANNEL 1 SLAVE
+ Channel 5: CHANNEL 2 SLAVE
+ Channel 6: 12 10 15 13
+ Channel 7: 13 11 16 14
+ Channel 8: 14 12 17 15
+ Same goes principally for channels 9-17 respectively.
+ */
}
-void OPL3::updateDeepFlags()
+void OPL3::commitDeepFlags()
{
- for(unsigned card = 0; card < NumCards; ++card)
+ for(size_t chip = 0; chip < m_numChips; ++chip)
{
- Poke(card, 0x0BD, regBD[card] = (HighTremoloMode * 0x80
- + HighVibratoMode * 0x40
- + AdlPercussionMode * 0x20));
+ m_regBD[chip] = (m_deepTremoloMode * 0x80 + m_deepVibratoMode * 0x40 + m_rhythmMode * 0x20);
+ writeReg(chip, 0x0BD, m_regBD[chip]);
}
}
-void OPL3::ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel)
+void OPL3::setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel)
{
switch(volumeModel)
{
@@ -476,18 +483,18 @@ void OPL3::ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel)
}
#ifndef ADLMIDI_HW_OPL
-void OPL3::ClearChips()
+void OPL3::clearChips()
{
- for(size_t i = 0; i < cardsOP2.size(); i++)
- cardsOP2[i].reset(NULL);
- cardsOP2.clear();
+ for(size_t i = 0; i < m_chips.size(); i++)
+ m_chips[i].reset(NULL);
+ m_chips.clear();
}
#endif
-void OPL3::Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
+void OPL3::reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
{
#ifndef ADLMIDI_HW_OPL
- ClearChips();
+ clearChips();
#else
(void)emulator;
(void)PCM_RATE;
@@ -495,24 +502,27 @@ void OPL3::Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
#if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
(void)audioTickHandler;
#endif
- ins.clear();
- pit.clear();
- regBD.clear();
+ m_ins.clear();
+ m_pit.clear();
+ m_regBD.clear();
#ifndef ADLMIDI_HW_OPL
- cardsOP2.resize(NumCards, AdlMIDI_SPtr<OPLChipBase>());
+ m_chips.resize(m_numChips, AdlMIDI_SPtr<OPLChipBase>());
#endif
- NumChannels = NumCards * 23;
- ins.resize(NumChannels, adl[adlDefaultNumber]);
- pit.resize(NumChannels, 0);
- regBD.resize(NumCards, 0);
- four_op_category.resize(NumChannels, 0);
+ const struct adldata defaultInsCache = { 0x1557403,0x005B381, 0x49,0x80, 0x4, +0 };
+ m_numChannels = m_numChips * 23;
+ m_ins.resize(m_numChannels, defaultInsCache);
+ m_pit.resize(m_numChannels, 0);
+ m_regBD.resize(m_numChips, 0);
+ m_channelCategory.resize(m_numChannels, 0);
- for(unsigned p = 0, a = 0; a < NumCards; ++a)
+ for(size_t p = 0, a = 0; a < m_numChips; ++a)
{
- for(unsigned b = 0; b < 18; ++b) four_op_category[p++] = 0;
- for(unsigned b = 0; b < 5; ++b) four_op_category[p++] = 8;
+ for(size_t b = 0; b < 18; ++b)
+ m_channelCategory[p++] = 0;
+ for(size_t b = 0; b < 5; ++b)
+ m_channelCategory[p++] = ChanCat_Rhythm_Slave;
}
static const uint16_t data[] =
@@ -521,9 +531,9 @@ void OPL3::Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
0x105, 0, 0x105, 1, 0x105, 0, // Pulse OPL3 enable
0x001, 32, 0x105, 1 // Enable wave, OPL3 extensions
};
- unsigned fours = NumFourOps;
+// size_t fours = m_numFourOps;
- for(size_t i = 0; i < NumCards; ++i)
+ for(size_t i = 0; i < m_numChips; ++i)
{
#ifndef ADLMIDI_HW_OPL
OPLChipBase *chip;
@@ -544,91 +554,23 @@ void OPL3::Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler)
break;
#endif
}
- cardsOP2[i].reset(chip);
+ m_chips[i].reset(chip);
chip->setChipId((uint32_t)i);
chip->setRate((uint32_t)PCM_RATE);
- if(runAtPcmRate)
+ if(m_runAtPcmRate)
chip->setRunningAtPcmRate(true);
# if defined(ADLMIDI_AUDIO_TICK_HANDLER)
chip->setAudioTickHandlerInstance(audioTickHandler);
# endif
#endif // ADLMIDI_HW_OPL
- for(unsigned a = 0; a < 18; ++a) Poke(i, 0xB0 + Channels[a], 0x00);
- for(unsigned a = 0; a < sizeof(data) / sizeof(*data); a += 2)
- Poke(i, data[a], static_cast<uint8_t>(data[a + 1]));
- Poke(i, 0x0BD, regBD[i] = (HighTremoloMode * 0x80
- + HighVibratoMode * 0x40
- + AdlPercussionMode * 0x20));
- unsigned fours_this_card = std::min(fours, 6u);
- Poke(i, 0x104, (1 << fours_this_card) - 1);
- //fprintf(stderr, "Card %u: %u four-ops.\n", card, fours_this_card);
- fours -= fours_this_card;
- }
-
- // Mark all channels that are reserved for four-operator function
- if(AdlPercussionMode == 1)
- {
- for(unsigned a = 0; a < NumCards; ++a)
- {
- for(unsigned b = 0; b < 5; ++b) four_op_category[a * 23 + 18 + b] = static_cast<char>(b + 3);
- for(unsigned b = 0; b < 3; ++b) four_op_category[a * 23 + 6 + b] = 8;
- }
- }
- unsigned nextfour = 0;
-
- for(unsigned a = 0; a < NumFourOps; ++a)
- {
- four_op_category[nextfour ] = 1;
- four_op_category[nextfour + 3] = 2;
-
- switch(a % 6)
- {
- case 0:
- case 1:
- nextfour += 1;
- break;
-
- case 2:
- nextfour += 9 - 2;
- break;
-
- case 3:
- case 4:
- nextfour += 1;
- break;
-
- case 5:
- nextfour += 23 - 9 - 2;
- break;
- }
+ /* Clean-up channels from any playing junk sounds */
+ for(size_t a = 0; a < 18; ++a)
+ writeReg(i, 0xB0 + g_channelsMap[a], 0x00);
+ for(size_t a = 0; a < sizeof(data) / sizeof(*data); a += 2)
+ writeReg(i, data[a], static_cast<uint8_t>(data[a + 1]));
}
- /**/
- /*
- In two-op mode, channels 0..8 go as follows:
- Op1[port] Op2[port]
- Channel 0: 00 00 03 03
- Channel 1: 01 01 04 04
- Channel 2: 02 02 05 05
- Channel 3: 06 08 09 0B
- Channel 4: 07 09 10 0C
- Channel 5: 08 0A 11 0D
- Channel 6: 12 10 15 13
- Channel 7: 13 11 16 14
- Channel 8: 14 12 17 15
- In four-op mode, channels 0..8 go as follows:
- Op1[port] Op2[port] Op3[port] Op4[port]
- Channel 0: 00 00 03 03 06 08 09 0B
- Channel 1: 01 01 04 04 07 09 10 0C
- Channel 2: 02 02 05 05 08 0A 11 0D
- Channel 3: CHANNEL 0 SLAVE
- Channel 4: CHANNEL 1 SLAVE
- Channel 5: CHANNEL 2 SLAVE
- Channel 6: 12 10 15 13
- Channel 7: 13 11 16 14
- Channel 8: 14 12 17 15
- Same goes principally for channels 9-17 respectively.
- */
- Silence();
+ updateChannelCategories();
+ silenceAll();
}
diff --git a/src/adlmidi_private.cpp b/src/adlmidi_private.cpp
index 3bc73a4..8d7b9a7 100644
--- a/src/adlmidi_private.cpp
+++ b/src/adlmidi_private.cpp
@@ -40,11 +40,13 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device)
MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer);
//Automatically calculate how much 4-operator channels is necessary
- if(play->opl.AdlBank == ~0u)
+#ifndef DISABLE_EMBEDDED_BANKS
+ if(play->m_synth.m_embeddedBank == ~0u)
+#endif
{
//For custom bank
- OPL3::BankMap::iterator it = play->opl.dynamic_banks.begin();
- OPL3::BankMap::iterator end = play->opl.dynamic_banks.end();
+ OPL3::BankMap::iterator it = play->m_synth.m_insBanks.begin();
+ OPL3::BankMap::iterator end = play->m_synth.m_insBanks.end();
for(; it != end; ++it)
{
uint16_t bank = it->first;
@@ -60,12 +62,13 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device)
}
}
}
+#ifndef DISABLE_EMBEDDED_BANKS
else
{
//For embedded bank
for(unsigned a = 0; a < 256; ++a)
{
- unsigned insno = banks[play->m_setup.AdlBank][a];
+ unsigned insno = banks[play->m_setup.bankId][a];
if(insno == 198)
continue;
++n_total[a / 128];
@@ -74,6 +77,7 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device)
++n_fourop[a / 128];
}
}
+#endif
unsigned numFourOps = 0;
@@ -96,7 +100,7 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device)
: (play->m_setup.NumCards == 1 ? 1 : play->m_setup.NumCards * 4);
*/
- play->opl.NumFourOps = play->m_setup.NumFourOps = (numFourOps * play->m_setup.NumCards);
+ play->m_synth.m_numFourOps = play->m_setup.numFourOps = (numFourOps * play->m_setup.numChips);
return 0;
}
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index f34404d..c2771fc 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -145,10 +145,13 @@ typedef BW_MidiSequencer MidiSequencer;
#endif
#include "adldata.hh"
+
#include "adlmidi.h" //Main API
+
#ifndef ADLMIDI_DISABLE_CPP_EXTRAS
#include "adlmidi.hpp" //Extra C++ API
#endif
+
#include "adlmidi_ptr.hpp"
#include "adlmidi_bankmap.h"
@@ -208,101 +211,231 @@ inline int32_t adl_cvtU32(int32_t x)
}
struct ADL_MIDIPlayer;
+/**
+ * @brief OPL3 Chip management class
+ */
class OPL3
{
-public:
friend class MIDIplay;
friend class AdlInstrumentTester;
- uint32_t NumChannels;
+ friend int adlRefreshNumCards(ADL_MIDIPlayer *device);
+public:
+ enum { PercussionTag = 1 << 15 };
+
+ //! Total number of chip channels between all running emulators
+ uint32_t m_numChannels;
+ //! Just a padding. Reserved.
char ____padding[4];
#ifndef ADLMIDI_HW_OPL
- std::vector<AdlMIDI_SPtr<OPLChipBase > > cardsOP2;
+ std::vector<AdlMIDI_SPtr<OPLChipBase > > m_chips;
#endif
+
private:
- std::vector<adldata> ins; // patch data, cached, needed by Touch()
- std::vector<uint8_t> pit; // value poked to B0, cached, needed by NoteOff)(
- std::vector<uint8_t> regBD;
+ //! Cached patch data, needed by Touch()
+ std::vector<adldata> m_ins;
+ //! Value poked to B0, cached, needed by NoteOff)
+ std::vector<uint8_t> m_pit;
+ //! Cached BD registry value (flags register: DeepTremolo, DeepVibrato, and RhythmMode)
+ std::vector<uint8_t> m_regBD;
- friend int adlRefreshNumCards(ADL_MIDIPlayer *device);
public:
+ /**
+ * @brief MIDI bank entry
+ */
struct Bank
{
+ //! MIDI Bank instruments
adlinsdata2 ins[128];
};
typedef BasicBankMap<Bank> BankMap;
- BankMap dynamic_banks;
- AdlBankSetup dynamic_bank_setup;
+ //! MIDI bank instruments data
+ BankMap m_insBanks;
+ //! MIDI bank-wide setup
+ AdlBankSetup m_insBankSetup;
public:
- void setEmbeddedBank(unsigned int bank);
- static const adlinsdata2 emptyInstrument;
- enum { PercussionTag = 1 << 15 };
-
+ //! Blank instrument template
+ static const adlinsdata2 m_emptyInstrument;
//! Total number of running concurrent emulated chips
- unsigned int NumCards;
+ uint32_t m_numChips;
//! Currently running embedded bank number. "~0" means usign of the custom bank.
- unsigned int AdlBank;
+ uint32_t m_embeddedBank;
//! Total number of needed four-operator channels in all running chips
- unsigned int NumFourOps;
+ uint32_t m_numFourOps;
//! Turn global Deep Tremolo mode on
- bool HighTremoloMode;
+ bool m_deepTremoloMode;
//! Turn global Deep Vibrato mode on
- bool HighVibratoMode;
- //! Use AdLib percussion mode
- bool AdlPercussionMode;
+ 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 ScaleModulators;
+ bool m_scaleModulators;
//! Run emulator at PCM rate if that possible. Reduces sounding accuracy, but decreases CPU usage on lower rates.
- bool runAtPcmRate;
- // ! Required to play CMF files. Can be turned on by using of "CMF" volume model
- //bool LogarithmicVolumes; //[REPLACED WITH "m_volumeScale == VOLUME_NATIVE", DEPRECATED!!!]
- // ! Required to play EA-MUS files [REPLACED WITH "m_musicMode", DEPRECATED!!!]
- //bool CartoonersVolumes;
+ bool m_runAtPcmRate;
+
+ /**
+ * @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;
+
//! Just a padding. Reserved.
char ___padding2[3];
- //! Volume models enum
+
+ /**
+ * @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;
- OPL3();
+ //! Reserved
char ____padding3[8];
- std::vector<char> four_op_category; // 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
-
- void Poke(size_t card, uint16_t index, uint8_t value);
-
- void NoteOff(size_t c);
- void NoteOn(unsigned c, double hertz);
- void Touch_Real(unsigned c, unsigned volume, uint8_t brightness = 127);
- //void Touch(unsigned c, unsigned volume)
-
- void Patch(uint16_t c, const adldata &adli);
- void Pan(unsigned c, unsigned value);
- void Silence();
- void updateFlags();
- void updateDeepFlags();
- void ChangeVolumeRangesModel(ADLMIDI_VolumeModels volumeModel);
+
+ /**
+ * @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<char> m_channelCategory;
+
+
+ /**
+ * @brief C.O. Constructor
+ */
+ OPL3();
+
+ /**
+ * @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 index Register address to write
+ * @param value Value to write
+ */
+ void writeReg(size_t chip, uint16_t address, uint8_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 c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param hertz Frequency of the tone in hertzes
+ */
+ void noteOn(size_t c, 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 touchReal(uint32_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(uint16_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);
+
#ifndef ADLMIDI_HW_OPL
- void ClearChips();
+ /**
+ * @brief Clean up all running emulated chip instances
+ */
+ void clearChips();
#endif
- void Reset(int emulator, unsigned long PCM_RATE, void *audioTickHandler);
+
+ /**
+ * @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);
};
@@ -343,56 +476,105 @@ public:
/**********************Internal structures and classes**********************/
- // Persistent settings for each MIDI channel
+ /**
+ * @brief Persistent settings for each MIDI channel
+ */
struct MIDIchannel
{
- uint8_t bank_lsb, bank_msb;
+ //! LSB Bank number
+ uint8_t bank_lsb,
+ //! MSB Bank number
+ bank_msb;
+ //! Current patch number
uint8_t patch;
- uint8_t volume, expression;
- uint8_t panning, vibrato, aftertouch;
+ //! Volume level
+ uint8_t volume,
+ //! Expression level
+ expression;
+ //! Panning level
+ uint8_t panning,
+ //! Vibrato level
+ vibrato,
+ //! Channel aftertouch level
+ aftertouch;
+ //! Portamento time
uint16_t portamento;
+ //! Is Pedal sustain active
bool sustain;
+ //! Is Soft pedal active
bool softPedal;
+ //! Is portamento enabled
bool portamentoEnable;
+ //! Source note number used by portamento
int8_t portamentoSource; // note number or -1
+ //! Portamento rate
double portamentoRate;
//! Per note Aftertouch values
uint8_t noteAftertouch[128];
//! Is note aftertouch has any non-zero value
bool noteAfterTouchInUse;
+ //! Reserved
char ____padding[6];
+ //! Pitch bend value
int bend;
+ //! Pitch bend sensitivity
double bendsense;
- int bendsense_lsb, bendsense_msb;
- double vibpos, vibspeed, vibdepth;
+ //! Pitch bend sensitivity LSB value
+ int bendsense_lsb,
+ //! Pitch bend sensitivity MSB value
+ bendsense_msb;
+ //! Vibrato position value
+ double vibpos,
+ //! Vibrato speed value
+ vibspeed,
+ //! Vibrato depth value
+ vibdepth;
+ //! Vibrato delay time
int64_t vibdelay;
- uint8_t lastlrpn, lastmrpn;
+ //! Last LSB part of RPN value received
+ uint8_t lastlrpn,
+ //! Last MSB poart of RPN value received
+ lastmrpn;
+ //! Interpret RPN value as NRPN
bool nrpn;
+ //! Brightness level
uint8_t brightness;
+
+ //! Is melodic channel turned into percussion
bool is_xg_percussion;
+
+ /**
+ * @brief Per-Note information
+ */
struct NoteInfo
{
+ //! Note number
uint8_t note;
+ //! Is note active
bool active;
- // Current pressure
+ //! Current pressure
uint8_t vol;
- // Note vibrato (a part of Note Aftertouch feature)
+ //! Note vibrato (a part of Note Aftertouch feature)
uint8_t vibrato;
- // Tone selected on noteon:
+ //! Tone selected on noteon:
int16_t noteTone;
- // Current tone (!= noteTone if gliding note)
+ //! Current tone (!= noteTone if gliding note)
double currentTone;
- // Gliding rate
+ //! Gliding rate
double glideRate;
- // Patch selected on noteon; index to bank.ins[]
+ //! Patch selected on noteon; index to bank.ins[]
size_t midiins;
- // Patch selected
+ //! Patch selected
const adlinsdata2 *ains;
enum
{
MaxNumPhysChans = 2,
MaxNumPhysItemCount = MaxNumPhysChans,
};
+
+ /**
+ * @brief Reference to currently using chip channel
+ */
struct Phys
{
//! Destination chip channel
@@ -416,11 +598,12 @@ public:
return !operator==(oth);
}
};
+
//! List of OPL3 channels it is currently occupying.
Phys chip_channels[MaxNumPhysItemCount];
//! Count of used channels.
unsigned chip_channels_count;
- //
+
Phys *phys_find(unsigned chip_chan)
{
Phys *ph = NULL;
@@ -461,8 +644,13 @@ public:
phys_erase_at(ph);
}
};
+
+ //! Reserved
char ____padding2[5];
+ //! Count of gliding notes in this channel
unsigned gliding_note_count;
+
+ //! Active notes in the channel
NoteInfo activenotes[128];
struct activenoteiterator
@@ -546,6 +734,9 @@ public:
}
}
+ /**
+ * @brief Reset channel into initial state
+ */
void reset()
{
resetAllControllers();
@@ -558,6 +749,10 @@ public:
nrpn = false;
is_xg_percussion = false;
}
+
+ /**
+ * @brief Reset all MIDI controllers into initial state
+ */
void resetAllControllers()
{
bend = 0;
@@ -582,15 +777,25 @@ public:
portamentoRate = HUGE_VAL;
brightness = 127;
}
+
+ /**
+ * @brief Has channel vibrato to process
+ * @return
+ */
bool hasVibrato()
{
return (vibrato > 0) || (aftertouch > 0) || noteAfterTouchInUse;
}
+
+ /**
+ * @brief Commit pitch bend sensitivity value from MSB and LSB
+ */
void updateBendSensitivity()
{
int cent = bendsense_msb * 128 + bendsense_lsb;
bendsense = cent * (1.0 / (128 * 8192));
}
+
MIDIchannel()
{
activenotes_clear();
@@ -599,7 +804,9 @@ public:
}
};
- // Additional information about OPL3 channels
+ /**
+ * @brief Additional information about OPL3 channels
+ */
struct AdlChannel
{
struct Location
@@ -631,7 +838,7 @@ public:
int64_t vibdelay;
};
- // If the channel is keyoff'd
+ //! Time left until sounding will be muted after key off
int64_t koff_time_until_neglible;
enum { users_max = 128 };
@@ -672,7 +879,11 @@ public:
return *this;
}
- void AddAge(int64_t ms);
+ /**
+ * @brief Increases age of active note in milliseconds time
+ * @param ms Amount time in milliseconds
+ */
+ void addAge(int64_t ms);
};
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
@@ -696,16 +907,16 @@ public:
{
int emulator;
bool runAtPcmRate;
- unsigned int AdlBank;
- unsigned int NumFourOps;
- unsigned int NumCards;
- int HighTremoloMode;
- int HighVibratoMode;
- int AdlPercussionMode;
- bool LogarithmicVolumes;
- int VolumeModel;
+ unsigned int bankId;
+ unsigned int numFourOps;
+ unsigned int numChips;
+ int deepTremoloMode;
+ int deepVibratoMode;
+ int rhythmMode;
+ bool logarithmicVolumes;
+ int volumeScaleModel;
//unsigned int SkipForward;
- int ScaleModulators;
+ int scaleModulators;
bool fullRangeBrightnessCC74;
double delay;
@@ -723,18 +934,34 @@ public:
unsigned long PCM_RATE;
};
+ /**
+ * @brief MIDI Marker entry
+ */
struct MIDI_MarkerEntry
{
+ //! Label of marker
std::string label;
+ //! Absolute position in seconds
double pos_time;
+ //! Absolute position in ticks in the track
uint64_t pos_ticks;
};
- std::vector<MIDIchannel> Ch;
- bool cmf_percussion_mode;
+ //! Available MIDI Channels
+ std::vector<MIDIchannel> m_midiChannels;
+
+ //! CMF Rhythm mode
+ bool m_cmfPercussionMode;
+
+ //! Master volume, controlled via SysEx
uint8_t m_masterVolume;
+
+ //! SysEx device ID
uint8_t m_sysExDeviceId;
+ /**
+ * @brief MIDI Synthesizer mode
+ */
enum SynthMode
{
Mode_GM = 0x00,
@@ -742,18 +969,23 @@ public:
Mode_XG = 0x02,
Mode_GM2 = 0x04,
};
+ //! MIDI Synthesizer mode
uint32_t m_synthMode;
+ //! Installed function hooks
MIDIEventHooks hooks;
private:
- std::map<std::string, uint64_t> devices;
- std::map<uint64_t /*track*/, uint64_t /*channel begin index*/> current_device;
+ //! Per-track MIDI devices map
+ std::map<std::string, uint64_t> m_midiDevices;
+ //! Current MIDI device per track
+ std::map<uint64_t /*track*/, uint64_t /*channel begin index*/> m_currentMidiDevice;
- //Padding to fix CLanc code model's warning
+ //! Padding to fix CLanc code model's warning
char ____padding[7];
- std::vector<AdlChannel> ch;
+ //! Chip channels map
+ std::vector<AdlChannel> m_chipChannels;
//! Counter of arpeggio processing
size_t m_arpeggioCounter;
@@ -777,14 +1009,35 @@ public:
const std::string &getErrorString();
void setErrorString(const std::string &err);
- OPL3 opl;
+ //! OPL3 Chip manager
+ OPL3 m_synth;
- int32_t outBuf[1024];
+ //! Generator output buffer
+ int32_t m_outBuf[1024];
+ //! Synthesizer setup
Setup m_setup;
+ /**
+ * @brief Load custom bank from file
+ * @param filename Path to bank file
+ * @return true on succes
+ */
bool LoadBank(const std::string &filename);
+
+ /**
+ * @brief Load custom bank from memory block
+ * @param data Pointer to memory block where raw bank file is stored
+ * @param size Size of given memory block
+ * @return true on succes
+ */
bool LoadBank(const void *data, size_t size);
+
+ /**
+ * @brief Load custom bank from opened FileAndMemReader class
+ * @param fr Instance with opened file
+ * @return true on succes
+ */
bool LoadBank(FileAndMemReader &fr);
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
@@ -967,6 +1220,9 @@ public:
#endif
private:
+ /**
+ * @brief Hardware manufacturer (Used for SysEx)
+ */
enum
{
Manufacturer_Roland = 0x41,
@@ -974,11 +1230,19 @@ private:
Manufacturer_UniversalNonRealtime = 0x7E,
Manufacturer_UniversalRealtime = 0x7F
};
+
+ /**
+ * @brief Roland Mode (Used for SysEx)
+ */
enum
{
RolandMode_Request = 0x11,
RolandMode_Send = 0x12
};
+
+ /**
+ * @brief Device model (Used for SysEx)
+ */
enum
{
RolandModel_GS = 0x42,
@@ -986,11 +1250,38 @@ private:
YamahaModel_XG = 0x4C
};
+ /**
+ * @brief Process generic SysEx events
+ * @param dev Device ID
+ * @param realtime Is real-time event
+ * @param data Raw SysEx data
+ * @param size Size of given SysEx data
+ * @return true when event was successfully handled
+ */
bool doUniversalSysEx(unsigned dev, bool realtime, const uint8_t *data, size_t size);
+
+ /**
+ * @brief Process events specific to Roland devices
+ * @param dev Device ID
+ * @param data Raw SysEx data
+ * @param size Size of given SysEx data
+ * @return true when event was successfully handled
+ */
bool doRolandSysEx(unsigned dev, const uint8_t *data, size_t size);
+
+ /**
+ * @brief Process events specific to Yamaha devices
+ * @param dev Device ID
+ * @param data Raw SysEx data
+ * @param size Size of given SysEx data
+ * @return true when event was successfully handled
+ */
bool doYamahaSysEx(unsigned dev, const uint8_t *data, size_t size);
private:
+ /**
+ * @brief Note Update properties
+ */
enum
{
Upd_Patch = 0x1,
@@ -1003,39 +1294,119 @@ private:
Upd_OffMute = Upd_Off + Upd_Mute
};
- void NoteUpdate(uint16_t MidCh,
+ /**
+ * @brief Update active note
+ * @param MidCh MIDI Channel where note is processing
+ * @param i Iterator that points to active note in the MIDI channel
+ * @param props_mask Properties to update
+ * @param select_adlchn Specify chip channel, or -1 - all chip channels used by the note
+ */
+ void noteUpdate(uint16_t midCh,
MIDIchannel::activenoteiterator i,
unsigned props_mask,
int32_t select_adlchn = -1);
- // Determine how good a candidate this adlchannel
- // would be for playing a note from this instrument.
- int64_t CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/) const;
+ /**
+ * @brief Update all notes in specified MIDI channel
+ * @param midCh MIDI channel to update all notes in it
+ * @param props_mask Properties to update
+ */
+ void noteUpdateAll(size_t midCh, unsigned props_mask);
+
- // A new note will be played on this channel using this instrument.
- // Kill existing notes on this channel (or don't, if we do arpeggio)
- void PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins);
+ /**
+ * @brief Determine how good a candidate this adlchannel would be for playing a note from this instrument.
+ * @param c Wanted chip channel
+ * @param ins Instrument wanted to be used in this channel
+ * @return Calculated coodness points
+ */
+ int64_t calculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const;
+
+ /**
+ * @brief A new note will be played on this channel using this instrument.
+ * @param c Wanted chip channel
+ * @param ins Instrument wanted to be used in this channel
+ * Kill existing notes on this channel (or don't, if we do arpeggio)
+ */
+ void prepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins);
- void KillOrEvacuate(
+ /**
+ * @brief Kills note that uses wanted channel. When arpeggio is possible, note is evaluating to another channel
+ * @param from_channel Wanted chip channel
+ * @param j Chip channel instance
+ * @param i MIDI Channel active note instance
+ */
+ void killOrEvacuate(
size_t from_channel,
AdlChannel::LocationData *j,
MIDIchannel::activenoteiterator i);
- void Panic();
- void KillSustainingNotes(int32_t MidCh = -1,
+
+ /**
+ * @brief Off all notes and silence sound
+ */
+ void panic();
+
+ /**
+ * @brief Kill note, sustaining by pedal or sostenuto
+ * @param MidCh MIDI channel, -1 - all MIDI channels
+ * @param this_adlchn Chip channel, -1 - all chip channels
+ * @param sustain_type Type of systain to process
+ */
+ void killSustainingNotes(int32_t MidCh = -1,
int32_t this_adlchn = -1,
uint8_t sustain_type = AdlChannel::LocationData::Sustain_ANY);
- void MarkSostenutoNotes(int32_t MidCh = -1);
- void SetRPN(unsigned MidCh, unsigned value, bool MSB);
- void UpdatePortamento(unsigned MidCh);
- void NoteUpdate_All(uint16_t MidCh, unsigned props_mask);
- void NoteOff(uint16_t MidCh, uint8_t note);
+ /**
+ * @brief Find active notes and mark them as sostenuto-sustained
+ * @param MidCh MIDI channel, -1 - all MIDI channels
+ */
+ void markSostenutoNotes(int32_t MidCh = -1);
+
+ /**
+ * @brief Set RPN event value
+ * @param MidCh MIDI channel
+ * @param value 1 byte part of RPN value
+ * @param MSB is MSB or LSB part of value
+ */
+ void setRPN(unsigned MidCh, unsigned value, bool MSB);
+
+ /**
+ * @brief Update portamento setup in MIDI channel
+ * @param midCh MIDI channel where portamento needed to be updated
+ */
+ void updatePortamento(size_t midCh);
+
+ /**
+ * @brief Off the note
+ * @param midCh MIDI channel
+ * @param note Note to off
+ */
+ void noteOff(uint16_t midCh, uint8_t note);
- void UpdateVibrato(double amount);
- void UpdateArpeggio(double /*amount*/);
- void UpdateGlide(double amount);
+ /**
+ * @brief Update processing of vibrato to amount of seconds
+ * @param amount Amount value in seconds
+ */
+ void updateVibrato(double amount);
+
+ /**
+ * @brief Update auto-arpeggio
+ * @param amount Amount value in seconds [UNUSED]
+ */
+ void updateArpeggio(double /*amount*/);
+
+ /**
+ * @brief Update Portamento gliding to amount of seconds
+ * @param amount Amount value in seconds
+ */
+ void updateGlide(double amount);
public:
- uint64_t ChooseDevice(const std::string &name);
+ /**
+ * @brief Checks was device name used or not
+ * @param name Name of MIDI device
+ * @return Offset of the MIDI Channels, multiple to 16
+ */
+ uint64_t chooseDevice(const std::string &name);
};
// I think, this is useless inside of Library
diff --git a/src/adlmidi_sequencer.cpp b/src/adlmidi_sequencer.cpp
index b8bf3dd..516f80d 100644
--- a/src/adlmidi_sequencer.cpp
+++ b/src/adlmidi_sequencer.cpp
@@ -136,13 +136,13 @@ double MIDIplay::Tick(double s, double granularity)
double ret = m_sequencer.Tick(s, granularity);
s *= m_sequencer.getTempoMultiplier();
- for(uint16_t c = 0; c < opl.NumChannels; ++c)
- ch[c].AddAge(static_cast<int64_t>(s * 1000.0));
+ for(uint16_t c = 0; c < m_synth.m_numChannels; ++c)
+ m_chipChannels[c].addAge(static_cast<int64_t>(s * 1000.0));
- UpdateVibrato(s);
- UpdateArpeggio(s);
+ updateVibrato(s);
+ updateArpeggio(s);
#if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
- UpdateGlide(s);
+ updateGlide(s);
#endif
return ret;
diff --git a/src/chips/opl_chip_base.tcc b/src/chips/opl_chip_base.tcc
index 48ad103..a64aa7c 100644
--- a/src/chips/opl_chip_base.tcc
+++ b/src/chips/opl_chip_base.tcc
@@ -236,8 +236,8 @@ void OPLChipBaseT<T>::resampledGenerate(int32_t *output)
rsm->out_count = 1;
rsm->out_data = f_out;
}
- output[0] = std::lround(f_out[0]);
- output[1] = std::lround(f_out[1]);
+ output[0] = static_cast<int32_t>(std::lround(f_out[0]));
+ output[1] = static_cast<int32_t>(std::lround(f_out[1]));
}
#else
template <class T>