diff --git a/src/Makefile b/src/Makefile index 8612096..fff576f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ CMSIS_DIR = ../CMSIS_5/CMSIS OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \ mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \ sysexfileloader.o performanceconfig.o perftimer.o \ - effect_platervbstereo.o effect_compressor.o + effect_mixer.o effect_compressor.o effect_platervbstereo.o include ./Synth_Dexed.mk include ./Rules.mk diff --git a/src/effect_mixer.cpp b/src/effect_mixer.cpp index 2a4861c..77d65fd 100644 --- a/src/effect_mixer.cpp +++ b/src/effect_mixer.cpp @@ -1,38 +1,22 @@ // Taken from https://github.com/manicken/Audio/tree/templateMixer // Adapted for MiniDexed by Holger Wirtz <dcoredump@googlemail.com> -/* Audio Library for Teensy 3.X - * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - #include <cstdlib> #include <stdint.h> #include <assert.h> #include "arm_math.h" #include "effect_mixer.h" +template <int NN> AudioMixer<NN>::AudioMixer(uint16_t len) +{ + buffer_length=len; + for (uint8_t i=0; i<NN; i++) + multiplier[i] = UNITY_GAIN; + + sumbufL=(float32_t*)malloc(sizeof(float32_t) * buffer_length); + arm_fill_f32(0.0, sumbufL, len); +} + template <int NN> void AudioMixer<NN>::gain(uint8_t channel, float32_t gain) { if (channel >= NN) return; @@ -56,50 +40,108 @@ template <int NN> void AudioMixer<NN>::gain(float32_t gain) } } -template <int NN> void AudioMixer<NN>::doAddMix(uint8_t channel, float32_t* in, float32_t* out, uint16_t len) +template <int NN> void AudioMixer<NN>::doAddMix(uint8_t channel, float32_t* in) { - float32_t* tmp=malloc(sizeof(float32_t)*len); + float32_t* tmp=malloc(sizeof(float32_t)*buffer_length); assert(tmp!=NULL); + assert(in); + + if(multiplier[channel]!=UNITY_GAIN) + arm_scale_f32(in,multiplier[channel],tmp,buffer_length); + arm_add_f32(sumbufL, tmp, sumbufL, buffer_length); - arm_scale_f32(in,multiplier[channel],tmp,len); - arm_add_f32(out, tmp, out, len); + if(sumbufL) + arm_fill_f32(0.0, sumbufL, buffer_length); free(tmp); } -template <int NN> void AudioMixer<NN>::get_mix(float32_t* buffer, uint16_t len) +template <int NN> void AudioMixer<NN>::getMix(float32_t* buffer) { assert(buffer); - assert(sumbuf); - arm_copy_f32 (sumbuf, buffer, len); + assert(sumbufL); + arm_copy_f32(sumbufL, buffer, buffer_length); +} + +template <int NN> AudioStereoMixer<NN>::AudioStereoMixer(uint16_t len) : AudioMixer<NN>(len) +{ + buffer_length=len; + for (uint8_t i=0; i<NN; i++) + panorama[i] = UNITY_PANORAMA; + + sumbufR=(float32_t*)malloc(sizeof(float32_t) * buffer_length); + arm_fill_f32(0.0, sumbufR, buffer_length); +} + +template <int NN> void AudioStereoMixer<NN>::pan(uint8_t channel, float32_t pan) +{ + if (channel >= NN) return; + + if (pan > MAX_PANORAMA) + pan = MAX_PANORAMA; + else if (pan < MIN_PANORAMA) + pan = MIN_PANORAMA; + panorama[channel] = pan; } -template <int NN> void AudioStereoMixer<NN>::doAddMix(uint8_t channel, float32_t* inL, float32_t* inR, float32_t* outL, float32_t* outR, uint16_t len) +template <int NN> void AudioStereoMixer<NN>::doAddMix(uint8_t channel, float32_t* in) { - float32_t* tmp=malloc(sizeof(float32_t)*len); + float32_t* tmp=malloc(sizeof(float32_t)*buffer_length); assert(tmp!=NULL); + assert(in); - // panorama - for(uint16_t i=0;i<len;i++) - { - // left - arm_scale_f32(inL,AudioMixer<NN>::multiplier[channel],tmp,len); - arm_add_f32(outL, tmp, outL, len); - // right - arm_scale_f32(inR,AudioMixer<NN>::multiplier[channel],tmp,len); - arm_add_f32(outR, tmp, outR, len); - } + // left + arm_scale_f32(in, 1.0f-panorama[channel], tmp, buffer_length); + if(multiplier[channel]!=UNITY_GAIN) + arm_scale_f32(tmp,AudioMixer<NN>::multiplier[channel],tmp,buffer_length); + arm_add_f32(sumbufL, tmp, sumbufL, buffer_length); + // right + arm_scale_f32(in, panorama[channel], tmp, buffer_length); + if(multiplier[channel]!=UNITY_GAIN) + arm_scale_f32(tmp,AudioMixer<NN>::multiplier[channel],tmp,buffer_length); + arm_add_f32(sumbufR, tmp, sumbufR, buffer_length); + + if(sumbufL) + arm_fill_f32(0.0, sumbufL, buffer_length); + if(sumbufR) + arm_fill_f32(0.0, sumbufR, buffer_length); + + free(tmp); +} + +template <int NN> void AudioStereoMixer<NN>::doAddMix(uint8_t channel, float32_t* inL, float32_t* inR) +{ + float32_t* tmp=malloc(sizeof(float32_t)*buffer_length); + + assert(tmp!=NULL); + assert(inL); + assert(inR); + + // left + if(multiplier[channel]!=UNITY_GAIN) + arm_scale_f32(inL,AudioMixer<NN>::multiplier[channel],tmp,buffer_length); + arm_add_f32(sumbufL, tmp, sumbufL, buffer_length); + // right + if(multiplier[channel]!=UNITY_GAIN) + arm_scale_f32(inR,AudioMixer<NN>::multiplier[channel],tmp,buffer_length); + arm_add_f32(sumbufR, tmp, sumbufR, buffer_length); + + if(sumbufL) + arm_fill_f32(0.0, sumbufL, buffer_length); + if(sumbufR) + arm_fill_f32(0.0, sumbufR, buffer_length); free(tmp); } -template <int NN> void AudioMixer<NN>::get_mix(float32_t* bufferL, float32_t bufferL, uint16_t len) +template <int NN> void AudioStereoMixer<NN>::getMix(float32_t* bufferL, float32_t* bufferR) { assert(bufferR); assert(bufferL); - assert(sumbuf); - arm_copy_f32 (sumbuf[0], bufferL, len); - arm_copy_f32 (sumbuf[1], bufferR, len); + assert(sumbufL); + assert(sumbufR); + arm_copy_f32 (sumbufL, bufferL, buffer_length); + arm_copy_f32 (sumbufR, bufferR, buffer_length); } diff --git a/src/effect_mixer.h b/src/effect_mixer.h index 1df26ce..2a401a4 100644 --- a/src/effect_mixer.h +++ b/src/effect_mixer.h @@ -1,87 +1,45 @@ // Taken from https://github.com/manicken/Audio/tree/templateMixer // Adapted for MiniDexed by Holger Wirtz <dcoredump@googlemail.com> -/* Audio Library for Teensy 3.X - * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com - * - * Development of this audio library was funded by PJRC.COM, LLC by sales of - * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop - * open source software by purchasing Teensy or other PJRC products. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice, development funding notice, and this permission - * notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - #ifndef template_mixer_h_ #define template_mixer_h_ #include "arm_math.h" #include <stdint.h> -#define UNITYGAIN 1.0f +#define UNITY_GAIN 1.0f #define MAX_GAIN 1.0f #define MIN_GAIN 0.0f +#define UNITY_PANORAMA 1.0f +#define MAX_PANORAMA 1.0f +#define MIN_PANORAMA 0.0f template <int NN> class AudioMixer { public: - AudioMixer(uint16_t len) - { - for (uint8_t i=0; i<NN; i++) - multiplier[i] = UNITYGAIN; - - sumbufL=(float32_t*)malloc(sizeof(float32_t) * len); - arm_fill_f32(0.0, sumbufL, len); - }; - void doAddMix(uint8_t channel, float32_t* in, uint16_t len); - /** - * this sets the individual gains - * @param channel - * @param gain - */ + AudioMixer(uint16_t len); + void doAddMix(uint8_t channel, float32_t* in); void gain(uint8_t channel, float32_t gain); - /** - * set all channels to specified gain - * @param gain - */ void gain(float32_t gain); - void get_mix(float32_t* buffer, uint16_t len); - + void getMix(float32_t* buffer); protected: float32_t multiplier[NN]; float32_t* sumbufL; + uint16_t buffer_length; }; template <int NN> class AudioStereoMixer : public AudioMixer<NN> { public: - AudioStereoMixer(uint16_t len) - { - AudioMixer<NN>(len); - for (uint8_t i=0; i<NN; i++) - panorama[i] = 0.0; - - sumbufR=(float32_t*)malloc(sizeof(float32_t) * len); - arm_fill_f32(0.0, sumbufR, len); - }; - void doAddMix(uint8_t channel, float32_t* inL, float32_t* inR, uint16_t len); - void get_mix(float32_t* bufferL, float32_t* bufferR, uint16_t len); + AudioStereoMixer(uint16_t len); + void pan(uint8_t channel, float32_t pan); + void doAddMix(uint8_t channel, float32_t* in); + void doAddMix(uint8_t channel, float32_t* inL, float32_t* inR); + void getMix(float32_t* bufferL, float32_t* bufferR); protected: + using AudioMixer<NN>::sumbufL; + using AudioMixer<NN>::multiplier; + using AudioMixer<NN>::buffer_length; float32_t panorama[NN]; float32_t* sumbufR; }; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index a242a6e..18d32c2 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -115,7 +115,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, #endif // BEGIN setup tg_mixer - //tg_mixer = new AudioStereoMixer<8>(pConfig->GetChunkSize()); + tg_mixer = new AudioStereoMixer<8>(pConfig->GetChunkSize()); // END setup tgmixer // BEGIN setup reverb @@ -748,7 +748,6 @@ void CMiniDexed::ProcessSound (void) // // now mix the output of all TGs - float32_t SampleBuffer[2][nFrames]; uint8_t indexL=0, indexR=1; if (m_bChannelsSwapped) @@ -756,42 +755,29 @@ void CMiniDexed::ProcessSound (void) indexL=1; indexR=0; } - - // init left sum output - assert (SampleBuffer[0]!=NULL); - arm_fill_f32(0.0, SampleBuffer[0], nFrames); - // init right sum output - assert (SampleBuffer[1]!=NULL); - arm_fill_f32(0.0, SampleBuffer[1], nFrames); assert (CConfig::ToneGenerators == 8); // BEGIN stereo panorama and TG mixing for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) { - float32_t tmpBuffer[2][nFrames]; - - assert (tmpBuffer[0]!=NULL); - arm_fill_f32(0.0, tmpBuffer[0], nFrames); - assert (tmpBuffer[1]!=NULL); - arm_fill_f32(0.0, tmpBuffer[1], nFrames); - - m_PanoramaSpinLock.Acquire (); - // calculate left panorama of this TG - arm_scale_f32(m_OutputLevel[i], 1.0f-m_fPan[i], tmpBuffer[0], nFrames); - // add left panorama output of this TG to sum output - arm_add_f32(SampleBuffer[indexL], tmpBuffer[0], SampleBuffer[indexL], nFrames); - - // calculate right panorama of this TG - arm_scale_f32(m_OutputLevel[i], m_fPan[i], tmpBuffer[1], nFrames); - // add right panaorama output of this TG to sum output - arm_add_f32(SampleBuffer[indexR], tmpBuffer[1], SampleBuffer[indexR], nFrames); - //tg_mixer->doAddMix(i,tmpBuffer[0],tmpBuffer[1],nFrames); - m_PanoramaSpinLock.Release (); + tg_mixer->pan(i,m_fPan[i]); + tg_mixer->doAddMix(i,m_OutputLevel[i]); } // END stereo panorama and TG mixing // BEGIN adding reverb + float32_t SampleBuffer[2][nFrames]; + + // init left sum output + assert (SampleBuffer[0]!=NULL); + arm_fill_f32(0.0, SampleBuffer[0], nFrames); + // init right sum output + assert (SampleBuffer[1]!=NULL); + arm_fill_f32(0.0, SampleBuffer[1], nFrames); + + tg_mixer->getMix(SampleBuffer[indexL], SampleBuffer[indexR]); + if (m_nParameter[ParameterReverbEnable]) { float32_t ReverbBuffer[2][nFrames]; diff --git a/src/minidexed.h b/src/minidexed.h index f343879..2c22ece 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -42,7 +42,7 @@ #include "common.h" #include "effect_platervbstereo.h" #include "effect_compressor.h" -//#include "effect_mixer.h" +#include "effect_mixer.h" class CMiniDexed #ifdef ARM_ALLOW_MULTI_CORE @@ -176,7 +176,7 @@ private: bool m_bProfileEnabled; AudioEffectPlateReverb* reverb; - //AudioStereoMixer<8>* tg_mixer; + AudioStereoMixer<8>* tg_mixer; CSpinLock m_PanoramaSpinLock; CSpinLock m_ReverbSpinLock;