Audio shield sampler 2 channel playback/recording problem

Status
Not open for further replies.
I'm currently building a two-buffer audio sampler using a Teensy 3.1 and the audio shield. Messy code below...I recognize that it's very poorly constructed!

My design uses four buttons, two for each buffer. Each buffer has a play/stop button, and a record button.

The current problem is very specific, but I can't figure out a solution. Essentially: if I'm holding the "play" button on one channel, and press the "record" button on the other channel, then everything stops and I have to restart the Teensy.

A few other clues:
- Recording into both buffers simultaneously works fine
- Playing both buffers simultaneously works fine
- Holding the play button and then pressing the record button on the same buffer works fine
- If I look at the files on a computer after an error, the file from the buffer where I pressed record is a zero byte file. e.g. if I was holding "play2" and pressed "record1" then the record1.raw file is zero bytes, while the record2.raw file is still intact

Any ideas? Many thanks!

-yann




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

// GUItool: begin automatically generated code
AudioPlaySdRaw           playRaw2;       //xy=189,349
AudioPlaySdRaw           playRaw1;       //xy=190,295
AudioInputI2S            i2s1;           //xy=226,112
AudioSynthWaveformSine   sine1;          //xy=261,453
AudioMixer4              mixer1;         //xy=395,309
AudioRecordQueue         queue2;         //xy=450,219
AudioRecordQueue         queue1;         //xy=453,89
AudioFilterStateVariable filter1;        //xy=461,421
AudioOutputI2S           i2s2;           //xy=609,428
AudioConnection          patchCord1(playRaw2, 0, mixer1, 1);
AudioConnection          patchCord2(playRaw1, 0, mixer1, 0);
AudioConnection          patchCord3(i2s1, 0, queue2, 0);
AudioConnection          patchCord4(i2s1, 0, queue1, 0);
AudioConnection          patchCord5(sine1, 0, filter1, 1);
AudioConnection          patchCord6(mixer1, 0, filter1, 0);
AudioConnection          patchCord7(filter1, 0, i2s2, 0);
AudioConnection          patchCord8(filter1, 0, i2s2, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=281,607
// GUItool: end automatically generated code



const int numReadings = 20;

int readings[numReadings];      // the readings from the analog input
int avgindex = 0;                  // the avgindex of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A10;


// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord = Bounce(0, 8);
Bounce buttonPlay =   Bounce(1, 8);  // 8 = 8 ms debounce time

Bounce buttonRecord2 = Bounce(2, 8);
Bounce buttonPlay2 =   Bounce(3, 8);

float filtercontrol;
float filterfreqcal = 15000;

// which input on the audio shield will be used?


// Remember which mode we're doing
int mode = 0; 
int mode2 = 0;
// 0=stopped, 1=recording, 2=playing
int loopMode = 0;
// The file where data is recorded
File frec;
File frec2;

void setup() {
  // Configure the pushbutton pins
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(16, OUTPUT);
  pinMode(17, OUTPUT);
  pinMode(20, OUTPUT);
  pinMode(21, OUTPUT);
 
  mixer1.gain(0,1);
  mixer1.gain(1,1);
  filter1.frequency(15000);
  filter1.resonance(1.5);
sine1.frequency(5);
  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(120);
const int myInput = AUDIO_INPUT_LINEIN;
  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(myInput);
  sgtl5000_1.volume(0.8);

  // Initialize the SD card
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;    
}


void loop() {
  // First, read the buttons

if (digitalRead(5) == 1) {
 loopMode = 1; 
     Serial.println("Loop On");
} else {
 loopMode = 0; 
  //  Serial.println("Loop Off");
}

  buttonRecord.update();
  buttonPlay.update();
  
  buttonRecord2.update();
  buttonPlay2.update();


setFilter();



  if (mode == 1) {
 digitalWrite(16, HIGH); 
} else {
  digitalWrite(16, LOW); 
}
if (mode == 2) {
 digitalWrite(17, HIGH); 
} else {
  digitalWrite(17, LOW); 
}

  if (mode2 == 1) {
 digitalWrite(20, HIGH); 
} else {
  digitalWrite(20, LOW); 
}
if (mode2 == 2) {
 digitalWrite(21, HIGH); 
} else {
  digitalWrite(21, LOW); 
}
  


  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
   else if (mode == 1) stopRecording();
  }
  


if (loopMode == 1) {

  if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press");
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
    if (mode == 2) startPlaying();
  }
}

if (loopMode == 0) {
    if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press OneShot");
   if (mode == 0) startPlaying();
    if (mode == 1) {
      stopRecording();
      startPlaying();
    }
  }
    if (buttonPlay.risingEdge() && mode != 1) {
     stopPlaying(); 
    }

}

  // If we're playing or recording, carry on...
  if (mode == 1) {
    continueRecording();
  }
  if (mode == 2) {
    continuePlaying();
  }


// second channel

  // Respond to button presses
  if (buttonRecord2.fallingEdge()) {
    Serial.println("Record Button Press 2");
    if (mode2 == 2) stopPlaying2();
    if (mode2 == 0) startRecording2();
   else if (mode2 == 1) stopRecording2();
  }

