On 5/2/17, Muhammad Faiz <mfc...@gmail.com> wrote: > On Mon, May 1, 2017 at 3:30 PM, Paul B Mahol <one...@gmail.com> wrote: >> Signed-off-by: Paul B Mahol <one...@gmail.com> >> --- >> configure | 2 + >> doc/filters.texi | 10 ++ >> libavfilter/Makefile | 1 + >> libavfilter/af_afirfilter.c | 409 >> ++++++++++++++++++++++++++++++++++++++++++++ >> libavfilter/allfilters.c | 1 + >> 5 files changed, 423 insertions(+) >> create mode 100644 libavfilter/af_afirfilter.c >> >> diff --git a/configure b/configure >> index b3cb5b0..7fc7af4 100755 >> --- a/configure >> +++ b/configure >> @@ -3078,6 +3078,8 @@ unix_protocol_select="network" >> # filters >> afftfilt_filter_deps="avcodec" >> afftfilt_filter_select="fft" >> +afirfilter_filter_deps="avcodec" >> +afirfilter_filter_select="fft" >> amovie_filter_deps="avcodec avformat" >> aresample_filter_deps="swresample" >> ass_filter_deps="libass" >> diff --git a/doc/filters.texi b/doc/filters.texi >> index 119e747..ea343d1 100644 >> --- a/doc/filters.texi >> +++ b/doc/filters.texi >> @@ -878,6 +878,16 @@ afftfilt="1-clip((b/nb)*b,0,1)" >> @end example >> @end itemize >> >> +@section afirfilter >> + >> +Apply an Arbitary Frequency Impulse Response filter. >> + >> +This filter uses second stream as FIR coefficients. >> +If second stream holds single channel, it will be used >> +for all input channels in first stream, otherwise >> +number of channels in second stream must be same as >> +number of channels in first stream. >> + >> @anchor{aformat} >> @section aformat >> >> diff --git a/libavfilter/Makefile b/libavfilter/Makefile >> index 66c36e4..1a0f24b 100644 >> --- a/libavfilter/Makefile >> +++ b/libavfilter/Makefile >> @@ -38,6 +38,7 @@ OBJS-$(CONFIG_AEMPHASIS_FILTER) += >> af_aemphasis.o >> OBJS-$(CONFIG_AEVAL_FILTER) += aeval.o >> OBJS-$(CONFIG_AFADE_FILTER) += af_afade.o >> OBJS-$(CONFIG_AFFTFILT_FILTER) += af_afftfilt.o >> window_func.o >> +OBJS-$(CONFIG_AFIRFILTER_FILTER) += af_afirfilter.o >> OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o >> OBJS-$(CONFIG_AGATE_FILTER) += af_agate.o >> OBJS-$(CONFIG_AINTERLEAVE_FILTER) += f_interleave.o >> diff --git a/libavfilter/af_afirfilter.c b/libavfilter/af_afirfilter.c >> new file mode 100644 >> index 0000000..ef2488a >> --- /dev/null >> +++ b/libavfilter/af_afirfilter.c >> @@ -0,0 +1,409 @@ >> +/* >> + * Copyright (c) 2017 Paul B Mahol >> + * >> + * This file is part of FFmpeg. >> + * >> + * FFmpeg is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU Lesser General Public >> + * License as published by the Free Software Foundation; either >> + * version 2.1 of the License, or (at your option) any later version. >> + * >> + * FFmpeg is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >> + * Lesser General Public License for more details. >> + * >> + * You should have received a copy of the GNU Lesser General Public >> + * License along with FFmpeg; if not, write to the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA >> 02110-1301 USA >> + */ >> + >> +/** >> + * @file >> + * An arbitrary audio FIR filter >> + */ >> + >> +#include "libavutil/audio_fifo.h" >> +#include "libavutil/avassert.h" >> +#include "libavutil/channel_layout.h" >> +#include "libavutil/common.h" >> +#include "libavutil/opt.h" >> +#include "libavcodec/avfft.h" >> + >> +#include "audio.h" >> +#include "avfilter.h" >> +#include "formats.h" >> +#include "internal.h" >> + >> +typedef struct FIRContext { >> + const AVClass *class; >> + >> + int n; >> + int eof_coeffs; >> + int have_coeffs; >> + int nb_taps; >> + int fft_length; >> + int nb_channels; >> + int one2many; >> + >> + FFTContext *fft, *ifft; >> + FFTComplex **fft_data; >> + FFTComplex **fft_coef; > > Probably you may use rdft for performance reason.
I will concentrate on correctness of output first. > > > >> + >> + AVAudioFifo *fifo[2]; >> + AVFrame *in[2]; >> + AVFrame *buffer; >> + int64_t pts; >> + int hop_size; >> + int start, end; >> +} FIRContext; >> + >> +static int fir_filter(FIRContext *s, AVFilterLink *outlink) >> +{ >> + AVFilterContext *ctx = outlink->src; >> + int start = s->start, end = s->end; >> + int ret = 0, n, ch, j, k; >> + int nb_samples; >> + AVFrame *out; >> + >> + nb_samples = FFMIN(s->fft_length, av_audio_fifo_size(s->fifo[0])); >> + >> + s->in[0] = ff_get_audio_buffer(ctx->inputs[0], nb_samples); >> + if (!s->in[0]) >> + return AVERROR(ENOMEM); >> + >> + av_audio_fifo_peek(s->fifo[0], (void **)s->in[0]->extended_data, >> nb_samples); >> + >> + for (ch = 0; ch < outlink->channels; ch++) { >> + const float *src = (float *)s->in[0]->extended_data[ch]; >> + float *buf = (float *)s->buffer->extended_data[ch]; >> + FFTComplex *fft_data = s->fft_data[ch]; >> + FFTComplex *fft_coef = s->fft_coef[ch]; >> + >> + memset(fft_data, 0, sizeof(*fft_data) * s->fft_length); >> + for (n = 0; n < nb_samples; n++) { >> + fft_data[n].re = src[n]; >> + fft_data[n].im = 0; >> + } >> + >> + av_fft_permute(s->fft, fft_data); >> + av_fft_calc(s->fft, fft_data); >> + >> + fft_data[0].re *= fft_coef[0].re; >> + fft_data[0].im *= fft_coef[0].im; >> + for (n = 1; n < s->fft_length; n++) { >> + const float re = fft_data[n].re; >> + const float im = fft_data[n].im; >> + >> + fft_data[n].re = re * fft_coef[n].re - im * fft_coef[n].im; >> + fft_data[n].im = re * fft_coef[n].im + im * fft_coef[n].re; >> + } >> + >> + av_fft_permute(s->ifft, fft_data); >> + av_fft_calc(s->ifft, fft_data); >> + >> + start = s->start; >> + end = s->end; >> + k = end; >> + >> + for (n = 0, j = start; j < k && n < s->fft_length; n++, j++) { >> + buf[j] = fft_data[n].re; >> + } >> + >> + for (; n < s->fft_length; n++, j++) { >> + buf[j] = fft_data[n].re; >> + } >> + >> + start += s->hop_size; >> + end = j; >> + } >> + >> + s->start = start; >> + s->end = end; >> + >> + if (start >= nb_samples) { >> + float *dst, *buf; >> + >> + start -= nb_samples; >> + end -= nb_samples; >> + >> + s->start = start; >> + s->end = end; >> + >> + out = ff_get_audio_buffer(outlink, nb_samples); >> + if (!out) >> + return AVERROR(ENOMEM); >> + >> + out->pts = s->pts; >> + s->pts += nb_samples; > > Is pts handled correctly here? Seem it is not derived from input pts. > It can not be derived in any other way. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel