0

MATLAB を使用して、ピアノの録音に存在する基本周波数を見つけようとしています。これらは私が従った手順です。

  1. 信号のエンベロープを見つける

  2. 音符の始まりを見つける

  3. 各オンセット間で FFT を実行する

  4. 高調波積スペクトル。

「次元が一致しません」というエラーに直面するのは、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_fft、seg_fft2、seg_fft3、seg_fft4p3 = p2.* (seg_fft);のサイズを実装する前は、すべて16384 1という同じサイズです。次に、残りのサイズが16384 1のままである間に変更のサイズを8192 1に実装すると、寸法が同じではないため、乗算でエラーが発生します。p3 = p2.* (seg_fft);seg_fft

なぜこれが起こり続け、私が試したことがうまくいかないように見えるのか、私は本当に混乱しています. ここでいくつかの助けを本当に本当に感謝します...誰かがこのコードを修正できれば、それは大きな助けになるでしょう...前もって感謝します..私はここで本当に必死です......

4

0 に答える 0