我有关于我使用自动关联的音轨的信息(20,000帧数据):
[r,lags] = xcorr(XX,XX,'biased');
它看起来像这样:
alt text http://a.imageshack.us/img809/3775/plot.jpg
希望到目前为止这么好。理想情况下,我希望能够获取与第二个峰值的最高部分相对应的帧编号。我已经阅读并尝试了大量不同的方法,但我似乎无法让它为我检索信息。
是否有人能够阐明我必须做的事情?
非常感谢!
EDIT1:
我尝试过使用findpeaks
,但它似乎对我不起作用。我不确定是不是因为我使用的是错误的数据。
edit2:我正在测试一种方法,只在这个音频轨道上使用,但很快我想扩展它,以便我可以在整个文件目录上执行此方法,所以我需要一个可以检测峰值而不是自己查找信息的脚本。
edit3:我的.M文件:
[y, fs, nb] = wavread('Three.wav'); %# Load the signal into variable y
frameWidth = 441; %# 10ms
numSamples = length(y); %# Number of samples in y
numFrames = floor(numSamples/frameWidth); %# Number of full frames in y
energy = zeros(1,numFrames); %# Initialize energy
startSample = zeros(1,numFrames); %# Initialize start indices
endSample = zeros(1,numFrames); %# Initialize end indices
for frame = 1:numFrames %# Loop over frames
startSample(frame) = (frame-1)*frameWidth+1; %# Starting index of frame
endSample(frame) = frame*frameWidth; %# Ending index of frame
frameIndex = startSample(frame):endSample(frame); %# Indices of frame samples
energy(frame) = sum(y(frameIndex).^2); %# Calculate frame energy
end %# End loop
XX = filtfilt(ones(1,10)/10, 1, energy); %# Smooths signal
[r,lags] = xcorr(XX,XX,'biased'); %# Auto-correlates the data
plot(lags,r), xlabel('lag'), ylabel('xcorr') %# Plots data
答案 0 :(得分:5)
修改强>:
%# load the signal
[y, fs, nb] = wavread('Three.wav');
y = mean(y,2); %# stereo, take avrg of 2 channels
%# Calculate frame energy
fWidth = round(fs*10e-3); %# 10ms
numFrames = floor(length(y)/fWidth);
energy = zeros(1,numFrames);
for f=1:numFrames
energy(f) = sum( y((f-1)*fWidth+1:f*fWidth).^2 );
end
%# smooth the signal (moving average with window size = 1% * length of data)
WINDOW_SIZE = round(length(energy) * 0.01); %# 200
XX = filtfilt(ones(1,WINDOW_SIZE)/WINDOW_SIZE, 1, energy);
%# auto-correlation
[r,lags] = xcorr(XX, 'biased');
%# find extrema points
dr = diff(r);
eIdx = find(dr(1:end-1) .* dr(2:end) <= 0) + 1;
[~,loc] = sort(r(eIdx), 'descend');
loc = loc(1:min(3,end)); %# take the highest 3 values
%# plot
plot(lags,r), hold on
plot(lags(eIdx), r(eIdx), 'g*')
plot(lags(eIdx(loc)), r(eIdx(loc)), 'ro')
hold off, xlabel('lag'), ylabel('xcorr')
和对应于标记峰的滞后值:
>> lags( eIdx(loc) )
ans =
0 -6316 6316
请注意,我们在计算自相关函数的导数之前平滑了信号,以便找到extrema points
答案 1 :(得分:1)
答案 2 :(得分:1)
如果您有信号处理工具箱,我认为findpeaks功能应该为您完成工作。
类似的东西:
th = x //(some value that will overlook noise in the data. See the documentation)
[peaks locs] = findpeaks(a,'threshold',th)
http://www.mathworks.com/access/helpdesk/help/toolbox/signal/findpeaks.html
我习惯在图像强度数据上使用它,它没有像你的数据那么多的局部方差(那些“厚”的情节部分只是很多数据点快速上下移动,正确?)。您可能需要首先平滑数据以使其工作。
答案 3 :(得分:1)
作为第一步,您应该使用xcorr
的第二个输出参数来使图中的单位正确:
Fs = length(data)./T; % or replace with whatever your sample frequency is (44.1 kHz?)
[a,lags] = xcorr(data,data,'biased');
plot(lags./Fs,a);
现在,您可以使用自己喜欢的方法来获得第二个峰值的延迟;如果您只需要执行一次,图中的数据资源管理器按钮就可以执行。如果您需要反复执行此操作,我认为没有办法避免进入findpeaks
或类似情况。
答案 4 :(得分:1)
你可以使用findpeaks两次。首先得到峰值的初始估计值,并使用该结果微调第二次调用的输入参数到findpeaks。从问题看,您似乎想要计算音高值。 这是代码:
maxlag = fs/50;
r = xcorr(x, maxlag, 'coeff');
r_slice = r(ceil(length(r)/2) : length(r));
[pksh,lcsh] = findpeaks(r_slice);
if length(lcsh) > 1
short = mean(diff(lcsh));
else
short = lcsh(1)-1;
end
[pklg,lclg] = findpeaks(r_slice,'MinPeakDistance',ceil(short),'MinPeakheight',0.3);
if length(lclg) > 1
long = mean(diff(lclg));
else
if length(lclg) > 0
long = lclg(1)-1;
else
long = -1;
end
end
if long > 0
pitch = fs / long; % fs is sample rate in Hertz
以上是给定here的代码的修改版本。