Audio Play queue help

Status
Not open for further replies.

ahinduja

Member
Hi all,

I am still trying to perform simple one way acoustic ranging through the audio library but keep having inconsistencies in the elapsed timing even after increasing the sampling rate. The idea I am pursuing is to see if I can record the sounds and post process the recording to detect the tone and derive the elapsed time through that.
I am working with two teensy 4's, one with a mic and the other with a speaker. What I am trying to do is have a sequential tone being played from the teensy+speaker which also triggers a pin (triggered using the bounce library) connected to the teensy+mic to direct it to start recording sound. I want to record a short duration (~150ms) into a record queue and then transfer that to a play queue to do a tone detection. I am trying to see if i can accurately detect which packet(and possibly sample) in the queue crosses the threshold for the tone detection, and if I can do that I can deduce the timing, possibly.
I am a bit unclear on how to transfer the data from the record queue to the play queue, and how much can the play queue hold on to. Here is a snippet of my code:

Code:
void back_end()
{
  queue_r.begin(); 
  while (1)
  {
   if(queue_r.available()>=50 )
   { queue_r.end(); 
    byte buffer[12800]; 
    for(int i =0; i<50; i++)
    {
      memcpy(buffer+i*256, queue_r.readBuffer(),256); 
      queue_r.freeBuffer(); 
     }
     int16_t *outbuf = queue_p.getBuffer();
     memcpy(outbuf, buffer, 12800); 
     
  }
}
}

I think this is wrong because the getBuffer() function can only do a 128 int16 array at a time. But it is not clear to me if the play queue works similar to the record queue and I can keep iterating through the buffer to fill in the play queue. Any hints are appreciated! Below is what the Audio GUI tool documentation says about the record queue.

Up to 52 packets may be queued by this object, which allows approximately 150 ms of audio to be held in the queue
 
Made some changes to my code and pasting the complete one here. I think I would need to use the playBuffer() in the play queue taking in each 128 16 bit array at a time. I am calling two functions in the loop based on the trigger from the other teensy. The first one (back_end()) records data in a queue of 50 packets and transfers that to a buffer. The second function (queue_tone_detect()) then iterates through this buffer, passing it on to the play queue which should make data available to the tone detection. However for some reason the queue detection loop does not go beyond the 1st packet in the buffer and gives a constant reading in the tone analysis, which means there is something amiss.

Code:
/*
  SD -> pin 8 (in1)/pin 5 (in2)
  L/R -> GND/VCC (left/right channel)
  WS -> pin 20 (LRCLK1)/pin 3 (LRCLK2)
  SCK -> pin21 (BCLK1)/pin 4 (BCLK2)
*/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <TimeLib.h>
#include "TeensyThreads.h"
#include <Bounce.h>
#include <utility/imxrt_hw.h>


#define TRIGGER 18
byte previousState = LOW;
// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=587.0023994445801,440.0024223327637
AudioRecordQueue         queue_r;         //xy=947.002326965332,411.31007289886475
AudioPlayQueue           queue_p;
AudioAnalyzeToneDetect   tone1;
AudioConnection          patchCord1(i2s1, 0, queue_r, 0);
AudioConnection          pathCord2(queue_p, tone1); 
// GUItool: end automatically generated code


double trigger_time;
double ping_time;
const double air_speed = 0.0343;
elapsedMicros t1;
byte buffer[12800];
Bounce bounce1 = Bounce(TRIGGER, 5);
void setup() {
  //Serial.begin(9600);
  AudioMemory(120);
  while (!Serial) ; // wait until Arduino Serial Monitor opens
  tone1.frequency(8000, 5);
  IntervalTimer listenTimer;
  pinMode(TRIGGER, INPUT);
//  setI2SFreq(176400);
  delay(3000);
  Serial.println("setup done");
}


//void back_end()
//{
//  queue_r.begin(); 
//  while (1)
//  {
//   if(queue_r.available()>=50 )
//   { queue_r.end(); 
//    byte buffer[12800]; 
//    for(int i =0; i<50; i++)
//    {
//      memcpy(buffer+i*256, queue_r.readBuffer(),256); 
//      queue_r.freeBuffer(); 
//     }
//     int16_t *outbuf = queue_p.getBuffer();
//     memcpy(outbuf, buffer, 12800); 
//      
//  }
//}
//}



void back_end()
{
  queue_r.begin(); 
  while (1)
  {
   if(queue_r.available()>=50 )
   { queue_r.end(); 
//    byte buffer[12800]; 
    for(int i =0; i<50; i++)
    {
      memcpy(buffer+i*256, queue_r.readBuffer(),256); 
      queue_r.freeBuffer(); 
     } 
      queue_r.clear();  
  break;   
  }
 
}
}

