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"
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);
		
	}

}
...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
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!