diff aim-mat/modules/usermodule/pitchstrength/find_pitches2.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/find_pitches2.m	Tue Aug 16 14:37:17 2011 +0100
@@ -0,0 +1,301 @@
+% function [pitchstrength, dominant_time] = find_pitches(profile, , a_priori, fqp_fq)
+%
+%   To analyse the time interval profile of the auditory image
+%
+%   INPUT VALUES:
+%  
+%   RETURN VALUE:
+%
+
+% (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 result = find_pitches(profile,options)
+
+plot_switch =0;
+
+if nargin < 2
+	options=[];
+end
+% 
+
+% peaks must be higher then this of the maximum to be recognised
+ps_threshold=0.1;	
+heighttowidthminimum=0.3;	% height of peak, where the width is measured
+octave_variability=0.35;	% in percent, when the octave is acepted as such
+
+
+
+% preliminary return values.
+result.final_pitchstrength=0;
+result.final_dominant_frequency=0;
+result.final_dominant_time=0;
+result.smoothed_signal=[];
+result.peaks = [];
+
+% change the scaling to logarithm, before doing anything else:
+log_profile=logsigx(profile,0.001,0.035);
+
+
+peak_found=0;
+current_lowpass_frequency=500;
+
+while ~peak_found
+	
+	smooth_sig=lowpass(log_profile,current_lowpass_frequency);
+	envpeaks = IPeakPicker(smooth_sig,0.01);
+	
+	if isempty(envpeaks) % only, when there is no signal
+		return
+	end
+	
+	% finde den peak mit der höchsten Pitschstrength
+	for i=1:length(envpeaks) % construct all maxima
+		where=bin2time(smooth_sig,envpeaks{i}.x);
+		[dummy,height,breit,where_widths]=qvalue(smooth_sig,where,heighttowidthminimum);
+		width=time2bin(smooth_sig,breit);
+		if width>0
+			envpeaks{i}.pitchstrength=height/width;
+		else
+			envpeaks{i}.pitchstrength=0;
+		end
+		envpeaks{i}.width=width;
+		envpeaks{i}.where_widths=where_widths;
+		envpeaks{i}.peak_base_height_y=height*(1-heighttowidthminimum);
+	end
+	
+	% sort all for the highest first!
+	% 	envpeaks=sortstruct(envpeaks,'pitchstrength');
+	envpeaks=sortstruct(envpeaks,'y');
+	
+	if plot_switch
+		figure(2134)
+		clf
+		hold on
+		plot(log_profile,'b')
+		plot(smooth_sig,'g')
+		for i=1:length(envpeaks)
+			time=envpeaks{i}.t;
+			x=envpeaks{i}.x;
+			y=envpeaks{i}.y;
+			plot(x,y,'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',2);
+			time_left=envpeaks{i}.left.t;
+			x_left=envpeaks{i}.left.x;
+			y_left=envpeaks{i}.left.y;
+			time_right=envpeaks{i}.right.t;
+			x_right=envpeaks{i}.right.x;
+			y_right=envpeaks{i}.right.y;
+			plot(x_left,y_left,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
+			plot(x_right,y_right,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
+		end
+		current_time=options.current_time*1000;
+		y=get(gca,'ylim');
+		y=y(2);
+		text(700,y,sprintf('%3.0f ms',current_time),'verticalalignment','top');
+		
+		for i=1:length(envpeaks)
+			pitchstrength=envpeaks{i}.pitchstrength;
+			if i <4
+				line([envpeaks{i}.x envpeaks{i}.x],[envpeaks{i}.y envpeaks{i}.y*(1-heighttowidthminimum)],'Color','r');
+				line([envpeaks{i}.where_widths(1) envpeaks{i}.where_widths(2)],[envpeaks{i}.y*(1-heighttowidthminimum) envpeaks{i}.y*(1-heighttowidthminimum)],'Color','r');
+				x=envpeaks{i}.x;
+				fre=envpeaks{i}.fre;
+				y=envpeaks{i}.y;
+				text(x,y*1.05,sprintf('%3.0fHz: %2.2f',fre,pitchstrength),'HorizontalAlignment','center');
+			end
+		end
+	end
+	
+	% kucke, ob sich das erste Maxima überlappt. Falls ja, nochmal
+	% berechnen mit niedriger Lowpass frequenz
+	nr_peaks=length(envpeaks);
+	if 	nr_peaks==1
+		peak_found=1;
+		continue
+	end
+	xleft=envpeaks{1}.where_widths(1);
+	xright=envpeaks{1}.where_widths(2);
+	for i=2:nr_peaks %
+		xnull=envpeaks{i}.x;
+		if xnull < xleft  && xnull > xright
+			peak_found=0;
+			current_lowpass_frequency=current_lowpass_frequency/2;
+			if current_lowpass_frequency<62.5
+				return
+			end
+			break
+		end
+		% wenn noch hier, dann ist alles ok
+		peak_found=1;
+	end
+end
+
+
+% reduce the peaks to the relevant ones:
+% through out all with pitchstrength smaller then threshold
+count=1;
+min_ps=ps_threshold*envpeaks{1}.pitchstrength;
+for i=1:length(envpeaks)
+	if envpeaks{i}.pitchstrength>min_ps
+		rpeaks{count}=envpeaks{i};
+		count=count+1;
+	end
+end
+
+
+% final result for the full set
+result.final_pitchstrength=rpeaks{1}.pitchstrength;
+result.final_dominant_frequency=rpeaks{1}.fre;
+result.final_dominant_time=rpeaks{1}.t;
+result.smoothed_signal=smooth_sig;
+result.peaks=rpeaks;
+% return
+
+% Neuberechnung der Pitchstrength für peaks, die das Kriterium der 
+% Höhe zu Breite nicht erfüllen
+for i=1:length(rpeaks) % construct all maxima
+	where=bin2time(smooth_sig,rpeaks{i}.x);
+	[dummy,height,breit,where_widths]=qvalue(smooth_sig,where,heighttowidthminimum);
+	width=time2bin(smooth_sig,breit);
+	
+	xleft=where_widths(2);
+	xright=where_widths(1);
+	left_peak=rpeaks{i}.left;
+	right_peak=rpeaks{i}.right;
+	
+	
+	xnull=rpeaks{i}.x;
+	if xleft<left_peak.x || xright>right_peak.x
+		t_xnull=bin2time(smooth_sig,xnull);
+		[val,height,breit,widthvals,base_peak_y]=qvalue2(smooth_sig,t_xnull);
+		width=time2bin(smooth_sig,breit);
+		if width>0
+			rpeaks{i}.pitchstrength=height/width;
+		else
+			rpeaks{i}.pitchstrength=0;
+		end
+		rpeaks{i}.where_widths=time2bin(smooth_sig,widthvals);
+		rpeaks{i}.width=width;
+		rpeaks{i}.peak_base_height_y=base_peak_y;
+	end
+end
+
+% sort again all for the highest first!
+% rpeaks=sortstruct(rpeaks,'pitchstrength');
+
+% return
+%%%%%%  look for octave relationships
+% 
+% 
+for i=1:length(rpeaks) % construct all maxima
+	% look, if the octave of the pitch is also present.
+	fre=rpeaks{i}.fre;
+	has_octave=0;
+	for j=1:length(rpeaks)
+		oct_fre=rpeaks{j}.fre;
+		% is the octave there?
+		if oct_fre > (2-octave_variability)*fre && oct_fre < (2+octave_variability)*fre
+			rpeaks{i}.has_octave=oct_fre;
+			rpeaks{i}.octave_peak_nr=j;
+				
+			% add the pss
+% 			rpeaks{j}.pitchstrength=rpeaks{i}.pitchstrength+rpeaks{j}.pitchstrength;
+
+			ps_real=rpeaks{j}.pitchstrength;
+			ps_oct=rpeaks{i}.pitchstrength;
+			hight_oct=rpeaks{j}.y;
+			hight_real=rpeaks{i}.y;
+			
+% 			if ps_oct>ps_real && hight_oct > hight_real
+% 				rpeaks{i}.pitchstrength=ps_real-1;	% artificially drop down
+% 			end
+
+			has_octave=1;
+			break
+		end
+		if ~has_octave
+			rpeaks{i}.has_octave=0;
+			rpeaks{i}.octave_peak_nr=0;
+		end
+	end
+end
+
+if plot_switch
+	figure(2134)
+	clf
+	hold on
+	plot(log_profile,'b')
+	plot(smooth_sig,'g')
+	for i=1:length(rpeaks)
+		time=rpeaks{i}.t;
+		x=rpeaks{i}.x;
+		y=rpeaks{i}.y;
+		plot(x,y,'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',2);
+		time_left=rpeaks{i}.left.t;
+		x_left=rpeaks{i}.left.x;
+		y_left=rpeaks{i}.left.y;
+		time_right=rpeaks{i}.right.t;
+		x_right=rpeaks{i}.right.x;
+		y_right=rpeaks{i}.right.y;
+		plot(x_left,y_left,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
+		plot(x_right,y_right,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
+	end
+	current_time=options.current_time*1000;
+	y=get(gca,'ylim');
+	y=y(2);
+	text(700,y,sprintf('%3.0f ms',current_time),'verticalalignment','top');
+	
+	for i=1:length(rpeaks)
+		pitchstrength=rpeaks{i}.pitchstrength;
+		if i <10
+			line([rpeaks{i}.x rpeaks{i}.x],[rpeaks{i}.y rpeaks{i}.peak_base_height_y],'Color','m');
+			line([rpeaks{i}.where_widths(1) rpeaks{i}.where_widths(2)],[rpeaks{i}.peak_base_height_y rpeaks{i}.peak_base_height_y],'Color','m');
+			x=rpeaks{i}.x;
+			fre=rpeaks{i}.fre;
+			y=rpeaks{i}.y;
+			text(x,y*1.05,sprintf('%3.0fHz: %2.2f',fre,pitchstrength),'HorizontalAlignment','center');
+		end
+	end
+end
+if plot_switch==1
+	for i=1:length(rpeaks)
+		x=rpeaks{i}.x;
+		y=rpeaks{i}.y;
+		plot(x,y,'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',6);
+		
+		% plot the octaves as green lines
+		octave=rpeaks{i}.has_octave;
+		fre=rpeaks{i}.fre;
+		if octave>0
+			oct_nr=rpeaks{i}.octave_peak_nr;
+			oct_fre=rpeaks{oct_nr}.fre;
+			
+			x=rpeaks{i}.x;
+			oct_x=rpeaks{oct_nr}.x;
+			y=rpeaks{i}.y;
+			oct_y=rpeaks{oct_nr}.y;
+			line([x oct_x],[y oct_y],'Color','g','LineStyle','--');
+		end
+	end
+end
+
+% rpeaks=sortstruct(rpeaks,'pitchstrength');
+rpeaks=sortstruct(rpeaks,'y');
+
+% final result for the full set
+result.final_pitchstrength=rpeaks{1}.pitchstrength;
+result.final_dominant_frequency=rpeaks{1}.fre;
+result.final_dominant_time=rpeaks{1}.t;
+result.smoothed_signal=smooth_sig;
+result.peaks=rpeaks;
+
+
+
+
+function fre=x2fre(sig,x)
+t_log = bin2time(sig,x);
+t=f2f(t_log,0,0.035,0.001,0.035,'linlog');
+fre=1/t;