Time division Multiplexing(TDM) for multilateration(TDOA) using mics from invensense

Status
Not open for further replies.
I'm sad because I thought I had it figured out. I am hoping someone can point out what I'm doing wrong.
this code has 5 mics listening and cycling through five 30 value 1-D arrays until an amplitude threshold is crossed, then it fills a 130 row x 5 column, two dimensional array starting at the 30th row index. Then, when it reaches the 129th row index the algorithm starts filling the first 30 rows in the 2-D array from the stored 1-D arrays.
the whole purpose being so that I can send 130 data points per mic, with historical values prior to the sound triggering event (I'm doing this to keep the sound event in the middle of the data set.)
here's the code:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);


// GUItool: end automatically generated code


int16_t* spot1 ; //I don't know what I'm doing - Greg
int16_t* spot2 ;
int16_t* spot3 ;
int16_t* spot4 ; 
int16_t* spot5 ; 
int16_t* spot6 ;
int16_t* spot7 ;
int16_t* spot8 ;
int16_t* spot9 ; 
int16_t* spot10 ;
int sig1;
int sig2;
int sig3;
int sig4;
int sig5;
int rows=0;
bool sp1 = false;
bool sp3 = false;
bool sp5 = false;
bool sp7 = false;
bool sp9 = false;
bool newl;
bool tripped = false;
bool filling = false;
long thresh=50000;
long lastThresh;
long mic1[100];
long mic2[100];
long mic3[100];
long mic4[100];
long mic5[100];
long sendMics[130][5];
byte ndex=0;
byte sendex=30;
byte row=0;
byte indexWrap;
byte indexTailLength;

void setup() 
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  
  AudioMemory(256);
  queue1.begin();//I thought I should enable 
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();
 
  
}

