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
y, sr = librosa.load(librosa.ex('choice'), duration=10)
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().
convstft = abs*np.cos(angle)+1j*np.sin(angle)
but it didn't match stftspectro variable @MarcusMüller $\endgroup$*
over+
! $\endgroup$