By moving the energy floor to the encoder, we can use a different
floor for prediction than for the decay level. Also, the fixed-point
dynamic range has been increased to avoid overflows when a fixed-point
decoder is used on a stream encoded in floating-point.
This patch makes all symbols conditional on whether or not there's
enough space left in the buffer to code them, and eliminates much
of the redundancy in the side information.
A summary of the major changes:
* The isTransient flag is moved up to before the the coarse energy.
If there are not enough bits to code the coarse energy, the flag
would get forced to 0, meaning what energy values were coded
would get interpreted incorrectly.
This might not be the end of the world, and I'd be willing to
move it back given a compelling argument.
* Coarse energy switches coding schemes when there are less than 15
bits left in the packet:
- With at least 2 bits remaining, the change in energy is forced
to the range [-1...1] and coded with 1 bit (for 0) or 2 bits
(for +/-1).
- With only 1 bit remaining, the change in energy is forced to
the range [-1...0] and coded with one bit.
- If there is less than 1 bit remaining, the change in energy is
forced to -1.
This effectively low-passes bands whose energy is consistently
starved; this might be undesirable, but letting the default be
zero is unstable, which is worse.
* The tf_select flag gets moved back after the per-band tf_res
flags again, and is now skipped entirely when none of the
tf_res flags are set, and the default value is the same for
either alternative.
* dynalloc boosting is now limited so that it stops once it's given
a band all the remaining bits in the frame, or when it hits the
"stupid cap" of (64<<LM)*(C<<BITRES) used during allocation.
* If dynalloc boosing has allocated all the remaining bits in the
frame, the alloc trim parameter does not get encoded (it would
have no effect).
* The intensity stereo offset is now limited to the range
[start...codedBands], and thus doesn't get coded until after
all of the skip decisions.
Some space is reserved for it up front, and gradually given back
as each band is skipped.
* The dual stereo flag is coded only if intensity>start, since
otherwise it has no effect.
It is now coded after the intensity flag.
* The space reserved for the final skip flag, the intensity stereo
offset, and the dual stereo flag is now redistributed to all
bands equally if it is unused.
Before, the skip flag's bit was given to the band that stopped
skipping without it (usually a dynalloc boosted band).
In order to enable simple interaction between VBR and these
packet-size enforced limits, many of which are encountered before
VBR is run, the maximum packet size VBR will allow is computed at
the beginning of the encoding function, and the buffer reduced to
that size immediately.
Later, when it is time to make the VBR decision, the minimum packet
size is set high enough to ensure that no decision made thus far
will have been affected by the packet size.
As long as this is smaller than the up-front maximum, all of the
encoder's decisions will remain in-sync with the decoder.
If it is larger than the up-front maximum, the packet size is kept
at that maximum, also ensuring sync.
The minimum used now is slightly larger than it used to be, because
it also includes the bits added for dynalloc boosting.
Such boosting is shut off by the encoder at low rates, and so
should not cause any serious issues at the rates where we would
actually run out of room before compute_allocation().
cf874373 raised the limit from 7 to 8 for N>1 bands in
interp_bits2pulses(), but did not raise the corresponding limits
for N=1 bands, or for [un]quant_energy_finalise().
This commit raises all of the limits to the same value, 8.
This simplifies a good bit of the error handling, and should make it
impossible to overrun the buffer in the encoder or decoder, while
still allowing tell() to operate correctly after a bust.
The encoder now tries to keep the range coder data intact after a
bust instead of corrupting it with extra bits data, though this is
not a guarantee (too many extra bits may have already been flushed).
It also now correctly reports errors when the bust occurs merging the
last byte of range coder and extra bits.
A number of abstraction barrier violations were cleaned up, as well.
This patch also includes a number of minor performance improvements:
ec_{enc|dec}_bits() in particular should be much faster.
Finally, tf_select was changed to be coded with the range coder
rather than extra bits, so that it is at the front of the packet
(for unequal error protection robustness).
All of our usage of ec_{enc|dec}_bit_prob had the probability of a
"one" being a power of two.
This adds a new ec_{enc|dec}_bit_logp() function that takes this
explicitly into account.
It introduces less rounding error than the bit_prob version, does not
require 17-bit integers to be emulated by ec_{encode|decode}_bin(),
and does not require any multiplies or divisions at all.
It is exactly equivalent to
ec_encode_bin(enc,_val?0:(1<<_logp)-1,(1<<_logp)-(_val?1:0),1<<_logp)
The old ec_{enc|dec}_bit_prob functions are left in place for now,
because I am not sure if SILK is still using them or not when
combined in Opus.
This tunes the entropy model for coarse energy introduced in commit
c1c40a76.
It uses a constant set of parameters, tuned from about an hour and a
half of randomly selected test data encoded for each frame size,
prediction type (inter/intra), and band number.
These will be slightly sub-optimal for different frame sizes, but
should be better than what we were using.
For inter, this saves an average of 2.8, 5.2, 7.1, and 6.7 bits/frame
for frame sizes of 120, 240, 480, and 960, respectively.
For intra, this saves an average of 1.5, 3.0, 4.5, and 5.3 bits/frame
(for the same frame sizes, respectively).
Prediction coefficient now depends on the frame size. Also, the pdfs and means
have been adjusted and better quantized. This breaks compatibility of course.