Mercurial > hg > camir-aes2014
comparison toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirflux.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function varargout = mirflux(orig,varargin) | |
2 % f = mirflux(x) measures distance between successive frames. | |
3 % First argument: | |
4 % If x is a spectrum, this corresponds to spectral flux. | |
5 % But the flux of any other data can be computed as well. | |
6 % If x is an audio file or audio signal, the spectral flux is | |
7 % computed by default. | |
8 % Optional arguments: | |
9 % f = mirflux(x,'Frame',...) specifies the frame parameters, if x is | |
10 % not already decomposed into frames. Default values are frame | |
11 % length of .2 seconds and hop factor of 1.3. | |
12 % f = mirflux(x,'Dist',d) specifies the distance between | |
13 % successive frames: (IF 'COMPLEX': DISTANCE = 'CITY' ALWAYS) | |
14 % d = 'Euclidian': Euclidian distance (Default) | |
15 % d = 'City': City-block distance | |
16 % d = 'Cosine': Cosine distance (or normalized correlation) | |
17 % f = mirflux(...,'Inc'): Only positive difference between frames are | |
18 % summed, in order to focus on increase of energy solely. | |
19 % f = mirflux(...,'Complex'), for spectral flux, combines use of | |
20 % energy and phase information (Bello et al, 2004). | |
21 % f = mirflux(...,'Halfwave'): performs a half-wave rectification on | |
22 % the result. | |
23 % f = mirflux(...,'Median',l,C): removes small spurious peaks by | |
24 % subtracting to the result its median filtering. The median | |
25 % filter computes the point-wise median inside a window of length | |
26 % l (in seconds), that includes a same number of previous and | |
27 % next samples. C is a scaling factor whose purpose is to | |
28 % artificially rise the curve slightly above the steady state of | |
29 % the signal. If no parameters are given, the default values are: | |
30 % l = 0.2 s. and C = 1.3 | |
31 % f = mirflux(...,'Median',l,C,'Halfwave'): The scaled median | |
32 % filtering is designed to be succeeded by the half-wave | |
33 % rectification process in order to select peaks above the | |
34 % dynamic threshold calculated with the help of the median | |
35 % filter. The resulting signal is called "detection function" | |
36 % (Alonso, David, Richard, 2004). To ensure accurate detection, | |
37 % the length l of the median filter must be longer than the | |
38 % average width of the peaks of the detection function. | |
39 % | |
40 % (Bello et al, 2004) Juan P. Bello, Chris Duxbury, Mike Davies, and Mark | |
41 % Sandler, On the Use of Phase and Energy for Musical Onset Detection in | |
42 % the Complex Domain, IEEE SIGNAL PROCESSING LETTERS, VOL. 11, NO. 6, | |
43 % JUNE 2004 | |
44 | |
45 dist.key = 'Dist'; | |
46 dist.type = 'String'; | |
47 dist.choice = {'Euclidian','City','Cosine'}; %PDIST???? (euclidean) | |
48 dist.default = 'Euclidian'; | |
49 option.dist = dist; | |
50 | |
51 inc.key = 'Inc'; | |
52 inc.type = 'Boolean'; | |
53 inc.default = 0; | |
54 option.inc = inc; | |
55 | |
56 complex.key = 'Complex'; | |
57 complex.type = 'Boolean'; | |
58 complex.default = 0; | |
59 option.complex = complex; | |
60 | |
61 h.key = 'Halfwave'; | |
62 h.type = 'Boolean'; | |
63 h.default = 0; | |
64 h.when = 'After'; | |
65 option.h = h; | |
66 | |
67 median.key = 'Median'; | |
68 median.type = 'Integer'; | |
69 median.number = 2; | |
70 median.default = [0 0]; | |
71 median.keydefault = [.2 1.3]; | |
72 median.when = 'After'; | |
73 option.median = median; | |
74 | |
75 frame.key = 'Frame'; | |
76 frame.type = 'Integer'; | |
77 frame.number = 2; | |
78 frame.default = [.05 .5]; | |
79 option.frame = frame; | |
80 | |
81 specif.option = option; | |
82 | |
83 varargout = mirfunction(@mirflux,orig,varargin,nargout,specif,@init,@main); | |
84 | |
85 | |
86 function [x type] = init(x,option) | |
87 if isamir(x,'miraudio') | |
88 if isframed(x) | |
89 x = mirspectrum(x); | |
90 else | |
91 x = mirspectrum(x,'Frame',option.frame.length.val,option.frame.length.unit,... | |
92 option.frame.hop.val,option.frame.hop.unit); | |
93 end | |
94 end | |
95 if isa(x,'mirdesign') | |
96 x = set(x,'Overlap',1); | |
97 end | |
98 type = 'mirscalar'; | |
99 | |
100 | |
101 function f = main(s,option,postoption) | |
102 if iscell(s) | |
103 s = s{1}; | |
104 end | |
105 t = get(s,'Title'); | |
106 if isa(s,'mirscalar') && ... | |
107 (strcmp(t,'Harmonic Change Detection Function') || ... | |
108 (length(t)>4 && strcmp(t(end-3:end),'flux')) || ... | |
109 (length(t)>5 && strcmp(t(end-4:end-1),'flux'))) | |
110 if not(isempty(postoption)) | |
111 f = modif(s,postoption); | |
112 end | |
113 else | |
114 if isa(s,'mirspectrum') | |
115 t = 'Spectral'; | |
116 end | |
117 m = get(s,'Data'); | |
118 if option.complex | |
119 if not(isa(s,'mirspectrum')) | |
120 error('ERROR IN MIRFLUX: ''Complex'' option only defined for spectral flux.'); | |
121 end | |
122 ph = get(s,'Phase'); | |
123 end | |
124 param.complex = option.complex; | |
125 param.inc = option.inc; | |
126 fp = get(s,'FramePos'); | |
127 if strcmp(t,'Tonal centroid') | |
128 t = 'Harmonic Change Detection Function'; | |
129 else | |
130 t = [t,' flux']; | |
131 end | |
132 disp(['Computing ' t '...']) | |
133 ff = cell(1,length(m)); | |
134 newsr = cell(1,length(m)); | |
135 dist = str2func(option.dist); | |
136 %[tmp s] = gettmp(s); %get(s,'Tmp'); | |
137 for h = 1:length(m) | |
138 ff{h} = cell(1,length(m{h})); | |
139 if not(iscell(m{h})) | |
140 m{h} = {m{h}}; | |
141 end | |
142 for i = 1:length(m{h}) | |
143 mi = m{h}{i}; | |
144 if size(mi,3) > 1 && size(mi,1) == 1 | |
145 mi = reshape(mi,size(mi,2),size(mi,3))'; | |
146 end | |
147 if option.complex | |
148 phi = ph{h}{i}; | |
149 end | |
150 fpi = fp{h}{i}; | |
151 %if 0 %not(isempty(tmp)) && isstruct(tmp) && isfield(tmp,'mi') | |
152 % mi = [tmp.mi mi]; | |
153 % fpi = [tmp.fpi fpi]; | |
154 %end | |
155 nc = size(mi,2); | |
156 np = size(mi,3); | |
157 if nc == 1 | |
158 warning('WARNING IN MIRFLUX: Flux can only be computed on signal decomposed into frames.'); | |
159 ff{h}{i} = NaN(1,1,np); | |
160 else | |
161 if option.complex | |
162 fl = zeros(1,nc-2,np); | |
163 for k = 1:np | |
164 d = diff(phi(:,:,k),2,2); | |
165 d = d/(2*pi) - round(d/(2*pi)); | |
166 g = sqrt(mi(:,3:end,k).^2 + mi(:,2:(end-1),k).^2 ... | |
167 - 2.*mi(:,3:end,k)... | |
168 .*mi(:,2:(end-1),k)... | |
169 .*cos(d)); | |
170 fl(1,:,k) = sum(g); | |
171 end | |
172 fp{h}{i} = fpi(:,3:end); | |
173 else | |
174 fl = zeros(1,nc-1,np); | |
175 for k = 1:np | |
176 for j = 1:nc-1 | |
177 fl(1,j,k) = dist(mi(:,j,k),mi(:,j+1,k),option.inc); | |
178 end | |
179 end | |
180 fp{h}{i} = fpi(:,2:end); | |
181 end | |
182 ff{h}{i} = fl; | |
183 %tmp.mi = mi(:,end,:); | |
184 %tmp.fpi = fpi(:,end,:); | |
185 end | |
186 end | |
187 %tmp = []; | |
188 if size(fpi,2)<2 | |
189 newsr{h} = 0; | |
190 else | |
191 newsr{h} = 1/(fpi(1,2)-fpi(1,1)); | |
192 end | |
193 end | |
194 f = mirscalar(s,'Data',ff,'FramePos',fp,'Sampling',newsr,... | |
195 'Title',t,'Parameter',param); %,'Tmp',tmp); | |
196 %f = settmp(f,tmp); | |
197 if not(isempty(postoption)) | |
198 f = modif(f,postoption); | |
199 end | |
200 end | |
201 | |
202 | |
203 function f = modif(f,option) | |
204 fl = get(f,'Data'); | |
205 r = get(f,'Sampling'); | |
206 for h = 1:length(fl) | |
207 for i = 1:length(fl{h}) | |
208 fli = fl{h}{i}; | |
209 nc = size(fli,2); | |
210 np = size(fli,3); | |
211 if option.median(1) | |
212 ffi = zeros(1,nc,np); | |
213 lr = round(option.median(1)*r{i}); | |
214 for k = 1:np | |
215 for j = 1:nc | |
216 ffi(:,j,k) = fli(:,j,k) - ... | |
217 option.median(2) * median(fli(:,max(1,j-lr):min(nc-1,j+lr),k)); | |
218 end | |
219 end | |
220 fli = ffi; | |
221 end | |
222 if option.h | |
223 fli = hwr(fli); | |
224 end | |
225 fl{h}{i} = fli; | |
226 end | |
227 end | |
228 f = set(f,'Data',fl); | |
229 | |
230 | |
231 function y = Euclidian(mi,mj,inc) | |
232 if inc | |
233 y = sqrt(sum(max(0,(mj-mi)).^2)); | |
234 else | |
235 y = sqrt(sum((mj-mi).^2)); | |
236 end | |
237 | |
238 | |
239 function y = City(mi,mj,inc) | |
240 if inc | |
241 y = sum(max(0,(mj-mi))); | |
242 else | |
243 y = sum(abs(mj-mi)); | |
244 end | |
245 | |
246 | |
247 function d = Cosine(r,s,inc) | |
248 nr = sqrt(r'*r); | |
249 ns = sqrt(s'*s); | |
250 if or(nr == 0, ns == 0); | |
251 d = 1; | |
252 else | |
253 d = 1 - r'*s/nr/ns; | |
254 end |