void loop() 
{

  
  if(queue1.available() > 0)
  {
    spot1=queue1.readBuffer(); 
    queue1.freeBuffer();
    sp1 = true;
  }  
  
  if(queue2.available() > 0)
  {
    spot2=queue2.readBuffer();
    queue2.freeBuffer();
    if (sp1)
      {
        sig1 = spot1[0]*256 + spot2[0]/256;
        if (filling)
        {
          sendMics[sendex][0]=sig1;
        }
        else
        {
          mic1[ndex]=sig1;
        }
        
        sp1=false;
      }
      
      else
      {
        sig1 = 0;
        if (filling)
        {
          sendMics[sendex][0]=sig1;
        }
        else
        {
          mic1[ndex]=sig1;
        }
      }
  }
  

  if(queue3.available() > 0)
  {
    spot3=queue3.readBuffer();
    queue3.freeBuffer();
    sp3 = true;
  }

  if(queue4.available() > 0)
  {
      spot4=queue4.readBuffer();
      queue4.freeBuffer();
      if (sp3)
      {
        sig2 = spot3[0]*256 + spot4[0]/256;
        if (filling)
        {
          sendMics[sendex][1]=sig2;
        }
        else
        {
          mic2[ndex]=sig2;
        }
        
        sp3=false;
      }
      
      else
      {
        sig2 = 0;
        if (filling)
        {
          sendMics[sendex][1]=sig2;
        }
        else
        {
          mic2[ndex]=sig2;
        }
      }  
  }


  if(queue5.available() > 0)
  {
      spot5=queue5.readBuffer();
      queue5.freeBuffer();
      sp5 = true;
  }

  if(queue6.available() > 0)
  {
      spot6=queue6.readBuffer();
      queue6.freeBuffer();
      if (sp5)
      {
        sig3 = spot5[0]*256 + spot6[0]/256;
        if (filling)
        {
          sendMics[sendex][2]=sig3;
        }
        else
        {
          mic3[ndex]=sig3;
        }
        
        sp5=false;
      }
      
      else
      {
        sig3 = 0;
        if (filling)
        {
          sendMics[sendex][2]=sig3;
        }
        else
        {
          mic3[ndex]=sig3;
        }
      }  
  }


  if(queue7.available() > 0)
  {
      spot7=queue7.readBuffer();
      queue7.freeBuffer();
      sp7 = true;
  }

  if(queue8.available() > 0)
  {
      spot8=queue8.readBuffer();
      queue8.freeBuffer();
      if (sp7)
      {
        sig5 = spot7[0]*256 + spot8[0]/256;
        if (filling)
        {
          sendMics[sendex][3]=sig4;
        }
        else
        {
          mic4[ndex]=sig4;
        }
        
        sp7=false;
      }
      
      else
      {
        sig4 = 0;
        if (filling)
        {
          sendMics[sendex][3]=sig4;
        }
        else
        {
          mic4[ndex]=sig4;
        }
      }  
  }


  if(queue9.available() > 0)
  {
      spot9=queue9.readBuffer();
      queue9.freeBuffer();
      sp9 = true;
  }

  if(queue10.available() > 0)
  {
      spot10=queue10.readBuffer();
      queue10.freeBuffer();
      if (sp9)
      {
        sig5 = spot9[0]*256 + spot10[0]/256;
        if (filling)
        {
          sendMics[sendex][4]=sig5;
          sendex++;
        }
        else
        {
          mic5[ndex]=sig5;
          ndex++;
        }
        
        sp9=false;
      }
      
      else
      {
          sig5 = 0;
          if (filling)
          {
            sendMics[sendex][4]=sig5;
            sendex++;
          }
          else
          {
            mic5[ndex]=sig5;
            ndex++;
          }
      }   
  }
  
  
  if(ndex>=30)
  {
    ndex=0;
  }

  
  if (((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)) && !filling)
  {
    tripped = true;
  }
  else
  {
    if (lastThresh>thresh)
    {
      //Serial.println(thresh);
      lastThresh=thresh;
    }
    
  }
  if (tripped)
  {  
      indexWrap = ndex;  //indexWrap is the indice of the oldest value in the "history arrays" (mic1,mic2,...)
      indexTailLength = 29-ndex;  //the remaining number of indices(if any) in the history arrays.
      filling = true;
      tripped = false;
  }
  if (filling)
  {
    if(sendex > 129)
    {
        for (row=0; row <= indexTailLength; row++)
        {
          sendMics[row][0]=mic1[row+indexWrap];
          sendMics[row][1]=mic2[row+indexWrap];
          sendMics[row][2]=mic3[row+indexWrap];
          sendMics[row][3]=mic4[row+indexWrap];
          sendMics[row][4]=mic5[row+indexWrap];
        }
        for (rows = 0; rows <= indexWrap; rows++)
        {
          sendMics[row+indexTailLength+1][0]=mic1[row];
          sendMics[row+indexTailLength+1][1]=mic2[row];
          sendMics[row+indexTailLength+1][2]=mic3[row];
          sendMics[row+indexTailLength+1][3]=mic4[row];
          sendMics[row+indexTailLength+1][4]=mic5[row];
        }
        filling=false;
        sendex=30;
        Serial.printf("indexWrap = %d",indexWrap);
        Serial.println();
        for (row = 0; row < 130; row++)
        {
          Serial.print(row);
          Serial.print(" ");
          for(int columns=0; columns<5; columns++)
          {
            Serial.print(sendMics[row][columns]);
            Serial.print(" ");
            delay(1);
          }
          Serial.println();
        }
    }
  }  

}
It writes a 0 value if the first 16 bit TDM value wasn't read.
the code works but it's buggy, for example, for some reason the first 30 rows are usually always solid zeros but varies (I thought I was very careful about the array indices and the for loop executions, but I must have messed up somewhere.) and it prints a lot of zero values throughout (a sign that my error checking method to show when the first (MSB) half of each mics 24 bit value wasn't available to read when it checked)
I currently only have 3 mics connected as can be seen in my sample serial printout:
Code:
indexWrap = 8
0 -34082 -63356 -49581 0 0 
1 2230 1212 2675 0 0 
2 1057 1330 462 0 0 
3 1024 2051 1138 0 0 
4 1974 710 1145 0 0 
5 -88 1680 638 0 0 
6 -2026 -3696 -1596 0 0 
7 -712 -2100 -1746 0 0 
8 1472 -1816 -2310 0 0 
9 892 91 1310 0 0 
10 -598 80 845 0 0 
11 -1288 656 -387 0 0 
12 565 -312 0 0 0 
13 13440 3142 4902 0 0 
14 1828 746 -106 0 0 
15 4074 14628 12720 0 0 
16 -2832 -1517 -2174 0 0 
17 13022 9090 10765 0 0 
18 -17978 -16561 -9950 0 0 
19 10093 2500 7862 0 0 
20 11608 2704 14318 0 0 
21 -200 -796 -35120 0 0 
22 0 0 0 0 0 
23 0 0 0 0 0 
24 -572 880 -467 0 0 
25 0 0 0 0 0 
26 0 0 0 0 0 
27 0 0 0 0 0 
28 0 0 0 0 0 
29 0 0 0 0 0 
30 43420 46518 35222 0 0 
31 21598 28446 -3318 0 0 
32 -11994 -24322 -7829 0 0 
33 55166 30588 42670 0 0 
34 -24528 -18577 -41796 0 0 
35 6312 4643 -2168 0 0 
36 55228 69576 72960 0 0 
37 -119346 -125024 -121546 0 0 
38 100840 92015 92483 0 0 
39 -30705 -11664 -22622 0 0 
40 4550 -1022 -382 0 0 
41 80306 74720 87645 0 0 
42 -69331 -71316 -71984 0 0 
43 32375 34348 38808 0 0 
44 1828 746 -106 0 0 
45 -59593 -85144 -70809 0 0 
46 28488 22768 41332 0 0 
47 -10981 -10600 -18984 0 0 
48 -1764 -4062 -4362 0 0 
49 40024 73757 39422 0 0 
50 0 -47704 -33858 0 0 
51 -2274 2666 14752 0 0 
52 -5444 4762 -3269 0 0 
53 -13906 -26828 -9174 0 0 
54 -2406 -1208 724 0 0 
55 0 -896 2132 0 0 
56 -128 787 4030 0 0 
57 -17108 -18230 -12654 0 0 
58 13924 11150 8991 0 0 
59 -152963 0 11109 0 0 
60 -22796 -28044 -16508 0 0 
61 37782 38802 39256 0 0 
62 -39577 -35190 -34443 0 0 
63 -84862 -78146 -81607 0 0 
64 0 53862 41406 0 0 
65 758 -804 -56205 0 0 
66 44820 40368 43502 0 0 
67 922 716 1082 0 0 
68 -44768 -47732 -41760 0 0 
69 58002 65256 62279 0 0 
70 -32808 -36787 -40480 0 0 
71 2654 2609 2814 0 0 
72 -6410 -11098 -4670 0 0 
73 -43183 -56990 -57162 0 0 
74 8248 11520 14500 0 0 
75 36450 44829 38552 0 0 
76 -15220 -15742 -14806 0 0 
77 9672 14657 14164 0 0 
78 18718 23504 24096 0 0 
79 -30036 -37970 -34124 0 0 
80 -1727 -2228 0 0 0 
81 15655 12188 14403 0 0 
82 -20182 -24468 -18862 0 0 
83 17165 22922 14048 0 0 
84 -17774 -19147 -13708 0 0 
85 -2279 -9674 0 0 0 
86 11402 21557 12778 0 0 
87 -13547 -19629 -16992 0 0 
88 3724 6884 5944 0 0 
89 -376 617 -672 0 0 
90 0 -5249 -3840 0 0 
91 4688 6312 2948 0 0 
92 -7352 -4829 -6750 0 0 
93 -389 -4434 -971 0 0 
94 2200 2879 3542 0 0 
95 0 -1796 -2174 0 0 
96 -3104 -2744 -2908 0 0 
97 4943 5374 4254 0 0 
98 -1197 -694 -1592 0 0 
99 -2762 2081 1291 0 0 
100 -953 1184 -438 0 0 
101 540 -2368 166 0 0 
102 254 -1169 -188 0 0 
103 1268 1514 1790 0 0 
104 0 -1560 633 0 0 
105 -1588 -1646 -2032 0 0 
106 -3828 -2576 -2463 0 0 
107 -147 -2 -431 0 0 
108 -544 0 2355 0 0 
109 -3082 -3920 -2098 0 0 
110 496 844 17 0 0 
111 -768 932 799 0 0 
112 -1177 -1298 -653 0 0 
113 -878 0 972 0 0 
114 -556 1486 -46 0 0 
115 176 -876 -1267 0 0 
116 2306 3324 2377 0 0 
117 3314 0 1004 0 0 
118 910 190 968 0 0 
119 868 -526 440 0 0 
120 -64 2702 1039 0 0 
121 0 0 0 0 0 
122 4264 3430 1954 0 0 
123 1033 1097 -42 0 0 
124 -202 -501 -512 0 0 
125 285 -434 1110 0 0 
126 -522 0 0 0 0 
127 390 -618 36 0 0 
128 462 799 230 0 0 
129 -412 -1920 -1880 0 0
and this is what that looks like:
TwoMics130Samples.png
I have a couple of suspicions of what is wrong, I think I need to handle the reading of the queue in a better way(any sugestions?), and I think I may have screwed up the transferring of the historical values to the final array being sent.
I know you guys have been generous with help already, but I could really use some more help to figure this out.
 
After a fast look through the code, it seems that ndex/sendex is increased when queue10 has been read without really checking or remembering anything about the states of the other queues. If the queues becomes available when the loop is checking queue5 then you will read queues6 to queue10 and increase the row counters without correctly reading the lower numbered queues, they will be read on the next run through the loop and end up on the wrong row.

