从频谱图中恢复相位

信息处理 傅里叶变换 频谱 频谱图 stft
2022-02-13 19:48:28

这个答案中,给出了一个迭代算法,用于从其频谱图中恢复信号,假设重叠窗口:

xn+1=istft(Sexp(iangle(stft(xn)))),

在哪里S是频谱图和(i)stft是(逆)短时傅里叶变换。我使用 NumPy、SciPy 和librosa进行了尝试:

import librosa
import numpy as np
import scipy

def mse(phase_pred, phase_true):
    '''
    Calculate the mean square error between the true phase and the
    predicted (reconstructed) phase.
    '''
    return np.mean(np.angle(phase_pred/phase_true)**2)

# Load an audio file and calculate STFT.
x, sample_rate = librosa.load('audio.wav', sr=44100)
D = librosa.stft(x)
mag, actual_phase = librosa.magphase(D)

# Try to reconstruct the phase using the iterative algorithm above.
phase = np.exp(1.j * np.random.uniform(0., 2*np.pi, size=actual_phase.shape))
x_ = librosa.istft(mag * phase)
print('iter {} mse {}'.format(-1, mse(phase, actual_phase)))
for i in range(100+1):
    _, phase = librosa.magphase(librosa.stft(x_))
    x_ = librosa.istft(mag * phase)
    print('iter {} mse {}'.format(i, mse(phase, actual_phase)))
    if i % 10 == 0:
        scipy.io.wavfile.write('recons{:05d}.wav'.format(i), 44100, x_)

据我所知,它没有收敛:

收敛

但是,第 100 次迭代后的音频听起来肯定比具有随机相位的音频更接近原始音频。

为什么这个算法没有收敛到正确的阶段?我误解了它的目的吗?

1个回答

从 STFT 的定义中应该清楚,结果在全局相变下是不变的。由于对实际输入信号的限制仍然提供符号模糊性或相位差π. 这意味着,即使您的重建是完美的,结果也可能与原始阶段不同。

无法收敛的另一个原因可能是信号中存在几乎断开的组件。假设您有两个声音分量在时间上是分开的,因此没有与两者重叠的 STFT 帧。每个组件都可以用不同的符号重建,给你四个不同的重建和相同的 STFT。这同样适用于在频率方向上分离得足够好的组件。每个分量都会使重构信号的模糊度加倍,并且会增加偏离原始信号的概率。

我能看到的最后一个原因在于迭代算法的性质。定点迭代(该算法属于哪种类型)可能无法收敛到适当的定点,保持振荡甚至发散。除非所涉及的地图在某种意义上表现良好,否则很难预测收敛。您的迭代似乎没有解决,并且不清楚添加迭代是否会有所帮助。所以这可能适用于这里,连同其他两个问题。