I believe I found the bug. It's memory leaks.
I just pushed a fix to github. Please give it a try and let me know how this works for you?
https://github.com/PaulStoffregen/Audio
// +++++++++++++++++++++ libraries +++++++++++++++++++++ //
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
// +++++++++++++++++++++ audio components +++++++++++++++++++++ //
// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
//
AudioPlaySdWav im_vo;
AudioPlaySdWav im_servo;
AudioMixer4 mainMix;
AudioOutputI2S headphones;
// Create Audio connections between the components
//
AudioConnection c1(im_vo, 0, mainMix, 0);
AudioConnection c2(im_servo, 0, mainMix, 1);
AudioConnection c3(mainMix, 0, headphones, 0);
AudioConnection c4(mainMix, 1, headphones, 0);
AudioConnection c5(mainMix, 0, headphones, 1);
AudioConnection c6(mainMix, 1, headphones, 1);
// Create an object to control the audio shield.
//
AudioControlSGTL5000 audioShield;
// +++++++++++++++++++++ variables +++++++++++++++++++++ //
char* wavToPlay;
char* servoToPlay;
char* voxToPlay;
boolean VOState;
boolean servoState;
int whatToPlay[2];
int serialIn;
byte whatToPlayIndx = 0;
void setup() {
// +++++++++++++++++++++ init serial ports +++++++++++++++++++++ //
Serial.begin(921600); // USB
Serial1.begin(115200); // incoming from gatekeeper micro
// +++++++++++++++++++++ audio setup +++++++++++++++++++++ //
// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(5);
float mixVol = 0.50;
mainMix.gain(0, mixVol); // vox
mainMix.gain(1, mixVol); // servo
audioShield.enable();
audioShield.volume(100); // <<<<< set volume here
// +++++++++++++++++++++ SD card inits +++++++++++++++++++++ //
SPI.setMOSI(7);
SPI.setSCK(14);
wavToPlay = "00000vIM.WAV"; // start up sound
if (SD.begin(10)) {
delay(1000); // so there's no pop at the beginning (not sure this works)
im_vo.play(wavToPlay); // init sound
}
}
void loop() {
// +++++++++++++++++++++ service USB for messages +++++++++++++++++++++ //
while (Serial.available() > 0) {
// mail call
serialIn = Serial.parseInt();
whatToPlay[whatToPlayIndx] = serialIn;
Serial.print(whatToPlay[whatToPlayIndx]);
Serial.write(10);
whatToPlayIndx++;
if (Serial.read() == '\n') { // end of message
servoState = im_servo.isPlaying();
if (servoState == 0) {
playServoSound();
}
VOState = im_vo.isPlaying();
if (VOState == 0) {
playVOXSound();
}
whatToPlayIndx = 0;
}
} // end USB check
} // end main loop
void playServoSound()
{
if (whatToPlay[0] == 0) return;
Serial.print("play Servo");
Serial.write(10);
if (whatToPlay[0] == 21) servoToPlay = "00173vIM.WAV";
Serial.print(servoToPlay);
Serial.write(10);
im_servo.play(servoToPlay);
Serial.print("playing servo");
Serial.write(10);
} // end playServoSound
void playVOXSound()
{
if (whatToPlay[1] == 0) return;
Serial.print("play VOX");
Serial.write(10);
if (whatToPlay[1] == 21) voxToPlay = "01234vIM.WAV";
Serial.print(voxToPlay);
Serial.write(10);
im_vo.play(voxToPlay);
Serial.print("playing VOX");
Serial.write(10);
} // end playVOXsound
Hi Rich,
That's really interesting. I'd be interested in seeing your code. Can you attach a zip of it here?
Pete
I know this is old (was on page 7 or this thread), but I'm actually seeing the same problems with the latest & greatest. Seems to lock up the board after playing a sound sample several times. Not sure when it's going to fail, but it does always fail.
Have you tried printing the memory consumption at regular intervals, or at least after each time playing?
If it really is a memory leak, you'll see the memory consumption grow until all 5 buffers are permanently used up.
@Rich:
I think your scaling needs to shift down by 15. When you multiply two signed 16-bit numbers (i.e. 1.15 format) the result is a 2.30 number - i.e. the top two bits of the 32-bit number will be the same and will both be the sign bit. If you shift this down by only 13 bits, you haven't shifted either of the top two sign bits down to the sign bit in the lower 16-bits. At least, that's what I think happens. I will have to play with it sometime.
Pete
case TONE_TYPE_SINE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// The value of ramp_up is always initialized to RAMP_LENGTH and then is
// decremented each time through here until it reaches zero.
// The value of ramp_up is used to generate a Q15 fraction which varies
// from [0 - 1), and multiplies this by the current sample
if(ramp_up) {
// ramp up to the new magnitude
// ramp_mag is the Q15 representation of the fraction
// Since ramp_up can't be zero, this cannot generate +1
ramp_mag = ((ramp_length-ramp_up)<<15)/ramp_length;
ramp_up--;
// adjust tone_phase to Q15 format and then adjust the result
// of the multiplication
// calculate the sample
tmp_amp = (short)((arm_sin_q15(tone_phase>>16) * tone_amp) >> 15);
*bp++ = (tmp_amp * ramp_mag)>>15;
}
else if(ramp_down) {
// ramp down to zero from the last magnitude
// The value of ramp_down is always initialized to RAMP_LENGTH and then is
// decremented each time through here until it reaches zero.
// The value of ramp_down is used to generate a Q15 fraction which varies
// from [0 - 1), and multiplies this by the current sample
// avoid RAMP_LENGTH/RAMP_LENGTH because Q15 format
// cannot represent +1
ramp_mag = ((ramp_down - 1)<<15)/ramp_length;
ramp_down--;
// adjust tone_phase to Q15 format and then adjust the result
// of the multiplication
tmp_amp = (short)((arm_sin_q15(tone_phase>>16) * last_tone_amp) >> 15);
*bp++ = (tmp_amp * ramp_mag)>>15;
} else {
// adjust tone_phase to Q15 format and then adjust the result
// of the multiplication
tmp_amp = (short)((arm_sin_q15(tone_phase>>16) * tone_amp) >> 15);
*bp++ = tmp_amp;
}
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
// If tone_phase has overflowed, truncate the top bit
if(tone_phase & 0x80000000)tone_phase &= 0x7fffffff;
}
break;
AudioConnection c3(toneHigh, 0, mult, 0);
AudioConnection c3a(toneLow, 0, mult, 1);
AudioConnection c13(mult, 0, recorder, 0);
.
.
.
toneLow.begin(1.0,1000,TONE_TYPE_SINE);
toneHigh.begin(0.99,vfo,TONE_TYPE_SINE);
SureI also recorded the two tones separately and they are both full scale waves so whatever is going on is after AudioSynthWaveform.
Is it OK if I send you a private message?
Pete
The datasheet says that mode 0 or mode 3 will work with the flash. My driver for the flash sets the SPI mode and I've tried both and the PlayFromSdWav sketch clobbers them both.
Pete