Enable ReplayGain processing for AAC and ALAC (not really tested though). Also, use...
[Rockbox.git] / apps / codecs / aac.c
bloba2248c6437fb512cb70e336a89f17087df9e8f85
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Dave Chapman
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "codeclib.h"
21 #include "libm4a/m4a.h"
22 #include "libfaad/common.h"
23 #include "libfaad/structs.h"
24 #include "libfaad/decoder.h"
26 CODEC_HEADER
28 #ifndef SIMULATOR
29 extern char iramcopy[];
30 extern char iramstart[];
31 extern char iramend[];
32 extern char iedata[];
33 extern char iend[];
34 #endif
36 struct codec_api* rb;
37 struct codec_api* ci;
39 /* this is the codec entry point */
40 enum codec_status codec_start(struct codec_api* api)
42 /* Note that when dealing with QuickTime/MPEG4 files, terminology is
43 * a bit confusing. Files with sound are split up in chunks, where
44 * each chunk contains one or more samples. Each sample in turn
45 * contains a number of "sound samples" (the kind you refer to with
46 * the sampling frequency).
48 size_t n;
49 static demux_res_t demux_res;
50 stream_t input_stream;
51 uint32_t sound_samples_done;
52 uint32_t elapsed_time;
53 uint32_t sample_duration;
54 uint32_t sample_byte_size;
55 int file_offset;
56 unsigned int i;
57 unsigned char* buffer;
58 static NeAACDecFrameInfo frame_info;
59 NeAACDecHandle decoder;
60 int err;
61 uint32_t s = 0;
62 unsigned char c = 0;
64 /* Generic codec initialisation */
65 rb = api;
66 ci = api;
68 #ifndef SIMULATOR
69 ci->memcpy(iramstart, iramcopy, iramend-iramstart);
70 ci->memset(iedata, 0, iend - iedata);
71 #endif
73 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
74 ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
76 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
77 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(29));
79 next_track:
80 err = CODEC_OK;
82 if (codec_init(api)) {
83 LOGF("FAAD: Codec init error\n");
84 err = CODEC_ERROR;
85 goto exit;
88 while (!*ci->taginfo_ready && !ci->stop_codec)
89 ci->sleep(1);
91 sound_samples_done = ci->id3->offset;
93 ci->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency));
94 codec_set_replaygain(rb->id3);
96 stream_create(&input_stream,ci);
98 /* if qtmovie_read returns successfully, the stream is up to
99 * the movie data, which can be used directly by the decoder */
100 if (!qtmovie_read(&input_stream, &demux_res)) {
101 LOGF("FAAD: File init error\n");
102 err = CODEC_ERROR;
103 goto done;
106 /* initialise the sound converter */
107 decoder = NeAACDecOpen();
109 if (!decoder) {
110 LOGF("FAAD: Decode open error\n");
111 err = CODEC_ERROR;
112 goto done;
115 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
116 conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
117 NeAACDecSetConfiguration(decoder, conf);
119 err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c);
120 if (err) {
121 LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
122 err = CODEC_ERROR;
123 goto done;
126 ci->id3->frequency = s;
128 i = 0;
130 if (sound_samples_done > 0) {
131 if (alac_seek_raw(&demux_res, &input_stream, sound_samples_done,
132 &sound_samples_done, (int*) &i)) {
133 elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
134 ci->set_elapsed(elapsed_time);
135 } else {
136 sound_samples_done = 0;
140 /* The main decoding loop */
141 while (i < demux_res.num_sample_byte_sizes) {
142 rb->yield();
144 if (ci->stop_codec || ci->new_track) {
145 break;
148 /* Deal with any pending seek requests */
149 if (ci->seek_time) {
150 if (alac_seek(&demux_res, &input_stream,
151 ((ci->seek_time-1)/10)*(ci->id3->frequency/100),
152 &sound_samples_done, (int*) &i)) {
153 elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
154 ci->set_elapsed(elapsed_time);
156 ci->seek_complete();
159 /* Lookup the length (in samples and bytes) of block i */
160 if (!get_sample_info(&demux_res, i, &sample_duration,
161 &sample_byte_size)) {
162 LOGF("AAC: get_sample_info error\n");
163 err = CODEC_ERROR;
164 goto done;
167 /* There can be gaps between chunks, so skip ahead if needed. It
168 * doesn't seem to happen much, but it probably means that a
169 * "proper" file can have chunks out of order. Why one would want
170 * that an good question (but files with gaps do exist, so who
171 * knows?), so we don't support that - for now, at least.
173 file_offset = get_sample_offset(&demux_res, i);
175 if (file_offset > ci->curpos)
177 ci->advance_buffer(file_offset - ci->curpos);
180 /* Request the required number of bytes from the input buffer */
181 buffer=ci->request_buffer(&n,sample_byte_size);
183 /* Decode one block - returned samples will be host-endian */
184 NeAACDecDecode(decoder, &frame_info, buffer, n);
185 /* Ignore return value, we access samples in the decoder struct
186 * directly.
188 if (frame_info.error > 0) {
189 LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
190 err = CODEC_ERROR;
191 goto done;
194 /* Advance codec buffer */
195 ci->advance_buffer(n);
197 /* Output the audio */
198 rb->yield();
199 while (!rb->pcmbuf_insert_split(decoder->time_out[0],
200 decoder->time_out[1],
201 frame_info.samples * 2))
203 rb->sleep(1);
206 /* Update the elapsed-time indicator */
207 sound_samples_done += sample_duration;
208 elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
209 ci->set_elapsed(elapsed_time);
211 /* Keep track of current position - for resuming */
212 ci->set_offset(elapsed_time);
214 i++;
217 err = CODEC_OK;
219 done:
220 LOGF("AAC: Decoded %d samples, %d frames\n", sound_samples_done);
222 if (ci->request_next_track())
223 goto next_track;
225 exit:
226 return err;