diff --git a/build.sh b/build.sh index de4d9f1..ef9ce68 100755 --- a/build.sh +++ b/build.sh @@ -18,9 +18,6 @@ fi cd circle-stdlib/ make mrproper || true ./configure -r ${RPI} --prefix "${TOOLCHAIN_PREFIX}" -if [ "${RPI}" -gt "1" ]; then - echo "DEFINE += -DARM_ALLOW_MULTI_CORE" >> libs/circle/Config.mk -fi echo "DEFINE += -DUSE_PWM_AUDIO_ON_ZERO" >> libs/circle/Config.mk echo "DEFINE += -DSAVE_VFP_REGS_ON_IRQ" >> libs/circle/Config.mk echo "DEFINE += -DREALTIME" >> libs/circle/Config.mk diff --git a/src/kernel.cpp b/src/kernel.cpp index dde24f0..2ad706d 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -18,6 +18,7 @@ // along with this program. If not, see . // #include "kernel.h" +#include #include #include #include @@ -64,7 +65,27 @@ bool CKernel::Initialize (void) m_Config.Load (); - m_pDexed = new CMiniDexed (&m_Config, &mInterrupt, &m_GPIOManager, &m_I2CMaster); + // select the sound device + const char *pSoundDevice = m_Config.GetSoundDevice (); + if (strcmp (pSoundDevice, "i2s") == 0) + { + LOGNOTE ("I2S mode"); + + m_pDexed = new CMiniDexedI2S (&m_Config, &mInterrupt, &m_GPIOManager, &m_I2CMaster); + } + else if (strcmp (pSoundDevice, "hdmi") == 0) + { + LOGNOTE ("HDMI mode"); + + m_pDexed = new CMiniDexedHDMI (&m_Config, &mInterrupt, &m_GPIOManager); + } + else + { + LOGNOTE ("PWM mode"); + + m_pDexed = new CMiniDexedPWM (&m_Config, &mInterrupt, &m_GPIOManager); + } + assert (m_pDexed); if (!m_pDexed->Initialize ()) diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 23f64cb..476a8f3 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -19,28 +19,18 @@ // #include "minidexed.h" #include -#include -#include -#include -#include -#include #include #include LOGMODULE ("minidexed"); -CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, - CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster) +CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, CGPIOManager *pGPIOManager) : CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()), -#ifdef ARM_ALLOW_MULTI_CORE - CMultiCoreSupport (CMemorySystem::Get ()), -#endif m_pConfig (pConfig), m_UI (this, pGPIOManager, pConfig), m_PCKeyboard (this), m_SerialMIDI (this, pInterrupt, pConfig), m_bUseSerial (false), - m_pSoundDevice (0), m_GetChunkTimer ("GetChunk", 1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()), m_bProfileEnabled (m_pConfig->GetProfileEnabled ()) @@ -50,38 +40,10 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, i); assert (m_pMIDIKeyboard[i]); } - - // select the sound device - const char *pDeviceName = pConfig->GetSoundDevice (); - if (strcmp (pDeviceName, "i2s") == 0) - { - LOGNOTE ("I2S mode"); - - m_pSoundDevice = new CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), - pConfig->GetChunkSize (), false, - pI2CMaster, pConfig->GetDACI2CAddress ()); - } - else if (strcmp (pDeviceName, "hdmi") == 0) - { - LOGNOTE ("HDMI mode"); - - m_pSoundDevice = new CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), - pConfig->GetChunkSize ()); - } - else - { - LOGNOTE ("PWM mode"); - - m_pSoundDevice = new CPWMSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), - pConfig->GetChunkSize ()); - } }; bool CMiniDexed::Initialize (void) { - assert (m_pConfig); - assert (m_pSoundDevice); - if (!m_UI.Initialize ()) { return false; @@ -101,37 +63,11 @@ bool CMiniDexed::Initialize (void) ProgramChange (0); setTranspose (24); - // setup and start the sound device - if (!m_pSoundDevice->AllocateQueueFrames (m_pConfig->GetChunkSize ()/2)) - { - LOGERR ("Cannot allocate sound queue"); - - return false; - } - - m_pSoundDevice->SetWriteFormat (SoundFormatSigned16, 1); // 16-bit Mono - - m_nQueueSizeFrames = m_pSoundDevice->GetQueueSizeFrames (); - - m_pSoundDevice->Start (); - -#ifdef ARM_ALLOW_MULTI_CORE - // start secondary cores - if (!CMultiCoreSupport::Initialize ()) - { - return false; - } -#endif - return true; } void CMiniDexed::Process (bool bPlugAndPlayUpdated) { -#ifndef ARM_ALLOW_MULTI_CORE - ProcessSound (); -#endif - for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++) { assert (m_pMIDIKeyboard[i]); @@ -153,21 +89,6 @@ void CMiniDexed::Process (bool bPlugAndPlayUpdated) } } -#ifdef ARM_ALLOW_MULTI_CORE - -void CMiniDexed::Run (unsigned nCore) -{ - if (nCore == 1) - { - while (1) - { - ProcessSound (); - } - } -} - -#endif - CSysExFileLoader *CMiniDexed::GetSysExFileLoader (void) { return &m_SysExFileLoader; @@ -199,30 +120,159 @@ void CMiniDexed::ProgramChange (unsigned nProgram) m_UI.ProgramChanged (nProgram); } -void CMiniDexed::ProcessSound (void) +//// PWM ////////////////////////////////////////////////////////////////////// + +CMiniDexedPWM::CMiniDexedPWM (CConfig *pConfig, CInterruptSystem *pInterrupt, + CGPIOManager *pGPIOManager) +: CMiniDexed (pConfig, pInterrupt, pGPIOManager), + CPWMSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), + pConfig->GetChunkSize ()) { - assert (m_pSoundDevice); +} - unsigned nFrames = m_nQueueSizeFrames - m_pSoundDevice->GetQueueFramesAvail (); - if (nFrames >= m_nQueueSizeFrames/2) +bool CMiniDexedPWM::Initialize (void) +{ + if (!CMiniDexed::Initialize ()) { - if (m_bProfileEnabled) - { - m_GetChunkTimer.Start (); - } + return false; + } - int16_t SampleBuffer[nFrames]; - getSamples (nFrames, SampleBuffer); + return Start (); +} - if ( m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer) - != (int) sizeof SampleBuffer) - { - LOGERR ("Sound data dropped"); - } +unsigned CMiniDexedPWM::GetChunk (u32 *pBuffer, unsigned nChunkSize) +{ + if (m_bProfileEnabled) + { + m_GetChunkTimer.Start (); + } + + unsigned nResult = nChunkSize; + + int16_t SampleBuffer[nChunkSize/2]; + getSamples (nChunkSize/2, SampleBuffer); + + for (unsigned i = 0; nChunkSize > 0; nChunkSize -= 2) // fill the whole buffer + { + s32 nSample = SampleBuffer[i++]; + nSample += 32768; + nSample *= GetRangeMax()/2; + nSample /= 32768; - if (m_bProfileEnabled) + *pBuffer++ = nSample; // 2 stereo channels + *pBuffer++ = nSample; + } + + if (m_bProfileEnabled) + { + m_GetChunkTimer.Stop (); + } + + return nResult; +}; + +//// I2S ////////////////////////////////////////////////////////////////////// + +CMiniDexedI2S::CMiniDexedI2S (CConfig *pConfig, CInterruptSystem *pInterrupt, + CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster) +: CMiniDexed (pConfig, pInterrupt, pGPIOManager), + CI2SSoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), + pConfig->GetChunkSize (), false, pI2CMaster, + pConfig->GetDACI2CAddress ()) +{ +} + +bool CMiniDexedI2S::Initialize (void) +{ + if (!CMiniDexed::Initialize ()) + { + return false; + } + + return Start (); +} + +unsigned CMiniDexedI2S::GetChunk (u32 *pBuffer, unsigned nChunkSize) +{ + if (m_bProfileEnabled) + { + m_GetChunkTimer.Start (); + } + + unsigned nResult = nChunkSize; + + int16_t SampleBuffer[nChunkSize/2]; + getSamples (nChunkSize/2, SampleBuffer); + + for (unsigned i = 0; nChunkSize > 0; nChunkSize -= 2) // fill the whole buffer + { + s32 nSample = SampleBuffer[i++]; + nSample <<= 8; + + *pBuffer++ = nSample; // 2 stereo channels + *pBuffer++ = nSample; + } + + if (m_bProfileEnabled) + { + m_GetChunkTimer.Stop (); + } + + return nResult; +}; + +//// HDMI ///////////////////////////////////////////////////////////////////// + +CMiniDexedHDMI::CMiniDexedHDMI (CConfig *pConfig, CInterruptSystem *pInterrupt, + CGPIOManager *pGPIOManager) +: CMiniDexed (pConfig, pInterrupt, pGPIOManager), + CHDMISoundBaseDevice (pInterrupt, pConfig->GetSampleRate (), + pConfig->GetChunkSize ()) +{ +} + +bool CMiniDexedHDMI::Initialize (void) +{ + if (!CMiniDexed::Initialize ()) + { + return false; + } + + return Start (); +} + +unsigned CMiniDexedHDMI::GetChunk(u32 *pBuffer, unsigned nChunkSize) +{ + if (m_bProfileEnabled) + { + m_GetChunkTimer.Start (); + } + + unsigned nResult = nChunkSize; + + int16_t SampleBuffer[nChunkSize/2]; + getSamples (nChunkSize/2, SampleBuffer); + + unsigned nFrame = 0; + for (unsigned i = 0; nChunkSize > 0; nChunkSize -= 2) // fill the whole buffer + { + s32 nSample = SampleBuffer[i++]; + nSample <<= 8; + + nSample = ConvertIEC958Sample (nSample, nFrame); + if (++nFrame == IEC958_FRAMES_PER_BLOCK) { - m_GetChunkTimer.Stop (); + nFrame = 0; } + + *pBuffer++ = nSample; // 2 stereo channels + *pBuffer++ = nSample; } -} + + if (m_bProfileEnabled) + { + m_GetChunkTimer.Stop(); + } + + return nResult; +}; diff --git a/src/minidexed.h b/src/minidexed.h index ae0eff6..d817f87 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -33,34 +33,25 @@ #include #include #include -#include -#include +#include +#include +#include class CMiniDexed : public CDexedAdapter -#ifdef ARM_ALLOW_MULTI_CORE - , public CMultiCoreSupport -#endif { public: CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, - CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster); + CGPIOManager *pGPIOManager); - bool Initialize (void); + virtual bool Initialize (void); void Process (bool bPlugAndPlayUpdated); -#ifdef ARM_ALLOW_MULTI_CORE - void Run (unsigned nCore); -#endif - CSysExFileLoader *GetSysExFileLoader (void); void BankSelectLSB (unsigned nBankLSB); void ProgramChange (unsigned nProgram); -private: - void ProcessSound (void); - private: CConfig *m_pConfig; @@ -72,12 +63,48 @@ private: CSerialMIDIDevice m_SerialMIDI; bool m_bUseSerial; - CSoundBaseDevice *m_pSoundDevice; - unsigned m_nQueueSizeFrames; - protected: CPerformanceTimer m_GetChunkTimer; bool m_bProfileEnabled; }; +//// PWM ////////////////////////////////////////////////////////////////////// + +class CMiniDexedPWM : public CMiniDexed, public CPWMSoundBaseDevice +{ +public: + CMiniDexedPWM (CConfig *pConfig, CInterruptSystem *pInterrupt, + CGPIOManager *pGPIOManager); + + bool Initialize (void); + + unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize); +}; + +//// I2S ////////////////////////////////////////////////////////////////////// + +class CMiniDexedI2S : public CMiniDexed, public CI2SSoundBaseDevice +{ +public: + CMiniDexedI2S (CConfig *pConfig, CInterruptSystem *pInterrupt, + CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster); + + bool Initialize (void); + + unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize); +}; + +//// HDMI ///////////////////////////////////////////////////////////////////// + +class CMiniDexedHDMI : public CMiniDexed, public CHDMISoundBaseDevice +{ +public: + CMiniDexedHDMI (CConfig *pConfig, CInterruptSystem *pInterrupt, + CGPIOManager *pGPIOManager); + + bool Initialize (void); + + unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize); +}; + #endif