bleeck@4
|
1 % function [pitchstrength, dominant_time] = analyse_timeinterval_profile(ti_profile, peaks, a_priori, fqp_fq)
|
bleeck@4
|
2 %
|
bleeck@4
|
3 % To analyse the time interval profile of the auditory image
|
bleeck@4
|
4 %
|
bleeck@4
|
5 % INPUT VALUES:
|
bleeck@4
|
6 %
|
bleeck@4
|
7 % RETURN VALUE:
|
bleeck@4
|
8 %
|
bleeck@4
|
9
|
bleeck@4
|
10 % (c) 2011, University of Southampton
|
bleeck@4
|
11 % Maintained by Stefan Bleeck (bleeck@gmail.com)
|
bleeck@4
|
12 % download of current version is on the soundsoftware site:
|
bleeck@4
|
13 % http://code.soundsoftware.ac.uk/projects/aimmat
|
bleeck@4
|
14 % documentation and everything is on http://www.acousticscale.org
|
bleeck@4
|
15
|
bleeck@4
|
16 function result = analyse_timeinterval_profile(ti_profile,options)
|
bleeck@4
|
17
|
bleeck@4
|
18 if nargin < 2
|
bleeck@4
|
19 options=[];
|
bleeck@4
|
20 end
|
bleeck@4
|
21
|
bleeck@4
|
22 if isfield(options,'target_frequency')
|
bleeck@4
|
23 end
|
bleeck@4
|
24
|
bleeck@4
|
25 if ~isfield(options,'options')
|
bleeck@4
|
26 target_frequency=0;
|
bleeck@4
|
27 end
|
bleeck@4
|
28
|
bleeck@4
|
29
|
bleeck@4
|
30 % for debug resons
|
bleeck@4
|
31 plot_switch = 1;
|
bleeck@4
|
32
|
bleeck@4
|
33
|
bleeck@4
|
34 intsum = ti_profile;
|
bleeck@4
|
35 intsum_vals = getdata(intsum);
|
bleeck@4
|
36 if plot_switch
|
bleeck@4
|
37 minimum_time_interval=0; % in ms
|
bleeck@4
|
38 maximum_time_interval=100;
|
bleeck@4
|
39 figure(654654)
|
bleeck@4
|
40 clf
|
bleeck@4
|
41 tip = intsum_vals;
|
bleeck@4
|
42 tip_x = bin2time(ti_profile, 1:length(tip)); % Get the times
|
bleeck@4
|
43 tip_x = tip_x((tip_x>=(minimum_time_interval/1000)) & tip_x<=(maximum_time_interval/1000));
|
bleeck@4
|
44 tip = tip(time2bin(ti_profile, tip_x(1)):time2bin(ti_profile, tip_x(end)));
|
bleeck@4
|
45 % tip_x is in ms. Change to Hz
|
bleeck@4
|
46 tip_x = 1./tip_x;
|
bleeck@4
|
47 plot(tip_x, tip, 'b');
|
bleeck@4
|
48 set(gca,'XScale','log');
|
bleeck@4
|
49 set(gca,'Ylim', [min(intsum)-10 max(intsum)+10]);
|
bleeck@4
|
50 set(gca,'Xlim', [30 1500]);
|
bleeck@4
|
51 hold on
|
bleeck@4
|
52 end
|
bleeck@4
|
53 if length(peaks)==0
|
bleeck@4
|
54 % If there is no peak than we just plot the function
|
bleeck@4
|
55 pitchstrength = 0;
|
bleeck@4
|
56 found_frequency = 0;
|
bleeck@4
|
57 return
|
bleeck@4
|
58 end
|
bleeck@4
|
59
|
bleeck@4
|
60
|
bleeck@4
|
61 sig=envelope(intsum)
|
bleeck@4
|
62
|
bleeck@4
|
63 % ++++++++++++ Part one: Peak finding ++++++++++
|
bleeck@4
|
64 % Calculate the envelope (curve of the peaks)
|
bleeck@4
|
65
|
bleeck@4
|
66 % sort peaks from low time interval to a heigh one
|
bleeck@4
|
67 % or from left to right
|
bleeck@4
|
68 peaks_lr = sortstruct(peaks,'x'); %
|
bleeck@4
|
69
|
bleeck@4
|
70 if plot_switch
|
bleeck@4
|
71 px=[];py=[];
|
bleeck@4
|
72 for i=1:length(peaks)
|
bleeck@4
|
73 px = [px tip_x(peaks{i}.x)];
|
bleeck@4
|
74 py = [py tip(peaks{i}.x)];
|
bleeck@4
|
75 end
|
bleeck@4
|
76 plot(px,py,'kx');
|
bleeck@4
|
77 end
|
bleeck@4
|
78
|
bleeck@4
|
79 % Create envelope of peaks
|
bleeck@4
|
80 peak_envX = [];
|
bleeck@4
|
81 peak_envY = [];
|
bleeck@4
|
82 for i=1:length(peaks_lr)
|
bleeck@4
|
83 peak_envX = [peak_envX peaks_lr{i}.x];
|
bleeck@4
|
84 peak_envY = [peak_envY peaks_lr{i}.y];
|
bleeck@4
|
85 end
|
bleeck@4
|
86
|
bleeck@4
|
87 if plot_switch
|
bleeck@4
|
88 plot(tip_x(peak_envX), peak_envY, ':k');
|
bleeck@4
|
89 end
|
bleeck@4
|
90
|
bleeck@4
|
91
|
bleeck@4
|
92 % Find Maxima of the envelope
|
bleeck@4
|
93 % create signal
|
bleeck@4
|
94
|
bleeck@4
|
95 sig=buildfrompoints(sig,xx,yy)
|
bleeck@4
|
96
|
bleeck@4
|
97
|
bleeck@4
|
98 peak_envsig = signal(length(peak_envX), 1);
|
bleeck@4
|
99 peak_envsig = setvalues(peak_envsig, peak_envY);
|
bleeck@4
|
100 params = 0;
|
bleeck@4
|
101 peak_env_peaks = PeakPicker(peak_envsig, params);
|
bleeck@4
|
102 % sort peaks of the envelope from low time interval to a heigh one
|
bleeck@4
|
103 % or from left to right
|
bleeck@4
|
104 peaks_env_peaks_lr = sortstruct(peak_env_peaks,'x'); %
|
bleeck@4
|
105
|
bleeck@4
|
106 if plot_switch
|
bleeck@4
|
107 for i=2:length(peaks_env_peaks_lr) % construct all maxima
|
bleeck@4
|
108 fre=peaks_env_peaks_lr{i}.t;
|
bleeck@4
|
109 plot(fre,gettimevalue(ti_profile,1/fre),'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',5);
|
bleeck@4
|
110 end
|
bleeck@4
|
111 end
|
bleeck@4
|
112
|
bleeck@4
|
113 % % Now make sure, that highest peak is not the first peak of envelope
|
bleeck@4
|
114 % peak_oi = peaks{1};
|
bleeck@4
|
115 % if (peak_oi.x == peak_envX(peaks_env_peaks_lr{1}.x))
|
bleeck@4
|
116 % % The first Peak is the heighest -> take second highest of envelope
|
bleeck@4
|
117 % if (length(peak_env_peaks)>=2)
|
bleeck@4
|
118 % poix = peak_envX(peak_env_peaks{2}.x);
|
bleeck@4
|
119 % poiy = peak_env_peaks{2}.y;
|
bleeck@4
|
120 % for i=1:length(peaks)
|
bleeck@4
|
121 % if poix==peaks{i}.x
|
bleeck@4
|
122 % peak_oi = peaks{i};
|
bleeck@4
|
123 % end
|
bleeck@4
|
124 % end
|
bleeck@4
|
125 % end
|
bleeck@4
|
126 % end
|
bleeck@4
|
127
|
bleeck@4
|
128
|
bleeck@4
|
129 % Stefans new method:
|
bleeck@4
|
130 % Take the one with the highest contrast
|
bleeck@4
|
131 if length(peaks_env_peaks_lr) > 1
|
bleeck@4
|
132 for i=2:length(peaks_env_peaks_lr) % construct all maxima
|
bleeck@4
|
133 maxpeak=peaks_env_peaks_lr{i}.y;
|
bleeck@4
|
134 minpeak1=peaks_env_peaks_lr{i}.left.y;
|
bleeck@4
|
135 minpeak2=peaks_env_peaks_lr{i}.right.y;
|
bleeck@4
|
136 minpeak=mean([minpeak1 minpeak2]);
|
bleeck@4
|
137
|
bleeck@4
|
138 % the definition of pitch strength: Contrast
|
bleeck@4
|
139 % contrast(i)=maxpeak/(mean([minpeak1 minpeak2]));
|
bleeck@4
|
140
|
bleeck@4
|
141 % the difference between both
|
bleeck@4
|
142 if maxpeak-minpeak > 0
|
bleeck@4
|
143 contrast(i)=(maxpeak-minpeak)/1000;
|
bleeck@4
|
144 else
|
bleeck@4
|
145 contrast(i)=0;
|
bleeck@4
|
146 end
|
bleeck@4
|
147 if plot_switch
|
bleeck@4
|
148 fre=1/peaks{i}.t;
|
bleeck@4
|
149 plot(fre,gettimevalue(ti_profile,1/fre),'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',5);
|
bleeck@4
|
150 text(fre,gettimevalue(ti_profile,1/fre)*1.1,sprintf('%2.2f',contrast(i)));
|
bleeck@4
|
151 end
|
bleeck@4
|
152 end
|
bleeck@4
|
153 else % there is only one peak
|
bleeck@4
|
154 maxpeak=peaks{1}.y;
|
bleeck@4
|
155 minpeak1=peaks{1}.left.y;
|
bleeck@4
|
156 minpeak2=peaks{1}.right.y;
|
bleeck@4
|
157 minpeak=mean([minpeak1 minpeak2]);
|
bleeck@4
|
158 if maxpeak-minpeak > 0
|
bleeck@4
|
159 contrast(1)=(maxpeak-minpeak)/1000;
|
bleeck@4
|
160 else
|
bleeck@4
|
161 contrast(1)=0;
|
bleeck@4
|
162 end
|
bleeck@4
|
163 end
|
bleeck@4
|
164
|
bleeck@4
|
165 [maxcontrast,wheremax]=max(contrast);
|
bleeck@4
|
166
|
bleeck@4
|
167 peak_oi=peaks{wheremax};
|
bleeck@4
|
168
|
bleeck@4
|
169 pitchstrength= contrast(wheremax);
|
bleeck@4
|
170 found_frequency = 1/peak_oi.t;
|
bleeck@4
|
171
|
bleeck@4
|
172 if plot_switch
|
bleeck@4
|
173 fre=found_frequency;
|
bleeck@4
|
174 plot(fre,gettimevalue(ti_profile,1/fre),'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',pitchstrength*10);
|
bleeck@4
|
175 text(fre*1.1,gettimevalue(ti_profile,1/fre)+5, ['highest pitchstrength found at ' num2str(round(fre)) 'Hz: ' num2str(fround(pitchstrength,2)) ],'VerticalAlignment','bottom','HorizontalAlignment','center','color','g','Fontsize',12);
|
bleeck@4
|
176 end
|
bleeck@4
|
177
|
bleeck@4
|
178 return
|
bleeck@4
|
179
|
bleeck@4
|
180
|
bleeck@4
|
181
|
bleeck@4
|
182
|
bleeck@4
|
183 % maxpeak=maxstruct(peaks,'y');
|
bleeck@4
|
184
|
bleeck@4
|
185 if length(peaks_env_peaks_lr)>1
|
bleeck@4
|
186 for i=1:length(peaks)
|
bleeck@4
|
187 % If second highes peak==peak with smallest time intervall -> take
|
bleeck@4
|
188 % third highest !!
|
bleeck@4
|
189 if peak_env_peaks{2}.x == peaks_env_peaks_lr{1}.x
|
bleeck@4
|
190 poix = peak_envX(peak_env_peaks{3}.x);
|
bleeck@4
|
191 else
|
bleeck@4
|
192 poix = peak_envX(peak_env_peaks{2}.x);
|
bleeck@4
|
193 end
|
bleeck@4
|
194 if peaks{i}.x==poix
|
bleeck@4
|
195 peak_oi = peaks{i};
|
bleeck@4
|
196 end
|
bleeck@4
|
197 end
|
bleeck@4
|
198 else
|
bleeck@4
|
199 % pure sinusoid ???
|
bleeck@4
|
200 dominant_time = 0
|
bleeck@4
|
201 pitchstrength = 0.001;
|
bleeck@4
|
202 return
|
bleeck@4
|
203 end
|
bleeck@4
|
204
|
bleeck@4
|
205
|
bleeck@4
|
206
|
bleeck@4
|
207 % Stefan's method on HCL
|
bleeck@4
|
208 % Take second peak of envelope from short time intervals
|
bleeck@4
|
209 if length(peaks_env_peaks_lr)>1
|
bleeck@4
|
210 for i=1:length(peaks)
|
bleeck@4
|
211 % If second highes peak==peak with smallest time intervall -> take
|
bleeck@4
|
212 % third highest !!
|
bleeck@4
|
213 if peak_env_peaks{2}.x == peaks_env_peaks_lr{1}.x
|
bleeck@4
|
214 poix = peak_envX(peak_env_peaks{3}.x);
|
bleeck@4
|
215 else
|
bleeck@4
|
216 poix = peak_envX(peak_env_peaks{2}.x);
|
bleeck@4
|
217 end
|
bleeck@4
|
218 if peaks{i}.x==poix
|
bleeck@4
|
219 peak_oi = peaks{i};
|
bleeck@4
|
220 end
|
bleeck@4
|
221 end
|
bleeck@4
|
222 else
|
bleeck@4
|
223 % pure sinusoid ???
|
bleeck@4
|
224 dominant_time = 0
|
bleeck@4
|
225 pitchstrength = 0.001;
|
bleeck@4
|
226 return
|
bleeck@4
|
227 end
|
bleeck@4
|
228
|
bleeck@4
|
229 if plot_switch
|
bleeck@4
|
230 plot(tip_x(peak_oi.x), peak_oi.y, 'ro');
|
bleeck@4
|
231 end
|
bleeck@4
|
232
|
bleeck@4
|
233
|
bleeck@4
|
234
|
bleeck@4
|
235
|
bleeck@4
|
236
|
bleeck@4
|
237 % peak_oi contains the peak for quantification
|
bleeck@4
|
238
|
bleeck@4
|
239
|
bleeck@4
|
240 % ++++++++++++ Part two: Quantification ++++++++++
|
bleeck@4
|
241
|
bleeck@4
|
242 % **** First method
|
bleeck@4
|
243 % pitchstrength is mean of sum / mean of peaks
|
bleeck@4
|
244 % psum = 0;
|
bleeck@4
|
245 % for i = 1:length(peaks)
|
bleeck@4
|
246 % psum = psum+peaks{i}.y;
|
bleeck@4
|
247 % end
|
bleeck@4
|
248 % psum = psum / length(peaks);
|
bleeck@4
|
249 % pitchstrength = psum/peaks{1}.y;
|
bleeck@4
|
250 % dominant_time = peaks{1}.x /getsr(ti_profile);
|
bleeck@4
|
251 % if plot_switch
|
bleeck@4
|
252 % hold off
|
bleeck@4
|
253 % plot(ti_profile);
|
bleeck@4
|
254 % hold on;
|
bleeck@4
|
255 % plot(peaks{1}.x, peaks{1}.y, 'ko');
|
bleeck@4
|
256 % end
|
bleeck@4
|
257
|
bleeck@4
|
258 % % ***** Second method
|
bleeck@4
|
259 % % Heigh of neighbour peak / highest peak
|
bleeck@4
|
260 % % First Peaks is the highest as pitchstrength of Peak Picker
|
bleeck@4
|
261 % % Find lower neighbour (with shorter time interval)
|
bleeck@4
|
262 % ioi=1; % index of interest
|
bleeck@4
|
263 % dist = inf;
|
bleeck@4
|
264 % for i=1:length(peaks)
|
bleeck@4
|
265 % d = peak_oi.x - peaks{i}.x;
|
bleeck@4
|
266 % if ((d<dist)&(d>0))
|
bleeck@4
|
267 % ioi = i;
|
bleeck@4
|
268 % dist = d;
|
bleeck@4
|
269 % end
|
bleeck@4
|
270 % end
|
bleeck@4
|
271 % pitchstrength = peaks{ioi}.y/ peak_oi.y;
|
bleeck@4
|
272 % dominant_time = peak_oi.x /getsr(ti_profile);
|
bleeck@4
|
273 % if plot_switch
|
bleeck@4
|
274 % hold on;
|
bleeck@4
|
275 % plot(peak_oi.x , peak_oi.y , 'ko');
|
bleeck@4
|
276 % plot(peaks{ioi}.x, peaks{ioi}.y, 'go');
|
bleeck@4
|
277 % end
|
bleeck@4
|
278
|
bleeck@4
|
279 % % Third Method:
|
bleeck@4
|
280 % Peak to mean valley ration - good with HCL
|
bleeck@4
|
281 pitchstrength= mean([peak_oi.left.y peak_oi.right.y])/peak_oi.y;
|
bleeck@4
|
282 dominant_time = peak_oi.x /getsr(ti_profile);
|
bleeck@4
|
283
|
bleeck@4
|
284 % Adaptation
|
bleeck@4
|
285 %pitchstrength = 1-pitchstrength;
|
bleeck@4
|
286
|
bleeck@4
|
287 % +++++++++++++ Histogram of distances between two peaks ++++++++++
|
bleeck@4
|
288
|
bleeck@4
|
289 %
|
bleeck@4
|
290 max_thresh = 1; %0.98;
|
bleeck@4
|
291 % The linear TIP
|
bleeck@4
|
292
|
bleeck@4
|
293 % Test if all other Peaks ar multiple of the highest peak
|
bleeck@4
|
294
|
bleeck@4
|
295 % Start with the first peak
|
bleeck@4
|
296 % Test how many peaks are mutiple of the first peak
|
bleeck@4
|
297 %---x---x---x---x---x---x
|
bleeck@4
|
298 % Take first peak of envelope.
|
bleeck@4
|
299 poix = peak_envX(peak_env_peaks{1}.x);
|
bleeck@4
|
300 for i=1:length(peaks_lr)
|
bleeck@4
|
301 if peaks_lr {i}.x==poix
|
bleeck@4
|
302 peak_first = peaks_lr{i};
|
bleeck@4
|
303 first_i=i;
|
bleeck@4
|
304 end
|
bleeck@4
|
305 end
|
bleeck@4
|
306 nomult = 0; % Number of multible
|
bleeck@4
|
307 max_delta = 0.1; %
|
bleeck@4
|
308 for i=first_i:length(peaks_lr)
|
bleeck@4
|
309 f = peaks_lr{i}.t / peak_first.t;
|
bleeck@4
|
310 if abs(round(f)-f)<max_delta
|
bleeck@4
|
311 nomult=nomult+1;
|
bleeck@4
|
312 end
|
bleeck@4
|
313 end
|
bleeck@4
|
314 nomult;
|
bleeck@4
|
315
|
bleeck@4
|
316 if plot_switch
|
bleeck@4
|
317 figure(savecf)
|
bleeck@4
|
318 end
|
bleeck@4
|
319
|
bleeck@4
|
320 %---x---x---x---x---x---x
|
bleeck@4
|
321
|
bleeck@4
|
322 % is there is a priori information?
|
bleeck@4
|
323 % if (nargin>2)
|
bleeck@4
|
324 % dominant_time = mb(h_index) / getsr(ti_profile);
|
bleeck@4
|
325 % pitchstrength = 0;
|
bleeck@4
|
326 % return
|
bleeck@4
|
327 % end
|
bleeck@4
|
328
|
bleeck@4
|
329
|
bleeck@4
|
330
|
bleeck@4
|
331 % ------------ subfunctions ---------------------
|
bleeck@4
|
332
|
bleeck@4
|
333 % turns a vector (row) upside down
|
bleeck@4
|
334 function y=upsidedown(x)
|
bleeck@4
|
335 y=[];
|
bleeck@4
|
336 for i=length(x):-1:1
|
bleeck@4
|
337 y=[y x(i)];
|
bleeck@4
|
338 end
|