On 1/30/15, Michael Niedermayer <michae...@gmx.at> wrote: > On Fri, Jan 30, 2015 at 10:17:59AM +0000, Paul B Mahol wrote: >> Signed-off-by: Paul B Mahol <one...@gmail.com> >> --- >> doc/filters.texi | 19 ++++++ >> libavfilter/Makefile | 1 + >> libavfilter/af_dcshift.c | 161 >> +++++++++++++++++++++++++++++++++++++++++++++++ >> libavfilter/allfilters.c | 1 + >> 4 files changed, 182 insertions(+) >> create mode 100644 libavfilter/af_dcshift.c >> >> diff --git a/doc/filters.texi b/doc/filters.texi >> index cba2697..27a745f 100644 >> --- a/doc/filters.texi >> +++ b/doc/filters.texi >> @@ -917,6 +917,7 @@ audio, the data is treated as if all the planes were >> concatenated. >> A list of Adler-32 checksums for each data plane. >> @end table >> >> +@anchor{astats} >> @section astats >> >> Display time domain statistical information about the audio channels. >> @@ -1394,6 +1395,24 @@ >> compand=.1|.1:.1|.1:-45.1/-45.1|-45/-900|0/-900:.01:45:-90:.1 >> @end example >> @end itemize >> >> +@section dcshift >> +Apply a DC shift to the audio. >> + >> +This can be useful to remove a DC offset (caused perhaps by a hardware >> problem >> +in the recording chain) from the audio. The effect of a DC offset is >> reduced >> +headroom and hence volume. The @ref{astats} filter can be used to >> determine if >> +a signal has a DC offset. >> + >> +@table @option >> +@item shift >> +Set the DC shift, allowed range is [-1, 1]. It indicates the amount to >> shift >> +the audio. >> + >> +@item limitergain >> +Optional. It should have a value much less than 1 (e.g. 0.05 or 0.02) and >> is >> +used to prevent clipping. >> +@end table >> + >> @section earwax >> >> Make audio easier to listen to on headphones. >> diff --git a/libavfilter/Makefile b/libavfilter/Makefile >> index 7e0d456..60072f9 100644 >> --- a/libavfilter/Makefile >> +++ b/libavfilter/Makefile >> @@ -65,6 +65,7 @@ OBJS-$(CONFIG_BS2B_FILTER) += >> af_bs2b.o >> OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o >> OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o >> OBJS-$(CONFIG_COMPAND_FILTER) += af_compand.o >> +OBJS-$(CONFIG_DCSHIFT_FILTER) += af_dcshift.o >> OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o >> OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o >> OBJS-$(CONFIG_EQUALIZER_FILTER) += af_biquads.o >> diff --git a/libavfilter/af_dcshift.c b/libavfilter/af_dcshift.c >> new file mode 100644 >> index 0000000..25fc66a >> --- /dev/null >> +++ b/libavfilter/af_dcshift.c >> @@ -0,0 +1,161 @@ >> +/* >> + * 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 >> + */ >> + >> +#include "libavutil/opt.h" >> +#include "libavutil/samplefmt.h" >> +#include "avfilter.h" >> +#include "audio.h" >> +#include "internal.h" >> + >> +typedef struct DCShiftContext { >> + const AVClass *class; >> + double dcshift; >> + double limiterthreshhold; >> + double limitergain; >> +} DCShiftContext; >> + >> +#define OFFSET(x) offsetof(DCShiftContext, x) >> +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM >> + >> +static const AVOption dcshift_options[] = { >> + { "shift", "set DC shift", OFFSET(dcshift), >> AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, A }, >> + { "limitergain", "set limiter gain", OFFSET(limitergain), >> AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 1, A }, >> + { NULL } >> +}; >> + >> +AVFILTER_DEFINE_CLASS(dcshift); >> + >> +static av_cold int init(AVFilterContext *ctx) >> +{ >> + DCShiftContext *s = ctx->priv; >> + >> + s->limiterthreshhold = INT32_MAX * (1.0 - (fabs(s->dcshift) - >> s->limitergain)); >> + >> + return 0; >> +} >> + >> +static int query_formats(AVFilterContext *ctx) >> +{ >> + AVFilterChannelLayouts *layouts; >> + AVFilterFormats *formats; >> + static const enum AVSampleFormat sample_fmts[] = { >> + AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE >> + }; >> + >> + layouts = ff_all_channel_layouts(); >> + if (!layouts) >> + return AVERROR(ENOMEM); >> + ff_set_common_channel_layouts(ctx, layouts); >> + >> + formats = ff_make_format_list(sample_fmts); >> + if (!formats) >> + return AVERROR(ENOMEM); >> + ff_set_common_formats(ctx, formats); >> + >> + formats = ff_all_samplerates(); >> + if (!formats) >> + return AVERROR(ENOMEM); >> + ff_set_common_samplerates(ctx, formats); >> + >> + return 0; >> +} >> + >> +static int filter_frame(AVFilterLink *inlink, AVFrame *in) >> +{ >> + AVFilterContext *ctx = inlink->dst; >> + AVFilterLink *outlink = ctx->outputs[0]; >> + AVFrame *out = ff_get_audio_buffer(inlink, in->nb_samples); >> + DCShiftContext *s = ctx->priv; >> + int i, j; >> + double dcshift = s->dcshift; >> + >> + if (!out) { >> + av_frame_free(&in); >> + return AVERROR(ENOMEM); >> + } >> + av_frame_copy_props(out, in); >> + >> + if (s->limitergain > 0) { >> + for (i = 0; i < inlink->channels; i++) { >> + const int32_t *src = (int32_t *)in->extended_data[i]; >> + int32_t *dst = (int32_t *)out->extended_data[i]; >> + >> + for (j = 0; j < in->nb_samples; j++) { >> + double d; >> + >> + d = src[j]; >> + >> + if (d > s->limiterthreshhold && dcshift > 0) { >> + d = (d - s->limiterthreshhold) * s->limitergain / >> + (INT32_MAX - s->limiterthreshhold) + >> + s->limiterthreshhold + dcshift; >> + } else if (d < -s->limiterthreshhold && dcshift < 0) { >> + d = (d + s->limiterthreshhold) * s->limitergain / >> + (INT32_MAX - s->limiterthreshhold) - >> + s->limiterthreshhold + dcshift; >> + } else { >> + d = dcshift * INT32_MAX + d; >> + } >> + >> + dst[j] = av_clipl_int32_c(d); >> + } >> + } >> + } else { >> + for (i = 0; i < inlink->channels; i++) { >> + const int32_t *src = (int32_t *)in->extended_data[i]; >> + int32_t *dst = (int32_t *)out->extended_data[i]; >> + >> + for (j = 0; j < in->nb_samples; j++) { >> + double d = dcshift * (INT32_MAX + 1.) + src[j]; >> + >> + dst[j] = av_clipl_int32_c(d); > > i think this should use some rounding function like llrint() ? > though with 32bit precission it probably doesnt really matter much > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > No human being will ever know the Truth, for even if they happen to say it > by chance, they would not even known they had done so. -- Xenophanes >
Will apply it as is if there is no more comments. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel