1
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ 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! $\endgroup$ Commented Dec 23, 2020 at 9:40
  • $\begingroup$ i tried to implement convstft = abs*np.cos(angle)+1j*np.sin(angle) but it didn't match stftspectro variable @MarcusMüller $\endgroup$ Commented Dec 23, 2020 at 10:29
  • $\begingroup$ um, your formula is wrong: operator precedence of * over +! $\endgroup$ Commented Dec 23, 2020 at 12:30

1 Answer 1

2
$\begingroup$

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().

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.