zoukankan      html  css  js  c++  java
  • 多媒体开发(5)&音频特征:声音可以调大一点吗?

    基本上,现在常用的声音采样办法是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是多少,如下图:
    pcm对应的dB

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

    所以,你的pcm数据需要去到90dB以上吗?想祸害谁?一般情况下,能表示到90dB就很够用了。

    既然知道了pcm数值与dB的关系,就可以搞点事情了,比如把pcm转成dB后再放大一点,再保存成新的文件,是不是播放就可以大声一点了呢?

    来做个实验。

    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。

  • 相关阅读:
    使用youtube-dl下载B站视频
    【北邮人论坛帖子备份】14 考公与考研、入党、秋招
    观《菊次郎的夏天》有感
    git远端分支改名并以当前分支为base新建分支
    依赖明明存在pom.xml却报Dependency 'groupId:artifactId:version' not found的错
    在服务器上搭建git服务
    【北邮人论坛帖子备份】【秋招】21届渣硕BAT后端研发上岸心得
    【北邮人论坛帖子备份】【心得】做科研写论文的一些小经验
    【北邮人论坛帖子备份】 图森同学 | Gala:一个北邮非典型学霸的成长之路
    Python-for循环
  • 原文地址:https://www.cnblogs.com/freeself/p/14267036.html
Copyright © 2011-2022 走看看