FFmpeg源码分析:音频滤镜介绍(下)
FFmpeg在libavfilter模塊提供音視頻濾鏡。所有的音頻濾鏡都注冊在libavfilter/allfilters.c。我們也可以使用ffmpeg -filters命令行來查看當前支持的所有濾鏡,前面-a代表音頻。本篇文章主要介紹音頻濾鏡,包括:混音、靜音填充、哈斯效應、合唱效果、均衡器、iir與fir濾波器、低通濾波器、帶通濾波器、高通濾波器、變速變調、音量調節、靜音檢測。
關于音頻濾鏡的詳細介紹,可查看官方文檔:音頻濾鏡。上半部分的音頻濾鏡,可查看:音頻濾鏡介紹(上)。
1、amerge
合并,把兩個或多個音頻流合并到一個多通道的輸出流。假如輸入聲道布局是交錯的,那么輸出聲道布局相應地設置,聲道根據需要進行重新排序。相反,假如輸入聲道布局不是交錯的,那么先是第一個輸入流的所有聲道,然后是第二個輸入流,依次類推。
比如合并兩個音頻流,參考命令如下:
ffmpeg -i one.mp3 -i two.mp3 -filter_complex [0:a][1:a]amerge=inputs=2[aout] -map [aout] out.mp32、amix
混音,把所有輸入音頻流混合成單個音頻流。該濾鏡僅支持浮點采樣格式。如果是整型采樣格式,會自動轉換成浮點采樣格式。參數選項如下:
- inputs:輸入音頻數,默認為2
- duration:混音后的音頻時長
- ? ? ?longest:使用最長的輸入流時長(默認)
- ? ? ?shortest:使用最短的輸入流時長
- ? ? ?first:使用第一個輸入流時長
- dropout_transition:過渡時間,默認為2秒
- weights:每個音頻流的占比權重,默認所有音頻流權重相同
- normalize:是否開啟歸一化,默認開啟
混音代碼位于libavfilter/af_amix.c,核心代碼如下:
// 從FIFO隊列讀取若干采樣數據,然后混音,寫到輸出緩沖區 static int output_frame(AVFilterLink *outlink) {AVFilterContext *ctx = outlink->src;MixContext *s = ctx->priv;AVFrame *out_buf, *in_buf;int nb_samples, ns, i;if (s->input_state[0] & INPUT_ON) {nb_samples = frame_list_next_frame_size(s->frame_list);for (i = 1; i < s->nb_inputs; i++) {if (s->input_state[i] & INPUT_ON) {ns = av_audio_fifo_size(s->fifos[i]);if (ns < nb_samples) {if (!(s->input_state[i] & INPUT_EOF))return 0;nb_samples = ns;}}}s->next_pts = frame_list_next_pts(s->frame_list);} else {nb_samples = INT_MAX;for (i = 1; i < s->nb_inputs; i++) {if (s->input_state[i] & INPUT_ON) {ns = av_audio_fifo_size(s->fifos[i]);nb_samples = FFMIN(nb_samples, ns);}}if (nb_samples == INT_MAX) {ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);return 0;}}frame_list_remove_samples(s->frame_list, nb_samples);calculate_scales(s, nb_samples);if (nb_samples == 0)return 0;out_buf = ff_get_audio_buffer(outlink, nb_samples);if (!out_buf)return AVERROR(ENOMEM);in_buf = ff_get_audio_buffer(outlink, nb_samples);if (!in_buf) {av_frame_free(&out_buf);return AVERROR(ENOMEM);}for (i = 0; i < s->nb_inputs; i++) {if (s->input_state[i] & INPUT_ON) {int planes, plane_size, p;// 從FIFO隊列讀取采樣數據av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data,nb_samples);planes = s->planar ? s->nb_channels : 1;plane_size = nb_samples * (s->planar ? 1 : s->nb_channels);plane_size = FFALIGN(plane_size, 16);// 開始混音,判斷是float類型還是double類型if (out_buf->format == AV_SAMPLE_FMT_FLT ||out_buf->format == AV_SAMPLE_FMT_FLTP) {for (p = 0; p < planes; p++) {s->fdsp->vector_fmac_scalar((float *)out_buf->extended_data[p],(float *) in_buf->extended_data[p],s->input_scale[i], plane_size);}} else {for (p = 0; p < planes; p++) {s->fdsp->vector_dmac_scalar((double *)out_buf->extended_data[p],(double *) in_buf->extended_data[p],s->input_scale[i], plane_size);}}}}av_frame_free(&in_buf);out_buf->pts = s->next_pts;if (s->next_pts != AV_NOPTS_VALUE)s->next_pts += nb_samples;return ff_filter_frame(outlink, out_buf); }?混音時,如果是浮點數據調用vector_fmac_scalar函數指針,來自libavutil/float_dsp.h的AVFloatDSPContext結構體一個成員變量。將源數據乘以標量,然后相加到目標矢量:
/*** Multiply a vector of floats by a scalar float and add to* destination vector. Source and destination vectors must* overlap exactly or not at all.** @param dst result vector* constraints: 32-byte aligned* @param src input vector* constraints: 32-byte aligned* @param mul scalar value* @param len length of vector* constraints: multiple of 16*/void (*vector_fmac_scalar)(float *dst, const float *src, float mul, int len);在float_dsp.c源代碼中,avpriv_float_dsp_alloc()對函數指針進行賦值:
av_cold AVFloatDSPContext *avpriv_float_dsp_alloc(int bit_exact) {AVFloatDSPContext *fdsp = av_mallocz(sizeof(AVFloatDSPContext));if (!fdsp)return NULL;fdsp->vector_fmac_scalar = vector_fmac_scalar_c;fdsp->vector_fmul_scalar = vector_fmul_scalar_c;return fdsp; }?讓我們看看vector_fmac_scalar_c()方法的實現:
static void vector_fmac_scalar_c(float *dst, const float *src, float mul,int len) {int i;for (i = 0; i < len; i++)dst[i] += src[i] * mul; }3、apad
填充,將音頻流結尾填充為靜音。參數選項如下:
- packet_size:靜音數據包大小,默認為4096
- pad_len:填充為靜音的采樣數
- whole_len:指定最少的輸出采樣數
- pad_dur:指定填充時長
- whole_dur:指定最小的輸出時長
4、atempo
變速,調節音頻播放速度。只接受一個參數atempo,取值范圍[0.5, 100.0],默認為1.0。需要注意的是,如果atempo大于2,將會跳過一些采樣數據。
音頻改為2倍速,參考命令如下:
ffmpeg -i in.mp3 -filter_complex atempo=2.0 out.mp35、chorus
合唱,添加合唱效果到音頻流。合唱類似于具有短延遲的回聲效果,但回聲的延遲是恒定的,而合唱則使用正弦波或三角形波調制來改變延遲。因此,延遲的聲音聽起來會更慢或更快,即延遲的聲音會圍繞原始聲音進行調諧。參數選項如下:
- in_gain:輸入增益,默認為0.4
- out_gain:輸出增益,默認為0.4
- delays:延遲時間,一般為40ms到60ms
- decays:衰減系數
- speeds:設置速度
- depths:設置深度
6、haas
哈斯,應用哈斯效應到音效中。需要注意的是,這主要作用于單聲道信號。將此濾波器應用單聲道信號時,會提供方向感,并且轉換為立體聲。參數選項如下:
- level_in:輸入等級,默認為1
- level_out:輸出等級,默認為1
- side_gain:側邊增益,默認為1
- middle_source:中間聲源類型,包括以下參數:
- ? ? ‘left’:選擇左聲道
- ? ? ‘right’:選擇右聲道
- ? ? ‘mid’:中間立體聲道
- ? ? ‘side’:側邊立體聲道
- middle_phase:是否改變中間相位,默認關閉
- left_delay:左聲道延遲,默認為2.05 ms
- left_balance:左聲道均衡,默認為-1
- left_gain:左聲道增益,默認為1
- left_phase:改變左相位,默認關閉
- right_delay:右聲道延遲,默認為2.12?ms
- right_balance:右聲道均衡,默認為1
- right_gain:右聲道增益,默認為1
- right_phase:改變右聲道相位,默認開啟
7、silencedetect
靜音檢測,檢測音頻流的靜音部分。當該過濾器檢測到輸入音頻音量小于或等于噪聲容限值,且持續時間大于或等于檢測到的最小噪聲持續時間時,認定為靜音。參數選項如下:
- noise, n:噪聲容忍值,單位為dB,?默認為-60dB
- duration, d:設置靜音時長,默認為2s
- mono, m:獨立處理每個聲道,默認關閉
檢測靜音的參考命令如下:
ffmpeg -i hello.mp3 -af silencedetect=noise=0.0001 -f null -輸出結果以silence_start開始,silence_end結束,silence_duraition為靜音時長:
[silencedetect @ 0000020c67936fc0] silence_start: 268.82 [silencedetect @ 0000020c67936fc0] silence_end: 271.048 | silence_duration: 2.22796總結
以上是生活随笔為你收集整理的FFmpeg源码分析:音频滤镜介绍(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RDKit | RDKit中处理分子Mo
- 下一篇: TRICP点云配准