Initial support for multiple Dexed instances

* Currently 2 similar instances, which work with the same parameters
* Only 1 instance with max. 8 notes polyphony on RPi 1
* Chunk size needs to be increased on RPi 1
pull/50/head
Rene Stange 3 years ago
parent 99a6f84bc8
commit 52ebc43671
  1. 6
      src/config.h
  2. 132
      src/minidexed.cpp
  3. 17
      src/minidexed.h
  4. 9
      src/userinterface.cpp

@ -30,7 +30,13 @@
class CConfig // Configuration for MiniDexed class CConfig // Configuration for MiniDexed
{ {
public: public:
#if RASPPI == 1
static const unsigned ToneGenerators = 1;
static const unsigned MaxNotes = 8; // polyphony
#else
static const unsigned ToneGenerators = 2;
static const unsigned MaxNotes = 16; // polyphony static const unsigned MaxNotes = 16; // polyphony
#endif
#if RASPPI <= 3 #if RASPPI <= 3
static const unsigned MaxUSBMIDIDevices = 2; static const unsigned MaxUSBMIDIDevices = 2;

@ -31,7 +31,7 @@ LOGMODULE ("minidexed");
CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster) CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster)
: CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()), :
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
CMultiCoreSupport (CMemorySystem::Get ()), CMultiCoreSupport (CMemorySystem::Get ()),
#endif #endif
@ -45,6 +45,16 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt,
1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()), 1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()),
m_bProfileEnabled (m_pConfig->GetProfileEnabled ()) m_bProfileEnabled (m_pConfig->GetProfileEnabled ())
{ {
assert (m_pConfig);
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ());
assert (m_pTG[i]);
m_pTG[i]->activate ();
}
for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++) for (unsigned i = 0; i < CConfig::MaxUSBMIDIDevices; i++)
{ {
m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, i); m_pMIDIKeyboard[i] = new CMIDIKeyboard (this, pConfig, i);
@ -96,14 +106,18 @@ bool CMiniDexed::Initialize (void)
m_bUseSerial = true; m_bUseSerial = true;
} }
activate ();
SetVolume (100); SetVolume (100);
ProgramChange (0); ProgramChange (0);
setTranspose (24);
setPBController (12, 1); for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
setMWController (99, 7, 0); {
assert (m_pTG[i]);
m_pTG[i]->setTranspose (24);
m_pTG[i]->setPBController (12, 1);
m_pTG[i]->setMWController (99, 7, 0);
}
// setup and start the sound device // setup and start the sound device
if (!m_pSoundDevice->AllocateQueueFrames (m_pConfig->GetChunkSize ())) if (!m_pSoundDevice->AllocateQueueFrames (m_pConfig->GetChunkSize ()))
@ -198,7 +212,11 @@ void CMiniDexed::ProgramChange (unsigned nProgram)
uint8_t Buffer[156]; uint8_t Buffer[156];
m_SysExFileLoader.GetVoice (nProgram, Buffer); m_SysExFileLoader.GetVoice (nProgram, Buffer);
loadVoiceParameters (Buffer); for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->loadVoiceParameters (Buffer);
}
m_UI.ProgramChanged (nProgram); m_UI.ProgramChanged (nProgram);
} }
@ -210,11 +228,81 @@ void CMiniDexed::SetVolume (unsigned nVolume)
return; return;
} }
setGain (nVolume / 127.0); for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->setGain (nVolume / 127.0);
}
m_UI.VolumeChanged (nVolume); m_UI.VolumeChanged (nVolume);
} }
void CMiniDexed::keyup (int16_t pitch)
{
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->keyup (pitch);
}
}
void CMiniDexed::keydown (int16_t pitch, uint8_t velocity)
{
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->keydown (pitch, velocity);
}
}
void CMiniDexed::setSustain(bool sustain)
{
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->setSustain (sustain);
}
}
void CMiniDexed::setModWheel (uint8_t value)
{
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->setModWheel (value);
}
}
void CMiniDexed::setPitchbend (int16_t value)
{
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->setPitchbend (value);
}
}
void CMiniDexed::ControllersRefresh (void)
{
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
assert (m_pTG[i]);
m_pTG[i]->ControllersRefresh ();
}
}
std::string CMiniDexed::GetVoiceName (unsigned nTG)
{
char VoiceName[11];
memset (VoiceName, 0, sizeof VoiceName);
assert (m_pTG[nTG]);
m_pTG[nTG]->setName (VoiceName);
std::string Result (VoiceName);
return Result;
}
void CMiniDexed::ProcessSound (void) void CMiniDexed::ProcessSound (void)
{ {
assert (m_pSoundDevice); assert (m_pSoundDevice);
@ -228,7 +316,33 @@ void CMiniDexed::ProcessSound (void)
} }
int16_t SampleBuffer[nFrames]; int16_t SampleBuffer[nFrames];
getSamples (nFrames, SampleBuffer);
#if RASPPI > 1
for (unsigned i = 0; i < CConfig::ToneGenerators; i++)
{
int16_t TempBuffer[nFrames];
assert (m_pTG[i]);
m_pTG[i]->getSamples (nFrames, TempBuffer);
if (i == 0)
{
for (unsigned j = 0; j < nFrames; j++)
{
SampleBuffer[j] = TempBuffer[j] / CConfig::ToneGenerators;
}
}
else
{
for (unsigned j = 0; j < nFrames; j++)
{
SampleBuffer[j] += TempBuffer[j] / CConfig::ToneGenerators;
}
}
}
#else
m_pTG[0]->getSamples (nFrames, SampleBuffer);
#endif
if ( m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer) if ( m_pSoundDevice->Write (SampleBuffer, sizeof SampleBuffer)
!= (int) sizeof SampleBuffer) != (int) sizeof SampleBuffer)

