From c55fa12135c51cbca05927017b9eb0a5071e1ea9 Mon Sep 17 00:00:00 2001 From: probonopd Date: Thu, 1 May 2025 12:19:08 +0200 Subject: [PATCH] Apply voice change in TG to auxiliary TGs --- src/minidexed.cpp | 54 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/minidexed.cpp b/src/minidexed.cpp index a60a64b..fd6cdd8 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -679,6 +679,29 @@ void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) m_pTG[nTG]->loadVoiceParameters (Buffer); setOPMask(0b111111, nTG); + // Propagate to auxiliary TGs for unison + unsigned unisonVoices = m_nUnisonVoices[nTG]; + if (unisonVoices < 1) unisonVoices = 1; + int baseDetune = m_nMasterTune[nTG]; + unsigned basePan = m_nPan[nTG]; + unsigned unisonDetune = m_nUnisonDetune[nTG]; + unsigned unisonSpread = m_nUnisonSpread[nTG]; + for (unsigned v = 0; v < unisonVoices; ++v) { + unsigned physicalTG = getPhysicalTG(nTG, v, unisonVoices); + if (physicalTG == nTG || physicalTG >= m_nToneGenerators) continue; + m_pTG[physicalTG]->loadVoiceParameters(Buffer); + setOPMask(0b111111, physicalTG); + // Apply per-voice detune and pan + float detuneOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonDetune; + float panOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonSpread; + int detune = baseDetune + (int)detuneOffset; + unsigned pan = basePan + (int)panOffset; + detune = constrain(detune, -99, 99); + pan = constrain((int)pan, 0, 127); + m_pTG[physicalTG]->setMasterTune((int8_t)detune); + tg_mixer->pan(physicalTG, mapfloat(pan, 0, 127, 0.0f, 1.0f)); + } + if (m_pConfig->GetMIDIAutoVoiceDumpOnPC()) { // Only do the voice dump back out over MIDI if we have a specific @@ -1636,9 +1659,9 @@ bool CMiniDexed::DoSavePerformance (void) m_PerformanceConfig.SetPortamentoGlissando (m_nPortamentoGlissando[nTG], nTG); m_PerformanceConfig.SetPortamentoTime (m_nPortamentoTime[nTG], nTG); - m_PerformanceConfig.SetNoteLimitLow (m_nNoteLimitLow[nTG], nTG); - m_PerformanceConfig.SetNoteLimitHigh (m_nNoteLimitHigh[nTG], nTG); - m_PerformanceConfig.SetNoteShift (m_nNoteShift[nTG], nTG); + m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG); + m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG); + m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG); if (nTG < m_pConfig->GetToneGenerators()) { m_pTG[nTG]->getVoiceData(m_nRawVoiceData); @@ -1898,16 +1921,35 @@ void CMiniDexed::loadVoiceParameters(const uint8_t* data, uint8_t nTG) { if (voice[151 + i] > 126) // filter characters voice[151 +i] = 32; - } + } m_pTG[nTG]->loadVoiceParameters(&voice[6]); m_pTG[nTG]->doRefreshVoice(); setOPMask(0b111111, nTG); - FOR_AUX_UNISON_TGS(nTG, { + + // Propagate to auxiliary TGs for unison + unsigned unisonVoices = m_nUnisonVoices[nTG]; + if (unisonVoices < 1) unisonVoices = 1; + int baseDetune = m_nMasterTune[nTG]; + unsigned basePan = m_nPan[nTG]; + unsigned unisonDetune = m_nUnisonDetune[nTG]; + unsigned unisonSpread = m_nUnisonSpread[nTG]; + for (unsigned v = 0; v < unisonVoices; ++v) { + unsigned physicalTG = getPhysicalTG(nTG, v, unisonVoices); + if (physicalTG == nTG || physicalTG >= m_nToneGenerators) continue; m_pTG[physicalTG]->loadVoiceParameters(&voice[6]); m_pTG[physicalTG]->doRefreshVoice(); setOPMask(0b111111, physicalTG); - }) + // Apply per-voice detune and pan + float detuneOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonDetune; + float panOffset = ((float)v - (unisonVoices - 1) / 2.0f) * (float)unisonSpread; + int detune = baseDetune + (int)detuneOffset; + unsigned pan = basePan + (int)panOffset; + detune = constrain(detune, -99, 99); + pan = constrain((int)pan, 0, 127); + m_pTG[physicalTG]->setMasterTune((int8_t)detune); + tg_mixer->pan(physicalTG, mapfloat(pan, 0, 127, 0.0f, 1.0f)); + } m_UI.ParameterChanged (); }