音頻淡入淡出效果——解決音頻突變的爆音問題

使用軟件調節音量時如果音量之間的步進太大,聲音突變,就能聽到明顯的爆音,尤其以單音音頻更爲明顯,類似的問題還在聲音起播、暫停、結束、快進快退時經常會出現,這個時候一般需要對音頻進行漸入漸出的效果處理。

先來看一個典型的爆音音頻示例,播放一個1k hz的正玄波,並調節音量,可以看到波形幅度增大

由於幅度跳變太大,過渡不連續,造成爆音,從頻譜圖來看這條豎直的亮線處,就是產生爆音的位置

爲解決這個問題,就需要引入漸入漸出處理了,聲音由大變小時需要做漸出處理,由小變大時需要做漸入處理

所謂漸入漸出處理就是需要一個平滑的過渡,比如從0到1,可以在中間插幾個點,平緩的過渡到1,插多少點和每個點的值帶來的效果也不一樣。這種處理也應用在各種動畫過渡場景中,原理相通。

動畫效果中經常用到的緩動公式,有興趣的同學可以深入研究一下其中的數學原理,有幾個相關的資料網頁:

http://www.timotheegroleau.com/Flash/experiments/easing_function_generator.htm

這個網頁十分強大,可以手動設計緩動效果並生成對應的函數接口

http://blog.moagrius.com/actionscript/jsas-understanding-easing/

這個網頁詳細解釋了函數公式的意義:

These functions are usually written with 4 arguments [2]:


function noEasing (t, b, c, d) {
	return c * t / d + b;
}
@t is the current time (or position) of the tween. This can be seconds or frames, steps, seconds, ms, whatever – as long as the unit is the same as is used for the total time [3].
@b is the beginning value of the property.
@c is the change between the beginning and destination value of the property.
@d is the total time of the tween.

這裏的解釋是針對動畫效果而言,翻譯成音頻來說,我們的音量假設從0增大到1.0

b就代表起始音量0,c表示目標音量到起始音量的差即1.0

d意味着需要對多少樣本做處理,一般我們會以時間來計算,比如我要200ms內的音頻數據緩動處理,那麼這麼樣本總值就是:

d = 200*sr(採樣率)/1000  ,因爲左右聲道是同時處理,我們以frame爲單位,48000採樣率,d的大小爲9600

t就是處理的frame計數了,從0到9600增加,返回值就是當前的frame需要的當前音量,參考代碼如下:


vol_delta = target_volume - current_volume;
for (j = 0; j < nframes; j++) {
          if (ease_frames == 0) {
                     current_volume = target_volume;
          } else if (ease_frames_elapsed < ease_frames) {

                        current_volume= floatEaseNext((float)ease_frames_elapsed,
                                                    start_volume, vol_delta, (float)(ease_frames - 1));
                        ease_frames_elapsed++;
                    }
			
                    for (i = 0 ; i < ch; i++) {
                        data[j * ch + i] = data[j * ch + i] * current_volume;
                    }
       }

公式有很多種,每種公式處理的過渡效果不一,這是兩種ease in和ease out的處理公式

EaseInCubic:
floatEaseFunc( float t, float b, float c, float d) {
        t /= d;
        return c * t * t * t + b;
}
EaseOutCubic:
       floatEaseFunc( float t, float b, float c, float d) {
         t = t / d - 1;
        return c * (t * t * t + 1) + b;
}

來看一下實際對音頻突變的處理效果,這是系統在播放1Khz時不斷調整音量時dump的pcm數據

我們從頻譜圖上來看

整段音頻非常乾淨,沒有任何雜音爆破音,處理的相當完美。

據瞭解緩動公式由大神robert penner提出,再次感謝膜拜大神!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章