3
$\begingroup$

I read the source code of librosa.stft and sicpy.signal.stft, and notice that the calculation results of STFT in these two libraries are quite different: In scipy.signal.stft, the stft result is scaled by 1.0/win.sum(), while in librosa.stft no scaling or normalization procedure is done. So why scipy.signal.stft do the additional scaling procedure? And is there any other difference in the calculation of STFT in these two libraries?

$\endgroup$

3 Answers 3

2
$\begingroup$

Fft scaling (normalization) isn't strictly a part of an fft algorithm although some implementations (like the one you mention) include it. Since scaling depends on the actual fft algorithm, it makes sense, in my opinion, to include it in the implementation because it may not be obvious for programmers to decide what scaling factor(s) to use (the usual scaling factors are $1/N$, $2/N$ (an efficient fft algorithm that is using only half the spectrum so we need to multiply by 2 to compensate for the missing energy), $1/sum(wnd)$, $2/sum(wnd)$

As for your second question, I haven't gone over the code (you haven't provided any links to the source), but some (usually minor) calculation differences might exist given that an fft algorithm can be implemented in a number of ways ( e.g real fft vs complex fft, decimation in frequency vs decimation in time, radix 2 vs mixed radix etc and combinations thereof)

$\endgroup$
2
$\begingroup$

scipy.signal.stft uses scale factor for the result stft source code
To get the same values as for librosa.stft you need:

_, _, stft_res = scipy.signal.stft(inputAudio, window='hamming', nperseg=640, noverlap=480, boundary=None, padded=False)
hamm_win = scipy.signal.get_window('hamming', 640)
scale = np.sqrt(1.0 / hamm_win.sum()**2)
stft_res = stft_res / scale

$\endgroup$
0
$\begingroup$
  • scipy rescales output by 2 / win.sum(), librosa doesn't.
  • scipy and librosa sometimes differ in output shapes; scipy appears to follow what I'm describing here (I've not checked). (Note, I'm no longer much advocating for what I did in that thread)
  • scipy handles complex signals, librosa doesn't (but it may have another method for those, unsure)
  • scipy and librosa offer different built-in pre- and post-processing steps (some already mentioned), e.g. scipy has detrend and librosa has center. "built-in" meaning directly in call to stft, and not via a separate method.
  • librosa has ways to configure the fft that's used in its methods, which likely (I've not checked) includes stft, hence supporting hardware acceleration.

The 2 / win.sum() scaling yields the amplitude time norm, making $|\texttt{STFT}|$ peak at true amplitude values when possible - explained (with examples) in Amplitude extraction using STFT. This normalization isn't always useful, however - it's sometimes detrimental, and it adds compute expense - and there's no way to turn it off.

Between the two, librosa is the more mature time-frequency library, and it should be preferred. I'd also recommend ssqueezepy (I'm author), where a superior complex-valued STFT is implemented (and has built-in CPU and GPU acceleration), as described here.

$\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.