2016-04-26 304 views
0

我想对歌曲做谱图分析。目前,我从一首歌中获得大约10秒的剪辑,并试图找到当地的山峰。在3D谱图中正确找到MATLAB峰值

我真正想要的是有显示一些N×N的邻居值得幅度

[y,fs] = audioread('audio_file.wav'); 
window = hamming(512); 
num_overlap = 256; 
nfft = 1024; 
[S,F,T,P] = spectrogram(y(:,1), window, num_overlap, nfft, fs, 'yaxis'); 
surf(T,F,10*log10(P), 'edgecolor', 'none'); axis tight; view(0, 90); colormap hot; 

这导致下面的图像中的内局部最大值的散点图:

enter image description here

其中x轴当然是时间[0,〜10],y轴是频率[0,22.5 KHz],z轴是振幅

现在我发誓d喜欢做的是在这个冲浪上创建一个3D散点图来显示峰值的位置。 S,F,T,P的尺寸为
S: 513 x 1770 complex double
F: 513 x 1 double
T: 1 x 1770 double
P: 513 x 1770 double

现在,这是我敢肯定,我做错了什么或不完全了解MATLAB在哪里。

msk = true(3,3,3); 
msk(2,2,2) = false; 
dil = imdilate(10*log10(P), msk); 
M = 10*log10(P) > dil; 

我的理解是,这将让我一个1地方是我的局部峰值是

现在我们只想说,amp = 10*log10(P),我想只能够调用scatter3以同样的方式我叫冲浪,像所以:

scatter3(T, F, amp(M)) 

但当然,我得到X, Y and Z must be vectors of the same length.我想这对我来说很有意义,所以我决定重复值多次,因为他们需要的是得到轴相等。

Tr = repelem(T, 513)'; 
Fr = repelem(F, 1770); 
Zr = reshape(amp, [908010, 1]); 
[pks, locs] = findpeaks(Zr); 
scatter3(Tr(locs), Fr(locs), Zr(locs)); 

这导致3D散点图像这样:

enter image description here

这是绝对不正确的,因为应该有整个所示幅度许多局部峰值。我不确定我做错了什么,但我也几乎肯定有一个更简单的方法来实现我想要的。我真正想要的是有一个散点图,显示某个NxN邻域值振幅的局部最大值

+0

才有可能获得访问该音频剪辑?我希望能够重现您的图表,并帮助您真正绘制您想要的图表。另外,您没有正确指定掩码。你实际上希望中心元素是“真”而不是“假”。这种技术称为**非最大值抑制**,它确保窗口的中心元素是最大值,如果不是,则抑制此点。这正是你想要在“N×N×N”3D元素邻域中找到局部峰值时的情况。 – rayryeng

回答

1

如果我明白你想要的,你有一个矩阵M与本地峰值,你想绘制分散的位置峰。你可以使用sub2ind线性指标使用find和各峰的行\西:

[Fi,Ti] = find(10*log10(P) > dil); 
Pi = sub2ind(size(P),Fi,Ti); 

scatter3(T(Ti),F(Fi),amp(Pi)); 
+0

完美工作,谢谢!我的3x3x3邻域太紧凑了,所以我把它改成了15x15x15 – ZWiki