ITPub博客

首页 > > > 10877 「人耳对相位不敏感」到底是什么意思(下)

10877 「人耳对相位不敏感」到底是什么意思(下)

作者:格伯纳 时间:2018-02-06 00:04:21 0 删除 编辑

.  上一篇文章阐释了「人耳对相位不敏感」的一般含义:对乐音的各次谐波分别进行独立的相移,人耳并不会觉察到任何变化。这篇文章就来研究一下,如何以一段真实声音为材料,通过人为修改其频谱的方法,达到「对乐音的各次谐波进行独立相移」的效果,从而证明人耳对相位不敏感。我会逐个讨论这个问题下各个答主的方法能否达到这一目的。

零、相移操作对调幅、调频信号相位的影响

  要通过人为修改的办法对一段声音进行相移,我们首先需要一些理论知识,即弄清楚一段调幅、调频信号相移时,它的频谱(包括幅度谱和相位谱)如何变化。

  调幅、调频信号的一般表达式为:

x(t) = A(t) \cos \left( 2\pi \int_0^t f(\tau) \,\text{d}\tau + \phi_0 \right) \\

为简便起见,定义 \phi(t) = 2\pi \int_0^t f(\tau) \,\text{d} \tau + \phi_0 ,则上述表达式可写为

x(t) = A(t) \cos \phi(t) \\

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

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

x(t) = x_+(t) + x_-(t) = \frac{A(t)}{2} \text{e}^{\text{i}\phi(t)} + \frac{A(t)}{2} \text{e}^{-\text{i}\phi(t)} \\

拆出来的两项,就分别对应着幅度谱中正频率的部分(右侧)和负频率的部分(左侧)。

  现在把 x(t) 的相位推迟 \Delta\phi ,则其表达式变为:

y(t) = A(t)\cos[\phi(t) - \Delta\phi] \\

同样利用欧拉公式,这个信号也可以拆成两个复信号之和:

y(t) = \text{e}^{-\text{i} \Delta\phi} \cdot \frac{A(t)}{2} \text{e}^{\text{i}\phi(t)} + \text{e}^{\text{i} \Delta\phi} \cdot \frac{A(t)}{2} \text{e}^{-\text{i}\phi(t)} \\

可以看到,相移的效果是对正、负频率分量分别乘以了 \text{e}^{-\text{i} \Delta\phi}、\text{e}^{\text{i} \Delta\phi} 两个系数,即保持幅度谱不变,在相位谱的正频率部分减去 \Delta\phi ,负频率部分加上 \Delta\phi 。如果取 \Delta\phi = \pi/2 ,那么相移操作就是我们熟悉的希尔伯特变换。

  有了上面的理论准备,我们就可以开始讨论实验方法了。

一、分频段修改相位谱

  如果能把一段真实声音信号中每个乐音的每个谐波分解出来,就可以利用修改相位谱的办法,独立地对各个谐波进行相移;把相移后的各个谐波再合成到一起播放,听起来与原始信号没有差异,就可以证明人耳对相位不敏感。然而,从真实声音信号中分离出各次谐波本身就是一件很困难的事情,我们只能对真实声音信号的频谱进行整体修改。

  最简单的办法,就是在真实声音信号的相位谱上,从正频率部分减去 \Delta\phi ,往负频率部分加上 \Delta\phi 。在 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。这相当于取 \Delta\phi = \pi 的特例。

  对信号的相位谱进行整体修改,总感觉丧失了一些自由度:本来各次谐波是可以进行不等量的相移的嘛。为了近似达到这一效果,我们想到:可以对不同频段进行不等量的相移。例如,对 600 Hz 以下的频率,相位推迟 \pi/4 ;对 600 Hz 以上的频率,相位提前 3\pi/4 。

  这个办法基本可以奏效,但是有一点美中不足:如果你的原始信号恰恰在临界频率处有比较强的能量,那么这些能量会被弥散到整个时间轴上去。「呜~呜」信号恰好在 600 Hz 处有比较强的能量。下面的视频演示了分段相移的效果,视频画面显示的是原始信号和修改后的信号的语谱图,你会看到以及听到修改后的信号中有一个幽灵般的 600 Hz 单音贯穿始终。

https://

  这种副作用的产生,跟「群延时」有关。如果某个频率 f 附近的相移 \Delta\phi(f) 不是常数,那么这些相移会造成频率在 f 周围的信号发生整体的延时,具体的延时量为 \tau_g(f) = -\frac{1}{2\pi}\frac{\text{d} \Delta\phi(f)}{\text{d} f} 。在对频谱进行分段相移时,临界频率处的相移有突变,这就造成了临界频率周围的信号产生剧烈的群延时,听起来就是这一频率的信号弥散到了整个时间轴上去。

  能不能既实现不同频段进行不等量相移的效果,又避免相移的突变造成的剧烈群延时呢?我的答案中使用的「全通滤波器」法,就恰恰达到了这个目的。

