| @@ -0,0 +1,193 @@ | |||
| // Record sound as raw data to a SD card, and play it back. | |||
| // | |||
| // Requires the audio shield: | |||
| // http://www.pjrc.com/store/teensy3_audio.html | |||
| // | |||
| // Three pushbuttons need to be connected: | |||
| // Record Button: pin 0 to GND | |||
| // Stop Button: pin 1 to GND | |||
| // Play Button: pin 2 to GND | |||
| // | |||
| // This example code is in the public domain. | |||
| #include <Bounce.h> | |||
| #include <Audio.h> | |||
| #include <Wire.h> | |||
| #include <SPI.h> | |||
| #include <SD.h> | |||
| // GUItool: begin automatically generated code | |||
| AudioInputI2S i2s2; //xy=105,63 | |||
| AudioAnalyzePeak peak1; //xy=278,108 | |||
| AudioRecordQueue queue1; //xy=281,63 | |||
| AudioPlaySdRaw playRaw1; //xy=302,157 | |||
| AudioOutputI2S i2s1; //xy=470,120 | |||
| AudioConnection patchCord1(i2s2, 0, queue1, 0); | |||
| AudioConnection patchCord2(i2s2, 0, peak1, 0); | |||
| AudioConnection patchCord3(playRaw1, 0, i2s1, 0); | |||
| AudioConnection patchCord4(playRaw1, 0, i2s1, 1); | |||
| AudioControlSGTL5000 sgtl5000_1; //xy=265,212 | |||
| // GUItool: end automatically generated code | |||
| // Bounce objects to easily and reliably read the buttons | |||
| Bounce buttonRecord = Bounce(0, 8); | |||
| Bounce buttonStop = Bounce(1, 8); // 8 = 8 ms debounce time | |||
| Bounce buttonPlay = Bounce(2, 8); | |||
| // which input on the audio shield will be used? | |||
| const int myInput = AUDIO_INPUT_LINEIN; | |||
| //const int myInput = AUDIO_INPUT_MIC; | |||
| // Remember which mode we're doing | |||
| int mode = 0; // 0=stopped, 1=recording, 2=playing | |||
| // The file where data is recorded | |||
| File frec; | |||
| void setup() { | |||
| // Configure the pushbutton pins | |||
| pinMode(0, INPUT_PULLUP); | |||
| pinMode(1, INPUT_PULLUP); | |||
| pinMode(2, INPUT_PULLUP); | |||
| // Audio connections require memory, and the record queue | |||
| // uses this memory to buffer incoming audio. | |||
| AudioMemory(60); | |||
| // Enable the audio shield, select input, and enable output | |||
| sgtl5000_1.enable(); | |||
| sgtl5000_1.inputSelect(myInput); | |||
| sgtl5000_1.volume(0.5); | |||
| // 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); | |||
| } | |||
| } | |||
| } | |||
| void loop() { | |||
| // First, read the buttons | |||
| buttonRecord.update(); | |||
| buttonStop.update(); | |||
| buttonPlay.update(); | |||
| // Respond to button presses | |||
| if (buttonRecord.fallingEdge()) { | |||
| Serial.println("Record Button Press"); | |||
| if (mode == 2) stopPlaying(); | |||
| if (mode == 0) startRecording(); | |||
| } | |||
| if (buttonStop.fallingEdge()) { | |||
| Serial.println("Stop Button Press"); | |||
| if (mode == 1) stopRecording(); | |||
| if (mode == 2) stopPlaying(); | |||
| } | |||
| if (buttonPlay.fallingEdge()) { | |||
| Serial.println("Play Button Press"); | |||
| if (mode == 1) stopRecording(); | |||
| if (mode == 0) startPlaying(); | |||
| } | |||
| // If we're playing or recording, carry on... | |||
| if (mode == 1) { | |||
| continueRecording(); | |||
| } | |||
| if (mode == 2) { | |||
| continuePlaying(); | |||
| } | |||
| // when using a microphone, continuously adjust gain | |||
| if (myInput == AUDIO_INPUT_MIC) adjustMicLevel(); | |||
| } | |||
| 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.stop(); | |||
| mode = 0; | |||
| } | |||
| } | |||
| void stopPlaying() { | |||
| Serial.println("stopPlaying"); | |||
| if (mode == 2) playRaw1.stop(); | |||
| mode = 0; | |||
| } | |||
| void adjustMicLevel() { | |||
| // TODO: read the peak1 object and adjust sgtl5000_1.micGain() | |||
| // if anyone gets this working, please submit a github pull request :-) | |||
| } | |||