多媒體開發(5)&音頻特徵:聲音能夠調大一點嗎?

基本上,如今經常使用的聲音採樣辦法是pcm,而對於壓縮音頻的解碼,獲得的也pcm數據。這個pcm數據,只是一堆數值,有正有負,看這個值看不出什麼花樣。code

聲音採集,採的是什麼呢?blog

採的是聲音的強度變化,也是聲音這種能量的強弱變化,這種強弱用分貝來表示,即dB。因此,pcm數據跟這個dB就必定有關係,這個關係是這樣的:
dB=20∗log10(pcm)
pcm=pow(10,(dB/20.0))it

模數轉換ADC時經常使用的位深是16bit,也就是用16位來表示一個sample,這裏不考慮偷懶而使用不足16位的狀況。16位能表示65536個值,也就意味着有65536個dB能夠表示出來,哪又怎麼樣?很厲害了嗎?io

的確是比較厲害的了。test

16位的pcm數值,分正負,那正數的範圍是0至32767,負數的範圍是-1至-32768,隨便挑幾個來看看,對應的dB是多少,以下圖:
pcm對應的dBimport

由上面的運算可知,16位的pcm值,若是不分正負,最大能夠表示96dB,若是分正負,也能表示到90dB。90dB是什麼概念?有數據代表(我也不清楚什麼數據),85dB就會傷害了你,90dB至關於摩托車啓動的聲音--你有開過嗎?音頻

因此,你的pcm數據須要去到90dB以上嗎?想禍害誰?通常狀況下,能表示到90dB就很夠用了。file

既然知道了pcm數值與dB的關係,就能夠搞點事情了,好比把pcm轉成dB後再放大一點,再保存成新的文件,是否是播放就能夠大聲一點了呢?channel

來作個實驗。float

import math
import math
import wave
import audioread
import contextlib
import sys
import math
import struct

def gainpcm(filepath):
    try:
        with audioread.audio_open(filepath) as f:
            with contextlib.closing(wave.open(filepath+'.wav', 'w')) as of:
                of.setnchannels(f.channels)
                of.setframerate(f.samplerate)
                of.setsampwidth(2)
                for buf in f:
                    for i in range(0, len(buf)-2, 2):
                        s = buf[i] + buf[i+1]
                        pcm = struct.unpack('<h', s)[0]
                        apcm = abs(pcm)
                        if apcm==0:
                            apcm=1
                        db = 20*math.log10(apcm)
                        db = db * 1.2
                        apcm=int(math.pow(10, float(db)/20.0))
                        if apcm>32767:
                            apcm=32767
                        if pcm < 0:
                            pcm=-apcm
                        else:
                            pcm = apcm
                        tbuf = struct.pack('<h', pcm)
                        of.writeframes(tbuf)

    except audioread.DecodeError:
        print("File could not be decoded.")
        sys.exit(1)

if __name__ == '__main__':
    gainpcm('test.mp3')

這裏是對代碼的簡單解釋:
代碼解釋

把一個mp3放過去試驗,出來一個wav,發現wav文件的聲音真的大了好多(好可能是由於這裏設置了db*1.2)。可是,另外一個問題也暴露出來了,就是聽起來聲音失真很嚴重了,這是由於放大到這個程度,不少apcm都超過了32767,也就是人們說的截頂失真了,看一下原文件與放大後的文件波形圖就更清楚了:
原文件波形

改變db文件波形

因爲不能上傳音頻,這裏就不提供直接的音頻對比了。

因而可知,要想不失真,那db就不要乘那麼大的數啊--另外一個辦法:給它限幅(壓幅),或者直接使用更合適的總體技術(靈活變音量跟限幅都考慮進去了)好比agc或drc等,明顯這個不是這裏的內容。

好了,總結一下,本文演示了改變音量的一種最原始的辦法,就是直接改pcm的值(轉dB再改變,其實也能夠直接改變pcm值),但這不是最好的辦法,由於它會引入失真的反作用。而從pcm數據中提取出能量(dB),這個也更像是音頻特徵的技能。有緣再見,see you。

相關文章
相關標籤/搜索