So you probably should keep flags for successful reading of the five channels and then update the ndex/sendex only when all channels are read. Or wait until all queues have data available before reading and placing into the array, or if all queues gets available data at the same time (audio loop interrupt) at least wait for queue1 before looking at any of the other queues. Another to possible way could be to simply return from the loop function if there is no data in queue1, this is very easy to test.

Code:
  if(queue1.available() > 0)
  {
    spot1=queue1.readBuffer(); 
    queue1.freeBuffer();
    sp1 = true;
  }  
[B]  else return;[/B]
 
Among the many problems here is use of the buffer after you call freeBuffer().

Code:
    spot2=queue2.readBuffer();
    queue2.freeBuffer();
    if (sp1)
      {
        sig1 = spot1[0]*256 + spot2[0]/256;

This might work sometimes, but it's unreliable. When you call freeBuffer(), the audio library is allowed to use that array again. It could overwrite the array at any moment. You need to copy or otherwise use the data *before* you call freeBuffer().
 
Thank you both so much for pointing out those blunders, I fixed many bugs with those suggestions. I caught another problem with my code along the way, It appears that the variables: rows, row, and columns were already taken by the libraries I am using. I think maybe it would be nice if each variable that is taken in the audio library and others could turn the libraries variables orange to keep a user from using any of them.

I added error checking in case the queue has more than one value (it doesn't anymore, after I added an queues.end() before writing to the arrays), this is what I have now:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);


// GUItool: end automatically generated code


int16_t* spot1 ; //I don't know what I'm doing - Greg
int16_t* spot2 ;
int16_t* spot3 ;
int16_t* spot4 ; 
int16_t* spot5 ; 
int16_t* spot6 ;
int16_t* spot7 ;
int16_t* spot8 ;
int16_t* spot9 ; 
int16_t* spot10 ;
int sig1;
int sig2;
int sig3;
int sig4;
int sig5;
bool sp1 = false;
bool sp2 = false;
bool sp3 = false;
bool sp4 = false;
bool sp5 = false;
bool sp6 = false;
bool sp7 = false;
bool sp8 = false;
bool sp9 = false;
bool sp10 = false;
bool tripped = false;
bool filling = false;
bool historyArrayFull = false;
long thresh=50000;
long lastThresh;
long mic1[30];
long mic2[30];
long mic3[30];
long mic4[30];
long mic5[30];
long sendMics[130][5];
byte ndex=0;
byte sendex=30;
byte i=0;
byte indexWrap;
byte indexTailLength;

void setup() 
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  
  AudioMemory(120);
  queue1.begin();//I thought I should enable 
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();
 
  
}

void loop() 
{

  if(queue1.available() > 1)
  {
    Serial.println("WARNING 1 !!!"); 
  }
  if(queue2.available() > 1)
  {
    Serial.println("WARNING 2 !!!"); 
  }
  if(queue3.available() > 1)
  {
    Serial.println("WARNING 3 !!!"); 
  }
  if(queue4.available() > 1)
  {
    Serial.println("WARNING 4 !!!"); 
  }
  if(queue5.available() > 1)
  {
    Serial.println("WARNING 5 !!!"); 
  }
  if(queue6.available() > 1)
  {
    Serial.println("WARNING 6 !!!"); 
  }
  if(queue7.available() > 1)
  {
    Serial.println("WARNING 7 !!!"); 
  }
  if(queue8.available() > 1)
  {
    Serial.println("WARNING 8 !!!"); 
  }
  if(queue9.available() > 1)
  {
    Serial.println("WARNING 9 !!!"); 
  }
  if(queue10.available() > 1)
  {
    Serial.println("WARNING 10 !!!"); 
  }

  
  if(queue1.available() > 0 && ! sp1)
  {
    spot1=queue1.readBuffer(); 
    sp1 = true;
    //Serial.println("got 1");
  }
  else return;  
  
  if(queue2.available() > 0 && ! sp2)
  {
      spot2=queue2.readBuffer();
      sp2 = true;
      sig1 = spot1[0]*256 + spot2[0]/256;
      //Serial.println("got 2");
      if (filling)
      {
        sendMics[sendex][0]=sig1;
        queue1.freeBuffer();
        queue2.freeBuffer();
      }
      else
      {
        mic1[ndex]=sig1;
        queue1.freeBuffer();
        queue2.freeBuffer();
      }   
  }
  else return;


  if(queue3.available() > 0 && ! sp3)
  {
    spot3=queue3.readBuffer(); 
    sp3 = true;
    //Serial.println("got 3");
  }
  else return;  
  
  if(queue4.available() > 0 && ! sp4)
  {
      spot4=queue4.readBuffer();
      sp4 = true;
      //Serial.println("got 4");
      sig2 = spot3[0]*256 + spot4[0]/256;
      if (filling)
      {
        sendMics[sendex][1]=sig2;
        queue3.freeBuffer();
        queue4.freeBuffer();
      }
      else
      {
        mic2[ndex]=sig2;
        queue3.freeBuffer();
        queue4.freeBuffer();
      }
  }
  else return;
  


  if(queue5.available() > 0 && ! sp5)
  {
    spot5=queue5.readBuffer(); 
    sp5 = true;
    //Serial.println("got 5");
  }
  else return;  
  
  if(queue6.available() > 0 && ! sp6)
  {
      spot6=queue6.readBuffer();
      sp6 = true;
      //Serial.println("got 6");
      sig3 = spot5[0]*256 + spot6[0]/256;
      if (filling)
      {
        sendMics[sendex][2]=sig3;
        queue5.freeBuffer();
        queue6.freeBuffer();
      }
      else
      {
        mic3[ndex]=sig3;
        queue5.freeBuffer();
        queue6.freeBuffer();
      }
  }
  else return;


  if(queue7.available() > 0 && ! sp7)
  {
    spot7=queue7.readBuffer(); 
    sp7 = true;
    //Serial.println("got 7");
  }
  else return;  
  
  if(queue8.available() > 0 && ! sp8)
  {
      spot8 = queue8.readBuffer();
      sp8 = true;
      //Serial.println("got 8");
      sig4 = spot7[0]*256 + spot8[0]/256;
      if (filling)
      {
        sendMics[sendex][3]=sig4;
        queue7.freeBuffer();
        queue8.freeBuffer();
      }
      else
      {
        mic4[ndex]=sig4;
        queue7.freeBuffer();
        queue8.freeBuffer();
      }
  }
  else return;

  
  if(queue9.available() > 0 && ! sp9)
  {
    spot9 = queue9.readBuffer(); 
    sp9 = true;
    //Serial.println("got 9");
  }
  else return;  
  
  if(queue10.available() > 0 && ! sp10)
  {
      spot10 = queue10.readBuffer();
      sp10 = true;
      //Serial.println("got 10");
      sig5 = spot9[0]*256 + spot10[0]/256;
      if (filling)
      {
        sendMics[sendex][4]=sig5;
        queue9.freeBuffer();
        queue10.freeBuffer();
        sendex++;
      }
      else
      {
        mic5[ndex]=sig5;
        queue9.freeBuffer();
        queue10.freeBuffer();
        ndex++;
      }
      sp1 = false;
      sp2 = false;
      sp3 = false;
      sp4 = false;
      sp5 = false;
      sp6 = false;
      sp7 = false;
      sp8 = false;
      sp9 = false;
      sp10 = false;
            
  }
  else return;
  
  if(ndex>=30)
  {
    ndex=0;
    historyArrayFull = true;
  }


  if (!filling && historyArrayFull && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
  {
    tripped = true;
  }
  else
  {
    if (lastThresh>thresh)
    {
      //Serial.println(thresh);
      lastThresh=thresh;
    }
    
  }
  if (tripped)
  {  
      indexWrap = ndex;  //indexWrap is the indice of the oldest value in the "history arrays" (mic1,mic2,...)
      indexTailLength = 29-ndex;  //the remaining number of indices(if any) in the history arrays.
      filling = true;
      tripped = false;
  }
  if (filling)
  {
    //Serial.println("got filling");
    if(sendex > 129)
    {
        queue1.end();//I thought I should disable while it takes it's time filling and printing the final array. 
        queue2.end();
        queue3.end();
        queue4.end();
        queue5.end();
        queue6.end();
        queue7.end();
        queue8.end();
        queue9.end();
        queue10.end();
        //Serial.println("                got sending");
        for (i=0; i <= indexTailLength; i++)
        {
          sendMics[i][0]=mic1[i+indexWrap];
          sendMics[i][1]=mic2[i+indexWrap];
          sendMics[i][2]=mic3[i+indexWrap];
          sendMics[i][3]=mic4[i+indexWrap];
          sendMics[i][4]=mic5[i+indexWrap];
        }
        for (i = 0; i <= indexWrap-1; i++)
        {
          sendMics[i+indexTailLength+1][0]=mic1[i];
          sendMics[i+indexTailLength+1][1]=mic2[i];
          sendMics[i+indexTailLength+1][2]=mic3[i];
          sendMics[i+indexTailLength+1][3]=mic4[i];
          sendMics[i+indexTailLength+1][4]=mic5[i];
        }
        filling=false;
        historyArrayFull = false;
        sendex=30;
//        Serial.printf("indexWrap = %d",indexWrap);//for troubleshooting
//        Serial.println();
        for (i = 0; i < 130; i++)
        {
          Serial.print(i);
          Serial.print(" ");
          for(int j=0; j<5; j++)
          {
            Serial.print(sendMics[i][j]);
            Serial.print(" ");
            delay(1);
          }
          Serial.println();
        }
        queue1.begin(); 
        queue2.begin();
        queue3.begin();
        queue4.begin();
        queue5.begin();
        queue6.begin();
        queue7.begin();
        queue8.begin();
        queue9.begin();
        queue10.begin();
    }
  
  }       

}
Paul, I moved the freeBuffer statements to after where I declared the array positions value. but I want to make sure I understood you correctly when you said copy the values first. (i'm worried that declaring a spot in an array is just pointing to the buffer, not copying it) so, did I fix the queue.freeBuffer() problem?

Now all I have left is a strange problem of: it seems as if the teensy isn't queuing the samples as fast as the mics are sending them, my oscilloscope says the teensy is pulsing the WS pin at 44.1kHz like it should, but when I play a 15kHz audio signal at the mics,
this is what it captures:
3MicsAt1500Hz.jpg
I count roughly 45 periods for 130 samples at 1500Hz which suggests the sampling rate is actually 4333.33 SPS, thats 10 times slower than I need. What is happening? What did I do wrong now?
 
I am not an expert with the audio library, but I would expect the data to arrive in chunks of 128 samples to the queues, because the library processes sound data in 128 sample blocks, and therefore all the queues should be filled with 128 samples each when the audio system interrupt happens.
 
oh, this might be a problem. Is there any way for me to not use a queue, but to just use the tdm_input object directly?
 
Is there any way for me to not use a queue, but to just use the tdm_input object directly?

No, at least not the way it's currently written. Like all the input objects of the audio library, it only delivers data to audio library connections. The connections are meant to pass the data to other objects that actually process the data. The queue objects are the intended why for programs to actually access the audio library's data.

Of course all the source code is available, so you can edit the library if you wish. But it's fundamentally designed to deliver the data in blocks, because that's much more efficient than processing 1 sample at a time. It's the reason a Teensy board can do so much audio processing!
 
No, at least not the way it's currently written. Like all the input objects of the audio library, it only delivers data to audio library connections. The connections are meant to pass the data to other objects that actually process the data. The queue objects are the intended why for programs to actually access the audio library's data.

Of course all the source code is available, so you can edit the library if you wish. But it's fundamentally designed to deliver the data in blocks, because that's much more efficient than processing 1 sample at a time. It's the reason a Teensy board can do so much audio processing!

I think i will try to work with the library then. I think I just need to restructure the way I'm doing this.
...a few hours later...
so this is my attempt:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);


// GUItool: end automatically generated code


int spot1[128]; //I don't know what I'm doing - Greg
int spot2[128];
int spot3[128];
int spot4[128];
int spot5[128];
int spot6[128];
int spot7[128];
int spot8[128];
int spot9[128];
int spot10[128];
long sig1[128];
long sig2[128];
long sig3[128];
long sig4[128];
long sig5[128];
int dex=0;
bool sp1 = false;
bool sp2 = false;
bool sp3 = false;
bool sp4 = false;
bool sp5 = false;
bool sp6 = false;
bool sp7 = false;
bool sp8 = false;
bool sp9 = false;
bool sp10 = false;
bool tripped = false;
long thresh=50000;
byte ndex=0;

void setup() 
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  
  AudioMemory(120);
  queue1.begin();//I thought I should enable 
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();
 
  
}

void loop() 
{

  if(queue1.available() > 0 && ! sp1)
  {
    memcpy(spot1, queue1.readBuffer(), 128);
    sp1 = true;
    //Serial.println("got 1");
  }
  else return;  
  
  if(queue2.available() > 0 && ! sp2)
  {
      memcpy(spot2, queue2.readBuffer(), 128);
      sp2 = true;
      for(dex=0;dex<128;dex++)
      {
        sig1[dex] = spot1[dex]*256 + spot2[dex]/256;
      }
      
      queue1.freeBuffer();
      queue2.freeBuffer();
        
  }
  else return;


  if(queue3.available() > 0 && ! sp3)
  {
    memcpy(spot3, queue3.readBuffer(), 128);
    sp3 = true;
  }
  else return;  
  
  if(queue4.available() > 0 && ! sp4)
  {
      memcpy(spot4, queue4.readBuffer(), 128);
      sp4 = true;
      for(int dex=0;dex<128;dex++)
      {
        sig2[dex] = spot3[dex]*256 + spot4[dex]/256;
      }
      
      queue3.freeBuffer();
      queue4.freeBuffer();
        
  }
  else return;

  if(queue5.available() > 0 && ! sp5)
  {
    memcpy(spot5, queue5.readBuffer(), 128);
    sp5 = true;
  }
  else return;  
  
  if(queue6.available() > 0 && ! sp6)
  {
      memcpy(spot6, queue6.readBuffer(), 128);
      sp6 = true;
      for(int dex=0;dex<128;dex++)
      {
        sig3[dex] = spot5[dex]*256 + spot6[dex]/256;
      }
      
      queue5.freeBuffer();
      queue6.freeBuffer();
        
  }
  else return;

  if(queue7.available() > 0 && ! sp7)
  {
    memcpy(spot7, queue1.readBuffer(), 128);
    sp7 = true;
  }
  else return;  
  
  if(queue8.available() > 0 && ! sp8)
  {
      memcpy(spot8, queue8.readBuffer(), 128);
      sp8 = true;
      for(int dex=0;dex<128;dex++)
      {
        sig4[dex] = spot7[dex]*256 + spot8[dex]/256;
      }
      
      queue7.freeBuffer();
      queue8.freeBuffer();
        
  }
  else return;

  
  if(queue9.available() > 0 && ! sp9)
  {
    memcpy(spot9, queue9.readBuffer(), 128);
    sp9 = true;
  }
  else return;  
  
  if(queue10.available() > 0 && ! sp10)
  {
      memcpy(spot10, queue10.readBuffer(), 128);
      sp10 = true;
      for(int dex=0;dex<128;dex++)
      {
        sig5[dex] = spot9[dex]*256 + spot10[dex]/256;
      }
      
      queue9.freeBuffer();
      queue10.freeBuffer();
       
  }
  else return;

  

  if (sp1 && sp2 && sp3 && sp4 && sp5 && sp6 && sp7 && sp8 && sp9 && sp10)
  {
    queue1.end();//I thought I should disable while it takes it's time filling and printing the final array.  
    queue2.end();
    queue3.end();
    queue4.end();
    queue5.end();
    queue6.end();
    queue7.end();
    queue8.end();
    queue9.end();
    queue10.end();
    for(int i=0; i<128; i++)
    {
      Serial.print(sig1[i]);
      Serial.print(" ");
      Serial.print(sig2[i]);
      Serial.print(" ");
      Serial.print(sig3[i]);
      Serial.print(" ");
      Serial.print(sig4[i]);
      Serial.print(" ");
      Serial.println(sig5[i]);
      delay(1);      
    }
    sp1 = false;
    sp2 = false;
    sp3 = false;
    sp4 = false;
    sp5 = false;
    sp6 = false;
    sp7 = false;
    sp8 = false;
    sp9 = false;
    sp10 = false;
    delay(1000);
    queue1.begin();//I thought I should enable 
    queue2.begin();
    queue3.begin();
    queue4.begin();
    queue5.begin();
    queue6.begin();
    queue7.begin();
    queue8.begin();
    queue9.begin();
    queue10.begin();
  }
         

}
And this is what it produces, of the 128 total rows, the first 32 rows are the only ones I get, and they are much bigger than they should be (24 bit with all bits on is 16777216 but this is a 24 bit signed so at each value's limits it should be -8388608 to 8388607). the first 3 columns are all negative and the fourth is all positive. with the fifth being all 0 (which kind of makes sense). Something funky has happened.
Code:
-182061156 -136709974 -127011162 50298880 0
-209718064 -166463490 -160041243 119295 0
-211815271 -226364796 -152832478 2503168 0
-247598384 -273026608 -139987402 2487552 0
-290983390 -259395724 -169871998 2520575 0
-290066004 -282464488 -176555898 2520320 0
-316675045 -298718033 -204213176 2520320 0
-314315442 -284430838 -254414628 2487552 0
-305141054 -271716758 -246157247 2487808 0
-344331587 -254415118 -271585632 2487808 0
-381163477 -253628730 -283381457 2520575 0
-433461954 -242618584 -264638841 2503168 0
-477371596 -276172688 -275779730 2535680 0
-482745604 -236458384 -244847082 2487552 0
-515645122 -244190937 -217714487 2503168 0
-465313154 -248123188 -242486936 2516479 0
-470032078 -276303698 -251006292 2502912 0
-454302488 -258478276 -248253753 2503168 0
-435035078 -269618956 -227020626 2502912 0
-418782129 -244847002 -246025703 2535935 0
-435559296 -287838390 -244452949 2535935 0
-480517405 -271585396 -283119193 2535935 0
-474618410 -299896795 -325455704 2535680 0
-486153468 -255332482 -339350462 2503168 0
-491002664 -241963342 -318378483 2535935 0
-438705834 -254283134 -357045156 2535935 0
-452992588 -190975708 -355866114 2503168 0
-455089430 -207359230 -322049500 2535680 0
-451550230 -227020342 -288494776 2535680 0
-392043574 -247729908 -287445978 2502912 0
-363862406 -283775037 -267260245 2503168 0
-333715190 -318247586 -257822796 2535935 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
now, what did I do wrong? :(
 
I think you should return to the previous code, just dont free any queue's until you have read 128 entries from the blocks of data that the spot's points to.
memcpy copies bytes, and you have arrays of 32 bit ints and the audiobuffers are 16 bit ints. The memcopy is not needed.

You have a loop, checking for any data in the first queue, when this arrives "queue1.available() > 0" there should be a filled 128 elements audio buffer in every queue.
Now read the buffer addresses for all 10 queues into spot1 .. spot10 and set a counter to 128, that is the number of waiting data in each queue buffer , datacount == -1 will signal that all buffers are freed and all data processed, waiting for more queue data.

Code:
   if ((queue1.available() > 0) &&(datacount == -1)) {
      spot1 = queue1.readBuffer();
      spot2 = queue2.readBuffer();
      spot3 = queue3.readBuffer();
      ...
      datacount = 128;
   };

While the datacount is >0 run through your loop but always read from the next location in the buffer:
Code:
      sig1 = spot1[128-datacount]*256 + spot2[128-datacount]/256;
      sig2 = spot3[128-datacount]*256 + spot4[128-datacount]/256;
      sig3 = spot5[128-datacount]*256 + spot6[128-datacount]/256;
      ...
      if (filling)
      {
          sendMics[sendex][1]=sig1;
          sendMics[sendex][2]=sig2;
          ...
      }
      else
      {
        mic1[ndex]=sig1;
        mic2[ndex]=sig2;
        ...
      }
 
     datacount--;

do not free the buffers until after the whole block of 128 entries has been processed.

When datacount is 0 free all the queue buffers and set datacount to -1, no need to disable/enable the queues.
 
Last edited:
I dont have the hardware to test, but the following code compiles at least, and hopefully the logic is easy to follow:

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);


// GUItool: end automatically generated code


int16_t* spot1 ; //I don't know what I'm doing - Greg
int16_t* spot2 ;
int16_t* spot3 ;
int16_t* spot4 ; 
int16_t* spot5 ; 
int16_t* spot6 ;
int16_t* spot7 ;
int16_t* spot8 ;
int16_t* spot9 ; 
int16_t* spot10 ;
int sig1;
int sig2;
int sig3;
int sig4;
int sig5;
int rows=0;
bool sp1 = false;
bool sp3 = false;
bool sp5 = false;
bool sp7 = false;
bool sp9 = false;
bool newl;
bool tripped = false;
bool filling = false;
long thresh=50000;
long lastThresh;
long mic1[100];
long mic2[100];
long mic3[100];
long mic4[100];
long mic5[100];
long sendMics[130][5];
byte ndex=0;
byte sendex=30;
byte row=0;
byte indexWrap;
byte indexTailLength;
int datacount = -1;

int16_t dummybuffer[128];   /* Holds dummy values if a queuebuffer is not found */

void setup() 
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  
  AudioMemory(256);
  queue1.begin();//I thought I should enable 
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();

  for (int k=0; k<128; k++) dummybuffer[k] = -1; /* dummybuffer in case read from queue fails */
}

void loop() 
{

  if((queue1.available() > 0)&&(datacount == -1)) /* Buffers are empty and queues have new data */
  {
    spot1=queue1.readBuffer(); 
    spot2=queue2.readBuffer(); 
    spot3=queue3.readBuffer(); 
    spot4=queue4.readBuffer(); 
    spot5=queue5.readBuffer(); 
    spot6=queue6.readBuffer(); 
    spot7=queue7.readBuffer(); 
    spot8=queue8.readBuffer(); 
    spot9=queue9.readBuffer(); 
    spot10=queue10.readBuffer(); 

    /* Here we can check that there is actually a block available in every queue, this shouldnt happen but will show up in output data */
    if (spot1==NULL) spot1 = dummybuffer;
    if (spot2==NULL) spot2 = dummybuffer;
    if (spot3==NULL) spot3 = dummybuffer;
    if (spot4==NULL) spot4 = dummybuffer;
    if (spot5==NULL) spot5 = dummybuffer;
    if (spot6==NULL) spot6 = dummybuffer;
    if (spot7==NULL) spot7 = dummybuffer;
    if (spot8==NULL) spot8 = dummybuffer;
    if (spot9==NULL) spot9 = dummybuffer;
    if (spot10==NULL) spot10 = dummybuffer;
    
    datacount = 128;
  }

  if (datacount>0)  /* Data in buffers to process, read next row of samples from buffers */
  {
    sig1 = spot1[128-datacount]*256 + spot2[128-datacount]/256;
    sig2 = spot3[128-datacount]*256 + spot4[128-datacount]/256;
    sig3 = spot5[128-datacount]*256 + spot6[128-datacount]/256;
    sig4 = spot7[128-datacount]*256 + spot8[128-datacount]/256;
    sig5 = spot9[128-datacount]*256 + spot10[128-datacount]/256;
    datacount--;

    if (filling)
    {
      sendMics[sendex][0]=sig1;
      sendMics[sendex][1]=sig2;
      sendMics[sendex][2]=sig3;
      sendMics[sendex][3]=sig4;
      sendMics[sendex][4]=sig5;
    }
    else
    {
      mic1[ndex]=sig1;
      mic2[ndex]=sig2;
      mic3[ndex]=sig3;
      mic3[ndex]=sig3;
      mic3[ndex]=sig3;
    }

  }
  else return;           /* No data has been processed so return */

  if(datacount == 0)     /* Buffers has been fully read, free them */
  {
    queue1.freeBuffer(); 
    queue2.freeBuffer(); 
    queue3.freeBuffer(); 
    queue4.freeBuffer(); 
    queue5.freeBuffer(); 
    queue6.freeBuffer(); 
    queue7.freeBuffer(); 
    queue8.freeBuffer(); 
    queue9.freeBuffer(); 
    queue10.freeBuffer(); 

    datacount = -1;
  }

  /* If we arrive here a new row of samples has been read, now process this row */

  if(ndex>=30)
  {
    ndex=0;
  }

  
  if (((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)) && !filling)
  {
    tripped = true;
  }
  else
  {
    if (lastThresh>thresh)
    {
      //Serial.println(thresh);
      lastThresh=thresh;
    }
    
  }
  if (tripped)
  {  
      indexWrap = ndex;  //indexWrap is the indice of the oldest value in the "history arrays" (mic1,mic2,...)
      indexTailLength = 29-ndex;  //the remaining number of indices(if any) in the history arrays.
      filling = true;
      tripped = false;
  }
  if (filling)
  {
    if(sendex > 129)
    {
        for (row=0; row <= indexTailLength; row++)
        {
          sendMics[row][0]=mic1[row+indexWrap];
          sendMics[row][1]=mic2[row+indexWrap];
          sendMics[row][2]=mic3[row+indexWrap];
          sendMics[row][3]=mic4[row+indexWrap];
          sendMics[row][4]=mic5[row+indexWrap];
        }
        for (rows = 0; rows <= indexWrap; rows++)
        {
          sendMics[row+indexTailLength+1][0]=mic1[row];
          sendMics[row+indexTailLength+1][1]=mic2[row];
          sendMics[row+indexTailLength+1][2]=mic3[row];
          sendMics[row+indexTailLength+1][3]=mic4[row];
          sendMics[row+indexTailLength+1][4]=mic5[row];
        }
        filling=false;
        sendex=30;
        Serial.printf("indexWrap = %d",indexWrap);
        Serial.println();
        for (row = 0; row < 130; row++)
        {
          Serial.print(row);
          Serial.print(" ");
          for(int columns=0; columns<5; columns++)
          {
            Serial.print(sendMics[row][columns]);
            Serial.print(" ");
            delay(1);
          }
          Serial.println();
        }
    }
  }  

}
 
I tried it, there was no output on the serial monitor. I think it might be because the indexes aren't being updated, where would the increments go?
But the reason I think I need to start over with the new understanding of blocks is that they come in fast so if I'm looping and for looping so many times, I think I might be falling behind in the queues. Originally I wanted only 130 samples, but that was dumb, (somewhere I read a theorem that says you need 5 periods for an accurate time delay estimate and I'm interested in human speech, 100Hz to 1000Hz so I think I need 18 queues at most) somehow I need to collect and search the queues without falling behind. How can I do that with my old code?
 
