Userblock data array in AudioPLayQueue and AudioRecordQueue difference?

Status
Not open for further replies.
Hi everyone, I want to used AudioPlayQueue and play the sound from AudioRecordQueue. When looking to the .cpp file, I found the different userblock queue size, I have an question to ask that will this different make the block transmission mismatch? and how much memory is enough in case I want to transfer 128 samples captured by AudioRecordQueue to AudioPLayQueue ? Sorry for the full code policy as I have no idea to start yet.


Code:
int16_t * AudioRecordQueue::readBuffer(void)
{
	uint32_t t;

	if (userblock) return NULL;
	t = tail;
	if (t == head) return NULL;
	if (++t >= 53) t = 0;
	userblock = queue[t];
	tail = t;
	return userblock->data;
}

Code:
void AudioPlayQueue::playBuffer(void)
{
	uint32_t h;

	if (!userblock) return;
	h = head + 1;
	if (h >= 32) h = 0;
	while (tail == h) ; // wait until space in the queue
	queue[h] = userblock;
	head = h;
	userblock = NULL;
}
 
Last edited:
This is the full program I wrote and I cant hear anything. Look like there is somthing wrong with playQueue. However, I tried directly sent to i2s1 from SDWav and heard my song playing.

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


// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=100,103
AudioRecordQueue         queue1;         //xy=269,118
AudioPlayQueue           queue2;         //xy=406,127
AudioOutputI2S           i2s1;           //xy=585,135
AudioConnection          patchCord1(queue2, 0, i2s1, 0);
AudioConnection          patchCord2(playSdWav1, 0, queue1, 0);

AudioControlSGTL5000     sgtl5000_1;     //xy=105,226
// GUItool: end automatically generated code

// GUItool: end automatically generated code


int filenumber = 0;  // while file to play
const char * filelist[4] = {"SDTEST1.WAV", "SDTEST2.WAV", "SDTEST3.WAV", "SDTEST4.WAV"};

// Void setup

void setup() {
  Serial.begin(9600);
  AudioMemory(90);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  delay(20);
  queue1.begin();
 
}
// End setup


void loop() {


  if (playSdWav1.isPlaying() == false) {
    const char *filename = filelist[filenumber];
    filenumber = filenumber + 1;
    if (filenumber >= 4) filenumber = 0;
    playSdWav1.play(filename);
     Serial.print("Start playing ");
    Serial.println(filename);
    delay(10); // wait for library to parse WAV info
  }

if (queue1.available() >= 1) {
    int aa = queue1.available();
    Serial.print(aa);
    //byte buffer[512];
    // Fetch 2 blocks from the audio library and copy
    // into a 512 byte buffer.  The Arduino SD library
    // is most efficient when full 512 byte sector size
    // writes are used.
    *queue2.getBuffer()=*queue1.readBuffer();
    queue1.freeBuffer();
    queue2.playBuffer();
   elapsedMicros usec = 0;
     Serial.print("SD write, us=");
    Serial.println(usec);
 
}

}
 
Last edited:
I believe this line may be the problem.

Code:
*queue2.getBuffer()=*queue1.readBuffer();

My guess is you probably meant for this to copy 128 samples, but it only copies the first sample. The other 127 aren't copied. You need to use a loop or call memcpy().

It's also a good practice to check queue2.getBuffer() returns NULL, since you only checked queue1.available().
 
I believe this line may be the problem.

Code:
*queue2.getBuffer()=*queue1.readBuffer();

My guess is you probably meant for this to copy 128 samples, but it only copies the first sample. The other 127 aren't copied. You need to use a loop or call memcpy().

It's also a good practice to check queue2.getBuffer() returns NULL, since you only checked queue1.available().


I tried this:

queue1.end();
memcpy(queue3.getBuffer(), queue1.readBuffer(), 128);
queue1.freeBuffer();
queue3.playBuffer();

