首页 > > > 10877 「人耳对相位不敏感」到底是什么意思(下)
. 上一篇文章阐释了「人耳对相位不敏感」的一般含义:对乐音的各次谐波分别进行独立的相移,人耳并不会觉察到任何变化。这篇文章就来研究一下,如何以一段真实声音为材料,通过人为修改其频谱的方法,达到「对乐音的各次谐波进行独立相移」的效果,从而证明人耳对相位不敏感。我会逐个讨论这个问题下各个答主的方法能否达到这一目的。
要通过人为修改的办法对一段声音进行相移,我们首先需要一些理论知识,即弄清楚一段调幅、调频信号相移时,它的频谱(包括幅度谱和相位谱)如何变化。
调幅、调频信号的一般表达式为:

为简便起见,定义
,则上述表达式可写为

调幅、调频信号的带宽一般是有限的,其频率范围比信号的瞬时频率范围宽一点儿。以上一篇文章中那个「呜~呜」信号为例,它的瞬时频率变化范围约为 140 ~ 860 Hz。它的幅度谱如下图所示,幅度明显非零的频率范围约为 100 ~ 900 Hz。

调幅、调频信号是一个实信号,所以它的幅度谱是左右对称的。利用欧拉公式,可以把这个信号拆成两个复信号之和:

