Hi, I'm writing a surround panner object for use with the Teensy and the CS42448 8ch codec. It accepts an audio input and a -1 to 1 control input, sending the input to one of 8 outputs.
I'm wondering how I can accomplish equal power scaling using audio library integer math. Is there any sort of optimized square root routine I can use for this?
Additionally, in order to pan based on one 16-bit control signal, I'm having to compress the amplitude scaling down to 12-bits. Is there any simple smoothing y'all can recommend that could remove some of the steppiness this introduces to the signal?
Also, this is my first crack at a more complicated audio object using the optimized integer math, if you see anything I could be doing better best practice wise I'd appreciate any tips. Thanks!
Here's the start I have on the panner object code:
I'm wondering how I can accomplish equal power scaling using audio library integer math. Is there any sort of optimized square root routine I can use for this?
Additionally, in order to pan based on one 16-bit control signal, I'm having to compress the amplitude scaling down to 12-bits. Is there any simple smoothing y'all can recommend that could remove some of the steppiness this introduces to the signal?
Also, this is my first crack at a more complicated audio object using the optimized integer math, if you see anything I could be doing better best practice wise I'd appreciate any tips. Thanks!
Here's the start I have on the panner object code:
Code:
#ifndef panner_h_
#define panner_h_
#include "Arduino.h"
#include "AudioStream.h"
#define PANNER_NUM_CHANNELS 8
class Panner : public AudioStream
{
public:
Panner( void ) : AudioStream(2, inputQueueArray) {}
virtual void update(void);
private:
audio_block_t *inputQueueArray[2];
};
#endif
Code:
#include <Arduino.h>
#include "panner.h"
#include "utility/dspinst.h"
void Panner::update(void){
audio_block_t *in = receiveReadOnly(0);
audio_block_t *out[8]; // = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
if(in){
audio_block_t *pan = receiveReadOnly(1);
if(pan){
for(int och = 0; och < 8; ++och){
out[och] = allocate();
if (out[och]) {
memset(out[och]->data, 0, AUDIO_BLOCK_SAMPLES*2);
}
}
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; ++i){
int32_t p = pan->data[i];
if(p < 0){
p = 32768 + p;
}
int a = p >> 12;
int b = (a + 1) % 8;
int32_t p2 = (p % 4096) << 4;
int32_t p1 = (65536 - p2);
if(out[a]){
int32_t val1 = signed_multiply_32x16b(p1, in->data[i]);
out[a]->data[i] = signed_saturate_rshift(val1, 16, 0);
}
if(out[b]){
int32_t val2 = signed_multiply_32x16b(p2, in->data[i]);
out[b]->data[i] = signed_saturate_rshift(val2, 16, 0);
}
}
for(int och = 0; och < 8; ++och){
if(out[och]){
transmit(out[och], och);
release(out[och]);
}
}
release(pan);
}
release(in);
}
}