summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Gashlin <agashlin@gmail.com>2007-11-09 02:42:39 +0000
committerAdam Gashlin <agashlin@gmail.com>2007-11-09 02:42:39 +0000
commitb9dba4f12817f4d1d146def093520aeee78a1c7a (patch)
tree71a7438eb754444b72216f964726a4075b87b20a
parente43c1ac338fa57b874c17238452e5fcfa5481489 (diff)
downloadrockbox-b9dba4f12817f4d1d146def093520aeee78a1c7a.tar.gz
rockbox-b9dba4f12817f4d1d146def093520aeee78a1c7a.zip
Sorry, switching back again to the "better behaved" ADX codec of r15494.
Not perfect, but with a safer failure than the hacky old/reborn one. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15548 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/adx.c106
1 files changed, 54 insertions, 52 deletions
diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c
index 715df579d7..f558bae135 100644
--- a/apps/codecs/adx.c
+++ b/apps/codecs/adx.c
@@ -6,7 +6,7 @@
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * 8 *
9 * Copyright (C) 2006 Adam Gashlin (hcs) 9 * Copyright (C) 2006-2007 Adam Gashlin (hcs)
10 * 10 *
11 * All files in this archive are subject to the GNU General Public License. 11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement. 12 * See the file COPYING in the source tree root for full license agreement.
@@ -15,7 +15,6 @@
15 * KIND, either express or implied. 15 * KIND, either express or implied.
16 * 16 *
17 ****************************************************************************/ 17 ****************************************************************************/
18
19#include "codeclib.h" 18#include "codeclib.h"
20#include "inttypes.h" 19#include "inttypes.h"
21 20
@@ -42,7 +41,7 @@ enum codec_status codec_main(void)
42 int sampleswritten, i; 41 int sampleswritten, i;
43 uint8_t *buf; 42 uint8_t *buf;
44 int32_t ch1_1, ch1_2, ch2_1, ch2_2; /* ADPCM history */ 43 int32_t ch1_1, ch1_2, ch2_1, ch2_2; /* ADPCM history */
45 size_t n, bufsize; 44 size_t n;
46 int endofstream; /* end of stream flag */ 45 int endofstream; /* end of stream flag */
47 uint32_t avgbytespersec; 46 uint32_t avgbytespersec;
48 int looping; /* looping flag */ 47 int looping; /* looping flag */
@@ -72,17 +71,15 @@ next_track:
72 71
73 codec_set_replaygain(ci->id3); 72 codec_set_replaygain(ci->id3);
74 73
75 /* Read the entire file (or as much as possible) */ 74 /* Get header */
76 DEBUGF("ADX: request initial buffer\n"); 75 DEBUGF("ADX: request initial buffer\n");
77 ci->configure(CODEC_SET_FILEBUF_WATERMARK, ci->filesize);
78 ci->seek_buffer(0); 76 ci->seek_buffer(0);
79 buf = ci->request_buffer(&n, ci->filesize); 77 buf = ci->request_buffer(&n, 0x38);
80 if (!buf || n < 0x38) { 78 if (!buf || n < 0x38) {
81 return CODEC_ERROR; 79 return CODEC_ERROR;
82 } 80 }
83 bufsize = n;
84 bufoff = 0; 81 bufoff = 0;
85 DEBUGF("ADX: read size = %lx\n",(unsigned long)bufsize); 82 DEBUGF("ADX: read size = %lx\n",(unsigned long)n);
86 83
87 /* Get file header for starting offset, channel count */ 84 /* Get file header for starting offset, channel count */
88 85
@@ -151,10 +148,13 @@ next_track:
151 } 148 }
152 149
153 /* advance to first frame */ 150 /* advance to first frame */
154 /*ci->seek_buffer(chanstart);*/
155 DEBUGF("ADX: first frame at %lx\n",chanstart); 151 DEBUGF("ADX: first frame at %lx\n",chanstart);
156 bufoff = chanstart; 152 bufoff = chanstart;
157 153
154 /* get in position */
155 ci->seek_buffer(bufoff);
156
157
158 /* setup pcm buffer format */ 158 /* setup pcm buffer format */
159 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 159 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
160 if (channels == 2) { 160 if (channels == 2) {
@@ -180,7 +180,7 @@ next_track:
180 } 180 }
181 181
182 /* do we need to loop? */ 182 /* do we need to loop? */
183 if (bufoff >= end_adr-18*channels && looping) { 183 if (bufoff > end_adr-18*channels && looping) {
184 DEBUGF("ADX: loop!\n"); 184 DEBUGF("ADX: loop!\n");
185 /* check for endless looping */ 185 /* check for endless looping */
186 if (ci->global_settings->repeat_mode==REPEAT_ONE) { 186 if (ci->global_settings->repeat_mode==REPEAT_ONE) {
@@ -198,6 +198,7 @@ next_track:
198 } 198 }
199 } 199 }
200 bufoff = start_adr; 200 bufoff = start_adr;
201 ci->seek_buffer(bufoff);
201 } 202 }
202 203
203 /* do we need to seek? */ 204 /* do we need to seek? */
@@ -218,55 +219,40 @@ next_track:
218 bufoff-=end_adr-start_adr; 219 bufoff-=end_adr-start_adr;
219 loop_count++; 220 loop_count++;
220 } 221 }
222 ci->seek_buffer(bufoff);
221 ci->seek_complete(); 223 ci->seek_complete();
222 } 224 }
223 225
224 if (bufoff>ci->filesize-channels*18) break; /* End of stream */ 226 if (bufoff>ci->filesize-channels*18) break; /* End of stream */
225 227
226 /* dance with the devil in the pale moonlight */
227 if ((bufoff > ci->curpos + (off_t)bufsize - channels*18) ||
228 bufoff < ci->curpos) {
229 DEBUGF("ADX: requesting another buffer at %lx size %lx\n",
230 bufoff,ci->filesize-bufoff);
231 ci->seek_buffer(bufoff);
232 buf = ci->request_buffer(&n, ci->filesize-bufoff);
233 bufsize = n;
234 DEBUGF("ADX: read size = %lx\n",(unsigned long)bufsize);
235 if ((off_t)bufsize < channels*18) {
236 /* if we can't get a full frame, just request a single
237 frame (should be able to fit it in the guard buffer) */
238 DEBUGF("ADX: requesting single frame at %lx\n",bufoff);
239 buf = ci->request_buffer(&n, channels*18);
240 bufsize=n;
241 DEBUGF("ADX: read size = %lx\n",(unsigned long)bufsize);
242 }
243 if (!buf) {
244 DEBUGF("ADX: couldn't get buffer at %lx size %lx\n",
245 bufoff,ci->filesize-bufoff);
246 return CODEC_ERROR;
247 }
248 buf-=bufoff;
249 }
250
251 if (bufsize == 0) break; /* End of stream */
252
253 sampleswritten=0; 228 sampleswritten=0;
254 229
255 while ( 230 while (
256 /* Is there data in the file buffer? */ 231 /* Is there data left in the file? */
257 ((size_t)bufoff <= ci->curpos+bufsize-(18*channels)) && 232 (bufoff <= ci->filesize-(18*channels)) &&
258 /* Is there space in the output buffer? */ 233 /* Is there space in the output buffer? */
259 (sampleswritten <= WAV_CHUNK_SIZE-(32*channels)) && 234 (sampleswritten <= WAV_CHUNK_SIZE-(32*channels)) &&
260 /* Should we be looping? */ 235 /* Should we be looping? */
261 ((!looping) || bufoff < end_adr-18*channels)) { 236 ((!looping) || bufoff <= end_adr-18*channels))
262 /* decode 18 bytes to 32 samples (from bero) */ 237 {
263 int32_t scale = ((buf[bufoff] << 8) | (buf[bufoff+1])) * BASE_VOL; 238 /* decode first/only channel */
264 239 int32_t scale;
265 int32_t ch1_0, d; 240 int32_t ch1_0, d;
266 241
242 /* fetch a frame */
243 buf = ci->request_buffer(&n, 18);
244
245 if (!buf || n!=18) {
246 DEBUGF("ADX: couldn't get buffer at %lx\n",
247 bufoff);
248 return CODEC_ERROR;
249 }
250
251 scale = (((buf[0] << 8) | (buf[1])) +1) * BASE_VOL;
252
267 for (i = 2; i < 18; i++) 253 for (i = 2; i < 18; i++)
268 { 254 {
269 d = (buf[bufoff+i] >> 4) & 15; 255 d = (buf[i] >> 4) & 15;
270 if (d & 8) d-= 16; 256 if (d & 8) d-= 16;
271 ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14; 257 ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14;
272 if (ch1_0 > 32767) ch1_0 = 32767; 258 if (ch1_0 > 32767) ch1_0 = 32767;
@@ -274,7 +260,8 @@ next_track:
274 samples[sampleswritten] = ch1_0; 260 samples[sampleswritten] = ch1_0;
275 sampleswritten+=channels; 261 sampleswritten+=channels;
276 ch1_2 = ch1_1; ch1_1 = ch1_0; 262 ch1_2 = ch1_1; ch1_1 = ch1_0;
277 d = buf[bufoff+i] & 15; 263
264 d = buf[i] & 15;
278 if (d & 8) d -= 16; 265 if (d & 8) d -= 16;
279 ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14; 266 ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14;
280 if (ch1_0 > 32767) ch1_0 = 32767; 267 if (ch1_0 > 32767) ch1_0 = 32767;
@@ -284,16 +271,28 @@ next_track:
284 ch1_2 = ch1_1; ch1_1 = ch1_0; 271 ch1_2 = ch1_1; ch1_1 = ch1_0;
285 } 272 }
286 bufoff+=18; 273 bufoff+=18;
274 ci->advance_buffer(18);
287 275
288 if (channels == 2) { 276 if (channels == 2) {
289 int32_t scale = ((buf[bufoff] << 8)|(buf[bufoff+1]))*BASE_VOL; 277 /* decode second channel */
290 278 int32_t scale;
291 int32_t ch2_0, d; 279 int32_t ch2_0, d;
280
281 buf = ci->request_buffer(&n, 18);
282
283 if (!buf || n!=18) {
284 DEBUGF("ADX: couldn't get buffer at %lx\n",
285 bufoff);
286 return CODEC_ERROR;
287 }
288
289 scale = (((buf[0] << 8)|(buf[1]))+1)*BASE_VOL;
290
292 sampleswritten-=63; 291 sampleswritten-=63;
293 292
294 for (i = 2; i < 18; i++) 293 for (i = 2; i < 18; i++)
295 { 294 {
296 d = (buf[bufoff+i] >> 4) & 15; 295 d = (buf[i] >> 4) & 15;
297 if (d & 8) d-= 16; 296 if (d & 8) d-= 16;
298 ch2_0 = (d*scale + 0x7298L*ch2_1 - 0x3350L*ch2_2) >> 14; 297 ch2_0 = (d*scale + 0x7298L*ch2_1 - 0x3350L*ch2_2) >> 14;
299 if (ch2_0 > 32767) ch2_0 = 32767; 298 if (ch2_0 > 32767) ch2_0 = 32767;
@@ -301,7 +300,8 @@ next_track:
301 samples[sampleswritten] = ch2_0; 300 samples[sampleswritten] = ch2_0;
302 sampleswritten+=2; 301 sampleswritten+=2;
303 ch2_2 = ch2_1; ch2_1 = ch2_0; 302 ch2_2 = ch2_1; ch2_1 = ch2_0;
304 d = buf[bufoff+i] & 15; 303
304 d = buf[i] & 15;
305 if (d & 8) d -= 16; 305 if (d & 8) d -= 16;
306 ch2_0 = (d*scale + 0x7298L*ch2_1 - 0x3350L*ch2_2) >> 14; 306 ch2_0 = (d*scale + 0x7298L*ch2_1 - 0x3350L*ch2_2) >> 14;
307 if (ch2_0 > 32767) ch2_0 = 32767; 307 if (ch2_0 > 32767) ch2_0 = 32767;
@@ -311,8 +311,10 @@ next_track:
311 ch2_2 = ch2_1; ch2_1 = ch2_0; 311 ch2_2 = ch2_1; ch2_1 = ch2_0;
312 } 312 }
313 bufoff+=18; 313 bufoff+=18;
314 ci->advance_buffer(18);
314 sampleswritten--; /* go back to first channel's next sample */ 315 sampleswritten--; /* go back to first channel's next sample */
315 } 316 }
317
316 if (fade_count>0) { 318 if (fade_count>0) {
317 fade_count--; 319 fade_count--;
318 for (i=0;i<(channels==1?32:64);i++) samples[sampleswritten-i-1]= 320 for (i=0;i<(channels==1?32:64);i++) samples[sampleswritten-i-1]=