diff options
author | Antoine Soulier <asoulier@google.com> | 2023-07-25 10:49:55 -0700 |
---|---|---|
committer | Antoine Soulier <asoulier@google.com> | 2023-07-25 10:49:55 -0700 |
commit | 67f2231815532bb7b34a097108b1a24ff49dd9f3 (patch) | |
tree | 5482e6640cc79a9674fa9377b1d31d196c452d2f | |
parent | 3b238846114abd304e88a17fd9915e91036ea392 (diff) | |
download | liblc3-67f2231815532bb7b34a097108b1a24ff49dd9f3.tar.gz |
fix: Gain adjustment during second quantization phase can exceed minimum gain
-rw-r--r-- | src/spec.c | 23 | ||||
-rw-r--r-- | test/spec.py | 6 | ||||
-rw-r--r-- | test/spec_py.c | 13 |
3 files changed, 23 insertions, 19 deletions
@@ -44,11 +44,12 @@ static int resolve_gain_offset(enum lc3_srate sr, int nbytes) * nbits_off Offset on the available bits, temporarily smoothed * g_off Gain index offset * reset_off Return True when the nbits_off must be reset + * g_min Return lower bound of quantized gain value * return The quantized gain value */ LC3_HOT static int estimate_gain( enum lc3_dt dt, enum lc3_srate sr, const float *x, - int nbits_budget, float nbits_off, int g_off, bool *reset_off) + int nbits_budget, float nbits_off, int g_off, bool *reset_off, int *g_min) { int ne = LC3_NE(dt, sr) >> 2; int e[LC3_MAX_NE]; @@ -102,12 +103,12 @@ LC3_HOT static int estimate_gain( /* --- Limit gain index --- */ - int g_min = x2_max == 0 ? -g_off : + *g_min = x2_max == 0 ? -g_off : ceilf(28 * log10f(sqrtf(x2_max) / (32768 - 0.375f))); - *reset_off = g_int < g_min || x2_max == 0; + *reset_off = g_int < *g_min || x2_max == 0; if (*reset_off) - g_int = g_min; + g_int = *g_min; return g_int; } @@ -118,10 +119,11 @@ LC3_HOT static int estimate_gain( * g_idx The estimated quantized gain index * nbits Computed number of bits coding the spectrum * nbits_budget Number of bits available for coding the spectrum + * g_idx_min Minimum gain index value * return Gain adjust value (-1 to 2) */ -LC3_HOT static int adjust_gain( - enum lc3_srate sr, int g_idx, int nbits, int nbits_budget) +LC3_HOT static int adjust_gain(enum lc3_srate sr, int g_idx, + int nbits, int nbits_budget, int g_idx_min) { /* --- Compute delta threshold --- */ @@ -149,7 +151,7 @@ LC3_HOT static int adjust_gain( /* --- Adjust gain --- */ if (nbits < nbits_budget - (delta + 2)) - return -(g_idx > 0); + return -(g_idx > g_idx_min); if (nbits > nbits_budget) return (g_idx < 255) + (g_idx < 254 && nbits >= nbits_budget + delta); @@ -789,8 +791,8 @@ void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr, int g_off = resolve_gain_offset(sr, nbytes); - int g_int = estimate_gain(dt, sr, - x, nbits_budget, nbits_off, g_off, &reset_off); + int g_min, g_int = estimate_gain(dt, sr, + x, nbits_budget, nbits_off, g_off, &reset_off, &g_min); /* --- Quantization --- */ @@ -803,7 +805,8 @@ void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr, /* --- Adjust gain and requantize --- */ - int g_adj = adjust_gain(sr, g_int + g_off, nbits, nbits_budget); + int g_adj = adjust_gain(sr, g_off + g_int, + nbits, nbits_budget, g_off + g_min); if (g_adj) quantize(dt, sr, g_adj, x, xq, &side->nq); diff --git a/test/spec.py b/test/spec.py index 898c9a1..22c5e3e 100644 --- a/test/spec.py +++ b/test/spec.py @@ -589,7 +589,7 @@ def check_estimate_gain(rng, dt, sr): (g_int, reset_off) = \ analysis.estimate_gain(x, nbits_budget, nbits_off, g_off) - (g_int_c, reset_off_c) = lc3.spec_estimate_gain( + (g_int_c, reset_off_c, _) = lc3.spec_estimate_gain( dt, sr, x, nbits_budget, nbits_off, -g_off) ok = ok and g_int_c == g_int @@ -664,7 +664,7 @@ def check_adjust_gain(rng, dt, sr): g_adj = analysis.adjust_gain(g_idx, nbits, nbits_budget) - g_adj_c = lc3.spec_adjust_gain(sr, g_idx, nbits, nbits_budget) + g_adj_c = lc3.spec_adjust_gain(sr, g_idx, nbits, nbits_budget, 0) ok = ok and g_adj_c == g_adj @@ -752,7 +752,7 @@ def check_appendix_c(dt): ok = ok and nbits == C.NBITS_EST[dt][i] g_adj = lc3.spec_adjust_gain(sr, - C.GG_IND[dt][i], C.NBITS_EST[dt][i], C.NBITS_SPEC[dt][i]) + C.GG_IND[dt][i], C.NBITS_EST[dt][i], C.NBITS_SPEC[dt][i], 0) ok = ok and g_adj == C.GG_IND_ADJ[dt][i] - C.GG_IND[dt][i] if C.GG_IND_ADJ[dt][i] != C.GG_IND[dt][i]: diff --git a/test/spec_py.c b/test/spec_py.c index 814f253..730f68f 100644 --- a/test/spec_py.c +++ b/test/spec_py.c @@ -30,7 +30,7 @@ static PyObject *estimate_gain_py(PyObject *m, PyObject *args) float *x; int nbits_budget; float nbits_off; - int g_off; + int g_off, g_min; bool reset_off; if (!PyArg_ParseTuple(args, "IIOifi", &dt, &sr, @@ -45,23 +45,24 @@ static PyObject *estimate_gain_py(PyObject *m, PyObject *args) CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); int g_int = estimate_gain(dt, sr, - x, nbits_budget, nbits_off, g_off, &reset_off); + x, nbits_budget, nbits_off, g_off, &reset_off, &g_min); - return Py_BuildValue("ii", g_int, reset_off); + return Py_BuildValue("iii", g_int, reset_off, g_min); } static PyObject *adjust_gain_py(PyObject *m, PyObject *args) { unsigned sr; - int g_idx, nbits, nbits_budget; + int g_idx, nbits, nbits_budget, g_idx_min; - if (!PyArg_ParseTuple(args, "Iiii", &sr, &g_idx, &nbits, &nbits_budget)) + if (!PyArg_ParseTuple(args, "Iiiii", &sr, &g_idx, + &nbits, &nbits_budget, &g_idx_min)) return NULL; CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE); CTYPES_CHECK("g_idx", g_idx >= 0 && g_idx <= 255); - g_idx = adjust_gain(sr, g_idx, nbits, nbits_budget); + g_idx = adjust_gain(sr, g_idx, nbits, nbits_budget, g_idx_min); return Py_BuildValue("i", g_idx); } |