1.PulseAudio音量模型
2.linux内核源码:网络通信简介——网络拥塞控制之BBR算法
3.c语言编程题打印出所有的“水仙花数”所谓“水仙花数”是指一个三位数其各位数字立方和等于该数本身
PulseAudio音量模型
对于任何一个跟声音相关的软件/硬件,音量无疑都是非常重要的东西。太小听不见,太大有损听力。对数字音频来说大音量时还可能有失真。对车机来说,短线宝超准稳赢 源码大音量机器功率也相应增大,增加电力消耗。所以了解一些音量相关的知识还是很有必要的。
参考文献:
简单说来,人耳对音量的感知是反直觉的。如左下图所示,声音振幅随音量滑块线性变化,此时,人耳对音量的感觉如右下图所示。小音量时,滑块等距变化,听上去音量变化很大;大音量时,滑块等距变化,红狸网源码听上去音量变化反而没那么大。
当声音振幅随音量滑块呈现左下图那样的非线性变化时,人耳对音量的感觉如右下图所示,呈线性变化,比较符合人的直觉。关于声音振幅随音量滑块的非线性变化,PulseAudio采用了一种立方映射模型(cubic mapping)。
PulseAudio里有四种音量,这四种音量是等价的,可以使用volume.h中的api进行相互换算。
volume是PulseAudio里基本的音量表示,属于pa_volume_t类型,相关定义见下面的代码段。
就是2.1中的volume与PA_VOLUME_NORM的百分比。
linear是PulseAudio立方音量模型的体现,linear与volume之间的关系如下:
其中, 为linear, 为volume,扫码 积分 源码 为PA_VOLUME_NORM。
可以理解为通常声学意义上的分贝(dB)。
其中, 为decibel, 为linear, 为volume, 为PA_VOLUME_NORM。
一段PCM格式的数字音频,如果要将音量调大(小),只要把这段音频里的每个数据都调大(小)。实操的话,只要乘以相应的系数就可以了。这个系数就是前文提到的PulseAudio四种音量里的linear。
对于一段音频 ,调整音量后得到 ,则
其中, 为linear, 为volume,ckeditor查看源码换行 为PA_VOLUME_NORM,画成框图的话:
如果一段音频 ,先调整了音量 ,又调整了 ,则最终的 :
用框图表示:
这样子处理当然没有什么问题,但对于同一段音频,经过一个音量调整块需要做 次运算(跟音频格式、时长等有关),经过两个音量调整块的话就需要 次运算。这种情况是可以优化的,只要运用乘法结合律改变一下运算顺序就可以了。这样无论这段音频经过几个音量调块,算法的时间复杂度都是不变的。
可能是出于编码实践方面的考量,对于一段音频先后经过几个音量调整块的情况,PulseAudio里采用了一种等效音量的做法,其目的也是在降低多次音量调整的时间复杂度。
对于一段音频 ,洛克bendan辅助源码先调整了音量 ,又调整了音量 ,得到了最终的 。那么,完全可以想象有一个等效音量 ,使得同样的 ,调整音量 后得到同样的 。
由此可以得出,
进一步,
反映到代码上,
PulseAudio的音量模型到此介绍完毕,关于不同通道、不同位深、有符号/无符号、整型/浮点型、大端/小端等不同音频格式的细致处理,可以去看源码。
最后再说一个mute on的事。从笔者对应DSP驱动的经验来看,mute和volume设定的是同一个寄存器,mute on就是把volume调到最小。但PulseAudio的实现不是这样的。上面讲过,调volume就是对音频数据做乘法。mute on如果也这样实现的话,有点浪费算力了。因为对于给定的音频格式,不用做乘法也知道mute on时对应的数据是啥,直接调用memset()就可以了。但不要想当然的以为是memset(void *s, 0, size_t n),不同格式下对应mute on时的音频数据并不都是0。具体见下面代码段里silent_byte()的实现。
linux内核源码:网络通信简介——网络拥塞控制之BBR算法
从网络诞生至十年前,TCP拥塞控制采用的经典算法如reno、new-reno、bic、cubic等,在低带宽有线网络中运行了几十年。然而,随着网络带宽的增加以及无线网络通信的普及,这些传统算法开始难以适应新的环境。
根本原因是,传统拥塞控制算法将丢包/错包等同于网络拥塞。这一认知上的缺陷导致了算法在面对新环境时的不适应性。BBR算法的出现,旨在解决这一问题。BBR通过以下方式控制拥塞:
1. 确保源端发送数据的速率不超过瓶颈链路的带宽,避免长时间排队造成拥塞。
2. 设定BDP(往返延迟带宽积)的上限,即源端发送的待确认在途数据包(inflight)不超过BDP,换句话说,双向链路中数据包总和不超过RTT(往返延迟)与BtlBW(瓶颈带宽)的乘积。
BBR算法需要两个关键变量:RTT(RTprop:往返传播延迟时间)和BtlBW(瓶颈带宽),并需要精确测量这两个变量的值。
1. RTT的定义为源端从发送数据到收到ACK的耗时,即数据包一来一回的时间总和。在应用受限阶段测量是最合适的。
2. BtlBW的测量则在带宽受限阶段进行,通过多次测量交付速率,将近期的最大交付速率作为BtlBW。测量的时间窗口通常在6-个RTT之间,确保测量结果的准确性。
在上述概念基础上,BBR算法实现了从初始启动、排水、探测带宽到探测RTT的四个阶段,以实现更高效、更稳定的网络通信。
通信双方在节点中,通过发送和接收数据进行交互。BBR算法通过接收ACK包时更新RTT、部分包更新BtlBW,以及发送数据包时判断inflight数据量是否超过BDP,通过一系列动作实现数据的有效传输。
在具体的实现上,BBR算法的源码位于net\ipv4\tcp_bbr.c文件中(以Linux 4.9源码为例)。关键函数包括估算带宽的bbr_update_bw、设置pacing_rate来控制发送速度的bbr_set_pacing_rate以及更新最小的RTT的bbr_update_min_rtt等。
总的来说,BBR算法不再依赖丢包判断,也不采用传统的AIMD线性增乘性减策略维护拥塞窗口。而是通过采样估计网络链路拓扑情况,极大带宽和极小延时,以及使用发送窗口来优化数据传输效率。同时,引入Pacing Rate限制数据发送速率,与cwnd配合使用,有效降低数据冲击。
c语言编程题打印出所有的“水仙花数”所谓“水仙花数”是指一个三位数其各位数字立方和等于该数本身
打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数
本身。例如:是一个“水仙花数”,因为=1的三次方+5的三次方+3的三次方。
1.程序分析:利用for循环控制-个数,每个数分解出个位,十位,百位。
2.程序源代码:
main()
{
int i,j,k,n;
printf("'water flower'number is:");
for(n=;n<;n++)
{
i=n/;/*分解出百位*/
j=n/%;/*分解出十位*/
k=n%;/*分解出个位*/
if(i*+j*+k==i*i*i+j*j*j+k*k*k)
{
printf("%-5d",n);
}
}
printf("\n");
}