diff --git a/MicroDexed.ino b/MicroDexed.ino index 1b746bb..92b2f06 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -43,13 +43,11 @@ using namespace TeensyTimerTool; #else #include "effect_freeverbf.h" #endif +#include "template_mixer.hpp" #include "UI.hpp" #if NUM_DRUMS > 0 #include "drums.h" #include "drumset.h" -#if NUM_DRUMS > 4 -#include "mixer8.h" -#endif #endif #ifdef SGTL5000_AUDIO_ENHANCE #include "control_sgtl5000plus.h" @@ -64,34 +62,34 @@ AudioSynthWaveform* chorus_modulator[NUM_DEXED]; AudioFilterBiquad* modchorus_filter[NUM_DEXED]; #endif AudioEffectModulatedDelay* modchorus[NUM_DEXED]; -AudioMixer4* chorus_mixer[NUM_DEXED]; -AudioMixer4* delay_fb_mixer[NUM_DEXED]; +AudioMixer<4>* chorus_mixer[NUM_DEXED]; +AudioMixer<4>* delay_fb_mixer[NUM_DEXED]; AudioEffectDelay* delay_fx[NUM_DEXED]; -AudioMixer4* delay_mixer[NUM_DEXED]; +AudioMixer<4>* delay_mixer[NUM_DEXED]; #endif AudioEffectMonoStereo* mono2stereo[NUM_DEXED]; -AudioMixer4 microdexed_peak_mixer; +AudioMixer<4> microdexed_peak_mixer; AudioAnalyzePeak microdexed_peak; #if defined(USE_FX) -AudioMixer4 reverb_mixer_r; -AudioMixer4 reverb_mixer_l; +AudioMixer<4> reverb_mixer_r; +AudioMixer<4> reverb_mixer_l; #ifdef USE_PLATEREVERB AudioEffectPlateReverb reverb; #else AudioEffectFreeverbStereoFloat freeverb; #endif #endif -AudioMixer4 master_mixer_r; -AudioMixer4 master_mixer_l; +AudioMixer<4> master_mixer_r; +AudioMixer<4> master_mixer_l; AudioAmplifier volume_r; AudioAmplifier volume_l; AudioEffectStereoMono stereo2mono; AudioAnalyzePeak master_peak_r; AudioAnalyzePeak master_peak_l; #if defined(TEENSY_AUDIO_BOARD) && defined(SGTL5000_AUDIO_THRU) -AudioMixer4 audio_thru_mixer_r; -AudioMixer4 audio_thru_mixer_l; +AudioMixer<4> audio_thru_mixer_r; +AudioMixer<4> audio_thru_mixer_l; #endif // Drumset @@ -99,19 +97,19 @@ AudioMixer4 audio_thru_mixer_l; //AudioPlayMemory* Drum[NUM_DRUMS]; AudioPlayArrayResmp* Drum[NUM_DRUMS]; #if NUM_DRUMS < 5 -AudioMixer4 drum_mixer_r; -AudioMixer4 drum_mixer_l; +AudioMixer<4> drum_mixer_r; +AudioMixer<4> drum_mixer_l; #else -AudioMixer8 drum_mixer_r; -AudioMixer8 drum_mixer_l; +AudioMixer<8> drum_mixer_r; +AudioMixer<8> drum_mixer_l; #endif #ifdef USE_FX #if NUM_DRUMS < 5 -AudioMixer4 drum_reverb_send_mixer_r; -AudioMixer4 drum_reverb_send_mixer_l; +AudioMixer<4> drum_reverb_send_mixer_r; +AudioMixer<4> drum_reverb_send_mixer_l; #else -AudioMixer8 drum_reverb_send_mixer_r; -AudioMixer8 drum_reverb_send_mixer_l; +AudioMixer<8> drum_reverb_send_mixer_r; +AudioMixer<8> drum_reverb_send_mixer_l; #endif #endif #endif @@ -133,7 +131,7 @@ AudioControlWM8731master wm8731_1; AudioOutputPT8211 pt8211_1; #elif defined(TEENSY_DAC_SYMMETRIC) AudioOutputAnalogStereo dacOut; -AudioMixer4 invMixer; +AudioMixer<4> invMixer; #elif defined(TEENSY_DAC) AudioOutputAnalogStereo dacOut; #endif @@ -241,10 +239,10 @@ void create_audio_dexed_chain(uint8_t instance_id) modchorus_filter[instance_id] = new AudioFilterBiquad(); #endif modchorus[instance_id] = new AudioEffectModulatedDelay(); - chorus_mixer[instance_id] = new AudioMixer4(); - delay_fb_mixer[instance_id] = new AudioMixer4(); + chorus_mixer[instance_id] = new AudioMixer<4>(); + delay_fb_mixer[instance_id] = new AudioMixer<4>(); delay_fx[instance_id] = new AudioEffectDelay(); - delay_mixer[instance_id] = new AudioMixer4(); + delay_mixer[instance_id] = new AudioMixer<4>(); #endif dynamicConnections[nDynamic++] = new AudioConnection(*MicroDexed[instance_id], 0, microdexed_peak_mixer, instance_id); @@ -2225,7 +2223,7 @@ float get_sample_reverb_send(uint8_t sample) uint8_t find_drum_number_from_note(uint8_t note) { - uint8_t number=0; + uint8_t number = 0; for (uint8_t d = 0; d < NUM_DRUMSET_CONFIG - 1; d++) { if (note == drum_config[d].midinote) @@ -2438,8 +2436,10 @@ void generate_version_string(char* buffer, uint8_t len) strncat(buffer, "-3.5", 4); #elif defined(TEENSY3_6) strncat(buffer, "-3.6", 4); -#elif defined(TEENSY4) +#elif defined(TEENSY4_0) strncat(buffer, "-4.0", 4); +#elif defined(TEENSY4_0) + strncat(buffer, "-4.1", 4); #endif #if defined(USE_FX) strncat(buffer, "FX", 2); diff --git a/UI.hpp b/UI.hpp index 2e312fb..864d06a 100644 --- a/UI.hpp +++ b/UI.hpp @@ -38,6 +38,7 @@ #else #include "effect_freeverbf.h" #endif +#include "template_mixer.hpp" #include "drumset.h" #define _LCDML_DISP_cols LCD_cols @@ -129,26 +130,26 @@ extern AudioControlSGTL5000 sgtl5000; #if defined(USE_FX) extern AudioSynthWaveform* chorus_modulator[NUM_DEXED]; extern AudioEffectModulatedDelay* modchorus[NUM_DEXED]; -extern AudioMixer4* chorus_mixer[NUM_DEXED]; -extern AudioMixer4* delay_fb_mixer[NUM_DEXED]; +extern AudioMixer<4>* chorus_mixer[NUM_DEXED]; +extern AudioMixer<4>* delay_fb_mixer[NUM_DEXED]; extern AudioEffectDelay* delay_fx[NUM_DEXED]; -extern AudioMixer4* delay_mixer[NUM_DEXED]; +extern AudioMixer<4>* delay_mixer[NUM_DEXED]; #endif extern AudioEffectMonoStereo* mono2stereo[NUM_DEXED]; -extern AudioMixer4 microdexed_peak_mixer; +extern AudioMixer<4> microdexed_peak_mixer; extern AudioAnalyzePeak microdexed_peak; #if defined(USE_FX) -extern AudioMixer4 reverb_mixer_r; -extern AudioMixer4 reverb_mixer_l; +extern AudioMixer<4> reverb_mixer_r; +extern AudioMixer<4> reverb_mixer_l; #ifdef USE_PLATEREVERB extern AudioEffectPlateReverb reverb; #else extern AudioEffectFreeverbStereoFloat freeverb; #endif #endif -extern AudioMixer4 master_mixer_r; -extern AudioMixer4 master_mixer_l; +extern AudioMixer<4> master_mixer_r; +extern AudioMixer<4> master_mixer_l; extern AudioEffectStereoMono stereo2mono; extern AudioAnalyzePeak master_peak_r; extern AudioAnalyzePeak master_peak_l; diff --git a/mixer8.cpp b/mixer8.cpp deleted file mode 100644 index 0f71e4c..0000000 --- a/mixer8.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* 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 -#include "mixer8.h" -#include "utility/dspinst.h" - -#if defined(__ARM_ARCH_7EM__) -#define MULTI_UNITYGAIN 65536 - -static void applyGain(int16_t *data, int32_t mult) -{ - uint32_t *p = (uint32_t *)data; - const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES); - - do { - uint32_t tmp32 = *p; // read 2 samples from *data - int32_t val1 = signed_multiply_32x16b(mult, tmp32); - int32_t val2 = signed_multiply_32x16t(mult, tmp32); - val1 = signed_saturate_rshift(val1, 16, 0); - val2 = signed_saturate_rshift(val2, 16, 0); - *p++ = pack_16b_16b(val2, val1); - } while (p < end); -} - -static void applyGainThenAdd(int16_t *data, const int16_t *in, int32_t mult) -{ - uint32_t *dst = (uint32_t *)data; - const uint32_t *src = (uint32_t *)in; - const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES); - - if (mult == MULTI_UNITYGAIN) { - do { - uint32_t tmp32 = *dst; - *dst++ = signed_add_16_and_16(tmp32, *src++); - tmp32 = *dst; - *dst++ = signed_add_16_and_16(tmp32, *src++); - } while (dst < end); - } else { - do { - uint32_t tmp32 = *src++; // read 2 samples from *data - int32_t val1 = signed_multiply_32x16b(mult, tmp32); - int32_t val2 = signed_multiply_32x16t(mult, tmp32); - val1 = signed_saturate_rshift(val1, 16, 0); - val2 = signed_saturate_rshift(val2, 16, 0); - tmp32 = pack_16b_16b(val2, val1); - uint32_t tmp32b = *dst; - *dst++ = signed_add_16_and_16(tmp32, tmp32b); - } while (dst < end); - } -} - -#elif defined(KINETISL) -#define MULTI_UNITYGAIN 256 - -static void applyGain(int16_t *data, int32_t mult) -{ - const int16_t *end = data + AUDIO_BLOCK_SAMPLES; - - do { - int32_t val = *data * mult; - *data++ = signed_saturate_rshift(val, 16, 0); - } while (data < end); -} - -static void applyGainThenAdd(int16_t *dst, const int16_t *src, int32_t mult) -{ - const int16_t *end = dst + AUDIO_BLOCK_SAMPLES; - - if (mult == MULTI_UNITYGAIN) { - do { - int32_t val = *dst + *src++; - *dst++ = signed_saturate_rshift(val, 16, 0); - } while (dst < end); - } else { - do { - int32_t val = *dst + ((*src++ * mult) >> 8); // overflow possible?? - *dst++ = signed_saturate_rshift(val, 16, 0); - } while (dst < end); - } -} - -#endif - -void AudioMixer8::update(void) -{ - audio_block_t *in, *out=NULL; - unsigned int channel; - - for (channel=0; channel < 8; channel++) { - if (!out) { - out = receiveWritable(channel); - if (out) { - int32_t mult = multiplier[channel]; - if (mult != MULTI_UNITYGAIN) applyGain(out->data, mult); - } - } else { - in = receiveReadOnly(channel); - if (in) { - applyGainThenAdd(out->data, in->data, multiplier[channel]); - release(in); - } - } - } - if (out) { - transmit(out); - release(out); - } -} - diff --git a/mixer8.h b/mixer8.h deleted file mode 100644 index a4bd841..0000000 --- a/mixer8.h +++ /dev/null @@ -1,70 +0,0 @@ -/* 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 mixer8_h_ -#define mixer8_h_ - -#include "Arduino.h" -#include "AudioStream.h" - -class AudioMixer8 : public AudioStream -{ -#if defined(__ARM_ARCH_7EM__) -public: - AudioMixer8(void) : AudioStream(8, inputQueueArray) { - for (int i=0; i<8; i++) multiplier[i] = 65536; - } - virtual void update(void); - void gain(unsigned int channel, float gain) { - if (channel >= 8) return; - if (gain > 32767.0f) gain = 32767.0f; - else if (gain < -32767.0f) gain = -32767.0f; - multiplier[channel] = gain * 65536.0f; // TODO: proper roundoff? - } -private: - int32_t multiplier[8]; - audio_block_t *inputQueueArray[8]; - -#elif defined(KINETISL) -public: - AudioMixer8(void) : AudioStream(8, inputQueueArray) { - for (int i=0; i<8; i++) multiplier[i] = 256; - } - virtual void update(void); - void gain(unsigned int channel, float gain) { - if (channel >= 8) return; - if (gain > 127.0f) gain = 127.0f; - else if (gain < -127.0f) gain = -127.0f; - multiplier[channel] = gain * 256.0f; // TODO: proper roundoff? - } -private: - int16_t multiplier[8]; - audio_block_t *inputQueueArray[8]; -#endif -}; - -#endif - diff --git a/template_mixer.hpp b/template_mixer.hpp new file mode 100644 index 0000000..244ad07 --- /dev/null +++ b/template_mixer.hpp @@ -0,0 +1,203 @@ +// Taken from https://github.com/manicken/Audio/tree/templateMixer + +/* 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 "Arduino.h" +#include "AudioStream.h" + +#define AudioMixer4 AudioMixer<4> + +#if defined(__ARM_ARCH_7EM__) + +#define MULTI_UNITYGAIN 65536 +#define MULTI_UNITYGAIN_F 65536.0f +#define MAX_GAIN 32767.0f +#define MIN_GAIN -32767.0f +#define MULT_DATA_TYPE int32_t + +#elif defined(KINETISL) + +#define MULTI_UNITYGAIN 256 +#define MULTI_UNITYGAIN_F 256.0f +#define MAX_GAIN 127.0f +#define MIN_GAIN -127.0f +#define MULT_DATA_TYPE int16_t + +#endif + +// because of the template use applyGain and applyGainThenAdd functions +// must be in this file and NOT in cpp file +#if defined(__ARM_ARCH_7EM__) + + static void applyGain(int16_t *data, int32_t mult) + { + uint32_t *p = (uint32_t *)data; + const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES); + + do { + uint32_t tmp32 = *p; // read 2 samples from *data + int32_t val1 = signed_multiply_32x16b(mult, tmp32); + int32_t val2 = signed_multiply_32x16t(mult, tmp32); + val1 = signed_saturate_rshift(val1, 16, 0); + val2 = signed_saturate_rshift(val2, 16, 0); + *p++ = pack_16b_16b(val2, val1); + } while (p < end); + } + + static void applyGainThenAdd(int16_t *data, const int16_t *in, int32_t mult) + { + uint32_t *dst = (uint32_t *)data; + const uint32_t *src = (uint32_t *)in; + const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES); + + if (mult == MULTI_UNITYGAIN) { + do { + uint32_t tmp32 = *dst; + *dst++ = signed_add_16_and_16(tmp32, *src++); + tmp32 = *dst; + *dst++ = signed_add_16_and_16(tmp32, *src++); + } while (dst < end); + } else { + do { + uint32_t tmp32 = *src++; // read 2 samples from *data + int32_t val1 = signed_multiply_32x16b(mult, tmp32); + int32_t val2 = signed_multiply_32x16t(mult, tmp32); + val1 = signed_saturate_rshift(val1, 16, 0); + val2 = signed_saturate_rshift(val2, 16, 0); + tmp32 = pack_16b_16b(val2, val1); + uint32_t tmp32b = *dst; + *dst++ = signed_add_16_and_16(tmp32, tmp32b); + } while (dst < end); + } + } + +#elif defined(KINETISL) + + static void applyGain(int16_t *data, int32_t mult) + { + const int16_t *end = data + AUDIO_BLOCK_SAMPLES; + + do { + int32_t val = *data * mult; + *data++ = signed_saturate_rshift(val, 16, 0); + } while (data < end); + } + + static void applyGainThenAdd(int16_t *dst, const int16_t *src, int32_t mult) + { + const int16_t *end = dst + AUDIO_BLOCK_SAMPLES; + + if (mult == MULTI_UNITYGAIN) { + do { + int32_t val = *dst + *src++; + *dst++ = signed_saturate_rshift(val, 16, 0); + } while (dst < end); + } else { + do { + int32_t val = *dst + ((*src++ * mult) >> 8); // overflow possible?? + *dst++ = signed_saturate_rshift(val, 16, 0); + } while (dst < end); + } + } +#endif + +template class AudioMixer : public AudioStream +{ +public: + AudioMixer(void) : AudioStream(NN, inputQueueArray) { + for (int i=0; i void AudioMixer::gain(unsigned int channel, float gain) { + if (channel >= NN) return; + if (gain > MAX_GAIN) gain = MAX_GAIN; + else if (gain < MIN_GAIN) gain = MIN_GAIN; + multiplier[channel] = gain * MULTI_UNITYGAIN_F; // TODO: proper roundoff? +} + +template void AudioMixer::gain(float gain) { + for (int i = 0; i < NN; i++) { + if (gain > MAX_GAIN) gain = MAX_GAIN; + else if (gain < MIN_GAIN) gain = MIN_GAIN; + multiplier[i] = gain * MULTI_UNITYGAIN_F; // TODO: proper roundoff? + } +} + +template void AudioMixer::update() { + audio_block_t *in, *out=NULL; + unsigned int channel; + for (channel=0; channel < NN; channel++) { + if (!out) { + out = receiveWritable(channel); + if (out) { + int32_t mult = multiplier[channel]; + if (mult != MULTI_UNITYGAIN) applyGain(out->data, mult); + } + } else { + in = receiveReadOnly(channel); + if (in) { + applyGainThenAdd(out->data, in->data, multiplier[channel]); + release(in); + } + } + } + if (out) { + transmit(out); + release(out); + } +} + +#endif