summaryrefslogtreecommitdiff
path: root/apps/codecs/ape.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/ape.c')
-rw-r--r--apps/codecs/ape.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/apps/codecs/ape.c b/apps/codecs/ape.c
new file mode 100644
index 0000000000..b77abc0c74
--- /dev/null
+++ b/apps/codecs/ape.c
@@ -0,0 +1,162 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "codeclib.h"
21#define ROCKBOX
22#include <codecs/demac/libdemac/demac.h>
23
24CODEC_HEADER
25
26#define BLOCKS_PER_LOOP 4608
27#define MAX_CHANNELS 2
28#define MAX_BYTESPERSAMPLE 3
29
30#define INPUT_CHUNKSIZE (32*1024)
31
32/* 4608*4 = 18432 bytes per channel */
33static int32_t decoded0[BLOCKS_PER_LOOP] IBSS_ATTR;
34static int32_t decoded1[BLOCKS_PER_LOOP] IBSS_ATTR;
35
36#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
37
38/* this is the codec entry point */
39enum codec_status codec_main(void)
40{
41 struct ape_ctx_t ape_ctx;
42 uint32_t samplesdone;
43 uint32_t elapsedtime;
44 size_t bytesleft;
45 int retval;
46
47 uint32_t currentframe;
48 int nblocks;
49 int bytesconsumed;
50 unsigned char* inbuffer;
51 int blockstodecode;
52 int res;
53 int firstbyte;
54
55 /* Generic codec initialisation */
56 ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
57 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, 1024*128);
58
59 ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
60
61 next_track:
62
63 if (codec_init()) {
64 LOGF("APE: Error initialising codec\n");
65 retval = CODEC_ERROR;
66 goto exit;
67 }
68
69 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
70
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;
76 }
77 ci->advance_buffer(ape_ctx.firstframe);
78
79 while (!*ci->taginfo_ready && !ci->stop_codec)
80 ci->sleep(1);
81
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);
86
87 /* The main decoding loop */
88
89 currentframe = 0;
90 samplesdone = 0;
91
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 */
95
96 /* The main decoding loop - we decode the frames a small chunk at a time */
97 while (currentframe < ape_ctx.totalframes)
98 {
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;
104
105 ape_ctx.currentframeblocks = nblocks;
106
107 /* Initialise the frame decoder */
108 init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed);
109
110 ci->advance_buffer(bytesconsumed);
111 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
112
113 /* Decode the frame a chunk at a time */
114 while (nblocks > 0)
115 {
116 ci->yield();
117 if (ci->stop_codec || ci->new_track) {
118 break;
119 }
120
121 blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);
122
123 if ((res = decode_chunk(&ape_ctx, inbuffer, &firstbyte,
124 &bytesconsumed,
125 decoded0, decoded1,
126 blockstodecode)) < 0)
127 {
128 /* Frame decoding error, abort */
129 LOGF("APE: Frame %d, error %d\n",currentframe,res);
130 retval = CODEC_ERROR;
131 goto done;
132 }
133
134 ci->yield();
135 ci->pcmbuf_insert(decoded0, decoded1, blockstodecode);
136
137 /* Update the elapsed-time indicator */
138 samplesdone += blockstodecode;
139 elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
140 ci->set_elapsed(elapsedtime);
141
142 ci->advance_buffer(bytesconsumed);
143 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
144
145 /* Decrement the block count */
146 nblocks -= blockstodecode;
147 }
148
149 currentframe++;
150 }
151
152 retval = CODEC_OK;
153
154done:
155 LOGF("APE: Decoded %ld samples\n",samplesdone);
156
157 if (ci->request_next_track())
158 goto next_track;
159
160exit:
161 return retval;
162}