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)
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.
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.