void queue_tone_det()
{
  for (int i = 0; i<50; i++)
  {
     int16_t *outbuf = queue_p.getBuffer();
     memcpy(outbuf, buffer+i*256, 256); // how to dicretize this as buffer is of size 12800 but getBuffer() only takes in 128 int_16 array at a time (256 mem)
     queue_p.playBuffer();  //by doing this an audio packet should be available to the tone detection
     if(tone1.available())
     {Serial.println(i);
      Serial.println(tone1.read()*10);
      //check if packet contents cross the threshold. 
      //do stuff
     }
  }

  
}


//elapsedMillis fps; //for loop speed controll. Any lower and the inconstencies increase.
void loop()
{
  bounce1.update();
  if (bounce1.risingEdge())
  {
  back_end();
  delay(300);  
  queue_tone_det();
  }
}
   

   
  
  

}

The output I get right now is as follows
Code:
setup done

0

0.62

0

0.62

0

0.62

0

0.62

Which is not what I'd expect. I thought I would see the 50 packets and some of the earlier ones would be crossing the tone detection threshold. I don't see any obvious errors. Any insights will be much appreciated.
 
Actually realized that by placing a small delay, I could get the output as expected. Also clearing the pointer helped. Sharing the code if anybody else find's it useful.

Code:
/*
  SD -> pin 8 (in1)/pin 5 (in2)
  L/R -> GND/VCC (left/right channel)
  WS -> pin 20 (LRCLK1)/pin 3 (LRCLK2)
  SCK -> pin21 (BCLK1)/pin 4 (BCLK2)
*/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <TimeLib.h>
#include "TeensyThreads.h"
#include <Bounce.h>
#include <utility/imxrt_hw.h>


#define TRIGGER 18
byte previousState = LOW;
// GUItool: begin automatically generated code
AudioInputI2S            i2s1;           //xy=587.0023994445801,440.0024223327637
AudioRecordQueue         queue_r;         //xy=947.002326965332,411.31007289886475
AudioPlayQueue           queue_p;
AudioAnalyzeToneDetect   tone1;
AudioAnalyzeRMS          rms1; 
AudioConnection          patchCord1(i2s1, 0, queue_r, 0);
AudioConnection          pathCord2(queue_p, tone1); 
// GUItool: end automatically generated code


double trigger_time;
double ping_time;
const double air_speed = 0.0343;
elapsedMicros t1;
byte buffer_1[12800];
Bounce bounce1 = Bounce(TRIGGER, 5);
void setup() {
  //Serial.begin(9600);
  AudioMemory(120);
  while (!Serial) ; // wait until Arduino Serial Monitor opens
  tone1.frequency(8000, 5);
  IntervalTimer listenTimer;
  pinMode(TRIGGER, INPUT);
//  setI2SFreq(176400);
  delay(3000);
  Serial.println("setup done");
}


//void back_end()
//{
//  queue_r.begin(); 
//  while (1)
//  {
//   if(queue_r.available()>=50 )
//   { queue_r.end(); 
//    byte buffer[12800]; 
//    for(int i =0; i<50; i++)
//    {
//      memcpy(buffer+i*256, queue_r.readBuffer(),256); 
//      queue_r.freeBuffer(); 
//     }
//     int16_t *outbuf = queue_p.getBuffer();
//     memcpy(outbuf, buffer, 12800); 
//      
//  }
//}
//}



void back_end()
{
  queue_r.begin(); 
  while (1)
  {
   if(queue_r.available()>=50 )
   { queue_r.end(); 
//    byte buffer_1[12800]; 
    for(int i =0; i<50; i++)
    {
      memcpy(buffer_1+i*256, queue_r.readBuffer(),256); 
      queue_r.freeBuffer(); 
     } 
      queue_r.clear();  
  break;   
  }
 
}
}

void queue_tone_det()
{
  for (int i = 0; i<50; i++)
  {
     int16_t *outbuf = queue_p.getBuffer();
     memcpy(outbuf, buffer_1+i*256, 256); // how to dicretize this as buffer is of size 12800 but getBuffer() only takes in 128 int_16 array at a time (256 mem)
     queue_p.playBuffer();  //by doing this an audio packet should be available to the tone detection
     delay(30); 
     if(tone1.available())
     {Serial.println(i);
      Serial.println(tone1.read()*10);
      //check if packet contents cross the threshold. 
      //do stuff
      outbuf = nullptr; 
     }
  }
// buffer = NULL; 
  
}


//elapsedMillis fps; //for loop speed controll. Any lower and the inconstencies increase.
void loop()
{
  bounce1.update();
  if (bounce1.risingEdge())
  {
  back_end();
  delay(300);  
  queue_tone_det();
  }
}
 
Status
Not open for further replies.
Back
Top