Last edited:
Sorry missed those, they go in the if (filling) block

Code:
    if (filling)
    {
      sendMics[sendex][0]=sig1;
      sendMics[sendex][1]=sig2;
      sendMics[sendex][2]=sig3;
      sendMics[sendex][3]=sig4;
      sendMics[sendex][4]=sig5;
      sendex++;
    }
    else
    {
      mic1[ndex]=sig1;
      mic2[ndex]=sig2;
      mic3[ndex]=sig3;
      mic3[ndex]=sig3;
      mic3[ndex]=sig3;
      ndex++;
    }
 
Sorry I edited my last reply after you responded, I just added the paragraph after the question about the indexes.
I will try adding the increments though.
 
Well at the moment I would suggest you get this code with 129 samples working cleanly, if for no other reason so you understand the mechanics.

Then polish this code to remove as much unnecessary copying as possible, read all 128 samples without exiting the loop, and after that start planning to grab larger samples. My point is that you use your work so far to get
a good grasp of how the TDM audio capture library works.
 
Last edited:
The audio library will keep adding more filled audio buffers to the queues even if they have not been processed, so there is some automatic buffering.
 
Indeed those queues are going to pile up data very quickly. Remember 16 audio streams arriving simultaneously.

When you later get done printing, before you back to looking for incoming data, perhaps call clear() on all the queues to cause them to discard the old data they have collected.
 
