|
|
|
@ -363,7 +363,7 @@ static inline float celt_decode_pulses(OpusRangeCoder *rc, int *y, uint32_t N, u |
|
|
|
|
* Faster than libopus's search, operates entirely in the signed domain. |
|
|
|
|
* Slightly worse/better depending on N, K and the input vector. |
|
|
|
|
*/ |
|
|
|
|
static int celt_pvq_search(float *X, int *y, int K, int N) |
|
|
|
|
static float ppp_pvq_search_c(float *X, int *y, int K, int N) |
|
|
|
|
{ |
|
|
|
|
int i, y_norm = 0; |
|
|
|
|
float res = 0.0f, xy_norm = 0.0f; |
|
|
|
@ -408,17 +408,17 @@ static int celt_pvq_search(float *X, int *y, int K, int N) |
|
|
|
|
y[max_idx] += phase; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return y_norm; |
|
|
|
|
return (float)y_norm; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint32_t celt_alg_quant(OpusRangeCoder *rc, float *X, uint32_t N, uint32_t K, |
|
|
|
|
enum CeltSpread spread, uint32_t blocks, float gain, |
|
|
|
|
void *scratch) |
|
|
|
|
CeltPVQ *pvq) |
|
|
|
|
{ |
|
|
|
|
int *y = scratch; |
|
|
|
|
int *y = pvq->qcoeff; |
|
|
|
|
|
|
|
|
|
celt_exp_rotation(X, N, blocks, K, spread, 1); |
|
|
|
|
gain /= sqrtf(celt_pvq_search(X, y, K, N)); |
|
|
|
|
gain /= sqrtf(pvq->pvq_search(X, y, K, N)); |
|
|
|
|
celt_encode_pulses(rc, y, N, K); |
|
|
|
|
celt_normalize_residual(y, X, N, gain); |
|
|
|
|
celt_exp_rotation(X, N, blocks, K, spread, 0); |
|
|
|
@ -429,9 +429,9 @@ static uint32_t celt_alg_quant(OpusRangeCoder *rc, float *X, uint32_t N, uint32_ |
|
|
|
|
the final normalised signal in the current band. */ |
|
|
|
|
static uint32_t celt_alg_unquant(OpusRangeCoder *rc, float *X, uint32_t N, uint32_t K, |
|
|
|
|
enum CeltSpread spread, uint32_t blocks, float gain, |
|
|
|
|
void *scratch) |
|
|
|
|
CeltPVQ *pvq) |
|
|
|
|
{ |
|
|
|
|
int *y = scratch; |
|
|
|
|
int *y = pvq->qcoeff; |
|
|
|
|
|
|
|
|
|
gain /= sqrtf(celt_decode_pulses(rc, y, N, K)); |
|
|
|
|
celt_normalize_residual(y, X, N, gain); |
|
|
|
@ -477,19 +477,16 @@ static void celt_stereo_ms_decouple(float *X, float *Y, int N) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define QUANT_FN(name) uint32_t (*name)(CeltFrame *f, OpusRangeCoder *rc, \ |
|
|
|
|
const int band, float *X, float *Y, \
|
|
|
|
|
int N, int b, uint32_t blocks, \
|
|
|
|
|
float *lowband, int duration, \
|
|
|
|
|
float *lowband_out, int level, \
|
|
|
|
|
float gain, float *lowband_scratch, \
|
|
|
|
|
int fill) |
|
|
|
|
|
|
|
|
|
static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCoder *rc, const int band, |
|
|
|
|
float *X, float *Y, int N, int b, uint32_t blocks, |
|
|
|
|
float *lowband, int duration, float *lowband_out, |
|
|
|
|
int level, float gain, float *lowband_scratch, |
|
|
|
|
int fill, int quant) |
|
|
|
|
static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f, |
|
|
|
|
OpusRangeCoder *rc, |
|
|
|
|
const int band, float *X, |
|
|
|
|
float *Y, int N, int b, |
|
|
|
|
uint32_t blocks, float *lowband, |
|
|
|
|
int duration, float *lowband_out, |
|
|
|
|
int level, float gain, |
|
|
|
|
float *lowband_scratch, |
|
|
|
|
int fill, int quant, |
|
|
|
|
QUANT_FN(*rec)) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
const uint8_t *cache; |
|
|
|
@ -505,7 +502,6 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
float mid = 0, side = 0; |
|
|
|
|
int longblocks = (B0 == 1); |
|
|
|
|
uint32_t cm = 0; |
|
|
|
|
QUANT_FN(rec) = quant ? ff_celt_encode_band : ff_celt_decode_band; |
|
|
|
|
|
|
|
|
|
if (N == 1) { |
|
|
|
|
float *x = X; |
|
|
|
@ -565,7 +561,7 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
|
|
|
|
|
/* Reorganize the samples in time order instead of frequency order */ |
|
|
|
|
if (B0 > 1 && (quant || lowband)) |
|
|
|
|
celt_deinterleave_hadamard(f->scratch, quant ? X : lowband, |
|
|
|
|
celt_deinterleave_hadamard(pvq->hadamard_tmp, quant ? X : lowband, |
|
|
|
|
N_B >> recombine, B0 << recombine, |
|
|
|
|
longblocks); |
|
|
|
|
} |
|
|
|
@ -702,7 +698,7 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
sign = 1 - 2 * sign; |
|
|
|
|
/* We use orig_fill here because we want to fold the side, but if
|
|
|
|
|
itheta==16384, we'll have cleared the low bits of fill. */ |
|
|
|
|
cm = rec(f, rc, band, x2, NULL, N, mbits, blocks, lowband, duration, |
|
|
|
|
cm = rec(pvq, f, rc, band, x2, NULL, N, mbits, blocks, lowband, duration, |
|
|
|
|
lowband_out, level, gain, lowband_scratch, orig_fill); |
|
|
|
|
/* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
|
|
|
|
|
and there's no need to worry about mixing with the other channel. */ |
|
|
|
@ -755,7 +751,7 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
if (mbits >= sbits) { |
|
|
|
|
/* In stereo mode, we do not apply a scaling to the mid
|
|
|
|
|
* because we need the normalized mid for folding later */ |
|
|
|
|
cm = rec(f, rc, band, X, NULL, N, mbits, blocks, lowband, |
|
|
|
|
cm = rec(pvq, f, rc, band, X, NULL, N, mbits, blocks, lowband, |
|
|
|
|
duration, next_lowband_out1, next_level, |
|
|
|
|
stereo ? 1.0f : (gain * mid), lowband_scratch, fill); |
|
|
|
|
rebalance = mbits - (rebalance - f->remaining2); |
|
|
|
@ -764,14 +760,14 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
|
|
|
|
|
/* For a stereo split, the high bits of fill are always zero,
|
|
|
|
|
* so no folding will be done to the side. */ |
|
|
|
|
cmt = rec(f, rc, band, Y, NULL, N, sbits, blocks, next_lowband2, |
|
|
|
|
cmt = rec(pvq, f, rc, band, Y, NULL, N, sbits, blocks, next_lowband2, |
|
|
|
|
duration, NULL, next_level, gain * side, NULL, |
|
|
|
|
fill >> blocks); |
|
|
|
|
cm |= cmt << ((B0 >> 1) & (stereo - 1)); |
|
|
|
|
} else { |
|
|
|
|
/* For a stereo split, the high bits of fill are always zero,
|
|
|
|
|
* so no folding will be done to the side. */ |
|
|
|
|
cm = rec(f, rc, band, Y, NULL, N, sbits, blocks, next_lowband2, |
|
|
|
|
cm = rec(pvq, f, rc, band, Y, NULL, N, sbits, blocks, next_lowband2, |
|
|
|
|
duration, NULL, next_level, gain * side, NULL, fill >> blocks); |
|
|
|
|
cm <<= ((B0 >> 1) & (stereo - 1)); |
|
|
|
|
rebalance = sbits - (rebalance - f->remaining2); |
|
|
|
@ -780,7 +776,7 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
|
|
|
|
|
/* In stereo mode, we do not apply a scaling to the mid because
|
|
|
|
|
* we need the normalized mid for folding later */ |
|
|
|
|
cm |= rec(f, rc, band, X, NULL, N, mbits, blocks, lowband, duration, |
|
|
|
|
cm |= rec(pvq, f, rc, band, X, NULL, N, mbits, blocks, lowband, duration, |
|
|
|
|
next_lowband_out1, next_level, stereo ? 1.0f : (gain * mid), |
|
|
|
|
lowband_scratch, fill); |
|
|
|
|
} |
|
|
|
@ -802,10 +798,10 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
/* Finally do the actual (de)quantization */ |
|
|
|
|
if (quant) { |
|
|
|
|
cm = celt_alg_quant(rc, X, N, (q < 8) ? q : (8 + (q & 7)) << ((q >> 3) - 1), |
|
|
|
|
f->spread, blocks, gain, f->scratch); |
|
|
|
|
f->spread, blocks, gain, pvq); |
|
|
|
|
} else { |
|
|
|
|
cm = celt_alg_unquant(rc, X, N, (q < 8) ? q : (8 + (q & 7)) << ((q >> 3) - 1), |
|
|
|
|
f->spread, blocks, gain, f->scratch); |
|
|
|
|
f->spread, blocks, gain, pvq); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
/* If there's no pulse, fill the band anyway */ |
|
|
|
@ -845,7 +841,7 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
|
|
|
|
|
/* Undo the sample reorganization going from time order to frequency order */ |
|
|
|
|
if (B0 > 1) |
|
|
|
|
celt_interleave_hadamard(f->scratch, X, N_B >> recombine, |
|
|
|
|
celt_interleave_hadamard(pvq->hadamard_tmp, X, N_B >> recombine, |
|
|
|
|
B0 << recombine, longblocks); |
|
|
|
|
|
|
|
|
|
/* Undo time-freq changes that we did earlier */ |
|
|
|
@ -876,33 +872,28 @@ static av_always_inline uint32_t quant_band_template(CeltFrame *f, OpusRangeCode |
|
|
|
|
return cm; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t ff_celt_decode_band(CeltFrame *f, OpusRangeCoder *rc, const int band, |
|
|
|
|
float *X, float *Y, int N, int b, uint32_t blocks, |
|
|
|
|
float *lowband, int duration, float *lowband_out, |
|
|
|
|
int level, float gain, float *lowband_scratch, |
|
|
|
|
int fill) |
|
|
|
|
|
|
|
|
|
static QUANT_FN(pvq_decode_band) |
|
|
|
|
{ |
|
|
|
|
return quant_band_template(f, rc, band, X, Y, N, b, blocks, lowband, duration, |
|
|
|
|
lowband_out, level, gain, lowband_scratch, fill, 0); |
|
|
|
|
return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration, |
|
|
|
|
lowband_out, level, gain, lowband_scratch, fill, 0, |
|
|
|
|
pvq->decode_band); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t ff_celt_encode_band(CeltFrame *f, OpusRangeCoder *rc, const int band, |
|
|
|
|
float *X, float *Y, int N, int b, uint32_t blocks, |
|
|
|
|
float *lowband, int duration, float *lowband_out, |
|
|
|
|
int level, float gain, float *lowband_scratch, |
|
|
|
|
int fill) |
|
|
|
|
static QUANT_FN(pvq_encode_band) |
|
|
|
|
{ |
|
|
|
|
return quant_band_template(f, rc, band, X, Y, N, b, blocks, lowband, duration, |
|
|
|
|
lowband_out, level, gain, lowband_scratch, fill, 1); |
|
|
|
|
return quant_band_template(pvq, f, rc, band, X, Y, N, b, blocks, lowband, duration, |
|
|
|
|
lowband_out, level, gain, lowband_scratch, fill, 1, |
|
|
|
|
pvq->encode_band); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
float ff_celt_quant_band_cost(CeltFrame *f, OpusRangeCoder *rc, int band, float *bits, |
|
|
|
|
float lambda) |
|
|
|
|
static float pvq_band_cost(CeltPVQ *pvq, CeltFrame *f, OpusRangeCoder *rc, int band, |
|
|
|
|
float *bits, float lambda) |
|
|
|
|
{ |
|
|
|
|
int i, b = 0; |
|
|
|
|
uint32_t cm[2] = { (1 << f->blocks) - 1, (1 << f->blocks) - 1 }; |
|
|
|
|
const int band_size = ff_celt_freq_range[band] << f->size; |
|
|
|
|
float buf[352], lowband_scratch[176], norm1[176], norm2[176]; |
|
|
|
|
float buf[176 * 2], lowband_scratch[176], norm1[176], norm2[176]; |
|
|
|
|
float dist, cost, err_x = 0.0f, err_y = 0.0f; |
|
|
|
|
float *X = buf; |
|
|
|
|
float *X_orig = f->block[0].coeffs + (ff_celt_freq_bands[band] << f->size); |
|
|
|
@ -921,14 +912,14 @@ float ff_celt_quant_band_cost(CeltFrame *f, OpusRangeCoder *rc, int band, float |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (f->dual_stereo) { |
|
|
|
|
ff_celt_encode_band(f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, |
|
|
|
|
f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); |
|
|
|
|
pvq->encode_band(pvq, f, rc, band, X, NULL, band_size, b / 2, f->blocks, NULL, |
|
|
|
|
f->size, norm1, 0, 1.0f, lowband_scratch, cm[0]); |
|
|
|
|
|
|
|
|
|
ff_celt_encode_band(f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, |
|
|
|
|
f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); |
|
|
|
|
pvq->encode_band(pvq, f, rc, band, Y, NULL, band_size, b / 2, f->blocks, NULL, |
|
|
|
|
f->size, norm2, 0, 1.0f, lowband_scratch, cm[1]); |
|
|
|
|
} else { |
|
|
|
|
ff_celt_encode_band(f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, |
|
|
|
|
norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); |
|
|
|
|
pvq->encode_band(pvq, f, rc, band, X, Y, band_size, b, f->blocks, NULL, f->size, |
|
|
|
|
norm1, 0, 1.0f, lowband_scratch, cm[0] | cm[1]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < band_size; i++) { |
|
|
|
@ -944,3 +935,24 @@ float ff_celt_quant_band_cost(CeltFrame *f, OpusRangeCoder *rc, int band, float |
|
|
|
|
|
|
|
|
|
return lambda*dist*cost; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int av_cold ff_celt_pvq_init(CeltPVQ **pvq) |
|
|
|
|
{ |
|
|
|
|
CeltPVQ *s = av_malloc(sizeof(CeltPVQ)); |
|
|
|
|
if (!s) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
s->pvq_search = ppp_pvq_search_c; |
|
|
|
|
s->decode_band = pvq_decode_band; |
|
|
|
|
s->encode_band = pvq_encode_band; |
|
|
|
|
s->band_cost = pvq_band_cost; |
|
|
|
|
|
|
|
|
|
*pvq = s; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void av_cold ff_celt_pvq_uninit(CeltPVQ **pvq) |
|
|
|
|
{ |
|
|
|
|
av_freep(pvq); |
|
|
|
|
} |
|
|
|
|