From c971992278519b29768be349dd3962bbd93dbb22 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Sun, 30 Sep 2018 04:57:56 +0300 Subject: Lock settings for CMF and IMF playing to don't destroy them For now, all settings are in safe, except of custom bank that getting be dropped away by CMF file that does passing of own custom instruments. --- src/adlmidi.cpp | 131 ++++++++++++++++++++++++++++++++++------------- src/adlmidi_load.cpp | 18 ++++++- src/adlmidi_midiplay.cpp | 8 ++- src/adlmidi_opl3.cpp | 8 +++ src/adlmidi_private.cpp | 8 +-- src/adlmidi_private.hpp | 14 +++-- 6 files changed, 140 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp index bde8757..097fce8 100644 --- a/src/adlmidi.cpp +++ b/src/adlmidi.cpp @@ -68,7 +68,7 @@ ADLMIDI_EXPORT struct ADL_MIDIPlayer *adl_init(long sample_rate) return NULL; } midi_device->adl_midiPlayer = player; - adlRefreshNumCards(midi_device); + adlCalculateFourOpChannels(player); return midi_device; } @@ -113,10 +113,25 @@ ADLMIDI_EXPORT int adl_setNumChips(ADL_MIDIPlayer *device, int numChips) return -1; } - play->m_synth.m_numChips = play->m_setup.numChips; - play->partialReset(); + int maxFourOps = static_cast(play->m_setup.numChips * 6); + + if(play->m_setup.numFourOps > maxFourOps) + play->m_setup.numFourOps = maxFourOps; + else if(play->m_setup.numFourOps < -1) + play->m_setup.numFourOps = -1; - return adlRefreshNumCards(device); + if(!play->m_synth.setupLocked()) + { + play->m_synth.m_numChips = play->m_setup.numChips; + if(play->m_setup.numFourOps < 0) + adlCalculateFourOpChannels(play, true); + else + play->m_synth.m_numFourOps = static_cast(play->m_setup.numFourOps); + play->partialReset(); + return 0; + } + + return 0; } ADLMIDI_EXPORT int adl_getNumChips(struct ADL_MIDIPlayer *device) @@ -128,6 +143,15 @@ ADLMIDI_EXPORT int adl_getNumChips(struct ADL_MIDIPlayer *device) return (int)play->m_setup.numChips; } +ADLMIDI_EXPORT int adl_getNumChipsObtained(struct ADL_MIDIPlayer *device) +{ + if(device == NULL) + return -2; + MidiPlayer *play = GET_MIDI_PLAYER(device); + assert(play); + return (int)play->m_synth.m_numChips; +} + ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) { #ifdef DISABLE_EMBEDDED_BANKS @@ -159,7 +183,7 @@ ADLMIDI_EXPORT int adl_setBank(ADL_MIDIPlayer *device, int bank) play->m_synth.setEmbeddedBank(play->m_setup.bankId); play->applySetup(); - return adlRefreshNumCards(device); + return 0; #endif } @@ -357,9 +381,6 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4) if(!device) return -1; - if(ops4 == -1) - return adlRefreshNumCards(device); - MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); if((unsigned int)ops4 > 6 * play->m_setup.numChips) @@ -371,8 +392,14 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4) } play->m_setup.numFourOps = static_cast(ops4); - play->m_synth.m_numFourOps = play->m_setup.numFourOps; - play->m_synth.updateChannelCategories(); + if(!play->m_synth.setupLocked()) + { + if(play->m_setup.numFourOps >= 0) + play->m_synth.m_numFourOps = play->m_setup.numFourOps; + else + adlCalculateFourOpChannels(play); + play->m_synth.updateChannelCategories(); + } return 0; } @@ -380,22 +407,35 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4) ADLMIDI_EXPORT int adl_getNumFourOpsChn(struct ADL_MIDIPlayer *device) { if(!device) - return -1; + return -2; MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); - return (int)play->m_setup.numFourOps; + return play->m_setup.numFourOps; } +ADLMIDI_EXPORT int adl_getNumFourOpsChnObtained(struct ADL_MIDIPlayer *device) +{ + if(!device) + return -2; + MidiPlayer *play = GET_MIDI_PLAYER(device); + assert(play); + return (int)play->m_synth.m_numFourOps; +} + + ADLMIDI_EXPORT void adl_setPercMode(ADL_MIDIPlayer *device, int percmod) { if(!device) return; MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); 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(); + if(!play->m_synth.setupLocked()) + { + 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) @@ -404,10 +444,13 @@ ADLMIDI_EXPORT void adl_setHVibrato(ADL_MIDIPlayer *device, int hvibro) MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); 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(); + if(!play->m_synth.setupLocked()) + { + 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 int adl_getHVibrato(struct ADL_MIDIPlayer *device) @@ -424,10 +467,13 @@ ADLMIDI_EXPORT void adl_setHTremolo(ADL_MIDIPlayer *device, int htremo) MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); 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(); + if(!play->m_synth.setupLocked()) + { + 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 int adl_getHTremolo(struct ADL_MIDIPlayer *device) @@ -445,9 +491,12 @@ ADLMIDI_EXPORT void adl_setScaleModulators(ADL_MIDIPlayer *device, int smod) MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); 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); + if(!play->m_synth.setupLocked()) + { + 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) @@ -489,10 +538,13 @@ ADLMIDI_EXPORT void adl_setLogarithmicVolumes(struct ADL_MIDIPlayer *device, int MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); play->m_setup.logarithmicVolumes = (logvol != 0); - if(play->m_setup.logarithmicVolumes) - play->m_synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3); - else - play->m_synth.setVolumeScaleModel(static_cast(play->m_synth.m_volumeScale)); + if(!play->m_synth.setupLocked()) + { + if(play->m_setup.logarithmicVolumes) + play->m_synth.setVolumeScaleModel(ADLMIDI_VolumeModel_NativeOPL3); + else + play->m_synth.setVolumeScaleModel(static_cast(play->m_synth.m_volumeScale)); + } } ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int volumeModel) @@ -502,10 +554,13 @@ ADLMIDI_EXPORT void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *device, int v MidiPlayer *play = GET_MIDI_PLAYER(device); assert(play); 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->m_synth.setVolumeScaleModel(static_cast(volumeModel)); + if(!play->m_synth.setupLocked()) + { + 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->m_synth.setVolumeScaleModel(static_cast(volumeModel)); + } } ADLMIDI_EXPORT int adl_getVolumeRangeModel(struct ADL_MIDIPlayer *device) @@ -531,7 +586,8 @@ ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *f play->setErrorString("ADL MIDI: Can't load file"); return -1; } - else return adlRefreshNumCards(device); + else + return adlCalculateFourOpChannels(play, true); } ADLMIDI_ErrorString = "Can't load file: ADLMIDI is not initialized"; @@ -552,7 +608,8 @@ ADLMIDI_EXPORT int adl_openBankData(struct ADL_MIDIPlayer *device, const void *m play->setErrorString("ADL MIDI: Can't load data from memory"); return -1; } - else return adlRefreshNumCards(device); + else + return adlCalculateFourOpChannels(play, true); } ADLMIDI_ErrorString = "Can't load file: ADL MIDI is not initialized"; diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp index e86f23e..07ad875 100644 --- a/src/adlmidi_load.cpp +++ b/src/adlmidi_load.cpp @@ -1,4 +1,4 @@ -/* +/* * libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation * * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma @@ -214,20 +214,36 @@ bool MIDIplay::LoadMIDI_post() m_synth.m_rhythmMode = true; m_synth.m_musicMode = OPL3::MODE_CMF; m_synth.m_volumeScale = OPL3::VOLUME_NATIVE; + + m_synth.m_numChips = 1; + m_synth.m_numFourOps = 0; } else if(format == MidiSequencer::Format_RSXX) { //opl.CartoonersVolumes = true; m_synth.m_musicMode = OPL3::MODE_RSXX; m_synth.m_volumeScale = OPL3::VOLUME_NATIVE; + + m_synth.m_numChips = 1; + m_synth.m_numFourOps = 0; } else if(format == MidiSequencer::Format_IMF) { //std::fprintf(stderr, "Done reading IMF file\n"); m_synth.m_numFourOps = 0; //Don't use 4-operator channels for IMF playing! m_synth.m_musicMode = OPL3::MODE_IMF; + + m_synth.m_numChips = 1; + m_synth.m_numFourOps = 0; + } + else + { + m_synth.m_numChips = m_setup.numChips; + if(m_setup.numFourOps < 0) + adlCalculateFourOpChannels(this, true); } + m_setup.tick_skip_samples_delay = 0; m_synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); // Reset OPL3 chip //opl.Reset(); // ...twice (just in case someone misprogrammed OPL3 previously) m_chipChannels.clear(); diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 276a33d..585e855 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -141,7 +141,7 @@ MIDIplay::MIDIplay(unsigned long sampleRate): m_setup.maxdelay = 512.0 / (double)m_setup.PCM_RATE; m_setup.bankId = 0; - m_setup.numFourOps = 7; + m_setup.numFourOps = -1; m_setup.numChips = 2; m_setup.deepTremoloMode = -1; m_setup.deepVibratoMode = -1; @@ -198,9 +198,13 @@ void MIDIplay::applySetup() m_synth.m_volumeScale = (OPL3::VolumesScale)m_synth.m_insBankSetup.volumeModel; m_synth.m_numChips = m_setup.numChips; - m_synth.m_numFourOps = m_setup.numFourOps; m_cmfPercussionMode = false; + if(m_setup.numFourOps >= 0) + m_synth.m_numFourOps = m_setup.numFourOps; + else + adlCalculateFourOpChannels(this, true); + m_synth.reset(m_setup.emulator, m_setup.PCM_RATE, this); m_chipChannels.clear(); m_chipChannels.resize(m_synth.m_numChannels); diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp index e486dd6..f3672d3 100644 --- a/src/adlmidi_opl3.cpp +++ b/src/adlmidi_opl3.cpp @@ -181,6 +181,13 @@ OPL3::OPL3() : #endif } +bool OPL3::setupLocked() +{ + return (m_musicMode == MODE_CMF || + m_musicMode == MODE_IMF || + m_musicMode == MODE_RSXX); +} + void OPL3::setEmbeddedBank(uint32_t bank) { #ifndef DISABLE_EMBEDDED_BANKS @@ -487,6 +494,7 @@ void OPL3::setPan(size_t c, uint8_t value) int panning = 0; if(value < 64 + 32) panning |= OPL_PANNING_LEFT; if(value >= 64 - 32) panning |= OPL_PANNING_RIGHT; + writePan(chip, g_channelsMap[cc], 64); writeRegI(chip, 0xC0 + g_channelsMap[cc], m_insCache[c].feedconn | panning); #ifndef ADLMIDI_HW_OPL } diff --git a/src/adlmidi_private.cpp b/src/adlmidi_private.cpp index 43fe8de..4e8e488 100644 --- a/src/adlmidi_private.cpp +++ b/src/adlmidi_private.cpp @@ -34,10 +34,9 @@ void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate) } #endif -int adlRefreshNumCards(ADL_MIDIPlayer *device) +int adlCalculateFourOpChannels(MIDIplay *play, bool silent) { size_t n_fourop[2] = {0, 0}, n_total[2] = {0, 0}; - MIDIplay *play = reinterpret_cast(device->adl_midiPlayer); //Automatically calculate how much 4-operator channels is necessary #ifndef DISABLE_EMBEDDED_BANKS @@ -100,9 +99,10 @@ int adlRefreshNumCards(ADL_MIDIPlayer *device) : (play->m_setup.NumCards == 1 ? 1 : play->m_setup.NumCards * 4); */ - play->m_synth.m_numFourOps = play->m_setup.numFourOps = static_cast(numFourOps * play->m_setup.numChips); + play->m_synth.m_numFourOps = static_cast(numFourOps * play->m_synth.m_numChips); // Update channel categories and set up four-operator channels - play->m_synth.updateChannelCategories(); + if(!silent) + play->m_synth.updateChannelCategories(); return 0; } diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 43986c5..c3d65c0 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -211,6 +211,7 @@ inline int32_t adl_cvtU32(int32_t x) } struct ADL_MIDIPlayer; +class MIDIplay; /** * @brief OPL3 Chip management class */ @@ -218,7 +219,7 @@ class OPL3 { friend class MIDIplay; friend class AdlInstrumentTester; - friend int adlRefreshNumCards(ADL_MIDIPlayer *device); + friend int adlCalculateFourOpChannels(MIDIplay *play, bool silent); public: enum { @@ -362,6 +363,12 @@ public: */ OPL3(); + /** + * @brief Checks are setup locked to be changed on the fly or not + * @return true when setup on the fly is locked + */ + bool setupLocked(); + /** * @brief Choose one of embedded banks * @param bank ID of the bank @@ -951,7 +958,7 @@ public: int emulator; bool runAtPcmRate; unsigned int bankId; - unsigned int numFourOps; + int numFourOps; unsigned int numChips; int deepTremoloMode; int deepVibratoMode; @@ -1485,9 +1492,10 @@ extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate) /** * @brief Automatically calculate and enable necessary count of 4-op channels on emulated chips * @param device Library context + * @param silent Don't re-count channel categories * @return Always 0 */ -extern int adlRefreshNumCards(ADL_MIDIPlayer *device); +extern int adlCalculateFourOpChannels(MIDIplay *play, bool silent = false); /** * @brief Check emulator availability -- cgit v1.2.3