基本上,当初罕用的声音采样方法是pcm,而对于压缩音频的解码,失去的也pcm数据。这个pcm数据,只是一堆数值,有正有负,看这个值看不出什么花色。

声音采集,采的是什么呢?

采的是声音的强度变动,也是声音这种能量的强弱变动,这种强弱用分贝来示意,即dB。所以,pcm数据跟这个dB就肯定有关系,这个关系是这样的:

dB=20∗log10(pcm)pcm=pow(10,(dB/20.0))

模数转换ADC时罕用的位深是16bit,也就是用16位来示意一个sample,这里不思考偷懒而应用有余16位的状况。16位能示意65536个值,也就意味着有65536个dB能够示意进去,哪又怎么样?很厉害了吗?

确实是比拟厉害的了。

16位的pcm数值,分正负,那负数的范畴是0至32767,正数的范畴是-1至-32768,轻易挑几个来看看,对应的dB是多少,如下图:

由下面的运算可知,16位的pcm值,如果不分正负,最大能够示意96dB,如果分正负,也能示意到90dB。90dB是什么概念?有数据表明(我也不分明什么数据),85dB就会挫伤了你,90dB相当于摩托车启动的声音--你有开过吗?

所以,你的pcm数据须要去到90dB以上吗?想祸患谁?个别状况下,能示意到90dB就很够用了。

既然晓得了pcm数值与dB的关系,就能够搞点事件了,比方把pcm转成dB后再放大一点,再保留成新的文件,是不是播放就能够大声一点了呢?

来做个试验。

import mathimport mathimport waveimport audioreadimport contextlibimport sysimport mathimport structdef 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就不要乘那么大的数啊--另一个方法:给它限幅(压幅),或者间接应用更适合的整体技术(灵便变音量跟限幅都思考进去了)比方agc或drc等,显著这个不是这里的内容。

好了,总结一下,本文演示了扭转音量的一种最原始的方法,就是间接改pcm的值(转dB再扭转,其实也能够间接扭转pcm值),但这不是最好的方法,因为它会引入失真的副作用。而从pcm数据中提取出能量(dB),这个也更像是音频特色的技能。有缘再见,see you。