拆出来的两项,就分别对应着幅度谱中正频率的部分(右侧)和负频率的部分(左侧)。
现在把
的相位推迟
,则其表达式变为:
![y(t) = A(t)\cos[\phi(t) - \Delta\phi] \\](https://image.z.itpub.net/zitpub.net/JPG/2020-06-19/DD7D81B8D54BB8F9CBCB1FDB0CD0657A.jpg)
同样利用欧拉公式,这个信号也可以拆成两个复信号之和:

可以看到,相移的效果是对正、负频率分量分别乘以了
、
两个系数,即保持幅度谱不变,在相位谱的正频率部分减去
,负频率部分加上
。如果取
,那么相移操作就是我们熟悉的希尔伯特变换。
有了上面的理论准备,我们就可以开始讨论实验方法了。
如果能把一段真实声音信号中每个乐音的每个谐波分解出来,就可以利用修改相位谱的办法,独立地对各个谐波进行相移;把相移后的各个谐波再合成到一起播放,听起来与原始信号没有差异,就可以证明人耳对相位不敏感。然而,从真实声音信号中分离出各次谐波本身就是一件很困难的事情,我们只能对真实声音信号的频谱进行整体修改。
最简单的办法,就是在真实声音信号的相位谱上,从正频率部分减去
,往负频率部分加上
。在 Matlab 中,设原始声音信号为 x(假设它的长度为偶数),则上述操作可以如下进行:
X = fft(x); % 求原始信号的频谱
Y = X;
Y(2:end/2) = Y(2:end/2) .* exp(-1i * delta_phi); % 正频率相位减去 delta_phi
Y(end/2+2:end) = Y(end/2+2:end) .* exp(1i * delta_phi); % 负频率相位加上 delta_phi
y = real(ifft(Y)); % 合成新信号播放 x 与 y,听起来应该是一模一样的。
有的答主提到把整个声音信号反相,即令 y = -x。这相当于取
的特例。
对信号的相位谱进行整体修改,总感觉丧失了一些自由度:本来各次谐波是可以进行不等量的相移的嘛。为了近似达到这一效果,我们想到:可以对不同频段进行不等量的相移。例如,对 600 Hz 以下的频率,相位推迟
;对 600 Hz 以上的频率,相位提前
。
这个办法基本可以奏效,但是有一点美中不足:如果你的原始信号恰恰在临界频率处有比较强的能量,那么这些能量会被弥散到整个时间轴上去。「呜~呜」信号恰好在 600 Hz 处有比较强的能量。下面的视频演示了分段相移的效果,视频画面显示的是原始信号和修改后的信号的语谱图,你会看到以及听到修改后的信号中有一个幽灵般的 600 Hz 单音贯穿始终。
https:// 这种副作用的产生,跟「群延时」有关。如果某个频率
附近的相移
不是常数,那么这些相移会造成频率在
周围的信号发生整体的延时,具体的延时量为
。在对频谱进行分段相移时,临界频率处的相移有突变,这就造成了临界频率周围的信号产生剧烈的群延时,听起来就是这一频率的信号弥散到了整个时间轴上去。
能不能既实现不同频段进行不等量相移的效果,又避免相移的突变造成的剧烈群延时呢?我的答案中使用的「全通滤波器」法,就恰恰达到了这个目的。
全通滤波器的幅度响应为常数,这是通过在关于单位圆反演对称的位置设置零极点对来实现的。为了保证滤波器稳定,极点必须都在单位圆内;对于每一个极点
,都会相应地设置一个零点
。为了保证滤波器系数为实数,零极点必须都成共轭对,所以对于上述的零极点,还会设置另外一对零极点
和
。由
组成的二阶滤波器,就可以认为是全通滤波器的组成单元;高阶的全通滤波器由许多这样的二阶滤波器级联而成。
全通滤波器既然幅度响应为常数,那么自然地相位响应就值得关注了。上述二阶全通滤波器单元的相位响应
如下图 (a) 所示,这里
代表归一化角频率,参数取
,
。它是一条单调递减的曲线,起点为
,终点为
。曲线的斜率呈现「缓—陡—缓」的变化趋势,其中较陡的一段,横坐标在零极点的辐角
附近;陡峭的程度由极点的模
控制,
越大越陡。

群延时理论告诉我们,这样的全通滤波器单元会在归一化角频率
附近造成较大的群延时;而在归一化角频率远离
的左右两段,群延时比较小,相移是主要的效果。下面我们计算一下,扣除群延时效果后,全通滤波器单元造成的净相移有多大。当相位响应为
时,归一化角频率
处的群延时为
(单位为采样点个数)。而单纯地把整个信号向后平移
,在归一化角频率
处产生的相移是
。于是,全通滤波器单元的净相移就是:
![\begin{align} \Delta\phi_\text{net}(\omega) &= \Delta\phi(\omega) - [-\omega \cdot \tau_g(\omega)] \\ &= \Delta\phi(\omega) - \omega \cdot \frac{\text{d}\Delta\phi(\omega)}{\text{d}\omega} \\ \end{align} \\](https://image.z.itpub.net/zitpub.net/JPG/2020-06-19/739F18F5D2BCE3F2491E7A425A0DA5DE.jpg)
上面的图 (c) 画出了全通滤波器单元的净相移。可以看到,在低频处净相移接近 0,在高频处净相移虽然接近
但仍有距离,这就达到了「分频段相移」的目的。而在归一化角频率
附近有变换比较剧烈的净相移,这其实也是我们想要的效果 —— 在不同的频率处进行不等量的相移。
那么全通滤波器单元的副作用「群延时」有多大呢?上面的图 (b) 画出了各频率处的群延时的大小,纵轴的单位为采样点的个数,把它除以采样频率就可以得到以「秒」为单位的延时量。若取采样频率为 8000 Hz,则临界频率附近的最大群延时(19 个采样点)约为 2.4 毫秒,这点儿群延时是可以接受的。
我在设计这个实验的当时,出发点是设计一个比较「崎岖」的相位响应。为此,我把所有极点的模
都选在了 0.9 到 0.99 之间。现在想来,其实没必要把
选得这么大。当
很接近 1 时,临界频率附近就会体现出比较明显的群延时,这是我们不想要的。另外,当
很接近 1 时,低频和高频处的净相移之差就会很接近
,而
的相位差跟 0 是一回事,于是反倒达不到「分频段相移」的目的。当然,
小了之后,净相移就会变成「渐变」而不是「分段」的,不过这没有关系,我们的初衷就是让不同频率处的净相移不同嘛。
我在实验中使用的是 20 阶全通滤波器,即 10 个二阶全通滤波器单元级联。滤波器的阶数可以继续增加,但有两个问题:一是 Matlab 中的 poly 函数无法计算特别高阶的滤波器的系数。比如,如果你直接计算一个 100 阶全通滤波器的系数,可能会导致数值不稳定;你需要分别生成五个 20 阶全通滤波器,依次对信号进行滤波。二是高阶全通滤波器的群延时也会比较大。我们看到了不同频段的群延时会有不同,如果各频段的群延时之间的差距达到了几十毫秒的数量级,就会破坏谐波之间「时间重合」的关系,人就会开始听到回声的效果了,这也是我们希望避免的副作用。
下面的视频包含了三段声音,第一段是原始语音「电灯比油灯进步多了」,第二段是经 20 阶全通滤波器滤波后的结果,第三段是经 1000 阶全通滤波器滤波后的结果。极点的模仍按我的原始实验,都取在 0.9 到 0.99 之间。从语谱图上能看出 20 阶全通滤波器已经有了微小的群延时,但尚未影响听觉效果;1000 阶全通滤波器的群延时已经非常明显了,并且因为各频段的群延时不同,回声效果比较严重。
https://. @Bimos 做的实验很有意思:他把一段声音 x 的幅度谱和另一段声音 y 的相位谱放在一起,发现合成出来的声音听起来像是带有噪音的 y,从而说明声音的信息主要蕴藏在相位谱中。例如,下面一段视频就依次播放了三段声音:
这跟「人耳对相位不敏感」是否矛盾呢?
https:// 原来,把 x 的相位谱换成 y 的相位谱,其效果是让 x 的相位谱上的每一个点都发生了剧烈而混乱的变化。这种变化会造成 x 的所有频段都发生剧烈的群延时,从而面目全非。下面的视频,演示了把第一段声音(电灯比油灯进步多了)的相位谱替换成在
上均匀分布的随机值造成的效果。可以发现,原声音的所有频段都发生了随机、大幅的群延时,导致内容已经完全听不出来了,新的信号只是幅度谱与原信号相同的噪声。
https://而把 x 的相位谱换成 y 的相位谱,其效果则是让各频段在群延时之后恰好排成类似 y 信号的语谱图的样子,从而听起来更像 y。
从另一个角度看,「x 的幅度谱与 y 的相位谱合成」,也可以看成是对 y 的幅度谱进行了修改,即把 y 通过了一个没有任何延时(包括相移和群延时)的滤波器。这样一个滤波器只是对 y 的各个频段进行了加强或减弱,所以并不会大幅影响其内容,只是让音质变差了。
从 @Bimos 的实验中,可以得出「声音的信息主要蕴藏在相位谱中」的结论。但这并不能说明「人耳对相位敏感」,因为「交换相位谱」这一操作,并不是对声音信号中乐音的各次谐波进行了相移,而是进行了剧烈而混乱的群延时,它破坏了谐波之间「时间重合」的关系,甚至将频率稍有变化的谐波完全撕裂。
上面的所有实验,修改的对象都是一段声音整体做傅里叶变换后得到的相位谱,即长时相位谱。然而,在分析修改的效果的时候,我们却多次观察了声音的语谱图,即对声音逐帧进行短时傅里叶变换后得到的幅度谱。事实上,人耳对声音信号的处理方式正是短时傅里叶变换,人们认为多个谐波组成了同一个乐音,正是因为这些谐波在短时傅里叶的幅度谱上呈现出「时间重合、频率成整数倍」的关系。 @Bimos 得到的结论「声音的信息主要蕴藏在(长时)相位谱中」固然正确,但信息具体是怎么蕴藏的,则很难解释,不如说「声音的信息主要蕴藏在短时幅度谱中」来得直接。
那么短时相位谱呢?如果说短时相位谱不重要,是否可以通过胡乱修改声音的短时相位谱的方式,来证明「人耳对相位不敏感」呢?
我在做大四毕业设计课题(歌声与伴奏的分离)时,曾经使用如下步骤获得一段声音的短时幅度谱和相位谱,进行修改后再反过来合成声音:
个采样点,相邻两帧重叠
个采样点;
点傅里叶变换,得到幅度谱和相位谱;
点逆傅里叶变换,得到长度为
的一帧信号;
个采样点),得到合成声音。可以验证,只要分析窗与合成窗相乘的结果是汉宁窗,如果在第 4 步不进行任何修改,合成出的声音就会与原始声音完全相同。实际中,我是在第 2、6 步中都施加正弦窗(正弦窗的平方就是汉宁窗);其实也可以在第 2 步中不加窗(相当于加矩形窗),并在第 6 步中加汉宁窗。
上面的步骤,就提供了一种「胡乱修改声音的短时相位谱」的方法。比如,对于「电灯比油灯进步多了」这段声音,我们可以在第 4 步将它的短时相位谱改成全零,或者改成随机值,或者干脆换成「三个火枪手」的相位谱。下面的视频演示了原始声音和三种修改的效果,声音的采样率为 8000 Hz,帧长为 320 个采样点,即 40 毫秒。
https://我们发现,修改短时相位谱后,声音都「抖」了起来,而不是像预想的那样毫无变化,似乎不能用「修改短时相位谱」的方法证明「人耳对相位不敏感」。这是为什么呢?
原来,胡乱修改每一帧声音的相位谱,同样会造成这一帧声音各频段产生剧烈、混乱的群延时。只不过,因为傅里叶变换只是在这一帧信号上进行的,群延时也被局限在这一帧信号的范围(几十毫秒)内。第 6 步中说经过修改后的信号两端不一定是渐渐衰减到 0 的,其实正是这种群延时的体现,施加合成窗只不过是「头痛医头」的补救措施。纵观整个合成信号,它相当于原始信号中的各个时频单元都发生了几十毫秒的错位,那么它的听觉效果就难免变成「汉顺字序不影阅响读」的样子 —— 人们可以分辨出声音的内容,但听起来确实会觉得「抖」了。
按本节中的步骤修改短时相位谱,达到的也并不是「对乐音的各个谐波进行独立的相移」的效果,所以就不能用来证明「人耳对相位不敏感」了。
事实上,本节中的分析—合成步骤还有一个根本的 bug。假设原始声音信号的长度为
个采样点,那么它可以被分成
帧(加一减一等都忽略)。对每一帧进行
点短时傅里叶变换,可以得到幅度谱和相位谱,它们的长度都是
。由于原始声音信号是实的,幅度谱和相位谱都具有对称性,所以幅度谱和相位谱各自都只有
个自由度。把所有帧都放到一起,它们的幅度谱一共有
个自由度,相位谱也一共有
个自由度。但是,原始声音信号只有
个自由度,所以幅度谱和相位谱合在一起的
个自由度中,有一半是冗余的!
这就是说,给定了具有
个自由度的短时幅度谱之后,理论上不需要知道短时相位谱,就应该能够合成出声音。换句话说,给定了短时幅度谱之后,会存在一种短时相位谱,能够合成出最「自然」的声音,而使用别的相位谱,都只能合成出「发抖」的声音。这种理想的短时相位谱应当满足这样的约束:用它合成出的相邻两帧信号,去掉分析窗后,在重叠的部分应当是一模一样的。至于如何找到这样的理想短时相位谱,我并不知道有什么算法(如果你知道,请告诉我);但如果有这种算法,算法就也只需要短时幅度谱作为输入,而没有短时相位谱什么事儿了,于是也就无法用修改短时相位谱的方法证明「人耳对相位不敏感」了。
要用实验的方法证明「人耳对相位不敏感」,就要保证实验确实能达到「对乐音中的各次谐波进行不等量的相移」的效果,并尽量减小副作用。「分频段相移法」和「全通滤波器法」能够达到这样的效果。「交换相位谱法」以及「修改短时相位谱法」的主要效果是剧烈、混乱的群延时,而不是对各次谐波进行不等量的相移,所以就不能用来证明「人耳对相位不敏感」了。
11025 更新:在仅已知幅度谱、不知道相位谱的条件下重建语音的算法是存在的。它叫做 Griffin-Lim 算法,发表于 1984 年。这么古老的算法我居然现在才知道!
算法的原理极其简单。它是一个迭代算法,迭代过程如下:
该算法可以在频域内在最小均方误差意义下逼近已知幅度谱。但如果把一个时域信号进行短傅里叶分析后丢弃相位谱,再输入进 Griffin-Lim 算法,则不能保证重建出的时域信号与原信号在细节上相似。
原文作者:;如有侵权,请联系管理员删除。