Hello,
I would like to create a matrix mixer with X out and X inputs. Using the mixer4 for this is possible but will be very complicated.
The code I have so far is not working properly.
"matrix_mixer.cpp"
"matrix_mixer.h"
Arduino code
This is a 4x4 matrix test using the normal mixer code.
This only outputs the first channel BUT if I change the update in the cpp file to this...
...I can change the active output with "out_sel" and get the intend output on whichever out I want. But the others are silent. So my other code with the multiplier array works.
This must have something to do with my misunderstanding of how the whole receive and release thing works but when I tried to first read all the inputs or put them in a 2d array so each of the 16 individual mixers in this 4x4 array had it's own reading to start with I'd have all kind of issues with freezing and crazy memory reporting.
Here's an example of one thing I've tried that did not work
Thanks!
I would like to create a matrix mixer with X out and X inputs. Using the mixer4 for this is possible but will be very complicated.
The code I have so far is not working properly.
"matrix_mixer.cpp"
Code:
//matrix_mixer.cpp
#include <Arduino.h>
#include "matrix_mixer.h"
#include "utility/dspinst.h"
#define MULTI_UNITYGAIN 65536
static void MMapplyGain(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 MMapplyGainThenAdd(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);
}
}
void AudioMatrixMixer::update(void)
{
audio_block_t *in, *out = NULL;
unsigned int channel;
byte out_sel = 0;
byte started = 0;
for (out_sel = 0; out_sel < 4; out_sel++) {
started = 0;
for (channel = 0; channel < 4; channel++) {
if (started == 1) {
in = receiveReadOnly(channel);
if (in) {
MMapplyGainThenAdd(out->data, in->data, multiplier[out_sel][channel]);
release(in);
}
}
if (started == 0) {
out = receiveWritable(channel);
if (out) {
int32_t mult = multiplier[out_sel][channel];
if (mult != MULTI_UNITYGAIN) MMapplyGain(out->data, mult);
started = 1;
}
}
}
if (out) {
transmit(out, out_sel);
release(out);
}
}
}
"matrix_mixer.h"
Code:
// matrix_mixer.h
#ifndef matrix_mixer_h_
#define matrix_mixer_h_
#include "Arduino.h"
#include "AudioStream.h"
class AudioMatrixMixer : public AudioStream
{
public:
AudioMatrixMixer(void) : AudioStream(4, inputQueueArray) {
/* for (int j = 0; j < 4; j++) {
for (int i = 0; i < 4; i++) {
multiplier[j][i] = 65536;
}*/
}
virtual void update(void);
void gain(unsigned int out_sel, unsigned int channel, float gain) {
if (channel >= 4) return;
if (out_sel >= 4) return;
if (gain > 32767.0f) gain = 32767.0f;
else if (gain < -32767.0f) gain = -32767.0f;
multiplier[out_sel][channel] = gain * 65536.0f; // TODO: proper roundoff?
}
private:
int32_t multiplier[4][4];
audio_block_t *inputQueueArray[4];
};
#endif
Arduino code
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioMatrixMixer mm1;
AudioSynthWaveform wf1, wf2, wf3, wf4;
AudioOutputI2S i2sout;
AudioConnection patchCord1(wf1, 0, mm1, 0);
AudioConnection patchCord2(wf2, 0, mm1, 1);
AudioConnection patchCord3(wf3, 0, mm1, 2);
AudioConnection patchCord5(mm1, 0, i2sout, 1);
AudioConnection patchCord6(mm1, 1, i2sout, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=854,187
// GUItool: end automatically generated code
uint32_t cm, prev[4], dm, cu, pu;
float r1, f1, f2;
void setup() {
AudioNoInterrupts();
AudioMemory(90);
sgtl5000_1.enable();
sgtl5000_1.volume(0.75);
wf1.begin(1, 100 , WAVEFORM_SINE );
wf2.begin(1, 200 , WAVEFORM_SINE );
wf3.begin(1, 300 , WAVEFORM_SINE );
wf4.begin(1, 400 , WAVEFORM_SINE);
mm1.gain(0, 0, .2);
mm1.gain(0, 1, .5);
mm1.gain(0, 2, .4);
mm1.gain(0, 3, 0);
mm1.gain(1, 0, .3);
mm1.gain(1, 1, .3);
mm1.gain(1, 2, 0);
mm1.gain(1, 3, 0);
analogReadResolution(12);
analogReadAveraging(64);
AudioInterrupts();
}
void loop() {
cm = millis();
if (cm - prev[2] > 250) {
prev[2] = cm;
Serial.print(AudioProcessorUsageMax());
Serial.print(" ");
Serial.println(AudioMemoryUsageMax());
Serial.println();
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}
}
This is a 4x4 matrix test using the normal mixer code.
This only outputs the first channel BUT if I change the update in the cpp file to this...
Code:
void AudioMatrixMixer::update(void)
{
audio_block_t *in, *out = NULL;
unsigned int channel;
byte out_sel = 1;
byte started = 0;
started = 0;
for (channel = 0; channel < 4; channel++) {
if (started == 1) {
in = receiveReadOnly(channel);
if (in) {
MMapplyGainThenAdd(out->data, in->data, multiplier[out_sel][channel]);
release(in);
}
}
if (started == 0) {
out = receiveWritable(channel);
if (out) {
int32_t mult = multiplier[out_sel][channel];
if (mult != MULTI_UNITYGAIN) MMapplyGain(out->data, mult);
started = 1;
}
}
}
if (out) {
transmit(out, out_sel);
release(out);
}
}
This must have something to do with my misunderstanding of how the whole receive and release thing works but when I tried to first read all the inputs or put them in a 2d array so each of the 16 individual mixers in this 4x4 array had it's own reading to start with I'd have all kind of issues with freezing and crazy memory reporting.
Here's an example of one thing I've tried that did not work
Code:
void AudioMatrixMixer::update(void)
{
const byte printo = 0;
audio_block_t *in = NULL, *out = NULL;
audio_block_t *mmin[4], *mmo[4];
if (printo == 1) {Serial.println(" - ");}
for (byte jj = 0; jj < 4; jj++) {
mmin[jj] = NULL;
mmo[jj] = NULL;
}
//for (byte out_sel = 0; out_sel < 4; out_sel++) {}
for (byte jj = 0; jj < 4; jj++) {
mmin[jj] = receiveWritable(jj);
//mmo[jj] = mmin[jj];
}
////////////////
byte started = 0;
byte out_sel = 0;
for (byte channel = 0; channel < 4; channel++) {
if (mmin[channel]) {
if (started == 1) {
MMapplyGainThenAdd(mmo[out_sel]->data, mmin[channel]->data, multiplier[out_sel][channel]);
}
if (started == 0) {
mmo[out_sel] = mmin[channel];
int32_t mult = multiplier[out_sel][channel];
if (mult != MULTI_UNITYGAIN) MMapplyGain(mmo[out_sel]->data, mult);
started = 1;
}
}
}
for (byte hh = 0; hh < 4; hh++) {
if (mmo[hh]) {
transmit(mmo[hh], hh);
release(mmo[hh]);
}
if (mmin[hh]) {
release(mmin[hh]);
}
}
}
Thanks!