MP3 Player without external hardware MP3 Player without external hardware. A software based MP3 player based on a modified version of libmad. Mono output (at the moment) via AnalogOut. Files are read from an USB drive. This is a demo program, it plays only one file at the moment. Documentation is in "main.cpp" and "config.h"

Dependencies:   mbed

Committer:
Gruenfrosch
Date:
Sat Nov 27 17:27:33 2010 +0000
Revision:
2:f28cf0afd021
Parent:
0:7627c79db971
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 /*
Gruenfrosch 0:7627c79db971 2 * libmad - MPEG audio decoder library
Gruenfrosch 0:7627c79db971 3 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
Gruenfrosch 0:7627c79db971 4 *
Gruenfrosch 0:7627c79db971 5 * This program is free software; you can redistribute it and/or modify
Gruenfrosch 0:7627c79db971 6 * it under the terms of the GNU General Public License as published by
Gruenfrosch 0:7627c79db971 7 * the Free Software Foundation; either version 2 of the License, or
Gruenfrosch 0:7627c79db971 8 * (at your option) any later version.
Gruenfrosch 0:7627c79db971 9 *
Gruenfrosch 0:7627c79db971 10 * This program is distributed in the hope that it will be useful,
Gruenfrosch 0:7627c79db971 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Gruenfrosch 0:7627c79db971 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Gruenfrosch 0:7627c79db971 13 * GNU General Public License for more details.
Gruenfrosch 0:7627c79db971 14 *
Gruenfrosch 0:7627c79db971 15 * You should have received a copy of the GNU General Public License
Gruenfrosch 0:7627c79db971 16 * along with this program; if not, write to the Free Software
Gruenfrosch 0:7627c79db971 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Gruenfrosch 0:7627c79db971 18 *
Gruenfrosch 0:7627c79db971 19 * $Id: decoder.c,v 1.1 2010/11/23 20:12:57 andy Exp $
Gruenfrosch 0:7627c79db971 20 */
Gruenfrosch 0:7627c79db971 21
Gruenfrosch 0:7627c79db971 22 # include "config.h"
Gruenfrosch 0:7627c79db971 23
Gruenfrosch 0:7627c79db971 24 # include "global.h"
Gruenfrosch 0:7627c79db971 25
Gruenfrosch 0:7627c79db971 26
Gruenfrosch 0:7627c79db971 27 # ifdef HAVE_SYS_TYPES_H
Gruenfrosch 0:7627c79db971 28 # include <sys/types.h>
Gruenfrosch 0:7627c79db971 29 # endif
Gruenfrosch 0:7627c79db971 30
Gruenfrosch 0:7627c79db971 31 # ifdef HAVE_SYS_WAIT_H
Gruenfrosch 0:7627c79db971 32 # include <sys/wait.h>
Gruenfrosch 0:7627c79db971 33 # endif
Gruenfrosch 0:7627c79db971 34
Gruenfrosch 0:7627c79db971 35 # ifdef HAVE_UNISTD_H
Gruenfrosch 0:7627c79db971 36 # include <unistd.h>
Gruenfrosch 0:7627c79db971 37 # endif
Gruenfrosch 0:7627c79db971 38
Gruenfrosch 0:7627c79db971 39 # ifdef HAVE_FCNTL_H
Gruenfrosch 0:7627c79db971 40 # include <fcntl.h>
Gruenfrosch 0:7627c79db971 41 # endif
Gruenfrosch 0:7627c79db971 42
Gruenfrosch 0:7627c79db971 43 # include <stdlib.h>
Gruenfrosch 0:7627c79db971 44
Gruenfrosch 0:7627c79db971 45 # ifdef HAVE_ERRNO_H
Gruenfrosch 0:7627c79db971 46 # include <errno.h>
Gruenfrosch 0:7627c79db971 47 # endif
Gruenfrosch 0:7627c79db971 48
Gruenfrosch 0:7627c79db971 49 # include "stream.h"
Gruenfrosch 0:7627c79db971 50 # include "frame.h"
Gruenfrosch 0:7627c79db971 51 # include "synth.h"
Gruenfrosch 0:7627c79db971 52 # include "decoder.h"
Gruenfrosch 0:7627c79db971 53
Gruenfrosch 0:7627c79db971 54 /*
Gruenfrosch 0:7627c79db971 55 * NAME: decoder->init()
Gruenfrosch 0:7627c79db971 56 * DESCRIPTION: initialize a decoder object with callback routines
Gruenfrosch 0:7627c79db971 57 */
Gruenfrosch 0:7627c79db971 58 void mad_decoder_init(struct mad_decoder *decoder, void *data,
Gruenfrosch 0:7627c79db971 59 enum mad_flow (*input_func)(void *,
Gruenfrosch 0:7627c79db971 60 struct mad_stream *),
Gruenfrosch 0:7627c79db971 61 enum mad_flow (*header_func)(void *,
Gruenfrosch 0:7627c79db971 62 struct mad_header const *),
Gruenfrosch 0:7627c79db971 63 enum mad_flow (*filter_func)(void *,
Gruenfrosch 0:7627c79db971 64 struct mad_stream const *,
Gruenfrosch 0:7627c79db971 65 struct mad_frame *),
Gruenfrosch 0:7627c79db971 66 enum mad_flow (*output_func)(void *,
Gruenfrosch 0:7627c79db971 67 struct mad_header const *,
Gruenfrosch 0:7627c79db971 68 struct mad_pcm *),
Gruenfrosch 0:7627c79db971 69 enum mad_flow (*error_func)(void *,
Gruenfrosch 0:7627c79db971 70 struct mad_stream *,
Gruenfrosch 0:7627c79db971 71 struct mad_frame *),
Gruenfrosch 0:7627c79db971 72 enum mad_flow (*message_func)(void *,
Gruenfrosch 0:7627c79db971 73 void *, unsigned int *))
Gruenfrosch 0:7627c79db971 74 {
Gruenfrosch 0:7627c79db971 75 decoder->mode = (enum mad_decoder_mode)-1;
Gruenfrosch 0:7627c79db971 76
Gruenfrosch 0:7627c79db971 77 decoder->options = 0;
Gruenfrosch 0:7627c79db971 78
Gruenfrosch 0:7627c79db971 79
Gruenfrosch 0:7627c79db971 80 decoder->sync = 0;
Gruenfrosch 0:7627c79db971 81
Gruenfrosch 0:7627c79db971 82 decoder->cb_data = data;
Gruenfrosch 0:7627c79db971 83
Gruenfrosch 0:7627c79db971 84 decoder->input_func = input_func;
Gruenfrosch 0:7627c79db971 85 decoder->header_func = header_func;
Gruenfrosch 0:7627c79db971 86 decoder->filter_func = filter_func;
Gruenfrosch 0:7627c79db971 87 decoder->output_func = output_func;
Gruenfrosch 0:7627c79db971 88 decoder->error_func = error_func;
Gruenfrosch 0:7627c79db971 89 decoder->message_func = message_func;
Gruenfrosch 0:7627c79db971 90 }
Gruenfrosch 0:7627c79db971 91
Gruenfrosch 0:7627c79db971 92 int mad_decoder_finish(struct mad_decoder *decoder)
Gruenfrosch 0:7627c79db971 93 {
Gruenfrosch 0:7627c79db971 94 return 0;
Gruenfrosch 0:7627c79db971 95 }
Gruenfrosch 0:7627c79db971 96
Gruenfrosch 0:7627c79db971 97
Gruenfrosch 0:7627c79db971 98 static
Gruenfrosch 0:7627c79db971 99 enum mad_flow error_default(void *data, struct mad_stream *stream,
Gruenfrosch 0:7627c79db971 100 struct mad_frame *frame)
Gruenfrosch 0:7627c79db971 101 {
Gruenfrosch 0:7627c79db971 102 int *bad_last_frame = (int *)data;
Gruenfrosch 0:7627c79db971 103
Gruenfrosch 0:7627c79db971 104 switch (stream->error) {
Gruenfrosch 0:7627c79db971 105 case MAD_ERROR_BADCRC:
Gruenfrosch 0:7627c79db971 106 if (*bad_last_frame)
Gruenfrosch 0:7627c79db971 107 mad_frame_mute(frame);
Gruenfrosch 0:7627c79db971 108 else
Gruenfrosch 0:7627c79db971 109 *bad_last_frame = 1;
Gruenfrosch 0:7627c79db971 110
Gruenfrosch 0:7627c79db971 111 return MAD_FLOW_IGNORE;
Gruenfrosch 0:7627c79db971 112
Gruenfrosch 0:7627c79db971 113 default:
Gruenfrosch 0:7627c79db971 114 return MAD_FLOW_CONTINUE;
Gruenfrosch 0:7627c79db971 115 }
Gruenfrosch 0:7627c79db971 116 }
Gruenfrosch 0:7627c79db971 117
Gruenfrosch 0:7627c79db971 118 static
Gruenfrosch 0:7627c79db971 119 int run_sync(struct mad_decoder *decoder)
Gruenfrosch 0:7627c79db971 120 {
Gruenfrosch 0:7627c79db971 121 enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *);
Gruenfrosch 0:7627c79db971 122 void *error_data;
Gruenfrosch 0:7627c79db971 123 int bad_last_frame = 0;
Gruenfrosch 0:7627c79db971 124 struct mad_stream *stream;
Gruenfrosch 0:7627c79db971 125 struct mad_frame *frame;
Gruenfrosch 0:7627c79db971 126 struct mad_synth *synth;
Gruenfrosch 0:7627c79db971 127 int result = 0;
Gruenfrosch 0:7627c79db971 128
Gruenfrosch 0:7627c79db971 129 if (decoder->input_func == 0)
Gruenfrosch 0:7627c79db971 130 return 0;
Gruenfrosch 0:7627c79db971 131
Gruenfrosch 0:7627c79db971 132 if (decoder->error_func) {
Gruenfrosch 0:7627c79db971 133 error_func = decoder->error_func;
Gruenfrosch 0:7627c79db971 134 error_data = decoder->cb_data;
Gruenfrosch 0:7627c79db971 135 }
Gruenfrosch 0:7627c79db971 136 else {
Gruenfrosch 0:7627c79db971 137 error_func = error_default;
Gruenfrosch 0:7627c79db971 138 error_data = &bad_last_frame;
Gruenfrosch 0:7627c79db971 139 }
Gruenfrosch 0:7627c79db971 140
Gruenfrosch 0:7627c79db971 141 stream = &decoder->sync->stream;
Gruenfrosch 0:7627c79db971 142 frame = &decoder->sync->frame;
Gruenfrosch 0:7627c79db971 143 synth = decoder->sync->synth;
Gruenfrosch 0:7627c79db971 144
Gruenfrosch 0:7627c79db971 145 mad_stream_init(stream);
Gruenfrosch 0:7627c79db971 146 mad_frame_init(frame);
Gruenfrosch 0:7627c79db971 147 mad_synth_init(synth);
Gruenfrosch 0:7627c79db971 148
Gruenfrosch 0:7627c79db971 149 mad_stream_options(stream, decoder->options);
Gruenfrosch 0:7627c79db971 150
Gruenfrosch 0:7627c79db971 151 do {
Gruenfrosch 0:7627c79db971 152 switch (decoder->input_func(decoder->cb_data, stream)) {
Gruenfrosch 0:7627c79db971 153 case MAD_FLOW_STOP:
Gruenfrosch 0:7627c79db971 154 goto done;
Gruenfrosch 0:7627c79db971 155 case MAD_FLOW_BREAK:
Gruenfrosch 0:7627c79db971 156 goto fail;
Gruenfrosch 0:7627c79db971 157 case MAD_FLOW_IGNORE:
Gruenfrosch 0:7627c79db971 158 continue;
Gruenfrosch 0:7627c79db971 159 case MAD_FLOW_CONTINUE:
Gruenfrosch 0:7627c79db971 160 break;
Gruenfrosch 0:7627c79db971 161 }
Gruenfrosch 0:7627c79db971 162
Gruenfrosch 0:7627c79db971 163 while (1) {
Gruenfrosch 0:7627c79db971 164 if (decoder->header_func) {
Gruenfrosch 0:7627c79db971 165 if (mad_header_decode(&frame->header, stream) == -1) {
Gruenfrosch 0:7627c79db971 166 if (!MAD_RECOVERABLE(stream->error))
Gruenfrosch 0:7627c79db971 167 break;
Gruenfrosch 0:7627c79db971 168
Gruenfrosch 0:7627c79db971 169 switch (error_func(error_data, stream, frame)) {
Gruenfrosch 0:7627c79db971 170 case MAD_FLOW_STOP:
Gruenfrosch 0:7627c79db971 171 goto done;
Gruenfrosch 0:7627c79db971 172 case MAD_FLOW_BREAK:
Gruenfrosch 0:7627c79db971 173 goto fail;
Gruenfrosch 0:7627c79db971 174 case MAD_FLOW_IGNORE:
Gruenfrosch 0:7627c79db971 175 case MAD_FLOW_CONTINUE:
Gruenfrosch 0:7627c79db971 176 default:
Gruenfrosch 0:7627c79db971 177 continue;
Gruenfrosch 0:7627c79db971 178 }
Gruenfrosch 0:7627c79db971 179 }
Gruenfrosch 0:7627c79db971 180
Gruenfrosch 0:7627c79db971 181 switch (decoder->header_func(decoder->cb_data, &frame->header)) {
Gruenfrosch 0:7627c79db971 182 case MAD_FLOW_STOP:
Gruenfrosch 0:7627c79db971 183 goto done;
Gruenfrosch 0:7627c79db971 184 case MAD_FLOW_BREAK:
Gruenfrosch 0:7627c79db971 185 goto fail;
Gruenfrosch 0:7627c79db971 186 case MAD_FLOW_IGNORE:
Gruenfrosch 0:7627c79db971 187 continue;
Gruenfrosch 0:7627c79db971 188 case MAD_FLOW_CONTINUE:
Gruenfrosch 0:7627c79db971 189 break;
Gruenfrosch 0:7627c79db971 190 }
Gruenfrosch 0:7627c79db971 191 }
Gruenfrosch 0:7627c79db971 192
Gruenfrosch 0:7627c79db971 193 if (mad_frame_decode(frame, stream) == -1) {
Gruenfrosch 0:7627c79db971 194 if (!MAD_RECOVERABLE(stream->error))
Gruenfrosch 0:7627c79db971 195 break;
Gruenfrosch 0:7627c79db971 196
Gruenfrosch 0:7627c79db971 197 switch (error_func(error_data, stream, frame)) {
Gruenfrosch 0:7627c79db971 198 case MAD_FLOW_STOP:
Gruenfrosch 0:7627c79db971 199 goto done;
Gruenfrosch 0:7627c79db971 200 case MAD_FLOW_BREAK:
Gruenfrosch 0:7627c79db971 201 goto fail;
Gruenfrosch 0:7627c79db971 202 case MAD_FLOW_IGNORE:
Gruenfrosch 0:7627c79db971 203 break;
Gruenfrosch 0:7627c79db971 204 case MAD_FLOW_CONTINUE:
Gruenfrosch 0:7627c79db971 205 default:
Gruenfrosch 0:7627c79db971 206 continue;
Gruenfrosch 0:7627c79db971 207 }
Gruenfrosch 0:7627c79db971 208 }
Gruenfrosch 0:7627c79db971 209 else
Gruenfrosch 0:7627c79db971 210 bad_last_frame = 0;
Gruenfrosch 0:7627c79db971 211
Gruenfrosch 0:7627c79db971 212 if (decoder->filter_func) {
Gruenfrosch 0:7627c79db971 213 switch (decoder->filter_func(decoder->cb_data, stream, frame)) {
Gruenfrosch 0:7627c79db971 214 case MAD_FLOW_STOP:
Gruenfrosch 0:7627c79db971 215 goto done;
Gruenfrosch 0:7627c79db971 216 case MAD_FLOW_BREAK:
Gruenfrosch 0:7627c79db971 217 goto fail;
Gruenfrosch 0:7627c79db971 218 case MAD_FLOW_IGNORE:
Gruenfrosch 0:7627c79db971 219 continue;
Gruenfrosch 0:7627c79db971 220 case MAD_FLOW_CONTINUE:
Gruenfrosch 0:7627c79db971 221 break;
Gruenfrosch 0:7627c79db971 222 }
Gruenfrosch 0:7627c79db971 223 }
Gruenfrosch 0:7627c79db971 224
Gruenfrosch 0:7627c79db971 225 mad_synth_frame(synth, frame);
Gruenfrosch 0:7627c79db971 226
Gruenfrosch 0:7627c79db971 227 if (decoder->output_func) {
Gruenfrosch 0:7627c79db971 228 switch (decoder->output_func(decoder->cb_data,
Gruenfrosch 0:7627c79db971 229 &frame->header, &synth->pcm)) {
Gruenfrosch 0:7627c79db971 230 case MAD_FLOW_STOP:
Gruenfrosch 0:7627c79db971 231 goto done;
Gruenfrosch 0:7627c79db971 232 case MAD_FLOW_BREAK:
Gruenfrosch 0:7627c79db971 233 goto fail;
Gruenfrosch 0:7627c79db971 234 case MAD_FLOW_IGNORE:
Gruenfrosch 0:7627c79db971 235 case MAD_FLOW_CONTINUE:
Gruenfrosch 0:7627c79db971 236 break;
Gruenfrosch 0:7627c79db971 237 }
Gruenfrosch 0:7627c79db971 238 }
Gruenfrosch 0:7627c79db971 239 }
Gruenfrosch 0:7627c79db971 240 }
Gruenfrosch 0:7627c79db971 241 while (stream->error == MAD_ERROR_BUFLEN);
Gruenfrosch 0:7627c79db971 242
Gruenfrosch 0:7627c79db971 243 fail:
Gruenfrosch 0:7627c79db971 244 result = -1;
Gruenfrosch 0:7627c79db971 245
Gruenfrosch 0:7627c79db971 246 done:
Gruenfrosch 0:7627c79db971 247 mad_synth_finish(synth);
Gruenfrosch 0:7627c79db971 248 mad_frame_finish(frame);
Gruenfrosch 0:7627c79db971 249 mad_stream_finish(stream);
Gruenfrosch 0:7627c79db971 250
Gruenfrosch 0:7627c79db971 251 return result;
Gruenfrosch 0:7627c79db971 252 }
Gruenfrosch 0:7627c79db971 253
Gruenfrosch 0:7627c79db971 254
Gruenfrosch 0:7627c79db971 255 /*
Gruenfrosch 0:7627c79db971 256 * NAME: decoder->run()
Gruenfrosch 0:7627c79db971 257 * DESCRIPTION: run the decoder thread either synchronously or asynchronously
Gruenfrosch 0:7627c79db971 258 */
Gruenfrosch 0:7627c79db971 259 int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode)
Gruenfrosch 0:7627c79db971 260 {
Gruenfrosch 0:7627c79db971 261 int result;
Gruenfrosch 0:7627c79db971 262 int (*run)(struct mad_decoder *) = 0;
Gruenfrosch 0:7627c79db971 263
Gruenfrosch 0:7627c79db971 264 switch (decoder->mode = mode) {
Gruenfrosch 0:7627c79db971 265 case MAD_DECODER_MODE_SYNC:
Gruenfrosch 0:7627c79db971 266 run = run_sync;
Gruenfrosch 0:7627c79db971 267 break;
Gruenfrosch 0:7627c79db971 268
Gruenfrosch 0:7627c79db971 269 case MAD_DECODER_MODE_ASYNC:
Gruenfrosch 0:7627c79db971 270 break;
Gruenfrosch 0:7627c79db971 271 }
Gruenfrosch 0:7627c79db971 272
Gruenfrosch 0:7627c79db971 273 if (run == 0)
Gruenfrosch 0:7627c79db971 274 return -1;
Gruenfrosch 2:f28cf0afd021 275 // static struct mad_sync_s sync_mem;
Gruenfrosch 0:7627c79db971 276 decoder->sync = (struct mad_sync_s *)malloc(sizeof(*decoder->sync));
Gruenfrosch 2:f28cf0afd021 277 #if defined(TARGET_LPC1768)
Gruenfrosch 2:f28cf0afd021 278 decoder->sync->synth = (struct mad_synth *)mad_malloc(sizeof(struct mad_synth));
Gruenfrosch 2:f28cf0afd021 279 #else
Gruenfrosch 2:f28cf0afd021 280 decoder->sync->synth = (struct mad_synth *)malloc(sizeof(struct mad_synth));
Gruenfrosch 2:f28cf0afd021 281 #endif
Gruenfrosch 0:7627c79db971 282 if (decoder->sync == 0)
Gruenfrosch 0:7627c79db971 283 return -1;
Gruenfrosch 0:7627c79db971 284
Gruenfrosch 0:7627c79db971 285 result = run(decoder);
Gruenfrosch 2:f28cf0afd021 286 #if !defined(TARGET_LPC1768)
Gruenfrosch 2:f28cf0afd021 287 free(decoder->sync->synth);
Gruenfrosch 2:f28cf0afd021 288 #endif
Gruenfrosch 0:7627c79db971 289 free(decoder->sync);
Gruenfrosch 0:7627c79db971 290 decoder->sync = 0;
Gruenfrosch 2:f28cf0afd021 291 reset_ahb_mem();
Gruenfrosch 0:7627c79db971 292 return result;
Gruenfrosch 0:7627c79db971 293 }
Gruenfrosch 0:7627c79db971 294
Gruenfrosch 0:7627c79db971 295 /*
Gruenfrosch 0:7627c79db971 296 * NAME: decoder->message()
Gruenfrosch 0:7627c79db971 297 * DESCRIPTION: send a message to and receive a reply from the decoder process
Gruenfrosch 0:7627c79db971 298 */
Gruenfrosch 0:7627c79db971 299 int mad_decoder_message(struct mad_decoder *decoder,
Gruenfrosch 0:7627c79db971 300 void *message, unsigned int *len)
Gruenfrosch 0:7627c79db971 301 {
Gruenfrosch 0:7627c79db971 302 return -1;
Gruenfrosch 0:7627c79db971 303 }