diff aim-mat/modules/usermodule/pitchstrength/PeakPicker.m @ 4:537f939baef0 tip

various bug fixes and changed copyright message
author Stefan Bleeck <bleeck@gmail.com>
date Tue, 16 Aug 2011 14:37:17 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aim-mat/modules/usermodule/pitchstrength/PeakPicker.m	Tue Aug 16 14:37:17 2011 +0100
@@ -0,0 +1,146 @@
+%  
+% function out = PeakPicker(sig_in, params)
+%
+%   Find the peaks of a signal
+%
+%   INPUT VALUES:
+%       sig_in                  Input signal
+%       params.dyn_thresh       dynamic threshold. Off if not used
+%       params.smooth_sigma     sigma for smoothing
+%                               
+%       
+% 		
+%
+%   RETURN VALUE:
+%       out is an array of a struct
+%       out.x                    x position of the Peak
+%       out.t                    according time value
+%		out.y                    y value of the peak
+%       out.left.[x,t,y]         left Minumum
+%       out.right.[x,t,y]        right Minumum
+% 
+% (c) 2003, University of Cambridge, Medical Research Council 
+% Christoph Lindner 
+% (c) 2011, University of Southampton
+% Maintained by Stefan Bleeck (bleeck@gmail.com)
+% download of current version is on the soundsoftware site: 
+% http://code.soundsoftware.ac.uk/projects/aimmat
+% documentation and everything is on http://www.acousticscale.org
+
+function out = PeakPicker(sig_in, params)
+
+if nargin<2
+    params=[];
+end
+
+% % % % ----- Other Parameters -----
+% % % % Lowpass param for the higpassfilter
+% % % LP_sigma_for_HP_filter = getnrpoints(sig_in)/7;
+% % % LP_sigma_for_smooth = 3;
+% % % % min width of a peak: upper_threshold+lower_thresh
+% % % upper_thresh =  0.02*getnrpoints(sig_in);
+% % % lower_thresh =  0.03*getnrpoints(sig_in);
+
+% x is index or position in vector
+% y is value of the
+% t is the time domain wich is assigned to the x dimension
+
+% the original values befor filtering
+orig_values = getdata(sig_in)';
+
+if isfield(params,'smooth_sigma') 
+    if (params.smooth_sigma~=0)
+        % smooth the curve to kill small side peaks 
+        sig_in = smooth(sig_in, params.smooth_sigma);
+    end
+end
+
+values=getdata(sig_in)';
+
+% ------------------- Find the local maxima ------------------------------
+% find x positions of ALL local maxima, incl. zero!!
+max_x = find((values >= [0 values(1:end-1)]) & (values > [values(2:end) 0]));
+if isfield(params,'smooth_sigma') 
+    if (params.smooth_sigma~=0)
+        % smoothing might have shifted the positions of maxima.
+        % Therefore the maximum is the highest of the neighbours in
+        % distance +- smooth_sigma
+        for i=1:length(max_x)
+            start = max_x(i)-params.smooth_sigma;
+            if start<1
+                start=1;
+            end
+            stop = max_x(i)+params.smooth_sigma;
+            if stop>length(orig_values)
+                stop=length(orig_values);
+            end
+            m = find(orig_values(start:stop) == max(orig_values(start:stop)));
+            m=m(1);
+            max_x(i)=start-1+m;
+        end
+    end
+end
+max_y = orig_values(max_x);
+orig_max_y = orig_values(max_x);
+
+% ------------------- Find the local minima -----------------------------
+min_x = find((values < [inf values(1:end-1)]) & (values <= [values(2:end) inf]));
+min_y = values(min_x);
+
+
+% peakpos_x=zeros(1,length(max_x));
+peakpos_x=[];
+for i=1:length(max_x),
+    % only take the highest peak 
+    my = [max_y==max(max_y)];  % find the highest peak
+%     peakpos_x(i) = max_x(my);   % x pos of highest peak
+    peakpos_x = [peakpos_x max_x(my)]; 
+    max_y = max_y([max_y<max(max_y)]);   % del max value in y domain
+    max_x = max_x([max_x ~= peakpos_x(end)]); % and in x domain
+end
+peakpos_y = orig_values(peakpos_x);  % extract the y vector 
+
+% --------------- Dynamic Threshold ---------------------
+% works relativ to the mean
+if isfield(params,'dyn_thresh') 
+    if (params.dyn_thresh~=0)
+        % dynamic thresholding 
+        m = mean(orig_values);  
+        dthr = params.dyn_thresh.*m;
+        peakpos_x = peakpos_x([peakpos_y>=dthr]);
+        peakpos_y = peakpos_y([peakpos_y>=dthr]);
+    end
+end
+
+maxima = cell(1, length(peakpos_x));
+% find the left end right minima that belong to a maximum
+for i=1:length(peakpos_x)
+    maxima{i}.x = peakpos_x(i);
+    maxima{i}.t = bin2time(sig_in, maxima{i}.x);
+    maxima{i}.y = orig_values(peakpos_x(i));
+    
+    % find left and right minimum for this maximum
+    maxima{i}.left.x = max(min_x([min_x < maxima{i}.x]));
+    if isempty(maxima{i}.left.x)
+        maxima{i}.left.x = 1;
+        maxima{i}.left.t = 0;
+        maxima{i}.left.y = orig_values(maxima{i}.left.x);
+    else
+        maxima{i}.left.y = orig_values(maxima{i}.left.x);
+        maxima{i}.left.t = bin2time(sig_in, maxima{i}.left.x);
+    end
+    maxima{i}.right.x = min(min_x([min_x > maxima{i}.x]));
+    if isempty(maxima{i}.right.x)
+        maxima{i}.right.x = length(orig_values);
+        maxima{i}.right.t = 0;
+        maxima{i}.right.y = orig_values(maxima{i}.right.x);
+    else
+        maxima{i}.right.y = orig_values(maxima{i}.right.x);
+        maxima{i}.right.t = bin2time(sig_in, maxima{i}.right.x);
+    end
+end
+
+
+out = maxima;
+
+