From c4f48f2618b9f8c5b34b1645f92199f074256a1c Mon Sep 17 00:00:00 2001 From: Antoine SOULIER Date: Tue, 10 May 2022 13:49:57 +0200 Subject: [PATCH] Improve storage of quantized coefficients --- src/lc3.c | 6 ++-- src/spec.c | 78 +++++++++++++++++++++++++++++++++----------------- src/spec.h | 12 ++++++-- test/spec_py.c | 27 +++++++++++++---- 4 files changed, 87 insertions(+), 36 deletions(-) diff --git a/src/lc3.c b/src/lc3.c index 525ac01..219e381 100644 --- a/src/lc3.c +++ b/src/lc3.c @@ -199,7 +199,7 @@ static void load_s24( * side, xq Return frame data */ static void analyze(struct lc3_encoder *encoder, - int nbytes, struct side_data *side, int16_t *xq) + int nbytes, struct side_data *side, uint16_t *xq) { enum lc3_dt dt = encoder->dt; enum lc3_srate sr = encoder->sr; @@ -250,7 +250,7 @@ static void analyze(struct lc3_encoder *encoder, * buffer Output bitstream buffer of `nbytes` size */ static void encode(struct lc3_encoder *encoder, - const struct side_data *side, int16_t *xq, int nbytes, void *buffer) + const struct side_data *side, uint16_t *xq, int nbytes, void *buffer) { enum lc3_dt dt = encoder->dt; enum lc3_srate sr = encoder->sr; @@ -348,7 +348,7 @@ int lc3_encode(struct lc3_encoder *encoder, enum lc3_pcm_format fmt, /* --- Processing --- */ struct side_data side; - int16_t xq[LC3_NE(encoder->dt, encoder->sr)]; + uint16_t xq[LC3_NE(encoder->dt, encoder->sr)]; load[fmt](encoder, pcm, stride); diff --git a/src/spec.c b/src/spec.c index 174ae40..dbe70bd 100644 --- a/src/spec.c +++ b/src/spec.c @@ -197,9 +197,13 @@ static float unquantize_gain(int g_int) * g_int Quantization gain value * x Spectral coefficients, scaled as output * xq, nq Output spectral quantized coefficients, and count + * + * The spectral coefficients `xq` are stored as : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ LC3_HOT static void quantize(enum lc3_dt dt, enum lc3_srate sr, - int g_int, float *x, int16_t *xq, int *nq) + int g_int, float *x, uint16_t *xq, int *nq) { float g_inv = 1 / unquantize_gain(g_int); int ne = LC3_NE(dt, sr); @@ -207,15 +211,16 @@ LC3_HOT static void quantize(enum lc3_dt dt, enum lc3_srate sr, *nq = ne; for (int i = 0; i < ne; i += 2) { - int16_t x0, x1; + uint16_t x0, x1; x[i+0] *= g_inv; - x0 = fminf(floorf(fabsf(x[i+0]) + 6.f/16), INT16_MAX); - xq[i+0] = x[i+0] < 0 ? -x0 : x0; - x[i+1] *= g_inv; - x1 = fminf(floorf(fabsf(x[i+1]) + 6.f/16), INT16_MAX); - xq[i+1] = x[i+1] < 0 ? -x1 : x1; + + x0 = fminf(fabsf(x[i+0]) + 6.f/16, INT16_MAX); + x1 = fminf(fabsf(x[i+1]) + 6.f/16, INT16_MAX); + + xq[i+0] = (x0 << 1) + ((x0 > 0) & (x[i+0] < 0)); + xq[i+1] = (x1 << 1) + ((x1 > 0) & (x[i+1] < 0)); *nq = x0 || x1 ? ne : *nq - 2; } @@ -266,10 +271,14 @@ static int resolve_high_rate(enum lc3_srate sr, int nbytes) * nbits_budget Truncate to stay in budget, when not zero * p_lsb_mode Return True when LSB's are not AC coded, or NULL * return The number of bits coding the spectrum + * + * The spectral coefficients `x` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ LC3_HOT static int compute_nbits( enum lc3_dt dt, enum lc3_srate sr, int nbytes, - const int16_t *x, int *n, int nbits_budget, bool *p_lsb_mode) + const uint16_t *x, int *n, int nbits_budget, bool *p_lsb_mode) { int ne = LC3_NE(dt, sr); @@ -295,11 +304,11 @@ LC3_HOT static int compute_nbits( && nbits <= nbits_budget; i += 2) { const uint8_t *lut = lut_coeff[state]; - int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]); + uint16_t a = x[i] >> 1, b = x[i+1] >> 1; /* --- Sign values --- */ - int s = (a != 0) + (b != 0); + int s = (a > 0) + (b > 0); nbits += s * 2048; /* --- LSB values Reduce to 2*2 bits MSB values --- @@ -312,6 +321,7 @@ LC3_HOT static int compute_nbits( int m = (a | b) >> 2; if (m) { + if (lsb_mode) { nbits += lc3_spectrum_bits[lut[k++]][16] - 2*2048; nbits_lsb += 2 + (a == 1) + (b == 1); @@ -362,10 +372,14 @@ LC3_HOT static int compute_nbits( * dt, sr, nbytes Duration, samplerate and size of the frame * x Spectral quantized * nq, lsb_mode Count of significants, and LSB discard indication + * + * The spectral coefficients `x` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ LC3_HOT static void put_quantized(lc3_bits_t *bits, enum lc3_dt dt, enum lc3_srate sr, int nbytes, - const int16_t *x, int nq, bool lsb_mode) + const uint16_t *x, int nq, bool lsb_mode) { int ne = LC3_NE(dt, sr); bool high_rate = resolve_high_rate(sr, nbytes); @@ -380,8 +394,7 @@ LC3_HOT static void put_quantized(lc3_bits_t *bits, for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) { const uint8_t *lut = lut_coeff[state]; - bool a_neg = x[i] < 0, b_neg = x[i+1] < 0; - int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]); + uint16_t a = x[i] >> 1, b = x[i+1] >> 1; /* --- LSB values Reduce to 2*2 bits MSB values --- * Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic @@ -413,8 +426,8 @@ LC3_HOT static void put_quantized(lc3_bits_t *bits, /* --- Sign values --- */ - if (a) lc3_put_bit(bits, a_neg); - if (b) lc3_put_bit(bits, b_neg); + if (a) lc3_put_bit(bits, x[i+0] & 1); + if (b) lc3_put_bit(bits, x[i+1] & 1); /* --- MSB values --- */ @@ -511,18 +524,24 @@ LC3_HOT static int get_quantized(lc3_bits_t *bits, * Put residual bits of quantization * bits Bitstream context * nbits Maximum number of bits to output - * xq, n Spectral quantized, and count of significants + * x, n Spectral quantized, and count of significants * xf Scaled spectral coefficients + * + * The spectral coefficients `x` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ LC3_HOT static void put_residual( - lc3_bits_t *bits, int nbits, const int16_t *xq, int n, const float *xf) + lc3_bits_t *bits, int nbits, const uint16_t *x, int n, const float *xf) { for (int i = 0; i < n && nbits > 0; i++) { - if (xq[i] == 0) + if (x[i] == 0) continue; - lc3_put_bit(bits, xf[i] >= xq[i]); + float xq = x[i] & 1 ? -(x[i] >> 1) : (x[i] >> 1); + + lc3_put_bit(bits, xf[i] >= xq); nbits--; } } @@ -555,14 +574,17 @@ LC3_HOT static void get_residual( * bits Bitstream context * nbits Maximum number of bits to output * x, n Spectral quantized, and count of significants + * + * The spectral coefficients `x` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ LC3_HOT static void put_lsb( - lc3_bits_t *bits, int nbits, const int16_t *x, int n) + lc3_bits_t *bits, int nbits, const uint16_t *x, int n) { for (int i = 0; i < n && nbits > 0; i += 2) { - - bool a_neg = x[i] < 0, b_neg = x[i+1] < 0; - int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]); + uint16_t a = x[i] >> 1, b = x[i+1] >> 1; + int a_neg = x[i] & 1, b_neg = x[i+1] & 1; if ((a | b) >> 2 == 0) continue; @@ -631,9 +653,13 @@ LC3_HOT static void get_lsb(lc3_bits_t *bits, * xq, nq Quantized spectral coefficients * x Quantization scaled spectrum coefficients * return Noise factor (0 to 7) + * + * The spectral coefficients `x` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ LC3_HOT static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw, - const int16_t *xq, int nq, const float *x) + const uint16_t *xq, int nq, const float *x) { int bw_stop = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw); int w = 2 + dt; @@ -739,7 +765,7 @@ static int get_nbits_ac(enum lc3_dt dt, enum lc3_srate sr, int nbytes) void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr, int nbytes, bool pitch, const lc3_tns_data_t *tns, struct lc3_spec_analysis *spec, float *x, - int16_t *xq, struct lc3_spec_side *side) + uint16_t *xq, struct lc3_spec_side *side) { bool reset_off; @@ -802,7 +828,7 @@ void lc3_spec_put_side(lc3_bits_t *bits, */ void lc3_spec_encode(lc3_bits_t *bits, enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes, - const int16_t *xq, const lc3_spec_side_t *side, const float *x) + const uint16_t *xq, const lc3_spec_side_t *side, const float *x) { bool lsb_mode = side->lsb_mode; int nq = side->nq; diff --git a/src/spec.h b/src/spec.h index b5ec913..091d25f 100644 --- a/src/spec.h +++ b/src/spec.h @@ -54,10 +54,14 @@ typedef struct lc3_spec_side { * spec Context of analysis * x Spectral coefficients, scaled as output * xq, side Return quantization data + * + * The spectral coefficients `xq` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr, int nbytes, bool pitch, const lc3_tns_data_t *tns, - lc3_spec_analysis_t *spec, float *x, int16_t *xq, lc3_spec_side_t *side); + lc3_spec_analysis_t *spec, float *x, uint16_t *xq, lc3_spec_side_t *side); /** * Put spectral quantization side data @@ -75,10 +79,14 @@ void lc3_spec_put_side(lc3_bits_t *bits, * nbytes and size of the frame * xq, side Quantization data * x Scaled spectral coefficients + * + * The spectral coefficients `xq` storage is : + * b0 0:positive or zero 1:negative + * b15..b1 Absolute value */ void lc3_spec_encode(lc3_bits_t *bits, enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes, - const int16_t *xq, const lc3_spec_side_t *side, const float *x); + const uint16_t *xq, const lc3_spec_side_t *side, const float *x); /* ---------------------------------------------------------------------------- diff --git a/test/spec_py.c b/test/spec_py.c index 872ebe6..814f253 100644 --- a/test/spec_py.c +++ b/test/spec_py.c @@ -86,8 +86,12 @@ static PyObject *quantize_py(PyObject *m, PyObject *args) CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); xq_obj = new_1d_ptr(NPY_INT16, ne, &xq); + uint16_t __xq[ne]; - quantize(dt, sr, g_int, x, xq, &nq); + quantize(dt, sr, g_int, x, __xq, &nq); + + for (int i = 0; i < nq; i++) + xq[i] = __xq[i] & 1 ? -(__xq[i] >> 1) : (__xq[i] >> 1); return Py_BuildValue("ONi", x_obj, xq_obj, nq); } @@ -111,8 +115,12 @@ static PyObject *compute_nbits_py(PyObject *m, PyObject *args) CTYPES_CHECK("xq", xq_obj = to_1d_ptr(xq_obj, NPY_INT16, ne, &xq)); + uint16_t __xq[ne]; + for (int i = 0; i < ne; i++) + __xq[i] = xq[i] < 0 ? (-xq[i] << 1) + 1 : (xq[i] << 1); + int nbits = compute_nbits( - dt, sr, nbytes, xq, &nq, nbits_budget, &lsb_mode); + dt, sr, nbytes, __xq, &nq, nbits_budget, &lsb_mode); return Py_BuildValue("iii", nbits, nq, lsb_mode); } @@ -140,9 +148,14 @@ static PyObject *analyze_py(PyObject *m, PyObject *args) CTYPES_CHECK(NULL, tns_obj = to_tns_data(tns_obj, &tns)); CTYPES_CHECK(NULL, spec_obj = to_spec_analysis(spec_obj, &spec)); CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); - xq_obj = new_1d_ptr(NPY_INT16, ne, &xq); - lc3_spec_analyze(dt, sr, nbytes, pitch, &tns, &spec, x, xq, &side); + xq_obj = new_1d_ptr(NPY_INT16, ne, &xq); + uint16_t __xq[ne]; + + lc3_spec_analyze(dt, sr, nbytes, pitch, &tns, &spec, x, __xq, &side); + + for (int i = 0; i < ne; i++) + xq[i] = __xq[i] & 1 ? -(__xq[i] >> 1) : (__xq[i] >> 1); from_spec_analysis(spec_obj, &spec); return Py_BuildValue("ONN", x_obj, xq_obj, new_spec_side(&side)); @@ -167,7 +180,11 @@ static PyObject *estimate_noise_py(PyObject *m, PyObject *args) CTYPES_CHECK("xq", xq_obj = to_1d_ptr(xq_obj, NPY_INT16, ne, &xq)); CTYPES_CHECK("x" , x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x )); - int noise_factor = estimate_noise(dt, bw, xq, nq, x); + uint16_t __xq[nq]; + for (int i = 0; i < nq; i++) + __xq[i] = xq[i] < 0 ? (-xq[i] << 1) + 1 : (xq[i] << 1); + + int noise_factor = estimate_noise(dt, bw, __xq, nq, x); return Py_BuildValue("i", noise_factor); }