1

我试图在 MATLAB 中使用 plot3 绘制 STFT,但失败了。有人可以指导我怎么做吗?我的 MWE 如下所示:

%% STFT Computataion
clear; clc; clf;

%% Get input and calculate frame size and overlap/shift
[Y,Fs]=wavread('D_NEHU_F0001_MN_10001');
frame_size=round(20*Fs/1000);         % calculate frame size for 20ms
frame_shift=round(10*Fs/1000);        % calculate frame shift for 10ms

%% Plot the input signal in time domain
t=1/Fs:1/Fs:(length(Y)/Fs);
subplot(2,1,1)
    plot(t,Y);
    title('Speech signal in time domain');
    ylabel('Magnitude of samples');
    xlabel('time in seconds');

%% Calculation of STFT
%NoOfFrames=floor((length(Y)/frame_shift)-1);
NoOfFrames=length(Y)-frame_size;
j=1;
%for i=1:frame_shift:(length(Y)-frame_size)
for i=1:frame_shift:((length(Y)-frame_size))%+frame_shift)
    sp_frame=Y(i:(i+frame_size)).*hamming(frame_size+1);
    sp_frame_dft=abs(fft(sp_frame)); % Compute STFT
    sp_frame_array(:,j)=sp_frame_dft;
    j=j+1;
end

%% Plot the STFT in 3D
[rows,cols]=size(sp_frame_array);
F=linspace(1/Fs,Fs/2000,cols);
T=1/Fs:(frame_shift*Fs/1000):(cols*(frame_shift*Fs/1000));
Z=1:frame_size+1;
subplot(2,1,2)
    %mesh(sp_frame_array);
    %surf(sp_frame_array,'EdgeColor','none');
   plot3(T,F,sp_frame_array);
4

1 回答 1

2

我不确定你的问题到底是关于什么的,但我想问题是,使用提供的代码,你不会得到一个类似于你得到的情节,比如说,用surf.

此外,我也不太清楚你为什么要使用plot3,也许是为了得到时间和频率的标签吧?你可以这样做surf

surf(T, F, sp_frame_array,'EdgeColor','none');

事实上,你plot3没有给出相同数字的原因是因为 的参数plot3必须是三个相同大小的矩阵(检查它help plot3)。根据我的测试,您的代码实际上应该在 Matlab 上被破坏,但事实并非如此。好吧,Matlab 又一次允许人们在没有警告的情况下乱搞(去 Python!:D)......无论如何,尝试将矩阵设置为更像以下内容:

F=linspace(1/Fs,Fs/2000, rows); % note: has to be rows, not cols here!
Fmat = F(:) * ones(1,cols); % or use repmat
T=1/Fs:(frame_shift*Fs/1000):(cols*(frame_shift*Fs/1000));
Tmat = ones(rows,1) * T(:)';

plot3(Tmat,Fmat,sp_frame_array);

虽然这通常会产生更符合我在绘制频谱图时所期望的东西,但我仍然会发表一些评论:

  • 由于您填写的方式,您的F向量应该上升到。更具体地说,它应该从 0Hz 变为:Fssp_frame_dftFs - Fs/rows

    F = linspace(0,Fs*(1-1/rows)/1000,rows); % in kHz
    
  • 您可能希望以 dB 为单位绘制幅度:

    plot3(Tmat,Fmat,db(sp_frame_array));
    

情节3结果

  • plot3每列提供的矩阵绘制一条线。这意味着可能要画很多线!正如@atul-ingle 所问,你确定这是你想要的吗?也许waterfall会以更低的成本提供更好的渲染?

    waterfall(T,F,db(sp_frame_array));
    

瀑布结果

好吧,你会得到行的行,而不是列,所以如果后者是你想要的,你可能需要转置。

  • 您可能还更喜欢仅可视化矩阵的前半部分(因为高于 Fs/2 的频率只是矩阵另一半的镜像)。

希望有帮助!

于 2013-01-27T21:07:35.147 回答