# revert back to stft from abs and phase

I have the following code on python

stftspectro = librosa.stft(audio, n_fft=fft_length, hop_length=stride, win_length=window, window='hann')
abs = np.abs(stftspectro)
angle = np.angle(stftspectro)


Can i revert back to stftspectro from below abs and angle. I have no knowledge about sound signals but spectogram from stft is great for audio properties as i have read, and i am applying some deep neural networks that rely on such features. Moreover, doing the inverse stft will produce the same sound:

stfttoaudio = librosa.istft(stftspectro, hop_length=stride, win_length=window, window='hann')


so collecting both abs and angle is helpful in my thought.

• This is just a question about complex numbers. Yes, any complex number can be represented as magnitude (abs) and angle, see Euler's formula – that's pretty fundamental math that you should really understand if you're dealing with Fourier transforms! Commented Dec 23, 2020 at 9:40
• i tried to implement convstft = abs*np.cos(angle)+1j*np.sin(angle) but it didn't match stftspectro variable @MarcusMüller Commented Dec 23, 2020 at 10:29
• um, your formula is wrong: operator precedence of * over +! Commented Dec 23, 2020 at 12:30

As Marcus Müller said, there is an error, when converting abs and angle values back to complex numbers. It should be like this:

\begin{align} x = |x|(\cos \phi + j \sin\phi) \end{align}

Note, that the result convstft of this conversion will be close, but not equal to the original values in stftspectro, most probably, due to inaccuracy of floating point computations.

Here is a reproducible example:

import numpy as np
import librosa

# Creating some audio signal
tempo, beats = librosa.beat.beat_track(y=y, sr=sr)
audio = librosa.clicks(frames=beats, sr=sr)

# Applying short-time Fourier transform with default parameters
fft_length = 2048
stride = 2048 // 4
window = 2048

stftspectro = librosa.stft(audio, n_fft=fft_length, hop_length=stride, win_length=window, window='hann')
abs_val = np.abs(stftspectro)
angle = np.angle(stftspectro)

# Converting abs and angle back to complex number
convstft = abs_val*(np.cos(angle)+1j*np.sin(angle))

# Checking results
# Choosing an arbitrary element index
n=50
m=45

# Is this element similar?
print("stftspectro element:",stftspectro[n][m])
print("abs_val element:",abs_val[n][m])
print("angle element:",angle[n][m])
print("convstft element:",convstft[n][m])

# Are stftspectro and convstft the same?
A=stftspectro
B=convstft
eps = 0.0001+1j*0.0001
print("Are they similar: ",np.array_equal(A,B))  # test if same shape, same elements values
print("Are they close: ",np.allclose(A,B,atol=eps)) # test if same shape, elements have close enough values


Also, I wouldn't use abs as a name for a variable, since it's the name of the python method abs().