Improvement: LTPF now work on decoded ring buffer

This commit is contained in:
Antoine SOULIER
2022-04-20 14:52:49 +02:00
parent 6f2b25df8a
commit c3831b7b24
8 changed files with 142 additions and 96 deletions

View File

@@ -58,7 +58,7 @@
/**
* Return number of samples, delayed samples and
* encoded spectrum coefficients within a frame
* For decoding, add number of samples of 18 ms history
* For decoding, keep 18 ms of history, aligned on frames, and a frame
*/
#define LC3_NS(dt, sr) \
@@ -73,8 +73,8 @@
#define LC3_MAX_NE \
LC3_NE(LC3_DT_10M, LC3_SRATE_48K)
#define LC3_NH(sr) \
(18 * LC3_SRATE_KHZ(sr))
#define LC3_NR(dt, sr) \
( ((3 - dt) + 1) * LC3_NS(dt, sr) )
/**

View File

@@ -361,6 +361,7 @@ static void store_s16(
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr_pcm;
float *xs = decoder->xs;
int ns = LC3_NS(dt, sr);
@@ -384,6 +385,7 @@ static void store_s24(
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr_pcm;
float *xs = decoder->xs;
int ns = LC3_NS(dt, sr);
@@ -406,6 +408,7 @@ static int decode(struct lc3_decoder *decoder,
{
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr;
float *xf = decoder->xs;
int ns = LC3_NS(dt, sr);
int ne = LC3_NE(dt, sr);
@@ -452,11 +455,11 @@ static void synthesize(struct lc3_decoder *decoder,
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr = decoder->sr;
enum lc3_srate sr_pcm = decoder->sr_pcm;
int ns = LC3_NS(dt, sr_pcm);
int ne = LC3_NE(dt, sr);
int nh = LC3_NH(sr_pcm);
float *xf = decoder->xs;
int ns = LC3_NS(dt, sr_pcm);
int ne = LC3_NE(dt, sr);
float *xg = decoder->xg;
float *xd = decoder->xd;
float *xs = xf;
@@ -481,9 +484,22 @@ static void synthesize(struct lc3_decoder *decoder,
}
lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf,
side && side->pitch_present ? &side->ltpf : NULL, xs);
side && side->pitch_present ? &side->ltpf : NULL, decoder->xr, xs);
}
memmove(xs - nh, xs - nh+ns, nh * sizeof(*xs));
/**
* Update decoder state on decoding completion
* decoder Decoder state
*/
static void complete(struct lc3_decoder *decoder)
{
enum lc3_dt dt = decoder->dt;
enum lc3_srate sr_pcm = decoder->sr_pcm;
int nr = LC3_NR(dt, sr_pcm);
int ns = LC3_NS(dt, sr_pcm);
decoder->xs = decoder->xs - decoder->xr < nr - ns ?
decoder->xs + ns : decoder->xr;
}
/**
@@ -516,16 +532,19 @@ struct lc3_decoder *lc3_setup_decoder(
return NULL;
struct lc3_decoder *decoder = mem;
int nh = LC3_NH(sr_pcm);
int nr = LC3_NR(dt, sr_pcm);
int ns = LC3_NS(dt, sr_pcm);
int nd = LC3_ND(dt, sr_pcm);
*decoder = (struct lc3_decoder){
.dt = dt, .sr = sr,
.sr_pcm = sr_pcm,
.xs = decoder->s + nh,
.xd = decoder->s + nh+ns,
.xg = decoder->s + nh+ns+nd,
.xr = decoder->s,
.xs = decoder->s + nr-ns,
.xd = decoder->s + nr,
.xg = decoder->s + nr+nd,
};
lc3_plc_reset(&decoder->plc);
@@ -566,5 +585,7 @@ int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes,
store[fmt](decoder, pcm, stride);
complete(decoder);
return ret;
}

View File

@@ -431,95 +431,109 @@ bool lc3_ltpf_analyse(enum lc3_dt dt, enum lc3_srate sr,
/**
* Synthesis filter template
* ym [-w/2..0] Previous, [0..w-1] Current pitch samples
* xm w-1 previous input samples
* xr, nr Ring buffer of filtered samples
* lag Lag parameter in the ring buffer
* x0 w-1 previous input samples
* x, n Current samples as input, filtered as output
* c, w Coefficients by pair (num, den), and count of pairs
* c, w Coefficients `den` then `num`, and width of filter
* fade Fading mode of filter -1: Out 1: In 0: None
*/
static inline void synthesize_template(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], const int w, int fade)
static inline void synthesize_template(const float *xr, int nr, int lag,
const float *x0, float *x, int n, const float *c, const int w, int fade)
{
float g = (float)(fade <= 0);
float g_incr = (float)((fade > 0) - (fade < 0)) / n;
float u[w];
int i;
ym -= (w >> 1);
/* --- Load previous samples --- */
for (i = 1-w; i < 0; i++) {
float xi = *(xm++), yi = *(ym++);
lag += (w >> 1);
u[i + w-1] = 0;
for (int k = w-1; k+i >= 0; k--)
u[i+k] += xi * c[k][0] - yi * c[k][1];
const float *y = x - xr < lag ? x + (nr - lag) : x - lag;
const float *y_end = xr + nr - 1;
for (int j = 0; j < w-1; j++) {
u[j] = 0;
float yi = *y, xi = *(x0++);
y = y < y_end ? y + 1 : xr;
for (int k = 0; k <= j; k++)
u[j-k] -= yi * c[k];
for (int k = 0; k <= j; k++)
u[j-k] += xi * c[w+k];
}
u[w-1] = 0;
/* --- Process --- */
for (; i < n; i += w) {
/* --- Process by filter length --- */
for (int i = 0; i < n; i += w)
for (int j = 0; j < w; j++, g += g_incr) {
float xi = *x, yi = *(ym++);
for (int k = w-1; k >= 0; k--)
u[(j+k)%w] += xi * c[k][0] - yi * c[k][1];
float yi = *y, xi = *x;
y = y < y_end ? y + 1 : xr;
for (int k = 0; k < w; k++)
u[(j+(w-1)-k)%w] -= yi * c[k];
for (int k = 0; k < w; k++)
u[(j+(w-1)-k)%w] += xi * c[w+k];
*(x++) = xi - g * u[j];
u[j] = 0;
}
}
}
/**
* Synthesis filter for each samplerates (width of filter)
*/
static void synthesize_4(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
static void nsynthesize_4(const float *xr, int nr, int lag,
const float *x0, float *x, int n, const float *c, int fade)
{
synthesize_template(ym, xm, x, n, c, 4, fade);
synthesize_template(xr, nr, lag, x0, x, n, c, 4, fade);
}
static void synthesize_6(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
static void nsynthesize_6(const float *xr, int nr, int lag,
const float *x0, float *x, int n, const float *c, int fade)
{
synthesize_template(ym, xm, x, n, c, 6, fade);
synthesize_template(xr, nr, lag, x0, x, n, c, 6, fade);
}
static void synthesize_8(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
static void nsynthesize_8(const float *xr, int nr, int lag,
const float *x0, float *x, int n, const float *c, int fade)
{
synthesize_template(ym, xm, x, n, c, 8, fade);
synthesize_template(xr, nr, lag, x0, x, n, c, 8, fade);
}
static void synthesize_12(const float *ym, const float *xm,
float *x, int n, const float (*c)[2], int fade)
static void nsynthesize_12(const float *xr, int nr, int lag,
const float *x0, float *x, int n, const float *c, int fade)
{
synthesize_template(ym, xm, x, n, c, 12, fade);
synthesize_template(xr, nr, lag, x0, x, n, c, 12, fade);
}
static void (* const synthesize[])(
const float *, const float *, float *, int, const float (*)[2], int) =
static void (* const synthesize[])(const float *, int, int,
const float *, float *, int, const float *, int) =
{
[LC3_SRATE_8K ] = synthesize_4,
[LC3_SRATE_16K] = synthesize_4,
[LC3_SRATE_24K] = synthesize_6,
[LC3_SRATE_32K] = synthesize_8,
[LC3_SRATE_48K] = synthesize_12,
[LC3_SRATE_8K ] = nsynthesize_4,
[LC3_SRATE_16K] = nsynthesize_4,
[LC3_SRATE_24K] = nsynthesize_6,
[LC3_SRATE_32K] = nsynthesize_8,
[LC3_SRATE_48K] = nsynthesize_12,
};
/**
* LTPF Synthesis
*/
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr,
int nbytes, struct lc3_ltpf_synthesis *ltpf,
const struct lc3_ltpf_data *data, float *x)
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data,
const float *xr, float *x)
{
int nr = LC3_NR(dt, sr);
int dt_us = LC3_DT_US(dt);
/* --- Filter parameters --- */
@@ -527,8 +541,8 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr,
int p_idx = data ? data->pitch_index : 0;
int pitch =
p_idx >= 440 ? (((p_idx ) - 283) << 2) :
p_idx >= 380 ? (((p_idx >> 1) - 63) << 2) + (((p_idx & 1)) << 1) :
(((p_idx >> 2) + 32) << 2) + (((p_idx & 3)) << 0) ;
p_idx >= 380 ? (((p_idx >> 1) - 63) << 2) + (((p_idx & 1)) << 1) :
(((p_idx >> 2) + 32) << 2) + (((p_idx & 3)) << 0) ;
pitch = (pitch * LC3_SRATE_KHZ(sr) * 10 + 64) / 128;
@@ -537,47 +551,47 @@ void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr,
bool active = data && data->active && g_idx < 4;
int w = LC3_MAX(4, LC3_SRATE_KHZ(sr) / 4);
float c[w][2];
float c[2*w];
for (int i = 0; i < w; i++) {
float g = active ? 0.4f - 0.05f * g_idx : 0;
c[i][0] = active ? 0.85f * g * lc3_ltpf_cnum[sr][g_idx][i] : 0;
c[i][1] = active ? g * lc3_ltpf_cden[sr][pitch & 3][i] : 0;
c[ i] = g * lc3_ltpf_cden[sr][pitch & 3][(w-1)-i];
c[w+i] = 0.85f * g * lc3_ltpf_cnum[sr][g_idx][(w-1)-i];
}
/* --- Transition handling --- */
int ns = LC3_NS(dt, sr);
int nt = ns / (4 - (dt == LC3_DT_7M5));
float xm[12];
int nt = ns / (3 + dt);
float x0[w];
if (active)
memcpy(xm, x + nt-(w-1), (w-1) * sizeof(float));
memcpy(x0, x + nt-(w-1), (w-1) * sizeof(float));
if (!ltpf->active && active)
synthesize[sr](x - pitch/4, ltpf->x, x, nt, c, 1);
synthesize[sr](xr, nr, pitch/4, ltpf->x, x, nt, c, 1);
else if (ltpf->active && !active)
synthesize[sr](x - ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
synthesize[sr](xr, nr, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
else if (ltpf->active && active && ltpf->pitch == pitch)
synthesize[sr](x - pitch/4, ltpf->x, x, nt, c, 0);
synthesize[sr](xr, nr, pitch/4, ltpf->x, x, nt, c, 0);
else if (ltpf->active && active) {
synthesize[sr](x - ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
synthesize[sr](x - pitch/4, x - (w-1), x, nt, c, 1);
synthesize[sr](xr, nr, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
synthesize[sr](xr, nr, pitch/4,
(x <= xr ? x + nr : x) - (w-1), x, nt, c, 1);
}
/* --- Remainder --- */
memcpy(ltpf->x, x + ns-(w-1), (w-1) * sizeof(float));
memcpy(ltpf->x, x + ns - (w-1), (w-1) * sizeof(float));
if (active)
synthesize[sr](x - pitch/4 + nt, xm, x + nt, ns-nt, c, 0);
synthesize[sr](xr, nr, pitch/4, x0, x + nt, ns-nt, c, 0);
/* --- Update state --- */
ltpf->active = active;
ltpf->pitch = pitch;
memcpy(ltpf->c, c, w * sizeof(ltpf->c[0]));
memcpy(ltpf->c, c, 2*w * sizeof(*ltpf->c));
}

View File

@@ -96,12 +96,15 @@ void lc3_ltpf_get_data(lc3_bits_t *bits, lc3_ltpf_data_t *data);
* nbytes Size in bytes of the frame
* ltpf Context of synthesis
* data Bitstream data, NULL when pitch not present
* x [-d..-1] Previous, [0..ns-1] Current, filtered as output
* xr Base address of ring buffer of decoded samples
* x Samples to proceed in the ring buffer, filtered as output
*
* The number of previous samples `d` accessed on `x` is about 18 ms
* The size of the ring buffer is `nh + ns`.
* The filtering needs an history of at least 18 ms.
*/
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data, float *x);
lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data,
const float *xr, float *x);
#endif /* __LC3_LTPF_H */