Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: TDM Matrix mixer

  1. #1
    Senior Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    183

    TDM Matrix mixer

    I'm writing a TDM 8x8 matrix mixer.

    The basic pattern is

    Click image for larger version. 

Name:	mixer pattern.jpg 
Views:	24 
Size:	34.4 KB 
ID:	24012

    All goes well up to 4 replications of the Mixer 1-2-3 pattern. Any higher number (I've tested 5, 6 & 8), produces an output (green trace) like this:

    Click image for larger version. 

Name:	6 mixers.png 
Views:	14 
Size:	16.9 KB 
ID:	24013

    Here's the code:
    Code:
    /*
     * 8 channels TDM into matrix of 8 x 2 4-channel mixers
     * Down mix to 8 single output channels to TDM outs
     */
     
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    
    #define MIXRS 5
    #define CHANS 8
    #define ABLOX 36
    
    AudioMixer4           Amixer[MIXRS][2];     // pairs of 4 input Amixers, summed by a Bmixer
    AudioMixer4           Bmixer[MIXRS];        // mix down pairs of Amixers 
    AudioConnection     * Apatch[MIXRS][CHANS]; // TDM to Amixers
    AudioConnection     * Bpatch[MIXRS][2];     // Amixers to Bmixers
    AudioConnection     * Cpatch[MIXRS];        // Bmixers to outputs. Insert tone/FX here.
    AudioInputTDM         TDM_in;       
    AudioOutputTDM        TDM_out;       
    AudioControlCS42448   cs42448_1;      
    
    AudioAnalyzePeak peak1, peak2;
    AudioConnection p1(TDM_in, 0, peak1, 0); 
    AudioConnection p2(Bmixer[0], 0, peak2, 0); 
      
    void setup() {
      // put your setup code here, to run once:
      AudioMemory(ABLOX);
      Serial.begin(115200);
      delay(1000);
      Serial.println("Starting T4 TDM multi mixer test");
      
      for(int i = 0; i < MIXRS; i++)
      {
        for(int j = 0; j < CHANS; j++)
        {
          // set up TDM to A mixer patches - only every second TDM in/out is used
          if(j < CHANS/2)
          {
            Apatch[i][j] = new AudioConnection(TDM_in, i*2, Amixer[i][0], i);
            Amixer[i][0].gain(j, 1.0); // unity gain for the mixer channel
          }
          else // second half TDM go to the other Amixer in the pair
          {
            Apatch[i][j] = new AudioConnection(TDM_in, i*2, Amixer[i][1], i - CHANS/2);
            Amixer[i][1].gain(j, 1.0); // unity gain for the mixer channel
          }     
        }
        // pacth Amixers to Bmixers
        Bpatch[i][0] = new AudioConnection(Amixer[i][0], 0, Bmixer[i], 0);  
        Bpatch[i][1] = new AudioConnection(Amixer[i][1], 0, Bmixer[i], 1); 
        Bmixer[i].gain(0, 1.0); // unity gain for the mixer channel 
        Bmixer[i].gain(1, 1.0); 
        // Bmixers to TDM outputs
        Cpatch[i]    = new AudioConnection(Bmixer[i], 0, TDM_out, i*2);  
      }
      Serial.println("Done setup");
    }
    uint32_t loops;
    
    void loop() {
      float Again = 1.0;
      int procUse = AudioProcessorUsageMax();
      AudioProcessorUsageMaxReset();
      int memUse = AudioMemoryUsage();
      float peakA = peak1.read();
      float peakB =  peak2.read();
      Again = (float)random(200, 1000) / 1000.0;    // gain 0.2 .. 1.0
      Amixer[0][0].gain(0, Again); // vary gain for mixer channel 0
    
      Serial.printf("%i: proc %i, mem %i, gain %3.2f, peak1 %3.2f, peak2 %3.2f\n",loops, procUse, memUse, Again, peakA, peakB);
     
      delay(5000);
      loops++;
    }
    Output is as follows, so I'm not running out of CPU or AudioMemory.
    ...
    137: proc 1, mem 21, gain 0.43, peak1 0.54, peak2 0.25
    138: proc 1, mem 21, gain 0.81, peak1 0.54, peak2 0.23
    139: proc 1, mem 10, gain 0.77, peak1 0.54, peak2 0.44
    ...

  2. #2

  3. #3
    Senior Member
    Join Date
    Jul 2020
    Posts
    966
    You should create objects and connections in the correct order - otherwise you'll get strange behaviour and
    unwanted latencies. Specifically here you should create TDM_in, then 2 mixers and the first peak, connect them,
    then add the final mixer and peak, connect them, then create TDM_out and connect it. All the signal processing
    that's interrupt-driven currently goes in the order objects are created, irrespective of the dataflow, so you need
    to follow these rules if you code the audio signal graph yourself.
    (the Audio design tool specifically manages this for you - I'd run it and copy/paste/renumber the results for
    multiply banks for instance)

    Whenever you see missing audio blocks like this (they are 2.9ms long), in a cyclic fashion, its a strong indicator
    the blocks are being handled in the wrong order, which can produce hidden latencies, or audible artifacts. It
    can also, of course, be due to inadequate number of blocks being initialized in AudioMemory, or processor load.

    Here the first object you create, one of the mixers, is getting audio blocks left over from the last time, not from TDM_in,
    since TDM_in doesn't exist when that mixer is created. As you added more copies of your graph the pattern of use changed
    and its the fourth one that triggered the gross error - careful investigation should show that it was already misbehaving.

  4. #4
    Senior Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    183
    Thanks - both of you.

    Mark - the app is actually an 8x8 matrix mixer - so I'll take the creation order from the Audio Tool, as you suggest, and build it into the code that generates the mixer objects and connections.

    Manicksan - I searched the forum for "matrix" mixer rather than "crosspoint" - so thanks for the link. It's pretty much exactly what I want and has the benefit of one less processing stage (though if I follow Mark's advice it shouldn't cost me anything in added latency). I'll have a go at making the number of inputs/outputs an argument for the constructor, to reduce processing time and resource use.

    Richard

  5. #5
    Junior Member
    Join Date
    Apr 2020
    Posts
    6
    That looks quite exciting! I wanna do something similiar with teensy. May I ask what kind of hardware you use for getting 8 inputs and outputs?

    EDIT: Ah you combine this https://oshpark.com/shared_projects/2Yj6rFaW with the regular teensy audio board?

    How is it with bit debth? can you use the 24bit of the tdm board still?
    Last edited by Blindsmyth; 03-18-2021 at 05:32 PM.

  6. #6
    Senior Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    183
    Hi,

    I use a variant of Paul's CS42448 board - see https://forum.pjrc.com/threads/58836...ed-performance it provides 8x8 with a CS5341 ADC for the extra two input channels, it also provides balanced ins and outs, raising the noise floor (potentially) by 6dB and CMRR by substantially more. Electrolytics isolate the inputs and outputs, to avoid the frequency dependent capacitance of large MLCCs. I'll be happy to share the Gerbers once it's fully tested (see above).

    Paul's new 8x8 (6+2 x 8) board is at https://hackaday.io/project/2984-tee...-for-teensy-4x and https://oshpark.com/profiles/PaulStoffregen

    My main use for Teensy audio is live performance (I have 16 channels of 24 bit/96kHz pro gear for recording), so I haven't played with changing bit depth or sample rate as 44.1kHz/16 bits works just fine for this use.

    While you can use 24 bit mode, you would need to split them across two 16 streams, as each of the 16 TDM object's ins and outs are 16 bit.

    I agree with Paul's logic of why it's not worth the effort https://www.pjrc.com/teensy/td_libs_AudioRoadmap.html, though there have been several streams of discussion around 24 bit and 48kHz operation. I haven't followed them in any detail.

    BTW, if you're going to try 24 bit - you could use the 16 x 16 matrix mixer that manicksan notes, ganging two channels together (above).

  7. #7
    Junior Member
    Join Date
    Apr 2020
    Posts
    6
    Quote Originally Posted by palmerr View Post
    Hi,

    I use a variant of Paul's CS42448 board - see https://forum.pjrc.com/threads/58836...ed-performance it provides 8x8 with a CS5341 ADC for the extra two input channels, it also provides balanced ins and outs, raising the noise floor (potentially) by 6dB and CMRR by substantially more. Electrolytics isolate the inputs and outputs, to avoid the frequency dependent capacitance of large MLCCs. I'll be happy to share the Gerbers once it's fully tested (see above).
    Thanks for your answer! That looks very promising! I have no experience in soldering these smd chips with many pins. So I would need to find someone that can do the job, but I'd be happy to get the gerber files and try my luck.

    Quote Originally Posted by palmerr View Post

    My main use for Teensy audio is live performance (I have 16 channels of 24 bit/96kHz pro gear for recording), so I haven't played with changing bit depth or sample rate as 44.1kHz/16 bits works just fine for this use.

    While you can use 24 bit mode, you would need to split them across two 16 streams, as each of the 16 TDM object's ins and outs are 16 bit.

    BTW, if you're going to try 24 bit - you could use the 16 x 16 matrix mixer that manicksan notes, ganging two channels together (above).
    Allright. My Idea with this would be connecting my live Instruments and DIY gear (a couple of axoloti boards) with my pro gear (RME UCX) via ADAT, and be able to route several inputs to several (axoloti) fx devices. So 24bit would be a huge bonus, allthough I wouldn't mind starting with 16bit.

    May I ask what you are using this setup for more specifically? Just out of curiosity...

  8. #8
    Senior Member
    Join Date
    Aug 2016
    Location
    Australia
    Posts
    183
    Sure,

    Live monitor matrix mixing, quite like the venerable Aviom setups in concept, other than the audio is not (yet) routed over the network cables, instead delivered via spare multicore channels (for now), as I haven't yet managed to get low latency/high reliability WiFi audio delivery working as well as I'd like.

    I'll get back to that, and improving my UDP/IP transport layer for Teensy Audio at some point!

    8 inputs from main desk channel inserts or sends, matrix mixed to 8 line outputs for personal/stage monitors, all using Teensy Audio. Control is via a serial link from one of a set of ESP32 touch screen controllers. User selects channel with touch button, encoder knob controls fader levels. Red and white buttons are channel on and PFL. Cycle through the different output mixes using the encoder press switch.
    Click image for larger version. 

Name:	proto.jpg 
Views:	16 
Size:	115.8 KB 
ID:	24115
    Each player has a personal monitor, and as many controllers are spread around as makes sense - as any controller can manage any (all) of the mixes (or just the one for that player).

  9. #9
    Junior Member
    Join Date
    Apr 2020
    Posts
    6
    Wow that looks impressive! Thanks for sharing. Let me know when your pcb is ready to be shared

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •