Fix red by moving fsincos back to libwma
[kugel-rb.git] / apps / codecs / raac.c
blob2f3635a8acb7b54aad4a7fb51dfe3ebc4dea59b8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "codeclib.h"
23 #include "librm/rm.h"
24 #include "libfaad/common.h"
25 #include "libfaad/structs.h"
26 #include "libfaad/decoder.h"
27 #include "libfaad/output.h"
29 CODEC_HEADER
31 static void init_rm(RMContext *rmctx)
33 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
36 RMContext rmctx;
37 RMPacket pkt;
38 /* this is the codec entry point */
39 enum codec_status codec_main(void)
41 static NeAACDecFrameInfo frame_info;
42 NeAACDecHandle decoder;
43 size_t n;
44 int32_t *output;
45 unsigned int i;
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 int playback_on = -1;
51 size_t resume_offset = ci->id3->offset;
53 /* Generic codec initialisation */
54 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
55 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
57 next_track:
58 err = CODEC_OK;
60 if (codec_init()) {
61 DEBUGF("FAAD: Codec init error\n");
62 return CODEC_ERROR;
65 while (!*ci->taginfo_ready && !ci->stop_codec)
66 ci->sleep(1);
68 ci->memset(&rmctx,0,sizeof(RMContext));
69 ci->memset(&pkt,0,sizeof(RMPacket));
70 init_rm(&rmctx);
71 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
72 codec_set_replaygain(ci->id3);
74 /* initialise the sound converter */
75 decoder = NeAACDecOpen();
77 if (!decoder) {
78 DEBUGF("FAAD: Decode open error\n");
79 err = CODEC_ERROR;
80 goto done;
82 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
83 conf->outputFormat = FAAD_FMT_16BIT;
84 NeAACDecSetConfiguration(decoder, conf);
86 decoder->config.defObjectType = rmctx.codec_extradata[0];
87 decoder->config.defSampleRate = rmctx.sample_rate;
88 err = NeAACDecInit(decoder, NULL, 0, &s, &c);
90 if (err) {
91 DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
92 err = CODEC_ERROR;
93 goto done;
96 /* check for a mid-track resume and force a seek time accordingly */
97 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
98 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
99 /* put number of subpackets to skip in resume_offset */
100 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
101 ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
104 ci->id3->frequency = s;
105 ci->set_elapsed(0);
106 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
108 /* The main decoding loop */
109 seek_start:
110 while (1) {
111 ci->yield();
112 if (ci->stop_codec || ci->new_track) {
113 break;
116 if (ci->seek_time) {
118 /* Do not allow seeking beyond the file's length */
119 if ((unsigned) ci->seek_time > ci->id3->length) {
120 ci->seek_complete();
121 goto done;
124 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
126 /* Seek to the start of the track */
127 if (ci->seek_time == 1) {
128 ci->set_elapsed(0);
129 ci->seek_complete();
130 goto seek_start;
133 skipped = 0;
134 while(1) {
135 buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
136 pkt_offset = skipped - pkt.length;
137 consumed = rm_get_packet(&buffer, &rmctx, &pkt);
138 if(consumed < 0 && playback_on != 0) {
139 if(playback_on == -1) {
140 /* Error only if packet-parsing failed and playback hadn't started */
141 DEBUGF("rm_get_packet failed\n");
142 return CODEC_ERROR;
144 else
145 goto done;
147 skipped += pkt.length;
148 if(pkt.timestamp > (unsigned)ci->seek_time) break;
149 ci->advance_buffer(pkt.length);
151 ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE);
152 buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
153 ci->seek_complete();
156 /* Request the required number of bytes from the input buffer */
157 buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000);
158 consumed = rm_get_packet(&buffer, &rmctx, &pkt);
160 if(consumed < 0 && playback_on != 0) {
161 if(playback_on == -1) {
162 /* Error only if packet-parsing failed and playback hadn't started */
163 DEBUGF("rm_get_packet failed\n");
164 return CODEC_ERROR;
166 else
167 goto done;
170 playback_on = 1;
171 if (pkt.timestamp >= ci->id3->length)
172 goto done;
173 /* Decode one block - returned samples will be host-endian */
174 for(i = 0; i < rmctx.sub_packet_cnt; i++) {
175 output = (int32_t *)NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]);
176 buffer += rmctx.sub_packet_lengths[i];
177 if (frame_info.error > 0) {
178 DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
179 err = CODEC_ERROR;
180 goto exit;
182 output = (int32_t *) output_to_PCM(decoder, decoder->time_out, output,
183 rmctx.nb_channels, decoder->frameLength, decoder->config.outputFormat);
184 ci->pcmbuf_insert(output, NULL, frame_info.samples/rmctx.nb_channels);
185 ci->set_elapsed(pkt.timestamp);
188 ci->advance_buffer(pkt.length);
191 err = CODEC_OK;
193 done:
194 if (ci->request_next_track())
195 goto next_track;
197 exit:
198 return err;