0

I'm trying to create a GUI on MATLAB that will automatically transcribe piano music when a .wav file is given as an input. Before using GUI I created the whole algorithm using MATLAB and it worked just fine.

Now when I create the GUI and transfer the codings there, my onset (peak) detection produces wrong results as the envelope of my signal is not as smooth as how it was when run using matlab script.

Onsets before using GUI

Onset Detection after when using GUI

As you can see the envelope is pretty much smooth when used normally rather than when using GUI. Due to these peaks are detected all over the slope as well and not just at the actal peaks.

This is the code I used to build the algorithm:

[song,FS] = wavread('C major.wav');

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);

%----------------------Finding the envelope of the signal-----------------%
% Gaussian Filter
w = 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 = -w .* exp( -(w.^2)/(2*sigma.^2));  % compute first derivative, but leave constants out
myFilter = myFilter / sum( abs( myFilter ) ); % normalize

% 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 = [];
j = (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 = j(i); 
  end
  if peak < min1, 
      min1 = peak;
      min_pos = j(i); 
  end

  if lookformax
    if peak < max1-0.09
      maxtab = [maxtab ; max_pos max1];
      min1 = peak; 
      min_pos = j(i);
      lookformax = 0;
    end  
  else
    if peak > min1+0.08
      mintab = [mintab ; min_pos min1];
      max1 = peak; 
      max_pos = j(i);
      lookformax = 1;
    end
  end
end
% % Plot song filtered with edge detector          
         figure(4)
         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')

And this is what I included in the GUI script:

[FileName,PathName] = uigetfile({'*.wav'},'Load Wav File');
[x,Fs] = wavread([PathName '/' FileName]);

N = length(x);
handles.x = sum(x,2);
handles.x = x./max(abs(x));
handles.Fs = Fs;

%Gaussian Edge detection filter
P = 20000;
w = 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 = -w .* exp( -(w.^2)/(2*sigma.^2));  % compute first derivative, but leave constants out
myFilter = myFilter / sum( abs( myFilter ) ); % normalize
axes(handles.axes3);
plot(myFilter)

%Peak detection
myFilter = myFilter(:);                         % create a column vector
x(length(x)+length(myFilter)-1) = 0;      %zero pad song
myFilter(length(x)) = 0;                     %zero pad myFilter
edges =ifft(fft(x).*fft(myFilter));

tedges=edges(P:N+P-1);                      % shift by P/2 so peaks line up w/ edges
tedges=tedges/max(abs(tedges));                 % normalize

maxtab = [];
mintab = [];
j = (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 = j(i); 
  end
  if peak < min1, 
      min1 = peak;
      min_pos = j(i); 
  end

  if lookformax
    if peak < max1-0.09
      maxtab = [maxtab ; max_pos max1];
      min1 = peak; 
      min_pos = j(i);
      lookformax = 0;
    end  
  else
    if peak > min1+0.08
      mintab = [mintab ; min_pos min1];
      max1 = peak; 
      max_pos = j(i);
      lookformax = 1;
    end
  end
end

axes(handles.axes4);
plot(1/Fs:1/Fs:N/Fs,tedges)
axis([0 N/Fs -1 1.1]);

What am I doing wrong here?? Really appreciate if someone could help me out here. Thanx in advance...

Björn Lindqvist
  • 19,221
  • 20
  • 87
  • 122
user2482542
  • 361
  • 2
  • 14
  • 26
  • Try using the comparison view in the Matlab editor. If the result is different, the code must be different. Open both functions/scripts in the editor, use Tools->Compare Against and check where there are differences. Or - this would generally be the proper way - change your code to become one (now two, that "should" be doing the same) function, that takes a filename as input. This will eliminate to need to spot differences in your two versions.. – sebastian Nov 14 '13 at 11:40
  • The above should read "not two" instead of "now two"... °° – sebastian Nov 14 '13 at 11:51
  • Well apparently the code seems to be the same. Things go wrong when implementing `edges =ifft(fft(x).*fft(myFilter));` They give different values in the editor and the GUI... – user2482542 Nov 14 '13 at 12:14
  • Well, then `x` or `myFilter` must be different – sebastian Nov 14 '13 at 12:27
  • Apparently its `x`. In my original code once i take the `abs(song)` all the song values are positive. but in GUI all the `x`(which happens to be "song") values have negative as well as positive values, while the magnitudes are the same as the `song` values in the original code.... – user2482542 Nov 14 '13 at 12:32
  • Well, in the original code there is `abs(song)` but in the GUI there's no equivalent `abs(x)` line that I can see. Instead you have `x./max(abs(x))`. So it's not surprising that there are negative values remaining in x. – nkjt Nov 14 '13 at 12:43
  • See that's the thing. I did try `abs(x)` but it still gives me positive and negative values... which seems to be weird because when I plot the time domain signal it does in fact plot the abs values(the graph is above zero).. – user2482542 Nov 14 '13 at 12:45

0 Answers0