|
|
@ -31,6 +31,9 @@ |
|
|
|
#include <assert.h> |
|
|
|
#include <assert.h> |
|
|
|
#include "arm_float_to_q23.h" |
|
|
|
#include "arm_float_to_q23.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Forward declaration for getPhysicalTG
|
|
|
|
|
|
|
|
static unsigned getPhysicalTG(unsigned logicalTG, unsigned unisonVoice, unsigned unisonVoices); |
|
|
|
|
|
|
|
|
|
|
|
const char WLANFirmwarePath[] = "SD:firmware/"; |
|
|
|
const char WLANFirmwarePath[] = "SD:firmware/"; |
|
|
|
const char WLANConfigFile[] = "SD:wpa_supplicant.conf"; |
|
|
|
const char WLANConfigFile[] = "SD:wpa_supplicant.conf"; |
|
|
|
#define FTPUSERNAME "admin" |
|
|
|
#define FTPUSERNAME "admin" |
|
|
@ -126,6 +129,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, |
|
|
|
m_pTG[i]->setEngineType(pConfig->GetEngineType ()); |
|
|
|
m_pTG[i]->setEngineType(pConfig->GetEngineType ()); |
|
|
|
m_pTG[i]->activate (); |
|
|
|
m_pTG[i]->activate (); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
m_nUnisonVoices[i] = 1; |
|
|
|
|
|
|
|
m_nUnisonDetune[i] = 0; |
|
|
|
|
|
|
|
m_nUnisonSpread[i] = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin(); |
|
|
|
unsigned nUSBGadgetPin = pConfig->GetUSBGadgetPin(); |
|
|
@ -848,9 +854,34 @@ void CMiniDexed::keyup (int16_t pitch, unsigned nTG) |
|
|
|
assert (m_pTG[nTG]); |
|
|
|
assert (m_pTG[nTG]); |
|
|
|
|
|
|
|
|
|
|
|
pitch = ApplyNoteLimits (pitch, nTG); |
|
|
|
pitch = ApplyNoteLimits (pitch, nTG); |
|
|
|
if (pitch >= 0) |
|
|
|
if (pitch < 0) return; |
|
|
|
{ |
|
|
|
|
|
|
|
m_pTG[nTG]->keyup (pitch); |
|
|
|
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 >= m_nToneGenerators) break; |
|
|
|
|
|
|
|
// Ensure virtual TG plays the same voice as logical TG
|
|
|
|
|
|
|
|
if (physicalTG != nTG) { |
|
|
|
|
|
|
|
uint8_t voiceData[156]; |
|
|
|
|
|
|
|
m_pTG[nTG]->getVoiceData(voiceData); |
|
|
|
|
|
|
|
m_pTG[physicalTG]->loadVoiceParameters(voiceData); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
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_pTG[physicalTG]->keyup(pitch); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -862,9 +893,30 @@ void CMiniDexed::keydown (int16_t pitch, uint8_t velocity, unsigned nTG) |
|
|
|
assert (m_pTG[nTG]); |
|
|
|
assert (m_pTG[nTG]); |
|
|
|
|
|
|
|
|
|
|
|
pitch = ApplyNoteLimits (pitch, nTG); |
|
|
|
pitch = ApplyNoteLimits (pitch, nTG); |
|
|
|
if (pitch >= 0) |
|
|
|
if (pitch < 0) return; |
|
|
|
{ |
|
|
|
|
|
|
|
m_pTG[nTG]->keydown (pitch, velocity); |
|
|
|
unsigned unisonVoices = m_nUnisonVoices[nTG]; |
|
|
|
|
|
|
|
if (unisonVoices < 1) unisonVoices = 1; |
|
|
|
|
|
|
|
unsigned maxLogicalTGs = m_nToneGenerators / unisonVoices; |
|
|
|
|
|
|
|
if (nTG >= maxLogicalTGs) return; // Don't exceed available physical TGs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 >= m_nToneGenerators) break; |
|
|
|
|
|
|
|
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_pTG[physicalTG]->keydown(pitch, velocity); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1130,10 +1182,20 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT |
|
|
|
|
|
|
|
|
|
|
|
case TGParameterReverbSend: SetReverbSend (nValue, nTG); break; |
|
|
|
case TGParameterReverbSend: SetReverbSend (nValue, nTG); break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
case TGParameterUnisonVoices: |
|
|
|
assert (0); |
|
|
|
m_nUnisonVoices[nTG] = constrain(nValue, 1, 4); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case TGParameterUnisonDetune: |
|
|
|
|
|
|
|
m_nUnisonDetune[nTG] = constrain(nValue, 0, 99); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case TGParameterUnisonSpread: |
|
|
|
|
|
|
|
m_nUnisonSpread[nTG] = constrain(nValue, 0, 99); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case TGParameterUnknown: |
|
|
|
|
|
|
|
// No action needed for unknown parameter
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) |
|
|
|
int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) |
|
|
@ -1180,7 +1242,12 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) |
|
|
|
case TGParameterATAmplitude: return getModController(3, 2, nTG);
|
|
|
|
case TGParameterATAmplitude: return getModController(3, 2, nTG);
|
|
|
|
case TGParameterATEGBias: return getModController(3, 3, nTG);
|
|
|
|
case TGParameterATEGBias: return getModController(3, 3, nTG);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case TGParameterUnisonVoices: |
|
|
|
|
|
|
|
return m_nUnisonVoices[nTG]; |
|
|
|
|
|
|
|
case TGParameterUnisonDetune: |
|
|
|
|
|
|
|
return m_nUnisonDetune[nTG]; |
|
|
|
|
|
|
|
case TGParameterUnisonSpread: |
|
|
|
|
|
|
|
return m_nUnisonSpread[nTG]; |
|
|
|
default: |
|
|
|
default: |
|
|
|
assert (0); |
|
|
|
assert (0); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
@ -2025,7 +2092,6 @@ void CMiniDexed::LoadPerformanceParameters(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++) |
|
|
|
for (unsigned nTG = 0; nTG < CConfig::AllToneGenerators; nTG++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG); |
|
|
|
BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG); |
|
|
|
ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); |
|
|
|
ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); |
|
|
|
SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); |
|
|
|
SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); |
|
|
@ -2062,7 +2128,10 @@ void CMiniDexed::LoadPerformanceParameters(void) |
|
|
|
setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG); |
|
|
|
setAftertouchRange (m_PerformanceConfig.GetAftertouchRange (nTG), nTG); |
|
|
|
setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG); |
|
|
|
setAftertouchTarget (m_PerformanceConfig.GetAftertouchTarget (nTG), nTG); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Unison parameters
|
|
|
|
|
|
|
|
m_nUnisonVoices[nTG] = m_PerformanceConfig.GetUnisonVoices(nTG); |
|
|
|
|
|
|
|
m_nUnisonDetune[nTG] = m_PerformanceConfig.GetUnisonDetune(nTG); |
|
|
|
|
|
|
|
m_nUnisonSpread[nTG] = m_PerformanceConfig.GetUnisonSpread(nTG); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Effects
|
|
|
|
// Effects
|
|
|
@ -2493,3 +2562,9 @@ bool CMiniDexed::InitNetwork() |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Forward declaration and definition for getPhysicalTG
|
|
|
|
|
|
|
|
static unsigned getPhysicalTG(unsigned logicalTG, unsigned unisonVoice, unsigned unisonVoices); |
|
|
|
|
|
|
|
static unsigned getPhysicalTG(unsigned logicalTG, unsigned unisonVoice, unsigned unisonVoices) { |
|
|
|
|
|
|
|
return logicalTG * unisonVoices + unisonVoice; |
|
|
|
|
|
|
|
} |
|
|
|