streo mp3 player see: http://mbed.org/users/okini3939/notebook/I2S_AUDIO

Dependencies:   FatFileSystemCpp I2SSlave TLV320 mbed

Fork of madplayer by Andreas Grün

Committer:
okini3939
Date:
Wed Dec 19 06:01:00 2012 +0000
Revision:
3:6f07b5f52c38
Parent:
2:f28cf0afd021
Child:
4:30b2cf4a8ee2
1st build;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Gruenfrosch 0:7627c79db971 1 /* This file demonstrates the use of the modified libmad library on LPC1768
Gruenfrosch 0:7627c79db971 2 * Changes to the library are documented in config.h.
Gruenfrosch 0:7627c79db971 3 *
Gruenfrosch 0:7627c79db971 4 * The main change is to use parts of the AHB RAM dedicated to the ethernet module,
Gruenfrosch 0:7627c79db971 5 * because standard RAM is not sufficient for decoding.
Gruenfrosch 0:7627c79db971 6 * This means the ethernet module cannot be used !!!
Gruenfrosch 0:7627c79db971 7 *
Gruenfrosch 0:7627c79db971 8 * It plays a file "test.mp3" from an external USB-drive/USB-stick.
Gruenfrosch 0:7627c79db971 9 * For wiring of the USB-connector, see mbed.org
Gruenfrosch 0:7627c79db971 10 * ID3 decoding is not present at the moment and will cause warnings
Gruenfrosch 0:7627c79db971 11 * on stderr, and some short noise at the beginning or end of playback.
Gruenfrosch 0:7627c79db971 12 *
Gruenfrosch 0:7627c79db971 13 * Output is only for one channel on the DAC (AnalogOut) pin.
Gruenfrosch 0:7627c79db971 14 * (For connections see datasheets/mbed.org)
Gruenfrosch 0:7627c79db971 15 * This pin should be decoupled with a capacitor (100u or so) to remove DC.
Gruenfrosch 0:7627c79db971 16 * The output current is high enough to drive small headphones or active
Gruenfrosch 0:7627c79db971 17 * speakers directly.
Gruenfrosch 0:7627c79db971 18 *
okini3939 3:6f07b5f52c38 19 * Schematic: :-)
Gruenfrosch 0:7627c79db971 20 * MBED Pin 18 (AOut) o--||--o Headphone Left
okini3939 3:6f07b5f52c38 21 * MBED Pin 1 (GND) o------o Headphone Common
Gruenfrosch 0:7627c79db971 22 *
Gruenfrosch 0:7627c79db971 23 * It has been tested with fixed bitrate MP3's up to 320kbps and VBR files.
Gruenfrosch 0:7627c79db971 24 *
Gruenfrosch 0:7627c79db971 25 * The remaining RAM is very limited, so don't overuse it !
Gruenfrosch 0:7627c79db971 26 * The MSCFileSystem library from mbed.org is needed !
Gruenfrosch 0:7627c79db971 27 * Last warning: the main include file "mad.h" maybe not up to date,
Gruenfrosch 0:7627c79db971 28 * use "decoder.h" for now
Gruenfrosch 0:7627c79db971 29 * Have fun,
Gruenfrosch 0:7627c79db971 30 * Andreas Gruen
Gruenfrosch 2:f28cf0afd021 31 * *** Version 3: ***
Gruenfrosch 2:f28cf0afd021 32 * moved another memory block into AHB RAM, giving more room for
Gruenfrosch 2:f28cf0afd021 33 * stereo buffer.
Gruenfrosch 2:f28cf0afd021 34 * moved content of decode() to main()
okini3939 3:6f07b5f52c38 35 * decoding is now safe to be called multiple times (bug in older versions)
Gruenfrosch 2:f28cf0afd021 36 * Output routine now fills stereo buffer, DAC output sums channels,
Gruenfrosch 2:f28cf0afd021 37 * just for demonstration that stereo output could go here
Gruenfrosch 0:7627c79db971 38 */
Gruenfrosch 0:7627c79db971 39
Gruenfrosch 0:7627c79db971 40 #include "mbed.h"
okini3939 3:6f07b5f52c38 41 #include "decoder.h"
okini3939 3:6f07b5f52c38 42 #include "TLV320.h"
Gruenfrosch 0:7627c79db971 43
okini3939 3:6f07b5f52c38 44 DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
okini3939 3:6f07b5f52c38 45 Serial pc(USBTX, USBRX);
Gruenfrosch 0:7627c79db971 46 FILE *fp;
okini3939 3:6f07b5f52c38 47 #include "SDHCFileSystem.h"
okini3939 3:6f07b5f52c38 48 SDFileSystem sd(p11, p12, p13, p14, "sd");
okini3939 3:6f07b5f52c38 49 TLV320 audio(p9, p10, 0x34, p5, p6, p7, p8, p16); // I2S Codec
Gruenfrosch 0:7627c79db971 50
Gruenfrosch 2:f28cf0afd021 51 static enum mad_flow input(void *data,struct mad_stream *stream);
Gruenfrosch 2:f28cf0afd021 52 static enum mad_flow output(void *data,struct mad_header const *header,struct mad_pcm *pcm);
Gruenfrosch 2:f28cf0afd021 53 static enum mad_flow error_fn(void *data,struct mad_stream *stream,struct mad_frame *frame);
Gruenfrosch 2:f28cf0afd021 54
Gruenfrosch 2:f28cf0afd021 55 struct dacout_s {
Gruenfrosch 2:f28cf0afd021 56 unsigned short l;
Gruenfrosch 2:f28cf0afd021 57 unsigned short r;
Gruenfrosch 2:f28cf0afd021 58 };
Gruenfrosch 2:f28cf0afd021 59
Gruenfrosch 2:f28cf0afd021 60 volatile dacout_s dacbuf[1152];
Gruenfrosch 2:f28cf0afd021 61 volatile dacout_s *dac_s, *dac_e;
Gruenfrosch 0:7627c79db971 62
Gruenfrosch 0:7627c79db971 63 Ticker dacclk;
okini3939 3:6f07b5f52c38 64
Gruenfrosch 0:7627c79db971 65 void dacout(void)
Gruenfrosch 0:7627c79db971 66 {
Gruenfrosch 0:7627c79db971 67 if(dac_s < dac_e)
Gruenfrosch 0:7627c79db971 68 {
okini3939 3:6f07b5f52c38 69 dac_s++;
Gruenfrosch 0:7627c79db971 70 }
Gruenfrosch 0:7627c79db971 71 }
Gruenfrosch 0:7627c79db971 72
okini3939 3:6f07b5f52c38 73 void isr_audio () {
okini3939 3:6f07b5f52c38 74 int i;
okini3939 3:6f07b5f52c38 75 short l, r;
okini3939 3:6f07b5f52c38 76 static int buf[4] = {0,0,0,0};
okini3939 3:6f07b5f52c38 77
okini3939 3:6f07b5f52c38 78 for (i = 0; i < 4; i ++) {
okini3939 3:6f07b5f52c38 79 if (dac_s < dac_e) {
okini3939 3:6f07b5f52c38 80 l = dac_s->l - 0x8000;
okini3939 3:6f07b5f52c38 81 r = dac_s->r - 0x8000;
okini3939 3:6f07b5f52c38 82 buf[i] = (l << 16) | (r & 0xffff);
okini3939 3:6f07b5f52c38 83 dac_s++;
okini3939 3:6f07b5f52c38 84 led3 = !led3;
okini3939 3:6f07b5f52c38 85 } else {
okini3939 3:6f07b5f52c38 86 if (i) {
okini3939 3:6f07b5f52c38 87 buf[i] = buf[i - 1];
okini3939 3:6f07b5f52c38 88 } else {
okini3939 3:6f07b5f52c38 89 buf[i] = buf[3];
okini3939 3:6f07b5f52c38 90 }
okini3939 3:6f07b5f52c38 91 led4 = !led4;
okini3939 3:6f07b5f52c38 92 }
okini3939 3:6f07b5f52c38 93 }
okini3939 3:6f07b5f52c38 94 audio.write(buf, 0, 4);
okini3939 3:6f07b5f52c38 95 }
okini3939 3:6f07b5f52c38 96
Gruenfrosch 0:7627c79db971 97 int main(int argc, char *argv[])
Gruenfrosch 0:7627c79db971 98 {
Gruenfrosch 2:f28cf0afd021 99 int result;
Gruenfrosch 0:7627c79db971 100 Timer t;
Gruenfrosch 2:f28cf0afd021 101 struct mad_decoder decoder;
Gruenfrosch 0:7627c79db971 102
okini3939 3:6f07b5f52c38 103 pc.baud(115200);
Gruenfrosch 0:7627c79db971 104 dac_s = dac_e = dacbuf;
okini3939 3:6f07b5f52c38 105 // dacclk.attach_us(dacout,23);
okini3939 3:6f07b5f52c38 106
okini3939 3:6f07b5f52c38 107 audio.power(0x02); // mic off
okini3939 3:6f07b5f52c38 108 audio.outputVolume(1, 1);
okini3939 3:6f07b5f52c38 109 audio.inputVolume(0.7, 0.7);
okini3939 3:6f07b5f52c38 110 audio.frequency(44100);
okini3939 3:6f07b5f52c38 111 audio.attach(&isr_audio);
okini3939 3:6f07b5f52c38 112 audio.start(TRANSMIT);
okini3939 3:6f07b5f52c38 113
Gruenfrosch 2:f28cf0afd021 114 while(1) {
okini3939 3:6f07b5f52c38 115 fp = fopen("/sd/canyouparty.mp3","rb");
okini3939 3:6f07b5f52c38 116
okini3939 3:6f07b5f52c38 117 if(!fp) return(printf("file error\r\n"));
okini3939 3:6f07b5f52c38 118 fprintf(stderr,"decode start\r\n");
okini3939 3:6f07b5f52c38 119 led1 = 1;
okini3939 3:6f07b5f52c38 120 mad_decoder_init(&decoder, NULL,input, 0, 0, output,error_fn, 0);
okini3939 3:6f07b5f52c38 121 t.reset();
okini3939 3:6f07b5f52c38 122 t.start();
okini3939 3:6f07b5f52c38 123 led2 = 1;
okini3939 3:6f07b5f52c38 124 result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
okini3939 3:6f07b5f52c38 125 t.stop();
okini3939 3:6f07b5f52c38 126 fprintf(stderr,"decode ret=%d in %d ms\r\n",result,t.read_ms());
okini3939 3:6f07b5f52c38 127 led2 = 0;
okini3939 3:6f07b5f52c38 128 mad_decoder_finish(&decoder);
okini3939 3:6f07b5f52c38 129 fclose(fp);
okini3939 3:6f07b5f52c38 130 }
Gruenfrosch 0:7627c79db971 131 }
Gruenfrosch 0:7627c79db971 132
Gruenfrosch 0:7627c79db971 133 /*
Gruenfrosch 0:7627c79db971 134 * This is the input callback. The purpose of this callback is to (re)fill
Gruenfrosch 0:7627c79db971 135 * the stream buffer which is to be decoded.
Gruenfrosch 0:7627c79db971 136 */
Gruenfrosch 0:7627c79db971 137
Gruenfrosch 0:7627c79db971 138 static
Gruenfrosch 0:7627c79db971 139 enum mad_flow input(void *data,
Gruenfrosch 0:7627c79db971 140 struct mad_stream *stream)
Gruenfrosch 0:7627c79db971 141 {
Gruenfrosch 0:7627c79db971 142 static unsigned char strmbuff[2100];
Gruenfrosch 0:7627c79db971 143 int ret;
Gruenfrosch 0:7627c79db971 144 int rsz;
Gruenfrosch 0:7627c79db971 145 unsigned char *bp;
Gruenfrosch 0:7627c79db971 146
Gruenfrosch 0:7627c79db971 147 /* the remaining bytes from incomplete frames must be copied
Gruenfrosch 0:7627c79db971 148 to the beginning of the new buffer !
Gruenfrosch 0:7627c79db971 149 */
Gruenfrosch 0:7627c79db971 150 bp = strmbuff;
Gruenfrosch 0:7627c79db971 151 rsz = 0;
Gruenfrosch 0:7627c79db971 152 if(stream->error == MAD_ERROR_BUFLEN||stream->buffer==NULL)
Gruenfrosch 0:7627c79db971 153 {
Gruenfrosch 0:7627c79db971 154 if(stream->next_frame!=NULL)
Gruenfrosch 0:7627c79db971 155 {
Gruenfrosch 0:7627c79db971 156 rsz = stream->bufend-stream->next_frame;
Gruenfrosch 0:7627c79db971 157 memmove(strmbuff,stream->next_frame,rsz);
Gruenfrosch 0:7627c79db971 158 bp = strmbuff+rsz;
Gruenfrosch 0:7627c79db971 159 }
Gruenfrosch 0:7627c79db971 160 }
Gruenfrosch 0:7627c79db971 161
Gruenfrosch 0:7627c79db971 162 ret = fread(bp,1,sizeof(strmbuff) - rsz,fp);
Gruenfrosch 0:7627c79db971 163
Gruenfrosch 0:7627c79db971 164 if (!ret)
Gruenfrosch 0:7627c79db971 165 return MAD_FLOW_STOP;
Gruenfrosch 0:7627c79db971 166
Gruenfrosch 0:7627c79db971 167
Gruenfrosch 0:7627c79db971 168 mad_stream_buffer(stream, strmbuff, ret + rsz);
Gruenfrosch 0:7627c79db971 169
Gruenfrosch 0:7627c79db971 170 return MAD_FLOW_CONTINUE;}
Gruenfrosch 0:7627c79db971 171
Gruenfrosch 0:7627c79db971 172
Gruenfrosch 0:7627c79db971 173 /*
Gruenfrosch 0:7627c79db971 174 * The following utility routine performs simple rounding, clipping, and
Gruenfrosch 0:7627c79db971 175 * scaling of MAD's high-resolution samples down to 16 bits. It does not
Gruenfrosch 0:7627c79db971 176 * perform any dithering or noise shaping, which would be recommended to
Gruenfrosch 0:7627c79db971 177 * obtain any exceptional audio quality. It is therefore not recommended to
Gruenfrosch 0:7627c79db971 178 * use this routine if high-quality output is desired.
Gruenfrosch 0:7627c79db971 179 */
Gruenfrosch 0:7627c79db971 180
Gruenfrosch 0:7627c79db971 181 static /*inline*/
Gruenfrosch 0:7627c79db971 182 signed int scale(mad_fixed_t sample)
Gruenfrosch 0:7627c79db971 183 {
Gruenfrosch 0:7627c79db971 184 /* round */
Gruenfrosch 0:7627c79db971 185 sample += (1L << (MAD_F_FRACBITS - 16));
Gruenfrosch 0:7627c79db971 186
Gruenfrosch 0:7627c79db971 187 /* clip */
Gruenfrosch 0:7627c79db971 188 if (sample >= MAD_F_ONE)
Gruenfrosch 0:7627c79db971 189 sample = MAD_F_ONE - 1;
Gruenfrosch 0:7627c79db971 190 else if (sample < -MAD_F_ONE)
Gruenfrosch 0:7627c79db971 191 sample = -MAD_F_ONE;
Gruenfrosch 0:7627c79db971 192
Gruenfrosch 0:7627c79db971 193 /* quantize */
Gruenfrosch 0:7627c79db971 194 return sample >> (MAD_F_FRACBITS + 1 - 16);
Gruenfrosch 0:7627c79db971 195 }
Gruenfrosch 0:7627c79db971 196
Gruenfrosch 0:7627c79db971 197 /*
Gruenfrosch 0:7627c79db971 198 * This is the output callback function. It is called after each frame of
Gruenfrosch 0:7627c79db971 199 * MPEG audio data has been completely decoded. The purpose of this callback
Gruenfrosch 0:7627c79db971 200 * is to output (or play) the decoded PCM audio.
Gruenfrosch 0:7627c79db971 201 */
Gruenfrosch 0:7627c79db971 202
Gruenfrosch 0:7627c79db971 203 static
Gruenfrosch 0:7627c79db971 204 enum mad_flow output(void *data,
Gruenfrosch 0:7627c79db971 205 struct mad_header const *header,
Gruenfrosch 0:7627c79db971 206 struct mad_pcm *pcm)
Gruenfrosch 0:7627c79db971 207 {
Gruenfrosch 0:7627c79db971 208 unsigned int nchannels, nsamples;
Gruenfrosch 0:7627c79db971 209 mad_fixed_t const *left_ch, *right_ch;
Gruenfrosch 0:7627c79db971 210
Gruenfrosch 2:f28cf0afd021 211
Gruenfrosch 0:7627c79db971 212 /* pcm->samplerate contains the sampling frequency */
Gruenfrosch 0:7627c79db971 213 nchannels = pcm->channels;
Gruenfrosch 0:7627c79db971 214 nsamples = pcm->length;
Gruenfrosch 0:7627c79db971 215 left_ch = pcm->samples[0];
Gruenfrosch 0:7627c79db971 216 right_ch = pcm->samples[1];
Gruenfrosch 2:f28cf0afd021 217
Gruenfrosch 2:f28cf0afd021 218 while(dac_s < dac_e) wait_us(1);
Gruenfrosch 2:f28cf0afd021 219 dac_e = dacbuf; // potential thread problem ?? no...
Gruenfrosch 2:f28cf0afd021 220 dac_s = dacbuf;
Gruenfrosch 0:7627c79db971 221
Gruenfrosch 0:7627c79db971 222 while (nsamples--) {
Gruenfrosch 2:f28cf0afd021 223 signed int sample_l,sample_r;
Gruenfrosch 2:f28cf0afd021 224 sample_l = scale(*left_ch);
Gruenfrosch 2:f28cf0afd021 225 sample_r = scale(*right_ch);
Gruenfrosch 2:f28cf0afd021 226 dac_e->l = sample_l +32768;
Gruenfrosch 2:f28cf0afd021 227 dac_e->r = sample_r +32768;
Gruenfrosch 2:f28cf0afd021 228 dac_e++;
Gruenfrosch 2:f28cf0afd021 229 left_ch++;
Gruenfrosch 2:f28cf0afd021 230 right_ch++;
Gruenfrosch 0:7627c79db971 231 }
Gruenfrosch 0:7627c79db971 232 return MAD_FLOW_CONTINUE;
Gruenfrosch 0:7627c79db971 233 }
Gruenfrosch 0:7627c79db971 234
Gruenfrosch 0:7627c79db971 235 /*
Gruenfrosch 0:7627c79db971 236 * This is the error callback function. It is called whenever a decoding
Gruenfrosch 0:7627c79db971 237 * error occurs. The error is indicated by stream->error; the list of
Gruenfrosch 0:7627c79db971 238 * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
Gruenfrosch 0:7627c79db971 239 * header file.
Gruenfrosch 0:7627c79db971 240 */
Gruenfrosch 0:7627c79db971 241
Gruenfrosch 0:7627c79db971 242 static
Gruenfrosch 0:7627c79db971 243 enum mad_flow error_fn(void *data,
Gruenfrosch 0:7627c79db971 244 struct mad_stream *stream,
Gruenfrosch 0:7627c79db971 245 struct mad_frame *frame)
Gruenfrosch 0:7627c79db971 246 {
Gruenfrosch 0:7627c79db971 247 /* ID3 tags will cause warnings and short noise, ignore it for the moment*/
okini3939 3:6f07b5f52c38 248 /*
Gruenfrosch 0:7627c79db971 249 fprintf(stderr, "decoding error 0x%04x (%s)\n",
Gruenfrosch 0:7627c79db971 250 stream->error, mad_stream_errorstr(stream));
okini3939 3:6f07b5f52c38 251 */
Gruenfrosch 0:7627c79db971 252
Gruenfrosch 0:7627c79db971 253 /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
Gruenfrosch 0:7627c79db971 254
Gruenfrosch 0:7627c79db971 255 return MAD_FLOW_CONTINUE;
Gruenfrosch 0:7627c79db971 256 }
Gruenfrosch 0:7627c79db971 257
Gruenfrosch 0:7627c79db971 258