1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 Mohamed Tarek
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
24 #include "libfaad/common.h"
25 #include "libfaad/structs.h"
26 #include "libfaad/decoder.h"
27 #include "libfaad/output.h"
31 static void init_rm(RMContext
*rmctx
)
33 memcpy(rmctx
, (void*)(( (intptr_t)ci
->id3
->id3v2buf
+ 3 ) &~ 3), sizeof(RMContext
));
38 /* this is the codec entry point */
39 enum codec_status
codec_main(void)
41 static NeAACDecFrameInfo frame_info
;
42 NeAACDecHandle decoder
;
46 unsigned char* buffer
;
47 int err
, consumed
, pkt_offset
, skipped
= 0;
48 uint32_t s
= 0; /* sample rate */
49 unsigned char c
= 0; /* channels */
50 /* Generic codec initialisation */
51 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_INTERLEAVED
);
52 ci
->configure(DSP_SET_SAMPLE_DEPTH
, 16);
58 DEBUGF("FAAD: Codec init error\n");
62 while (!*ci
->taginfo_ready
&& !ci
->stop_codec
)
65 ci
->memset(&rmctx
,0,sizeof(RMContext
));
66 ci
->memset(&pkt
,0,sizeof(RMPacket
));
68 ci
->configure(DSP_SWITCH_FREQUENCY
, ci
->id3
->frequency
);
69 codec_set_replaygain(ci
->id3
);
71 /* initialise the sound converter */
72 decoder
= NeAACDecOpen();
75 DEBUGF("FAAD: Decode open error\n");
79 NeAACDecConfigurationPtr conf
= NeAACDecGetCurrentConfiguration(decoder
);
80 conf
->outputFormat
= FAAD_FMT_16BIT
;
81 NeAACDecSetConfiguration(decoder
, conf
);
83 decoder
->config
.defObjectType
= rmctx
.codec_extradata
[0];
84 decoder
->config
.defSampleRate
= rmctx
.sample_rate
;
85 err
= NeAACDecInit(decoder
, NULL
, 0, &s
, &c
);
88 DEBUGF("FAAD: DecInit: %d, %d\n", err
, decoder
->object_type
);
92 ci
->id3
->frequency
= s
;
94 ci
->advance_buffer(rmctx
.data_offset
+ DATA_HEADER_SIZE
);
96 /* The main decoding loop */
100 if (ci
->stop_codec
|| ci
->new_track
) {
106 /* Do not allow seeking beyond the file's length */
107 if ((unsigned) ci
->seek_time
> ci
->id3
->length
) {
112 ci
->seek_buffer(rmctx
.data_offset
+ DATA_HEADER_SIZE
);
114 /* Seek to the start of the track */
115 if (ci
->seek_time
== 1) {
123 buffer
= ci
->request_buffer(&n
,rmctx
.audio_framesize
+ 1000);
124 pkt_offset
= skipped
- pkt
.length
;
125 consumed
= rm_get_packet(&buffer
, &rmctx
, &pkt
);
127 DEBUGF("rm_get_packet failed\n");
130 skipped
+= pkt
.length
;
131 if(pkt
.timestamp
> (unsigned)ci
->seek_time
) break;
132 ci
->advance_buffer(pkt
.length
);
134 ci
->seek_buffer(pkt_offset
+ rmctx
.data_offset
+ DATA_HEADER_SIZE
);
135 buffer
= ci
->request_buffer(&n
,rmctx
.audio_framesize
+ 1000);
139 /* Request the required number of bytes from the input buffer */
140 buffer
=ci
->request_buffer(&n
,rmctx
.audio_framesize
+ 1000);
141 consumed
= rm_get_packet(&buffer
, &rmctx
, &pkt
);
143 DEBUGF("rm_get_packet failed\n");
147 if (pkt
.timestamp
>= ci
->id3
->length
)
149 /* Decode one block - returned samples will be host-endian */
150 for(i
= 0; i
< rmctx
.sub_packet_cnt
; i
++) {
151 output
= (int32_t *)NeAACDecDecode(decoder
, &frame_info
, buffer
, rmctx
.sub_packet_lengths
[i
]);
152 buffer
+= rmctx
.sub_packet_lengths
[i
];
153 if (frame_info
.error
> 0) {
154 DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info
.error
));
158 output
= (int32_t *) output_to_PCM(decoder
, decoder
->time_out
, output
,
159 rmctx
.nb_channels
, decoder
->frameLength
, decoder
->config
.outputFormat
);
160 ci
->pcmbuf_insert(output
, NULL
, frame_info
.samples
/rmctx
.nb_channels
);
161 ci
->set_elapsed(pkt
.timestamp
);
164 ci
->advance_buffer(pkt
.length
);
170 if (ci
->request_next_track())