lucky1928
lucky1928

Reputation: 8925

FFT noise frequency remove

I use audacity to generate a 10Hz tone with 48KHz samplerate and 1 seconds duration. then load it with below script to plot FFT graph:

from scipy.io import wavfile
from scipy.fftpack import fft, fftfreq
import matplotlib.pyplot as plt
from pydub import AudioSegment
import numpy as np

wav_filename = "\\test\\10Hz.wav"
samplerate, data = wavfile.read(wav_filename)
total_samples = len(data)
limit = int((total_samples /2)-1)
fft_abs = abs(fft(data))*2/total_samples
fft_db = 20*np.log10(fft_abs/32760)
freqs = fftfreq(total_samples,1/samplerate)
# plot the frequencies
plt.plot(freqs[:limit], fft_db[:limit])
plt.xscale('log',basex=10)
plt.title("Frequency spectrum")
plt.xlabel('Hz')
plt.ylabel('amplitude')
plt.show()

I got below noisy graph: enter image description here

But if I use audacity to view the spectrum graph, it's pretty good.

How should I improve my script to get better FFT drawing?

Upvotes: 3

Views: 1261

Answers (1)

francis
francis

Reputation: 9817

That particular pattern of the frequency spectrum of the WAV file is generated by the noise-shaped dither applied by Audacity to mitigate the distortion created by quantization.

The signal is stored as signed 16-bit integers in the WAV file. This quantization makes the signal quite innacurate: 2^15 is 32768 : relative errors of 0.5/32768 are very likely and computing the DFT may increase it. That is about 1e-5, or -96dB. Hence, any frequency below 96dB can be discarted as quantization noise if the values of the signal are carelessly cast to the nearest integer.

Nevertheless, the frequency spectrum of the exported WAV file looks very nice, as all frequencies feature an amplitude lower than -100dB, the only exception being the frequency of the sine wave, which features an amplitude near 0dB. The question is to be rephrased: how does Audacity acheive such an accurate spectrum for the WAV file?

The exported values are optimized to improve the accuracy of the spectrum. In fact, the accuracy of the individual exported values is less precise than casting floating values to integer. I generated a sine wave of amplitude 0.8 in audacity and exported it as WAV signed 16bit PCM. The quantization error can be computed as:

x=np.linspace(0,1,len(data),endpoint=False)
data2=np.sin(10*2*np.pi*x)

data=data.astype(np.double)
plt.plot(x, data-0.8*32768*data2, label="data-sin(x)")
#plt.xscale('log',basex=10)
plt.title("signal")
plt.xlabel('time, s')
plt.ylabel('amplitude')
plt.show()

The generated plot of the quantization error: enter image description here

If the signal values were simply cast to nearest integer and poured in the WAV file, the generated error would have been lower than 0.5. The actual pointwise error is about 5.

A noise-shaped dither is considered in Audacidy to improve the dynamic range of quantizated signals by adding a high frequency noise hardly heard by human hears. there, there and there.

You may choose the dither in Audacity or even disable it. Go into Preferences=> Quality! If no dither is considered, the pointwise error in the real space is smaller:

enter image description here

But the quantization error on the spectrum is higher:

enter image description here

A rectangular dither could be used to retreive something looking like a white noise: it may proove the best choice for your use, as the error on the spectrum is about -125dB and the pointwise error is +-1.

enter image description here

enter image description here

Upvotes: 4

Related Questions