Como criar um eixo de frequência para comprimentos pares e ímpares de FFT?

12

Posso obter ajuda sobre como fazer com que o eixo da frequência passe da frequência negativa para a frequência positiva (em Hertz), que será o eixo x em um resultado da FFT, mas com uma FFT de comprimento uniforme ou FFT de comprimento ímpar. Estou tendo alguns problemas para fazer isso no MATLAB. (Suponha que você conheça a frequência de amostragem f_s).

TheGrapeBeyond
fonte
1
Pode ajudá-lo a pensar sobre as frequências espaçadas igualmente ao redor do círculo unitário. Uma FFT de 4 pontos possui compartimentos de frequência em [0 / 4fs, 1 / 4fs, 2 / 4fs, 3 / 4fs], por exemplo, que é mais comumente escrito como [0, fs / 4, fs / 2, -fs / 4] Uma FFT de 3 pontos possui compartimentos de frequência em [0 / 3fs, 1 / 3fs, 2 / 3fs] ou pode ser escrita como [0, fs / 3, -fs / 3]. Para tamanhos ímpares Isso salta espaçamento iguais ao longo da frequência Nyquist, mas sempre inclui 0.
endolith
@ endolith Essa analogia me ajudou imensamente, muito obrigado!
Mark LeMoine

Respostas:

5

Uma abordagem é simplesmente calcular o vetor de frequência para a saída DFT não deslocada (ou seja, o que você obteria diretamente da fft()função do MATLAB , sem fazer um fftshift()), depois remapear as frequências que correspondem aos locais no lado negativo do eixo. Exemplo:

% assume input signal "x", sampling frequency "fs"
% calculate FFT
X = fft(x,Nfft);
% calculate frequency spacing
df = fs / Nfft;
% calculate unshifted frequency vector
f = (0:(Nfft-1))*df;
% move all frequencies that are greater than fs/2 to the negative side of the axis
f(f >= fs/2) = f(f >= fs/2) - fs;
% now, X and f are aligned with one another; if you want frequencies in strictly
% increasing order, fftshift() them
X_normal_order = fftshift(X);
f_normal_order = fftshift(f);

A resposta fornecida pelo learnvst deve funcionar também; essa é apenas outra maneira de pensar sobre isso, que não requer nenhum revestimento especial para tamanhos DFT pares / ímpares.

Jason R
fonte
Olá JasonR, é certo que esse código está funcionando, pois se eu tentar com fs = 1000 e Nfft = 256, o f_normal_order que recebo começa com um número positivo, torna-se negativo e positivo novamente. Além disso, os comprimentos não são correspondentes.
TheGrapeBeyond
Desculpe, corrigimos alguns erros de digitação no código. Deve funcionar agora.
Jason R
9

Você pode criar um espectro de frequência positivo de maneira bastante simples (onde fsestá a taxa de amostragem e NFFTo número de caixas de fft). Na implementação Matlab do algoritmo FFT, o primeiro elemento é sempre o componente DC, portanto, o motivo pelo qual a matriz começa do zero. Isso é verdadeiro para valores ímpares e pares de NFFT.

%//Calculate frequency axis
df = fs/NFFT;
fAxis = 0:df:(fs-df);

Se você precisar envolver o espectro de frequências, precisará levar em consideração se possui um NFFT de número ímpar. Sempre precisa haver um componente DC , então. .

df = fs/NFFT;
fAxis = (0:df:(fs-df)) - (fs-mod(NFFT,2)*df)/2;

Observe como o cálculo do eixo de frequência positivo é idêntico ao acima, mas o termo deslocado da FFT muda para acomodar comprimentos pares ou ímpares da FFT.

Esses trechos de código foram extraídos de uma resposta longa publicada no SO (que você pode achar interessante) encontrada aqui: /programming/9694297/matlab-fft-xaxis-limits-messing-up-and-fftshift/ 9699983 # 9699983

learnvst
fonte
Ok, então posso usar isso para NFFT estranho também?
TheGrapeBeyond
Ah desculpa. Vejo a ligeira complicação ao passar de -ve para + ve frequência. Eu mudei a resposta um pouco.
learnvst