Daniel Worrall
/
Recorder
Record audio data to a .wav file, complete with header, using the TLV320 CODEC and I2S port
main.cpp
- Committer:
- d_worrall
- Date:
- 2011-08-05
- Revision:
- 0:e7efc8468066
File content as of revision 0:e7efc8468066:
#include "mbed.h" #include "SDHCFileSystem.h" #include "MSCFileSystem.h" #include "TLV320.h" TLV320 audio(p9, p10, 52, p5, p6, p7, p8, p29); //TLV320 object SDFileSystem sd(p11, p12, p13, p14, "sd"); //SD Card object MSCFileSystem msc("usb"); //USB object InterruptIn finish(p16); //button to stop recording FILE *outfp; //file pointer object /* Buffers, pointers and states */ int circularBuffer[4096]; volatile int writePointer = 0; volatile int theta = 0; volatile bool recording = false; volatile long size = 36; /* Record settings */ unsigned int frequency = 8000; //sample rate unsigned short wordWidth = 16; //bits per sample per channel unsigned short channels = 2; //number of channels /* Function to read content of I2SRXFIFO into circular buffer */ void record(void){ audio.read(); circularBuffer[writePointer] = audio.rxBuffer[0]; circularBuffer[++writePointer] = audio.rxBuffer[1]; circularBuffer[++writePointer] = audio.rxBuffer[2]; circularBuffer[++writePointer] = audio.rxBuffer[3]; ++writePointer; theta += 4; if(writePointer > 4094) writePointer = 0; } /*Function to write data from circular buffer to usb storage */ void streamToFile(void){ static volatile int readPointer = 0; while(recording){ if(theta > 512){ // only start writing when there is enough data! fwrite(&circularBuffer[readPointer], 4, 128, outfp); //write data in 512 byte chunks, this is theta -= 128; //the natural usb memory chunk size readPointer += 128; if(readPointer > 4094) readPointer = 0; size += 512; } } //Complete file and header details fseek(outfp, 0, SEEK_END); for(int k = 0; k < theta; ++k){ fwrite(&circularBuffer[readPointer], 4, 1, outfp); //this writes the last of the data ++readPointer; //held in the circular buffer to memory if(readPointer > 4094) readPointer = 0; size += 4; } return; } /* Function to stop recording, namely to stop audio interrupts */ void stopRecording(void){ audio.stop(); recording = false; return; } /* Function to write .wav header */ void startHeader(void){ /* RIFF WAV header * --------------- * This is composed of several sub chunks. All strings * are in big endian form. All numeric data is in little endian form. * All data to be completed after recording (i.e. data chunk size) is default blank. */ char blockAlign = (char)channels * (wordWidth/8); int bps = (int)frequency * blockAlign; char header[44] = { 0x52, 0x49, 0x46, 0x46, //'RIFF' 0x00, 0x00, 0x00, 0x00, //file size 0x57, 0x41, 0x56, 0x45, //'WAVE' /*sub chunk 1*/ 0x66, 0x6d, 0x74, 0x20, //'fmt ' 0x10, 0x00, 0x00, 0x00, //subchunk size = 16 0x01, 0x00, ((char)(channels & 0xff)), 0x00, //PCM compression code | number of channels - I assume no more than 2 channels ((char)((frequency & 0xff)>>0)), ((char)((frequency & 0xff00)>>8)), ((char)((frequency & 0xff0000)>>16)), ((char)((frequency & 0xff000000)>>24)), //sample rate ((char)((bps & 0xff)>>0)), ((char)((bps & 0xff00)>>8)), ((char)((bps & 0xff0000)>>16)), ((char)((bps & 0xff000000)>>24)), //bit rate blockAlign, 0x00, ((char)((wordWidth & 0xff)>>0)), ((char)((wordWidth & 0xff00)>>8)), //bloack align | wordwidth /*sub chunk 2*/ 0x64, 0x61, 0x74, 0x61, //'data' 0x00, 0x00, 0x00, 0x00}; //size of data chunk in bytes fwrite(header, 1, 44, outfp); } /* Function to complete header, once recording finishes */ void completeHeader(void){ fseek(outfp, 4, SEEK_SET); fputc((int) (0xff & size), outfp); //All these lines are needed to switch the endianess of the data fputc((int) ((0xff00 & size) >> 8), outfp); fputc((int) ((0xff0000 & size) >> 16), outfp); fputc((int) ((0xff000000 & size) >> 24), outfp); fseek(outfp, 40, SEEK_SET); size -= 36; fputc((int) (0xff & size), outfp); fputc((int) ((0xff00 & size) >> 8), outfp); fputc((int) ((0xff0000 & size) >> 16), outfp); fputc((int) ((0xff000000 & size) >> 24), outfp); } /* Main */ int main(){ /* Create a file to write to */ outfp = fopen("/usb/rec.wav", "w"); if(outfp == NULL){ perror("Error opening file!"); exit(1); } startHeader(); //write first half of header audio.power(0x02); //power up all TLV320, just not microphone audio.inputVolume(0.999, 0.999); //Set input volume to max - I don't like to use 1.0 due to rounding errors audio.frequency(frequency); audio.format(wordWidth, (2-channels)); //note int mode = 2 - channels audio.attach(&record); //attach record function to audio interrupt finish.rise(&stopRecording); //attach stop button for(int j = 0; j < 4096; ++j){ circularBuffer[j] = 0; //clear circular buffer } recording = true; audio.start(RECEIVE); //start recording streamToFile(); completeHeader(); //once finished recording complete the header fclose(outfp); //and close the file }