summaryrefslogtreecommitdiff
path: root/libavcodec/opus_pvq.c
diff options
context:
space:
mode:
authorRostislav Pehlivanov <atomnuker@gmail.com>2017-05-10 06:47:44 +0100
committerRostislav Pehlivanov <atomnuker@gmail.com>2017-05-16 11:22:07 +0100
commit8e7e74df93d18c903164a67c861a428bd4244cb1 (patch)
tree53bc9d9c22ee0a41bbac22560acafc0025829e60 /libavcodec/opus_pvq.c
parente6ec482b429b241de0fb3088d87e28777d70ded5 (diff)
downloadffmpeg-8e7e74df93d18c903164a67c861a428bd4244cb1.tar.gz
opus_pvq: port to allow for SIMD functions
Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
Diffstat (limited to 'libavcodec/opus_pvq.c')
-rw-r--r--libavcodec/opus_pvq.c118
1 files changed, 65 insertions, 53 deletions
diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c
index fa349c47da..2ac66a0ede 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);
+}