okay it works.
this is what the waveform looks like now, with a 1500Hz audio played.
3MicsAt1500Hzcorrected.jpg
there's some garbled portion, which is probably my array sorting mistake, but this is correct for the periods per frame.
I'm excited! I'll see what I can do to polish this for my application. you guys are good, real good. I'll keep everyone posted.
 
#define PRETRIGSAMPLES 30

Code:
        for (row=0; row <PRETRIGSAMPLES; row++)
        {
          int micRow = (row+ndex)%PRETRIGSAMPLES;
          sendMics[row][0]=mic1[micRow];
          sendMics[row][1]=mic2[micRow];
          sendMics[row][2]=mic3[micRow];
          sendMics[row][3]=mic4[micRow];
          sendMics[row][4]=mic5[micRow];
        }
 
#define PRETRIGSAMPLES 30

Code:
        for (row=0; row <PRETRIGSAMPLES; row++)
        {
          int micRow = (row+ndex)%PRETRIGSAMPLES;
          sendMics[row][0]=mic1[micRow];
          sendMics[row][1]=mic2[micRow];
          sendMics[row][2]=mic3[micRow];
          sendMics[row][3]=mic4[micRow];
          sendMics[row][4]=mic5[micRow];
        }

this suggestion didn't work but I am intrigued, the % has always confused me. but I got the code working nicely, here it is for all who care:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);


