From 7666793cc5431fefeb4caec8123a2d21f520138c Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Sun, 22 May 2022 12:42:30 +0200 Subject: [PATCH] Sending voice data via SYSEX when voice is changed. Adding master volume and changing master volume when SYSEX master volume is triggered. --- src/.mididevice.cpp.swp | Bin 24576 -> 0 bytes src/mididevice.cpp | 5 +- src/mididevice.h | 2 +- src/minidexed.cpp | 114 ++++++++++++++++++++++++---------------- src/minidexed.h | 3 ++ 5 files changed, 76 insertions(+), 48 deletions(-) delete mode 100644 src/.mididevice.cpp.swp diff --git a/src/.mididevice.cpp.swp b/src/.mididevice.cpp.swp deleted file mode 100644 index 2e5140579eb329cf52896835cd85cac9db380542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 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 diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 712adfa..9762e49 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -170,9 +170,9 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign // GLOBAL MIDI SYSEX if (pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN && pMessage[3] == 0x04 && pMessage[4] == 0x01 && pMessage[nLength-1] == MIDI_SYSTEM_EXCLUSIVE_END) // MASTER VOLUME { - float32_t nMasterVolume=(pMessage[5] & (pMessage[6]<<7))/(1<<14); + float32_t nMasterVolume=((pMessage[5] & 0x7c) & ((pMessage[6] & 0x7c) <<7))/(1<<14); LOGNOTE("Master volume: %f",nMasterVolume); - // TODO: Handle global master volume + m_pSynthesizer->setMasterVolume(nMasterVolume); } else { @@ -427,7 +427,6 @@ void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nL // load sysex-data into voice memory LOGDBG("One Voice bulk upload"); m_pSynthesizer->loadVoiceParameters(pMessage,nTG); - break; case 200: LOGDBG("Bank bulk upload."); diff --git a/src/mididevice.h b/src/mididevice.h index 556306e..196a61b 100644 --- a/src/mididevice.h +++ b/src/mididevice.h @@ -49,12 +49,12 @@ public: u8 GetChannel (unsigned nTG) const; virtual void Send (const u8 *pMessage, size_t nLength, unsigned nCable = 0) {} + virtual void SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG); protected: void MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsigned nCable = 0); void AddDevice (const char *pDeviceName); void HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG); - void SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG); private: CMiniDexed *m_pSynthesizer; CConfig *m_pConfig; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 1e1c173..c434c0a 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -363,6 +363,7 @@ void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) assert (m_pTG[nTG]); m_pTG[nTG]->loadVoiceParameters (Buffer); + m_SerialMIDI.SendSystemExclusiveVoice(nProgram,0,nTG); m_UI.ParameterChanged (); } @@ -867,56 +868,70 @@ void CMiniDexed::ProcessSound (void) } // BEGIN TG mixing - for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) - { - tg_mixer->doAddMix(i,m_OutputLevel[i]); - reverb_send_mixer->doAddMix(i,m_OutputLevel[i]); - } - // END TG mixing - - // BEGIN create SampleBuffer for holding audio data - float32_t SampleBuffer[2][nFrames]; - // END create SampleBuffer for holding audio data - - // get the mix of all TGs - tg_mixer->getMix(SampleBuffer[indexL], SampleBuffer[indexR]); + float32_t tmp_float[nFrames*2]; + int16_t tmp_int[nFrames*2]; - // BEGIN adding reverb - if (m_nParameter[ParameterReverbEnable]) + if(nMasterVolume > 0.0) { - float32_t ReverbBuffer[2][nFrames]; - float32_t ReverbSendBuffer[2][nFrames]; - - arm_fill_f32(0.0f, ReverbBuffer[indexL], nFrames); - arm_fill_f32(0.0f, ReverbBuffer[indexR], nFrames); - arm_fill_f32(0.0f, ReverbSendBuffer[indexR], nFrames); - arm_fill_f32(0.0f, ReverbSendBuffer[indexL], nFrames); - - m_ReverbSpinLock.Acquire (); - - reverb_send_mixer->getMix(ReverbSendBuffer[indexL], ReverbSendBuffer[indexR]); - reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames); + for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) + { + tg_mixer->doAddMix(i,m_OutputLevel[i]); + reverb_send_mixer->doAddMix(i,m_OutputLevel[i]); + } + // END TG mixing + + // BEGIN create SampleBuffer for holding audio data + float32_t SampleBuffer[2][nFrames]; + // END create SampleBuffer for holding audio data - // scale down and add left reverb buffer by reverb level - arm_scale_f32(ReverbBuffer[indexL], reverb->get_level(), ReverbBuffer[indexL], nFrames); - arm_add_f32(SampleBuffer[indexL], ReverbBuffer[indexL], SampleBuffer[indexL], nFrames); - // scale down and add right reverb buffer by reverb level - arm_scale_f32(ReverbBuffer[indexR], reverb->get_level(), ReverbBuffer[indexR], nFrames); - arm_add_f32(SampleBuffer[indexR], ReverbBuffer[indexR], SampleBuffer[indexR], nFrames); + // get the mix of all TGs + tg_mixer->getMix(SampleBuffer[indexL], SampleBuffer[indexR]); - m_ReverbSpinLock.Release (); - } - // END adding reverb + // BEGIN adding reverb + if (m_nParameter[ParameterReverbEnable]) + { + float32_t ReverbBuffer[2][nFrames]; + float32_t ReverbSendBuffer[2][nFrames]; - // Convert dual float array (left, right) to single int16 array (left/right) - float32_t tmp_float[nFrames*2]; - int16_t tmp_int[nFrames*2]; - for(uint16_t i=0; igetMix(ReverbSendBuffer[indexL], ReverbSendBuffer[indexR]); + reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames); + + // scale down and add left reverb buffer by reverb level + arm_scale_f32(ReverbBuffer[indexL], reverb->get_level(), ReverbBuffer[indexL], nFrames); + arm_add_f32(SampleBuffer[indexL], ReverbBuffer[indexL], SampleBuffer[indexL], nFrames); + // scale down and add right reverb buffer by reverb level + arm_scale_f32(ReverbBuffer[indexR], reverb->get_level(), ReverbBuffer[indexR], nFrames); + arm_add_f32(SampleBuffer[indexR], ReverbBuffer[indexR], SampleBuffer[indexR], nFrames); + + m_ReverbSpinLock.Release (); + } + // END adding reverb + + // Convert dual float array (left, right) to single int16 array (left/right) + for(uint16_t i=0; i0.0 && nMasterVolume <1.0) + { + tmp_float[i*2]=SampleBuffer[indexL][i] * nMasterVolume; + tmp_float[(i*2)+1]=SampleBuffer[indexR][i] * nMasterVolume; + } + else if(nMasterVolume == 1.0) + { + tmp_float[i*2]=SampleBuffer[indexL][i]; + tmp_float[(i*2)+1]=SampleBuffer[indexR][i]; + } + } + arm_float_to_q15(tmp_float,tmp_int,nFrames*2); } - arm_float_to_q15(tmp_float,tmp_int,nFrames*2); + else + arm_fill_q15(0, tmp_int, nFrames * 2); if (m_pSoundDevice->Write (tmp_int, sizeof(tmp_int)) != (int) sizeof(tmp_int)) { @@ -1183,3 +1198,14 @@ void CMiniDexed::getSysExVoiceDump(uint8_t* dest, uint8_t nTG) dest[161] = checksum & 0x7f; // Checksum dest[162] = 0xF7; // SysEx end } + +void CMiniDexed::setMasterVolume (float32_t vol) +{ + if(vol < 0.0) + vol = 0.0; + else if(vol > 1.0) + vol = 1.0; + + nMasterVolume=vol; +} + diff --git a/src/minidexed.h b/src/minidexed.h index 6eccf3e..14a1023 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -150,6 +150,7 @@ public: std::string GetVoiceName (unsigned nTG); bool SavePerformance (void); + void setMasterVolume (float32_t vol); private: int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note @@ -195,6 +196,8 @@ private: unsigned m_nReverbSend[CConfig::ToneGenerators]; + float32_t nMasterVolume; + CUserInterface m_UI; CSysExFileLoader m_SysExFileLoader; CPerformanceConfig m_PerformanceConfig;