@ -29,6 +29,7 @@
#include "serialmididevice.h" #include "serialmididevice.h"
#include "perftimer.h" #include "perftimer.h"
#include <stdint.h> #include <stdint.h>
#include <string>
#include <circle/types.h> #include <circle/types.h>
#include <circle/interrupt.h> #include <circle/interrupt.h>
#include <circle/gpiomanager.h> #include <circle/gpiomanager.h>
@ -36,9 +37,9 @@
#include <circle/multicore.h> #include <circle/multicore.h>
#include <circle/soundbasedevice.h> #include <circle/soundbasedevice.h>
class CMiniDexed : public CDexedAdapter class CMiniDexed
#ifdef ARM_ALLOW_MULTI_CORE #ifdef ARM_ALLOW_MULTI_CORE
, public CMultiCoreSupport : public CMultiCoreSupport
#endif #endif
{ {
public: public:
@ -59,12 +60,24 @@ public:
void ProgramChange (unsigned nProgram); void ProgramChange (unsigned nProgram);
void SetVolume (unsigned nVolume); void SetVolume (unsigned nVolume);
void keyup (int16_t pitch);
void keydown (int16_t pitch, uint8_t velocity);
void setSustain (bool sustain);
void setModWheel (uint8_t value);
void setPitchbend (int16_t value);
void ControllersRefresh (void);
std::string GetVoiceName (unsigned nTG = 0);
private: private:
void ProcessSound (void); void ProcessSound (void);
private: private:
CConfig *m_pConfig; CConfig *m_pConfig;
CDexedAdapter *m_pTG[CConfig::ToneGenerators];
CUserInterface m_UI; CUserInterface m_UI;
CSysExFileLoader m_SysExFileLoader; CSysExFileLoader m_SysExFileLoader;

@ -135,20 +135,17 @@ void CUserInterface::ProgramChanged (unsigned nProgram)
nProgram++; // MIDI numbering starts with 0, user interface with 1 nProgram++; // MIDI numbering starts with 0, user interface with 1
// fetch program name from Dexed instance
char ProgramName[11];
memset (ProgramName, 0, sizeof ProgramName);
assert (m_pMiniDexed); assert (m_pMiniDexed);
m_pMiniDexed->setName (ProgramName); std::string VoiceName = m_pMiniDexed->GetVoiceName ();
printf ("Loading voice %u: \"%s\"\n", nProgram, ProgramName); printf ("Loading voice %u: \"%s\"\n", nProgram, VoiceName.c_str ());
if (m_UIMode == UIModeVoiceSelect) if (m_UIMode == UIModeVoiceSelect)
{ {
CString String; CString String;
String.Format ("%u", nProgram); String.Format ("%u", nProgram);
DisplayWrite (String, "VOICE", ProgramName); DisplayWrite (String, "VOICE", VoiceName.c_str ());
} }
} }

Loading…
Cancel
Save