Separate out voice options for .talk clips (FS #7249). This removes the assumptions...
[Rockbox.git] / apps / codecs / ape.c
blobb77abc0c745bf4142f6cf2a07c423c5f06448829
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 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 #define ROCKBOX
22 #include <codecs/demac/libdemac/demac.h>
24 CODEC_HEADER
26 #define BLOCKS_PER_LOOP 4608
27 #define MAX_CHANNELS 2
28 #define MAX_BYTESPERSAMPLE 3
30 #define INPUT_CHUNKSIZE (32*1024)
32 /* 4608*4 = 18432 bytes per channel */
33 static int32_t decoded0[BLOCKS_PER_LOOP] IBSS_ATTR;
34 static int32_t decoded1[BLOCKS_PER_LOOP] IBSS_ATTR;
36 #define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
38 /* this is the codec entry point */
39 enum codec_status codec_main(void)
41 struct ape_ctx_t ape_ctx;
42 uint32_t samplesdone;
43 uint32_t elapsedtime;
44 size_t bytesleft;
45 int retval;
47 uint32_t currentframe;
48 int nblocks;
49 int bytesconsumed;
50 unsigned char* inbuffer;
51 int blockstodecode;
52 int res;
53 int firstbyte;
55 /* Generic codec initialisation */
56 ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
57 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, 1024*128);
59 ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
61 next_track:
63 if (codec_init()) {
64 LOGF("APE: Error initialising codec\n");
65 retval = CODEC_ERROR;
66 goto exit;
69 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
71 /* Read the file headers to populate the ape_ctx struct */
72 if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) {
73 LOGF("APE: Error reading header\n");
74 retval = CODEC_ERROR;
75 goto exit;
77 ci->advance_buffer(ape_ctx.firstframe);
79 while (!*ci->taginfo_ready && !ci->stop_codec)
80 ci->sleep(1);
82 ci->configure(DSP_SWITCH_FREQUENCY, ape_ctx.samplerate);
83 ci->configure(DSP_SET_STEREO_MODE, ape_ctx.channels == 1 ?
84 STEREO_MONO : STEREO_NONINTERLEAVED);
85 codec_set_replaygain(ci->id3);
87 /* The main decoding loop */
89 currentframe = 0;
90 samplesdone = 0;
92 /* Initialise the buffer */
93 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
94 firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */
96 /* The main decoding loop - we decode the frames a small chunk at a time */
97 while (currentframe < ape_ctx.totalframes)
99 /* Calculate how many blocks there are in this frame */
100 if (currentframe == (ape_ctx.totalframes - 1))
101 nblocks = ape_ctx.finalframeblocks;
102 else
103 nblocks = ape_ctx.blocksperframe;
105 ape_ctx.currentframeblocks = nblocks;
107 /* Initialise the frame decoder */
108 init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed);
110 ci->advance_buffer(bytesconsumed);
111 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
113 /* Decode the frame a chunk at a time */
114 while (nblocks > 0)
116 ci->yield();
117 if (ci->stop_codec || ci->new_track) {
118 break;
121 blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);
123 if ((res = decode_chunk(&ape_ctx, inbuffer, &firstbyte,
124 &bytesconsumed,
125 decoded0, decoded1,
126 blockstodecode)) < 0)
128 /* Frame decoding error, abort */
129 LOGF("APE: Frame %d, error %d\n",currentframe,res);
130 retval = CODEC_ERROR;
131 goto done;
134 ci->yield();
135 ci->pcmbuf_insert(decoded0, decoded1, blockstodecode);
137 /* Update the elapsed-time indicator */
138 samplesdone += blockstodecode;
139 elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
140 ci->set_elapsed(elapsedtime);
142 ci->advance_buffer(bytesconsumed);
143 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
145 /* Decrement the block count */
146 nblocks -= blockstodecode;
149 currentframe++;
152 retval = CODEC_OK;
154 done:
155 LOGF("APE: Decoded %ld samples\n",samplesdone);
157 if (ci->request_next_track())
158 goto next_track;
160 exit:
161 return retval;