diff --git a/src/minidexed.cpp b/src/minidexed.cpp index ce8f4d9..df37609 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -41,6 +41,9 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_SerialMIDI (this, pInterrupt, pConfig), m_bUseSerial (false), m_pSoundDevice (0), +#ifdef ARM_ALLOW_MULTI_CORE + m_nActiveTGsLog2 (0), +#endif m_GetChunkTimer ("GetChunk", 1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()), m_bProfileEnabled (m_pConfig->GetProfileEnabled ()) @@ -50,6 +53,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, for (unsigned i = 0; i < CConfig::ToneGenerators; i++) { m_nVoiceBankID[i] = 0; + m_nPan[i] = 64; m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()); assert (m_pTG[i]); @@ -138,7 +142,11 @@ bool CMiniDexed::Initialize (void) return false; } +#ifndef ARM_ALLOW_MULTI_CORE m_pSoundDevice->SetWriteFormat (SoundFormatSigned16, 1); // 16-bit Mono +#else + m_pSoundDevice->SetWriteFormat (SoundFormatSigned16, 2); // 16-bit Stereo +#endif m_nQueueSizeFrames = m_pSoundDevice->GetQueueSizeFrames (); @@ -291,6 +299,19 @@ void CMiniDexed::SetVolume (unsigned nVolume, unsigned nTG) m_UI.VolumeChanged (nVolume, nTG); } +void CMiniDexed::SetPan (unsigned nPan, unsigned nTG) +{ + if (nPan > 127) + { + return; + } + + assert (nTG < CConfig::ToneGenerators); + m_nPan[nTG] = nPan; + + m_UI.PanChanged (nPan, nTG); +} + void CMiniDexed::SetMasterTune (int nMasterTune, unsigned nTG) { if (!(-99 <= nMasterTune && nMasterTune <= 99)) @@ -322,6 +343,21 @@ void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG) m_SerialMIDI.SetChannel (uchChannel, nTG); } +#ifdef ARM_ALLOW_MULTI_CORE + unsigned nActiveTGs = 0; + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + if (m_PCKeyboard.GetChannel (nTG) != CMIDIDevice::Disabled) + { + nActiveTGs++; + } + } + + assert (nActiveTGs <= 8); + static const unsigned Log2[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; + m_nActiveTGsLog2 = Log2[nActiveTGs]; +#endif + m_UI.MIDIChannelChanged (uchChannel, nTG); } @@ -452,20 +488,32 @@ void CMiniDexed::ProcessSound (void) } // now mix the output of all TGs - int16_t SampleBuffer[nFrames]; + int16_t SampleBuffer[nFrames][2]; assert (CConfig::ToneGenerators == 8); for (unsigned i = 0; i < nFrames; i++) { - int32_t nSample = m_OutputLevel[0][i] - + m_OutputLevel[1][i] - + m_OutputLevel[2][i] - + m_OutputLevel[3][i] - + m_OutputLevel[4][i] - + m_OutputLevel[5][i] - + m_OutputLevel[6][i] - + m_OutputLevel[7][i]; - - SampleBuffer[i] = (int16_t) (nSample / CConfig::ToneGenerators); + int32_t nLeft = m_OutputLevel[0][i] * (127-m_nPan[0]) + + m_OutputLevel[1][i] * (127-m_nPan[1]) + + m_OutputLevel[2][i] * (127-m_nPan[2]) + + m_OutputLevel[3][i] * (127-m_nPan[3]) + + m_OutputLevel[4][i] * (127-m_nPan[4]) + + m_OutputLevel[5][i] * (127-m_nPan[5]) + + m_OutputLevel[6][i] * (127-m_nPan[6]) + + m_OutputLevel[7][i] * (127-m_nPan[7]); + nLeft >>= m_nActiveTGsLog2 + 7; + + int32_t nRight = m_OutputLevel[0][i] * m_nPan[0] + + m_OutputLevel[1][i] * m_nPan[1] + + m_OutputLevel[2][i] * m_nPan[2] + + m_OutputLevel[3][i] * m_nPan[3] + + m_OutputLevel[4][i] * m_nPan[4] + + m_OutputLevel[5][i] * m_nPan[5] + + m_OutputLevel[6][i] * m_nPan[6] + + m_OutputLevel[7][i] * m_nPan[7]; + nRight >>= m_nActiveTGsLog2 + 7; + + SampleBuffer[i][0] = (int16_t) nLeft; + SampleBuffer[i][1] = (int16_t) nRight; } if ( m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer) diff --git a/src/minidexed.h b/src/minidexed.h index b4dccca..b592af7 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -59,6 +59,7 @@ public: void BankSelectLSB (unsigned nBankLSB, unsigned nTG); void ProgramChange (unsigned nProgram, unsigned nTG); void SetVolume (unsigned nVolume, unsigned nTG); + void SetPan (unsigned nPan, unsigned nTG); // 0 .. 127 void SetMasterTune (int nMasterTune, unsigned nTG); // -99 .. 99 void SetMIDIChannel (uint8_t uchChannel, unsigned nTG); @@ -91,6 +92,7 @@ private: CDexedAdapter *m_pTG[CConfig::ToneGenerators]; unsigned m_nVoiceBankID[CConfig::ToneGenerators]; + unsigned m_nPan[CConfig::ToneGenerators]; CUserInterface m_UI; CSysExFileLoader m_SysExFileLoader; @@ -104,6 +106,7 @@ private: unsigned m_nQueueSizeFrames; #ifdef ARM_ALLOW_MULTI_CORE + unsigned m_nActiveTGsLog2; volatile TCoreStatus m_CoreStatus[CORES]; volatile unsigned m_nFramesToProcess; int16_t m_OutputLevel[CConfig::ToneGenerators][CConfig::MaxChunkSize]; diff --git a/src/userinterface.cpp b/src/userinterface.cpp index 38bb3b6..2df0fdc 100644 --- a/src/userinterface.cpp +++ b/src/userinterface.cpp @@ -44,6 +44,7 @@ CUserInterface::CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManag m_nBank[nTG] = 0; m_nProgram[nTG] = 0; m_nVolume[nTG] = 0; + m_nPan[nTG] = 64; m_nMasterTune[nTG] = 0; m_uchMIDIChannel[nTG] = CMIDIDevice::Disabled; } @@ -185,6 +186,32 @@ void CUserInterface::VolumeChanged (unsigned nVolume, unsigned nTG) } } +void CUserInterface::PanChanged (unsigned nPan, unsigned nTG) +{ + assert (nPan < 128); + assert (nTG < CConfig::ToneGenerators); + m_nPan[nTG] = nPan; + + if ( m_UIMode == UIModePan + && m_nTG == nTG) + { + CString TG; + TG.Format ("TG%u", nTG+1); + + char PanMarker[CConfig::LCDColumns+1]; + memset (PanMarker, '.', CConfig::LCDColumns); + PanMarker[CConfig::LCDColumns] = '\0'; + unsigned nIndex = nPan * CConfig::LCDColumns / 127; + if (nIndex == CConfig::LCDColumns) + { + nIndex--; + } + PanMarker[nIndex] = '\xFF'; + + DisplayWrite (TG, "PAN", PanMarker); + } +} + void CUserInterface::MasterTuneChanged (int nMasterTune, unsigned nTG) { assert (-99 <= nMasterTune && nMasterTune <= 99); @@ -364,6 +391,22 @@ void CUserInterface::EncoderEventHandler (CKY040::TEvent Event) m_pMiniDexed->SetVolume (nVolume, m_nTG); } break; + case UIModePan: { + const int Increment = 128 / CConfig::LCDColumns; + + int nPan = m_nPan[m_nTG] + nStep*Increment; + if (nPan < 0) + { + nPan = 0; + } + else if (nPan > 127) + { + nPan = 127; + } + + m_pMiniDexed->SetPan (nPan, m_nTG); + } break; + case UIModeMasterTune: { int nMasterTune = m_nMasterTune[m_nTG] + nStep; if (nMasterTune < -99) diff --git a/src/userinterface.h b/src/userinterface.h index 06b3448..3602d64 100644 --- a/src/userinterface.h +++ b/src/userinterface.h @@ -42,6 +42,7 @@ public: void BankSelected (unsigned nBankLSB, unsigned nTG); // 0 .. 127 void ProgramChanged (unsigned nProgram, unsigned nTG); // 0 .. 127 void VolumeChanged (unsigned nVolume, unsigned nTG); // 0 .. 127 + void PanChanged (unsigned nPan, unsigned nTG); // 0 .. 127 void MasterTuneChanged (int nMasterTune, unsigned nTG); // -99 .. 99 void MIDIChannelChanged (uint8_t uchChannel, unsigned nTG); @@ -66,6 +67,7 @@ private: UIModeVoiceSelect = UIModeStart, UIModeBankSelect, UIModeVolume, + UIModePan, UIModeMasterTune, UIModeMIDI, UIModeUnknown @@ -87,6 +89,7 @@ private: unsigned m_nBank[CConfig::ToneGenerators]; unsigned m_nProgram[CConfig::ToneGenerators]; unsigned m_nVolume[CConfig::ToneGenerators]; + unsigned m_nPan[CConfig::ToneGenerators]; int m_nMasterTune[CConfig::ToneGenerators]; uint8_t m_uchMIDIChannel[CConfig::ToneGenerators]; };