1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Dave Chapman
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 ****************************************************************************/
23 #include <inttypes.h> /* Needed by a52.h */
24 #include <codecs/liba52/config-a52.h>
25 #include <codecs/liba52/a52.h>
29 #define BUFFER_SIZE 4096
31 #define A52_SAMPLESPERFRAME (6*256)
33 static a52_state_t
*state
;
34 static unsigned long samplesdone
;
35 static unsigned long frequency
;
37 /* used outside liba52 */
38 static uint8_t buf
[3840] IBSS_ATTR
;
40 static inline void output_audio(sample_t
*samples
)
43 ci
->pcmbuf_insert(&samples
[0], &samples
[256], 256);
46 static void a52_decode_data(uint8_t *start
, uint8_t *end
)
48 static uint8_t *bufptr
= buf
;
49 static uint8_t *bufpos
= buf
+ 7;
51 * sample_rate and flags are static because this routine could
52 * exit between the a52_syncinfo() and the ao_setup(), and we want
53 * to have the same values when we get back !
55 static int sample_rate
;
64 if (len
> bufpos
- bufptr
)
65 len
= bufpos
- bufptr
;
66 memcpy(bufptr
, start
, len
);
69 if (bufptr
== bufpos
) {
70 if (bufpos
== buf
+ 7) {
73 length
= a52_syncinfo(buf
, &flags
, &sample_rate
, &bit_rate
);
76 for (bufptr
= buf
; bufptr
< buf
+ 6; bufptr
++)
77 bufptr
[0] = bufptr
[1];
80 bufpos
= buf
+ length
;
82 /* Unity gain is 1 << 26, and we want to end up on 28 bits
83 of precision instead of the default 30.
85 level_t level
= 1 << 24;
89 /* This is the configuration for the downmixing: */
90 flags
= A52_STEREO
| A52_ADJUST_LEVEL
;
92 if (a52_frame(state
, buf
, &flags
, &level
, bias
))
94 a52_dynrng(state
, NULL
, NULL
);
95 frequency
= sample_rate
;
97 /* An A52 frame consists of 6 blocks of 256 samples
98 So we decode and output them one block at a time */
99 for (i
= 0; i
< 6; i
++) {
100 if (a52_block(state
))
102 output_audio(a52_samples(state
));
105 ci
->set_elapsed(samplesdone
/(frequency
/1000));
110 //logf("Error decoding A52 stream\n");
118 /* this is the codec entry point */
119 enum codec_status
codec_main(enum codec_entry_call_reason reason
)
121 if (reason
== CODEC_LOAD
) {
122 /* Generic codec initialisation */
123 ci
->configure(DSP_SET_STEREO_MODE
, STEREO_NONINTERLEAVED
);
124 ci
->configure(DSP_SET_SAMPLE_DEPTH
, 28);
126 else if (reason
== CODEC_UNLOAD
) {
134 /* this is called for each file to process */
135 enum codec_status
codec_run(void)
138 unsigned char *filebuf
;
145 ci
->configure(DSP_SWITCH_FREQUENCY
, ci
->id3
->frequency
);
146 codec_set_replaygain(ci
->id3
);
148 /* Intialise the A52 decoder and check for success */
151 /* The main decoding loop */
152 if (ci
->id3
->offset
) {
153 if (ci
->seek_buffer(ci
->id3
->offset
)) {
154 samplesdone
= (ci
->id3
->offset
/ ci
->id3
->bytesperframe
) *
156 ci
->set_elapsed(samplesdone
/(ci
->id3
->frequency
/ 1000));
160 ci
->seek_buffer(ci
->id3
->first_frame_offset
);
165 enum codec_command_action action
= ci
->get_command(¶m
);
167 if (action
== CODEC_ACTION_HALT
)
170 if (action
== CODEC_ACTION_SEEK_TIME
) {
171 sample_loc
= param
/1000 * ci
->id3
->frequency
;
173 if (ci
->seek_buffer((sample_loc
/A52_SAMPLESPERFRAME
)*ci
->id3
->bytesperframe
)) {
174 samplesdone
= sample_loc
;
175 ci
->set_elapsed(samplesdone
/(ci
->id3
->frequency
/1000));
180 filebuf
= ci
->request_buffer(&n
, BUFFER_SIZE
);
182 if (n
== 0) /* End of Stream */
185 a52_decode_data(filebuf
, filebuf
+ n
);
186 ci
->advance_buffer(n
);