mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
SPC Codec: Need to restore a bit more data from cached waves.
'Nuff said. Last update wasn't quite right. Change-Id: I082a79c4e0c82b968fe2375cb82ee5c3a64a208b
This commit is contained in:
parent
de86b4a3c5
commit
1f76edabf9
2 changed files with 56 additions and 62 deletions
|
@ -272,18 +272,21 @@ enum state_t
|
||||||
state_release = 2
|
state_release = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cache_entry_t
|
|
||||||
{
|
|
||||||
int16_t const* samples;
|
|
||||||
unsigned end; /* past-the-end position */
|
|
||||||
unsigned loop; /* number of samples in loop */
|
|
||||||
unsigned start_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum { BRR_BLOCK_SIZE = 16 };
|
enum { BRR_BLOCK_SIZE = 16 };
|
||||||
enum { BRR_CACHE_SIZE = 0x20000 + 32};
|
|
||||||
|
|
||||||
#if SPC_BRRCACHE
|
#if SPC_BRRCACHE
|
||||||
|
struct cache_entry_t
|
||||||
|
{
|
||||||
|
int16_t const* samples; /* decoded samples (cached) */
|
||||||
|
unsigned end; /* past-the-end position (cached) */
|
||||||
|
unsigned loop; /* number of samples in loop (cached) */
|
||||||
|
uint16_t start_addr; /* RAM start address */
|
||||||
|
uint16_t loop_addr; /* RAM loop address */
|
||||||
|
uint8_t block_header; /* final wave block header */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { BRR_CACHE_SIZE = 0x20000 + 32};
|
||||||
|
|
||||||
struct voice_wave_t
|
struct voice_wave_t
|
||||||
{
|
{
|
||||||
int16_t const* samples; /* decoded samples in cache */
|
int16_t const* samples; /* decoded samples in cache */
|
||||||
|
@ -291,7 +294,7 @@ struct voice_wave_t
|
||||||
long end; /* end position in samples buffer */
|
long end; /* end position in samples buffer */
|
||||||
int loop; /* length of looping area */
|
int loop; /* length of looping area */
|
||||||
unsigned block_header; /* header byte from current BRR block */
|
unsigned block_header; /* header byte from current BRR block */
|
||||||
uint8_t const* addr; /* BRR waveform address in RAM */
|
unsigned start_addr; /* BRR waveform address in RAM */
|
||||||
unsigned loop_addr; /* Loop address in RAM */
|
unsigned loop_addr; /* Loop address in RAM */
|
||||||
};
|
};
|
||||||
#else /* !SPC_BRRCACHE */
|
#else /* !SPC_BRRCACHE */
|
||||||
|
@ -300,7 +303,7 @@ struct voice_wave_t
|
||||||
int16_t samples [3 + BRR_BLOCK_SIZE + 1]; /* last decoded block */
|
int16_t samples [3 + BRR_BLOCK_SIZE + 1]; /* last decoded block */
|
||||||
int32_t position; /* position in samples buffer, 12-bit frac */
|
int32_t position; /* position in samples buffer, 12-bit frac */
|
||||||
unsigned block_header; /* header byte from current BRR block */
|
unsigned block_header; /* header byte from current BRR block */
|
||||||
uint8_t const* addr; /* BRR waveform address in RAM */
|
unsigned start_addr; /* BRR waveform address in RAM */
|
||||||
};
|
};
|
||||||
#endif /* SPC_BRRCACHE */
|
#endif /* SPC_BRRCACHE */
|
||||||
|
|
||||||
|
@ -359,7 +362,7 @@ struct Spc_Dsp
|
||||||
#endif /* !SPC_NOECHO */
|
#endif /* !SPC_NOECHO */
|
||||||
|
|
||||||
#if SPC_BRRCACHE
|
#if SPC_BRRCACHE
|
||||||
uint8_t oldsize;
|
unsigned oldsize;
|
||||||
struct cache_entry_t wave_entry [256];
|
struct cache_entry_t wave_entry [256];
|
||||||
struct cache_entry_t wave_entry_old [256];
|
struct cache_entry_t wave_entry_old [256];
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -154,15 +154,14 @@ void DSP_write( struct Spc_Dsp* this, int i, int data )
|
||||||
|
|
||||||
/* Decode BRR block */
|
/* Decode BRR block */
|
||||||
static inline void
|
static inline void
|
||||||
decode_brr_block( struct voice_t* voice, uint8_t const* addr, int16_t* out )
|
decode_brr_block( struct voice_t* voice, unsigned start_addr, int16_t* out )
|
||||||
{
|
{
|
||||||
/* header */
|
/* header */
|
||||||
unsigned block_header = *addr;
|
start_addr += 9; /* point to next header */
|
||||||
|
uint8_t const* addr = ram.ram + start_addr;
|
||||||
|
unsigned block_header = addr[-9];
|
||||||
voice->wave.block_header = block_header;
|
voice->wave.block_header = block_header;
|
||||||
|
voice->wave.start_addr = start_addr;
|
||||||
/* point to next header */
|
|
||||||
addr += 9;
|
|
||||||
voice->wave.addr = addr;
|
|
||||||
|
|
||||||
/* previous samples */
|
/* previous samples */
|
||||||
int smp2 = out [0];
|
int smp2 = out [0];
|
||||||
|
@ -318,20 +317,15 @@ brr_decode_cache( struct Spc_Dsp* this, struct src_dir const* sd,
|
||||||
/* a little extra for samples that go past end */
|
/* a little extra for samples that go past end */
|
||||||
static int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR;
|
static int16_t BRRcache [BRR_CACHE_SIZE] CACHEALIGN_ATTR;
|
||||||
|
|
||||||
DEBUGF( "decode at %08x (wave #%d)\n", start_addr, waveform );
|
DEBUGF( "decode at %04x (wave #%u)\n", start_addr, waveform );
|
||||||
|
|
||||||
struct cache_entry_t* const wave_entry = &this->wave_entry [waveform];
|
struct cache_entry_t* const wave_entry = &this->wave_entry [waveform];
|
||||||
|
|
||||||
wave_entry->start_addr = start_addr;
|
wave_entry->start_addr = start_addr;
|
||||||
|
|
||||||
unsigned loop_addr = letoh16( sd [waveform].loop );
|
unsigned const loop_addr = letoh16( sd [waveform].loop );
|
||||||
uint8_t const* const loop_ptr = ram.ram + loop_addr;
|
|
||||||
|
|
||||||
DEBUGF( "loop addr at %08x\n", (unsigned)loop_addr );
|
|
||||||
|
|
||||||
int16_t* loop_start = NULL;
|
int16_t* loop_start = NULL;
|
||||||
|
|
||||||
uint8_t const* addr = ram.ram + start_addr;
|
DEBUGF( "loop addr at %04x (wave #%u)\n", loop_addr, waveform );
|
||||||
|
|
||||||
int16_t* out = BRRcache + start_addr * 2;
|
int16_t* out = BRRcache + start_addr * 2;
|
||||||
wave_entry->samples = out;
|
wave_entry->samples = out;
|
||||||
|
@ -350,35 +344,36 @@ brr_decode_cache( struct Spc_Dsp* this, struct src_dir const* sd,
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ( addr == loop_ptr )
|
if ( start_addr == loop_addr )
|
||||||
{
|
{
|
||||||
loop_start = out;
|
loop_start = out;
|
||||||
DEBUGF( "loop found at %08lx (wave #%d)\n",
|
DEBUGF( "loop found at %04x (wave #%u)\n", start_addr, waveform );
|
||||||
(unsigned long)(addr - RAM), waveform );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output position - preincrement */
|
/* output position - preincrement */
|
||||||
out += BRR_BLOCK_SIZE;
|
out += BRR_BLOCK_SIZE;
|
||||||
|
|
||||||
decode_brr_block( voice, addr, out );
|
decode_brr_block( voice, start_addr, out );
|
||||||
|
|
||||||
block_header = voice->wave.block_header;
|
block_header = voice->wave.block_header;
|
||||||
addr = voice->wave.addr;
|
start_addr = voice->wave.start_addr;
|
||||||
|
|
||||||
/* if next block has end flag set, this block ends early */
|
/* if next block has end flag set, this block ends early */
|
||||||
/* (verified) */
|
/* (verified) */
|
||||||
if ( (block_header & 3) != 3 && (*addr & 3) == 1 )
|
if ( (block_header & 3) != 3 && (start_addr[ram.ram] & 3) == 1 )
|
||||||
{
|
{
|
||||||
/* skip last 9 samples */
|
/* skip last 9 samples */
|
||||||
DEBUGF( "block early end\n" );
|
DEBUGF( "block early end (wave #%u)\n", waveform );
|
||||||
out -= 9;
|
out -= 9;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ( !(block_header & 1) && addr < RAM + 0x10000 );
|
while ( !(block_header & 1) && start_addr < 0x10000 );
|
||||||
|
|
||||||
wave_entry->end = (out - 1 - wave_entry->samples) << 12;
|
wave_entry->end = (out - 1 - wave_entry->samples) << 12;
|
||||||
wave_entry->loop = 0;
|
wave_entry->loop = 0;
|
||||||
|
wave_entry->loop_addr = 0;
|
||||||
|
wave_entry->block_header = block_header;
|
||||||
|
|
||||||
if ( (block_header & 2) )
|
if ( (block_header & 2) )
|
||||||
{
|
{
|
||||||
|
@ -399,10 +394,11 @@ brr_decode_cache( struct Spc_Dsp* this, struct src_dir const* sd,
|
||||||
next [BRR_BLOCK_SIZE + 1] = out [0];
|
next [BRR_BLOCK_SIZE + 1] = out [0];
|
||||||
next [BRR_BLOCK_SIZE + 2] = out [1];
|
next [BRR_BLOCK_SIZE + 2] = out [1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wave_entry->loop_addr = loop_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGF( "end at %08lx (wave #%d)\n",
|
DEBUGF( "end at %04x (wave #%u)\n\n", start_addr, waveform );
|
||||||
(unsigned long)(addr - RAM), waveform );
|
|
||||||
|
|
||||||
/* add to cache */
|
/* add to cache */
|
||||||
this->wave_entry_old [this->oldsize++] = *wave_entry;
|
this->wave_entry_old [this->oldsize++] = *wave_entry;
|
||||||
|
@ -416,15 +412,15 @@ brr_probe_cache( struct Spc_Dsp* this, unsigned start_addr,
|
||||||
if ( wave_entry->start_addr == start_addr )
|
if ( wave_entry->start_addr == start_addr )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for ( int i = 0; i < this->oldsize; i++ )
|
for ( unsigned i = 0; i < this->oldsize; i++ )
|
||||||
{
|
{
|
||||||
struct cache_entry_t* e = &this->wave_entry_old [i];
|
struct cache_entry_t* e = &this->wave_entry_old [i];
|
||||||
|
|
||||||
if ( e->start_addr == start_addr )
|
if ( e->start_addr == start_addr )
|
||||||
{
|
{
|
||||||
#if 0 /* do NOT want to see all the key down stuff for cached waves */
|
#if 0 /* do NOT want to see all the key down stuff for cached waves */
|
||||||
DEBUGF( "found in wave_entry_old (oldsize=%d)\n",
|
DEBUGF( "found in wave_entry_old (oldsize=%u)\n",
|
||||||
this->oldsize );
|
this->oldsize );
|
||||||
#endif
|
#endif
|
||||||
*wave_entry = *e;
|
*wave_entry = *e;
|
||||||
return true; /* Wave in cache */
|
return true; /* Wave in cache */
|
||||||
|
@ -458,11 +454,13 @@ brr_key_on( struct Spc_Dsp* this, struct src_dir const* sd,
|
||||||
initial_point );
|
initial_point );
|
||||||
}
|
}
|
||||||
|
|
||||||
voice->wave.position = 3 * 0x1000 - 1; /* 0x2fff */
|
voice->wave.position = 3 * 0x1000 - 1; /* 0x2fff */
|
||||||
voice->wave.samples = wave_entry->samples;
|
voice->wave.samples = wave_entry->samples;
|
||||||
voice->wave.end = wave_entry->end;
|
voice->wave.end = wave_entry->end;
|
||||||
voice->wave.loop = wave_entry->loop;
|
voice->wave.loop = wave_entry->loop;
|
||||||
voice->wave.loop_addr = letoh16( sd [waveform].loop );
|
voice->wave.start_addr = wave_entry->start_addr;
|
||||||
|
voice->wave.loop_addr = wave_entry->loop_addr;
|
||||||
|
voice->wave.block_header = wave_entry->block_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd,
|
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,
|
||||||
struct voice_t* voice, struct raw_voice_t const* raw_voice,
|
struct voice_t* voice, struct raw_voice_t const* raw_voice,
|
||||||
unsigned start_addr )
|
unsigned start_addr )
|
||||||
{
|
{
|
||||||
voice->wave.addr = ram.ram + letoh16( sd [raw_voice->waveform].start );
|
voice->wave.start_addr = letoh16( sd [raw_voice->waveform].start );
|
||||||
/* BRR filter uses previous samples */
|
/* BRR filter uses previous samples */
|
||||||
voice->wave.samples [BRR_BLOCK_SIZE + 1] = 0;
|
voice->wave.samples [BRR_BLOCK_SIZE + 1] = 0;
|
||||||
voice->wave.samples [BRR_BLOCK_SIZE + 2] = 0;
|
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,
|
||||||
struct voice_t* voice,
|
struct voice_t* voice,
|
||||||
struct raw_voice_t const* raw_voice )
|
struct raw_voice_t const* raw_voice )
|
||||||
{
|
{
|
||||||
#undef RAM
|
|
||||||
#if defined(CPU_ARM) && !SPC_BRRCACHE
|
|
||||||
uint8_t* const ram_ = ram.ram;
|
|
||||||
#define RAM ram_
|
|
||||||
#else
|
|
||||||
#define RAM ram.ram
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( voice->wave.position < BRR_BLOCK_SIZE * 0x1000 )
|
if ( voice->wave.position < BRR_BLOCK_SIZE * 0x1000 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
voice->wave.position -= BRR_BLOCK_SIZE * 0x1000;
|
voice->wave.position -= BRR_BLOCK_SIZE * 0x1000;
|
||||||
|
|
||||||
uint8_t const* addr = voice->wave.addr;
|
unsigned start_addr = voice->wave.start_addr;
|
||||||
|
|
||||||
if ( addr >= RAM + 0x10000 )
|
if ( start_addr >= 0x10000 )
|
||||||
addr -= 0x10000;
|
start_addr -= 0x10000;
|
||||||
|
|
||||||
unsigned block_header = voice->wave.block_header;
|
unsigned block_header = voice->wave.block_header;
|
||||||
|
|
||||||
|
@ -535,7 +525,7 @@ static inline int brr_decode( struct Spc_Dsp* this, struct src_dir const* sd,
|
||||||
|
|
||||||
if ( block_header & 1 )
|
if ( block_header & 1 )
|
||||||
{
|
{
|
||||||
addr = RAM + letoh16( sd [raw_voice->waveform].loop );
|
start_addr = letoh16( sd [raw_voice->waveform].loop );
|
||||||
dec = 1;
|
dec = 1;
|
||||||
|
|
||||||
if ( !(block_header & 2) ) /* 1% of the time */
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decode_brr_block( voice, addr, &voice->wave.samples [1 + BRR_BLOCK_SIZE] );
|
decode_brr_block( voice, start_addr,
|
||||||
|
&voice->wave.samples [1 + BRR_BLOCK_SIZE] );
|
||||||
|
|
||||||
return dec;
|
return dec;
|
||||||
(void)this;
|
(void)this;
|
||||||
|
@ -956,13 +947,13 @@ void DSP_reset( struct Spc_Dsp* this )
|
||||||
{
|
{
|
||||||
struct voice_t* v = this->voice_state + i;
|
struct voice_t* v = this->voice_state + i;
|
||||||
v->env_mode = state_release;
|
v->env_mode = state_release;
|
||||||
v->wave.addr = ram.ram;
|
v->wave.start_addr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SPC_BRRCACHE
|
#if SPC_BRRCACHE
|
||||||
this->oldsize = 0;
|
this->oldsize = 0;
|
||||||
for ( int i = 0; i < 256; i++ )
|
for ( int i = 0; i < 256; i++ )
|
||||||
this->wave_entry [i].start_addr = -1;
|
this->wave_entry [i].start_addr = 0xffff;
|
||||||
#endif /* SPC_BRRCACHE */
|
#endif /* SPC_BRRCACHE */
|
||||||
|
|
||||||
#if !SPC_NOECHO
|
#if !SPC_NOECHO
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue