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:
Gruenfrosch
Date:
Sat Nov 27 17:27:33 2010 +0000
Revision:
2:f28cf0afd021
Parent:
0:7627c79db971
Child:
3:6f07b5f52c38
Version 3:
* moved another memory block into AHB RAM, giving more room for
* stereo buffer.
* moved content of decode() to main()
* decoding is now safe to be called multiple times (bug in older versions)
* Output routine now fills stereo buffer, DAC output sums channels,
* just for demonstration that stereo output could go here

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 *
Gruenfrosch 0:7627c79db971 19 * Schematic: :-)
Gruenfrosch 0:7627c79db971 20 * MBED Pin 18 (AOut) o--||--o Headphone Left
Gruenfrosch 0:7627c79db971 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()
Gruenfrosch 2:f28cf0afd021 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"
Gruenfrosch 0:7627c79db971 41 # include "decoder.h"
Gruenfrosch 0:7627c79db971 42
Gruenfrosch 0:7627c79db971 43 FILE *fp;
Gruenfrosch 0:7627c79db971 44 #include "MSCFileSystem.h"
Gruenfrosch 0:7627c79db971 45 MSCFileSystem fs("usb");
Gruenfrosch 0:7627c79db971 46
Gruenfrosch 2:f28cf0afd021 47 static enum mad_flow input(void *data,struct mad_stream *stream);
Gruenfrosch 2:f28cf0afd021 48 static enum mad_flow output(void *data,struct mad_header const *header,struct mad_pcm *pcm);
Gruenfrosch 2:f28cf0afd021 49 static enum mad_flow error_fn(void *data,struct mad_stream *stream,struct mad_frame *frame);
Gruenfrosch 2:f28cf0afd021 50
Gruenfrosch 2:f28cf0afd021 51 struct dacout_s {
Gruenfrosch 2:f28cf0afd021 52 unsigned short l;
Gruenfrosch 2:f28cf0afd021 53 unsigned short r;
Gruenfrosch 2:f28cf0afd021 54 };
Gruenfrosch 2:f28cf0afd021 55
Gruenfrosch 2:f28cf0afd021 56 volatile dacout_s dacbuf[1152];
Gruenfrosch 2:f28cf0afd021 57 volatile dacout_s *dac_s, *dac_e;
Gruenfrosch 0:7627c79db971 58
Gruenfrosch 0:7627c79db971 59 AnalogOut dac(p18);
Gruenfrosch 0:7627c79db971 60 Ticker dacclk;
Gruenfrosch 0:7627c79db971 61
Gruenfrosch 0:7627c79db971 62 void dacout(void)
Gruenfrosch 0:7627c79db971 63 {
Gruenfrosch 0:7627c79db971 64 if(dac_s < dac_e)
Gruenfrosch 0:7627c79db971 65 {
Gruenfrosch 2:f28cf0afd021 66 dac.write_u16((dac_s->l/2)+(dac_s->r/2));
Gruenfrosch 2:f28cf0afd021 67 dac_s++;
Gruenfrosch 0:7627c79db971 68 }
Gruenfrosch 0:7627c79db971 69 }
Gruenfrosch 0:7627c79db971 70
Gruenfrosch 0:7627c79db971 71 int main(int argc, char *argv[])
Gruenfrosch 0:7627c79db971 72 {
Gruenfrosch 2:f28cf0afd021 73 int result;
Gruenfrosch 0:7627c79db971 74 Timer t;
Gruenfrosch 2:f28cf0afd021 75 struct mad_decoder decoder;
Gruenfrosch 0:7627c79db971 76
Gruenfrosch 0:7627c79db971 77 dac_s = dac_e = dacbuf;
Gruenfrosch 0:7627c79db971 78 dacclk.attach_us(dacout,23);
Gruenfrosch 2:f28cf0afd021 79 while(1) {
Gruenfrosch 2:f28cf0afd021 80 fp = fopen("/usb/test.mp3","rb");
Gruenfrosch 2:f28cf0afd021 81
Gruenfrosch 2:f28cf0afd021 82 if(!fp) return(printf("file error\r\n"));
Gruenfrosch 2:f28cf0afd021 83 fprintf(stderr,"decode start\r\n");
Gruenfrosch 2:f28cf0afd021 84 mad_decoder_init(&decoder, NULL,input, 0, 0, output,error_fn, 0);
Gruenfrosch 2:f28cf0afd021 85 t.reset();
Gruenfrosch 2:f28cf0afd021 86 t.start();
Gruenfrosch 2:f28cf0afd021 87 result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
Gruenfrosch 2:f28cf0afd021 88 t.stop();
Gruenfrosch 2:f28cf0afd021 89 fprintf(stderr,"decode ret=%d in %d ms\r\n",result,t.read_ms());
Gruenfrosch 2:f28cf0afd021 90 mad_decoder_finish(&decoder);
Gruenfrosch 2:f28cf0afd021 91 fclose(fp);
Gruenfrosch 2:f28cf0afd021 92 }
Gruenfrosch 0:7627c79db971 93 return 0;
Gruenfrosch 0:7627c79db971 94 }
Gruenfrosch 0:7627c79db971 95
Gruenfrosch 0:7627c79db971 96 /*
Gruenfrosch 0:7627c79db971 97 * This is the input callback. The purpose of this callback is to (re)fill
Gruenfrosch 0:7627c79db971 98 * the stream buffer which is to be decoded.
Gruenfrosch 0:7627c79db971 99 */
Gruenfrosch 0:7627c79db971 100
Gruenfrosch 0:7627c79db971 101 static
Gruenfrosch 0:7627c79db971 102 enum mad_flow input(void *data,
Gruenfrosch 0:7627c79db971 103 struct mad_stream *stream)
Gruenfrosch 0:7627c79db971 104 {
Gruenfrosch 0:7627c79db971 105 static unsigned char strmbuff[2100];
Gruenfrosch 0:7627c79db971 106 int ret;
Gruenfrosch 0:7627c79db971 107 int rsz;
Gruenfrosch 0:7627c79db971 108 unsigned char *bp;
Gruenfrosch 0:7627c79db971 109
Gruenfrosch 0:7627c79db971 110 /* the remaining bytes from incomplete frames must be copied
Gruenfrosch 0:7627c79db971 111 to the beginning of the new buffer !
Gruenfrosch 0:7627c79db971 112 */
Gruenfrosch 0:7627c79db971 113 bp = strmbuff;
Gruenfrosch 0:7627c79db971 114 rsz = 0;
Gruenfrosch 0:7627c79db971 115 if(stream->error == MAD_ERROR_BUFLEN||stream->buffer==NULL)
Gruenfrosch 0:7627c79db971 116 {
Gruenfrosch 0:7627c79db971 117 if(stream->next_frame!=NULL)
Gruenfrosch 0:7627c79db971 118 {
Gruenfrosch 0:7627c79db971 119 rsz = stream->bufend-stream->next_frame;
Gruenfrosch 0:7627c79db971 120 memmove(strmbuff,stream->next_frame,rsz);
Gruenfrosch 0:7627c79db971 121 bp = strmbuff+rsz;
Gruenfrosch 0:7627c79db971 122 }
Gruenfrosch 0:7627c79db971 123 }
Gruenfrosch 0:7627c79db971 124
Gruenfrosch 0:7627c79db971 125 ret = fread(bp,1,sizeof(strmbuff) - rsz,fp);
Gruenfrosch 0:7627c79db971 126
Gruenfrosch 0:7627c79db971 127 if (!ret)
Gruenfrosch 0:7627c79db971 128 return MAD_FLOW_STOP;
Gruenfrosch 0:7627c79db971 129
Gruenfrosch 0:7627c79db971 130
Gruenfrosch 0:7627c79db971 131 mad_stream_buffer(stream, strmbuff, ret + rsz);
Gruenfrosch 0:7627c79db971 132
Gruenfrosch 0:7627c79db971 133 return MAD_FLOW_CONTINUE;}
Gruenfrosch 0:7627c79db971 134
Gruenfrosch 0:7627c79db971 135
Gruenfrosch 0:7627c79db971 136 /*
Gruenfrosch 0:7627c79db971 137 * The following utility routine performs simple rounding, clipping, and
Gruenfrosch 0:7627c79db971 138 * scaling of MAD's high-resolution samples down to 16 bits. It does not
Gruenfrosch 0:7627c79db971 139 * perform any dithering or noise shaping, which would be recommended to
Gruenfrosch 0:7627c79db971 140 * obtain any exceptional audio quality. It is therefore not recommended to
Gruenfrosch 0:7627c79db971 141 * use this routine if high-quality output is desired.
Gruenfrosch 0:7627c79db971 142 */
Gruenfrosch 0:7627c79db971 143
Gruenfrosch 0:7627c79db971 144 static /*inline*/
Gruenfrosch 0:7627c79db971 145 signed int scale(mad_fixed_t sample)
Gruenfrosch 0:7627c79db971 146 {
Gruenfrosch 0:7627c79db971 147 /* round */
Gruenfrosch 0:7627c79db971 148 sample += (1L << (MAD_F_FRACBITS - 16));
Gruenfrosch 0:7627c79db971 149
Gruenfrosch 0:7627c79db971 150 /* clip */
Gruenfrosch 0:7627c79db971 151 if (sample >= MAD_F_ONE)
Gruenfrosch 0:7627c79db971 152 sample = MAD_F_ONE - 1;
Gruenfrosch 0:7627c79db971 153 else if (sample < -MAD_F_ONE)
Gruenfrosch 0:7627c79db971 154 sample = -MAD_F_ONE;
Gruenfrosch 0:7627c79db971 155
Gruenfrosch 0:7627c79db971 156 /* quantize */
Gruenfrosch 0:7627c79db971 157 return sample >> (MAD_F_FRACBITS + 1 - 16);
Gruenfrosch 0:7627c79db971 158 }
Gruenfrosch 0:7627c79db971 159
Gruenfrosch 0:7627c79db971 160 /*
Gruenfrosch 0:7627c79db971 161 * This is the output callback function. It is called after each frame of
Gruenfrosch 0:7627c79db971 162 * MPEG audio data has been completely decoded. The purpose of this callback
Gruenfrosch 0:7627c79db971 163 * is to output (or play) the decoded PCM audio.
Gruenfrosch 0:7627c79db971 164 */
Gruenfrosch 0:7627c79db971 165
Gruenfrosch 0:7627c79db971 166 static
Gruenfrosch 0:7627c79db971 167 enum mad_flow output(void *data,
Gruenfrosch 0:7627c79db971 168 struct mad_header const *header,
Gruenfrosch 0:7627c79db971 169 struct mad_pcm *pcm)
Gruenfrosch 0:7627c79db971 170 {
Gruenfrosch 0:7627c79db971 171 unsigned int nchannels, nsamples;
Gruenfrosch 0:7627c79db971 172 mad_fixed_t const *left_ch, *right_ch;
Gruenfrosch 0:7627c79db971 173
Gruenfrosch 2:f28cf0afd021 174
Gruenfrosch 0:7627c79db971 175 /* pcm->samplerate contains the sampling frequency */
Gruenfrosch 0:7627c79db971 176 nchannels = pcm->channels;
Gruenfrosch 0:7627c79db971 177 nsamples = pcm->length;
Gruenfrosch 0:7627c79db971 178 left_ch = pcm->samples[0];
Gruenfrosch 0:7627c79db971 179 right_ch = pcm->samples[1];
Gruenfrosch 2:f28cf0afd021 180
Gruenfrosch 2:f28cf0afd021 181 while(dac_s < dac_e) wait_us(1);
Gruenfrosch 2:f28cf0afd021 182 dac_e = dacbuf; // potential thread problem ?? no...
Gruenfrosch 2:f28cf0afd021 183 dac_s = dacbuf;
Gruenfrosch 0:7627c79db971 184
Gruenfrosch 0:7627c79db971 185 while (nsamples--) {
Gruenfrosch 2:f28cf0afd021 186 signed int sample_l,sample_r;
Gruenfrosch 2:f28cf0afd021 187 sample_l = scale(*left_ch);
Gruenfrosch 2:f28cf0afd021 188 sample_r = scale(*right_ch);
Gruenfrosch 2:f28cf0afd021 189 dac_e->l = sample_l +32768;
Gruenfrosch 2:f28cf0afd021 190 dac_e->r = sample_r +32768;
Gruenfrosch 2:f28cf0afd021 191 dac_e++;
Gruenfrosch 2:f28cf0afd021 192 left_ch++;
Gruenfrosch 2:f28cf0afd021 193 right_ch++;
Gruenfrosch 0:7627c79db971 194 }
Gruenfrosch 0:7627c79db971 195 return MAD_FLOW_CONTINUE;
Gruenfrosch 0:7627c79db971 196 }
Gruenfrosch 0:7627c79db971 197
Gruenfrosch 0:7627c79db971 198 /*
Gruenfrosch 0:7627c79db971 199 * This is the error callback function. It is called whenever a decoding
Gruenfrosch 0:7627c79db971 200 * error occurs. The error is indicated by stream->error; the list of
Gruenfrosch 0:7627c79db971 201 * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
Gruenfrosch 0:7627c79db971 202 * header file.
Gruenfrosch 0:7627c79db971 203 */
Gruenfrosch 0:7627c79db971 204
Gruenfrosch 0:7627c79db971 205 static
Gruenfrosch 0:7627c79db971 206 enum mad_flow error_fn(void *data,
Gruenfrosch 0:7627c79db971 207 struct mad_stream *stream,
Gruenfrosch 0:7627c79db971 208 struct mad_frame *frame)
Gruenfrosch 0:7627c79db971 209 {
Gruenfrosch 0:7627c79db971 210 /* ID3 tags will cause warnings and short noise, ignore it for the moment*/
Gruenfrosch 0:7627c79db971 211
Gruenfrosch 0:7627c79db971 212 fprintf(stderr, "decoding error 0x%04x (%s)\n",
Gruenfrosch 0:7627c79db971 213 stream->error, mad_stream_errorstr(stream));
Gruenfrosch 0:7627c79db971 214
Gruenfrosch 0:7627c79db971 215
Gruenfrosch 0:7627c79db971 216 /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
Gruenfrosch 0:7627c79db971 217
Gruenfrosch 0:7627c79db971 218 return MAD_FLOW_CONTINUE;
Gruenfrosch 0:7627c79db971 219 }
Gruenfrosch 0:7627c79db971 220
Gruenfrosch 0:7627c79db971 221