ref: 428a77d6bddab3ea10e31de4b054430c137c8117
parent: 76ea41e17fb702fa86cfaf498579a421beaa0e0b
author: Timothy B. Terriberry <[email protected]>
date: Thu Dec 16 11:50:16 EST 2010
More cleanups to compute_allocation(). The bisection search in compute_allocation() was not using the same method to count psum as interp_bits2pulses, i.e., it did not include the 64*C<<BITRES<<LM allocation ceiling (this adds at most 84 max operations/frame, and so should have a trivial CPU cost). Again, I wouldn't want to try to explain why these are different in a spec, so let's make them the same. In addition, the procedure used to fill in bits1 and bits2 after the bisection search was not the same as the one used during the bisection search. I.e., the if (bits1[j] > 0) bits1[j] += trim_offset[j]; step was not also done for bits2, so bits1[j] + bits2[j] would not be equal to what was computed earlier for the hi line, and would not be guaranteed to be larger than total. We now compute both allocation lines in the same manner, and then obtain bits2 by subtracting them, instead of trying to compute the offset from bits1 up front. Finally, there was nothing to stop a bitstream from boosting a band beyond the number of bits remaining, which means that bits1 would not produce an allocation less than or equal to total, which means that some bands would receive a negative allocation in the decoder when the "left over" negative bits were redistributed to other bands. This patch only adds the dynalloc offset to allocation lines greater than 0, so that an all-zeros floor still exists; the effect is that a dynalloc boost gets linearly scaled between allocation lines 0 and 1, and is constant (like it was before) after that. We don't have to add the extra condition to the bisection search, because it never examines allocation line 0. This re-writes the indexing in the search to make that explicit; it was tested and gives exactly the same results in exactly the same number of iterations as the old search.
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -395,9 +395,9 @@
trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(alloc_trim-5-LM)*(m->nbEBands-j-1)
<<(LM+BITRES)>>6;
- lo = 0;
- hi = m->nbAllocVectors - 1;
- while (hi-lo != 1)
+ lo = 1;
+ hi = m->nbAllocVectors - 2;
+ do
{
int psum = 0;
int mid = (lo+hi) >> 1;
@@ -406,12 +406,10 @@
int N = m->eBands[j+1]-m->eBands[j];
bits1[j] = C*N*m->allocVectors[mid*len+j]<<LM>>2;
if (bits1[j] > 0)
- bits1[j] += trim_offset[j];
- if (bits1[j] < 0)
- bits1[j] = 0;
+ bits1[j] = IMAX(0, bits1[j] + trim_offset[j]);
bits1[j] += offsets[j];
if (bits1[j] >= thresh[j])
- psum += bits1[j];
+ psum += IMIN(bits1[j], 64*C<<BITRES<<LM);
else if (bits1[j] >= C<<BITRES)
psum += C<<BITRES;
@@ -419,24 +417,29 @@
}
/*printf ("\n");*/
if (psum > total)
- hi = mid;
+ hi = mid - 1;
else
- lo = mid;
+ lo = mid + 1;
/*printf ("lo = %d, hi = %d\n", lo, hi);*/
}
+ while (lo <= hi);
+ hi = lo--;
/*printf ("interp between %d and %d\n", lo, hi);*/
for (j=start;j<end;j++)
{
int N = m->eBands[j+1]-m->eBands[j];
- bits1[j] = (C*N*m->allocVectors[lo*len+j]<<LM>>2);
- bits2[j] = (C*N*m->allocVectors[hi*len+j]<<LM>>2) - bits1[j];
+ bits1[j] = C*N*m->allocVectors[lo*len+j]<<LM>>2;
+ bits2[j] = C*N*m->allocVectors[hi*len+j]<<LM>>2;
if (bits1[j] > 0)
- bits1[j] += trim_offset[j];
- if (bits1[j] < 0)
- bits1[j] = 0;
- bits1[j] += offsets[j];
+ bits1[j] = IMAX(0, bits1[j] + trim_offset[j]);
+ if (bits2[j] > 0)
+ bits2[j] = IMAX(0, bits2[j] + trim_offset[j]);
+ if (lo > 0)
+ bits1[j] += offsets[j];
+ bits2[j] += offsets[j];
if (offsets[j]>0)
skip_start = j;
+ bits2[j] -= bits1[j];
}
codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh,
total, skip_rsv, pulses, ebits, fine_priority, len, C, LM, ec, encode, prev);