Working Audio output queue example

Status
Not open for further replies.

GremlinWrangler

Well-known member
While trying to rough out some functionality around using the audio queue output object had a fair bit of trouble getting a basic example to work.

For anybody else looking at generating audio from code without going into the audio library itself to make a custom object and wanting a place to start

WARNING this produces a test waveform where the DAC is referencing various code values and will sound horrible and be possibly damaging connected to a speaker, it is intended to be plugged into a scope to see what the various values are doing

Specifically it sets pin 13 high to sync the scope, then loads 30 blocks of memory with 128 values each with a high start pulse, then a negative counter marker, then a positive memory used marker (at the time data was written, not outputed) and a positive, max memory allocated marker (40)


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

// GUItool: begin automatically generated code
//AudioInputAnalog         adc1;           //xy=189,311
//AudioRecordQueue         queue2;         //xy=319,326
AudioPlayQueue           queueOut;         //xy=352,226
AudioOutputAnalog        dac1;           //xy=494,223
//AudioConnection          patchCord1(adc1, queue2);
AudioConnection          patchCord2(queueOut, dac1);
// GUItool: end automatically generated code

int16_t buffer[128];
elapsedMicros usec = 0;
uint32_t tempval =0;
uint32_t loopcount =0;


void setup() {
    AudioMemory(40);
    pinMode(13,OUTPUT);
    dac1.analogReference(EXTERNAL); //3.3V p-p vs default 1.2
  Serial.begin(9600);

}

void updateBuffer()
{
  int16_t memoryused AudioMemoryUsage();
    for (int i=0;i<128;i++) {
      int16_t  cellvalue=0;
      if (i>4&&i<12) cellvalue = 32767;
      if (i>32&&i<64) cellvalue = -32767+loopcount*256*3;
      if (i>64&&i<96) cellvalue = memoryused*256*3;
       if (i>96&&i<128) cellvalue = 40*256*3;
       buffer[i]=cellvalue;
    }
     int16_t *p = queueOut.getBuffer();
      memcpy(p, buffer, 128);
      queueOut.playBuffer();
}

void loop() {
//  if (loopcount<20||(loopcount<30&&usec>5*2900)){ //writing while playing test
    if (loopcount<30){
      digitalWrite(13,HIGH);
      updateBuffer();
      loopcount++;      
      digitalWrite(13,LOW);    
  }
  if (usec>35*2900+1000&&AudioMemoryUsage()<2) {
      loopcount=0;
      usec=0;
      Serial.println(AudioMemoryUsageMax());
  }   
}

At time of writing (Aug 2017) the behavior observed was that you load multiple blocks in, and they are then played back in order, and you can add more in FIFO during playback (see commented line) but not overwrite them, each block needs a playbuffer call. The only way I could find to check if queue is still playing (aka needed topping up) was to monitor memory usage, hence why the last if in the loop checks both elapsed time and free memory before adding data again.

Unsure with the memcpy line if it should be 128 or 256 (number of bytes or number of int16s), both seem to work which isn't what I expected.
 
Status
Not open for further replies.
Back
Top