diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/adx.c | 106 |
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]= |