Hi folks,
With an overabundance of sudden free time, I'm now working on this again. For those catching up I have started with the generic 4 in, 1 out mixer and tried to add a second channel to it.
Here's the my current definition in the .h file:
Code:
class AudioMixer4x2 : public AudioStream
{
#if defined(__ARM_ARCH_7EM__)
public:
AudioMixer4x2(void) : AudioStream(4, inputQueueArray) {
for (int i=0; i<4; i++) {
multiplier0[i] = 65536;
multiplier1[i] = 65536;
}
}
virtual void update(void);
void gain(unsigned int output, unsigned int channel, float gain) {
if ((output < 0)||(output > 1)) return;
if (channel >= 4) return;
if (gain > 32767.0f) gain = 32767.0f;
else if (gain < -32767.0f) gain = -32767.0f;
if (output == 0) multiplier0[channel] = gain * 65536.0f; // TODO: proper roundoff?
if (output == 1) multiplier1[channel] = gain * 65536.0f; // TODO: proper roundoff?
}
private:
int32_t multiplier0[4];
int32_t multiplier1[4];
audio_block_t *inputQueueArray[4];
#elif defined(KINETISL)
public:
AudioMixer4x2(void) : AudioStream(4, inputQueueArray) {
for (int i=0; i<4; i++) {
multiplier0[i] = 256;
multiplier1[i] = 256;
}
}
virtual void update(void);
void gain(unsigned int output, unsigned int channel, float gain) {
if (output < 0)||(output > 1) return;
if (channel >= 4) return;
if (gain > 127.0f) gain = 127.0f;
else if (gain < -127.0f) gain = -127.0f;
if (output == 0) multiplier0[channel] = gain * 256.0f; // TODO: proper roundoff?
if (output == 1) multiplier1[channel] = gain * 256.0f; // TODO: proper roundoff?
}
private:
int32_t multiplier0[4];
int32_t multiplier1[4];
audio_block_t *inputQueueArray[4];
#endif
};
And here's the update function from .cpp:
Code:
void AudioMixer4x2::update(void)
{
// audio_block_t *in, *intemp=NULL, *out1=NULL, *out2=NULL;
audio_block_t *in, *out0=NULL, *out1=NULL;
unsigned int channel;
int32_t mult;
for (channel=0; channel < 4; channel++) {
in = receiveReadOnly(channel);
if (!out0) {
out0 = in;
if (out0) {
mult = multiplier0[channel];
if (mult != MULTI_UNITYGAIN) applyGain(out0->data, mult);
}
} else {
if (in){
applyGainThenAdd(out0->data, in->data, multiplier0[channel]);
}
}
if (!out1) {
out1 = in;
if (out1) {
mult = multiplier1[channel];
if (mult != MULTI_UNITYGAIN) applyGain(out1->data, mult);
}
} else {
if (in){
applyGainThenAdd(out1->data, in->data, multiplier1[channel]);
}
}
release(in);
}
if (out0) {
transmit(out0);
release(out0);
}
if (out1) {
transmit(out1);
release(out1);
}
}
Does it work? No! But...sort of.
Right now my test is just a simple USB in object and the output goes through I2S to the headphone jack on an audio shield. I have a .WAV file I'm playing back of me saying "left" on the left channel, and "right" on the right channel. If I connect USB in directly to I2S out, it works fine. If I connect through two regular mixer objects, it also works fine.
However, if I connect through my fancy new things are a bit more complicated. For the moment I have not tried adjusting any levels, just in case my gain() function is broken. When I play back my audio file, I do hear it, so that's a start. But the audio has crackles in it. Not once in a while, fairly constantly. Almost like clipping. Both left and right are heard out of output 0, and output 1 doesn't have any audio coming out. Level-wise it's about the same as without the mixer object, so I don't think I've accidentally cranked things up enough to clip.
I'm going to keep plugging away at it, but if anyone has any suggestions on what I've messed up I'm all ears!