使用窗口函数 MATLAB 改善频谱图外观

信息处理 matlab 窗函数 频谱图
2022-01-30 21:43:28

我有一个程序,它使用 surf 函数将在 NI USB DAQ 中获得的数据实时绘制到频谱图上。我想使用某种窗口函数来改善绘图的外观。我的问题是:哪个窗口函数最适合用于此?以及如何实施?这是我当前代码的示例:

fprintf('Initializing DAQ\n');
s = daq.createSession ('ni');
addAnalogInputChannel(s, 'Dev1','ai1', 'Voltage'); 


s.NumberOfScans = Fs*Record_Time;
s.Rate = Fs;
s.Channels.Range = [-1 1];
s.DurationInSeconds = 5;

Spect_nFFT = 2^8;
num_overlap = 19*round(Spect_nFFT/20);
start_sample = 1;

DataRdy = true;
% Run in background session

Lh = s.addlistener('DataAvailable', @(src,event) CaptureData(event.TimeStamps, event.Data));
s.NotifyWhenDataAvailableExceeds = 100000*.1;
s.IsContinuous = true;
s.startBackground();
NFFT = 2^nextpow2(L);
P = zeros(8193,50);
F = Fs/2*linspace(0,1,NFFT/2+1);
g=0;

while g==0

    while DataRdy == 0
        pause(.01)
    end
    pause(.5)

    Min_Threshold = 10^12;

    start_sample = 1;
    NFFT = 2^nextpow2(L); % Next power of 2 from length of myRecording
    FFT_Out = fft(myRecording(start_sample:end),NFFT)/size(myRecording(start_sample:end),1);
    FFT_Out = FFT_Out(1:NFFT/2+1);

    A = sqrt(FFT_Out.*conj(FFT_Out));
    P = [P(:,2:end), sqrt(FFT_Out.*conj(FFT_Out))];
    P(P<=max(max(P))/Min_Threshold)=max(max(P))/Min_Threshold;
    surf(1:size(P,2),F,10*log10(P),'edgecolor','none'); axis tight; 


    % Create updating spectrogram
    view(0,90); 

    xlabel('Time'); 
    ylabel('Hz');


    drawnow;

    DataRdy = 0;
    uicontrol('Style', 'pushbutton', 'String', 'Exit',...
    'Position', [20 20 50 20],...
    'Callback', 'g=g+1');

end
delete(Lh);
stop(s);

谢谢你的帮助!

1个回答

窗口化只不过是信号与窗口函数的逐元素乘法。

假设您要应用汉宁窗。在您的情况下,信号存储在myRecording(start_sample:end).

  • 创建信号长度的窗口值向量:win = hann(length(myRecording(start_sample:end)))
  • 乘以您的信号并将其存储在变量中:sig = win.*size(myRecording(start_sample:end)
  • 执行 FFT,但请记住,现在您不能简单地标准化信号长度(就像您在 FFT 函数中所做的那样),但您应该(非常简单地说)除以窗口值的总和:sum(win). 可能您会注意到,如果没有应用窗口 = 矩形窗口,这也是正确的。

回答您问题的第二部分,选择哪个窗口?您可以从这份出色的白皮书开始(在图 8 中,您有针对不同窗口类型的建议):Windowing: Optimizing FFTs Using Window Functions

在此处输入图像描述

请记住,如果您增加旁瓣衰减,那么您也会使您的主瓣更宽(更差的频率分辨率)。汉宁是一个好的开始。

更多信息可以参考文献:

Harris FJ - 使用离散傅里叶变换进行谐波分析的窗口 Heinzel G. - DFT 的频谱和频谱密度估计

此外,我在您的代码中注意到您正在按样本数量进行归一化,然后只取频谱的前半部分。这完全没问题,但您还必须将幅度乘以 2 以补偿在fs2

如果您有更多疑问,您可以搜索有关开窗和泄漏的问题和答案——您会发现很多。