0
$\begingroup$

I am experimenting with audio (wav files) using Short-Time Fourier Transform (STFT) in Python using scipy.signal.stft. As I understand we get data for freq, time and magnitude + phase in rectangular format. for e.g. (shortened for illustration)

freq, time, Zxx = scipy.signal.stft(signal, fs=fs , .. and some other parms)

If I take a single value from Zxx , e.g.

x = -0.01224990-0.01877387j ,

I would like to convert this value to dB, do some modification such as

  • add/reduce few dB's
  • Also change angle or phase
  • and reconstruct the value back to x

So far I have,

#Magnitude
m = np.abs(-0.01224990-0.01877387j)
0.022416918717497732

#angle in degrees
ad =np.angle(-0.01224990-0.01877387j, deg=True)
-123.12434072219258

#phase 
cmath.phase(-0.01224990-0.01877387j)
-2.1489251349495935

#magnitude in dB
dB = 20*np.log10(abs(p))
-32.988481658150704

#modified magnitude
dB = dB + 10.0

#Modified angle
ad = -123.12434072219258 + 50.0

Now, How do I convert it back to modified x. using above values?

I researched but couldn't find a straightforward solution. Before reinventing the wheel of constructing the complex mathematical functions, i thought I would ask the experts.

The only reference I found was mag2db and db2mag at matlab, but not sure how to access or implement these in python.

EDIT1
Please note: I am not trying to reconstruct original signal (or x value) back. I need to modify Zxx values and hence I know I will get a different signal back using scipy.signal.istft.

Although I can directly manipulate x+jy which affect both magnitude and phase, I would like to modify them individually and Hence this question. Thanks in advance.

$\endgroup$
  • $\begingroup$ Converting mel spectrogram to spectrogram <- Does not solve my problem as the linked question is to convert spectrogram back. I am trying to understand how to convert a magnitude + phase back to rectangular entity (x + jy) using python. $\endgroup$ – Anil_M Dec 15 '17 at 22:58
2
$\begingroup$

If $X_\mathrm{db} = 20 \cdot \mathrm{log}_{10}(|X|)$, then $|X| = 10^{X_\mathrm{db} / 20}$, of course. Furthermore, you can compute the cartesian representation of a complex number $c = a + ib$ from its magnitude $|c|$ and phase $\varphi$: $c = |c| \cdot \mathrm{exp}(i \varphi)$

So you are probably looking for something like this:

import numpy as np
from matplotlib import pyplot as plt

fs = 100
t = np.arange(100)
x = np.sin(2 * np.pi * 3 * t / fs)

X = np.fft.fft(x)
X_mag = np.abs(X)
X_db = 20 * np.log10(X_mag)
X_phase = np.angle(X)

# ... do modification on X_db and X_phase ...

X_mag_rec = 10 ** (X_db / 20)
X_rec = X_mag_rec * np.exp(1j * X_phase)
x_rec = np.real(np.fft.ifft(X_rec))

plt.plot(t, x, label='original')
plt.plot(t, x_rec, label='reconstructed')
plt.legend()
plt.show()

If you are doing the modification in the STFT domain, note there may be no valid inverse STFT. For details on that look into:

D. Griffin, J. Lim: Signal estimation from modified short-time Fourier transform, in: IEEE Transactions on Acoustics, Speech, and Signal Processing, vol. 32, no. 2, pp. 236–243, Apr 1984.

| improve this answer | |
$\endgroup$

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