From 23a860690e39a11fe30620ade24a1baf8ea33fe4 Mon Sep 17 00:00:00 2001 From: palmerr23 Date: Fri, 12 Mar 2021 14:13:16 +1100 Subject: [PATCH] Add files via upload --- matrixMixer_example.ino | 71 ++++++++++++++++++++ mixerMatrix.cpp | 145 ++++++++++++++++++++++++++++++++++++++++ mixerMatrix.h | 87 ++++++++++++++++++++++++ 3 files changed, 303 insertions(+) create mode 100644 matrixMixer_example.ino create mode 100644 mixerMatrix.cpp create mode 100644 mixerMatrix.h diff --git a/matrixMixer_example.ino b/matrixMixer_example.ino new file mode 100644 index 0000000..106de25 --- /dev/null +++ b/matrixMixer_example.ino @@ -0,0 +1,71 @@ +/* + * Matrix mixer example + * + */ +#include +#include "mixerMatrix.h" + +#define INS 8 +#define OUTS 2 +#define BLOX 20 + +AudioSynthWaveformSine sine1; +AudioAnalyzePeak peak1; +// define the mixer with the required number of INS and OUTS +AudioMixerMatrix Amixer(INS, OUTS); +AudioAnalyzePeak peak2; +AudioAnalyzePeak peak3; + +// we need a source of interrupts for the Audio library to operate +// AudioInputAnalog is convenient for T3s, but doesn't create interrupts on the T4 (yet) +// I2S (SGTL5000) is used herre as it's the most common +//AudioInputAnalog adc1; +AudioOutputI2S i2s1; +AudioControlSGTL5000 sgtl1; + +// sine to mixer input 1 and peak1 +AudioConnection p1(sine1, 0, Amixer, 0); +AudioConnection p2(sine1, 0, peak1, 0); + +// mixer outputs 1 & 2 to peaks and I2S +AudioConnection p3(Amixer, 0, i2s1, 0); +AudioConnection p4(Amixer, 0, peak2, 0); + +AudioConnection p5(Amixer, 1, i2s1, 1); +AudioConnection p6(Amixer, 1, peak3, 0); +void setup() +{ + // put your setup code here, to run once: + AudioMemory(BLOX); + Serial.begin(115200); + delay(1000); + Serial.println("Starting matrix mixer example"); + + sgtl1.enable(); + sine1.frequency(800); + sine1.amplitude(1.0); + +Serial.println("Done setup"); +} +uint32_t loops; +float Again1 = 1.0, Again2 = 1.0; +void loop() { + int procUse = AudioProcessorUsage(); + int memUse = AudioMemoryUsage(); + float peakA = peak1.read(); + float peakB = peak2.read(); + float peakC = peak3.read(); + + Serial.printf("%i: proc %i, mem %i, input level %3.2f\n", loops, procUse, memUse, peakA); + Serial.printf("Gain1 %3.2f, output1 level %3.2f\n", Again1, peakB); + Serial.printf("Gain2 %3.2f, output2 level %3.2f\n\n", Again2, peakC); + + // set gain for next iteration + Again1 = (float)random(100, 1000) / 1000.0; // gain 0.1 .. 1.0 + Amixer.gain(0, 0, Again1); + Again2 = (float)random(100, 1000) / 1000.0; // gain 0.1 .. 1.0 + Amixer.gain(0, 1, Again2); + + delay(5000); + loops++; +} diff --git a/mixerMatrix.cpp b/mixerMatrix.cpp new file mode 100644 index 0000000..59297c2 --- /dev/null +++ b/mixerMatrix.cpp @@ -0,0 +1,145 @@ +/* Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Modified by Macaba, palmerr23 + * + * 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 "mixerMatrix.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 AudioMixerMatrix::update(void) +{ + audio_block_t *in[MMINMAX], *out=NULL; + unsigned int inChannel, outChannel; + unsigned int sample; + + // get the incoming audio_blocks + for (inChannel=0; inChannel < inChannels; inChannel++) { + in[inChannel] = receiveReadOnly(inChannel); + } + + // crosspoint mix + for (outChannel=0; outChannel < outChannels; outChannel++) { + out = allocate(); //get an audio_block that we'll sum the other channels to + for(sample=0; sample < AUDIO_BLOCK_SAMPLES; sample++){ + out->data[sample] = 0; // slightly faster than memset()? + } + // OR memset(out->data, 0, AUDIO_BLOCK_SAMPLES * sizeof(int16_t)); + + if(out){ + for (inChannel=0; inChannel < inChannels; inChannel++) { + if (in[inChannel]) { + applyGainThenAdd(out->data, in[inChannel]->data, multiplier[inChannel][outChannel]); + } + } + transmit(out, outChannel); + release(out); + } + } //outChannel +//Now release all the input audio_blocks + for (inChannel=0; inChannel < inChannels; inChannel++) { + if(in[inChannel]) + release(in[inChannel]); + } +} + diff --git a/mixerMatrix.h b/mixerMatrix.h new file mode 100644 index 0000000..c2cb7cd --- /dev/null +++ b/mixerMatrix.h @@ -0,0 +1,87 @@ +/* Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Modified by Macaba, palmerr23 + * + * 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" +#define MMINPUTS 4 // default numbers for inputs and outputs +#define MMOUTPUTS 4 +#define MMINMAX 8 // Biggest values +#define MMOUTMAX 8 + +class AudioMixerMatrix : public AudioStream +{ +#if defined(__ARM_ARCH_7EM__) +public: + AudioMixerMatrix(uint8_t inCh = MMINPUTS, uint8_t outCh = MMOUTPUTS) : AudioStream(inCh, inputQueueArray) { + inChannels = inCh; + outChannels = outCh; + for (int i=0; i< MMINMAX; i++) + for(int j=0; j= MMOUTMAX) return; + if (inChannel >= MMINMAX) return; + if (gain > 32767.0f) gain = 32767.0f; + else if (gain < -32767.0f) gain = -32767.0f; + multiplier[inChannel][outChannel] = gain * 65536.0f; // TODO: proper roundoff? + } +private: + int32_t multiplier[MMINMAX][MMOUTMAX]; + audio_block_t *inputQueueArray[MMINMAX]; + uint8_t inChannels, outChannels; + +#elif defined(KINETISL) +public: + AudioMixerMatrix(uint8_t inCh = MMINPUTS, uint8_t outCh = MMOUTPUTS) : AudioStream(inCh, inputQueueArray) { + inChannels = inCh; + outChannels = outCh; + for (int i=0; i< MMINMAX; i++) + for(int j=0; j= MMOUTMAX) return; + if (inChannel >= MMINMAX) return; + if (gain > 127.0f) gain = 127.0f; + else if (gain < -127.0f) gain = -127.0f; + multiplier[inChannel][outChannel] = gain * 256.0f; // TODO: proper roundoff? + } +private: + int16_t multiplier[MMINMAX][MMOUTMAX]; + audio_block_t *inputQueueArray[MMINMAX]; + uint8_t inChannels, outChannels; +#endif +}; + +#endif