From patchwork Sat May 28 07:23:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 35952 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6914:b0:82:6b11:2509 with SMTP id q20csp1253633pzj; Sat, 28 May 2022 00:20:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxjs8sPc0XpoUkHuQDwsC/fTyCd9k6wbjBUfN3SYDeMDT14C1VMakxfNdJDUn/sEnS7IfI+ X-Received: by 2002:a17:907:7810:b0:6e7:ef73:8326 with SMTP id la16-20020a170907781000b006e7ef738326mr40936837ejc.429.1653722450407; Sat, 28 May 2022 00:20:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1653722450; cv=none; d=google.com; s=arc-20160816; b=Egcd+NLtmDusouPfVeNjPJwHvhj6nIcOJj6yyR/UqSyVw3RXQe9Rc10JtFzgUgutSC DUAiuSxofOeDZdSwrpk/CMrGzvNvn+ICBOwzKoqtCxVSk1gmkBdXhM/OlxB5XwNjplQS 4FyOvEq0NtIX2zj+rgi3gf+KrTdaQys6mAP+nN0IQKHfiTlonQGOmupap/xXN0TX0W4c X2t7yvgznHYgZ4l4NssEZn8Uzxk2tEWh+Qf2DHB2Wum14qBvN1xGpUXQKlZzQcu/QD0j I5hVH5Gdyziuzkb+zDP2Knq1dgK1CrdTjAxKn1FDndxomQwvCteOt9Zb2ByVt1Zg5ZXn 33+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=/MWIGDU2pcLNI+jVUyZzKecDSAt1/jMN3SCFuoDkR40=; b=sA9+wNepDRK7GZ4k+n2MYKyJgR/KE06YXaCp+hXlOj0A92gAQJcsJAALkWtFLUKbYu FvohBQLw+Lccngbm+8NcMLNdoiy8nB2IaUi8syfeDVCxEKvvqY3bU5vtoMWzG6jJFNbt 4GbCSRpBQwfngA/qVFpqg7ubvpU43D5l5sEE23mMZ6s9GZNDT6n1jViQZvEL7zf3icbF RroaOjiNETbe46NAnMRos5swArOcWuCRGX7Uow5CMhHn4v64pu/u0i2IhCD95VOeg/rG E1YGY2ZKqkdUkNYDmY6ACeie6mXOezI4aX3Y2DEVx7IjI4Aq1oxoTdCVXsKwHVFw0thl QfsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b="NfBE/JPo"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id r6-20020a05640251c600b0042b615e6037si7398176edd.264.2022.05.28.00.20.49; Sat, 28 May 2022 00:20:50 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b="NfBE/JPo"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 29E0968B58E; Sat, 28 May 2022 10:20:46 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1E49968B39E for ; Sat, 28 May 2022 10:20:40 +0300 (EEST) Received: by mail-ed1-f51.google.com with SMTP id h11so7775061eda.8 for ; Sat, 28 May 2022 00:20:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=5N+C35wz9kPfYBm1FP3Z27Z4AGuaWHoidImJKF9da98=; b=NfBE/JPokiy628kyN1+4+OM0eQ1LKOheqUKdkL5M1yan/f6ciNssWXSPURGalbOL/B C11lRbomFbhUNR0Q3mcx/fOKBUQGqW+TYaaaNbF0Kqrr2PJIEH3/VCel9pAfk6P9WIQu paOM1ABVpS9D9mltbPCZgLJLYlZShceORK5f4g+SxpygQAyeQwZwdtAhuzG1ebyoUNz4 BkfNDAgyvWpKOTuVWMN2XY59GMYozm09ZrCqHwLiAF+6+w/exqsiqVg/Kf3PGf0vTCAn /It1LaLx0GdU+ttSmauyFN5jTK1QUvH+8hKnN/k9luqyZw1XPZ1YP2p5qj0xL3bPBRWr cS8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=5N+C35wz9kPfYBm1FP3Z27Z4AGuaWHoidImJKF9da98=; b=48EHMsFzr4gWEPevljueeoAfIbY+W5YQmVh4YNm1l5LBxJSR3LLPprrqkLb9KORrkx L26rA7y88wnpr9t2IMTWjRrpakQK39Gn5bOwNfkQGL800BbCykdUaMd/xCFLAZtwYD28 vxS6lj60QqGus2BvppbHGsaC/mHcZnvnUFPaXXKMtsntoxgqbqeh9xBhthgbzSF/mwRv 4vEelfqpK6le+dXzrovFbHKzJu3imjFwFFsXE7MYw/wbyrGe6KQhRV/Sq0gYsnNdYhlz E/TEnu8hCnjJbMqjH7OpdAXH9kJFeOm4qjKywfzjLCvBoSRkNPLZeEkULLkeHaGPvLjf hkeQ== X-Gm-Message-State: AOAM532orq05xsuAW62t4kC7qoElMxCjXF6xQufAS6EVkvVspW5ygDq2 rGQ8syf114iIPuN79FARUw9j69SargY= X-Received: by 2002:a05:6402:292b:b0:42b:dbc5:c553 with SMTP id ee43-20020a056402292b00b0042bdbc5c553mr11634981edb.297.1653722439438; Sat, 28 May 2022 00:20:39 -0700 (PDT) Received: from localhost.localdomain ([95.168.121.73]) by smtp.gmail.com with ESMTPSA id r17-20020a50d691000000b0042617ba6389sm3171604edi.19.2022.05.28.00.20.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 May 2022 00:20:38 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sat, 28 May 2022 09:23:27 +0200 Message-Id: <20220528072327.116623-1-onemda@gmail.com> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avfilter: add tiltshelf audio filter X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: PDNhSBK0oeUB Signed-off-by: Paul B Mahol --- doc/filters.texi | 91 ++++++++++++++++++++++++++++++++++++++++ libavfilter/af_biquads.c | 39 ++++++++++++++--- libavfilter/allfilters.c | 1 + 3 files changed, 125 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 0e10946cca..d65e83d4d0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -6690,6 +6690,97 @@ Set window overlap. If set to 1, the recommended overlap for selected window function will be picked. Default is @code{0.5}. @end table +@section tiltshelf + +Boost or cut the lower frequencies and cut or boost higher frequencies +of the audio using a two-pole shelving filter with a response similar to +that of a standard hi-fi's tone-controls. +This is also known as shelving equalisation (EQ). + +The filter accepts the following options: + +@table @option +@item gain, g +Give the gain at 0 Hz. Its useful range is about -20 +(for a large cut) to +20 (for a large boost). +Beware of clipping when using a positive gain. + +@item frequency, f +Set the filter's central frequency and so can be used +to extend or reduce the frequency range to be boosted or cut. +The default value is @code{3000} Hz. + +@item width_type, t +Set method to specify band-width of filter. +@table @option +@item h +Hz +@item q +Q-Factor +@item o +octave +@item s +slope +@item k +kHz +@end table + +@item width, w +Determine how steep is the filter's shelf transition. + +@item poles, p +Set number of poles. Default is 2. + +@item mix, m +How much to use filtered signal in output. Default is 1. +Range is between 0 and 1. + +@item channels, c +Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdi +@item tdii +@item latt +@item svf +@item zdf +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. +@end table + +@subsection Commands + +This filter supports some options as @ref{commands}. + @section treble, highshelf Boost or cut treble (upper) frequencies of the audio using a two-pole diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index 26cb4d49bb..9110faabac 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -85,6 +85,7 @@ enum FilterType { lowpass, lowshelf, highshelf, + tiltshelf, }; enum WidthType { @@ -698,6 +699,17 @@ static void convert_dir2zdf(BiquadsContext *s, int sample_rate) m[1] = k * (A - 1.); m[2] = A * A - 1.; break; + case tiltshelf: + A = ff_exp10(s->gain / 20.); + g = tan(M_PI * s->frequency / sample_rate) / sqrt(A); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1./ A; + m[1] = k * (A - 1.) / A; + m[2] = (A * A - 1.) / A; + break; case treble: case highshelf: A = ff_exp10(s->gain / 40.); @@ -777,7 +789,8 @@ static int config_filter(AVFilterLink *outlink, int reset) AVFilterContext *ctx = outlink->src; BiquadsContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - double A = ff_exp10(s->gain / 40); + double gain = s->gain * ((s->filter_type == tiltshelf) + 1.); + double A = ff_exp10(gain / 40); double w0 = 2 * M_PI * s->frequency / inlink->sample_rate; double K = tan(w0 / 2.); double alpha, beta; @@ -835,9 +848,10 @@ static int config_filter(AVFilterLink *outlink, int reset) break; case bass: beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); + case tiltshelf: case lowshelf: if (s->poles == 1) { - double A = ff_exp10(s->gain / 20); + double A = ff_exp10(gain / 20); double ro = -sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); double n = (A + 1) / (A - 1); double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); @@ -863,7 +877,7 @@ static int config_filter(AVFilterLink *outlink, int reset) beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); case highshelf: if (s->poles == 1) { - double A = ff_exp10(s->gain / 20); + double A = ff_exp10(gain / 20); double ro = sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); double n = (A + 1) / (A - 1); double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); @@ -985,6 +999,14 @@ static int config_filter(AVFilterLink *outlink, int reset) s->b2 *= factor; } + switch (s->filter_type) { + case tiltshelf: + s->b0 /= A; + s->b1 /= A; + s->b2 /= A; + break; + } + s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->ch_layout.nb_channels); if (!s->cache) return AVERROR(ENOMEM); @@ -1528,7 +1550,7 @@ DEFINE_BIQUAD_FILTER_2(bass, "Boost or cut lower frequencies.", bass_lowshelf); DEFINE_BIQUAD_FILTER_2(lowshelf, "Apply a low shelf filter.", bass_lowshelf); #endif /* CONFIG_LOWSHELF_FILTER */ #endif /* CONFIG_BASS_FILTER || CONFIG LOWSHELF_FILTER */ -#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER +#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER || CONFIG_TILTSHELF_FILTER static const AVOption treble_highshelf_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, @@ -1572,7 +1594,7 @@ static const AVOption treble_highshelf_options[] = { {NULL} }; -AVFILTER_DEFINE_CLASS_EXT(treble_highshelf, "treble/highshelf", +AVFILTER_DEFINE_CLASS_EXT(treble_highshelf, "treble/high/tiltshelf", treble_highshelf_options); #if CONFIG_TREBLE_FILTER @@ -1582,7 +1604,12 @@ DEFINE_BIQUAD_FILTER_2(treble, "Boost or cut upper frequencies.", treble_highshe #if CONFIG_HIGHSHELF_FILTER DEFINE_BIQUAD_FILTER_2(highshelf, "Apply a high shelf filter.", treble_highshelf); #endif /* CONFIG_HIGHSHELF_FILTER */ -#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER */ + +#if CONFIG_TILTSHELF_FILTER +DEFINE_BIQUAD_FILTER_2(tiltshelf, "Apply a tilt shelf filter.", treble_highshelf); +#endif +#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER || CONFIG_TILTSHELF_FILTER */ + #if CONFIG_BANDPASS_FILTER static const AVOption bandpass_options[] = { {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 2409964e53..2f72477523 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -149,6 +149,7 @@ extern const AVFilter ff_af_stereotools; extern const AVFilter ff_af_stereowiden; extern const AVFilter ff_af_superequalizer; extern const AVFilter ff_af_surround; +extern const AVFilter ff_af_tiltshelf; extern const AVFilter ff_af_treble; extern const AVFilter ff_af_tremolo; extern const AVFilter ff_af_vibrato;