我正在尝试使用 MATLAB 查找钢琴录音中存在的基本频率。这些是我遵循的步骤;
找到信号的包络
找到音符开始
在每次发作之间执行 FFT
谐波产物谱。
当我尝试实现 HPS 算法时,我遇到了“尺寸不一致”错误。这是我使用的全部代码。
[song,FS] = wavread('C major.wav');
%sound(song,FS);
P = 20000;
N=length(song); % length of song
t=0:1/FS:(N-1)/FS; % define time period
song = sum(song,2);
song=abs(song);
% Plot time domain signal
figure(1);
subplot(2,1,1)
plot(t,3*song)
title('Wave File')
ylabel('Amplitude')
xlabel('Length (in seconds)')
%ylim([-1.1 1.1])
xlim([0 N/FS])
%----------------------Finding the envelope of the signal-----------------%
% Gaussian Filter
x = linspace( -1, 1, P); % create a vector of P values between -1 and 1 inclusive
sigma = 0.335; % standard deviation used in Gaussian formula
myFilter = -x .* exp( -(x.^2)/(2*sigma.^2)); % compute first derivative, but leave constants out
myFilter = myFilter / sum( abs( myFilter ) ); % normalize
% Plot Gaussian Filter
subplot(2,1,2)
plot(myFilter)
title('Edge Detection Filter')
% fft convolution
myFilter = myFilter(:); % create a column vector
song(length(song)+length(myFilter)-1) = 0; %zero pad song
myFilter(length(song)) = 0; %zero pad myFilter
edges =ifft(fft(song).*fft(myFilter));
tedges=edges(P:N+P-1); % shift by P/2 so peaks line up w/ edges
tedges=tedges/max(abs(tedges)); % normalize
%---------------------------Onset Detection-------------------------------%
% Finding peaks
maxtab = [];
mintab = [];
x = (1:length(tedges));
min1 = Inf;
max1 = -Inf;
min_pos = NaN;
max_pos = NaN;
lookformax = 1;
for i=1:length(tedges)
peak = tedges(i:i);
if peak > max1,
max1 = peak;
max_pos = x(i);
end
if peak < min1,
min1 = peak;
min_pos = x(i);
end
if lookformax
if peak < max1-0.001
maxtab = [maxtab ; max_pos max1];
min1 = peak;
min_pos = x(i);
lookformax = 0;
end
else
if peak > min1+0.005
mintab = [mintab ; min_pos min1];
max1 = peak;
max_pos = x(i);
lookformax = 1;
end
end
end
% % Plot song filtered with edge detector
figure(2)
plot(1/FS:1/FS:N/FS,tedges)
title('Song Filtered With Edge Detector 1')
xlabel('Time (s)')
ylabel('Amplitude')
ylim([-1 1.1])
xlim([0 N/FS])
hold on;
plot(maxtab(:,1)/FS, maxtab(:,2), 'ro')
plot(mintab(:,1)/FS, mintab(:,2), 'ko')
max_col = maxtab(:,1);
peaks_det = max_col/FS;
No_of_peaks = length(peaks_det);
[song,FS] = wavread('C major.wav');
%---------------------------Performing STFT--------------------------------%
h = 1;
for i = 2:No_of_peaks
song_seg = song(max_col(i-1):max_col(i)-1);
L = length(song_seg);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
seg_fft = fft(song_seg,NFFT);%/L;
U = size(seg_fft,1)
% In harmonic prodcut spectrum, you downsample the fft data several times and multiply all those with the original fft data to get the maximum peak.
%HPS
seg_fft = seg_fft(1 : size(seg_fft,1)/2 );
seg_fft = abs(seg_fft);
%HPS: downsampling
for i = 1:length(seg_fft)
seg_fft2(i,1) = 1;
seg_fft3(i,1) = 1;
seg_fft4(i,1) = 1;
% seg_fft5(i,1) = 1;
end
for i = 1:floor((length(seg_fft)-1)/2)
seg_fft2(i,1) = (seg_fft(2*i,1) + seg_fft((2*i)+1,1))/2;
end
for i = 1:floor((length(seg_fft)-2)/3)
seg_fft3(i,1) = (seg_fft(3*i,1) + seg_fft((3*i)+1,1) + seg_fft((3*i)+2,1))/3;
end
for i = 1:floor((length(seg_fft)-3)/4)
seg_fft4(i,1) = (seg_fft(4*i,1) + seg_fft((4*i)+1,1) + seg_fft((4*i)+2,1) + seg_fft((4*i)+3,1))/4;
end
%HPS, PartII: calculate product
p1 = (seg_fft3) .* (seg_fft4);
p2 = p1.* (seg_fft2);
p3 = p2.* (seg_fft);
HPS, PartIII: find max
[f_y1,I] = max(p3)
for c = 1 : length(p3)
if(p3(c,1) == f_y1)
index = c;
end
end
% Convert that to a frequency
f_y(h) = (index / NFFT) * FS;
h=h+1;
f_y = abs(f_y)';
end
在实现seg_fftp3 = p2.* (seg_fft);
的大小之前,seg_fft2、seg_fft3、seg_fft4都具有相同的尺寸16384 1。然后,当我将更改p3 = p2.* (seg_fft);
的大小实现为8192 1而其余的大小保持在16384 1时,由于尺寸不同,因此导致乘法错误。seg_fft
我真的很困惑为什么这种情况不断发生,而我尝试的任何事情似乎都没有成功。真的很感谢这里的一些帮助......如果有人可以修复这段代码,那将是一个很大的帮助......提前谢谢......我真的很绝望......