这是我想象的那种情节。
https://de.mathworks.com/help/matlab/ref/waterfall.html
好的,我不想解释太多,我的代码是如何工作的。这需要太多时间。只需自己尝试第二个代码。拿你能找到的任何小wav文件。编译代码时,您可以看到三个频段,并看到每30ms绘制一个频谱。如果您对我的代码有一个具体的问题,它是如何工作的,请在评论中问我。
我希望每个频谱,至少从一个频段,在三维图中绘制它。简而言之,第一个光谱的坐标是什么,第二个,第三个,第四个等等。 我的时间段是fft应用,长度为30毫秒。 x轴上的第一个点是30 ms,下一个是60 ms,下一个是90 ms,依此类推。 30ms的y坐标是多少?这将在频率轴或y轴上。 z轴将是某个时间点(或在给定的滑动窗口帧)的频率分量之外的幅度。 我该怎么做?我怎么写呢?我在这件事上遇到了大麻烦。而且由于每种解释都使用另一种语言,因此对我来说更难。
你可能知道,我有一个音频文件(音乐),我在其上计算STFT。我想要想象它。请参阅我的代码中的以下说明。阅读评论!
我的第一个想法就是使用函数“mesh”或类似的东西。
这是我的网格代码:
X=1:10;
Y=1:15;
Z = [];
% Here i would define the number of time segments
% See the next following code, to understand, what i mean.
for i = 1:length(X)
% Here in this line, i want to compute my short fft
%
% number of frequencies
for j = 1: length(Y)
Z(j,i) = 1.0/(i*j);
end
end
mesh(X,Y,Z)
这段代码给我画了一个网格,我只是想知道自己是如何工作的。无论如何请注意,我很确定我不知道,“网格”功能如何发挥最大作用,但我认为,我理解其中的大部分内容。 我需要提到的另一件事是,我在下面的代码中定义了频段。我这样做了,因为我注意到,我的振幅非常高,范围从1到1000Hz,这就是为什么我定义了3个频段。没有必要绘制所有这些,但我想要想象至少一个。不能从音频信号中可视化整个频率范围,而只能看到特定选择的频段。
%% MATLAB
%_________________________________________
[y,fs]=audioread('dontstopmenow.wav');
% audioread = Read WAV-file
% y = Vector, which contains audio signal
% fs = Sample Rate
% 'dontstopmenow' = WAV-file
%_________________________________________
%PARAMETER FOR STFT
%_________________________________________
t_seg=0.03; % Length of segment in ms
fftlen = 4096; %FFT-Points
%Defining the length of my frequency bands
f_LOW= 1:200; % contain lower frequencies
f_MEDIUM= 201:600; % contain medium frequencies
f_HIGH= 601:1000; % contain higher frequencies
%_______________________________________________________
segl =floor(t_seg*fs);
% Length of segment, on which we use the fft
% "floor" rounds off the result
windowshift=segl/2;
% size of window which goes to the next segment
window=hann(segl);
%hann function
window=window.';
% From a row vector to a column vector
si=1;
%Start index
ei=segl;
%End index
N= length(y)/windowshift - 1;
% Number of time segements in audio signal
f1=figure;
% New window
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
% frequency vector
Ya=zeros(1,fftlen);
%Plotting time segments!
for m= 1:1:N
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
Ya=abs(Ya(1:end/2));
%One-sided-spectrum
drawnow; %Updates graphical objects
figure(f1);
plot(f(1:end/2), 20*log10(Ya));
%STFT __ plots the whole audio signal after a stft, every 30ms
%% L,M,H - Bands
subplot(3,1,1)
y_low = Ya(f_LOW);
plot(f_LOW,y_low);
ylim([-20 60]);
title('Spektrum (LOW)');
xlabel('f(Hz)');
ylabel('dB');
grid on
subplot(3,1,2)
y_medium = Ya(f_MEDIUM);
plot(f_MEDIUM,y_medium);
ylim([-20 30]);
title('Spektrum (MEDIUM)');
xlabel('f(Hz)');
ylabel('dB');
grid on
subplot(3,1,3)
y_high = Ya(f_HIGH);
plot(f_HIGH,y_high);
ylim([-20 30]);
title('Spektrum (HIGH)');
xlabel('f(Hz)');
ylabel('dB');
grid on;
si=si+windowshift;
% start index updated
ei=ei+windowshift;
% end index updated
end
答案 0 :(得分:0)
以下是您可以添加到代码中以生成瀑布图的语句列表:
让我们将所有STFT输出存储在名为Yb
的矩阵中。首先,通过在for循环之前添加此行来分配内存。
Yb = NaN(N, fftlen/2);
接下来,在for循环中,保存每个段的fft结果。这可以通过在完成Ya
的计算(在drawnow
之前)之后添加以下行来完成。
Yb(m,:) = Ya;
现在您已准备好生成瀑布图。这可以通过在for循环结束后添加以下代码来完成。
figure;
waterfall(f(f_LOW), (1:N)*windowshift/fs, Yb(:,f_LOW));
xlabel('Frequency (Hz)');
ylabel('Time (s)');
希望这能达到你想要的效果。
以下与主要问题无关:我还提出以下建议以改进代码的其他方面:
(1)频率网格f
的计算具有小的缩放误差。它应该是:
f=f/fftlen*fs;
(2)根据您使用的WAV文件,您的代码可能会在windowshift
和N
中获得小数值,但它们都需要是整数。因此,在计算它们时使用适当的舍入方法。我建议如下:
windowshift = round(segl/2);
N = floor(length(y)/windowshift);
(3)在for循环中,您只绘制整个fft以立即覆盖子图。该行应删除。