二、全通滤波

  全通滤波器的幅度响应为常数,这是通过在关于单位圆反演对称的位置设置零极点对来实现的。为了保证滤波器稳定,极点必须都在单位圆内;对于每一个极点 p = r\text{e}^{\text{i}\theta} ,都会相应地设置一个零点 z=\frac{1}{r}\text{e}^{\text{i}\theta} 。为了保证滤波器系数为实数,零极点必须都成共轭对,所以对于上述的零极点,还会设置另外一对零极点 \bar{z} = \frac{1}{r}\text{e}^{-\text{i}\theta} 和 \bar{p} = r\text{e}^{-\text{i}\theta}。由 (z, \bar{z}; p, \bar{p}) 组成的二阶滤波器,就可以认为是全通滤波器的组成单元;高阶的全通滤波器由许多这样的二阶滤波器级联而成。

  全通滤波器既然幅度响应为常数,那么自然地相位响应就值得关注了。上述二阶全通滤波器单元的相位响应 \Delta\phi(\omega) 如下图 (a) 所示,这里 \omega \in [0, \pi] 代表归一化角频率,参数取 r = 0.9 ,\theta = \pi/4 。它是一条单调递减的曲线,起点为 (0,0) ,终点为 (\pi, -2\pi) 。曲线的斜率呈现「缓—陡—缓」的变化趋势,其中较陡的一段,横坐标在零极点的辐角 \theta 附近;陡峭的程度由极点的模 r 控制, r 越大越陡。

  群延时理论告诉我们,这样的全通滤波器单元会在归一化角频率 \theta 附近造成较大的群延时;而在归一化角频率远离 \theta 的左右两段,群延时比较小,相移是主要的效果。下面我们计算一下,扣除群延时效果后,全通滤波器单元造成的净相移有多大。当相位响应为 \Delta\phi(\omega) 时,归一化角频率 \omega 处的群延时为 \tau_g(\omega) = -\frac{\text{d}\Delta\phi(\omega)}{\text{d}\omega} (单位为采样点个数)。而单纯地把整个信号向后平移 \tau_g(\omega) ,在归一化角频率 \omega 处产生的相移是 -\omega \cdot \tau_g(\omega)。于是,全通滤波器单元的净相移就是:

\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} \\

上面的图 (c) 画出了全通滤波器单元的净相移。可以看到,在低频处净相移接近 0,在高频处净相移虽然接近 -2\pi 但仍有距离,这就达到了「分频段相移」的目的。而在归一化角频率 \theta 附近有变换比较剧烈的净相移,这其实也是我们想要的效果 —— 在不同的频率处进行不等量的相移。

  那么全通滤波器单元的副作用「群延时」有多大呢?上面的图 (b) 画出了各频率处的群延时的大小,纵轴的单位为采样点的个数,把它除以采样频率就可以得到以「秒」为单位的延时量。若取采样频率为 8000 Hz,则临界频率附近的最大群延时(19 个采样点)约为 2.4 毫秒,这点儿群延时是可以接受的。

  我在设计这个实验的当时,出发点是设计一个比较「崎岖」的相位响应。为此,我把所有极点的模 r 都选在了 0.9 到 0.99 之间。现在想来,其实没必要把 r 选得这么大。当 r 很接近 1 时,临界频率附近就会体现出比较明显的群延时,这是我们不想要的。另外,当 r 很接近 1 时,低频和高频处的净相移之差就会很接近 2\pi ,而 2\pi 的相位差跟 0 是一回事,于是反倒达不到「分频段相移」的目的。当然,  r 小了之后,净相移就会变成「渐变」而不是「分段」的,不过这没有关系,我们的初衷就是让不同频率处的净相移不同嘛。

  我在实验中使用的是 20 阶全通滤波器,即 10 个二阶全通滤波器单元级联。滤波器的阶数可以继续增加,但有两个问题:一是 Matlab 中的 poly 函数无法计算特别高阶的滤波器的系数。比如,如果你直接计算一个 100 阶全通滤波器的系数,可能会导致数值不稳定;你需要分别生成五个 20 阶全通滤波器,依次对信号进行滤波。二是高阶全通滤波器的群延时也会比较大。我们看到了不同频段的群延时会有不同,如果各频段的群延时之间的差距达到了几十毫秒的数量级,就会破坏谐波之间「时间重合」的关系,人就会开始听到回声的效果了,这也是我们希望避免的副作用。

  下面的视频包含了三段声音,第一段是原始语音「电灯比油灯进步多了」,第二段是经 20 阶全通滤波器滤波后的结果,第三段是经 1000 阶全通滤波器滤波后的结果。极点的模仍按我的原始实验,都取在 0.9 到 0.99 之间。从语谱图上能看出 20 阶全通滤波器已经有了微小的群延时,但尚未影响听觉效果;1000 阶全通滤波器的群延时已经非常明显了,并且因为各频段的群延时不同,回声效果比较严重。