// GUItool: end automatically generated code


int16_t* spot1 ; //I might know what I'm doing now... a little bit(thanks Paul, mlu, WMXZ and tni) - Greg
int16_t* spot2 ;
int16_t* spot3 ;
int16_t* spot4 ; 
int16_t* spot5 ; 
int16_t* spot6 ;
int16_t* spot7 ;
int16_t* spot8 ;
int16_t* spot9 ; 
int16_t* spot10 ;
int sig1;
int sig2;
int sig3;
int sig4;
int sig5;
bool sp1 = false;
bool sp2 = false;
bool sp3 = false;
bool sp4 = false;
bool sp5 = false;
bool sp6 = false;
bool sp7 = false;
bool sp8 = false;
bool sp9 = false;
bool sp10 = false;
bool tripped = false;
bool filling = false;
bool historyArrayFull = false;
long thresh=50000;
long lastThresh;
long mic1[30];
long mic2[30];
long mic3[30];
long mic4[30];
long mic5[30];
long sendMics[128][5];
byte ndex=0;
byte sendex=30;
byte i=0;
byte indexWrap;
byte indexTailLength;
int datacount = -1;

int16_t dummybuffer[128];   /* Holds dummy values if a queuebuffer is not found */

void setup() 
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  
  AudioMemory(256);
  queue1.begin();//I thought I should enable 
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();

  for (int k=0; k<128; k++) dummybuffer[k] = -1; /* dummybuffer in case read from queue fails */
}

