diff options
author | Dave Chapman <dave@dchapman.com> | 2007-06-05 16:58:29 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2007-06-05 16:58:29 +0000 |
commit | 520274219a0745384cb9bc6df4d7ee7905090f5d (patch) | |
tree | 8d6f4536b6758d00e72a2a9457f892ce28a591bd /apps/codecs/demac/libdemac/entropy.c | |
parent | 887b31c01aebb46c0fcc6910241a4a64d9e7991e (diff) | |
download | rockbox-520274219a0745384cb9bc6df4d7ee7905090f5d.tar.gz rockbox-520274219a0745384cb9bc6df4d7ee7905090f5d.zip |
Initial commit of Monkey's Audio (.ape/.mac) support. Note that Monkey's is an extremely CPU-intensive codec, and that the decoding speed is directly related to the compression level (-c1000, -c2000, -c3000, -c4000 or -c5000) used when encoding the file. Current performance is: -c1000 to -c3000 are realtime on a Gigabeat, -c1000 is realtime on Coldfire targets (H100, H300 and Cowon), and nothing is realtime on PortalPlayer targets (iPods, H10, Sansa). Hopefully this can be improved. More information at FS #7256.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13562 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/demac/libdemac/entropy.c')
-rw-r--r-- | apps/codecs/demac/libdemac/entropy.c | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/apps/codecs/demac/libdemac/entropy.c b/apps/codecs/demac/libdemac/entropy.c new file mode 100644 index 0000000000..2c60420250 --- /dev/null +++ b/apps/codecs/demac/libdemac/entropy.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | |||
3 | libdemac - A Monkey's Audio decoder | ||
4 | |||
5 | $Id:$ | ||
6 | |||
7 | Copyright (C) Dave Chapman 2007 | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | ||
22 | |||
23 | */ | ||
24 | |||
25 | #include <inttypes.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #include "parser.h" | ||
29 | #include "entropy.h" | ||
30 | #include "rangecoding.h" /* Range-coding (static inline) functions */ | ||
31 | |||
32 | #define MODEL_ELEMENTS 64 | ||
33 | |||
34 | /* | ||
35 | The following counts arrays for use with the range decoder are | ||
36 | hard-coded in the Monkey's Audio decoder. | ||
37 | */ | ||
38 | |||
39 | static const int counts_3970[65] ICONST_ATTR = | ||
40 | { | ||
41 | 0,14824,28224,39348,47855,53994,58171,60926, | ||
42 | 62682,63786,64463,64878,65126,65276,65365,65419, | ||
43 | 65450,65469,65480,65487,65491,65493,65494,65495, | ||
44 | 65496,65497,65498,65499,65500,65501,65502,65503, | ||
45 | 65504,65505,65506,65507,65508,65509,65510,65511, | ||
46 | 65512,65513,65514,65515,65516,65517,65518,65519, | ||
47 | 65520,65521,65522,65523,65524,65525,65526,65527, | ||
48 | 65528,65529,65530,65531,65532,65533,65534,65535, | ||
49 | 65536 | ||
50 | }; | ||
51 | |||
52 | /* counts_diff_3970[i] = counts_3970[i+1] - counts_3970[i] */ | ||
53 | static const int counts_diff_3970[64] ICONST_ATTR = | ||
54 | { | ||
55 | 14824,13400,11124,8507,6139,4177,2755,1756, | ||
56 | 1104,677,415,248,150,89,54,31, | ||
57 | 19,11,7,4,2,1,1,1, | ||
58 | 1,1,1,1,1,1,1,1, | ||
59 | 1,1,1,1,1,1,1,1, | ||
60 | 1,1,1,1,1,1,1,1, | ||
61 | 1,1,1,1,1,1,1,1, | ||
62 | 1,1,1,1,1,1,1,1 | ||
63 | }; | ||
64 | |||
65 | static const int counts_3980[65] ICONST_ATTR = | ||
66 | { | ||
67 | 0,19578,36160,48417,56323,60899,63265,64435, | ||
68 | 64971,65232,65351,65416,65447,65466,65476,65482, | ||
69 | 65485,65488,65490,65491,65492,65493,65494,65495, | ||
70 | 65496,65497,65498,65499,65500,65501,65502,65503, | ||
71 | 65504,65505,65506,65507,65508,65509,65510,65511, | ||
72 | 65512,65513,65514,65515,65516,65517,65518,65519, | ||
73 | 65520,65521,65522,65523,65524,65525,65526,65527, | ||
74 | 65528,65529,65530,65531,65532,65533,65534,65535, | ||
75 | 65536 | ||
76 | }; | ||
77 | |||
78 | /* counts_diff_3980[i] = counts_3980[i+1] - counts_3980[i] */ | ||
79 | |||
80 | static const int counts_diff_3980[64] ICONST_ATTR = | ||
81 | { | ||
82 | 19578,16582,12257,7906,4576,2366,1170,536, | ||
83 | 261,119,65,31,19,10,6,3, | ||
84 | 3,2,1,1,1,1,1,1, | ||
85 | 1,1,1,1,1,1,1,1, | ||
86 | 1,1,1,1,1,1,1,1, | ||
87 | 1,1,1,1,1,1,1,1, | ||
88 | 1,1,1,1,1,1,1,1, | ||
89 | 1,1,1,1,1,1,1,1 | ||
90 | }; | ||
91 | |||
92 | /* | ||
93 | range_get_symbol_* functions based on main decoding loop in simple_d.c from | ||
94 | http://www.compressconsult.com/rangecoder/rngcod13.zip | ||
95 | (c) Michael Schindler | ||
96 | */ | ||
97 | |||
98 | static inline int range_get_symbol_3980(void) | ||
99 | { | ||
100 | int symbol, cf; | ||
101 | |||
102 | cf = range_decode_culshift(16); | ||
103 | |||
104 | /* figure out the symbol inefficiently; a binary search would be much better */ | ||
105 | for (symbol = 0; counts_3980[symbol+1] <= cf; symbol++); | ||
106 | |||
107 | range_decode_update(counts_diff_3980[symbol],counts_3980[symbol]); | ||
108 | |||
109 | return symbol; | ||
110 | } | ||
111 | |||
112 | static inline int range_get_symbol_3970(void) | ||
113 | { | ||
114 | int symbol, cf; | ||
115 | |||
116 | cf = range_decode_culshift(16); | ||
117 | |||
118 | /* figure out the symbol inefficiently; a binary search would be much better */ | ||
119 | for (symbol = 0; counts_3970[symbol+1] <= cf; symbol++); | ||
120 | |||
121 | range_decode_update(counts_diff_3970[symbol],counts_3970[symbol]); | ||
122 | |||
123 | return symbol; | ||
124 | } | ||
125 | |||
126 | /* MAIN DECODING FUNCTIONS */ | ||
127 | |||
128 | struct rice_t | ||
129 | { | ||
130 | uint32_t k; | ||
131 | uint32_t ksum; | ||
132 | }; | ||
133 | |||
134 | static struct rice_t riceX IBSS_ATTR; | ||
135 | static struct rice_t riceY IBSS_ATTR; | ||
136 | |||
137 | static inline void update_rice(struct rice_t* rice, int x) | ||
138 | { | ||
139 | rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5); | ||
140 | |||
141 | if (rice->k == 0) { | ||
142 | rice->k = 1; | ||
143 | } else if (rice->ksum < ((uint32_t)1 << (rice->k + 4))) { | ||
144 | rice->k--; | ||
145 | } else if (rice->ksum >= ((uint32_t)1 << (rice->k + 5))) { | ||
146 | rice->k++; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static inline int entropy_decode3980(struct rice_t* rice) | ||
151 | { | ||
152 | int base, x, pivot, overflow; | ||
153 | |||
154 | pivot = rice->ksum >> 5; | ||
155 | if (pivot == 0) pivot=1; | ||
156 | |||
157 | overflow = range_get_symbol_3980(); | ||
158 | |||
159 | if (overflow == (MODEL_ELEMENTS-1)) { | ||
160 | overflow = range_decode_short() << 16; | ||
161 | overflow |= range_decode_short(); | ||
162 | } | ||
163 | |||
164 | if (pivot >= 0x10000) { | ||
165 | /* Codepath for 24-bit streams */ | ||
166 | int nbits, lo_bits, base_hi, base_lo; | ||
167 | |||
168 | /* Count the number of bits in pivot */ | ||
169 | nbits = 17; /* We know there must be at least 17 bits */ | ||
170 | while ((pivot >> nbits) > 0) { nbits++; } | ||
171 | |||
172 | /* base_lo is the low (nbits-16) bits of base | ||
173 | base_hi is the high 16 bits of base | ||
174 | */ | ||
175 | lo_bits = (nbits - 16); | ||
176 | |||
177 | base_hi = range_decode_culfreq((pivot >> lo_bits) + 1); | ||
178 | range_decode_update(1, base_hi); | ||
179 | |||
180 | base_lo = range_decode_culfreq(1 << lo_bits); | ||
181 | range_decode_update(1, base_lo); | ||
182 | |||
183 | base = (base_hi << lo_bits) + base_lo; | ||
184 | } else { | ||
185 | /* Codepath for 16-bit streams */ | ||
186 | base = range_decode_culfreq(pivot); | ||
187 | range_decode_update(1, base); | ||
188 | } | ||
189 | |||
190 | x = base + (overflow * pivot); | ||
191 | update_rice(rice, x); | ||
192 | |||
193 | /* Convert to signed */ | ||
194 | if (x & 1) | ||
195 | return (x >> 1) + 1; | ||
196 | else | ||
197 | return -(x >> 1); | ||
198 | } | ||
199 | |||
200 | |||
201 | static inline int entropy_decode3970(struct rice_t* rice) | ||
202 | { | ||
203 | int x, tmpk; | ||
204 | |||
205 | int overflow = range_get_symbol_3970(); | ||
206 | |||
207 | if (overflow == (MODEL_ELEMENTS - 1)) { | ||
208 | tmpk = range_decode_bits(5); | ||
209 | overflow = 0; | ||
210 | } else { | ||
211 | tmpk = (rice->k < 1) ? 0 : rice->k - 1; | ||
212 | } | ||
213 | |||
214 | if (tmpk <= 16) { | ||
215 | x = range_decode_bits(tmpk); | ||
216 | } else { | ||
217 | x = range_decode_short(); | ||
218 | x |= (range_decode_bits(tmpk - 16) << 16); | ||
219 | } | ||
220 | x += (overflow << tmpk); | ||
221 | |||
222 | update_rice(rice, x); | ||
223 | |||
224 | /* Convert to signed */ | ||
225 | if (x & 1) | ||
226 | return (x >> 1) + 1; | ||
227 | else | ||
228 | return -(x >> 1); | ||
229 | } | ||
230 | |||
231 | void init_entropy_decoder(struct ape_ctx_t* ape_ctx, | ||
232 | unsigned char* inbuffer, int* firstbyte, | ||
233 | int* bytesconsumed) | ||
234 | { | ||
235 | bytebuffer = inbuffer; | ||
236 | bytebufferoffset = *firstbyte; | ||
237 | |||
238 | /* Read the CRC */ | ||
239 | ape_ctx->CRC = read_byte(); | ||
240 | ape_ctx->CRC = (ape_ctx->CRC << 8) | read_byte(); | ||
241 | ape_ctx->CRC = (ape_ctx->CRC << 8) | read_byte(); | ||
242 | ape_ctx->CRC = (ape_ctx->CRC << 8) | read_byte(); | ||
243 | |||
244 | /* Read the frame flags if they exist */ | ||
245 | ape_ctx->frameflags = 0; | ||
246 | if ((ape_ctx->fileversion > 3820) && (ape_ctx->CRC & 0x80000000)) { | ||
247 | ape_ctx->CRC &= ~0x80000000; | ||
248 | |||
249 | ape_ctx->frameflags = read_byte(); | ||
250 | ape_ctx->frameflags = (ape_ctx->frameflags << 8) | read_byte(); | ||
251 | ape_ctx->frameflags = (ape_ctx->frameflags << 8) | read_byte(); | ||
252 | ape_ctx->frameflags = (ape_ctx->frameflags << 8) | read_byte(); | ||
253 | } | ||
254 | /* Keep a count of the blocks decoded in this frame */ | ||
255 | ape_ctx->blocksdecoded = 0; | ||
256 | |||
257 | /* Initialise the rice structs */ | ||
258 | riceX.k = 10; | ||
259 | riceX.ksum = (1 << riceX.k) * 16; | ||
260 | riceY.k = 10; | ||
261 | riceY.ksum = (1 << riceY.k) * 16; | ||
262 | |||
263 | /* The first 8 bits of input are ignored. */ | ||
264 | skip_byte(); | ||
265 | |||
266 | range_start_decoding(); | ||
267 | |||
268 | /* Return the new state of the buffer */ | ||
269 | *bytesconsumed = (intptr_t)bytebuffer - (intptr_t)inbuffer; | ||
270 | *firstbyte = bytebufferoffset; | ||
271 | } | ||
272 | |||
273 | int entropy_decode(struct ape_ctx_t* ape_ctx, | ||
274 | unsigned char* inbuffer, int* firstbyte, | ||
275 | int* bytesconsumed, | ||
276 | int32_t* decoded0, int32_t* decoded1, | ||
277 | int blockstodecode) | ||
278 | { | ||
279 | bytebuffer = inbuffer; | ||
280 | bytebufferoffset = *firstbyte; | ||
281 | |||
282 | ape_ctx->blocksdecoded += blockstodecode; | ||
283 | |||
284 | if (ape_ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) { | ||
285 | /* We are pure silence, just memset the output buffer. */ | ||
286 | memset(decoded0, 0, blockstodecode * sizeof(int32_t)); | ||
287 | memset(decoded1, 0, blockstodecode * sizeof(int32_t)); | ||
288 | } else { | ||
289 | if (ape_ctx->fileversion > 3970) { | ||
290 | while (blockstodecode--) { | ||
291 | *(decoded0++) = entropy_decode3980(&riceY); | ||
292 | if (decoded1 != NULL) | ||
293 | *(decoded1++) = entropy_decode3980(&riceX); | ||
294 | } | ||
295 | } else { | ||
296 | while (blockstodecode--) { | ||
297 | *(decoded0++) = entropy_decode3970(&riceY); | ||
298 | if (decoded1 != NULL) | ||
299 | *(decoded1++) = entropy_decode3970(&riceX); | ||
300 | } | ||
301 | } | ||
302 | } | ||
303 | |||
304 | if (ape_ctx->blocksdecoded == ape_ctx->currentframeblocks) | ||
305 | { | ||
306 | range_done_decoding(); | ||
307 | } | ||
308 | |||
309 | /* Return the new state of the buffer */ | ||
310 | *bytesconsumed = bytebuffer - inbuffer; | ||
311 | *firstbyte = bytebufferoffset; | ||
312 | |||
313 | return(0); | ||
314 | } | ||