2
$\begingroup$

I'm trying to "standardize" the results of the fast Fourier transformation. I've one wav with two peaks (3000 and 3300 Hz) saved with three different encodings(int16, float32, int32).

And these are the scipy.fft plots:

int16 int16 float32 float32 int32 int32

It's clear enough that, while the peaks are coherent at 3000 and 3300Hz, their amplitudes are not so coherent.

I tried to "standardize" the amplitudes with a logarithmic scale, since using a dbFS worked fine in the time domain using the following code:

data=*array containing file.wav data*
data_log=20*log10(data/max_value_of_dtype)

The problem is that once I clean the signal with some filters and use scipy.fft I obtain only a float64 array "losing" information about the encoding and its scale.

Since they represent the same exact signal (even if with different types of encoding) I was expecting the same values of amplitudes with a logarithmic scale like:

fft_data=scipy.fft.fft(wav_audio_data)
fft_mod=numpy.abs(fft_data)
20*log10(fft_mod/max_value_of_fft_mod)

but I didn't obtain the expected result.

My best guess is, for now, re-encoding the wav file in run time to an "arbitrary" standard (for example at int16) and then calculate fft and stuff like that even if with this method the information about different types of encoding would be useless.

Am I missing something? I mean of course, different encodings means different "bit depth" but still they should represent the same signal. I tried different approaches and solutions to have a sort of "universal" dB scale but once I change encoding they stop working.

$\endgroup$
1
  • 1
    $\begingroup$ Just a suggestion, if you use soundfile for loading audio files then the returned array will be automatically stored in -1/+1 range, independently from the original bit-depth. This way you won't have to worry about scaling. Alternatively, you can do this normalization upon loading yourself. $\endgroup$
    – jojeck
    Commented Apr 11, 2022 at 14:05

1 Answer 1

-1
$\begingroup$

Evidently, if you filter your signal, your peak amplitudes will be lost. And regarding the data resolution, it is not the most important in here, just stick with the best resolution you can hold.

You must instead take the energy of the signal $p(t)$, which is the integral of the square the spectrum $P(f)$. $$ E_f=\int_{f_c^{min}}^{f_c^{max}}P^2(f)df $$

A Microphone will measure instantaneous Sound Pressure Level $p(t)$ in Pressure Units: The instantaneous Sound Energy Level will be its square $p^2(t)$. More details about this interesting and deep topic making the difference can be found at these Bruel & Kjaer Articles here and here.

From there, if you want to measure a frequeny peak, instead measuring its amplitude, measure its energy, by calculating the integral of the squared spectrum under a proper cutoff defining it.

Also, remember to hold Parseval Theorem, which is a must if you want to obtain a well scaled spectrum. So your time and spectral energies are actually the same.

It will be difficult at the beginning to integrate both in time and frequency properly to obtain the equivalence, but once achieved, you keep it forever.

$$ E_f=RMS^2\{P(f)\} =\frac{2F}{N}\int_{0}^{F}P^2(f)df\\ =E_t=RMS^2\{p(t)\}=\frac1T\int_{0}^{T}p^2(t)dt $$

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