I get a playback that sounds like just a few bytes.
 
Audio samples are each 2 bytes so a buffer is 256 bytes, not 128.
Why are you calling queue1.end() ?

Pete
 
Audio samples are each 2 bytes so a buffer is 256 bytes, not 128.
Why are you calling queue1.end() ?

Pete

because I want to stop recording the buffer before I play it back... like a delay.. kind of.
I'm learning how the buffers work.
I tried 256, 512, even 1024 lol.

current experiment is two buffers. while one plays, the other records, getting ready for playback
 
Last edited:
No, I meant that the memcpy must copy 256 bytes per buffer. 128 is wrong. You are only copying half the samples.
Code:
memcpy(queue3.getBuffer(), queue1.readBuffer(), 256);

Pete
 
No, I meant that the memcpy must copy 256 bytes per buffer. 128 is wrong. You are only copying half the samples.
Code:
memcpy(queue3.getBuffer(), queue1.readBuffer(), 256);

Pete

I tried 256, 512, even 1024. they all sound like a couple milliseconds chirp

from now on, I'll keep it as 256
 
Still not working! Sounds like "click...click...click"
And I KNOW that click/chirp is coming from a recorded sound.
Because if I don't input sound to line-in, there is no click.
And high-pitch sounds make a chirp.


if ( activeQueue == 1 ) {


Serial.println(1);

memcpy(queue3.getBuffer(), queue1.readBuffer(), 256);
queue1.freeBuffer();
queue3.playBuffer();

activeQueue = 2;

} else if ( activeQueue == 2 ) {

Serial.println(2);

memcpy(queue3.getBuffer(), queue2.readBuffer(), 256);
queue2.freeBuffer();
queue3.playBuffer();

activeQueue = 1;

}
 
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S i2s1; //xy=66.19999694824219,79
AudioRecordQueue queue1; //xy=180.2000274658203,261
AudioRecordQueue queue2; //xy=183.2000274658203,304
AudioPlayQueue queue3; //xy=315.20001220703125,260.20001220703125
AudioMixer4 mixer2; //xy=465.2000274658203,154
AudioOutputI2S i2s2; //xy=524.2000389099121,53
AudioConnection patchCord1(i2s1, 0, mixer2, 0);
AudioConnection patchCord2(i2s1, 0, queue1, 0);
AudioConnection patchCord3(i2s1, 0, queue2, 0);
AudioConnection patchCord4(queue3, 0, mixer2, 1);
AudioConnection patchCord6(mixer2, 0, i2s2, 0);
AudioConnection patchCord7(mixer2, 0, i2s2, 1);
AudioControlSGTL5000 audioShield; //xy=198.1999969482422,512
// GUItool: end automatically generated code


const int myInput = AUDIO_INPUT_LINEIN;


byte activeQueue = 1;

void setup() {
// put your setup code here, to run once:

Serial.begin(9600);
Serial.println("begin");

mixer2.gain(0, 0.5);
mixer2.gain(1, 0.5);

AudioMemory(600);
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);

queue1.begin();
queue2.begin();

}


unsigned long startTime = millis();


void loop() {

//the one second loop counter
if ( (millis()-startTime)>1000 ) {
startTime = millis();

if ( activeQueue == 1 ) {


Serial.println(1);

memcpy(queue3.getBuffer(), queue1.readBuffer(), 256);
queue1.freeBuffer();
queue3.playBuffer();


queue1.clear();

activeQueue = 2;
} else if ( activeQueue == 2 ) {

Serial.println(2);

memcpy(queue3.getBuffer(), queue2.readBuffer(), 256);
queue2.freeBuffer();
queue3.playBuffer();

queue2.clear();

activeQueue = 1;
}

}






}
 
What you are doing makes no sense in several ways.
First, you are reading a buffer from queue1 and queue2 when you don't know that one is ready. You should be testing queue1.available() (and the same for queue2) before copying from there to the output. All you will be doing is copying garbage to the output.
Second, however, it makes no sense to split the input from i2s1 into two separate queues and try some sort of double buffering. When you clear the queues, you have no idea how many buffers you are throwing away.

