autodetection: convert path to native separators before displaying it.
[Rockbox.git] / apps / codecs / a52.c
blob6cdddb5213b0f8449fe2250a87256ce7f9d6cd13
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 <inttypes.h> /* Needed by a52.h */
22 #include <codecs/liba52/config-a52.h>
23 #include <codecs/liba52/a52.h>
25 CODEC_HEADER
27 #define BUFFER_SIZE 4096
29 #define A52_SAMPLESPERFRAME (6*256)
31 static a52_state_t *state;
32 unsigned long samplesdone;
33 unsigned long frequency;
35 /* used outside liba52 */
36 static uint8_t buf[3840] IBSS_ATTR;
38 static inline void output_audio(sample_t *samples)
40 ci->yield();
41 ci->pcmbuf_insert(&samples[0], &samples[256], 256);
44 void a52_decode_data(uint8_t *start, uint8_t *end)
46 static uint8_t *bufptr = buf;
47 static uint8_t *bufpos = buf + 7;
49 * sample_rate and flags are static because this routine could
50 * exit between the a52_syncinfo() and the ao_setup(), and we want
51 * to have the same values when we get back !
53 static int sample_rate;
54 static int flags;
55 int bit_rate;
56 int len;
58 while (1) {
59 len = end - start;
60 if (!len)
61 break;
62 if (len > bufpos - bufptr)
63 len = bufpos - bufptr;
64 memcpy(bufptr, start, len);
65 bufptr += len;
66 start += len;
67 if (bufptr == bufpos) {
68 if (bufpos == buf + 7) {
69 int length;
71 length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
72 if (!length) {
73 //DEBUGF("skip\n");
74 for (bufptr = buf; bufptr < buf + 6; bufptr++)
75 bufptr[0] = bufptr[1];
76 continue;
78 bufpos = buf + length;
79 } else {
80 /* Unity gain is 1 << 26, and we want to end up on 28 bits
81 of precision instead of the default 30.
83 level_t level = 1 << 24;
84 sample_t bias = 0;
85 int i;
87 /* This is the configuration for the downmixing: */
88 flags = A52_STEREO | A52_ADJUST_LEVEL;
90 if (a52_frame(state, buf, &flags, &level, bias))
91 goto error;
92 a52_dynrng(state, NULL, NULL);
93 frequency = sample_rate;
95 /* An A52 frame consists of 6 blocks of 256 samples
96 So we decode and output them one block at a time */
97 for (i = 0; i < 6; i++) {
98 if (a52_block(state))
99 goto error;
100 output_audio(a52_samples(state));
101 samplesdone += 256;
103 ci->set_elapsed(samplesdone/(frequency/1000));
104 bufptr = buf;
105 bufpos = buf + 7;
106 continue;
107 error:
108 //logf("Error decoding A52 stream\n");
109 bufptr = buf;
110 bufpos = buf + 7;
116 /* this is the codec entry point */
117 enum codec_status codec_main(void)
119 size_t n;
120 unsigned char *filebuf;
121 int sample_loc;
122 int retval;
124 /* Generic codec initialisation */
125 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
126 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
128 next_track:
129 if (codec_init()) {
130 retval = CODEC_ERROR;
131 goto exit;
134 while (!ci->taginfo_ready)
135 ci->yield();
137 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
138 codec_set_replaygain(ci->id3);
140 /* Intialise the A52 decoder and check for success */
141 state = a52_init(0);
143 /* The main decoding loop */
144 if (ci->id3->offset) {
145 if (ci->seek_buffer(ci->id3->offset)) {
146 samplesdone = (ci->id3->offset / ci->id3->bytesperframe) *
147 A52_SAMPLESPERFRAME;
148 ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000));
151 else {
152 samplesdone = 0;
155 while (1) {
156 if (ci->stop_codec || ci->new_track)
157 break;
159 if (ci->seek_time) {
160 sample_loc = (ci->seek_time - 1)/1000 * ci->id3->frequency;
162 if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
163 samplesdone = sample_loc;
164 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
166 ci->seek_complete();
169 filebuf = ci->request_buffer(&n, BUFFER_SIZE);
171 if (n == 0) /* End of Stream */
172 break;
174 a52_decode_data(filebuf, filebuf + n);
175 ci->advance_buffer(n);
177 retval = CODEC_OK;
179 if (ci->request_next_track())
180 goto next_track;
182 exit:
183 a52_free(state);
184 return retval;