comparison toolboxes/MIRtoolbox1.3.2/MIRToolbox/@mirchromagram/mirchromagram.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 = mirchromagram(orig,varargin)
2 % c = mirchromagram(x) computes the chromagram, or distribution of energy
3 % along pitches, of the audio signal x.
4 % (x can be the name of an audio file as well, or a spectrum, ...)
5 % Optional argument:
6 % c = mirchromagram(...,'Tuning',t): specifies the central frequency
7 % (in Hz.) associated to chroma C.
8 % Default value, t = 261.6256 Hz
9 % c = mirchromagram(...,'Wrap',w): specifies whether the chromagram is
10 % wrapped or not.
11 % w = 1: groups all the pitches belonging to same pitch classes
12 % (default value)
13 % w = 0: pitches are considered as absolute values.
14 % c = mirchromagram(...,'Frame',l,h) orders a frame decomposition of window
15 % length l (in seconds) and hop factor h, expressed relatively to
16 % the window length. For instance h = 1 indicates no overlap.
17 % Default values: l = .2 seconds and h = .05
18 % c = mirchromagram(...,'Center'): centers the result.
19 % c = mirchromagram(...,'Normal',n): performs a n-norm of the
20 % resulting chromagram. Toggled off if n = 0
21 % Default value: n = Inf (corresponding to a normalization by
22 % the maximum value).
23 % c = mirchromagram(...,'Pitch',p): specifies how to label chromas in
24 % the figures.
25 % p = 1: chromas are labeled using pitch names (default)
26 % alternative syntax: chromagram(...,'Pitch')
27 % p = 0: chromas are labeled using MIDI pitch numbers
28 % c = mirchromagram(...,'Triangle'): weight the contribution of each
29 % frequency with respect to the distance with the actual
30 % frequency of the corresponding chroma.
31 % c = mirchromagram(...,'Weight',o): specifies the relative radius of
32 % the weighting window, with respect to the distance between
33 % frequencies of successive chromas.
34 % o = 1: each window begins at the centers of the previous one.
35 % o = .5: each window begins at the end of the previous one.
36 % (default value)
37 % mirchromagram(...,'Min',mi) indicates the lowest frequency taken into
38 % consideration in the spectrum computation, expressed in Hz.
39 % Default value: 100 Hz. (Gomez, 2006)
40 % mirchromagram(...,'Max',ma) indicates the highest frequency taken into
41 % consideration in the spectrum computation, expressed in Hz.
42 % This upper limit is further shifted to a highest value until
43 % the frequency range covers an exact multiple of octaves.
44 % Default value: 5000 Hz. (Gomez, 2006)
45 % mirchromagram(...,'Res',r) indicates the resolution of the
46 % chromagram in number of bins per octave.
47 % Default value, r = 12.
48 %
49 % Gómez, E. (2006). Tonal description of music audio signal. Phd thesis,
50 % Universitat Pompeu Fabra, Barcelona .
51
52 cen.key = 'Center';
53 cen.type = 'Boolean';
54 cen.default = 0;
55 option.cen = cen;
56
57 nor.key = {'Normal','Norm'};
58 nor.type = 'Integer';
59 nor.default = Inf;
60 option.nor = nor;
61
62 wth.key = 'Weight';
63 wth.type = 'Integer';
64 wth.default = .5;
65 option.wth = wth;
66
67 tri.key = 'Triangle';
68 tri.type = 'Boolean';
69 tri.default = 0;
70 option.tri = tri;
71
72 wrp.key = 'Wrap';
73 wrp.type = 'Boolean';
74 wrp.default = 1;
75 option.wrp = wrp;
76
77 plabel.key = 'Pitch';
78 plabel.type = 'Boolean';
79 plabel.default = 1;
80 option.plabel = plabel;
81
82 thr.key = {'Threshold','dB'};
83 thr.type = 'Integer';
84 thr.default = 20;
85 option.thr = thr;
86
87 min.key = 'Min';
88 min.type = 'Integer';
89 min.default = 100;
90 option.min = min;
91
92 max.key = 'Max';
93 max.type = 'Integer';
94 max.default = 5000;
95 option.max = max;
96
97 res.key = 'Res';
98 res.type = 'Integer';
99 res.default = 12;
100 option.res = res;
101
102 origin.key = 'Tuning';
103 origin.type = 'Integer';
104 origin.default = 261.6256;
105 option.origin = origin;
106
107 specif.option = option;
108 specif.defaultframelength = .2;
109 specif.defaultframehop = .05;
110
111 varargout = mirfunction(@mirchromagram,orig,varargin,nargout,specif,@init,@main);
112
113
114 function [x type] = init(x,option)
115 if isamir(x,'mirtemporal') || isamir(x,'mirspectrum')
116 freqmin = option.min;
117 freqmax = freqmin*2;
118 while freqmax < option.max
119 freqmax = freqmax*2;
120 end
121 %freqres = freqmin*(2.^(1/option.res)-1);
122 % Minimal frequency resolution should correspond to frequency range
123 % between the first two bins of the chromagram
124
125 x = mirspectrum(x,'dB',option.thr,'Min',freqmin,'Max',freqmax,...
126 'NormalInput','MinRes',option.res,'OctaveRatio',.85);
127 %freqres*.5,...
128 % 'WarningRes',freqres);
129 end
130 type = 'mirchromagram';
131
132
133 function c = main(orig,option,postoption)
134 if iscell(orig)
135 orig = orig{1};
136 end
137 if option.res == 12
138 chromascale = {'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'};
139 else
140 chromascale = 1:option.res;
141 option.plabel = 0;
142 end
143 if isa(orig,'mirchromagram')
144 c = modif(orig,option,chromascale);
145 else
146 c.plabel = 1;
147 c.wrap = 0;
148 c.chromaclass = {};
149 c.chromafreq = {};
150 c.register = {};
151 c = class(c,'mirchromagram',mirdata(orig));
152 c = purgedata(c);
153 c = set(c,'Title','Chromagram','Ord','magnitude','Interpolable',0);
154 if option.wrp
155 c = set(c,'Abs','chroma class');
156 else
157 c = set(c,'Abs','chroma');
158 end
159 m = get(orig,'Magnitude');
160 f = get(orig,'Frequency');
161 %disp('Computing chromagram...')
162 fs = get(orig,'Sampling');
163 n = cell(1,length(m)); % The final structured list of magnitudes.
164 cc = cell(1,length(m)); % The final structured list of chroma classes.
165 o = cell(1,length(m)); % The final structured list of octave registers.
166 p = cell(1,length(m)); % The final structured list of chromas.
167 cf = cell(1,length(m)); % The final structured list of central frequencies related to chromas.
168 for i = 1:length(m)
169 mi = m{i};
170 fi = f{i};
171 if not(iscell(mi))
172 mi = {mi};
173 fi = {fi};
174 end
175 ni = cell(1,length(mi)); % The list of magnitudes.
176 ci = cell(1,length(mi)); % The list of chroma classes.
177 oi = cell(1,length(mi)); % The list of octave registers.
178 pi = cell(1,length(mi)); % The list of absolute chromas.
179 cfi = cell(1,length(mi)); % The central frequency of each chroma.
180 for j = 1:length(mi)
181 mj = mi{j};
182 fj = fi{j};
183
184 % Let's remove the frequencies exceeding the last whole octave.
185 minfj = min(min(min(fj)));
186 maxfj = max(max(max(fj)));
187 maxfj = minfj*2^(floor(log2(maxfj/minfj)));
188 fz = find(fj(:,1,1,1) > maxfj);
189 mj(fz,:,:,:) = [];
190 fj(fz,:,:,:) = [];
191
192 [s1 s2 s3] = size(mj);
193
194 cj = freq2chro(fj,option.res,option.origin);
195 if not(ismember(min(cj)+1,cj))
196 warning('WARNING IN MIRCHROMAGRAM: Frequency resolution of the spectrum is too low.');
197 display('The conversion of low frequencies into chromas may be incorrect.');
198 end
199 ccj = min(min(min(cj))):max(max(max(cj)));
200 sc = length(ccj); % The size of range of absolute chromas.
201 mat = zeros(s1,sc);
202 fc = chro2freq(ccj,option.res,option.origin); % The absolute chromas in Hz.
203 fl = chro2freq(ccj-1,option.res,option.origin); % Each previous chromas in Hz.
204 fr = chro2freq(ccj+1,option.res,option.origin); % Each related next chromas in Hz.
205 for k = 1:sc
206 rad = find(and(fj(:,1) > fc(k)-option.wth*(fc(k)-fl(k)),...
207 fj(:,1) < fc(k)-option.wth*(fc(k)-fr(k))));
208 if option.tri
209 dist = fc(k) - fj(:,1,1,1);
210 rad1 = dist/(fc(k) - fl(k))/option.wth;
211 rad2 = dist/(fc(k) - fr(k))/option.wth;
212 ndist = max(rad1,rad2);
213 mat(:,k) = max(min(1-ndist,1),0)/length(rad);
214 else
215 mat(rad,k) = ones(length(rad),1)/length(rad);
216 end
217 if k ==1 || k == sc
218 mat(:,k) = mat(:,k)/2;
219 end
220 end
221 nj = zeros(sc,s2,s3);
222 for k = 1:s2
223 for l = 1:s3
224 nj(:,k,l) = (mj(:,k,l)'*mat)';
225 end
226 end
227 cj = mod(ccj',option.res);
228 oi{j} = floor(ccj/option.res)+4;
229 if option.plabel
230 pj = strcat(chromascale(cj+1)',num2str(oi{j}'));
231 else
232 pj = ccj'+60;
233 end
234 ci{j} = repmat(cj,[1,s2,s3]);
235 pi{j} = repmat(pj,[1,s2,s3]);
236 ni{j} = nj;
237 cfi{j} = fc;
238 end
239 n{i} = ni;
240 cc{i} = ci;
241 o{i} = oi;
242 p{i} = pi;
243 cf{i} = cfi;
244 end
245 c = set(c,'Magnitude',n,'Chroma',p,'ChromaClass',cc,...
246 'ChromaFreq',cf,'Register',o);
247 c = modif(c,option,chromascale);
248 c = {c orig};
249 end
250
251
252 function c = modif(c,option,chromascale)
253 if option.plabel
254 c = set(c,'PitchLabel',1);
255 end
256 if option.cen || option.nor || option.wrp
257 n = get(c,'Magnitude');
258 p = get(c,'Chroma');
259 cl = get(c,'ChromaClass');
260 fp = get(c,'FramePos');
261 n2 = cell(1,length(n));
262 p2 = cell(1,length(n));
263 wrp = option.wrp && not(get(c,'Wrap'));
264 for i = 1:length(n)
265 ni = n{i};
266 pi = p{i};
267 cli = cl{i};
268 if not(iscell(ni))
269 ni = {ni};
270 pi = {pi};
271 cli = {cli};
272 end
273 if wrp
274 c = set(c,'Wrap',option.wrp);
275 end
276 n2i = cell(1,length(ni));
277 p2i = cell(1,length(ni));
278 for j = 1:length(ni)
279 nj = ni{j};
280 pj = pi{j};
281 clj = cli{j};
282 if wrp
283 n2j = zeros(option.res,size(nj,2),size(nj,3));
284 for k = 1:size(pj,1)
285 n2j(clj(k)+1,:,:) = n2j(clj(k)+1,:,:) + nj(k,:,:); % squared sum (parameter)
286 end
287 p2i{j} = chromascale';
288 else
289 n2j = nj;
290 p2i{j} = pi{j};
291 end
292 if option.cen
293 n2j = n2j - repmat(mean(n2j),[size(n2j,1),1,1]);
294 end
295 if option.nor
296 n2j = n2j ./ repmat(vectnorm(n2j,option.nor) + ...
297 repmat(1e-6,[1,size(n2j,2),size(n2j,3)] )...
298 ,[size(n2j,1),1,1]);
299 end
300 n2i{j} = n2j;
301 end
302 n2{i} = n2i;
303 p2{i} = p2i;
304 end
305 c = set(c,'Magnitude',n2,'Chroma',p2,'FramePos',fp);
306 end
307
308
309 function c = freq2chro(f,res,origin)
310 c = round(res*log2(f/origin));
311
312
313 function f = chro2freq(c,res,origin)
314 f = 2.^(c/res)*origin;
315
316
317 function y = vectnorm(x,p)
318 if isinf(p)
319 y = max(x);
320 else
321 y = sum(abs(x).^p).^(1/p);
322 end