diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2013-05-21 16:51:23 -0400 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2013-05-21 16:59:58 -0400 |
commit | 1f76edabf9dca3b1cb25de77f6572a12370e35c4 (patch) | |
tree | da912dd9a37468c6ed4ca6ca8e2bcbced037c47f /lib/rbcodec | |
parent | de86b4a3c5f6e2add2dc7588e6be37c8df2302f0 (diff) | |
download | rockbox-1f76edabf9dca3b1cb25de77f6572a12370e35c4.tar.gz rockbox-1f76edabf9dca3b1cb25de77f6572a12370e35c4.zip |
SPC Codec: Need to restore a bit more data from cached waves.
'Nuff said. Last update wasn't quite right.
Change-Id: I082a79c4e0c82b968fe2375cb82ee5c3a64a208b
Diffstat (limited to 'lib/rbcodec')
-rw-r--r-- | lib/rbcodec/codecs/libspc/spc_codec.h | 21 | ||||
-rw-r--r-- | lib/rbcodec/codecs/libspc/spc_dsp.c | 91 |
2 files changed, 53 insertions, 59 deletions
diff --git a/lib/rbcodec/codecs/libspc/spc_codec.h b/lib/rbcodec/codecs/libspc/spc_codec.h index 9686694134..fad5a49916 100644 --- a/lib/rbcodec/codecs/libspc/spc_codec.h +++ b/lib/rbcodec/codecs/libspc/spc_codec.h | |||
@@ -272,18 +272,21 @@ enum state_t | |||
272 | state_release = 2 | 272 | state_release = 2 |
273 | }; | 273 | }; |
274 | 274 | ||
275 | enum { BRR_BLOCK_SIZE = 16 }; | ||
276 | |||
277 | #if SPC_BRRCACHE | ||
275 | struct cache_entry_t | 278 | struct cache_entry_t |
276 | { | 279 | { |
277 | int16_t const* samples; | 280 | int16_t const* samples; /* decoded samples (cached) */ |
278 | unsigned end; /* past-the-end position */ | 281 | unsigned end; /* past-the-end position (cached) */ |
279 | unsigned loop; /* number of samples in loop */ | 282 | unsigned loop; /* number of samples in loop (cached) */ |
280 | unsigned start_addr; | 283 | uint16_t start_addr; /* RAM start address */ |
284 | uint16_t loop_addr; /* RAM loop address */ | ||
285 | uint8_t block_header; /* final wave block header */ | ||
281 | }; | 286 | }; |
282 | 287 | ||
283 | enum { BRR_BLOCK_SIZE = 16 }; | ||
284 | enum { BRR_CACHE_SIZE = 0x20000 + 32}; | 288 | enum { BRR_CACHE_SIZE = 0x20000 + 32}; |
285 | 289 | ||
286 | #if SPC_BRRCACHE | ||
287 | struct voice_wave_t | 290 | struct voice_wave_t |
288 | { | 291 | { |
289 | int16_t const* samples; /* decoded samples in cache */ | 292 | int16_t const* samples; /* decoded samples in cache */ |
@@ -291,7 +294,7 @@ struct voice_wave_t | |||
291 | long end; /* end position in samples buffer */ | 294 | long end; /* end position in samples buffer */ |
292 | int loop; /* length of looping area */ | 295 | int loop; /* length of looping area */ |
293 | unsigned block_header; /* header byte from current BRR block */ | 296 | unsigned block_header; /* header byte from current BRR block */ |
294 | uint8_t const* addr; /* BRR waveform address in RAM */ | 297 | unsigned start_addr; /* BRR waveform address in RAM */ |
295 | unsigned loop_addr; /* Loop address in RAM */ | 298 | unsigned loop_addr; /* Loop address in RAM */ |
296 | }; | 299 | }; |
297 | #else /* !SPC_BRRCACHE */ | 300 | #else /* !SPC_BRRCACHE */ |
@@ -300,7 +303,7 @@ struct voice_wave_t | |||
300 | int16_t samples [3 + BRR_BLOCK_SIZE + 1]; /* last decoded block */ | 303 | int16_t samples [3 + BRR_BLOCK_SIZE + 1]; /* last decoded block */ |
301 | int32_t position; /* position in samples buffer, 12-bit frac */ | 304 | int32_t position; /* position in samples buffer, 12-bit frac */ |
302 | unsigned block_header; /* header byte from current BRR block */ | 305 | unsigned block_header; /* header byte from current BRR block */ |
303 | uint8_t const* addr; /* BRR waveform address in RAM */ | 306 | unsigned start_addr; /* BRR waveform address in RAM */ |
304 | }; | 307 | }; |
305 | #endif /* SPC_BRRCACHE */ | 308 | #endif /* SPC_BRRCACHE */ |
306 | 309 | ||
@@ -359,7 +362,7 @@ struct Spc_Dsp | |||
359 | #endif /* !SPC_NOECHO */ | 362 | #endif /* !SPC_NOECHO */ |
360 | 363 | ||
361 | #if SPC_BRRCACHE | 364 | #if SPC_BRRCACHE |
362 | uint8_t oldsize; | 365 | unsigned oldsize; |
363 | struct cache_entry_t wave_entry [256]; | 366 | struct cache_entry_t wave_entry [256]; |
364 | struct cache_entry_t wave_entry_old [256]; | 367 | struct cache_entry_t wave_entry_old [256]; |
365 | #endif | 368 | #endif |
diff --git a/lib/rbcodec/codecs/libspc/spc_dsp.c b/lib/rbcodec/codecs/libspc/spc_dsp.c index 0df0ab04f7..6ad194aba6 100644 --- a/lib/rbcodec/codecs/libspc/spc_dsp.c +++ b/lib/rbcodec/codecs/libspc/spc_dsp.c | |||
@@ -154,15 +154,14 @@ void DSP_write( struct Spc_Dsp* this, int i, int data ) | |||
154 | 154 | ||
155 | /* Decode BRR block */ | 155 | /* Decode BRR block */ |
156 | static inline void | 156 | static inline void |
157 | decode_brr_block( struct voice_t* voice, uint8_t const* addr, int16_t* out ) | 157 | decode_brr_block( struct voice_t* voice, unsigned start_addr, int16_t* out ) |
158 | { | 158 | { |
159 | /* header */ | 159 | /* header */ |
160 | unsigned block_header = *addr; | 160 | start_addr += 9; /* point to next header */ |
161 | uint8_t const* addr = ram.ram + start_addr; | ||
162 | unsigned block_header = addr[-9]; | ||
161 | voice->wave.block_header = block_header; | 163 | voice->wave.block_header = block_header; |
162 | 164 | voice->wave.start_addr = start_addr; | |
163 | /* point to next header */ | ||
164 | addr += 9; | ||
165 | voice->wave.addr = addr; | ||
166 | 165 | ||
167 | /* previous samples */ | 166 | /* previous samples */ |
168 | int smp2 = out [0]; | 167 | int smp2 = out [0]; |
@@ -318,20 +317,15 @@ brr_decode_cache( struct Spc_Dsp* this, struct src_dir const* sd, | |||
318 | /* a little extra for samples that go past end */ | 317 | /* a little extra for samples that go past end */ |
319 | static int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR; | 318 | static int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR; |
320 | 319 | ||
321 | DEBUGF( "decode at %08x (wave #%d)\n", start_addr, waveform ); | 320 | DEBUGF( "decode at %04x (wave #%u)\n", start_addr, waveform ); |
322 | 321 | ||
323 | struct cache_entry_t* const wave_entry = &this->wave_entry [waveform]; | 322 | struct cache_entry_t* const wave_entry = &this->wave_entry [waveform]; |
324 | |||
325 | wave_entry->start_addr = start_addr; | 323 | wave_entry->start_addr = start_addr; |
326 | 324 | ||
327 | unsigned loop_addr = letoh16( sd [waveform].loop ); | 325 | unsigned const loop_addr = letoh16( sd [waveform].loop ); |
328 | uint8_t const* const loop_ptr = ram.ram + loop_addr; | ||
329 | |||
330 | DEBUGF( "loop addr at %08x\n", (unsigned)loop_addr ); | ||
331 | |||
332 | int16_t* loop_start = NULL; | 326 | int16_t* loop_start = NULL; |
333 | 327 | ||
334 | uint8_t const* addr = ram.ram + start_addr; | 328 | DEBUGF( "loop addr at %04x (wave #%u)\n", loop_addr, waveform ); |
335 | 329 | ||
336 | int16_t* out = BRRcache + start_addr * 2; | 330 | int16_t* out = BRRcache + start_addr * 2; |
337 | wave_entry->samples = out; | 331 | wave_entry->samples = out; |
@@ -350,35 +344,36 @@ brr_decode_cache( struct Spc_Dsp* this, struct src_dir const* sd, | |||
350 | 344 | ||
351 | do | 345 | do |
352 | { | 346 | { |
353 | if ( addr == loop_ptr ) | 347 | if ( start_addr == loop_addr ) |
354 | { | 348 | { |
355 | loop_start = out; | 349 | loop_start = out; |
356 | DEBUGF( "loop found at %08lx (wave #%d)\n", | 350 | DEBUGF( "loop found at %04x (wave #%u)\n", start_addr, waveform ); |
357 | (unsigned long)(addr - RAM), waveform ); | ||
358 | } | 351 | } |
359 | 352 | ||
360 | /* output position - preincrement */ | 353 | /* output position - preincrement */ |
361 | out += BRR_BLOCK_SIZE; | 354 | out += BRR_BLOCK_SIZE; |
362 | 355 | ||
363 | decode_brr_block( voice, addr, out ); | 356 | decode_brr_block( voice, start_addr, out ); |
364 | 357 | ||
365 | block_header = voice->wave.block_header; | 358 | block_header = voice->wave.block_header; |
366 | addr = voice->wave.addr; | 359 | start_addr = voice->wave.start_addr; |
367 | 360 | ||
368 | /* if next block has end flag set, this block ends early */ | 361 | /* if next block has end flag set, this block ends early */ |
369 | /* (verified) */ | 362 | /* (verified) */ |
370 | if ( (block_header & 3) != 3 && (*addr & 3) == 1 ) | 363 | if ( (block_header & 3) != 3 && (start_addr[ram.ram] & 3) == 1 ) |
371 | { | 364 | { |
372 | /* skip last 9 samples */ | 365 | /* skip last 9 samples */ |
373 | DEBUGF( "block early end\n" ); | 366 | DEBUGF( "block early end (wave #%u)\n", waveform ); |
374 | out -= 9; | 367 | out -= 9; |
375 | break; | 368 | break; |
376 | } | 369 | } |
377 | } | 370 | } |
378 | while ( !(block_header & 1) && addr < RAM + 0x10000 ); | 371 | while ( !(block_header & 1) && start_addr < 0x10000 ); |
379 | 372 | ||
380 | wave_entry->end = (out - 1 - wave_entry->samples) << 12; | 373 | wave_entry->end = (out - 1 - wave_entry->samples) << 12; |
381 | wave_entry->loop = 0; | 374 | wave_entry->loop = 0; |
375 | wave_entry->loop_addr = 0; | ||
376 | wave_entry->block_header = block_header; | ||
382 | 377 | ||
383 | if ( (block_header & 2) ) | 378 | if ( (block_header & 2) ) |
384 | { | 379 | { |
@@ -399,10 +394,11 @@ brr_decode_cache( struct Spc_Dsp* this, struct src_dir const* sd, | |||
399 | next [BRR_BLOCK_SIZE + 1] = out [0]; | 394 | next [BRR_BLOCK_SIZE + 1] = out [0]; |
400 | next [BRR_BLOCK_SIZE + 2] = out [1]; | 395 | next [BRR_BLOCK_SIZE + 2] = out [1]; |
401 | } | 396 | } |
397 | |||
398 | wave_entry->loop_addr = loop_addr; | ||
402 | } | 399 | } |
403 | 400 | ||
404 | DEBUGF( "end at %08lx (wave #%d)\n", | 401 | DEBUGF( "end at %04x (wave #%u)\n\n", start_addr, waveform ); |
405 | (unsigned long)(addr - RAM), waveform ); | ||
406 | 402 | ||
407 | /* add to cache */ | 403 | /* add to cache */ |
408 | this->wave_entry_old [this->oldsize++] = *wave_entry; | 404 | this->wave_entry_old [this->oldsize++] = *wave_entry; |
@@ -416,15 +412,15 @@ brr_probe_cache( struct Spc_Dsp* this, unsigned start_addr, | |||
416 | if ( wave_entry->start_addr == start_addr ) | 412 | if ( wave_entry->start_addr == start_addr ) |
417 | return true; | 413 | return true; |
418 | 414 | ||
419 | for ( int i = 0; i < this->oldsize; i++ ) | 415 | for ( unsigned i = 0; i < this->oldsize; i++ ) |
420 | { | 416 | { |
421 | struct cache_entry_t* e = &this->wave_entry_old [i]; | 417 | struct cache_entry_t* e = &this->wave_entry_old [i]; |
422 | 418 | ||
423 | if ( e->start_addr == start_addr ) | 419 | if ( e->start_addr == start_addr ) |
424 | { | 420 | { |
425 | #if 0 /* do NOT want to see all the key down stuff for cached waves */ | 421 | #if 0 /* do NOT want to see all the key down stuff for cached waves */ |
426 | DEBUGF( "found in wave_entry_old (oldsize=%d)\n", | 422 | DEBUGF( "found in wave_entry_old (oldsize=%u)\n", |
427 | this->oldsize ); | 423 | this->oldsize ); |
428 | #endif | 424 | #endif |
429 | *wave_entry = *e; | 425 | *wave_entry = *e; |
430 | return true; /* Wave in cache */ | 426 | return true; /* Wave in cache */ |
@@ -458,11 +454,13 @@ brr_key_on( struct Spc_Dsp* this, struct src_dir const* sd, | |||
458 | initial_point ); | 454 | initial_point ); |
459 | } | 455 | } |
460 | 456 | ||
461 | voice->wave.position = 3 * 0x1000 - 1; /* 0x2fff */ | 457 | voice->wave.position = 3 * 0x1000 - 1; /* 0x2fff */ |
462 | voice->wave.samples = wave_entry->samples; | 458 | voice->wave.samples = wave_entry->samples; |
463 | voice->wave.end = wave_entry->end; | 459 | voice->wave.end = wave_entry->end; |
464 | voice->wave.loop = wave_entry->loop; | 460 | voice->wave.loop = wave_entry->loop; |
465 | voice->wave.loop_addr = letoh16( sd [waveform].loop ); | 461 | voice->wave.start_addr = wave_entry->start_addr; |
462 | voice->wave.loop_addr = wave_entry->loop_addr; | ||
463 | voice->wave.block_header = wave_entry->block_header; | ||
466 | } | 464 | } |
467 | 465 | ||
468 | static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd, | 466 | static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd, |
@@ -496,7 +494,7 @@ brr_key_on( struct Spc_Dsp* this, struct src_dir const* sd, | |||
496 | struct voice_t* voice, struct raw_voice_t const* raw_voice, | 494 | struct voice_t* voice, struct raw_voice_t const* raw_voice, |
497 | unsigned start_addr ) | 495 | unsigned start_addr ) |
498 | { | 496 | { |
499 | voice->wave.addr = ram.ram + letoh16( sd [raw_voice->waveform].start ); | 497 | voice->wave.start_addr = letoh16( sd [raw_voice->waveform].start ); |
500 | /* BRR filter uses previous samples */ | 498 | /* BRR filter uses previous samples */ |
501 | voice->wave.samples [BRR_BLOCK_SIZE + 1] = 0; | 499 | voice->wave.samples [BRR_BLOCK_SIZE + 1] = 0; |
502 | voice->wave.samples [BRR_BLOCK_SIZE + 2] = 0; | 500 | voice->wave.samples [BRR_BLOCK_SIZE + 2] = 0; |
@@ -510,23 +508,15 @@ static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd, | |||
510 | struct voice_t* voice, | 508 | struct voice_t* voice, |
511 | struct raw_voice_t const* raw_voice ) | 509 | struct raw_voice_t const* raw_voice ) |
512 | { | 510 | { |
513 | #undef RAM | ||
514 | #if defined(CPU_ARM) && !SPC_BRRCACHE | ||
515 | uint8_t* const ram_ = ram.ram; | ||
516 | #define RAM ram_ | ||
517 | #else | ||
518 | #define RAM ram.ram | ||
519 | #endif | ||
520 | |||
521 | if ( voice->wave.position < BRR_BLOCK_SIZE * 0x1000 ) | 511 | if ( voice->wave.position < BRR_BLOCK_SIZE * 0x1000 ) |
522 | return 0; | 512 | return 0; |
523 | 513 | ||
524 | voice->wave.position -= BRR_BLOCK_SIZE * 0x1000; | 514 | voice->wave.position -= BRR_BLOCK_SIZE * 0x1000; |
525 | 515 | ||
526 | uint8_t const* addr = voice->wave.addr; | 516 | unsigned start_addr = voice->wave.start_addr; |
527 | 517 | ||
528 | if ( addr >= RAM + 0x10000 ) | 518 | if ( start_addr >= 0x10000 ) |
529 | addr -= 0x10000; | 519 | start_addr -= 0x10000; |
530 | 520 | ||
531 | unsigned block_header = voice->wave.block_header; | 521 | unsigned block_header = voice->wave.block_header; |
532 | 522 | ||
@@ -535,7 +525,7 @@ static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd, | |||
535 | 525 | ||
536 | if ( block_header & 1 ) | 526 | if ( block_header & 1 ) |
537 | { | 527 | { |
538 | addr = RAM + letoh16( sd [raw_voice->waveform].loop ); | 528 | start_addr = letoh16( sd [raw_voice->waveform].loop ); |
539 | dec = 1; | 529 | dec = 1; |
540 | 530 | ||
541 | if ( !(block_header & 2) ) /* 1% of the time */ | 531 | if ( !(block_header & 2) ) /* 1% of the time */ |
@@ -546,7 +536,8 @@ static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd, | |||
546 | } | 536 | } |
547 | } | 537 | } |
548 | 538 | ||
549 | decode_brr_block( voice, addr, &voice->wave.samples [1 + BRR_BLOCK_SIZE] ); | 539 | decode_brr_block( voice, start_addr, |
540 | &voice->wave.samples [1 + BRR_BLOCK_SIZE] ); | ||
550 | 541 | ||
551 | return dec; | 542 | return dec; |
552 | (void)this; | 543 | (void)this; |
@@ -956,13 +947,13 @@ void DSP_reset( struct Spc_Dsp* this ) | |||
956 | { | 947 | { |
957 | struct voice_t* v = this->voice_state + i; | 948 | struct voice_t* v = this->voice_state + i; |
958 | v->env_mode = state_release; | 949 | v->env_mode = state_release; |
959 | v->wave.addr = ram.ram; | 950 | v->wave.start_addr = 0; |
960 | } | 951 | } |
961 | 952 | ||
962 | #if SPC_BRRCACHE | 953 | #if SPC_BRRCACHE |
963 | this->oldsize = 0; | 954 | this->oldsize = 0; |
964 | for ( int i = 0; i < 256; i++ ) | 955 | for ( int i = 0; i < 256; i++ ) |
965 | this->wave_entry [i].start_addr = -1; | 956 | this->wave_entry [i].start_addr = 0xffff; |
966 | #endif /* SPC_BRRCACHE */ | 957 | #endif /* SPC_BRRCACHE */ |
967 | 958 | ||
968 | #if !SPC_NOECHO | 959 | #if !SPC_NOECHO |