https://

三、交换两段声音的相位谱

.  @Bimos 做的实验很有意思:他把一段声音 x 的幅度谱和另一段声音 y 的相位谱放在一起,发现合成出来的声音听起来像是带有噪音的 y,从而说明声音的信息主要蕴藏在相位谱中。例如,下面一段视频就依次播放了三段声音:

  • 汉语男声「电灯比油灯进步多了」;
  • 带背景音乐的法语男声「les trois mousquetaires」(三个火枪手);
  • 用前者的幅度谱与后者的相位谱重新合成的声音,听起来更像后者。

这跟「人耳对相位不敏感」是否矛盾呢?

https://

  原来,把 x 的相位谱换成 y 的相位谱,其效果是让 x 的相位谱上的每一个点都发生了剧烈而混乱的变化。这种变化会造成 x 的所有频段都发生剧烈的群延时,从而面目全非。下面的视频,演示了把第一段声音(电灯比油灯进步多了)的相位谱替换成在 [0, 2\pi) 上均匀分布的随机值造成的效果。可以发现,原声音的所有频段都发生了随机、大幅的群延时,导致内容已经完全听不出来了,新的信号只是幅度谱与原信号相同的噪声。

https://

而把 x 的相位谱换成 y 的相位谱,其效果则是让各频段在群延时之后恰好排成类似 y 信号的语谱图的样子,从而听起来更像 y。

  从另一个角度看,「x 的幅度谱与 y 的相位谱合成」,也可以看成是对 y 的幅度谱进行了修改,即把 y 通过了一个没有任何延时(包括相移和群延时)的滤波器。这样一个滤波器只是对 y 的各个频段进行了加强或减弱,所以并不会大幅影响其内容,只是让音质变差了。

  从 @Bimos 的实验中,可以得出「声音的信息主要蕴藏在相位谱中」的结论。但这并不能说明「人耳对相位敏感」,因为「交换相位谱」这一操作,并不是对声音信号中乐音的各次谐波进行了相移,而是进行了剧烈而混乱的群延时,它破坏了谐波之间「时间重合」的关系,甚至将频率稍有变化的谐波完全撕裂。

四、修改短时相位谱

  上面的所有实验,修改的对象都是一段声音整体做傅里叶变换后得到的相位谱,即长时相位谱。然而,在分析修改的效果的时候,我们却多次观察了声音的语谱图,即对声音逐帧进行短时傅里叶变换后得到的幅度谱。事实上,人耳对声音信号的处理方式正是短时傅里叶变换,人们认为多个谐波组成了同一个乐音,正是因为这些谐波在短时傅里叶的幅度谱上呈现出「时间重合、频率成整数倍」的关系。 @Bimos 得到的结论「声音的信息主要蕴藏在(长时)相位谱中」固然正确,但信息具体是怎么蕴藏的,则很难解释,不如说「声音的信息主要蕴藏在短时幅度谱中」来得直接。

  那么短时相位谱呢?如果说短时相位谱不重要,是否可以通过胡乱修改声音的短时相位谱的方式,来证明「人耳对相位不敏感」呢?

  我在做大四毕业设计课题(歌声与伴奏的分离)时,曾经使用如下步骤获得一段声音的短时幅度谱和相位谱,进行修改后再反过来合成声音:

  1. 把声音分帧,设每帧长为 N 个采样点,相邻两帧重叠 N/2 个采样点;
  2. 对每帧加窗(称为「分析窗」);
  3. 对加窗后的每帧信号进行 N 点傅里叶变换,得到幅度谱和相位谱;
  4. 对幅度谱和相位谱进行任何想要的修改;
  5. 对修改后的幅度谱、相位谱进行 N 点逆傅里叶变换,得到长度为 N 的一帧信号;
  6. 这帧信号的两端不一定是渐渐衰减到 0 的,所以要再加一次窗(称为「合成窗」);
  7. 将各帧信号叠加(相邻两帧重叠 N/2 个采样点),得到合成声音。

