view 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 source
% 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;