void loop() 
{

  if((queue1.available() > 0)&&(datacount == -1)) /* Buffers are empty and queues have new data */
  {
    spot1=queue1.readBuffer(); 
    spot2=queue2.readBuffer(); 
    spot3=queue3.readBuffer(); 
    spot4=queue4.readBuffer(); 
    spot5=queue5.readBuffer(); 
    spot6=queue6.readBuffer(); 
    spot7=queue7.readBuffer(); 
    spot8=queue8.readBuffer(); 
    spot9=queue9.readBuffer(); 
    spot10=queue10.readBuffer(); 

    /* Here we can check that there is actually a block available in every queue, this shouldnt happen but will show up in output data */
    if (spot1==NULL) spot1 = dummybuffer;
    if (spot2==NULL) spot2 = dummybuffer;
    if (spot3==NULL) spot3 = dummybuffer;
    if (spot4==NULL) spot4 = dummybuffer;
    if (spot5==NULL) spot5 = dummybuffer;
    if (spot6==NULL) spot6 = dummybuffer;
    if (spot7==NULL) spot7 = dummybuffer;
    if (spot8==NULL) spot8 = dummybuffer;
    if (spot9==NULL) spot9 = dummybuffer;
    if (spot10==NULL) spot10 = dummybuffer;
    
    datacount = 128;
  }

  if (datacount>0)  /* Data in buffers to process, read next i of samples from buffers */
  {
    sig1 = spot1[128-datacount]*256 + spot2[128-datacount]/256;
    sig2 = spot3[128-datacount]*256 + spot4[128-datacount]/256;
    sig3 = spot5[128-datacount]*256 + spot6[128-datacount]/256;
    sig4 = spot7[128-datacount]*256 + spot8[128-datacount]/256;
    sig5 = spot9[128-datacount]*256 + spot10[128-datacount]/256;
    datacount--;

    if (filling)
    {
      sendMics[sendex][0]=sig1;
      sendMics[sendex][1]=sig2;
      sendMics[sendex][2]=sig3;
      sendMics[sendex][3]=sig4;
      sendMics[sendex][4]=sig5;
      sendex++;
    }
    else
    {
      mic1[ndex]=sig1;
      mic2[ndex]=sig2;
      mic3[ndex]=sig3;
      mic4[ndex]=sig4;
      mic5[ndex]=sig5;
      ndex++;
    }

  }
  else return;           /* No data has been processed so return */

  if(datacount == 0)     /* Buffers has been fully read, free them */
  {
    queue1.freeBuffer(); 
    queue2.freeBuffer(); 
    queue3.freeBuffer(); 
    queue4.freeBuffer(); 
    queue5.freeBuffer(); 
    queue6.freeBuffer(); 
    queue7.freeBuffer(); 
    queue8.freeBuffer(); 
    queue9.freeBuffer(); 
    queue10.freeBuffer(); 

    datacount = -1;
  }

  /* If we arrive here a new row of samples has been read, now process this row */

  if(ndex>=30)
  {
    ndex=0;
  }

  
  if (((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)) && !filling)
  {
    tripped = true;
  }
  else
  {
    if (lastThresh>thresh)
    {
      //Serial.println(thresh);
      lastThresh=thresh;
    }
    
  }
  if (tripped)
  {  
      indexWrap = ndex;  //indexWrap is the indice of the oldest value in the "history arrays" (mic1,mic2,...)
      indexTailLength = 29-ndex;  //the remaining number of indices(if any) in the history arrays.
      filling = true;
      tripped = false;
  }
  if (filling)
  {
    if(sendex > 127)
    {
        queue1.end();//I thought I should disable while it takes it's time filling and printing the final array.  
        queue2.end();
        queue3.end();
        queue4.end();
        queue5.end();
        queue6.end();
        queue7.end();
        queue8.end();
        queue9.end();
        queue10.end();
        for (i=0; i <= indexTailLength; i++)
        {
          sendMics[i][0]=mic1[i+indexWrap];
          sendMics[i][1]=mic2[i+indexWrap];
          sendMics[i][2]=mic3[i+indexWrap];
          sendMics[i][3]=mic4[i+indexWrap];
          sendMics[i][4]=mic5[i+indexWrap];
        }
        for (i = 0; i <= indexWrap-1; i++)
        {
          sendMics[i+indexTailLength+1][0]=mic1[i];
          sendMics[i+indexTailLength+1][1]=mic2[i];
          sendMics[i+indexTailLength+1][2]=mic3[i];
          sendMics[i+indexTailLength+1][3]=mic4[i];
          sendMics[i+indexTailLength+1][4]=mic5[i];
        }
        filling=false;
        sendex=30;
        Serial.printf("indexWrap = %d",indexWrap);
        Serial.println();
        for (i = 0; i < 128; i++)
        {
          Serial.print(i);
          Serial.print(" ");
          for(int j=0; j<5; j++)
          {
            Serial.print(sendMics[i][j]);
            Serial.print(" ");
            delay(1);
          }
          Serial.println();
        }
        queue1.begin();//I thought I should enable 
        queue2.begin();
        queue3.begin();
        queue4.begin();
        queue5.begin();
        queue6.begin();
        queue7.begin();
        queue8.begin();
        queue9.begin();
        queue10.begin();
    }
  }  

}
and here are two examples of nice sinusoids at 1500Hz.
1500Hzfirst.jpg
1500HzSecond.jpg
Thank you so much guys! I think I can do something with this now. But now I'm seriously considering processing the time shift using the Teensy, instead of the Raspberry pi (even though I already have some python code waiting to process samples (FYI these pictures are from where the mics are sitting on my desk spaced less than 30 cm apart, I'm going to try and space them 60cm apart.)

