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:
Fri Nov 26 12:18:30 2010 +0000
Revision:
0:7627c79db971
Child:
2:f28cf0afd021
First Version

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