In this answer, an iterative algorithm is given for recovering a signal from its spectrogram, assuming overlapping windows:
$$ x_{n+1} = \operatorname{istft}(S \cdot \exp(i \cdot \operatorname{angle}(\operatorname{stft}(x_n)))), $$
where $S$ is the spectrogram and $\operatorname{(i)stft}$ is the (inverse) short-time Fourier transform. I tried this out using NumPy, SciPy, and 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_)
As far as I can tell, it isn't converging:
However, the audio after the 100th iteration definitely sounds closer to the original than the one with randomized phases.
Why isn't this algorithm converging to the correct phase? Am I misunderstanding its purpose?