I'm creating a library object that selects 1 of 16 input blocks, applies gain, and then outputs a single block of audio.
I've been testing this on the Teensy 4.0. The multiplexing/switch of inputs seems to work fine, but when the gain of the output is set to 0.0 my code seems to crash.
The gain stage is code taken from the Amplifier library.
Would appreciate some input on what I might be doing wrong in my code.
muxAmp.H
muxAmp.cpp
I've been testing this on the Teensy 4.0. The multiplexing/switch of inputs seems to work fine, but when the gain of the output is set to 0.0 my code seems to crash.
The gain stage is code taken from the Amplifier library.
Would appreciate some input on what I might be doing wrong in my code.
muxAmp.H
Code:
#ifndef muxamp_h_
#define muxamp_h_
#include "Arduino.h"
#include "AudioStream.h"
class AudioMuxAmp : public AudioStream
{
public:
AudioMuxAmp(void) : AudioStream(16, inputQueueArray), multiplier(65536){}
virtual void update(void);
void gain(float n)
{
if (n > 32767.0f) n = 32767.0f;
else if (n < -32767.0f) n = -32767.0f;
multiplier = n * 65536.0f;
}
void select(byte input)
{
input_select = input;
}
private:
int32_t multiplier;
byte input_select;
audio_block_t *inputQueueArray[16];
};
#endif
muxAmp.cpp
Code:
#include <Arduino.h>
#include "muxamp.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);
}
//I added this to write all "0"s to the output block
static void makeZeros(int16_t *data)
{
uint32_t *p = (uint32_t *)data;
const uint32_t *end = (uint32_t *)(data + AUDIO_BLOCK_SAMPLES);
do
{
*p++ = 0;
}
while (p < 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);
}
//I added this to write all "0"s to the output block
static void makeZeros(int16_t *data)
{
const int16_t *end = data + AUDIO_BLOCK_SAMPLES;
do
{
*data++ = 0;
}
while (data < end);
}
#endif
void AudioMuxAmp::update(void)
{
audio_block_t *block;
int32_t mult = multiplier;
byte inSource = input_select;
if (mult == 0)
{
// zero gain, discard any input and transmit nothing
//block = receiveReadOnly(inSource);//original code
//if (block) release(block);//original code
//code I changed
block = receiveWritable(inSource);
if (block)
{
makeZeros(block->data);
transmit(block);
release(block);
}
}
else if (mult == MULTI_UNITYGAIN)
{
// unity gain, pass input to output without any change
block = receiveReadOnly(inSource);
if (block)
{
transmit(block);
release(block);
}
}
else
{
// apply gain to signal
block = receiveWritable(inSource);
if (block)
{
applyGain(block->data, mult);
transmit(block);
release(block);
}
}
}