X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fopus_pvq.c;h=2ac66a0ede3c8fcd4be78a4a7d1253851177b9bc;hb=d1da0fc4b9b3bcd146b429c79511181ca66a152a;hp=fa349c47da08387f4b6ec3694ef2ced987c825f8;hpb=5729acee8214170f212b6409ac363428152d05ff;p=ffmpeg diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index fa349c47da0..2ac66a0ede3 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -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); +}