OK, I've got it all working now. Turned out my original code was accidentally overwriting the header, which presumably prevented the AudioPlayMemory object from recognizing the array as legitimate.
In case it's useful to anyone else, here's a quick (and inelegant) sketch which populates an array with a simple calculated sinewave, then plays it through the speaker three times:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioPlayMemory playMem1; //xy=682.6666870117188,276.00000500679016
AudioOutputI2S audioOutput; //xy=1079.6666870117188,362.00000500679016
AudioConnection patchCord1(playMem1, 0, audioOutput, 0);
AudioControlSGTL5000 audioShield; //xy=913.6666870117188,232.00000500679016
// GUItool: end automatically generated code
const int TX_array_len_samples = 128 * 100 * 3;
const int TX_array_len_words = TX_array_len_samples / 2;
int TX_array[TX_array_len_words + 1];
void setup() {
AudioMemory(10);
delay(2000);
audioShield.enable();
audioShield.volume(0.5);
populate_tx_array(1000.0, 5000.0);
// print_tx_array();
// print_tuba_array();
for (int i = 0; i < 3; i++) {
playMem1.play(TX_array);
while (playMem1.isPlaying()) {};
delay(500);
}
}
void loop() {
}
uint16_t make_unsigned_16_bit_sample(float t) {
// First make the signal as a signed int:
int sample_a = (cos( 2 * PI * 1000.0 * t) / 2.5 ) * 65535;
// Convert to unsigned int type, with same contents:
unsigned int result = 0;
if (sample_a >= 0) {
result = sample_a;
} else {
result = (-sample_a + 1);
result = ~result + 1;
}
return result;
}
void populate_tx_array(float start_freq, float stop_freq) {
TX_array[0] = 0x81 << 24 | (TX_array_len_samples); //0x81 = 44100 Hz, 16 bit uncompressed PCM
for (int i = 1; i < TX_array_len_words ; i++) {
float t_a = (2.0 * i + 0) / 44100.0; // time in seconds
float t_b = (2.0 * i + 1) / 44100.0; // time in seconds
uint16_t sample_a = make_unsigned_16_bit_sample(t_a);
uint16_t sample_b = make_unsigned_16_bit_sample(t_b );
TX_array[ i] = (sample_b << 16) | (sample_a ); // two samples per array entry.
}
}
void print_tx_array() {
Serial.print("The array has length: ");
Serial.print(TX_array_len_words);
Serial.println(" words");
for (int i = 0; i < TX_array_len_words ; i++) {
int16_t sample_a = (int16_t)(TX_array[i] & 65535);
int16_t sample_b = (int16_t)(TX_array[i] >> 16);
Serial.print(sample_a);
Serial.print("\t\t");
Serial.println(sample_b);
}
delay(5000);
}
I should probably mention that If you actually need a waveform, this isn't the way you should do it, and the built in audio library objects are the way to go.
The reason I'm using it in this case is that I'm preparing an array upfront for transmitting, then recording the received waveform to another array. Once I have both arrays populated I can do cross-correlation on them and figure out sonar type depth scan info.