les règles empiriques comment lisser le spectre FFT pour éviter des artefacts lorsque la main peaufinage?

StackOverflow https://stackoverflow.com/questions/3827346

  •  26-09-2019
  •  | 
  •  

Question

J'ai un spectre d'amplitude FFT et je veux créer un filtre qui passe de celui-ci de manière sélective des sources de bruit périodiques (par exemple sinusoïde éperons) et zéros sur les bacs de fréquences associées au bruit de fond aléatoire. Je comprends des transitions nettes dans le domaine Freq créer des artefacts de sonnerie une fois ce filtre est de retour IFFT au domaine du temps ... et je me demande s'il y a des règles empiriques comment lisser les transitions dans le filtre d'un tel pour éviter une telle sonnerie.

Par exemple, si la FFT a des bacs de fréquence 1M, et il y a cinq éperons piquer du plancher de bruit de fond, je voudrais à zéro tous les bacs, sauf le bac de pic associé à chacun des cinq éperons. La question est de savoir comment gérer les bacs à denture droite voisins pour empêcher des artefacts dans le domaine temporel. Par exemple, si le bac de chaque côté d'un bac à éperon être réglé à l'amplitude de 50%? Si deux bacs de chaque côté d'un bac à éperon utilisé (le plus proche à 50%, et la plus rapprochée à 25%, etc.)? Toute pensée grandement appréciée. Merci!

Était-ce utile?

La solution

Je aime la méthode suivante:

  • Créer le spectre d'amplitude idéale (ne pas oublier de le rendre symétrique par rapport à DC)
  • Transformation inverse au domaine temporel
  • Faites pivoter le bloc de la moitié du blocksize
  • Appliquer une fenêtre de Hann

Je trouve raisonnablement lisse crée des résultats de domaine de fréquence, bien que je ne l'ai jamais essayé quelque chose aussi fort que vous proposez. Vous pouvez probablement faire un filtre plus nette en utilisant une fenêtre Kaiser-Bessel, mais vous devez choisir les paramètres de manière appropriée. En plus nette, je devine que vous pouvez peut-être réduire les lobes secondaires de 6 dB environ.

Voici quelques exemples de code Matlab / Octave. Pour tester les résultats, j'ai utilisé freqz(h, 1, length(h)*10);.

function [ht, htrot, htwin] = ArbBandPass(N, freqs)
%# N = desired filter length
%# freqs = array of frequencies, normalized by pi, to turn into passbands
%# returns raw, rotated, and rotated+windowed coeffs in time domain

if any(freqs >= 1) || any(freqs <= 0)
    error('0 < passband frequency < 1.0 required to fit within (DC,pi)')
end

hf = zeros(N,1); %# magnitude spectrum from DC to 2*pi is intialized to 0
%# In Matlabs FFT, idx 1 -> DC, idx 2 -> bin 1, idx N/2 -> Fs/2 - 1, idx N/2 + 1 -> Fs/2, idx N -> bin -1
idxs = round(freqs * N/2)+1; %# indeces of passband freqs between DC and pi
hf(idxs) = 1; %# set desired positive frequencies to 1
hf(N - (idxs-2)) = 1; %# make sure 2-sided spectrum is symmetric, guarantees real filter coeffs in time domain
ht = ifft(hf); %# this will have a small imaginary part due to numerical error
if any(abs(imag(ht)) > 2*eps(max(abs(real(ht)))))
    warning('Imaginary part of time domain signal surprisingly large - is the spectrum symmetric?')
end
ht = real(ht); %# discard tiny imag part from numerical error
htrot = [ht((N/2 + 1):end) ; ht(1:(N/2))]; %# circularly rotate time domain block by N/2 points
win = hann(N, 'periodic'); %# might want to use a window with a flatter mainlobe
htwin = htrot .* win;
htwin = htwin .* (N/sum(win)); %# normalize peak amplitude by compensating for width of window lineshape
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top