as a bonus here is the matlab code I wrote to simulate the possibility of interpolating between samples by using a spline fit, it turns out you can at least interpolate 208 times between points:

Code:
%MATLAB CODE (not C++)

decay=0.005;  %how fast the chirp decays this has an effect on accuracy of time delay(fit all of the wave in the window)
shift=-0.00035479;%simulated time shift
w=2*pi;      %normalization period
a=3.3;       %amplitude of first wave
b=2.8;       %amplitude of second wave
t=-.04:0.000021:.04;%range and 1/sampling frequency
phase=0;     %initial phase
f0=200;      %starting lower frequency
f1=3000;     %final upper frequency
T=.05;       %time to sweep frequency
k=(f1/f0)^(1/T);
snr=65;%signal to noise ratio in dBA



s1=a*sin(phase+((f0*w*((k).^(t)-1))/log(k))).*exp(-((t)/decay).^2);
s1n=awgn(s1,snr);
s2=b*sin(phase+((f0*w*((k).^(t+shift)-1))/log(k))).*exp(-((t+shift)/decay).^2);
s2n=awgn(s2,snr);
format long

figure
plot(t,s2n,'o',t,s1n,'o')
hold on
% [r,lag]=xcorr(s1n,s2n);%the time shift if only using sample rate for discrete shifting
% [~,I] = max(abs(r));
% lagDiff = lag(I)
% timeDiff = lagDiff/48000.0

time =-.04:0.00000001:.04;%may have to get creative with finding the bounds for the final application
p1 = interp1(t,s1n,time,'spline');%linear interpolation will never be better than original sampling speed
p2 = interp1(t,s2n,time,'spline');
plot(time,p1,time,p2)
hold off
[r2,lag2] = xcorr(p1,p2);%time shift after interpolation
[~,I2] = max(abs(r2));
lagDiff2 = lag2(I2);
timeDiff2 = lagDiff2/100000000
I was seeing if I could get a better time shift resolution(where I have, Dt +- dt, and I wanted a smaller dt) this simulation worked and I was able to meet my benchmark requirements it calculates the shift in .10 seconds and i get a dt of 0.0000001 and occasionally better. but it may require some tricky signal processing tricks. I'm just wondering if there is a way if I can write a spline fitting function with the Teensy, then over sample that fit and with the over sampled points do a cross correlation? or as someone once told me, I should do the cross correlation and then find the maximum of the correlation after spine fitting and over sampling the cross correlation.
Anyway, thank you so much for the help you guys have given me. this has been by far my best forum experience.
 
Last edited:
If the interpolation is a linear function of the measured values you can do any interpolation after the cross correlation with same results, try to simply fit a quadratic to the maximum of the cross correlation and the two surrounding points. The maximum of this quadratic polynomial is very easy to find.

Btw, did you replace both the copying of the front and the back of the history array with the code suggested ?
 
Btw, did you replace both the copying of the front and the back of the history array with the code suggested ?
I tried it but it the waveform ended up garbled in the history array portion, I even tried replacing the variable row with i(the audio library is using that variable and it affects it) and it still didn't work so I edited your last major edit (with the free buffers at a later point) and that worked.
 
Have you tried something simple, like just routing the TDM signals to a DAC output object, and listening to that with an amplified computer speaker?

I mean, if you haven't done that sort of simple test using only the known-good audio library objects, how do you know you're getting meaningful data at all?
 
Well, the waveforms look good, and have a period of 1500Hz like what I was playing with a signal generator. But that is a good point. What example should I use?
 
Status
Not open for further replies.
Back
Top