Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2005 Dave Chapman |
| 11 | * |
| 12 | * All files in this archive are subject to the GNU General Public License. |
| 13 | * See the file COPYING in the source tree root for full license agreement. |
| 14 | * |
| 15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 16 | * KIND, either express or implied. |
| 17 | * |
| 18 | ****************************************************************************/ |
| 19 | |
| 20 | #include "codeclib.h" |
| 21 | #include "libm4a/m4a.h" |
| 22 | #include "libfaad/common.h" |
| 23 | #include "libfaad/structs.h" |
| 24 | #include "libfaad/decoder.h" |
| 25 | |
Jens Arnold | b8749fd | 2006-01-18 00:05:14 +0000 | [diff] [blame] | 26 | CODEC_HEADER |
| 27 | |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 28 | #ifndef SIMULATOR |
| 29 | extern char iramcopy[]; |
| 30 | extern char iramstart[]; |
| 31 | extern char iramend[]; |
| 32 | #endif |
| 33 | |
| 34 | struct codec_api* rb; |
| 35 | struct codec_api* ci; |
| 36 | |
| 37 | /* this is the codec entry point */ |
| 38 | enum codec_status codec_start(struct codec_api* api) |
| 39 | { |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 40 | size_t n; |
| 41 | static demux_res_t demux_res; |
| 42 | stream_t input_stream; |
| 43 | uint32_t samplesdone; |
| 44 | uint32_t elapsedtime; |
| 45 | uint32_t sample_duration; |
| 46 | uint32_t sample_byte_size; |
| 47 | int samplesdecoded; |
| 48 | unsigned int i; |
| 49 | unsigned char* buffer; |
| 50 | static NeAACDecFrameInfo frameInfo; |
| 51 | NeAACDecHandle hDecoder; |
| 52 | int err; |
| 53 | int16_t* decodedbuffer; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 54 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 55 | /* Generic codec initialisation */ |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 56 | rb = api; |
Jens Arnold | b8749fd | 2006-01-18 00:05:14 +0000 | [diff] [blame] | 57 | ci = api; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 58 | |
| 59 | #ifndef SIMULATOR |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 60 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 61 | #endif |
| 62 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 63 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); |
| 64 | ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 65 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 66 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); |
| 67 | ci->configure(DSP_DITHER, (bool *)false); |
Thom Johansen | 0263ece | 2005-11-02 19:43:52 +0000 | [diff] [blame] | 68 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); |
| 69 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(29)); |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 70 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 71 | next_track: |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 72 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 73 | if (codec_init(api)) { |
| 74 | LOGF("FAAD: Error initialising codec\n"); |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 75 | err = CODEC_ERROR; |
| 76 | goto exit; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 79 | while (!rb->taginfo_ready) |
| 80 | rb->yield(); |
| 81 | |
| 82 | ci->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); |
| 83 | |
| 84 | stream_create(&input_stream,ci); |
| 85 | |
| 86 | /* if qtmovie_read returns successfully, the stream is up to |
| 87 | * the movie data, which can be used directly by the decoder */ |
| 88 | if (!qtmovie_read(&input_stream, &demux_res)) { |
| 89 | LOGF("FAAD: Error initialising file\n"); |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 90 | err = CODEC_ERROR; |
| 91 | goto exit; |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | /* initialise the sound converter */ |
| 95 | hDecoder = NULL; |
| 96 | hDecoder = NeAACDecOpen(); |
| 97 | |
| 98 | if (!hDecoder) { |
| 99 | LOGF("FAAD: Error opening decoder\n"); |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 100 | err = CODEC_ERROR; |
| 101 | goto exit; |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(hDecoder); |
Thom Johansen | 0263ece | 2005-11-02 19:43:52 +0000 | [diff] [blame] | 105 | conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */ |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 106 | NeAACDecSetConfiguration(hDecoder, conf); |
| 107 | |
| 108 | unsigned long s=0; |
| 109 | unsigned char c=0; |
| 110 | |
| 111 | err = NeAACDecInit2(hDecoder, demux_res.codecdata,demux_res.codecdata_len, &s, &c); |
| 112 | if (err) { |
| 113 | LOGF("FAAD: Error initialising decoder: %d, type=%d\n", err,hDecoder->object_type); |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 114 | err = CODEC_ERROR; |
| 115 | goto exit; |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | ci->id3->frequency=s; |
| 119 | |
| 120 | i=0; |
| 121 | samplesdone=0; |
| 122 | /* The main decoding loop */ |
| 123 | while (i < demux_res.num_sample_byte_sizes) { |
| 124 | rb->yield(); |
| 125 | if (ci->stop_codec || ci->reload_codec) { |
| 126 | break; |
| 127 | } |
| 128 | |
| 129 | /* Deal with any pending seek requests */ |
| 130 | if (ci->seek_time) { |
Daniel Stenberg | 76667e2 | 2005-12-02 08:42:48 +0000 | [diff] [blame] | 131 | if (alac_seek(&demux_res, &input_stream, |
Thom Johansen | c8193b8 | 2005-11-06 19:18:04 +0000 | [diff] [blame] | 132 | ((ci->seek_time-1)/10) * (ci->id3->frequency/100), |
Daniel Stenberg | 76667e2 | 2005-12-02 08:42:48 +0000 | [diff] [blame] | 133 | &samplesdone, (int *)&i)) { |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 134 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); |
| 135 | ci->set_elapsed(elapsedtime); |
| 136 | } |
Dave Chapman | 5006d15 | 2005-11-02 00:09:42 +0000 | [diff] [blame] | 137 | ci->seek_complete(); |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | /* Lookup the length (in samples and bytes) of block i */ |
| 141 | if (!get_sample_info(&demux_res, i, &sample_duration, |
| 142 | &sample_byte_size)) { |
| 143 | LOGF("AAC: Error in get_sample_info\n"); |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 144 | err = CODEC_ERROR; |
| 145 | goto exit; |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 146 | } |
| 147 | |
| 148 | /* Request the required number of bytes from the input buffer */ |
| 149 | buffer=ci->request_buffer((long*)&n,sample_byte_size); |
| 150 | |
| 151 | /* Decode one block - returned samples will be host-endian */ |
| 152 | rb->yield(); |
| 153 | decodedbuffer = NeAACDecDecode(hDecoder, &frameInfo, buffer, n); |
Thom Johansen | 0263ece | 2005-11-02 19:43:52 +0000 | [diff] [blame] | 154 | /* ignore decodedbuffer return value, we access samples in the |
| 155 | decoder struct directly */ |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 156 | if (frameInfo.error > 0) { |
| 157 | LOGF("FAAD: decoding error \"%s\"\n", NeAACDecGetErrorMessage(frameInfo.error)); |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 158 | err = CODEC_ERROR; |
| 159 | goto exit; |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | /* Get the number of decoded samples */ |
| 163 | samplesdecoded=frameInfo.samples; |
| 164 | |
| 165 | /* Advance codec buffer */ |
| 166 | ci->advance_buffer(n); |
| 167 | |
| 168 | /* Output the audio */ |
| 169 | rb->yield(); |
Thom Johansen | 0263ece | 2005-11-02 19:43:52 +0000 | [diff] [blame] | 170 | while (!rb->pcmbuf_insert_split(hDecoder->time_out[0], |
| 171 | hDecoder->time_out[1], |
| 172 | frameInfo.samples*2)) |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 173 | rb->yield(); |
| 174 | |
| 175 | /* Update the elapsed-time indicator */ |
| 176 | samplesdone+=sample_duration; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 177 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); |
| 178 | ci->set_elapsed(elapsedtime); |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 179 | |
| 180 | /* Keep track of current position - for resuming */ |
| 181 | ci->set_offset(elapsedtime); |
| 182 | |
| 183 | i++; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 184 | } |
| 185 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 186 | LOGF("AAC: Decoded %d samples\n",samplesdone); |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 187 | |
Dave Chapman | b08a942 | 2005-10-31 23:34:14 +0000 | [diff] [blame] | 188 | if (ci->request_next_track()) |
| 189 | goto next_track; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 190 | |
Brandon Low | 1060e44 | 2006-01-18 20:22:03 +0000 | [diff] [blame] | 191 | err = CODEC_OK; |
| 192 | exit: |
| 193 | return err; |
Dave Chapman | cea6d0c | 2005-10-31 20:56:29 +0000 | [diff] [blame] | 194 | } |