diff options
author | Adam Gashlin <agashlin@gmail.com> | 2007-11-07 19:01:58 +0000 |
---|---|---|
committer | Adam Gashlin <agashlin@gmail.com> | 2007-11-07 19:01:58 +0000 |
commit | 1c108df4ee230acde7f992ee4cff9b170b8299a9 (patch) | |
tree | 8de31ec01f6ea37f3957ecf64b707e6ab2607456 /apps/codecs/adx.c | |
parent | d74a8ec85dd83f50bf03938095890267d59d9825 (diff) | |
download | rockbox-1c108df4ee230acde7f992ee4cff9b170b8299a9.tar.gz rockbox-1c108df4ee230acde7f992ee4cff9b170b8299a9.zip |
Revert to old ADX codec, works around broken bacwards seek
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15518 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/adx.c')
-rw-r--r-- | apps/codecs/adx.c | 106 |
1 files changed, 52 insertions, 54 deletions
diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c index f558bae135..715df579d7 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-2007 Adam Gashlin (hcs) | 9 | * Copyright (C) 2006 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,6 +15,7 @@ | |||
15 | * KIND, either express or implied. | 15 | * KIND, either express or implied. |
16 | * | 16 | * |
17 | ****************************************************************************/ | 17 | ****************************************************************************/ |
18 | |||
18 | #include "codeclib.h" | 19 | #include "codeclib.h" |
19 | #include "inttypes.h" | 20 | #include "inttypes.h" |
20 | 21 | ||
@@ -41,7 +42,7 @@ enum codec_status codec_main(void) | |||
41 | int sampleswritten, i; | 42 | int sampleswritten, i; |
42 | uint8_t *buf; | 43 | uint8_t *buf; |
43 | int32_t ch1_1, ch1_2, ch2_1, ch2_2; /* ADPCM history */ | 44 | int32_t ch1_1, ch1_2, ch2_1, ch2_2; /* ADPCM history */ |
44 | size_t n; | 45 | size_t n, bufsize; |
45 | int endofstream; /* end of stream flag */ | 46 | int endofstream; /* end of stream flag */ |
46 | uint32_t avgbytespersec; | 47 | uint32_t avgbytespersec; |
47 | int looping; /* looping flag */ | 48 | int looping; /* looping flag */ |
@@ -71,15 +72,17 @@ next_track: | |||
71 | 72 | ||
72 | codec_set_replaygain(ci->id3); | 73 | codec_set_replaygain(ci->id3); |
73 | 74 | ||
74 | /* Get header */ | 75 | /* Read the entire file (or as much as possible) */ |
75 | DEBUGF("ADX: request initial buffer\n"); | 76 | DEBUGF("ADX: request initial buffer\n"); |
77 | ci->configure(CODEC_SET_FILEBUF_WATERMARK, ci->filesize); | ||
76 | ci->seek_buffer(0); | 78 | ci->seek_buffer(0); |
77 | buf = ci->request_buffer(&n, 0x38); | 79 | buf = ci->request_buffer(&n, ci->filesize); |
78 | if (!buf || n < 0x38) { | 80 | if (!buf || n < 0x38) { |
79 | return CODEC_ERROR; | 81 | return CODEC_ERROR; |
80 | } | 82 | } |
83 | bufsize = n; | ||
81 | bufoff = 0; | 84 | bufoff = 0; |
82 | DEBUGF("ADX: read size = %lx\n",(unsigned long)n); | 85 | DEBUGF("ADX: read size = %lx\n",(unsigned long)bufsize); |
83 | 86 | ||
84 | /* Get file header for starting offset, channel count */ | 87 | /* Get file header for starting offset, channel count */ |
85 | 88 | ||
@@ -148,13 +151,10 @@ next_track: | |||
148 | } | 151 | } |
149 | 152 | ||
150 | /* advance to first frame */ | 153 | /* advance to first frame */ |
154 | /*ci->seek_buffer(chanstart);*/ | ||
151 | DEBUGF("ADX: first frame at %lx\n",chanstart); | 155 | DEBUGF("ADX: first frame at %lx\n",chanstart); |
152 | bufoff = chanstart; | 156 | bufoff = chanstart; |
153 | 157 | ||
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,7 +198,6 @@ next_track: | |||
198 | } | 198 | } |
199 | } | 199 | } |
200 | bufoff = start_adr; | 200 | bufoff = start_adr; |
201 | ci->seek_buffer(bufoff); | ||
202 | } | 201 | } |
203 | 202 | ||
204 | /* do we need to seek? */ | 203 | /* do we need to seek? */ |
@@ -219,40 +218,55 @@ next_track: | |||
219 | bufoff-=end_adr-start_adr; | 218 | bufoff-=end_adr-start_adr; |
220 | loop_count++; | 219 | loop_count++; |
221 | } | 220 | } |
222 | ci->seek_buffer(bufoff); | ||
223 | ci->seek_complete(); | 221 | ci->seek_complete(); |
224 | } | 222 | } |
225 | 223 | ||
226 | if (bufoff>ci->filesize-channels*18) break; /* End of stream */ | 224 | if (bufoff>ci->filesize-channels*18) break; /* End of stream */ |
227 | 225 | ||
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 | |||
228 | sampleswritten=0; | 253 | sampleswritten=0; |
229 | 254 | ||
230 | while ( | 255 | while ( |
231 | /* Is there data left in the file? */ | 256 | /* Is there data in the file buffer? */ |
232 | (bufoff <= ci->filesize-(18*channels)) && | 257 | ((size_t)bufoff <= ci->curpos+bufsize-(18*channels)) && |
233 | /* Is there space in the output buffer? */ | 258 | /* Is there space in the output buffer? */ |
234 | (sampleswritten <= WAV_CHUNK_SIZE-(32*channels)) && | 259 | (sampleswritten <= WAV_CHUNK_SIZE-(32*channels)) && |
235 | /* Should we be looping? */ | 260 | /* Should we be looping? */ |
236 | ((!looping) || bufoff <= end_adr-18*channels)) | 261 | ((!looping) || bufoff < end_adr-18*channels)) { |
237 | { | 262 | /* decode 18 bytes to 32 samples (from bero) */ |
238 | /* decode first/only channel */ | 263 | int32_t scale = ((buf[bufoff] << 8) | (buf[bufoff+1])) * BASE_VOL; |
239 | int32_t scale; | 264 | |
240 | int32_t ch1_0, d; | 265 | int32_t ch1_0, d; |
241 | 266 | ||
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 | |||
253 | for (i = 2; i < 18; i++) | 267 | for (i = 2; i < 18; i++) |
254 | { | 268 | { |
255 | d = (buf[i] >> 4) & 15; | 269 | d = (buf[bufoff+i] >> 4) & 15; |
256 | if (d & 8) d-= 16; | 270 | if (d & 8) d-= 16; |
257 | ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14; | 271 | ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14; |
258 | if (ch1_0 > 32767) ch1_0 = 32767; | 272 | if (ch1_0 > 32767) ch1_0 = 32767; |
@@ -260,8 +274,7 @@ next_track: | |||
260 | samples[sampleswritten] = ch1_0; | 274 | samples[sampleswritten] = ch1_0; |
261 | sampleswritten+=channels; | 275 | sampleswritten+=channels; |
262 | ch1_2 = ch1_1; ch1_1 = ch1_0; | 276 | ch1_2 = ch1_1; ch1_1 = ch1_0; |
263 | 277 | d = buf[bufoff+i] & 15; | |
264 | d = buf[i] & 15; | ||
265 | if (d & 8) d -= 16; | 278 | if (d & 8) d -= 16; |
266 | ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14; | 279 | ch1_0 = (d*scale + 0x7298L*ch1_1 - 0x3350L*ch1_2) >> 14; |
267 | if (ch1_0 > 32767) ch1_0 = 32767; | 280 | if (ch1_0 > 32767) ch1_0 = 32767; |
@@ -271,28 +284,16 @@ next_track: | |||
271 | ch1_2 = ch1_1; ch1_1 = ch1_0; | 284 | ch1_2 = ch1_1; ch1_1 = ch1_0; |
272 | } | 285 | } |
273 | bufoff+=18; | 286 | bufoff+=18; |
274 | ci->advance_buffer(18); | ||
275 | 287 | ||
276 | if (channels == 2) { | 288 | if (channels == 2) { |
277 | /* decode second channel */ | 289 | int32_t scale = ((buf[bufoff] << 8)|(buf[bufoff+1]))*BASE_VOL; |
278 | int32_t scale; | ||
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 | 290 | ||
291 | int32_t ch2_0, d; | ||
291 | sampleswritten-=63; | 292 | sampleswritten-=63; |
292 | 293 | ||
293 | for (i = 2; i < 18; i++) | 294 | for (i = 2; i < 18; i++) |
294 | { | 295 | { |
295 | d = (buf[i] >> 4) & 15; | 296 | d = (buf[bufoff+i] >> 4) & 15; |
296 | if (d & 8) d-= 16; | 297 | if (d & 8) d-= 16; |
297 | ch2_0 = (d*scale + 0x7298L*ch2_1 - 0x3350L*ch2_2) >> 14; | 298 | ch2_0 = (d*scale + 0x7298L*ch2_1 - 0x3350L*ch2_2) >> 14; |
298 | if (ch2_0 > 32767) ch2_0 = 32767; | 299 | if (ch2_0 > 32767) ch2_0 = 32767; |
@@ -300,8 +301,7 @@ next_track: | |||
300 | samples[sampleswritten] = ch2_0; | 301 | samples[sampleswritten] = ch2_0; |
301 | sampleswritten+=2; | 302 | sampleswritten+=2; |
302 | ch2_2 = ch2_1; ch2_1 = ch2_0; | 303 | ch2_2 = ch2_1; ch2_1 = ch2_0; |
303 | 304 | d = buf[bufoff+i] & 15; | |
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,10 +311,8 @@ 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); | ||
315 | sampleswritten--; /* go back to first channel's next sample */ | 314 | sampleswritten--; /* go back to first channel's next sample */ |
316 | } | 315 | } |
317 | |||
318 | if (fade_count>0) { | 316 | if (fade_count>0) { |
319 | fade_count--; | 317 | fade_count--; |
320 | for (i=0;i<(channels==1?32:64);i++) samples[sampleswritten-i-1]= | 318 | for (i=0;i<(channels==1?32:64);i++) samples[sampleswritten-i-1]= |