mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 08:03:04 -04:00
libdemac: reciprocal table for the pivot division on ARMv5+
Of the two divisions a sample left in the entropy decoder, the first divides the range by the Rice pivot, which is small: below 1024 for 99.9% of the samples of a 16-bit test file and never as much as 4096. Keep a table of reciprocals, filled in as divisors turn up, and divide with a 32x32->64 multiply and one correction. Larger divisors go to the division routine as before. The other division, by help, has no such pattern. This is for ARMv5 and later without a hardware divide. ARMv4 has its own divider with a reciprocal table already, and a long multiply is slow there; its codec is unchanged. The table is 16 KB of bss. With r = (2^32 - 1) / n the estimate is the quotient or one less for any 32-bit numerator, checked against true division for every n below 4096. MHz for real time in perfsim's model of the Clip+, -c1000, -c2000 and -c3000: 32.5, 48.4, 76.4 to 30.1, 46.0, 74.0. A Clip+ measures 30.63 at -c1000, from 32.85, with the same checksum, 1008ffab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: I555ff83d7e19919848c8fb7b8d12ecfa671a976b
This commit is contained in:
parent
aa7ebbe057
commit
a6b7321d9f
1 changed files with 32 additions and 1 deletions
|
|
@ -184,6 +184,37 @@ DEMAC_INLINE void range_dec_normalize(struct rangecoder_t* rc)
|
|||
}
|
||||
}
|
||||
|
||||
/* range / tot_f. tot_f is the Rice pivot, which is small (below 1024
|
||||
for nearly every sample of ordinary 16-bit audio), so where a 32x32->64
|
||||
multiply is cheap its reciprocal comes from a table that is filled in as
|
||||
divisors turn up, and the division is a multiply and a correction. The
|
||||
other division, by help, has no such pattern. */
|
||||
#if defined(CPU_ARM) && ARM_ARCH >= 5 && !defined(ARM_HAVE_HW_DIV)
|
||||
#define RECIP_ENTRIES 4096
|
||||
/* recip[n] is (2^32 - 1) / n, which is never 0: 0 is "not worked out" */
|
||||
static uint32_t recip[RECIP_ENTRIES];
|
||||
|
||||
DEMAC_INLINE uint32_t range_div(uint32_t range, uint32_t tot_f)
|
||||
{
|
||||
uint32_t r, q;
|
||||
|
||||
if (UNLIKELY(tot_f >= RECIP_ENTRIES))
|
||||
return UDIV32(range, tot_f);
|
||||
|
||||
r = recip[tot_f];
|
||||
if (UNLIKELY(r == 0))
|
||||
r = recip[tot_f] = UDIV32(0xffffffff, tot_f);
|
||||
|
||||
/* this is the quotient or one less */
|
||||
q = ((uint64_t)range * r) >> 32;
|
||||
if (range - q * tot_f >= tot_f)
|
||||
q++;
|
||||
return q;
|
||||
}
|
||||
#else
|
||||
#define range_div(range, tot_f) UDIV32(range, tot_f)
|
||||
#endif
|
||||
|
||||
/* Calculate culmulative frequency for next symbol. Does NO update!*/
|
||||
/* tot_f is the total frequency */
|
||||
/* or: totf is (code_value)1<<shift */
|
||||
|
|
@ -191,7 +222,7 @@ DEMAC_INLINE void range_dec_normalize(struct rangecoder_t* rc)
|
|||
DEMAC_INLINE int range_decode_culfreq(struct rangecoder_t* rc, int tot_f)
|
||||
{
|
||||
range_dec_normalize(rc);
|
||||
rc->help = UDIV32(rc->range, tot_f);
|
||||
rc->help = range_div(rc->range, tot_f);
|
||||
return UDIV32(rc->low, rc->help);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue