wolffd@0
|
1 function varargout = mirenvelope(orig,varargin)
|
wolffd@0
|
2 % e = mirenvelope(x) extracts the envelope of x, showing the global shape
|
wolffd@0
|
3 % of the waveform.
|
wolffd@0
|
4 % mirenvelope(...,m) specifies envelope extraction method.
|
wolffd@0
|
5 % Possible values:
|
wolffd@0
|
6 % m = 'Filter' uses a low-pass filtering. (Default strategy)
|
wolffd@0
|
7 % m = 'Spectro' uses a spectrogram.
|
wolffd@0
|
8 %
|
wolffd@0
|
9 % Options related to the 'Filter' method:
|
wolffd@0
|
10 % mirenvelope(...,'Hilbert'): performs a preliminary Hilbert
|
wolffd@0
|
11 % transform.
|
wolffd@0
|
12 % mirenvelope(...,'PreDecim',N) downsamples by a factor N>1, where
|
wolffd@0
|
13 % N is an integer, before the low-pass filtering (Klapuri, 1999).
|
wolffd@0
|
14 % Default value: N = 1.
|
wolffd@0
|
15 % mirenvelope(...,'Filtertype',f) specifies the filter type.
|
wolffd@0
|
16 % Possible values are:
|
wolffd@0
|
17 % f = 'IIR': filter with one autoregressive coefficient
|
wolffd@0
|
18 % (default)
|
wolffd@0
|
19 % f = 'HalfHann': half-Hanning (raised cosine) filter
|
wolffd@0
|
20 % (Scheirer, 1998)
|
wolffd@0
|
21 % Option related to the 'IIR' option:
|
wolffd@0
|
22 % mirenvelope(...,'Tau',t): time constant of low-pass filter in
|
wolffd@0
|
23 % seconds.
|
wolffd@0
|
24 % Default value: t = 0.02 s.
|
wolffd@0
|
25 % mirenvelope(...,'PostDecim',N) downsamples by a factor N>1, where
|
wolffd@0
|
26 % N is an integer, after the low-pass filtering.
|
wolffd@0
|
27 % Default value: N = 16 if 'PreDecim' is not used, else N = 1.
|
wolffd@0
|
28 % mirenvelope(...,'Trim'): trims the initial ascending phase of the
|
wolffd@0
|
29 % curves related to the transitory state.
|
wolffd@0
|
30 %
|
wolffd@0
|
31 % Options related to the 'Spectro' method:
|
wolffd@0
|
32 % mirenvelope(...,b) specifies whether the frequency range is further
|
wolffd@0
|
33 % decomposed into bands. Possible values:
|
wolffd@0
|
34 % b = 'Freq': no band decomposition (default value)
|
wolffd@0
|
35 % b = 'Mel': Mel-band decomposition
|
wolffd@0
|
36 % b = 'Bark': Bark-band decomposition
|
wolffd@0
|
37 % b = 'Cents': decompositions into cents
|
wolffd@0
|
38 % mirenvelope(...,'Frame',...) specifies the frame configuration.
|
wolffd@0
|
39 % Default value: length: .1 s, hop factor: 10 %.
|
wolffd@0
|
40 % mirenvelope(...,'UpSample',N) upsamples by a factor N>1, where
|
wolffd@0
|
41 % N is an integer.
|
wolffd@0
|
42 % Default value if 'UpSample' called: N = 2
|
wolffd@0
|
43 % mirenvelope(...,'Complex') toggles on the 'Complex' method for the
|
wolffd@0
|
44 % spectral flux computation.
|
wolffd@0
|
45 %
|
wolffd@0
|
46 % Other available for all methods:
|
wolffd@0
|
47 % mirenvelope(...,'Sampling',r): resamples to rate r (in Hz).
|
wolffd@0
|
48 % 'Down' and 'Sampling' options cannot therefore be combined.
|
wolffd@0
|
49 % mirenvelope(...,'Halfwave'): performs a half-wave rectification.
|
wolffd@0
|
50 % mirenvelope(...,'Center'): centers the extracted envelope.
|
wolffd@0
|
51 % mirenvelope(...,'HalfwaveCenter'): performs a half-wave
|
wolffd@0
|
52 % rectification on the centered envelope.
|
wolffd@0
|
53 % mirenvelope(...,'Log'): computes the common logarithm (base 10) of
|
wolffd@0
|
54 % the envelope.
|
wolffd@0
|
55 % mirenvelope(...,'Mu',mu): computes the logarithm of the
|
wolffd@0
|
56 % envelope, before the eventual differentiation, using a mu-law
|
wolffd@0
|
57 % compression (Klapuri, 2006).
|
wolffd@0
|
58 % Default value for mu: 100
|
wolffd@0
|
59 % mirenvelope(...,'Log'): computes the logarithm of the envelope.
|
wolffd@0
|
60 % mirenvelope(...,'Power'): computes the power (square) of the
|
wolffd@0
|
61 % envelope.
|
wolffd@0
|
62 % mirenvelope(...,'Diff'): computes the differentation of the
|
wolffd@0
|
63 % envelope, i.e., the differences between successive samples.
|
wolffd@0
|
64 % mirenvelope(...,'HalfwaveDiff'): performs a half-wave
|
wolffd@0
|
65 % rectification on the differentiated envelope.
|
wolffd@0
|
66 % mirenvelope(...,'Normal'): normalizes the values of the envelope by
|
wolffd@0
|
67 % fixing the maximum value to 1.
|
wolffd@0
|
68 % mirenvelope(...,'Lambda',l): sums the half-wave rectified envelope
|
wolffd@0
|
69 % with the non-differentiated envelope, using the respective
|
wolffd@0
|
70 % weight 0<l<1 and (1-l). (Klapuri et al., 2006)
|
wolffd@0
|
71 % mirenvelope(...,'Smooth',o): smooths the envelope using a moving
|
wolffd@0
|
72 % average of order o.
|
wolffd@0
|
73 % Default value when the option is toggled on: o=30
|
wolffd@0
|
74 % mirenvelope(...,'Gauss',o): smooths the envelope using a gaussian
|
wolffd@0
|
75 % of standard deviation o samples.
|
wolffd@0
|
76 % Default value when the option is toggled on: o=30
|
wolffd@0
|
77 % mirenvelope(...,'Klapuri06'): follows the model proposed in
|
wolffd@0
|
78 % (Klapuri et al., 2006).
|
wolffd@0
|
79
|
wolffd@0
|
80 method.type = 'String';
|
wolffd@0
|
81 method.choice = {'Filter','Spectro'};
|
wolffd@0
|
82 method.default = 'Filter';
|
wolffd@0
|
83 option.method = method;
|
wolffd@0
|
84
|
wolffd@0
|
85 %% options related to 'Filter':
|
wolffd@0
|
86
|
wolffd@0
|
87 hilb.key = 'Hilbert';
|
wolffd@0
|
88 hilb.type = 'Boolean';
|
wolffd@0
|
89 hilb.default = 0;
|
wolffd@0
|
90 option.hilb = hilb;
|
wolffd@0
|
91
|
wolffd@0
|
92 decim.key = {'Decim','PreDecim'};
|
wolffd@0
|
93 decim.type = 'Integer';
|
wolffd@0
|
94 decim.default = 0;
|
wolffd@0
|
95 option.decim = decim;
|
wolffd@0
|
96
|
wolffd@0
|
97 filter.key = 'FilterType';
|
wolffd@0
|
98 filter.type = 'String';
|
wolffd@0
|
99 filter.choice = {'IIR','HalfHann',0};
|
wolffd@0
|
100 if isamir(orig,'mirenvelope')
|
wolffd@0
|
101 filter.default = 0; % no more envelope extraction, already done
|
wolffd@0
|
102 else
|
wolffd@0
|
103 filter.default = 'IIR';
|
wolffd@0
|
104 end
|
wolffd@0
|
105 option.filter = filter;
|
wolffd@0
|
106
|
wolffd@0
|
107 %% options related to 'IIR':
|
wolffd@0
|
108 tau.key = 'Tau';
|
wolffd@0
|
109 tau.type = 'Integer';
|
wolffd@0
|
110 tau.default = .02;
|
wolffd@0
|
111 option.tau = tau;
|
wolffd@0
|
112
|
wolffd@0
|
113 zp.key = 'ZeroPhase'; % internal use: for manual filtfilt
|
wolffd@0
|
114 zp.type = 'Boolean';
|
wolffd@0
|
115 if isamir(orig,'mirenvelope')
|
wolffd@0
|
116 zp.default = 0;
|
wolffd@0
|
117 else
|
wolffd@0
|
118 zp.default = NaN;
|
wolffd@0
|
119 end
|
wolffd@0
|
120 option.zp = zp;
|
wolffd@0
|
121
|
wolffd@0
|
122 ds.key = {'Down','PostDecim'};
|
wolffd@0
|
123 ds.type = 'Integer';
|
wolffd@0
|
124 if isamir(orig,'mirenvelope')
|
wolffd@0
|
125 ds.default = 1;
|
wolffd@0
|
126 else
|
wolffd@0
|
127 ds.default = NaN; % 0 if 'PreDecim' is used, else 16
|
wolffd@0
|
128 end
|
wolffd@0
|
129 ds.when = 'After';
|
wolffd@0
|
130 ds.chunkcombine = 'During';
|
wolffd@0
|
131 option.ds = ds;
|
wolffd@0
|
132
|
wolffd@0
|
133 trim.key = 'Trim';
|
wolffd@0
|
134 trim.type = 'Boolean';
|
wolffd@0
|
135 trim.default = 0;
|
wolffd@0
|
136 trim.when = 'After';
|
wolffd@0
|
137 option.trim = trim;
|
wolffd@0
|
138
|
wolffd@0
|
139 %% Options related to 'Spectro':
|
wolffd@0
|
140
|
wolffd@0
|
141 band.type = 'String';
|
wolffd@0
|
142 band.choice = {'Freq','Mel','Bark','Cents'};
|
wolffd@0
|
143 band.default = 'Freq';
|
wolffd@0
|
144 option.band = band;
|
wolffd@0
|
145
|
wolffd@0
|
146 up.key = {'UpSample'};
|
wolffd@0
|
147 up.type = 'Integer';
|
wolffd@0
|
148 up.default = 0;
|
wolffd@0
|
149 up.keydefault = 2;
|
wolffd@0
|
150 up.when = 'After';
|
wolffd@0
|
151 option.up = up;
|
wolffd@0
|
152
|
wolffd@0
|
153 complex.key = 'Complex';
|
wolffd@0
|
154 complex.type = 'Boolean';
|
wolffd@0
|
155 complex.default = 0;
|
wolffd@0
|
156 complex.when = 'After';
|
wolffd@0
|
157 option.complex = complex;
|
wolffd@0
|
158
|
wolffd@0
|
159 %% Options related to all methods:
|
wolffd@0
|
160
|
wolffd@0
|
161 sampling.key = 'Sampling';
|
wolffd@0
|
162 sampling.type = 'Integer';
|
wolffd@0
|
163 sampling.default = 0;
|
wolffd@0
|
164 sampling.when = 'After';
|
wolffd@0
|
165 option.sampling = sampling;
|
wolffd@0
|
166
|
wolffd@0
|
167 hwr.key = 'Halfwave';
|
wolffd@0
|
168 hwr.type = 'Boolean';
|
wolffd@0
|
169 hwr.default = 0;
|
wolffd@0
|
170 hwr.when = 'After';
|
wolffd@0
|
171 option.hwr = hwr;
|
wolffd@0
|
172
|
wolffd@0
|
173 c.key = 'Center';
|
wolffd@0
|
174 c.type = 'Boolean';
|
wolffd@0
|
175 c.default = 0;
|
wolffd@0
|
176 c.when = 'After';
|
wolffd@0
|
177 option.c = c;
|
wolffd@0
|
178
|
wolffd@0
|
179 chwr.key = 'HalfwaveCenter';
|
wolffd@0
|
180 chwr.type = 'Boolean';
|
wolffd@0
|
181 chwr.default = 0;
|
wolffd@0
|
182 chwr.when = 'After';
|
wolffd@0
|
183 option.chwr = chwr;
|
wolffd@0
|
184
|
wolffd@0
|
185 mu.key = 'Mu';
|
wolffd@0
|
186 mu.type = 'Integer';
|
wolffd@0
|
187 mu.default = 0;
|
wolffd@0
|
188 mu.keydefault = 100;
|
wolffd@0
|
189 mu.when = 'After';
|
wolffd@0
|
190 option.mu = mu;
|
wolffd@0
|
191
|
wolffd@0
|
192 oplog.key = 'Log';
|
wolffd@0
|
193 oplog.type = 'Boolean';
|
wolffd@0
|
194 oplog.default = 0;
|
wolffd@0
|
195 oplog.when = 'After';
|
wolffd@0
|
196 option.log = oplog;
|
wolffd@0
|
197
|
wolffd@0
|
198 oppow.key = 'Power';
|
wolffd@0
|
199 oppow.type = 'Integer';
|
wolffd@0
|
200 oppow.default = 0;
|
wolffd@0
|
201 oppow.when = 'After';
|
wolffd@0
|
202 option.power = oppow;
|
wolffd@0
|
203
|
wolffd@0
|
204 diff.key = 'Diff';
|
wolffd@0
|
205 diff.type = 'Integer';
|
wolffd@0
|
206 diff.default = 0;
|
wolffd@0
|
207 diff.keydefault = 1;
|
wolffd@0
|
208 diff.when = 'After';
|
wolffd@0
|
209 option.diff = diff;
|
wolffd@0
|
210
|
wolffd@0
|
211 diffhwr.key = 'HalfwaveDiff';
|
wolffd@0
|
212 diffhwr.type = 'Integer';
|
wolffd@0
|
213 diffhwr.default = 0;
|
wolffd@0
|
214 diffhwr.keydefault = 1;
|
wolffd@0
|
215 diffhwr.when = 'After';
|
wolffd@0
|
216 option.diffhwr = diffhwr;
|
wolffd@0
|
217
|
wolffd@0
|
218 lambda.key = 'Lambda';
|
wolffd@0
|
219 lambda.type = 'Integer';
|
wolffd@0
|
220 lambda.default = 1;
|
wolffd@0
|
221 lambda.when = 'After';
|
wolffd@0
|
222 option.lambda = lambda;
|
wolffd@0
|
223
|
wolffd@0
|
224 aver.key = 'Smooth';
|
wolffd@0
|
225 aver.type = 'Integer';
|
wolffd@0
|
226 aver.default = 0;
|
wolffd@0
|
227 aver.keydefault = 30;
|
wolffd@0
|
228 aver.when = 'After';
|
wolffd@0
|
229 option.aver = aver;
|
wolffd@0
|
230
|
wolffd@0
|
231 gauss.key = 'Gauss';
|
wolffd@0
|
232 gauss.type = 'Integer';
|
wolffd@0
|
233 gauss.default = 0;
|
wolffd@0
|
234 gauss.keydefault = 30;
|
wolffd@0
|
235 gauss.when = 'After';
|
wolffd@0
|
236 option.gauss = gauss;
|
wolffd@0
|
237
|
wolffd@0
|
238 norm.key = 'Normal';
|
wolffd@0
|
239 norm.type = 'Boolean';
|
wolffd@0
|
240 norm.default = 0;
|
wolffd@0
|
241 norm.when = 'After';
|
wolffd@0
|
242 option.norm = norm;
|
wolffd@0
|
243
|
wolffd@0
|
244 presel.type = 'String';
|
wolffd@0
|
245 presel.choice = {'Klapuri06'};
|
wolffd@0
|
246 presel.default = 0;
|
wolffd@0
|
247 option.presel = presel;
|
wolffd@0
|
248
|
wolffd@0
|
249 frame.key = 'Frame';
|
wolffd@0
|
250 frame.type = 'Integer';
|
wolffd@0
|
251 frame.number = 2;
|
wolffd@0
|
252 frame.default = [.1 .1];
|
wolffd@0
|
253 option.frame = frame;
|
wolffd@0
|
254
|
wolffd@0
|
255 specif.option = option;
|
wolffd@0
|
256
|
wolffd@0
|
257 specif.eachchunk = 'Normal';
|
wolffd@0
|
258 specif.combinechunk = 'Concat';
|
wolffd@0
|
259 specif.extensive = 1;
|
wolffd@0
|
260
|
wolffd@0
|
261 varargout = mirfunction(@mirenvelope,orig,varargin,nargout,specif,@init,@main);
|
wolffd@0
|
262
|
wolffd@0
|
263
|
wolffd@0
|
264 function [x type] = init(x,option)
|
wolffd@0
|
265 type = 'mirenvelope';
|
wolffd@0
|
266 if isamir(x,'mirscalar')
|
wolffd@0
|
267 return
|
wolffd@0
|
268 end
|
wolffd@0
|
269 if ischar(option.presel) && strcmpi(option.presel,'Klapuri06')
|
wolffd@0
|
270 option.method = 'Spectro';
|
wolffd@0
|
271 end
|
wolffd@0
|
272 if not(isamir(x,'mirenvelope'))
|
wolffd@0
|
273 if strcmpi(option.method,'Filter')
|
wolffd@0
|
274 if isnan(option.zp)
|
wolffd@0
|
275 if strcmpi(option.filter,'IIR')
|
wolffd@0
|
276 option.zp = 1;
|
wolffd@0
|
277 else
|
wolffd@0
|
278 option.zp = 0;
|
wolffd@0
|
279 end
|
wolffd@0
|
280 end
|
wolffd@0
|
281 if option.zp == 1
|
wolffd@0
|
282 x = mirenvelope(x,'ZeroPhase',2,'Down',1,...
|
wolffd@0
|
283 'Tau',option.tau,'PreDecim',option.decim);
|
wolffd@0
|
284 end
|
wolffd@0
|
285 elseif strcmpi(option.method,'Spectro')
|
wolffd@0
|
286 x = mirspectrum(x,'Frame',option.frame.length.val,...
|
wolffd@0
|
287 option.frame.length.unit,...
|
wolffd@0
|
288 option.frame.hop.val,...
|
wolffd@0
|
289 option.frame.hop.unit,...
|
wolffd@0
|
290 'Window','hanning',...
|
wolffd@0
|
291 option.band,'Power');
|
wolffd@0
|
292
|
wolffd@0
|
293 end
|
wolffd@0
|
294 end
|
wolffd@0
|
295
|
wolffd@0
|
296
|
wolffd@0
|
297 function e = main(orig,option,postoption)
|
wolffd@0
|
298 if iscell(orig)
|
wolffd@0
|
299 orig = orig{1};
|
wolffd@0
|
300 end
|
wolffd@0
|
301 if isamir(orig,'mirscalar')
|
wolffd@0
|
302 d = get(orig,'Data');
|
wolffd@0
|
303 fp = get(orig,'FramePos');
|
wolffd@0
|
304 for i = 1:length(d)
|
wolffd@0
|
305 for j = 1:length(d{i})
|
wolffd@0
|
306 d{i}{j} = reshape(d{i}{j},size(d{i}{j},2),1,size(d{i}{j},3));
|
wolffd@0
|
307 p{i}{j} = mean(fp{i}{j})';
|
wolffd@0
|
308 end
|
wolffd@0
|
309 end
|
wolffd@0
|
310 e.downsampl = 0;
|
wolffd@0
|
311 e.hwr = 0;
|
wolffd@0
|
312 e.diff = 0;
|
wolffd@0
|
313 e.method = 'Spectro';
|
wolffd@0
|
314 e.phase = {{}};
|
wolffd@0
|
315 e = class(e,'mirenvelope',mirtemporal(orig));
|
wolffd@0
|
316 e = set(e,'Title','Envelope','Data',d,'Pos',p,'FramePos',{{}});
|
wolffd@0
|
317 postoption.trim = 0;
|
wolffd@0
|
318 postoption.ds = 0;
|
wolffd@0
|
319 e = post(e,postoption);
|
wolffd@0
|
320 return
|
wolffd@0
|
321 end
|
wolffd@0
|
322 if isfield(option,'presel') && ischar(option.presel) && ...
|
wolffd@0
|
323 strcmpi(option.presel,'Klapuri06')
|
wolffd@0
|
324 option.method = 'Spectro';
|
wolffd@0
|
325 postoption.up = 2;
|
wolffd@0
|
326 postoption.mu = 100;
|
wolffd@0
|
327 postoption.diffhwr = 1;
|
wolffd@0
|
328 postoption.lambda = .8;
|
wolffd@0
|
329 end
|
wolffd@0
|
330 if isfield(postoption,'ds') && isnan(postoption.ds)
|
wolffd@0
|
331 if option.decim
|
wolffd@0
|
332 postoption.ds = 0;
|
wolffd@0
|
333 else
|
wolffd@0
|
334 postoption.ds = 16;
|
wolffd@0
|
335 end
|
wolffd@0
|
336 end
|
wolffd@0
|
337 if not(isfield(option,'filter')) || not(ischar(option.filter))
|
wolffd@0
|
338 e = post(orig,postoption);
|
wolffd@0
|
339 elseif strcmpi(option.method,'Spectro')
|
wolffd@0
|
340 d = get(orig,'Data');
|
wolffd@0
|
341 fp = get(orig,'FramePos');
|
wolffd@0
|
342 sr = get(orig,'Sampling');
|
wolffd@0
|
343 ch = get(orig,'Channels');
|
wolffd@0
|
344 ph = get(orig,'Phase');
|
wolffd@0
|
345 for h = 1:length(d)
|
wolffd@0
|
346 sr{h} = 0;
|
wolffd@0
|
347 for i = 1:length(d{h})
|
wolffd@0
|
348 if size(d{h}{i},3)>1 % Already in bands (channels in 3d dim)
|
wolffd@0
|
349 d{h}{i} = permute(sum(d{h}{i}),[2 1 3]);
|
wolffd@0
|
350 ph{h}{i} = permute(ph{h}{i},[2 1 3]);
|
wolffd@0
|
351 else % Simple spectrogram, frequency range sent to 3d dim
|
wolffd@0
|
352 d{h}{i} = permute(d{h}{i},[2 3 1]);
|
wolffd@0
|
353 ph{h}{i} = permute(ph{h}{i},[2 3 1]);
|
wolffd@0
|
354 end
|
wolffd@0
|
355 p{h}{i} = mean(fp{h}{i})';
|
wolffd@0
|
356 if not(sr{h}) && size(fp{h}{i},2)>1
|
wolffd@0
|
357 sr{h} = 1/(fp{h}{i}(1,2)-fp{h}{i}(1,1));
|
wolffd@0
|
358 end
|
wolffd@0
|
359 end
|
wolffd@0
|
360 if not(sr{h})
|
wolffd@0
|
361 warning('WARNING IN MIRENVELOPE: The frame decomposition did not succeed. Either the input is of too short duration, or the chunk size is too low.');
|
wolffd@0
|
362 end
|
wolffd@0
|
363 ch{h} = (1:size(d{h}{1},3))';
|
wolffd@0
|
364 end
|
wolffd@0
|
365 e.downsampl = 0;
|
wolffd@0
|
366 e.hwr = 0;
|
wolffd@0
|
367 e.diff = 0;
|
wolffd@0
|
368 %e.todelete = {};
|
wolffd@0
|
369 e.method = 'Spectro';
|
wolffd@0
|
370 e.phase = ph;
|
wolffd@0
|
371 e = class(e,'mirenvelope',mirtemporal(orig));
|
wolffd@0
|
372 e = set(e,'Title','Envelope','Data',d,'Pos',p,...
|
wolffd@0
|
373 'Sampling',sr,'Channels',ch);
|
wolffd@0
|
374 postoption.trim = 0;
|
wolffd@0
|
375 postoption.ds = 0;
|
wolffd@0
|
376 e = post(e,postoption);
|
wolffd@0
|
377 else
|
wolffd@0
|
378 if isnan(option.zp)
|
wolffd@0
|
379 if strcmpi(option.filter,'IIR')
|
wolffd@0
|
380 option.zp = 1;
|
wolffd@0
|
381 else
|
wolffd@0
|
382 option.zp = 0;
|
wolffd@0
|
383 end
|
wolffd@0
|
384 end
|
wolffd@0
|
385 if option.zp == 1
|
wolffd@0
|
386 option.decim = 0;
|
wolffd@0
|
387 end
|
wolffd@0
|
388 e.downsampl = 1;
|
wolffd@0
|
389 e.hwr = 0;
|
wolffd@0
|
390 e.diff = 0;
|
wolffd@0
|
391 e.method = option.filter;
|
wolffd@0
|
392 e.phase = {};
|
wolffd@0
|
393 e = class(e,'mirenvelope',mirtemporal(orig));
|
wolffd@0
|
394 e = purgedata(e);
|
wolffd@0
|
395 e = set(e,'Title','Envelope');
|
wolffd@0
|
396 sig = get(e,'Data');
|
wolffd@0
|
397 x = get(e,'Pos');
|
wolffd@0
|
398 sr = get(e,'Sampling');
|
wolffd@0
|
399 disp('Extracting envelope...')
|
wolffd@0
|
400 d = cell(1,length(sig));
|
wolffd@0
|
401 [state e] = gettmp(orig,e);
|
wolffd@0
|
402 for k = 1:length(sig)
|
wolffd@0
|
403 if option.decim
|
wolffd@0
|
404 sr{k} = sr{k}/option.decim;
|
wolffd@0
|
405 end
|
wolffd@0
|
406 if strcmpi(option.filter,'IIR')
|
wolffd@0
|
407 a2 = exp(-1/(option.tau*sr{k})); % filter coefficient
|
wolffd@0
|
408 a = [1 -a2];
|
wolffd@0
|
409 b = 1-a2;
|
wolffd@0
|
410 elseif strcmpi(option.filter,'HalfHann')
|
wolffd@0
|
411 a = 1;
|
wolffd@0
|
412 b = hann(sr{k}*.4);
|
wolffd@0
|
413 b = b(ceil(length(b)/2):end);
|
wolffd@0
|
414 end
|
wolffd@0
|
415 d{k} = cell(1,length(sig{k}));
|
wolffd@0
|
416 for i = 1:length(sig{k})
|
wolffd@0
|
417 sigi = sig{k}{i};
|
wolffd@0
|
418 if option.zp == 2
|
wolffd@0
|
419 sigi = flipdim(sigi,1);
|
wolffd@0
|
420 end
|
wolffd@0
|
421 if option.hilb
|
wolffd@0
|
422 try
|
wolffd@0
|
423 for h = 1:size(sigi,2)
|
wolffd@0
|
424 for j = 1:size(sigi,3)
|
wolffd@0
|
425 sigi(:,h,j) = hilbert(sigi(:,h,j));
|
wolffd@0
|
426 end
|
wolffd@0
|
427 end
|
wolffd@0
|
428 catch
|
wolffd@0
|
429 disp('Signal Processing Toolbox does not seem to be installed. No Hilbert transform.');
|
wolffd@0
|
430 end
|
wolffd@0
|
431 end
|
wolffd@0
|
432 sigi = abs(sigi);
|
wolffd@0
|
433
|
wolffd@0
|
434 if option.decim
|
wolffd@0
|
435 dsigi = zeros(ceil(size(sigi,1)/option.decim),...
|
wolffd@0
|
436 size(sigi,2),size(sigi,3));
|
wolffd@0
|
437 for f = 1:size(sigi,2)
|
wolffd@0
|
438 for c = 1:size(sigi,3)
|
wolffd@0
|
439 dsigi(:,f,c) = decimate(sigi(:,f,c),option.decim);
|
wolffd@0
|
440 end
|
wolffd@0
|
441 end
|
wolffd@0
|
442 sigi = dsigi;
|
wolffd@0
|
443 clear dsigi
|
wolffd@0
|
444 x{k}{i} = x{k}{i}(1:option.decim:end,:,:);
|
wolffd@0
|
445 end
|
wolffd@0
|
446
|
wolffd@0
|
447 % tmp = filtfilt(1-a,[1 -a],sigi); % zero-phase IIR filter for smoothing the envelope
|
wolffd@0
|
448
|
wolffd@0
|
449 % Manual filtfilt
|
wolffd@0
|
450 emptystate = isempty(state);
|
wolffd@0
|
451 tmp = zeros(size(sigi));
|
wolffd@0
|
452 for c = 1:size(sigi,3)
|
wolffd@0
|
453 if emptystate
|
wolffd@0
|
454 [tmp(:,:,c) state(:,c,1)] = filter(b,a,sigi(:,:,c));
|
wolffd@0
|
455 else
|
wolffd@0
|
456 [tmp(:,:,c) state(:,c,1)] = filter(b,a,sigi(:,:,c),...
|
wolffd@0
|
457 state(:,c,1));
|
wolffd@0
|
458 end
|
wolffd@0
|
459 end
|
wolffd@0
|
460
|
wolffd@0
|
461 tmp = max(tmp,0); % For security reason...
|
wolffd@0
|
462 if option.zp == 2
|
wolffd@0
|
463 tmp = flipdim(tmp,1);
|
wolffd@0
|
464 end
|
wolffd@0
|
465 d{k}{i} = tmp;
|
wolffd@0
|
466 %td{k} = round(option.tau*sr{k}*1.5);
|
wolffd@0
|
467 end
|
wolffd@0
|
468 end
|
wolffd@0
|
469 e = set(e,'Data',d,'Pos',x,'Sampling',sr); %,'ToDelete',td
|
wolffd@0
|
470 e = settmp(e,state);
|
wolffd@0
|
471 if not(option.zp == 2)
|
wolffd@0
|
472 e = post(e,postoption);
|
wolffd@0
|
473 end
|
wolffd@0
|
474 end
|
wolffd@0
|
475 if isfield(option,'presel') && ischar(option.presel) && ...
|
wolffd@0
|
476 strcmpi(option.presel,'Klapuri06')
|
wolffd@0
|
477 e = mirsum(e,'Adjacent',10);
|
wolffd@0
|
478 end
|
wolffd@0
|
479
|
wolffd@0
|
480
|
wolffd@0
|
481 function e = post(e,postoption)
|
wolffd@0
|
482 if isempty(postoption)
|
wolffd@0
|
483 return
|
wolffd@0
|
484 end
|
wolffd@0
|
485 if isfield(postoption,'lambda') && not(postoption.lambda)
|
wolffd@0
|
486 postoption.lambda = 1;
|
wolffd@0
|
487 end
|
wolffd@0
|
488 d = get(e,'Data');
|
wolffd@0
|
489 tp = get(e,'Time');
|
wolffd@0
|
490 sr = get(e,'Sampling');
|
wolffd@0
|
491 ds = get(e,'DownSampling');
|
wolffd@0
|
492 ph = get(e,'Phase');
|
wolffd@0
|
493 for k = 1:length(d)
|
wolffd@0
|
494 if isfield(postoption,'sampling')
|
wolffd@0
|
495 if postoption.sampling
|
wolffd@0
|
496 newsr = postoption.sampling;
|
wolffd@0
|
497 elseif isfield(postoption,'ds') && postoption.ds>1
|
wolffd@0
|
498 newsr = sr{k}/postoption.ds;
|
wolffd@0
|
499 else
|
wolffd@0
|
500 newsr = sr{k};
|
wolffd@0
|
501 end
|
wolffd@0
|
502 end
|
wolffd@0
|
503 if isfield(postoption,'up') && postoption.up
|
wolffd@0
|
504 [z,p,gain] = butter(6,10/newsr/postoption.up*2,'low');
|
wolffd@0
|
505 [sos,g] = zp2sos(z,p,gain);
|
wolffd@0
|
506 Hd = dfilt.df2tsos(sos,g);
|
wolffd@0
|
507 end
|
wolffd@0
|
508 for i = 1:length(d{k})
|
wolffd@0
|
509 if isfield(postoption,'sampling') && postoption.sampling
|
wolffd@0
|
510 if and(sr{k}, not(sr{k} == postoption.sampling))
|
wolffd@0
|
511 dk = d{k}{i};
|
wolffd@0
|
512 for j = 1:size(dk,3)
|
wolffd@0
|
513 if not(sr{k} == round(sr{k}))
|
wolffd@0
|
514 mirerror('mirenvelope','The ''Sampling'' postoption cannot be used after using the ''Down'' postoption.');
|
wolffd@0
|
515 end
|
wolffd@0
|
516 rk(:,:,j) = resample(dk(:,:,j),postoption.sampling,sr{k});
|
wolffd@0
|
517 end
|
wolffd@0
|
518 d{k}{i} = rk;
|
wolffd@0
|
519 tp{k}{i} = repmat((0:size(d{k}{i},1)-1)',...
|
wolffd@0
|
520 [1 1 size(tp{k}{i},3)])...
|
wolffd@0
|
521 /postoption.sampling + tp{k}{i}(1,:,:);
|
wolffd@0
|
522 if not(iscell(ds))
|
wolffd@0
|
523 ds = cell(length(d));
|
wolffd@0
|
524 end
|
wolffd@0
|
525 ds{k} = round(sr{k}/postoption.sampling);
|
wolffd@0
|
526 end
|
wolffd@0
|
527 elseif isfield(postoption,'ds') && postoption.ds>1
|
wolffd@0
|
528 if not(postoption.ds == round(postoption.ds))
|
wolffd@0
|
529 mirerror('mirenvelope','The ''Down'' sampling rate should be an integer.');
|
wolffd@0
|
530 end
|
wolffd@0
|
531 ds = postoption.ds;
|
wolffd@0
|
532 tp{k}{i} = tp{k}{i}(1:ds:end,:,:); % Downsampling...
|
wolffd@0
|
533 d{k}{i} = d{k}{i}(1:ds:end,:,:);
|
wolffd@0
|
534 end
|
wolffd@0
|
535 if isfield(postoption,'sampling')
|
wolffd@0
|
536 if not(strcmpi(e.method,'Spectro')) && postoption.trim
|
wolffd@0
|
537 tdk = round(newsr*.1);
|
wolffd@0
|
538 d{k}{i}(1:tdk,:,:) = repmat(d{k}{i}(tdk,:,:),[tdk,1,1]);
|
wolffd@0
|
539 d{k}{i}(end-tdk+1:end,:,:) = repmat(d{k}{i}(end-tdk,:,:),[tdk,1,1]);
|
wolffd@0
|
540 end
|
wolffd@0
|
541 if postoption.log
|
wolffd@0
|
542 d{k}{i} = log10(d{k}{i});
|
wolffd@0
|
543 end
|
wolffd@0
|
544 if postoption.mu
|
wolffd@0
|
545 dki = max(0,d{k}{i});
|
wolffd@0
|
546 mu = postoption.mu;
|
wolffd@0
|
547 dki = log(1+mu*dki)/log(1+mu);
|
wolffd@0
|
548 dki(~isfinite(d{k}{i})) = NaN;
|
wolffd@0
|
549 d{k}{i} = dki;
|
wolffd@0
|
550 end
|
wolffd@0
|
551 if postoption.power
|
wolffd@0
|
552 d{k}{i} = d{k}{i}.^2;
|
wolffd@0
|
553 end
|
wolffd@0
|
554 if postoption.up
|
wolffd@0
|
555 dki = zeros(size(d{k}{i},1).*postoption.up,...
|
wolffd@0
|
556 size(d{k}{i},2),size(d{k}{i},3));
|
wolffd@0
|
557 dki(1:postoption.up:end,:,:) = d{k}{i};
|
wolffd@0
|
558 dki = filter(Hd,[dki;...
|
wolffd@0
|
559 zeros(6,size(d{k}{i},2),size(d{k}{i},3))]);
|
wolffd@0
|
560 d{k}{i} = dki(1+ceil(6/2):end-floor(6/2),:,:);
|
wolffd@0
|
561 tki = zeros(size(tp{k}{i},1).*postoption.up,...
|
wolffd@0
|
562 size(tp{k}{i},2),...
|
wolffd@0
|
563 size(tp{k}{i},3));
|
wolffd@0
|
564 dt = repmat((tp{k}{i}(2)-tp{k}{i}(1))...
|
wolffd@0
|
565 /postoption.up,...
|
wolffd@0
|
566 [size(tp{k}{i},1),1,1]);
|
wolffd@0
|
567 for j = 1:postoption.up
|
wolffd@0
|
568 tki(j:postoption.up:end,:,:) = tp{k}{i}+dt*(j-1);
|
wolffd@0
|
569 end
|
wolffd@0
|
570 tp{k}{i} = tki;
|
wolffd@0
|
571 newsr = sr{k}*postoption.up;
|
wolffd@0
|
572 end
|
wolffd@0
|
573 if (postoption.diffhwr || postoption.diff) && ...
|
wolffd@0
|
574 not(get(e,'Diff'))
|
wolffd@0
|
575 tp{k}{i} = tp{k}{i}(1:end-1,:,:);
|
wolffd@0
|
576 order = max(postoption.diffhwr,postoption.diff);
|
wolffd@0
|
577 if postoption.complex
|
wolffd@0
|
578 dph = diff(ph{k}{i},2);
|
wolffd@0
|
579 dph = dph/(2*pi);% - round(dph/(2*pi));
|
wolffd@0
|
580 ddki = sqrt(d{k}{i}(3:end,:,:).^2 + d{k}{i}(2:end-1,:,:).^2 ...
|
wolffd@0
|
581 - 2.*d{k}{i}(3:end,:,:)...
|
wolffd@0
|
582 .*d{k}{i}(2:end-1,:,:)...
|
wolffd@0
|
583 .*cos(dph));
|
wolffd@0
|
584 d{k}{i} = d{k}{i}(2:end,:,:);
|
wolffd@0
|
585 tp{k}{i} = tp{k}{i}(2:end,:,:);
|
wolffd@0
|
586 elseif order == 1
|
wolffd@0
|
587 ddki = diff(d{k}{i},1,1);
|
wolffd@0
|
588 else
|
wolffd@0
|
589 b = firls(order,[0 0.9],[0 0.9*pi],'differentiator');
|
wolffd@0
|
590 ddki = filter(b,1,...
|
wolffd@0
|
591 [repmat(d{k}{i}(1,:,:),[order,1,1]);...
|
wolffd@0
|
592 d{k}{i};...
|
wolffd@0
|
593 repmat(d{k}{i}(end,:,:),[order,1,1])]);
|
wolffd@0
|
594 ddki = ddki(order+1:end-order-1,:,:);
|
wolffd@0
|
595 end
|
wolffd@0
|
596 if postoption.diffhwr
|
wolffd@0
|
597 ddki = hwr(ddki);
|
wolffd@0
|
598 end
|
wolffd@0
|
599 d{k}{i} = (1-postoption.lambda)*d{k}{i}(1:end-1,:,:)...
|
wolffd@0
|
600 + postoption.lambda*sr{k}/10*ddki;
|
wolffd@0
|
601 end
|
wolffd@0
|
602 if postoption.aver
|
wolffd@0
|
603 y = filter(ones(1,postoption.aver),1,...
|
wolffd@0
|
604 [d{k}{i};zeros(postoption.aver,...
|
wolffd@0
|
605 size(d{k}{i},2),...
|
wolffd@0
|
606 size(d{k}{i},3))]);
|
wolffd@0
|
607 d{k}{i} = y(1+ceil(postoption.aver/2):...
|
wolffd@0
|
608 end-floor(postoption.aver/2),:,:);
|
wolffd@0
|
609 end
|
wolffd@0
|
610 if postoption.gauss
|
wolffd@0
|
611 sigma = postoption.gauss;
|
wolffd@0
|
612 gauss = 1/sigma/2/pi...
|
wolffd@0
|
613 *exp(- (-4*sigma:4*sigma).^2 /2/sigma^2);
|
wolffd@0
|
614 y = filter(gauss,1,[d{k}{i};zeros(4*sigma,1,size(d{k}{i},3))]);
|
wolffd@0
|
615 y = y(4*sigma:end,:,:);
|
wolffd@0
|
616 d{k}{i} = y(1:size(d{k}{i},1),:,:);
|
wolffd@0
|
617 end
|
wolffd@0
|
618 if postoption.chwr
|
wolffd@0
|
619 d{k}{i} = center(d{k}{i});
|
wolffd@0
|
620 d{k}{i} = hwr(d{k}{i});
|
wolffd@0
|
621 end
|
wolffd@0
|
622 if postoption.hwr
|
wolffd@0
|
623 d{k}{i} = hwr(d{k}{i});
|
wolffd@0
|
624 end
|
wolffd@0
|
625 if postoption.c
|
wolffd@0
|
626 d{k}{i} = center(d{k}{i});
|
wolffd@0
|
627 end
|
wolffd@0
|
628 if postoption.norm
|
wolffd@0
|
629 d{k}{i} = d{k}{i}./repmat(max(abs(d{k}{i})),...
|
wolffd@0
|
630 [size(d{k}{i},1),1,1]);
|
wolffd@0
|
631 end
|
wolffd@0
|
632 end
|
wolffd@0
|
633 end
|
wolffd@0
|
634 if isfield(postoption,'sampling')
|
wolffd@0
|
635 sr{k} = newsr;
|
wolffd@0
|
636 end
|
wolffd@0
|
637 end
|
wolffd@0
|
638 if isfield(postoption,'ds') && postoption.ds>1
|
wolffd@0
|
639 e = set(e,'DownSampling',postoption.ds,'Sampling',sr);
|
wolffd@0
|
640 elseif isfield(postoption,'sampling') && postoption.sampling
|
wolffd@0
|
641 e = set(e,'DownSampling',ds,'Sampling',sr);
|
wolffd@0
|
642 elseif isfield(postoption,'up') && postoption.up
|
wolffd@0
|
643 e = set(e,'Sampling',sr);
|
wolffd@0
|
644 end
|
wolffd@0
|
645 if isfield(postoption,'sampling')
|
wolffd@0
|
646 if postoption.hwr
|
wolffd@0
|
647 e = set(e,'Halfwave',1);
|
wolffd@0
|
648 end
|
wolffd@0
|
649 if postoption.diff
|
wolffd@0
|
650 e = set(e,'Diff',1,'Halfwave',0,'Title','Differentiated envelope');
|
wolffd@0
|
651 end
|
wolffd@0
|
652 if postoption.diffhwr
|
wolffd@0
|
653 e = set(e,'Diff',1,'Halfwave',1,'Centered',0);
|
wolffd@0
|
654 end
|
wolffd@0
|
655 if postoption.c
|
wolffd@0
|
656 e = set(e,'Centered',1);
|
wolffd@0
|
657 end
|
wolffd@0
|
658 if postoption.chwr
|
wolffd@0
|
659 e = set(e,'Halfwave',1,'Centered',1);
|
wolffd@0
|
660 end
|
wolffd@0
|
661 end
|
wolffd@0
|
662 e = set(e,'Data',d,'Time',tp);
|
wolffd@0
|
663 %if isfield(postoption,'frame') && isstruct(postoption.frame)
|
wolffd@0
|
664 % e = mirframenow(e,postoption);
|
wolffd@0
|
665 %end |