美文网首页音频
PCM分析及音量控制

PCM分析及音量控制

作者: 泥孩儿0107 | 来源:发表于2018-04-11 18:53 被阅读0次

    一.声音的相关概念

    声音是介质振动在听觉系统中产生的反应。声音总可以被分解为不同频率不同强度正弦波的叠加(傅里叶变换)。

    声音有两个基本的物理属性:频率振幅。声音的振幅就是音量,频率的高低就是指音调,频率用赫兹(Hz)作单位。人耳只能听到20Hz到20khz范围的声音。

    模拟音频(Analogous Audio),用连续的电流或电压表示的音频信号,在时间和振幅上是连续。在过去记录声音记录的都是模拟音频,比如机械录音(以留声机、机械唱片为代表)、光学录音(以电影胶片为代表)、磁性录音(以磁带录音为代表)等模拟录音方式。

    数字音频(Digital Audio),通过采样和量化技术获得的离散性(数字化)音频数据。计算机内部处理的是二进制数据,处理的都是数字音频,所以需要将模拟音频通过采样、量化转换成有限个数字表示的离散序列(即实现音频数字化)。

    采样频率(Sampling Rate),单位时间内采集的样本数,是采样周期的倒数,指两个采样之间的时间间隔。采样频率必须至少是信号中最大频率分量频率的两倍,否则就不能从信号采样中恢复原始信号,这其实就是著名的香农采样定理。CD音质采样率为 44.1 kHz,其他常用采样率:22.05KHz,11.025KHz,一般网络和移动通信的音频采样率:8KHz。

    量化深度,表示一个样本的二进制的位数,即样本的比特数。量化是将经过采样得到的离散数据转换成二进制数的过程,量化深度表示每个采样点用多少比特表示,在计算机中音频的量化深度一般为4、8、16、32位(bit)等。例如:量化深度为8bit时,每个采样点可以表示256个不同的量化值,而量化深度为16bit时,每个采样点可以表示65536个不同的量化值。量化深度的大小影响到声音的质量,显然,位数越多,量化后的波形越接近原始波形,声音的质量越高,而需要的存储空间也越多;位数越少,声音的质量越低,需要的存储空间越少。CD音质采用的是16 bits,移动通信 8bits。

    声道数,记录声音时,如果每次生成一个声波数据,称为单声道;每次生成两个声波数据,称为双声道。使用双声道记录声音,能够在一定程度上再现声音的方位,反映人耳的听觉特性。

    数字音频存储大小。采样频率、量化深度数越高,声音质量也越高,保存这段声音所用的空间也就越大。立体声(双声道)存储大小是单声道文件的两倍。即:文件大小(B)=采样频率(Hz)×录音时间(S)×(量化深度/8)×声道数(单声道为1,立体声为2)

    如:录制1分钟采样频率为44.1KHz,量化深度为16位,立体声的声音(CD音质),文件大小为:

    44.1×1000×60×(16/8)×2=10584000B≈10.09M

    二.PCM 

    音频编码,指将模拟音频转换成数字音频并以某种格式存储的技术或过程。

    PCM(Pulse Code Modulation)编码,即通过脉冲编码调制方法生成数字音频数据的技术或格式,是一种无损编码格式,是音频模拟信号数字化的一种方法,需要经过采样、量化和编码过程,以实现音频模拟信号数字化。

    首先从6个方面描述PCM:

    1)采样率;

    2)符号:表示样本数据是否是有符号位,比如用一字节表示的样本数据,有符号的话表示范围为-128~127,无符号就是0~255,;

    3)字节序:字节序分为大端与小端;

    4)样本大小:决定了每个样本由多少位组成,即前面说到的量化深度,一般16位是最常见的;

    5)声道数:分为单声道与双声道。

    6)整形或浮点型:大多数格式的PCM样本数据使用整形表示,然而在一些对精度要求高的应用方面,使用浮点类型表示PCM样本数据。

    打开ffmpeg,敲:ffmpeg -formats命令,获取ffmpeg支持的音视频格式,在这当中我们可以找到支持的PCM格式

    DE f32be           PCM 32-bit floating-point big-endian

    DE f32le           PCM 32-bit floating-point little-endian

    DE f64be           PCM 64-bit floating-point big-endian

    DE f64le           PCM 64-bit floating-point little-endian

    DE mulaw           PCM mu-law

    DE s16be           PCM signed 16-bit big-endian

    DE s16le           PCM signed 16-bit little-endian

    DE s24be           PCM signed 24-bit big-endian

    DE s24le           PCM signed 24-bit little-endian

    DE s32be           PCM signed 32-bit big-endian

    DE s32le           PCM signed 32-bit little-endian

    DE s8              PCM signed 8-bit

    DE u16be           PCM unsigned 16-bit big-endian

    DE u16le           PCM unsigned 16-bit little-endian

    DE u24be           PCM unsigned 24-bit big-endian

    DE u24le           PCM unsigned 24-bit little-endian

    DE u32be           PCM unsigned 32-bit big-endian

    DE u32le           PCM unsigned 32-bit little-endian

    DE u8              PCM unsigned 8-bit

    比如DE s16be,就表示一个样本用16bits有符号的整形数据表示,字节序为大端。

    假设我们有一个PCM signed 16-bit little-endian,双声道的PCM文件。如下是文件中前9个样本:

    +------+------+------+------+------+------+------+------+------+

    |  500|  300|-100|-20  |-300|  900|-200|  -50|  250|

    +------+------+------+------+------+------+------+------+------+

    每个样本2字节,总共18字节,每个样本取值范围:-32768 ~ 32767。

    三.PCM音量控制 

    通过前面描述我们对PCM有了个了解,知道了在PCM流中数据如何存储。下面我们先看一个真正的音频样本波形:

    如果我们放大5倍波形,也就是振幅乘以5,此时我们听到了更大的声音,此时样本波形如下:

    假如我们有2048bytesPCM数据,样本大小两个字节,共有1024个样本,我们要放大两倍声音,代码可以按如下写:

    int16_t pcm[1024] = read in some pcm data;

    for (ctr = 0; ctr < 1024; ctr++) {

        pcm[ctr] *= 2;

    }

    这是不是很简单,但是接下来我们还需要考虑两个方面的问题。

    数据溢出 

    因为每个样本取值范围是有限制的,调节音量时不可能随便增大,比如一个signed 16 bits的样本,值为5000,我们放大10倍,由于有符号位16bits数据取值范围为-32768~32767,5000乘以10得到的50000超过了32767,数据溢出了,最后值可能变为-15536,不是我们期望的。此时我们就需要裁剪了,确保数值在正确范围内。如下代码对前面说到的放大两倍声音做了裁剪处理:

    int16_tpcm[1024]=readinsomepcmdata;

    int32_tpcmval;

    for(ctr=0;ctr<1024;ctr++){

        pcmval=pcm[ctr]*2;

        if(pcmval<32767&&pcmval>-32768){

            pcm[ctr]=pcmval

        }elseif(pcmval>32767){

            pcm[ctr]=32767;

        }elseif(pcmval<-32768){

            pcm[ctr]=-32768;

        }

    }

    对数描述 

    平时表示声音强度我们都是用分贝(db)作单位的,声学领域中,分贝的定义是声源功率与基准声功率比值的对数乘以10的数值。根据人耳的心理声学模型,人耳对声音感知程度是对数关系,而不是线性关系。人类的听觉反应是基于声音的相对变化而非绝对的变化。对数标度正好能模仿人类耳朵对声音的反应。所以用分贝作单位描述声音强度更符合人类对声音强度的感知。前面我们直接将声音乘以某个值,也就是线性调节,调节音量时会感觉到刚开始音量变化很快,后面调的话好像都没啥变化,使用对数关系调节音量的话声音听起来就会均匀增大。

    如下图,横轴表示音量调节滑块,纵坐标表示人耳感知到的音量,图中取了两块横轴变化相同的区域,音量滑块滑动变化一样,

    但是人耳感觉到的音量变化是不一样的,在左侧也就是较安静的地方,感觉到音量变化大,在右侧声音较大区域人耳感觉到的音量变化较小。

    下面我们讲下音量值乘数取值,这里我只简单的用tan函数模拟,效果也不错,至于使用对数如何调整请参考文末链接:

    int some_level;

    float multiplier = tan (some_level / 100.0 );

    上面代码中音量乘数取值为tan (some_level / 100.0 ),最后实现代码如下:

    int16_tpcm[1024]=readinsomepcmdata;

    int32_tpcmval;

    uint8_tlevel=certainvalue;

    floatmultiplier=tan(level/100.0);

    for(ctr=0;ctr<1024;ctr++){

        pcmval=pcm[ctr]*multiplier;

        if(pcmval<32767&&pcmval>-32768){

            pcm[ctr]=pcmval

        }elseif(pcmval>32767){

            pcm[ctr]=32767;

        }elseif(pcmval<-32768){

            pcm[ctr]=-32768;

        }

    }

    其中level取值需要具体测试实现,一般使用时level取值为某个范围的几个数,比如取10个数,这样音量就有10个阶跃可以调节。

    如下图,最后声音音量近似按对数关系增长了:

    如果想了解利用对数关系调节音量的具体实现,请参考下一篇文章。

    相关文章

      网友评论

        本文标题:PCM分析及音量控制

        本文链接:https://www.haomeiwen.com/subject/yjvzhftx.html