current experiment is two buffers. while one plays, the other records, getting ready for playback
That's not the way to do it. A Teensy is plenty fast enough to record and play buffers without double buffering provided that you make correct use of queue1.available() and the other functions available for handling queues.

Code:
AudioMemory(600);
You really don't need 600 buffers!

Pete
 
OK HERE IS A SIMPLIFIED VERSION.
Still doesn't playback the buffer.

Is this maybe a problem with the Teensy 3.6?


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S i2s1; //xy=64.19999694824219,32.19999694824219
AudioRecordQueue queue1; //xy=96.19999694824219,109.19999694824219
AudioPlayQueue queue2; //xy=222.20001220703125,128.1999969482422
AudioMixer4 mixer1; //xy=368.2000274658203,64.19999694824219
AudioOutputI2S i2s2; //xy=528.1999969482422,62.19999694824219
AudioConnection patchCord1(i2s1, 0, mixer1, 0);
AudioConnection patchCord2(i2s1, 0, queue1, 0);
AudioConnection patchCord3(queue2, 0, mixer1, 1);
AudioConnection patchCord4(mixer1, 0, i2s2, 0);
AudioControlSGTL5000 audioShield; //xy=195.1999969482422,302.1999969482422
// GUItool: end automatically generated code


const int myInput = AUDIO_INPUT_LINEIN;
bool playbackStarted = false;




void setup() {
// put your setup code here, to run once:

Serial.begin(9600);
Serial.println("begin");

mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);

AudioMemory(60);

audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);

queue1.begin();


}


unsigned long startTime = millis();


void loop() {

//the one second loop counter

if ( (millis() - startTime) > 1000 ) {
startTime = millis();

if ( playbackStarted == false ) {
if ( queue1.available() >= 2 ) {
Serial.println("buffer playback");
memcpy(queue2.getBuffer(), queue1.readBuffer(), 256);
queue1.freeBuffer();
queue2.playBuffer();
playbackStarted = true;
}

}


}

}
 
There's nothing wrong with the T3.6. I tried your code and it does exactly what you told it to do.
It plays the input from i2s1 into the mixer and from there directly to the output. At the same time, it delays for one second, copies one audio buffer from queue1 to queue2 (which then outputs it to the mixer) and then it stops reading queue1 altogether.
So, ignoring the one buffer from queue1, all this does is play audio from i2s1 directly through the mixer to the output at i2s2.

What are you trying to do?

Pete
 
There's nothing wrong with the T3.6. I tried your code and it does exactly what you told it to do.
It plays the input from i2s1 into the mixer and from there directly to the output. At the same time, it delays for one second, copies one audio buffer from queue1 to queue2 (which then outputs it to the mixer) and then it stops reading queue1 altogether.
So, ignoring the one buffer from queue1, all this does is play audio from i2s1 directly through the mixer to the output at i2s2.

What are you trying to do?

Pete

THANKS FOR YOUR HELP....

I think I have a defective Teensy.
UPS drover over my package.... the Audio shield was smashed, but the Teensy passed visual inspection.

What I'm trying to do: balance buffers for various processing.

I've been banging my head against the wall with half the examples pjrc provided with the Teensy library!
 
Have you gone through the Teensy Audio Tutorial- it uses just a couple buttons and pots but give a run through of most of the system with fully tested sketches and instructions and a video. This will confirm your hardware to work as indicated.
 
Have you gone through the Teensy Audio Tutorial- it uses just a couple buttons and pots but give a run through of most of the system with fully tested sketches and instructions and a video. This will confirm your hardware to work as indicated.

yes.
I'm not new to arduino and teensy.
I'm new to the audio library.
 
Status
Not open for further replies.
Back
Top