Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 /* This file demonstrates the use of the modified libmad library on LPC1768 00002 * Changes to the library are documented in config.h. 00003 * 00004 * The main change is to use parts of the AHB RAM dedicated to the ethernet module, 00005 * because standard RAM is not sufficient for decoding. 00006 * This means the ethernet module cannot be used !!! 00007 * 00008 * It plays a file "test.mp3" from an external USB-drive/USB-stick. 00009 * For wiring of the USB-connector, see mbed.org 00010 * ID3 decoding is not present at the moment and will cause warnings 00011 * on stderr, and some short noise at the beginning or end of playback. 00012 * 00013 * Output is only for one channel on the DAC (AnalogOut) pin. 00014 * (For connections see datasheets/mbed.org) 00015 * This pin should be decoupled with a capacitor (100u or so) to remove DC. 00016 * The output current is high enough to drive small headphones or active 00017 * speakers directly. 00018 * 00019 * Schematic: :-) 00020 * MBED Pin 18 (AOut) o--||--o Headphone Left 00021 * MBED Pin 1 (GND) o------o Headphone Common 00022 * 00023 * It has been tested with fixed bitrate MP3's up to 320kbps and VBR files. 00024 * 00025 * The remaining RAM is very limited, so don't overuse it ! 00026 * The MSCFileSystem library from mbed.org is needed ! 00027 * Last warning: the main include file "mad.h" maybe not up to date, 00028 * use "decoder.h" for now 00029 * Have fun, 00030 * Andreas Gruen 00031 * *** Version 3: *** 00032 * moved another memory block into AHB RAM, giving more room for 00033 * stereo buffer. 00034 * moved content of decode() to main() 00035 * decoding is now safe to be called multiple times (bug in older versions) 00036 * Output routine now fills stereo buffer, DAC output sums channels, 00037 * just for demonstration that stereo output could go here 00038 */ 00039 00040 #include "mbed.h" 00041 # include "decoder.h" 00042 00043 FILE *fp; 00044 #include "MSCFileSystem.h" 00045 MSCFileSystem fs("usb"); 00046 00047 static enum mad_flow input(void *data,struct mad_stream *stream); 00048 static enum mad_flow output(void *data,struct mad_header const *header,struct mad_pcm *pcm); 00049 static enum mad_flow error_fn(void *data,struct mad_stream *stream,struct mad_frame *frame); 00050 00051 struct dacout_s { 00052 unsigned short l; 00053 unsigned short r; 00054 }; 00055 00056 volatile dacout_s dacbuf[1152]; 00057 volatile dacout_s *dac_s, *dac_e; 00058 00059 AnalogOut dac(p18); 00060 Ticker dacclk; 00061 00062 void dacout(void) 00063 { 00064 if(dac_s < dac_e) 00065 { 00066 dac.write_u16((dac_s->l/2)+(dac_s->r/2)); 00067 dac_s++; 00068 } 00069 } 00070 00071 int main(int argc, char *argv[]) 00072 { 00073 int result; 00074 Timer t; 00075 struct mad_decoder decoder; 00076 00077 dac_s = dac_e = dacbuf; 00078 dacclk.attach_us(dacout,23); 00079 while(1) { 00080 fp = fopen("/usb/test.mp3","rb"); 00081 00082 if(!fp) return(printf("file error\r\n")); 00083 fprintf(stderr,"decode start\r\n"); 00084 mad_decoder_init(&decoder, NULL,input, 0, 0, output,error_fn, 0); 00085 t.reset(); 00086 t.start(); 00087 result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); 00088 t.stop(); 00089 fprintf(stderr,"decode ret=%d in %d ms\r\n",result,t.read_ms()); 00090 mad_decoder_finish(&decoder); 00091 fclose(fp); 00092 } 00093 return 0; 00094 } 00095 00096 /* 00097 * This is the input callback. The purpose of this callback is to (re)fill 00098 * the stream buffer which is to be decoded. 00099 */ 00100 00101 static 00102 enum mad_flow input(void *data, 00103 struct mad_stream *stream) 00104 { 00105 static unsigned char strmbuff[2100]; 00106 int ret; 00107 int rsz; 00108 unsigned char *bp; 00109 00110 /* the remaining bytes from incomplete frames must be copied 00111 to the beginning of the new buffer ! 00112 */ 00113 bp = strmbuff; 00114 rsz = 0; 00115 if(stream->error == MAD_ERROR_BUFLEN||stream->buffer==NULL) 00116 { 00117 if(stream->next_frame!=NULL) 00118 { 00119 rsz = stream->bufend-stream->next_frame; 00120 memmove(strmbuff,stream->next_frame,rsz); 00121 bp = strmbuff+rsz; 00122 } 00123 } 00124 00125 ret = fread(bp,1,sizeof(strmbuff) - rsz,fp); 00126 00127 if (!ret) 00128 return MAD_FLOW_STOP; 00129 00130 00131 mad_stream_buffer(stream, strmbuff, ret + rsz); 00132 00133 return MAD_FLOW_CONTINUE;} 00134 00135 00136 /* 00137 * The following utility routine performs simple rounding, clipping, and 00138 * scaling of MAD's high-resolution samples down to 16 bits. It does not 00139 * perform any dithering or noise shaping, which would be recommended to 00140 * obtain any exceptional audio quality. It is therefore not recommended to 00141 * use this routine if high-quality output is desired. 00142 */ 00143 00144 static /*inline*/ 00145 signed int scale(mad_fixed_t sample) 00146 { 00147 /* round */ 00148 sample += (1L << (MAD_F_FRACBITS - 16)); 00149 00150 /* clip */ 00151 if (sample >= MAD_F_ONE) 00152 sample = MAD_F_ONE - 1; 00153 else if (sample < -MAD_F_ONE) 00154 sample = -MAD_F_ONE; 00155 00156 /* quantize */ 00157 return sample >> (MAD_F_FRACBITS + 1 - 16); 00158 } 00159 00160 /* 00161 * This is the output callback function. It is called after each frame of 00162 * MPEG audio data has been completely decoded. The purpose of this callback 00163 * is to output (or play) the decoded PCM audio. 00164 */ 00165 00166 static 00167 enum mad_flow output(void *data, 00168 struct mad_header const *header, 00169 struct mad_pcm *pcm) 00170 { 00171 unsigned int nchannels, nsamples; 00172 mad_fixed_t const *left_ch, *right_ch; 00173 00174 00175 /* pcm->samplerate contains the sampling frequency */ 00176 nchannels = pcm->channels; 00177 nsamples = pcm->length; 00178 left_ch = pcm->samples[0]; 00179 right_ch = pcm->samples[1]; 00180 00181 while(dac_s < dac_e) wait_us(1); 00182 dac_e = dacbuf; // potential thread problem ?? no... 00183 dac_s = dacbuf; 00184 00185 while (nsamples--) { 00186 signed int sample_l,sample_r; 00187 sample_l = scale(*left_ch); 00188 sample_r = scale(*right_ch); 00189 dac_e->l = sample_l +32768; 00190 dac_e->r = sample_r +32768; 00191 dac_e++; 00192 left_ch++; 00193 right_ch++; 00194 } 00195 return MAD_FLOW_CONTINUE; 00196 } 00197 00198 /* 00199 * This is the error callback function. It is called whenever a decoding 00200 * error occurs. The error is indicated by stream->error; the list of 00201 * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h) 00202 * header file. 00203 */ 00204 00205 static 00206 enum mad_flow error_fn(void *data, 00207 struct mad_stream *stream, 00208 struct mad_frame *frame) 00209 { 00210 /* ID3 tags will cause warnings and short noise, ignore it for the moment*/ 00211 00212 fprintf(stderr, "decoding error 0x%04x (%s)\n", 00213 stream->error, mad_stream_errorstr(stream)); 00214 00215 00216 /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ 00217 00218 return MAD_FLOW_CONTINUE; 00219 } 00220 00221
Generated on Tue Jul 12 2022 23:11:09 by