可以验证,只要分析窗与合成窗相乘的结果是汉宁窗,如果在第 4 步不进行任何修改,合成出的声音就会与原始声音完全相同。实际中,我是在第 2、6 步中都施加正弦窗(正弦窗的平方就是汉宁窗);其实也可以在第 2 步中不加窗(相当于加矩形窗),并在第 6 步中加汉宁窗。

  上面的步骤,就提供了一种「胡乱修改声音的短时相位谱」的方法。比如,对于「电灯比油灯进步多了」这段声音,我们可以在第 4 步将它的短时相位谱改成全零,或者改成随机值,或者干脆换成「三个火枪手」的相位谱。下面的视频演示了原始声音和三种修改的效果,声音的采样率为 8000 Hz,帧长为 320 个采样点,即 40 毫秒。

https://

  我们发现,修改短时相位谱后,声音都「抖」了起来,而不是像预想的那样毫无变化,似乎不能用「修改短时相位谱」的方法证明「人耳对相位不敏感」。这是为什么呢?

  原来,胡乱修改每一帧声音的相位谱,同样会造成这一帧声音各频段产生剧烈、混乱的群延时。只不过,因为傅里叶变换只是在这一帧信号上进行的,群延时也被局限在这一帧信号的范围(几十毫秒)内。第 6 步中说经过修改后的信号两端不一定是渐渐衰减到 0 的,其实正是这种群延时的体现,施加合成窗只不过是「头痛医头」的补救措施。纵观整个合成信号,它相当于原始信号中的各个时频单元都发生了几十毫秒的错位,那么它的听觉效果就难免变成「汉顺字序不影阅响读」的样子 —— 人们可以分辨出声音的内容,但听起来确实会觉得「抖」了。

  按本节中的步骤修改短时相位谱,达到的也并不是「对乐音的各个谐波进行独立的相移」的效果,所以就不能用来证明「人耳对相位不敏感」了。

  事实上,本节中的分析—合成步骤还有一个根本的 bug。假设原始声音信号的长度为 L 个采样点,那么它可以被分成 2L/N 帧(加一减一等都忽略)。对每一帧进行 N 点短时傅里叶变换,可以得到幅度谱和相位谱,它们的长度都是 N 。由于原始声音信号是实的,幅度谱和相位谱都具有对称性,所以幅度谱和相位谱各自都只有 N/2 个自由度。把所有帧都放到一起,它们的幅度谱一共有 L 个自由度,相位谱也一共有 L 个自由度。但是,原始声音信号只有 L 个自由度,所以幅度谱和相位谱合在一起的 2L 个自由度中,有一半是冗余的!

  这就是说,给定了具有 L 个自由度的短时幅度谱之后,理论上不需要知道短时相位谱,就应该能够合成出声音。换句话说,给定了短时幅度谱之后,会存在一种短时相位谱,能够合成出最「自然」的声音,而使用别的相位谱,都只能合成出「发抖」的声音。这种理想的短时相位谱应当满足这样的约束:用它合成出的相邻两帧信号,去掉分析窗后,在重叠的部分应当是一模一样的。至于如何找到这样的理想短时相位谱,我并不知道有什么算法(如果你知道,请告诉我);但如果有这种算法,算法就也只需要短时幅度谱作为输入,而没有短时相位谱什么事儿了,于是也就无法用修改短时相位谱的方法证明「人耳对相位不敏感」了。

五、总结

  要用实验的方法证明「人耳对相位不敏感」,就要保证实验确实能达到「对乐音中的各次谐波进行不等量的相移」的效果,并尽量减小副作用。「分频段相移法」和「全通滤波器法」能够达到这样的效果。「交换相位谱法」以及「修改短时相位谱法」的主要效果是剧烈、混乱的群延时,而不是对各次谐波进行不等量的相移,所以就不能用来证明「人耳对相位不敏感」了。

11025 更新:在仅已知幅度谱、不知道相位谱的条件下重建语音的算法是存在的。它叫做 Griffin-Lim 算法,发表于 1984 年。这么古老的算法我居然现在才知道!

  算法的原理极其简单。它是一个迭代算法,迭代过程如下:

  1. 先瞎猜一个相位谱;
  2. 用相位谱和已知的幅度谱合成语音;
  3. 对合成的语音做短时傅里叶分析,得到新的幅度谱和相位谱;
  4. 丢弃新的幅度谱,用相位谱和已知的幅度谱合成语音,如此重复。

  该算法可以在频域内在最小均方误差意义下逼近已知幅度谱。但如果把一个时域信号进行短傅里叶分析后丢弃相位谱,再输入进 Griffin-Lim 算法,则不能保证重建出的时域信号与原信号在细节上相似。

原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
管理员

注册时间:2018-03-30

  • 博文量
    2383
  • 访问量
    984352