ref: 462c50d302e7bd57d908eb99f9e8378c26c89ba7
parent: 9840debedf2e472ea98b8e68f9deb4b1bf3e36c0
author: Jean-Marc Valin <jeanmarcv@google.com>
date: Wed Jun 4 10:00:35 EDT 2025
Disabling the comb filter when it's not useful Three cases where we disable it: 1) Strong transients with no pitch continuity 2) One channel gets significantly worse 3) No channel gets significantly better where better/worse is based on the signal's L1 norm
--- a/celt/celt_encoder.c
+++ b/celt/celt_encoder.c
@@ -1339,7 +1339,7 @@
}
static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem, int CC, int N,
- int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes, AnalysisInfo *analysis, opus_val16 tone_freq, opus_val32 toneishness)
+ int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, opus_val16 tf_estimate, int nbAvailableBytes, AnalysisInfo *analysis, opus_val16 tone_freq, opus_val32 toneishness)
{
int c;
VARDECL(celt_sig, _pre);
@@ -1351,6 +1351,8 @@
int pf_on;
int qg;
int overlap;
+ opus_val32 before[2]={0}, after[2]={0};
+ int cancel_pitch=0;
SAVE_STACK;
mode = st->mode;
@@ -1426,7 +1428,12 @@
/* Adjusting the threshold based on rate and continuity */
if (abs(pitch_index-st->prefilter_period)*10>pitch_index)
+ {
pf_threshold += QCONST16(.2f,15);
+ /* Completely disable the prefilter on strong transients without continuity. */
+ if (tf_estimate > QCONST16(.98f, 14))
+ gain1 = 0;
+ }
if (nbAvailableBytes<25)
pf_threshold += QCONST16(.1f,15);
if (nbAvailableBytes<35)
@@ -1461,9 +1468,11 @@
/*printf("%d %f\n", pitch_index, gain1);*/
c=0; do {
+ int i;
int offset = mode->shortMdctSize-overlap;
st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
OPUS_COPY(in+c*(N+overlap), st->in_mem+c*(overlap), overlap);
+ for (i=0;i<N;i++) before[c] += ABS32(SHR32(in[c*(N+overlap)+overlap+i], 12));
if (offset)
comb_filter(in+c*(N+overlap)+overlap, pre[c]+COMBFILTER_MAXPERIOD,
st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain,
@@ -1472,6 +1481,36 @@
comb_filter(in+c*(N+overlap)+overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset,
st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1,
st->prefilter_tapset, prefilter_tapset, mode->window, overlap, st->arch);
+ for (i=0;i<N;i++) after[c] += ABS32(SHR32(in[c*(N+overlap)+overlap+i], 12));
+ } while (++c<CC);
+
+ if (CC==2) {
+ opus_val16 thresh[2];
+ thresh[0] = MULT16_16_Q15(MULT16_16_Q15(QCONST16(.25f, 15), gain1), before[0]) + MULT16_16_Q15(QCONST16(.01f,15), before[1]);
+ thresh[1] = MULT16_16_Q15(MULT16_16_Q15(QCONST16(.25f, 15), gain1), before[1]) + MULT16_16_Q15(QCONST16(.01f,15), before[0]);
+ /* Don't use the filter if one channel gets significantly worse. */
+ if (after[0]-before[0] > thresh[0] || after[1]-before[1] > thresh[1]) cancel_pitch = 1;
+ /* Use the filter only if at least one channel gets significantly better. */
+ if (before[0]-after[0] < thresh[0] && before[1]-after[1] < thresh[1]) cancel_pitch = 1;
+ } else {
+ /* Check that the mono channel actually got better. */
+ if (after[0] > before[0]) cancel_pitch = 1;
+ }
+ /* If needed, revert to a gain of zero. */
+ if (cancel_pitch) {
+ c=0; do {
+ int offset = mode->shortMdctSize-overlap;
+ OPUS_COPY(in+c*(N+overlap)+overlap, pre[c]+COMBFILTER_MAXPERIOD, N);
+ comb_filter(in+c*(N+overlap)+overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset,
+ st->prefilter_period, pitch_index, overlap, -st->prefilter_gain, -0,
+ st->prefilter_tapset, prefilter_tapset, mode->window, overlap, st->arch);
+ } while (++c<CC);
+ gain1 = 0;
+ pf_on = 0;
+ qg = 0;
+ }
+
+ c=0; do {
OPUS_COPY(st->in_mem+c*(overlap), in+c*(N+overlap)+N, overlap);
if (N>COMBFILTER_MAXPERIOD)
@@ -1879,7 +1918,7 @@
&& st->complexity >= 5;
prefilter_tapset = st->tapset_decision;
- pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes, &st->analysis, tone_freq, toneishness);
+ pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, tf_estimate, nbAvailableBytes, &st->analysis, tone_freq, toneishness);
if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3)
&& (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period))
pitch_change = 1;
--
⑨