7

FFmpeg filters 分析:af_volume

 2 years ago
source link: http://blog.tubumu.com/2020/11/03/ffmpeg-filters-af-volume/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文分析 FFmpeg af_volume 的实现。

二、af_volume 的作用及基本原理

af_volume 的作用是调整音频的音量。基本原理是 PCM 数据乘于某个系数,就达到了调整音量的目的。

三、在调用 ffmpeg 程序时使用 af_volume

减半音量:

ffmpeg -i input.mp3 -af "volume=0.5" output.mp3

ffmpeg 的表达式解析和计算支持将 “volume=0.5” 写作 “volume=1/2”(不会当成整数相除为0的情况) 或 “volume=-6.0206dB”(负数)。

音量增大50%:

ffmpeg -i input.mp3 -af "volume=1.5" output.mp3

“volume=2” 可以写作 “volume=3.5218dB”(正数)。

备注: -6.0206 是个什么数字?pow(10, -6.0206 / 20) 约等于 0.5。同样的对于 3.5218, pow(10, 3.5218 / 20) 约等于 1.5

四、源码分析

af_volume 源码位于 ffmpg/libavfilter/af_volume.c 中。

分析 filter 一般从 static int filter_frame(AVFilterLink *inlink, AVFrame *in) 函数入手。

如果音量参数是以 dB 为单位,在运算时会转换为比例。

五、C# 简单实现

/// <summary>
/// 按分贝增加音量。支持 S16LE 格式。
/// </summary>
/// <param name="raw"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <param name="dB">正数增加,负数减少</param>
public static void IncreaseDecibel(byte[] raw, int offset, int length, double dB)
{
if (dB == 0) return;

var scaleFactor = Math.Pow(10, dB / 20);
SetVolume(raw, offset, length, scaleFactor);
}

/// <summary>
/// 按比例设置音量。支持 S16LE 格式。
/// </summary>
/// <param name="raw"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <param name="factor">大于1增加音量,小于1减小音量</param>
public static void SetVolume(byte[] raw, int offset, int length, double factor)
{
if (factor == 1) return;

var numberOfSamples = length / sizeof(short);
for (var i = offset; i < numberOfSamples; i++)
{
var temp = (int)(BitConverter.ToInt16(raw, i * sizeof(short)) * factor);
temp = temp > short.MaxValue ? short.MaxValue : temp;
temp = temp < short.MinValue ? short.MinValue : temp;
var bytes = BitConverter.GetBytes((short)temp);
raw[i * sizeof(short)] = bytes[0];
raw[i * sizeof(short) + 1] = bytes[1];
}
}

FFmpeg filters 官网文档: volume
Calculator dB


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK