ITPub博客

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

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

作者:格伯纳 时间:2018-02-06 14:07:03 0 删除 编辑

  写完了上、下两篇后,我又想到了一个有趣的数学问题,于是就再写下这篇「续」。

  在下篇的第一、二节,我把滤波器的相位响应分成了「群延时」和「净相移」两部分。如果一个滤波器的相位响应为 \Delta\phi(\omega) ,则它的群延时为

\tau_g(\omega) = -\frac{\text{d}\Delta\phi(\omega)}{\text{d}\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} \\

现在问题来了:给定了想要的净相移 \Delta\phi_\text{net}(\omega) ,如何求「毛相移」\Delta\phi(\omega) ?

  我们简化一下符号,把毛相移记作 f(\omega) ,净相移记作 g(\omega) ,于是它们之间的关系就是 g(\omega) = f(\omega) - \omega \cdot f'(\omega) 。这是一个微分方程,已知 g(\omega) ,求 f(\omega) 。怎么解呢?

  像所有的参考答案一样,我要使用一次「神来之笔」:方程右边很像两个函数之商的导数公式。原来, \left[ \frac{f(\omega)}{\omega} \right]' = \frac{\omega \cdot f'(\omega) - f(\omega)}{\omega^2} 。这样,微分方程就可以化成:

\left[ \frac{f(\omega)}{\omega} \right]' = -\frac{g(\omega)}{\omega^2} \\

两边积分,就得到了解:

f(\omega) = -\omega \cdot \int \frac{g(\omega)}{\omega^2} \,\text{d}\omega \\

注意,右边的不定积分算出来之后,别忘了加积分常数!

  下面来看两个例子。

【例 1】想让净相移呈线性变化,当归一化角频率从 0 变化至 \pi 时,净相移从 0 变化至 -2\pi ,即 g(\omega) = -2\omega 。求毛相移 f(\omega) 和群延时。

解:毛相移

\begin{align} f(\omega) &= -\omega \cdot \int \frac{-2\omega}{\omega^2} \,\text{d}\omega \\ &= -\omega \cdot (-2 \ln \omega + C) \\ &= 2\omega\ln\omega - C\omega \end{align} \\

群延时

\tau_g(\omega) = -f'(\omega) = -2(\ln\omega + 1) + C \\

不妨取 C = 0 ,此时毛相移、群延时、净相移的图象如下。这个群延时是为了得到想要的净相移所必须付出的代价。调整 C 可以让群延时曲线整体上移或下移,相当于把信号整体提前或推迟,实际上没有什么用。群延时在极低频处会比较大,不过好在极低频的声音是听不见的,所以没有关系。

【例 2】想让净相移分段为常数:

g(\omega) = \begin{cases} -\pi/4, & 0 \le \omega < \pi/4 \\ \pi/4, & \pi/4 \le \omega < \pi/2 \\ \pi/2, & \pi/2 \le \omega < 3\pi/4 \\ \pi, & 3\pi/4 \le \omega \le \pi \end{cases} \\

求毛相移 f(\omega) 和群延时。

解:在任一区间上,若 g(\omega) 为常数 b ,则 f(\omega) = -\omega \cdot \int \frac{b}{\omega^2} \,\text{d}\omega = b - C\omega 。也就是说,这是一条截距为 b 的直线上的一段。

  本题的 g(\omega) 把横轴 0 \le \omega \le \pi 平分成了四个区间,我们从左到右一个一个看:

  • 第一段的 b = -\pi/4 。不妨取 C = 0 ,于是在这一段上 f(\omega) = -\pi/4 ,其右端点为 (\pi/4, -\pi/4) 。
  • 第二段的 b = \pi/4 。又由于这一段上的 f(\omega) 必须过 (\pi/4, -\pi/4) 才能保证 f(\omega) 在整体上是连续的,可以解出这一段上的 C = -2 , f(\omega) = \pi/4 - 2\omega 。这一段的右端点为 (\pi/2, -3\pi/4) 。
  • 第三段的 b = \pi/2 。考虑到 f(\omega) 必须过 (\pi/2, -3\pi/4) ,可以解得这一段上 f(\omega) = \pi/2 - 5\omega/2 ,其右端点为 (3\pi/4, -11\pi/8) 。
  • 第四段的 b = \pi 。考虑到 f(\omega) 必须过 (3\pi/4, -11\pi/8) ,可以解得这一段上 f(\omega) = \pi - 19\omega/6 。

由此可得毛相移和群延时:

f(\omega) = \begin{cases} -\pi/4, & 0 \le \omega < \pi/4 \\ \pi/4 - 2\omega, & \pi/4 \le \omega < \pi/2 \\ \pi/2 - 5\omega/2, & \pi/2 \le \omega < 3\pi/4 \\ \pi - 19\omega/6, & 3\pi/4 \le \omega \le \pi \end{cases} \quad \quad \quad \tau_g(\omega) = \begin{cases} 0, & 0 \le \omega < \pi/4 \\ 2, & \pi/4 \le \omega < \pi/2 \\ 5/2, & \pi/2 \le \omega < 3\pi/4 \\ 19/6, & 3\pi/4 \le \omega \le \pi \end{cases} \\

  但是,眼看着群延时一段比一段大,不太爽。事实上,在第四段上,可以认为 g(\omega) = -\pi ,因为反正 -\pi 的相移跟 \pi 的相移是一回事。这样,就可以重新计算最后一段的毛相移和群延时:

f(\omega) = \begin{cases} -\pi/4, & 0 \le \omega < \pi/4 \\ \pi/4 - 2\omega, & \pi/4 \le \omega < \pi/2 \\ \pi/2 - 5\omega/2, & \pi/2 \le \omega < 3\pi/4 \\ -\pi - \omega/2, & 3\pi/4 \le \omega \le \pi \end{cases} \quad \quad \quad \tau_g(\omega) = \begin{cases} 0, & 0 \le \omega < \pi/4 \\ 2, & \pi/4 \le \omega < \pi/2 \\ 5/2, & \pi/2 \le \omega < 3\pi/4 \\ 1/2, & 3\pi/4 \le \omega \le \pi \end{cases} \\

群延时横跨的范围由 [0, 19/6] 缩小至 [0, 5/2] 。在想要的净相移为分段函数时,通过在各段上增减 2\pi ,有可能起到缩小群延时范围的作用,这算是面对命运的一点儿抗争。

  有了根据净相移计算毛相移的方法,我们就可以随心所欲地修改信号了!比如,我们用最后得到的毛相移处理「电灯比油灯进步多了」这段声音,代码如下:

[x, fs] = audioread('diandeng.wav');          % 读入声音
X = fft(x);                                   % 求频谱

% 按刚刚计算出的公式构造毛相移向量
omega = linspace(0, pi, length(X) / 2 + 1)';  % 自变量:归一化角频率,从0到pi
f = zeros(size(omega));                       % 因变量:毛相移
f(omega > 0 & omega < pi/4) = -pi/4;          % 注意归一化角频率等于0或pi处最好不要乱动
f(omega >= pi/4 & omega < pi/2) = pi/4 - 2 * omega(omega >= pi/4 & omega < pi/2);
f(omega >= pi/2 & omega < 3*pi/4) = pi/2 - 5/2 * omega(omega >= pi/2 & omega < 3*pi/4);
f(omega >= 3*pi/4 & omega < pi) = -pi - 1/2 * omega(omega >= 3*pi/4 & omega < pi);

H = exp(1i * f);                              % 把毛相移转化成滤波器的传输函数
H = [H; conj(H(end-1:-1:2))];                 % 补齐共轭对称的另一半

Y = X .* H;                                   % 改造声音的频谱!
y = real(ifft(Y));                            % 逆变换得到相移后的声音
soundsc(y, fs);                               % 播放!

  实验结果如下。因为群延时最大只有 2.5 个采样点,所以在语谱图上几乎看不出来,当然听就更听不出来啦。

https://

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

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

注册时间:2018-03-30

  • 博文量
    2383
  • 访问量
    984352