Read an wav file from sdcard and play it through I2S on LPC4088 QSB platform
Dependencies: EALib I2SSlave TLV320 mbed
Fork of playback by
works with 16bits / 44,1 khz files.
I'm going to work on 24/32 bits, 48khz 96 khz files...
main.cpp@0:3d6892f6384f, 2011-08-05 (annotated)
- Committer:
- d_worrall
- Date:
- Fri Aug 05 10:07:47 2011 +0000
- Revision:
- 0:3d6892f6384f
- Child:
- 2:ce93bf118649
version 2.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
d_worrall | 0:3d6892f6384f | 1 | #include "mbed.h" |
d_worrall | 0:3d6892f6384f | 2 | #include "SDHCFileSystem.h" |
d_worrall | 0:3d6892f6384f | 3 | #include "TLV320.h" |
d_worrall | 0:3d6892f6384f | 4 | |
d_worrall | 0:3d6892f6384f | 5 | TLV320 audio(p9, p10, 52, p5, p6, p7, p8, p29); //TLV320 object |
d_worrall | 0:3d6892f6384f | 6 | SDFileSystem sd(p11, p12, p13, p14, "sd"); //SD Card object |
d_worrall | 0:3d6892f6384f | 7 | InterruptIn volumeSet(p17); |
d_worrall | 0:3d6892f6384f | 8 | AnalogIn aIn(p19); |
d_worrall | 0:3d6892f6384f | 9 | FILE *infp; //File pointer object |
d_worrall | 0:3d6892f6384f | 10 | /* Buffers */ |
d_worrall | 0:3d6892f6384f | 11 | int circularBuffer[4096]; |
d_worrall | 0:3d6892f6384f | 12 | volatile int readPointer = 0; |
d_worrall | 0:3d6892f6384f | 13 | volatile int theta = 0; |
d_worrall | 0:3d6892f6384f | 14 | /* Wav file header data, for setting up the transfer protocol */ |
d_worrall | 0:3d6892f6384f | 15 | short channels; |
d_worrall | 0:3d6892f6384f | 16 | long sampleRate; |
d_worrall | 0:3d6892f6384f | 17 | short wordWidth; |
d_worrall | 0:3d6892f6384f | 18 | /* Function to set volume*/ |
d_worrall | 0:3d6892f6384f | 19 | void setVolume(void){ |
d_worrall | 0:3d6892f6384f | 20 | audio.outputVolume(aIn, aIn); |
d_worrall | 0:3d6892f6384f | 21 | } |
d_worrall | 0:3d6892f6384f | 22 | /* Function to read from circular buffer and send data to TLV320 */ |
d_worrall | 0:3d6892f6384f | 23 | void play(void){ |
d_worrall | 0:3d6892f6384f | 24 | audio.write(circularBuffer, readPointer, 8); |
d_worrall | 0:3d6892f6384f | 25 | //Pointer fun :-) |
d_worrall | 0:3d6892f6384f | 26 | readPointer += 8; |
d_worrall | 0:3d6892f6384f | 27 | readPointer &= 0xfff; |
d_worrall | 0:3d6892f6384f | 28 | theta -= 8; |
d_worrall | 0:3d6892f6384f | 29 | } |
d_worrall | 0:3d6892f6384f | 30 | /* Function to load circular buffer from SD Card */ |
d_worrall | 0:3d6892f6384f | 31 | void fillBuffer(void){ |
d_worrall | 0:3d6892f6384f | 32 | while(!feof(infp)){ //fill the circular buffer until the end of the file |
d_worrall | 0:3d6892f6384f | 33 | static volatile int writePointer = 0; |
d_worrall | 0:3d6892f6384f | 34 | if(theta < 4096){ |
d_worrall | 0:3d6892f6384f | 35 | fread(&circularBuffer[writePointer], 4, 4, infp); //read 4 integers into the circular buffer at a time |
d_worrall | 0:3d6892f6384f | 36 | //More pointer fun :D |
d_worrall | 0:3d6892f6384f | 37 | theta+=4; |
d_worrall | 0:3d6892f6384f | 38 | writePointer+=4; |
d_worrall | 0:3d6892f6384f | 39 | writePointer &= 0xfff; |
d_worrall | 0:3d6892f6384f | 40 | } |
d_worrall | 0:3d6892f6384f | 41 | } |
d_worrall | 0:3d6892f6384f | 42 | } |
d_worrall | 0:3d6892f6384f | 43 | /* main */ |
d_worrall | 0:3d6892f6384f | 44 | int main(){ |
d_worrall | 0:3d6892f6384f | 45 | infp = fopen("/sd/test.wav", "r"); //open file |
d_worrall | 0:3d6892f6384f | 46 | if(infp == NULL){ //make sure it's been opened |
d_worrall | 0:3d6892f6384f | 47 | perror("Error opening file!"); |
d_worrall | 0:3d6892f6384f | 48 | exit(1); |
d_worrall | 0:3d6892f6384f | 49 | } |
d_worrall | 0:3d6892f6384f | 50 | /* Parse wav file header */ |
d_worrall | 0:3d6892f6384f | 51 | fseek(infp, 22, SEEK_SET); |
d_worrall | 0:3d6892f6384f | 52 | fread(&channels, 2, 1, infp); |
d_worrall | 0:3d6892f6384f | 53 | fseek(infp, 24, SEEK_SET); |
d_worrall | 0:3d6892f6384f | 54 | fread(&sampleRate, 4, 1, infp); |
d_worrall | 0:3d6892f6384f | 55 | fseek(infp, 34, SEEK_SET); |
d_worrall | 0:3d6892f6384f | 56 | fread(&wordWidth, 2, 1, infp); |
d_worrall | 0:3d6892f6384f | 57 | |
d_worrall | 0:3d6892f6384f | 58 | volumeSet.rise(&setVolume); //attach set volume function to digital input |
d_worrall | 0:3d6892f6384f | 59 | audio.power(0x07); //power up TLV apart from analogue input |
d_worrall | 0:3d6892f6384f | 60 | audio.frequency(sampleRate); //set sample frequency |
d_worrall | 0:3d6892f6384f | 61 | audio.format(wordWidth, (2-channels)); //set transfer protocol |
d_worrall | 0:3d6892f6384f | 62 | audio.attach(&play); //attach interrupt handler to send data to TLV320 |
d_worrall | 0:3d6892f6384f | 63 | for(int j = 0; j < 4096; ++j){ //upon interrupt generation |
d_worrall | 0:3d6892f6384f | 64 | circularBuffer[j] = 0; //clear circular buffer |
d_worrall | 0:3d6892f6384f | 65 | } |
d_worrall | 0:3d6892f6384f | 66 | audio.start(TRANSMIT); //interrupt come from the I2STXFIFO only |
d_worrall | 0:3d6892f6384f | 67 | fillBuffer(); //continually fill circular buffer |
d_worrall | 0:3d6892f6384f | 68 | } |