Hello
Sorry guys, I know this has been answered a lot of times, but I am stucking with writing the wave-header to an recorded raw-file.
As a staring point use the basic Recorder demo from the Audio-lib and add the header data after recording.
The recording itself is ok, but at the end the file is not recognized as a wav file.
Is there a way to check if the header was written in the correct way?
Thanks in advance
Marcus
Sorry guys, I know this has been answered a lot of times, but I am stucking with writing the wave-header to an recorded raw-file.
As a staring point use the basic Recorder demo from the Audio-lib and add the header data after recording.
The recording itself is ok, but at the end the file is not recognized as a wav file.
Is there a way to check if the header was written in the correct way?
Thanks in advance
Marcus
Code:
#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputI2S i2s2; //xy=226.75,251.9999988079071
AudioRecordQueue queue1; //xy=402.75,251.9999988079071
AudioConnection patchCord1(i2s2, 0, queue1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=386.75,400.9999988079071
// 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
const int myInput = AUDIO_INPUT_LINEIN;
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
// Remember which mode we're doing
int mode = 0; // 0=stopped, 1=recording
// The file where data is recorded
File frec;
void setup() {
Serial.begin(9600);
// Configure the pushbutton pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
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(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here if no SD card, but print a message
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
}
void loop() {
buttonRecord.update();
buttonStop.update();
if (buttonRecord.fallingEdge()) {
Serial.println("Record Button Press");
if (mode == 0) startRecording();
}
if (buttonStop.fallingEdge()) {
Serial.println("Stop Button Press");
if (mode == 1) stopRecording();
}
// If we're playing or recording, carry on...
if (mode == 1) {
continueRecording();
}
if (mode == 2) {
Serial.println("Writing Header");
delay(100);
writeOutHeader();
}
}
///////////////////////////////////////////////////////// startRecording /////////////////////////////////////////
void startRecording() {
Serial.println("startRecording");
if (SD.exists("RECORD.WAV")) {
SD.remove("RECORD.RAW");
}
frec = SD.open("RECORD.WAV", FILE_WRITE);
if (frec) {
queue1.begin();
mode = 1;
}
}
///////////////////////////////////////////////////////// continueRecording /////////////////////////////////////////
void continueRecording() {
if (queue1.available() >= 2) {
byte buffer[512];
// 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);
}
}
///////////////////////////////////////////////////////// stopRecording /////////////////////////////////////////////
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 = 2;
}
///////////////////////////////////////////////////////// writeOutHeader ////////////////////////////////////////////
void writeOutHeader() { // update WAV header with final filesize/datasize
File frec = SD.open("RECORD.WAV");
int dataSize = frec.size();
int headerSize = 44;
int dataChunkSize = dataSize + headerSize - 8;
int subDataChunkSize = 16;
byte format = 0x1; //PCM
byte channels = 0x1; //mono
int sampleRate = 44100;
int bytesPerSample = 4;
int bitsPerSample = 16;
Serial.write("RIFF"); // 00 - RIFF
for (int n = 0; n < 4; ++n) Serial.write((byte)((dataChunkSize >> (n * 8)) & 0xFF)); // 04 - how big is the rest of this file?
Serial.write("WAVE"); // 08 - WAVE
Serial.write("fmt "); // 12 - fmt
for (int n = 0; n < 4; ++n) Serial.write((byte)((subDataChunkSize >> (n * 8)) & 0xFF )); // 16 - size of this chunk
for (int n = 0; n < 2; ++n) Serial.write((byte)((format >> (n * 8)) & 0xFF)); // 20 - what is the audio format? 1 for PCM = Pulse Code Modulation
for (int n = 0; n < 2; ++n) Serial.write((byte)((channels >> (n * 8)) & 0xFF)); // 22 - mono or stereo? 1 or 2? (or 5 or ???)
for (int n = 0; n < 4; ++n) Serial.write((byte)((sampleRate >> (n * 8)) & 0xFF)); // 24 - samples per second (numbers per second)
for (int n = 0; n < 4; ++n) Serial.write((byte)(((sampleRate * bytesPerSample) >> (n * 8)) & 0xFF)); // 28 - bytes per second
for (int n = 0; n < 2; ++n) Serial.write((byte)(((bytesPerSample) >> (n * 8)) & 0xFF )); // 32 - # of bytes in one sample, for all channels
for (int n = 0; n < 2; ++n) Serial.write((byte)((bitsPerSample >> (n * 8)) & 0xFF)); // 34 - how many bits in a sample(number)? usually 16 or 24
Serial.write("data"); // 36 - data
for (int n = 0; n < 4; ++n) Serial.write((byte)((dataSize >> (n * 8)) & 0xFF)); // 40 - how big is this data chunk
// 44 - the actual data itself
byte b;
bool reading = true;
do {
if (frec.available()) {
b = frec.read();
Serial.write(b);
}
else reading = false;
}
while (reading);
frec.close();
mode = 0;
}