[FFmpeg-devel] [PATCH] QCELP postfilter
Ronald S. Bultje
rsbultje
Wed Mar 31 21:37:11 CEST 2010
Hi,
On Tue, Mar 30, 2010 at 2:23 PM, Michael Niedermayer <michaelni at gmx.at> wrote:
> so what arguments do we have that the code is correct?
> it does not match the reference decoder not even slightly, and you seem to
> argue its better not to test how close the 2 decoders match the original
> encoder input.
Better to actually see what the difference stems from. Disregarding my
second patch, I basically see that my first patch comes closest to
what the binary does. PSNR (A) becomes 319.49 from ~290 by enabling
postfilter in our code versus reference (i.e. psnr
${code}-without-postfilter.wav ${code}-with-postfilter.wav, where code
is ourcode or refcode). Implementing the reference postfilter into our
code leads to a PSNR of ~310, and the difference between my own code
and that code (should be zero if it was an identical copy) is ~194
(PSNR (B), i.e. psnr ourcode-with-refpostfilter.wav
ourcode-with-ourpostfilter.wav). Yes, that's a lot for a postfilter
only doing four things.
Why? Three things change the PSNR significantly (>0.01): zero-filter,
adaptive gain control and tilt correction.
1) Zero-filter: not sure why, PSNR (A) doesn't change, but PSNR (B)
becomes ~10 (from zero) because of this. I've not looked too much into
it because it's not very significant compared to the rest.
2) AGC
ref code:
if ((input_energy!=0)&&(output_energy!=0)) {
norm=sqrt((double)(input_energy/output_energy));
*factor=AGC_FACTOR*(*factor)+(1-AGC_FACTOR)*norm;
}
for (i=0; i<length; i++) {
return_vals[i]=output[i]*(*factor);
}
So the "factor" (this is adaptive gain change) is changed per loop,
whereas FFmpeg changes the factor every sample. I believe this is a
bug in the reference code, and it doesn't have an audible effect on
sound quality (quite logically, all it does is smoothly modify gain).
Suggestions on whether I should conserve this bug are welcome. This
changes PSNR-A to 293 and PSNR-B to 139 (yeah, that's a lot).
3) tilt correction.
ref code (no joke):
float bright_lpc = -0.3;
do_pole_filter(samples, samples, 160, 1,
&q->postfilter_tilt_mem, &bright_lpc);
where pole_filter is a synthesis_filter. This does exactly the same as
our tilt filter, except that (thanks Kostya for figuring this out for
me) pole_filter will do a forward loop, so it will basically tilt it
against filtered samples, whereas our tilt code does a backward loop,
so it will tilt against unfiltered samples. Again, my understanding is
that this is a bug in the reference code. suggestions on whether we
want to maintain this bug or not are welcome (it does not affect sound
quality in any audible way). PSNR is changed to (A) 319.49 and (B)
194.42.
By the way, all this is a little fuzzy because the reference code does
incredibly weird stuff, e.g. their pole_filter is a synthesis filter
with negative LPCs (this is probably why my original numbers did crazy
stuff and returned NaN for each sample, after a few INFs first?), so I
had to add some plus/minus signs in random locations to get any
audible output at all, and I can't say for sure whether that output is
what I'm supposed to get (just that it sounds OK versus white-noise).
I apologize for that but don't really know any better way to work with
it.
Ronald
More information about the ffmpeg-devel
mailing list