-
Notifications
You must be signed in to change notification settings - Fork 402
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aea5f90
commit d4a8bb9
Showing
1 changed file
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 :-) | ||
} | ||
|