if (loopMode == 1) {

  if (buttonPlay2.fallingEdge()) {
    Serial.println("Play Button Press 2");
    if (mode2 == 1) stopRecording2();
    if (mode2 == 0) startPlaying2();
    if (mode2 == 2) startPlaying2();
  }
}

if (loopMode == 0) {
    if (buttonPlay2.fallingEdge()) {
    Serial.println("Play Button Press OneShot 2");
   if (mode2 == 0) startPlaying2();
    if (mode2 == 1) {
      stopRecording2();
      startPlaying2();
    }
  }
    if (buttonPlay2.risingEdge() && mode2 != 1) {
     stopPlaying2(); 
    }

}

  // If we're playing or recording, carry on...
  if (mode2 == 1) {
    continueRecording2();
  }
  if (mode2 == 2) {
    continuePlaying2();
  }


}


void startRecording() {
  Serial.println("startRecording");
  if (SD.exists("RECORD.RAW")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD.RAW");
  }
  frec = SD.open("RECORD.RAW", FILE_WRITE);
  if (frec) {
    queue1.begin();
    mode = 1;
  }
}

void continueRecording() {
  if (queue1.available() >= 2) {
    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.
    memcpy(buffer, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    memcpy(buffer+256, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    // write all 512 bytes to the SD card
    elapsedMicros usec = 0;
    frec.write(buffer, 512);
    // Uncomment these lines to see how long SD writes
    // are taking.  A pair of audio blocks arrives every
    // 5802 microseconds, so hopefully most of the writes
    // take well under 5802 us.  Some will take more, as
    // the SD library also must write to the FAT tables
    // and the SD card controller manages media erase and
    // wear leveling.  The queue1 object can buffer
    // approximately 301700 us of audio, to allow time
    // for occasional high SD card latency, as long as
    // the average write time is under 5802 us.
    Serial.print("SD write, us=");
    Serial.println(usec);
  }
}

void stopRecording() {
  Serial.println("stopRecording");
  queue1.end();
  if (mode == 1) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
    }
    frec.close();
  }
  mode = 0;
}



void startPlaying() {
  Serial.println("startPlaying");
  playRaw1.play("RECORD.RAW");
  mode = 2;
}

void continuePlaying() {
  if (!playRaw1.isPlaying()) {
  playRaw1.play("RECORD.RAW");
  //  mode = 0;
  }
}

void stopPlaying() {

  if (mode != 0) {
      Serial.println("stopPlaying");
    playRaw1.stop();
  mode = 0;
  }
}

// second channel
void startRecording2() {
  Serial.println("startRecording2");
  if (SD.exists("RECORD2.RAW")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD2.RAW");
    
  }
  frec2 = SD.open("RECORD2.RAW", FILE_WRITE);
  if (frec2) {
    queue2.begin();
    mode2 = 1; 
    Serial.println("made it this far");
  }
}

void continueRecording2() {
  if (queue2.available() >= 2) {
    byte buffer2[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.
    memcpy(buffer2, queue2.readBuffer(), 256);
    queue2.freeBuffer();
    memcpy(buffer2+256, queue2.readBuffer(), 256);
    queue2.freeBuffer();
    // write all 512 bytes to the SD card
    elapsedMicros usec = 0;
    frec2.write(buffer2, 512);
    // Uncomment these lines to see how long SD writes
    // are taking.  A pair of audio blocks arrives every
    // 5802 microseconds, so hopefully most of the writes
    // take well under 5802 us.  Some will take more, as
    // the SD library also must write to the FAT tables
    // and the SD card controller manages media erase and
    // wear leveling.  The queue1 object can buffer
    // approximately 301700 us of audio, to allow time
    // for occasional high SD card latency, as long as
    // the average write time is under 5802 us.
    //Serial.print("SD write, us=");
    //Serial.println(usec);
  }
}

void stopRecording2() {
  Serial.println("stopRecording2");
  queue2.end();
  if (mode2 == 1) {
    while (queue2.available() > 0) {
      frec2.write((byte*)queue2.readBuffer(), 256);
      queue2.freeBuffer();
      
    }
    frec2.close();
  }
  mode2 = 0;
}


void startPlaying2() {
  Serial.println("startPlaying2");
  playRaw2.play("RECORD2.RAW");
  mode2 = 2;
}

void continuePlaying2() {
  if (!playRaw2.isPlaying()) {
  playRaw2.play("RECORD2.RAW");
  //  mode = 0;
  }
}

void stopPlaying2() {
  Serial.println("stopPlaying2");
  if (mode2 == 2) playRaw2.stop();
  mode2 = 0;
}


void setFilter() {
    // subtract the last reading:
  total= total - readings[avgindex];         
  // read from the sensor:  
  readings[avgindex] = analogRead(inputPin); 
  // add the reading to the total:
  total= total + readings[avgindex];       
  // advance to the next position in the array:  
  avgindex = avgindex + 1;                    

  // if we're at the end of the array...
  if (avgindex >= numReadings)              
    // ...wrap around to the beginning: 
    avgindex = 0;                           

  // calculate the average:
  average = total / numReadings;         
  // send it to the computer as ASCII digits
 
  delay(1);        // delay in between reads for stability       
  
   
  filtercontrol = map(average,0,1023,100,12000);
    filter1.frequency(filtercontrol);
    // Serial.println(filtercontrol);   
  
}
 
Status
Not open for further replies.
Back
Top