[FFmpeg-devel] [PATCH 2/2] swresample/resample: speed up Blackman Nuttall filter
gajjanagadde at gmail.com
Mon Nov 9 15:38:44 CET 2015
This may be a slightly surprising optimization, but is actually based on
an understanding of how math libraries compute trigonometric functions.
Explanation is given here so that future development uses libm more effectively
across the codebase.
All libm's essentially compute transcendental functions via some kind of
polynomial approximation, be it Taylor-Maclaurin or Chebyshev.
Correction terms are added via polynomial correction factors when needed
to squeeze out the last bits of accuracy. Lookup tables are also
In the case of trigonometric functions, periodicity is exploited via
first doing a range reduction to an interval around zero, and then using
some polynomial approximation.
This range reduction is the most natural way of doing things - else one
would need polynomials for ranges in different periods which makes no
To avoid the need for the range reduction, it is helpful to feed in
arguments as close to the origin as possible for the trigonometric
functions. In fact, this also makes sense from an accuracy point of view:
IEEE floating point has far more resolution for small numbers than big ones.
This patch does this for the Blackman-Nuttall filter, and yields a
Sample benchmark (x86-64, Haswell, GNU/Linux)
18893514 decicycles in build_filter (loop 1000), 256 runs, 0 skips
18599863 decicycles in build_filter (loop 1000), 512 runs, 0 skips
18445574 decicycles in build_filter (loop 1000), 1000 runs, 24 skips
16290697 decicycles in build_filter (loop 1000), 256 runs, 0 skips
16267172 decicycles in build_filter (loop 1000), 512 runs, 0 skips
16251105 decicycles in build_filter (loop 1000), 1000 runs, 24 skips
Signed-off-by: Ganesh Ajjanagadde <gajjanagadde at gmail.com>
libswresample/resample.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libswresample/resample.c b/libswresample/resample.c
index d0a406e..c5ee62d 100644
@@ -180,8 +180,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
else y= d*(-4 + 8*x - 5*x*x + x*x*x);
- w = 2.0*x / (factor*tap_count) + M_PI;
- t = cos(w);
+ w = 2.0*x / (factor*tap_count);
+ t = -cos(w);
y *= 0.3635819 - 0.4891775 * t + 0.1365995 * (2*t*t-1) - 0.0106411 * (4*t*t*t - 3*t);
More information about the ffmpeg-devel