Skip to content

Commit

Permalink
fix: Gain adjustment during second quantization phase can exceed mini…
Browse files Browse the repository at this point in the history
…mum gain
  • Loading branch information
asoulier committed Jul 25, 2023
1 parent 3b23884 commit 67f2231
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 19 deletions.
23 changes: 13 additions & 10 deletions src/spec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
}
Expand All @@ -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 --- */

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 --- */

Expand All @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions test/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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]:
Expand Down
13 changes: 7 additions & 6 deletions test/spec_py.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down

0 comments on commit 67f2231

Please sign in to comment.