added HighPass filter, LowPass filter, Audiogate and Silencedetection

Former-commit-id: 074528238e
This commit is contained in:
Wilbert Bongers 2022-08-02 10:12:24 +02:00
parent b7e1c082e3
commit 5f014029d6
4 changed files with 213 additions and 0 deletions

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace FFMpegCore.Arguments
{
public class AudioGateArgument : IAudioFilterArgument
{
private readonly Dictionary<string, string> _arguments = new Dictionary<string, string>();
/// <summary>
/// Audio Gate. <see href="https://ffmpeg.org/ffmpeg-filters.html#agate"/>
/// </summary>
/// <param name="level_in">Set input level before filtering. Default is 1. Allowed range is from 0.015625 to 64.</param>
/// <param name="mode">Set the mode of operation. Can be upward or downward. Default is downward. If set to upward mode, higher parts of signal will be amplified, expanding dynamic range in upward direction. Otherwise, in case of downward lower parts of signal will be reduced.</param>
/// <param name="range">Set the level of gain reduction when the signal is below the threshold. Default is 0.06125. Allowed range is from 0 to 1. Setting this to 0 disables reduction and then filter behaves like expander.</param>
/// <param name="threshold">If a signal rises above this level the gain reduction is released. Default is 0.125. Allowed range is from 0 to 1.</param>
/// <param name="ratio">Set a ratio by which the signal is reduced. Default is 2. Allowed range is from 1 to 9000.</param>
/// <param name="attack">Amount of milliseconds the signal has to rise above the threshold before gain reduction stops. Default is 20 milliseconds. Allowed range is from 0.01 to 9000.</param>
/// <param name="release">Amount of milliseconds the signal has to fall below the threshold before the reduction is increased again. Default is 250 milliseconds. Allowed range is from 0.01 to 9000.</param>
/// <param name="makeup">Set amount of amplification of signal after processing. Default is 1. Allowed range is from 1 to 64.</param>
/// <param name="knee">Curve the sharp knee around the threshold to enter gain reduction more softly. Default is 2.828427125. Allowed range is from 1 to 8.</param>
/// <param name="detection">Choose if exact signal should be taken for detection or an RMS like one. Default is rms. Can be peak or rms.</param>
/// <param name="link">Choose if the average level between all channels or the louder channel affects the reduction. Default is average. Can be average or maximum.</param>
public AudioGateArgument(double level_in = 1, string mode = "downward", double range = 0.06125, double threshold = 0.125, int ratio = 2, double attack = 20, double release = 250, int makeup = 1, double knee = 2.828427125, string detection = "rms", string link = "average")
{
if (level_in < 0.015625 || level_in > 64) throw new ArgumentOutOfRangeException(nameof(level_in), "Level in must be between 0.015625 to 64");
if (!(mode == "upward" || mode == "downward")) throw new ArgumentOutOfRangeException(nameof(mode), "Mode must be either upward or downward");
if (range <= 0 || range > 1) throw new ArgumentOutOfRangeException(nameof(range));
if (threshold < 0 || threshold > 1) throw new ArgumentOutOfRangeException(nameof(threshold), "Threshold must be between 0 and 1");
if (ratio < 1 || ratio > 9000) throw new ArgumentOutOfRangeException(nameof(ratio), "Ratio must be between 1 and 9000");
if (attack < 0.01 || attack > 9000) throw new ArgumentOutOfRangeException(nameof(attack), "Attack must be between 0.01 and 9000");
if (release < 0.01 || release > 9000) throw new ArgumentOutOfRangeException(nameof(release), "Release must be between 0.01 and 9000");
if (makeup < 1 || makeup > 64) throw new ArgumentOutOfRangeException(nameof(makeup), "Makeup Gain must be between 1 and 64");
if (!(detection == "peak" || detection == "rms")) throw new ArgumentOutOfRangeException(nameof(detection), "Detection must be either peak or rms");
if (!(link != "average" || link != "maximum")) throw new ArgumentOutOfRangeException(nameof(link), "Link must be either average or maximum");
_arguments.Add("level_in", level_in.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("mode", mode.ToString());
_arguments.Add("range", range.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("threshold", threshold.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("ratio", ratio.ToString());
_arguments.Add("attack", attack.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("release", release.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("makeup", makeup.ToString());
_arguments.Add("detection", detection.ToString());
_arguments.Add("link", link.ToString());
}
public string Key { get; } = "agate";
public string Value => string.Join(":", _arguments.Select(pair => $"{pair.Key}={pair.Value}"));
}
}

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace FFMpegCore.Arguments
{
public class HighPassFilterArgument : IAudioFilterArgument
{
private readonly Dictionary<string, string> _arguments = new Dictionary<string, string>();
private readonly List<string> _widthTypes = new List<string>{"h", "q", "o", "s", "k"};
private readonly List<string> _transformTypes = new List<string>{"di", "dii", "tdi", "tdii", "latt", "svf", "zdf"};
private readonly List<string> _precision = new List<string> { "auto", "s16", "s32", "f32", "f64" };
/// <summary>
/// HighPass Filter. <see href="https://ffmpeg.org/ffmpeg-filters.html#highpass"/>
/// </summary>
/// <param name="frequency">Set frequency in Hz. Default is 3000.</param>
/// <param name="poles">Set number of poles. Default is 2.</param>
/// <param name="width_type">Set method to specify band-width of filter, possible values are: h, q, o, s, k</param>
/// <param name="width">Specify the band-width of a filter in width_type units. Applies only to double-pole filter. The default is 0.707q and gives a Butterworth response.</param>
/// <param name="mix">How much to use filtered signal in output. Default is 1. Range is between 0 and 1.</param>
/// <param name="channels">Specify which channels to filter, by default all available are filtered.</param>
/// <param name="normalize">Normalize biquad coefficients, by default is disabled. Enabling it will normalize magnitude response at DC to 0dB.</param>
/// <param name="transform">Set transform type of IIR filter, possible values are: di, dii, tdi, tdii, latt, svf, zdf</param>
/// <param name="precision">Set precison of filtering, possible values are: auto, s16, s32, f32, f64.</param>
/// <param name="block_size">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.</param>
public HighPassFilterArgument(double frequency = 3000, int poles = 2, string width_type = "q", double width = 0.707, double mix = 1, string channels = "", bool normalize = false, string transform = "", string precision = "auto", int? block_size = null)
{
if (frequency < 0) throw new ArgumentOutOfRangeException(nameof(frequency), "Frequency must be a positive number");
if (poles < 1 || poles > 2) throw new ArgumentOutOfRangeException(nameof(poles), "Poles must be either 1 or 2");
if (!_widthTypes.Contains(width_type)) throw new ArgumentOutOfRangeException(nameof(width_type), "Width type must be either " + _widthTypes.ToString());
if (mix < 0 || mix > 1) throw new ArgumentOutOfRangeException(nameof(mix), "Mix must be between 0 and 1");
if (!_precision.Contains(precision)) throw new ArgumentOutOfRangeException(nameof(precision), "Precision must be either " + _precision.ToString());
_arguments.Add("f", frequency.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("p", poles.ToString());
_arguments.Add("t", width_type);
_arguments.Add("w", width.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("m", mix.ToString("0.00", CultureInfo.InvariantCulture));
if (channels != "")
{
_arguments.Add("c", channels);
}
_arguments.Add("n", (normalize ? 1 : 0).ToString());
if (transform != "" && _transformTypes.Contains(transform))
{
_arguments.Add("a", transform);
}
_arguments.Add("r", precision);
if (block_size != null && block_size >= 0)
{
_arguments.Add("b", block_size.ToString());
}
}
public string Key { get; } = "highpass";
public string Value => string.Join(":", _arguments.Select(pair => $"{pair.Key}={pair.Value}"));
}
}

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace FFMpegCore.Arguments
{
public class LowPassFilterArgument : IAudioFilterArgument
{
private readonly Dictionary<string, string> _arguments = new Dictionary<string, string>();
private readonly List<string> _widthTypes = new List<string> { "h", "q", "o", "s", "k" };
private readonly List<string> _transformTypes = new List<string> { "di", "dii", "tdi", "tdii", "latt", "svf", "zdf" };
private readonly List<string> _precision = new List<string> { "auto", "s16", "s32", "f32", "f64" };
/// <summary>
/// LowPass Filter. <see href="https://ffmpeg.org/ffmpeg-filters.html#lowpass"/>
/// </summary>
/// <param name="frequency">Set frequency in Hz. Default is 3000.</param>
/// <param name="poles">Set number of poles. Default is 2.</param>
/// <param name="width_type">Set method to specify band-width of filter, possible values are: h, q, o, s, k</param>
/// <param name="width">Specify the band-width of a filter in width_type units. Applies only to double-pole filter. The default is 0.707q and gives a Butterworth response.</param>
/// <param name="mix">How much to use filtered signal in output. Default is 1. Range is between 0 and 1.</param>
/// <param name="channels">Specify which channels to filter, by default all available are filtered.</param>
/// <param name="normalize">Normalize biquad coefficients, by default is disabled. Enabling it will normalize magnitude response at DC to 0dB.</param>
/// <param name="transform">Set transform type of IIR filter, possible values are: di, dii, tdi, tdii, latt, svf, zdf</param>
/// <param name="precision">Set precison of filtering, possible values are: auto, s16, s32, f32, f64.</param>
/// <param name="block_size">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.</param>
public LowPassFilterArgument(double frequency = 3000, int poles = 2, string width_type = "q", double width = 0.707, double mix = 1, string channels = "", bool normalize = false, string transform = "", string precision = "auto", int? block_size = null)
{
if (frequency < 0) throw new ArgumentOutOfRangeException(nameof(frequency), "Frequency must be a positive number");
if (poles < 1 || poles > 2) throw new ArgumentOutOfRangeException(nameof(poles), "Poles must be either 1 or 2");
if (!_widthTypes.Contains(width_type)) throw new ArgumentOutOfRangeException(nameof(width_type), "Width type must be either " + _widthTypes.ToString());
if (mix < 0 || mix > 1) throw new ArgumentOutOfRangeException(nameof(mix), "Mix must be between 0 and 1");
if (!_precision.Contains(precision)) throw new ArgumentOutOfRangeException(nameof(precision), "Precision must be either " + _precision.ToString());
_arguments.Add("f", frequency.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("p", poles.ToString());
_arguments.Add("t", width_type);
_arguments.Add("w", width.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("m", mix.ToString("0.00", CultureInfo.InvariantCulture));
if (channels != "")
{
_arguments.Add("c", channels);
}
_arguments.Add("n", (normalize ? 1 : 0).ToString());
if (transform != "" && _transformTypes.Contains(transform))
{
_arguments.Add("a", transform);
}
_arguments.Add("r", precision);
if (block_size != null && block_size >= 0)
{
_arguments.Add("b", block_size.ToString());
}
}
public string Key { get; } = "lowpass";
public string Value => string.Join(":", _arguments.Select(pair => $"{pair.Key}={pair.Value}"));
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace FFMpegCore.Arguments
{
public class SilenceDetectArgument : IAudioFilterArgument
{
private readonly Dictionary<string, string> _arguments = new Dictionary<string, string>();
/// <summary>
/// Silence Detection. <see href="https://ffmpeg.org/ffmpeg-filters.html#silencedetect"/>
/// </summary>
/// <param name="noise_type">Set noise type to db (decibel) or ar (amplitude ratio). Default is dB</param>
/// <param name="noise">Set noise tolerance. Can be specified in dB (in case "dB" is appended to the specified value) or amplitude ratio. Default is -60dB, or 0.001.</param>
/// <param name="duration">Set silence duration until notification (default is 2 seconds). See (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual for the accepted syntax.</param>
/// <param name="mono">Process each channel separately, instead of combined. By default is disabled.</param>
public SilenceDetectArgument(string noise_type = "db", double noise = 60, double duration = 2, bool mono = false)
{
if(noise_type == "db")
{
_arguments.Add("n", $"{noise.ToString("0.0", CultureInfo.InvariantCulture)}dB");
}
else if (noise_type == "ar")
{
_arguments.Add("n", noise.ToString("0.00", CultureInfo.InvariantCulture));
}
else throw new ArgumentOutOfRangeException(nameof(noise_type), "Noise type must be either db or ar");
_arguments.Add("d", duration.ToString("0.00", CultureInfo.InvariantCulture));
_arguments.Add("m", (mono ? 1 : 0).ToString());
}
public string Key { get; } = "silencedetect";
public string Value => string.Join(":", _arguments.Select(pair => $"{pair.Key}={pair.Value}"));
}
}