xue@11
|
1 /*
|
xue@11
|
2 Harmonic sinusoidal modelling and tools
|
xue@11
|
3
|
xue@11
|
4 C++ code package for harmonic sinusoidal modelling and relevant signal processing.
|
xue@11
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@11
|
6 This file copyright 2011 Wen Xue.
|
xue@11
|
7
|
xue@11
|
8 This program is free software; you can redistribute it and/or
|
xue@11
|
9 modify it under the terms of the GNU General Public License as
|
xue@11
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@11
|
11 License, or (at your option) any later version.
|
xue@11
|
12 */
|
xue@1
|
13 //---------------------------------------------------------------------------
|
xue@1
|
14
|
xue@1
|
15 #include <math.h>
|
xue@1
|
16 #include "multires.h"
|
xue@1
|
17 #include "arrayalloc.h"
|
xue@1
|
18 #include "procedures.h"
|
xue@1
|
19
|
Chris@5
|
20 /** \file multires.h */
|
Chris@5
|
21
|
xue@1
|
22 //---------------------------------------------------------------------------
|
xue@1
|
23
|
xue@1
|
24 //function xlogx(x): returns x*log(x)
|
xue@1
|
25 inline double xlogx(double x)
|
xue@1
|
26 {
|
xue@1
|
27 if (x==0) return 0;
|
xue@1
|
28 else return x*log(x);
|
xue@1
|
29 }//xlogx
|
xue@1
|
30
|
xue@1
|
31 //macro NORMAL_: a normalization step used for tiling
|
xue@1
|
32 #define NORMAL_(A, a) A=a*(A+log(a));
|
xue@1
|
33 // #define NORMAL_(A, a) A=a*a*A;
|
xue@1
|
34 // #define NORMAL_(A, a) A=sqrt(a)*A;
|
xue@1
|
35
|
Chris@5
|
36 /**
|
xue@1
|
37 function DoCutSpectrogramSquare: find optimal tiling of a square. This is a recursive procedure.
|
xue@1
|
38
|
xue@1
|
39 In: Specs[0][1][N], Specs[1][2][N/2], ..., Specs[log2(N)][N][1], multiresolution power spectrogram
|
xue@1
|
40 e[Res]: total power of each level, e[i] equals the sum of Specs[i][][]
|
xue@1
|
41 NN: maximal tile height
|
xue@1
|
42 Out: cuts[N-1]: the tiling result
|
xue@1
|
43 ents[Res]
|
xue@1
|
44
|
xue@1
|
45 Returns the entropy of the output tiling.
|
xue@1
|
46 */
|
xue@1
|
47 double DoCutSpectrogramSquare(int* cuts, double*** Specs, double* e, int N, int NN, bool Norm, double* ents)
|
xue@1
|
48 {
|
xue@1
|
49 double result;
|
xue@1
|
50 int Res=log2(N)+1;
|
xue@1
|
51
|
xue@1
|
52 if (N==1) // 1*1 only(no cuts), returns the sample function.
|
xue@1
|
53 {
|
xue@1
|
54 double sp00;
|
xue@1
|
55 if (e[0]!=0) sp00=Specs[0][0][0]/e[0]; else sp00=0;
|
xue@1
|
56 ents[0]=xlogx(sp00);
|
xue@1
|
57 return ents[0];
|
xue@1
|
58 }
|
xue@1
|
59 else if (N==2)
|
xue@1
|
60 {
|
xue@1
|
61 double sp00, sp01, sp10, sp11;
|
xue@1
|
62 if (e[0]!=0) sp00=Specs[0][0][0]/e[0], sp01=Specs[0][0][1]/e[0]; else sp00=sp01=0;
|
xue@1
|
63 if (e[1]!=0) sp10=Specs[1][0][0]/e[1], sp11=Specs[1][1][0]/e[1]; else sp10=sp11=0;
|
xue@1
|
64 double ent0=xlogx(sp00)+xlogx(sp01);
|
xue@1
|
65 double ent1=xlogx(sp10)+xlogx(sp11);
|
xue@1
|
66 if (ent0<ent1)
|
xue@1
|
67 {
|
xue@1
|
68 cuts[0]=1;
|
xue@1
|
69 ents[0]=0, ents[1]=ent1;
|
xue@1
|
70 }
|
xue@1
|
71 else
|
xue@1
|
72 {
|
xue@1
|
73 cuts[0]=0;
|
xue@1
|
74 ents[0]=ent0, ents[1]=0;
|
xue@1
|
75 }
|
xue@1
|
76 }
|
xue@1
|
77 else
|
xue@1
|
78 {
|
xue@1
|
79 int* tmpcuts=new int[N-2];
|
xue@1
|
80 int *lcuts, *rcuts;
|
xue@1
|
81 double ***lSpecs, ***rSpecs, *el, *er, ent0, ent1, a;
|
xue@1
|
82 double *entl0=new double[Res-1], *entr0=new double[Res-1],
|
xue@1
|
83 *entl1=new double[Res-1], *entr1=new double[Res-1];
|
xue@1
|
84 //vertical cuts: l->left half, r->right half
|
xue@1
|
85 if (N<=NN)
|
xue@1
|
86 {
|
xue@1
|
87 lcuts=&cuts[1], rcuts=&cuts[N/2];
|
xue@1
|
88 VSplitSpecs(N, Specs, lSpecs, rSpecs);
|
xue@1
|
89 el=new double[Res-1], er=new double[Res-1];
|
xue@1
|
90 memset(el, 0, sizeof(double)*(Res-1)); memset(er, 0, sizeof(double)*(Res-1));
|
xue@1
|
91 if (Norm)
|
xue@1
|
92 {
|
xue@1
|
93 //normalization
|
xue@1
|
94 for (int i=0, Fr=1, n=N/2; i<Res-1; i++, Fr*=2, n/=2)
|
xue@1
|
95 for (int j=0; j<Fr; j++) for (int k=0; k<n; k++)
|
xue@1
|
96 el[i]+=lSpecs[i][j][k], er[i]+=rSpecs[i][j][k];
|
xue@1
|
97 }
|
xue@1
|
98 else
|
xue@1
|
99 for (int i=0; i<Res-1; i++) el[i]=er[i]=1;
|
xue@1
|
100
|
xue@1
|
101 DoCutSpectrogramSquare(lcuts, lSpecs, el, N/2, NN, Norm, entl1);
|
xue@1
|
102 DoCutSpectrogramSquare(rcuts, rSpecs, er, N/2, NN, Norm, entr1);
|
xue@1
|
103
|
xue@1
|
104 ent1=0;
|
xue@1
|
105
|
xue@1
|
106 for (int i=0; i<Res-1; i++)
|
xue@1
|
107 {
|
xue@1
|
108 if (e[i]!=0)
|
xue@1
|
109 {
|
xue@1
|
110 a=el[i]/e[i]; if (a>0) {NORMAL_(entl1[i], a);} else entl1[i]=0; ent1=ent1+entl1[i];
|
xue@1
|
111 a=er[i]/e[i]; if (a>0) {NORMAL_(entr1[i], a);} else entr1[i]=0; ent1=ent1+entr1[i];
|
xue@1
|
112 }
|
xue@1
|
113 else
|
xue@1
|
114 entl1[i]=entr1[i]=0;
|
xue@1
|
115 }
|
xue@1
|
116
|
xue@1
|
117 DeAlloc2(lSpecs); DeAlloc2(rSpecs);
|
xue@1
|
118 delete[] el; delete[] er;
|
xue@1
|
119
|
xue@1
|
120 }
|
xue@1
|
121 //horizontal cuts: l->lower half, r->upper half
|
xue@1
|
122 lcuts=tmpcuts, rcuts=&tmpcuts[N/2-1];
|
xue@1
|
123 HSplitSpecs(N, Specs, lSpecs, rSpecs);
|
xue@1
|
124 el=new double[Res-1], er=new double[Res-1];
|
xue@1
|
125 memset(el, 0, sizeof(double)*(Res-1)); memset(er, 0, sizeof(double)*(Res-1));
|
xue@1
|
126 if (Norm)
|
xue@1
|
127 {
|
xue@1
|
128 //normalization
|
xue@1
|
129 for (int i=0, Fr=1, n=N/2; i<Res-1; i++, Fr*=2, n/=2)
|
xue@1
|
130 for (int j=0; j<Fr; j++) for (int k=0; k<n; k++)
|
xue@1
|
131 el[i]+=lSpecs[i][j][k], er[i]+=rSpecs[i][j][k];
|
xue@1
|
132 }
|
xue@1
|
133 else
|
xue@1
|
134 for (int i=0; i<Res-1; i++) el[i]=er[i]=1;
|
xue@1
|
135
|
xue@1
|
136 DoCutSpectrogramSquare(lcuts, lSpecs, el, N/2, NN, Norm, entl0);
|
xue@1
|
137 DoCutSpectrogramSquare(rcuts, rSpecs, er, N/2, NN, Norm, entr0);
|
xue@1
|
138
|
xue@1
|
139 ent0=0;
|
xue@1
|
140
|
xue@1
|
141 if (Norm)
|
xue@1
|
142 for (int i=0; i<Res-1; i++)
|
xue@1
|
143 {
|
xue@1
|
144 if (e[i]!=0)
|
xue@1
|
145 {
|
xue@1
|
146 a=el[i]/e[i]; if (a>0) {NORMAL_(entl0[i], a);} else entl0[i]=0; ent0=ent0+entl0[i];
|
xue@1
|
147 a=er[i]/e[i]; if (a>0) {NORMAL_(entr0[i], a);} else entr0[i]=0; ent0=ent0+entr0[i];
|
xue@1
|
148 }
|
xue@1
|
149 else
|
xue@1
|
150 entl0[i]=entr0[i]=0;
|
xue@1
|
151 }
|
xue@1
|
152
|
xue@1
|
153 DeAlloc2(lSpecs); DeAlloc2(rSpecs);
|
xue@1
|
154 delete[] el; delete[] er;
|
xue@1
|
155
|
xue@1
|
156 if (N<=NN && ent0<ent1)
|
xue@1
|
157 {
|
xue@1
|
158 cuts[0]=1;
|
xue@1
|
159 result=ent1;
|
xue@1
|
160 for (int i=0; i<Res-1; i++)
|
xue@1
|
161 {
|
xue@1
|
162 ents[i+1]=entl1[i]+entr1[i];
|
xue@1
|
163 }
|
xue@1
|
164 ents[0]=0;
|
xue@1
|
165 }
|
xue@1
|
166 else
|
xue@1
|
167 {
|
xue@1
|
168 memcpy(&cuts[1], tmpcuts, sizeof(int)*(N-2));
|
xue@1
|
169 cuts[0]=0;
|
xue@1
|
170 result=ent0;
|
xue@1
|
171 for (int i=0; i<Res-1; i++)
|
xue@1
|
172 {
|
xue@1
|
173 ents[i]=entl0[i]+entr0[i];
|
xue@1
|
174 }
|
xue@1
|
175 ents[Res-1]=0;
|
xue@1
|
176 }
|
xue@1
|
177
|
xue@1
|
178 delete[] tmpcuts;
|
xue@1
|
179 delete[] entl0; delete[] entl1; delete[] entr0; delete[] entr1;
|
xue@1
|
180 }
|
xue@1
|
181
|
xue@1
|
182 return result;
|
xue@1
|
183 }//DoCutSpectrogramSquare
|
xue@1
|
184
|
Chris@5
|
185 /**
|
xue@1
|
186 function DoMixSpectrogramSquare: renders a composite spectrogram on a pixel grid. This is a recursive
|
xue@1
|
187 procedure.
|
xue@1
|
188
|
xue@1
|
189 In: Specs[0][1][N], Specs[1][2][N/2], Specs[2][4][N/4], ..., Specs[][N][1]: multiresolution power
|
xue@1
|
190 spectrogram
|
xue@1
|
191 cuts[N-1]: tiling
|
xue@1
|
192 X, Y: dimensions of pixel grid to render
|
xue@1
|
193 Out: Spec[X][Y]: pixel grid rendered to represent the given spectrograms and tiling
|
xue@1
|
194
|
xue@1
|
195 No return value;
|
xue@1
|
196 */
|
xue@1
|
197 void DoMixSpectrogramSquare(double** Spec, int* cuts, double*** Specs, int N, bool Norm, int X=0, int Y=0)
|
xue@1
|
198 {
|
xue@1
|
199 if (X==0 && Y==0) X=Y=N;
|
xue@1
|
200
|
xue@1
|
201 if (N==1)
|
xue@1
|
202 {
|
xue@1
|
203 double value=Specs[0][0][0];//sqrt(Specs[0][0][0]);
|
xue@1
|
204 value=value;
|
xue@1
|
205 for (int x=0; x<X; x++) for (int y=0; y<Y; y++) Spec[x][y]=value;
|
xue@1
|
206 }
|
xue@1
|
207 else
|
xue@1
|
208 {
|
xue@1
|
209 double* e;
|
xue@1
|
210 int Res;
|
xue@1
|
211
|
xue@1
|
212 if (Norm)
|
xue@1
|
213 {
|
xue@1
|
214 //normalization
|
xue@1
|
215 Res=log2(N)+1;
|
xue@1
|
216 e=new double[Res];
|
xue@1
|
217 memset(e, 0, sizeof(double)*Res);
|
xue@1
|
218 for (int i=0, Fr=1, n=N; i<Res; i++, Fr*=2, n/=2)
|
xue@1
|
219 for (int j=0; j<Fr; j++)
|
xue@1
|
220 for (int k=0; k<n; k++)
|
xue@1
|
221 e[i]+=Specs[i][j][k];
|
xue@1
|
222 double em=e[0];
|
xue@1
|
223 for (int i=1; i<Res; i++)
|
xue@1
|
224 {
|
xue@1
|
225 if (e[i]>em) e[i]=em/e[i];
|
xue@1
|
226 else e[i]=1;
|
xue@1
|
227 if (e[i]>em) em=e[i];
|
xue@1
|
228 } e[0]=1;
|
xue@1
|
229 for (int i=0, Fr=1, n=N; i<Res; i++, Fr*=2, n/=2)
|
xue@1
|
230 {
|
xue@1
|
231 if (e[i]!=0 && e[1]!=1)
|
xue@1
|
232 for (int j=0; j<Fr; j++)
|
xue@1
|
233 for (int k=0; k<n; k++)
|
xue@1
|
234 Specs[i][j][k]*=e[i];
|
xue@1
|
235 }
|
xue@1
|
236 }
|
xue@1
|
237
|
xue@1
|
238 double **lSpec, **rSpec, ***lSpecs, ***rSpecs;
|
xue@1
|
239 if (cuts[0]) //1: vertical split
|
xue@1
|
240 {
|
xue@1
|
241 VSplitSpecs(N, Specs, lSpecs, rSpecs);
|
xue@1
|
242 VSplitSpec(X, Y, Spec, lSpec, rSpec);
|
xue@1
|
243 DoMixSpectrogramSquare(lSpec, &cuts[1], lSpecs, N/2, Norm, X/2, Y);
|
xue@1
|
244 DoMixSpectrogramSquare(rSpec, &cuts[N/2], rSpecs, N/2, Norm, X/2, Y);
|
xue@1
|
245 }
|
xue@1
|
246 else //0: horizontal split
|
xue@1
|
247 {
|
xue@1
|
248 HSplitSpecs(N, Specs, lSpecs, rSpecs);
|
xue@1
|
249 HSplitSpec(X, Y, Spec, lSpec, rSpec);
|
xue@1
|
250 DoMixSpectrogramSquare(lSpec, &cuts[1], lSpecs, N/2, Norm, X, Y/2);
|
xue@1
|
251 DoMixSpectrogramSquare(rSpec, &cuts[N/2], rSpecs, N/2, Norm, X, Y/2);
|
xue@1
|
252 }
|
xue@1
|
253
|
xue@1
|
254 if (Norm)
|
xue@1
|
255 {
|
xue@1
|
256 for (int i=0, Fr=1, n=N; i<Res; i++, Fr*=2, n/=2)
|
xue@1
|
257 {
|
xue@1
|
258 if (e[i]!=0 && e[1]!=1)
|
xue@1
|
259 for (int j=0; j<Fr; j++)
|
xue@1
|
260 for (int k=0; k<n; k++)
|
xue@1
|
261 Specs[i][j][k]/=e[i];
|
xue@1
|
262 }
|
xue@1
|
263 delete[] e;
|
xue@1
|
264 }
|
xue@1
|
265
|
xue@1
|
266 delete[] lSpec; delete[] rSpec; DeAlloc2(lSpecs); DeAlloc2(rSpecs);
|
xue@1
|
267 }
|
xue@1
|
268 }//DoMixSpectrogramSquare
|
xue@1
|
269
|
Chris@5
|
270 /**
|
xue@1
|
271 function DoMixSpectrogramSquare: retrieves a composite spectrogram as a vector. This is a recursive
|
xue@1
|
272 procedure.
|
xue@1
|
273
|
xue@1
|
274 In: Specs[0][1][N], Specs[1][2][N/2], Specs[2][4][N/4], ..., Specs[][N][1]: multiresolution power
|
xue@1
|
275 spectrogram
|
xue@1
|
276 cuts[N-1]: tiling
|
xue@1
|
277 Out: Spec[N]: composite spectrogram sampled fron Specs according to tiling cut[]
|
xue@1
|
278
|
xue@1
|
279 No return value;
|
xue@1
|
280 */
|
xue@1
|
281 void DoMixSpectrogramSquare(double* Spec, int* cuts, double*** Specs, int N, bool Norm)
|
xue@1
|
282 {
|
xue@1
|
283 // if (X==0 && Y==0) X=Y=N;
|
xue@1
|
284
|
xue@1
|
285 if (N==1)
|
xue@1
|
286 Spec[0]=Specs[0][0][0];//sqrt(Specs[0][0][0]);
|
xue@1
|
287 else
|
xue@1
|
288 {
|
xue@1
|
289 double* e;
|
xue@1
|
290 int Res;
|
xue@1
|
291
|
xue@1
|
292 //Norm=false;
|
xue@1
|
293 if (Norm)
|
xue@1
|
294 {
|
xue@1
|
295 //normalization
|
xue@1
|
296 Res=log2(N)+1;
|
xue@1
|
297 e=new double[Res];
|
xue@1
|
298 memset(e, 0, sizeof(double)*Res);
|
xue@1
|
299 for (int i=0, Fr=1, n=N; i<Res; i++, Fr*=2, n/=2)
|
xue@1
|
300 for (int j=0; j<Fr; j++)
|
xue@1
|
301 for (int k=0; k<n; k++)
|
xue@1
|
302 e[i]+=Specs[i][j][k];
|
xue@1
|
303 double em=e[0];
|
xue@1
|
304 for (int i=1; i<Res; i++)
|
xue@1
|
305 {
|
xue@1
|
306 if (e[i]>em) e[i]=em/e[i];
|
xue@1
|
307 else e[i]=1;
|
xue@1
|
308 if (e[i]>em) em=e[i];
|
xue@1
|
309 } e[0]=1;
|
xue@1
|
310 for (int i=0, Fr=1, n=N; i<Res; i++, Fr*=2, n/=2)
|
xue@1
|
311 {
|
xue@1
|
312 if (e[i]!=0 && e[i]!=1)
|
xue@1
|
313 for (int j=0; j<Fr; j++)
|
xue@1
|
314 for (int k=0; k<n; k++)
|
xue@1
|
315 Specs[i][j][k]*=e[i];
|
xue@1
|
316 }
|
xue@1
|
317 }
|
xue@1
|
318
|
xue@1
|
319 double ***lSpecs, ***rSpecs;
|
xue@1
|
320 if (cuts[0]) //1: vertical split
|
xue@1
|
321 {
|
xue@1
|
322 VSplitSpecs(N, Specs, lSpecs, rSpecs);
|
xue@1
|
323 DoMixSpectrogramSquare(Spec, &cuts[1], lSpecs, N/2, Norm);
|
xue@1
|
324 DoMixSpectrogramSquare(&Spec[N/2], &cuts[N/2], rSpecs, N/2, Norm);
|
xue@1
|
325 }
|
xue@1
|
326 else //0: horizontal split
|
xue@1
|
327 {
|
xue@1
|
328 HSplitSpecs(N, Specs, lSpecs, rSpecs);
|
xue@1
|
329 DoMixSpectrogramSquare(Spec, &cuts[1], lSpecs, N/2, Norm);
|
xue@1
|
330 DoMixSpectrogramSquare(&Spec[N/2], &cuts[N/2], rSpecs, N/2, Norm);
|
xue@1
|
331 }
|
xue@1
|
332
|
xue@1
|
333 if (Norm)
|
xue@1
|
334 {
|
xue@1
|
335 for (int i=0, Fr=1, n=N; i<Res; i++, Fr*=2, n/=2)
|
xue@1
|
336 {
|
xue@1
|
337 if (e[i]!=0 && e[1]!=1)
|
xue@1
|
338 for (int j=0; j<Fr; j++)
|
xue@1
|
339 for (int k=0; k<n; k++)
|
xue@1
|
340 Specs[i][j][k]/=e[i];
|
xue@1
|
341 }
|
xue@1
|
342 delete[] e;
|
xue@1
|
343 }
|
xue@1
|
344
|
xue@1
|
345 DeAlloc2(lSpecs); DeAlloc2(rSpecs);
|
xue@1
|
346 }
|
xue@1
|
347 }//DoMixSpectrogramSquare
|
xue@1
|
348
|
xue@1
|
349 //---------------------------------------------------------------------------
|
Chris@5
|
350 /**
|
xue@1
|
351 function HSplitSpec: split a spectrogram horizontally into lower and upper halves.
|
xue@1
|
352
|
xue@1
|
353 In: Spec[X][Y]: spectrogram to split
|
xue@1
|
354 Out: lSpec[X][Y/2], uSpec[X][Y/2]: the two half spectrograms
|
xue@1
|
355
|
xue@1
|
356 No return value. Both lSpec and uSpec are allocated anew. The caller is responsible to free these
|
xue@1
|
357 buffers.
|
xue@1
|
358 */
|
xue@1
|
359 void HSplitSpec(int X, int Y, double** Spec, double**& lSpec, double**& uSpec)
|
xue@1
|
360 {
|
xue@1
|
361 lSpec=new double*[X], uSpec=new double*[X];
|
xue@1
|
362 for (int i=0; i<X; i++)
|
xue@1
|
363 lSpec[i]=Spec[i], uSpec[i]=&Spec[i][Y/2];
|
xue@1
|
364 }//HSplitSpec
|
xue@1
|
365
|
Chris@5
|
366 /**
|
xue@1
|
367 function HSplitSpecs: split a multiresolution spectrogram horizontally into lower and upper halves
|
xue@1
|
368
|
xue@1
|
369 A full spectrogram array is given in log2(N)+1 spectrograms, with the base spec of 1*N, 1st octave of
|
xue@1
|
370 2*(N/2), ..., last octave of N*1. When this array is split into two spectrogram arrays horizontally,
|
xue@1
|
371 the last spec (with the highest time resolution). Each of the two new arrays is given in log2(N)
|
xue@1
|
372 spectrograms.
|
xue@1
|
373
|
xue@1
|
374 In: Specs[nRes+1][][]: multiresolution spectrogram
|
xue@1
|
375 Out: lSpecs[nRes][][], uSpecs[nRes][][], the two half multiresolution spectrograms
|
xue@1
|
376
|
xue@1
|
377 This function allocates two 2nd order arrays of double*, which the caller is responsible to free.
|
xue@1
|
378 */
|
xue@1
|
379 void HSplitSpecs(int N, double*** Specs, double***& lSpecs, double***& uSpecs)
|
xue@1
|
380 {
|
xue@1
|
381 int nRes=log2(N); // new number of resolutions
|
xue@1
|
382 lSpecs=new double**[nRes], uSpecs=new double**[nRes];
|
xue@1
|
383 lSpecs[0]=new double*[nRes*N/2], uSpecs[0]=new double*[nRes*N/2]; for (int i=1; i<nRes; i++) lSpecs[i]=&lSpecs[0][i*N/2], uSpecs[i]=&uSpecs[0][i*N/2];
|
xue@1
|
384 for (int i=0, Fr=1, n=N; i<nRes; i++, Fr*=2, n/=2)
|
xue@1
|
385 for (int j=0; j<Fr; j++) lSpecs[i][j]=Specs[i][j], uSpecs[i][j]=&Specs[i][j][n/2];
|
xue@1
|
386 }//HSplitSpecs
|
xue@1
|
387
|
xue@1
|
388 //---------------------------------------------------------------------------
|
Chris@5
|
389 /**
|
xue@1
|
390 function MixSpectrogramSquare: find composite spectrogram from multiresolution spectrogram,output as
|
xue@1
|
391 pixel grid
|
xue@1
|
392
|
xue@1
|
393 In: Specs[0][1][N], Specs[1][2][N/2], ..., Specs[Res-1][N][1], multiresolution spectrogram
|
xue@1
|
394 Out: Spec[N][N]: composite spectrogram as pixel grid (N time redundant)
|
xue@1
|
395 cuts[N-1] (optional): tiling
|
xue@1
|
396
|
xue@1
|
397 Returns entropy.
|
xue@1
|
398 */
|
xue@1
|
399 double MixSpectrogramSquare(double** Spec, double*** Specs, int N, int Res, bool Norm, bool NormMix, int* cuts=0)
|
xue@1
|
400 {
|
xue@1
|
401 int tRes=log2(N)+1;
|
xue@1
|
402 if (Res==0) Res=tRes;
|
xue@1
|
403 int NN=1<<(Res-1);
|
xue@1
|
404 bool createcuts=(cuts==0);
|
xue@1
|
405 if (createcuts) cuts=new int[N];
|
xue@1
|
406 double* e=new double[tRes], *ents=new double[tRes];
|
xue@1
|
407 //normalization
|
xue@1
|
408 memset(e, 0, sizeof(double)*Res);
|
xue@1
|
409 for (int i=0, Fr=1, n=N; i<tRes; i++, Fr*=2, n/=2)
|
xue@1
|
410 for (int j=0; j<Fr; j++)
|
xue@1
|
411 for (int k=0; k<n; k++)
|
xue@1
|
412 e[i]+=Specs[i][j][k];
|
xue@1
|
413
|
xue@1
|
414 if (!Norm)
|
xue@1
|
415 {
|
xue@1
|
416 for (int i=0, Fr=1, n=N; i<tRes; i++, Fr*=2, n/=2)
|
xue@1
|
417 {
|
xue@1
|
418 if (e[i]!=0 && e[i]!=1)
|
xue@1
|
419 for (int j=0; j<Fr; j++)
|
xue@1
|
420 for (int k=0; k<n; k++)
|
xue@1
|
421 Specs[i][j][k]/=e[i];
|
xue@1
|
422 }
|
xue@1
|
423 // for (int i=0; i<Res; i++) e[i]=1;
|
xue@1
|
424 }
|
xue@1
|
425
|
xue@1
|
426 double result=DoCutSpectrogramSquare(cuts, Specs, e, N, NN, Norm, ents);
|
xue@1
|
427 delete[] ents;
|
xue@1
|
428
|
xue@1
|
429 if (!Norm)
|
xue@1
|
430 {
|
xue@1
|
431 for (int i=0, Fr=1, n=N; i<tRes; i++, Fr*=2, n/=2)
|
xue@1
|
432 {
|
xue@1
|
433 if (e[i]!=0 && e[i]!=1)
|
xue@1
|
434 for (int j=0; j<Fr; j++)
|
xue@1
|
435 for (int k=0; k<n; k++)
|
xue@1
|
436 Specs[i][j][k]*=e[i];
|
xue@1
|
437 }
|
xue@1
|
438 }
|
xue@1
|
439 DoMixSpectrogramSquare(Spec, cuts, Specs, N, NormMix, N, N);
|
xue@1
|
440
|
xue@1
|
441 delete[] e;
|
xue@1
|
442 if (createcuts) delete[] cuts;
|
xue@1
|
443 return result;
|
xue@1
|
444 }//MixSpectrogramSquare
|
xue@1
|
445
|
xue@1
|
446 //---------------------------------------------------------------------------
|
Chris@5
|
447 /**
|
xue@1
|
448 function MixSpectrogramSquare: find composite spectrogram from multiresolution spectrogram,output as
|
xue@1
|
449 vectors
|
xue@1
|
450
|
xue@1
|
451 In: Specs[0][1][N], Specs[1][2][N/2], ..., Specs[Res-1][N][1], multiresolution spectrogram
|
xue@1
|
452 Out: spl[N-1], Spec[N]: composite spectrogram as tiling and value vectors
|
xue@1
|
453
|
xue@1
|
454 Returns entropy.
|
xue@1
|
455 */
|
xue@1
|
456 double MixSpectrogramSquare(int* spl, double* Spec, double*** Specs, int N, int Res, bool Norm, bool NormMix)
|
xue@1
|
457 {
|
xue@1
|
458 int tRes=log2(N)+1;
|
xue@1
|
459 if (Res==0) Res=tRes;
|
xue@1
|
460 int NN=1<<(Res-1);
|
xue@1
|
461
|
xue@1
|
462 double* e=new double[tRes], *ents=new double[tRes];
|
xue@1
|
463
|
xue@1
|
464 //normalization
|
xue@1
|
465 memset(e, 0, sizeof(double)*Res);
|
xue@1
|
466 for (int i=0, Fr=1, n=N; i<tRes; i++, Fr*=2, n/=2)
|
xue@1
|
467 for (int j=0; j<Fr; j++)
|
xue@1
|
468 for (int k=0; k<n; k++)
|
xue@1
|
469 e[i]+=Specs[i][j][k];
|
xue@1
|
470
|
xue@1
|
471 if (!Norm)
|
xue@1
|
472 {
|
xue@1
|
473 for (int i=0, Fr=1, n=N; i<tRes; i++, Fr*=2, n/=2)
|
xue@1
|
474 {
|
xue@1
|
475 if (e[i]!=0 && e[i]!=1)
|
xue@1
|
476 for (int j=0; j<Fr; j++)
|
xue@1
|
477 for (int k=0; k<n; k++)
|
xue@1
|
478 Specs[i][j][k]/=e[i];
|
xue@1
|
479 }
|
xue@1
|
480 // for (int i=0; i<Res; i++) e[i]=1;
|
xue@1
|
481 }
|
xue@1
|
482
|
xue@1
|
483 double result=DoCutSpectrogramSquare(spl, Specs, e, N, NN, Norm, ents);
|
xue@1
|
484 delete[] ents;
|
xue@1
|
485 if (!Norm)
|
xue@1
|
486 {
|
xue@1
|
487 for (int i=0, Fr=1, n=N; i<tRes; i++, Fr*=2, n/=2)
|
xue@1
|
488 {
|
xue@1
|
489 if (e[i]!=0 && e[i]!=1)
|
xue@1
|
490 for (int j=0; j<Fr; j++)
|
xue@1
|
491 for (int k=0; k<n; k++)
|
xue@1
|
492 Specs[i][j][k]*=e[i];
|
xue@1
|
493 }
|
xue@1
|
494 }
|
xue@1
|
495 DoMixSpectrogramSquare(Spec, spl, Specs, N, NormMix);
|
xue@1
|
496 return result;
|
xue@1
|
497 }//MixSpectrogramSquare
|
xue@1
|
498
|
xue@1
|
499 //---------------------------------------------------------------------------
|
Chris@5
|
500 /**
|
xue@1
|
501 function MixSpectrogramBlock: obtain the composite spectrogram of a waveform block as pixel grid.
|
xue@1
|
502
|
xue@1
|
503 This method deals with the effective duration of WID/2 samples of a frame of WID samples. The maximal
|
xue@1
|
504 frame width is WID, minimal frame width is wid. The spectrum with frame width WID (base) is given in
|
xue@1
|
505 lSpecs[0][0], the spectra with frame width WID/2 (1st octave) is given in lSpecs[1][0] & lSpecs[1][1],
|
xue@1
|
506 etc.
|
xue@1
|
507
|
xue@1
|
508 The output Spec[WID/wid][WID] is a spectrogram sampled from lSpecs, with a redundancy factor WID/wid.
|
xue@1
|
509 The sampling is optimized so that a maximal entropy is achieved globally. This maximal entropy is
|
xue@1
|
510 returned.
|
xue@1
|
511
|
xue@1
|
512 In: Specs[0][1][WID], Specs[1][2][WID/2], ..., Specs[Res-1][WID/wid][wid], multiresolution spectrogram
|
xue@1
|
513 Out: Spec[WID/wid][WID], composite spectrogram as pixel grid
|
xue@1
|
514 cuts[wid][WID/wid-1] (optional), tilings of the wid squares the block is divided into.
|
xue@1
|
515
|
xue@1
|
516 Returns entropy.
|
xue@1
|
517 */
|
xue@1
|
518 double MixSpectrogramBlock(double** Spec, double*** Specs, int WID, int wid, bool norm, bool normmix, int** cuts=0)
|
xue@1
|
519 {
|
xue@1
|
520 int N=WID/wid, Res=log2(WID/wid)+1;
|
xue@1
|
521 double result=0, **lSpec=new double*[N], ***lSpecs=new double**[Res];
|
xue@1
|
522 lSpecs[0]=new double*[Res*N]; for (int i=1; i<Res; i++) lSpecs[i]=&lSpecs[0][i*N];
|
xue@1
|
523
|
xue@1
|
524 bool createcuts=(cuts==0);
|
xue@1
|
525 if (createcuts)
|
xue@1
|
526 {
|
xue@1
|
527 cuts=new int*[wid];
|
xue@1
|
528 memset(cuts, 0, sizeof(int*)*wid);
|
xue@1
|
529 }
|
xue@1
|
530
|
xue@1
|
531 for (int i=0; i<wid; i++)
|
xue@1
|
532 {
|
xue@1
|
533 for (int j=0; j<N; j++)
|
xue@1
|
534 lSpec[j]=&Spec[j][i*N];
|
xue@1
|
535 for (int j=0, n=N, Fr=1; j<Res; j++, n/=2, Fr*=2)
|
xue@1
|
536 {
|
xue@1
|
537 for (int k=0; k<Fr; k++)
|
xue@1
|
538 lSpecs[j][k]=&Specs[j][k][i*n];
|
xue@1
|
539 }
|
xue@1
|
540
|
xue@1
|
541 int Log2N=log2(N);
|
xue@1
|
542 if (i==0)
|
xue@1
|
543 result+=MixSpectrogramSquare(lSpec, lSpecs, N, Log2N>2?(log2(N)-1):2, norm, normmix, cuts[i]);
|
xue@1
|
544 else if (i==1)
|
xue@1
|
545 result+=MixSpectrogramSquare(lSpec, lSpecs, N, Log2N>1?Log2N:2, norm, normmix, cuts[i]);
|
xue@1
|
546 else
|
xue@1
|
547 result+=MixSpectrogramSquare(lSpec, lSpecs, N, Log2N+1, norm, normmix, cuts[i]);
|
xue@1
|
548 }
|
xue@1
|
549 delete[] lSpec;
|
xue@1
|
550 DeAlloc2(lSpecs);
|
xue@1
|
551 if (createcuts) delete[] cuts;
|
xue@1
|
552 return result;
|
xue@1
|
553 }//MixSpectrogramBlock
|
xue@1
|
554
|
Chris@5
|
555 /**
|
xue@1
|
556 function MixSpectrogramBlock: obtain the composite spectrogram of a waveform block as vectors.
|
xue@1
|
557
|
xue@1
|
558 In: Specs[0][1][WID], Specs[1][2][WID/2], ..., Specs[Res-1][WID/wid][wid], multiresolution spectrogram
|
xue@1
|
559 Out: spl[WID], Spec[WID], composite spectrogram as tiling and value vectors. Each of the vectors is
|
xue@1
|
560 made up of $wid subvectors, each subvector pair describing a N*N block of the composite
|
xue@1
|
561 spectrogram.
|
xue@1
|
562
|
xue@1
|
563 Returns entropy.
|
xue@1
|
564 */
|
xue@1
|
565 double MixSpectrogramBlock(int* spl, double* Spec, double*** Specs, int WID, int wid, bool norm, bool normmix)
|
xue@1
|
566 {
|
xue@1
|
567 int N=WID/wid, Res=log2(WID/wid)+1, *lspl;
|
xue@1
|
568 double result=0, *lSpec, ***lSpecs=new double**[Res];
|
xue@1
|
569 lSpecs[0]=new double*[Res*N]; for (int i=1; i<Res; i++) lSpecs[i]=&lSpecs[0][i*N];
|
xue@1
|
570
|
xue@1
|
571 for (int i=0; i<wid; i++)
|
xue@1
|
572 {
|
xue@1
|
573 lspl=&spl[i*N];
|
xue@1
|
574 lSpec=&Spec[i*N];
|
xue@1
|
575 for (int j=0, n=N, Fr=1; j<Res; j++, n/=2, Fr*=2)
|
xue@1
|
576 {
|
xue@1
|
577 for (int k=0; k<Fr; k++)
|
xue@1
|
578 lSpecs[j][k]=&Specs[j][k][i*n];
|
xue@1
|
579 }
|
xue@1
|
580 int Log2N=log2(N);
|
xue@1
|
581 /*
|
xue@1
|
582 if (i==0)
|
xue@1
|
583 result+=MixSpectrogramSquare(lspl, lSpec, lSpecs, N, Log2N>2?(log2(N)-1):2, norm, normmix);
|
xue@1
|
584 else if (i==1)
|
xue@1
|
585 result+=MixSpectrogramSquare(lspl, lSpec, lSpecs, N, Log2N>1?Log2N:2, norm, normmix);
|
xue@1
|
586 else */
|
xue@1
|
587 result+=MixSpectrogramSquare(lspl, lSpec, lSpecs, N, Log2N+1, norm, normmix);
|
xue@1
|
588
|
xue@1
|
589 }
|
xue@1
|
590 DeAlloc2(lSpecs);
|
xue@1
|
591
|
xue@1
|
592 return result;
|
xue@1
|
593 }//MixSpectrogramBlock
|
xue@1
|
594
|
xue@1
|
595
|
xue@1
|
596 //---------------------------------------------------------------------------
|
Chris@5
|
597 /**
|
Chris@5
|
598 functions names as ...Block2(...) implement the same functions as the above directly without
|
xue@1
|
599 explicitly dividing the multiresolution spectrogram into square blocks.
|
xue@1
|
600 */
|
xue@1
|
601
|
Chris@5
|
602 /**
|
xue@1
|
603 function DoCutSpectrogramBlock2: find optimal tiling for a block
|
xue@1
|
604
|
xue@1
|
605 In: Specs[R0][x0:x0+x-1][Y0:Y0+Y-1], [R0+1][2x0:2x0+2x-1][Y0/2:Y0/2+Y/2-1],...,
|
xue@1
|
606 Specs[R0+?][Nx0:Nx0+Nx-1][Y0/N:Y0/N+Y/N-1], multiresolution spectrogram
|
xue@1
|
607 Out: spl[Y-1], tiling of this block
|
xue@1
|
608
|
xue@1
|
609 Returns entropy.
|
xue@1
|
610 */
|
xue@1
|
611 double DoCutSpectrogramBlock2(int* spl, double*** Specs, int Y, int R0, int x0, int Y0, int N, double& ene)
|
xue@1
|
612 {
|
xue@1
|
613 double ent=0;
|
xue@1
|
614 if (Y>N) //N=WID/wid, the actual square size
|
xue@1
|
615 {
|
xue@1
|
616 spl[0]=0;
|
xue@1
|
617 double ene1, ene2;
|
xue@1
|
618 ent+=DoCutSpectrogramBlock2(&spl[1], Specs, Y/2, R0, x0, Y0, N, ene1);
|
xue@1
|
619 ent+=DoCutSpectrogramBlock2(&spl[Y/2], Specs, Y/2, R0, x0, Y0+Y/2, N, ene2);
|
xue@1
|
620 ene=ene1+ene2;
|
xue@1
|
621 }
|
xue@1
|
622 else if (N==1)
|
xue@1
|
623 {
|
xue@1
|
624 double tmp=Specs[R0][x0][Y0];
|
xue@1
|
625 ene=tmp;
|
xue@1
|
626 ent=xlogx(tmp);
|
xue@1
|
627 }
|
xue@1
|
628 else //Y==N, the square case
|
xue@1
|
629 {
|
xue@1
|
630 double enel, ener, enet, eneb, entl, entr, entt, entb;
|
xue@1
|
631 int* tmpspl=new int[Y];
|
xue@1
|
632 entl=DoCutSpectrogramBlock2(&spl[1], Specs, Y/2, R0+1, 2*x0, Y0/2, N/2, enel);
|
xue@1
|
633 entr=DoCutSpectrogramBlock2(&spl[Y/2], Specs, Y/2, R0+1, 2*x0+1, Y0/2, N/2, ener);
|
xue@1
|
634 entb=DoCutSpectrogramBlock2(&tmpspl[1], Specs, Y/2, R0, x0, Y0, N/2, eneb);
|
xue@1
|
635 entt=DoCutSpectrogramBlock2(&tmpspl[Y/2], Specs, Y/2, R0, x0, Y0+Y/2, N/2, enet);
|
xue@1
|
636 double ene0=enet+eneb, ene1=enel+ener, ent0=entt+entb, ent1=entl+entr;
|
xue@1
|
637 //normalize
|
xue@1
|
638 double eneres=1-(ene0+ene1)/2, norment0, norment1;
|
xue@1
|
639 //double a0=1/(ene0+eneres), a1=1/(ene1+eneres);
|
xue@1
|
640 //quasi-global normalization
|
xue@1
|
641 norment0=(ent0-ene0*log(ene0+eneres))/(ene0+eneres), norment1=(ent1-ene1*log(ene1+eneres))/(ene1+eneres);
|
xue@1
|
642 //local normalization
|
xue@1
|
643 //if (ene0>0) norment0=ent0/ene0-log(ene0); else norment0=0; if (ene1>0) norment1=ent1/ene1-log(ene1); else norment1=0;
|
xue@1
|
644 if (norment1<norment0)
|
xue@1
|
645 {
|
xue@1
|
646 spl[0]=0;
|
xue@1
|
647 ent=ent0, ene=ene0;
|
xue@1
|
648 memcpy(&spl[1], &tmpspl[1], sizeof(int)*(Y-2));
|
xue@1
|
649 }
|
xue@1
|
650 else
|
xue@1
|
651 {
|
xue@1
|
652 spl[0]=1;
|
xue@1
|
653 ent=ent1, ene=ene1;
|
xue@1
|
654 }
|
xue@1
|
655 }
|
xue@1
|
656 return ent;
|
xue@1
|
657 }//DoCutSpectrogramBlock2
|
xue@1
|
658
|
Chris@5
|
659 /**
|
xue@1
|
660 function DoMixSpectrogramBlock2: sampling multiresolution spectrogram according to given tiling
|
xue@1
|
661
|
xue@1
|
662 In: Specs[R0][x0:x0+x-1][Y0:Y0+Y-1], [R0+1][2x0:2x0+2x-1][Y0/2:Y0/2+Y/2-1],...,
|
xue@1
|
663 Specs[R0+?][Nx0:Nx0+Nx-1][Y0/N:Y0/N+Y/N-1], multiresolution spectrogram
|
xue@1
|
664 spl[Y-1]; tiling of this block
|
xue@1
|
665 Out: Spec[Y], composite spectrogram as value vector
|
xue@1
|
666
|
xue@1
|
667 Returns 0.
|
xue@1
|
668 */
|
xue@1
|
669 double DoMixSpectrogramBlock2(int* spl, double* Spec, double*** Specs, int Y, int R0, int x0, int Y0, bool normmix, int res, double* e)
|
xue@1
|
670 {
|
xue@1
|
671 if (Y==1)
|
xue@1
|
672 {
|
xue@1
|
673 Spec[0]=Specs[R0][x0][Y0]*e[0];
|
xue@1
|
674 }
|
xue@1
|
675 else
|
xue@1
|
676 {
|
xue@1
|
677 double le[32];
|
xue@1
|
678 if (normmix && Y<(1<<res))
|
xue@1
|
679 {
|
xue@1
|
680 for (int i=0, j=1, k=Y; i<res; i++, j*=2, k/=2)
|
xue@1
|
681 {
|
xue@1
|
682 double lle=0;
|
xue@1
|
683 for (int fr=0; fr<j; fr++) for (int n=0; n<k; n++) lle+=Specs[i+R0][x0+fr][Y0+n]*Specs[i+R0][x0+fr][Y0+n];
|
xue@1
|
684 lle=sqrt(lle)*e[i];
|
xue@1
|
685 if (i==0) le[0]=lle;
|
xue@1
|
686 else if (lle>le[0]*2) le[i]=e[i]*le[0]*2/lle;
|
xue@1
|
687 else le[i]=e[i];
|
xue@1
|
688 }
|
xue@1
|
689 le[0]=e[0];
|
xue@1
|
690 }
|
xue@1
|
691 else
|
xue@1
|
692 {
|
xue@1
|
693 memcpy(le, e, sizeof(double)*res);
|
xue@1
|
694 }
|
xue@1
|
695
|
xue@1
|
696 if (spl[0]==0)
|
xue@1
|
697 {
|
xue@1
|
698 int newres;
|
xue@1
|
699 if (Y>=(1<<res)) newres=res;
|
xue@1
|
700 else newres=res-1;
|
xue@1
|
701 DoMixSpectrogramBlock2(&spl[1], Spec, Specs, Y/2, R0, x0, Y0, normmix, newres, le);
|
xue@1
|
702 DoMixSpectrogramBlock2(&spl[Y/2], &Spec[Y/2], Specs, Y/2, R0, x0, Y0+Y/2, normmix, newres, le);
|
xue@1
|
703 }
|
xue@1
|
704 else
|
xue@1
|
705 {
|
xue@1
|
706 DoMixSpectrogramBlock2(&spl[1], Spec, Specs, Y/2, R0+1, x0*2, Y0/2, normmix, res-1, &le[1]);
|
xue@1
|
707 DoMixSpectrogramBlock2(&spl[Y/2], &Spec[Y/2], Specs, Y/2, R0+1, x0*2+1, Y0/2, normmix, res-1, &le[1]);
|
xue@1
|
708 }
|
xue@1
|
709 }
|
xue@1
|
710 return 0;
|
xue@1
|
711 }//DoMixSpectrogramBlock2
|
xue@1
|
712
|
Chris@5
|
713 /**
|
xue@1
|
714 function MixSpectrogramBlock2: obtain the composite spectrogram of a waveform block as vectors.
|
xue@1
|
715
|
xue@1
|
716 In: Specs[0][1][WID], Specs[1][2][WID/2], ..., Specs[Res-1][WID/wid][wid], multiresolution spectrogram
|
xue@1
|
717 Out: spl[WID], Spec[WID], composite spectrogram as tiling and value vectors. Each of the
|
xue@1
|
718 vectors is made up of $wid subvectors, each subvector pair describing a N*N block of the
|
xue@1
|
719 composite spectrogram.
|
xue@1
|
720
|
xue@1
|
721 Returns entropy.
|
xue@1
|
722 */
|
xue@1
|
723 double MixSpectrogramBlock2(int* spl, double* Spec, double*** Specs, int WID, int wid, bool normmix)
|
xue@1
|
724 {
|
xue@1
|
725 double ene[32];
|
xue@1
|
726 //find the total energy and normalize
|
xue@1
|
727 for (int i=0, Fr=1, Wid=WID; Wid>=wid; i++, Fr*=2, Wid/=2)
|
xue@1
|
728 {
|
xue@1
|
729 double lene=0;
|
xue@1
|
730 for (int fr=0; fr<Fr; fr++) for (int k=0; k<Wid; k++) lene+=Specs[i][fr][k]*Specs[i][fr][k];
|
xue@1
|
731 ene[i]=lene;
|
xue@1
|
732 if (lene!=0)
|
xue@1
|
733 {
|
xue@1
|
734 double ilene=1.0/lene;
|
xue@1
|
735 for (int fr=0; fr<Fr; fr++) for (int k=0; k<Wid; k++) Specs[i][fr][k]=Specs[i][fr][k]*Specs[i][fr][k]*ilene;
|
xue@1
|
736 }
|
xue@1
|
737 }
|
xue@1
|
738
|
xue@1
|
739 double result=DoCutSpectrogramBlock2(spl, Specs, WID, 0, 0, 0, WID/wid, ene[31]);
|
xue@1
|
740
|
xue@1
|
741 //de-normalize
|
xue@1
|
742 for (int i=0, Fr=1, Wid=WID; Wid>=wid; i++, Fr*=2, Wid/=2)
|
xue@1
|
743 {
|
xue@1
|
744 double lene=ene[i];
|
xue@1
|
745 if (lene!=0)
|
xue@1
|
746 for (int fr=0; fr<Fr; fr++) for (int k=0; k<Wid; k++) Specs[i][fr][k]=sqrt(Specs[i][fr][k]*lene);
|
xue@1
|
747 }
|
xue@1
|
748
|
xue@1
|
749 double e[32]; for (int i=0; i<32; i++) e[i]=1;
|
xue@1
|
750 DoMixSpectrogramBlock2(spl, Spec, Specs, WID, 0, 0, 0, normmix, log2(WID/wid)+1, e);
|
xue@1
|
751 return result;
|
xue@1
|
752 }//MixSpectrogramBlock2
|
xue@1
|
753
|
xue@1
|
754 //---------------------------------------------------------------------------
|
Chris@5
|
755 /**
|
xue@1
|
756 function MixSpectrogram: obtain composite spectrogram from multiresolutin spectrogram as pixel grid
|
xue@1
|
757
|
xue@1
|
758 This method deals with Fr (base) frames of WID samples. Each base frame may be divided into 2 1st-
|
xue@1
|
759 octave frames, 4 2nd-octave frames, ..., etc. The spectrogram calculated on base frame is given in
|
xue@1
|
760 Specs[0] (Fr frames); that of 1st octave is given in Specs[1] (2*Fr frames); etc. The method resamples
|
xue@1
|
761 the spectrograms of different frame width into a single spectrogram so that the entropy is maximized
|
xue@1
|
762 globally.
|
xue@1
|
763
|
xue@1
|
764 The output Spec is a spectrogram of apparent resolution WID at hop size wid. It is a redundant
|
xue@1
|
765 representation, with equal values occupying blocks of size WID/wid.
|
xue@1
|
766
|
xue@1
|
767 In: Specs[0][Fr][WID], Specs[1][Fr*2][WID/2], ..., Specs[Res-1] [Fr*(WID/wid)][wid], multiresolution
|
xue@1
|
768 spectrogram
|
xue@1
|
769 Out: Spec[Fr*(WID/wid)][WID], composite spectrogram as pixel grid
|
xue@1
|
770 cuts[Fr][wid][N=Wid/wid], tilings of small square blocks
|
xue@1
|
771 Returns 0.
|
xue@1
|
772 */
|
xue@1
|
773 double MixSpectrogram(double** Spec, double*** Specs, int Fr, int WID, int wid, bool norm, bool normmix, int*** cuts)
|
xue@1
|
774 {
|
xue@1
|
775 //totally Fr frames of WID samples
|
xue@1
|
776 //each frame is divided into wid VERTICAL parts
|
xue@1
|
777 bool createcuts=(cuts==0);
|
xue@1
|
778 if (createcuts)
|
xue@1
|
779 {
|
xue@1
|
780 cuts=new int**[Fr];
|
xue@1
|
781 memset(cuts, 0, sizeof(int**)*Fr);
|
xue@1
|
782 }
|
xue@1
|
783 int Res=log2(WID/wid)+1;
|
xue@1
|
784 double*** lSpecs=new double**[Res];
|
xue@1
|
785 for (int i=0; i<Fr; i++)
|
xue@1
|
786 {
|
xue@1
|
787 for (int j=0, nfr=1; j<Res; j++, nfr*=2) lSpecs[j]=&Specs[j][i*nfr];
|
xue@1
|
788 MixSpectrogramBlock(&Spec[i*WID/wid], lSpecs, WID, wid, norm, normmix, cuts[i]);
|
xue@1
|
789 }
|
xue@1
|
790
|
xue@1
|
791 delete[] lSpecs;
|
xue@1
|
792 if (createcuts) delete[] cuts;
|
xue@1
|
793 return 0;
|
xue@1
|
794 }//MixSpectrogram
|
xue@1
|
795
|
Chris@5
|
796 /**
|
xue@1
|
797 function MixSpectrogram: obtain composite spectrogram from multiresolutin spectrogram as vectors
|
xue@1
|
798
|
xue@1
|
799 In: Specs[0][Fr][WID], Specs[1][Fr*2][WID/2], ..., Specs[Res-1] [Fr*(WID/wid)][wid], multiresolution
|
xue@1
|
800 spectrogram
|
xue@1
|
801 Out: spl[Fr][WID], Spec[Fr][WID], composite spectrogram as tiling and value vectors by frame.
|
xue@1
|
802
|
xue@1
|
803 Returns 0.
|
xue@1
|
804 */
|
xue@1
|
805 double MixSpectrogram(int** spl, double** Spec, double*** Specs, int Fr, int WID, int wid, bool norm, bool normmix)
|
xue@1
|
806 {
|
xue@1
|
807 //totally Fr frames of WID samples
|
xue@1
|
808 //each frame is divided into wid VERTICAL parts
|
xue@1
|
809 int Res=log2(WID/wid)+1;
|
xue@1
|
810 double*** lSpecs=new double**[Res];
|
xue@1
|
811 for (int i=0; i<Fr; i++)
|
xue@1
|
812 {
|
xue@1
|
813 for (int j=0, nfr=1; j<Res; j++, nfr*=2) lSpecs[j]=&Specs[j][i*nfr];
|
xue@1
|
814 MixSpectrogramBlock(spl[i], Spec[i], lSpecs, WID, wid, norm, normmix);
|
xue@1
|
815 // MixSpectrogramBlock2(spl[i], Spec[i], lSpecs, WID, wid, norm);
|
xue@1
|
816 }
|
xue@1
|
817
|
xue@1
|
818 delete[] lSpecs;
|
xue@1
|
819 return 0;
|
xue@1
|
820 }//MixSpectrogram
|
xue@1
|
821
|
xue@1
|
822 //---------------------------------------------------------------------------
|
Chris@5
|
823 /**
|
xue@1
|
824 function VSplitSpec: split a spectrogram vertically into left and right halves.
|
xue@1
|
825
|
xue@1
|
826 In: Spec[X][Y]: spectrogram to split
|
xue@1
|
827 Out: lSpec[X][Y/2], rSpec[X][Y/2]: the two half spectrograms
|
xue@1
|
828
|
xue@1
|
829 No return value. Both lSpec and rSpec are allocated anew. The caller is responsible to free these
|
xue@1
|
830 buffers.
|
xue@1
|
831 */
|
xue@1
|
832 void VSplitSpec(int X, int Y, double** Spec, double**& lSpec, double**& rSpec)
|
xue@1
|
833 {
|
xue@1
|
834 lSpec=new double*[X/2], rSpec=new double*[X/2];
|
xue@1
|
835 for(int i=0; i<X/2; i++)
|
xue@1
|
836 lSpec[i]=Spec[i], rSpec[i]=Spec[i+X/2];
|
xue@1
|
837 }//VSplitSpec
|
xue@1
|
838
|
Chris@5
|
839 /**
|
xue@1
|
840 function VSplitSpecs: split a multiresolution spectrogram vertically into left and right halves
|
xue@1
|
841
|
xue@1
|
842 A full spectrogram array is given in log2(N)+1 spectrograms, with the base spec of 1*N, 1st octave of
|
xue@1
|
843 2*(N/2), ..., last octave of N*1. When this array is split into two spectrogram arrays horizontally,
|
xue@1
|
844 the last spec (with the highest time resolution). Each of the two new arrays is given in log2(N)
|
xue@1
|
845 spectrograms.
|
xue@1
|
846
|
xue@1
|
847 In: Specs[nRes+1][][]: multiresolution spectrogram
|
xue@1
|
848 Out: lSpecs[nRes][][], rSpecs[nRes][][], the two half multiresolution spectrograms
|
xue@1
|
849
|
xue@1
|
850 This function allocates two 2nd order arrays of double*, which the caller is responsible to free.
|
xue@1
|
851 */
|
xue@1
|
852 void VSplitSpecs(int N, double*** Specs, double***& lSpecs, double***& rSpecs)
|
xue@1
|
853 {
|
xue@1
|
854 int nRes=log2(N); // new number of resolutions
|
xue@1
|
855 lSpecs=new double**[nRes], rSpecs=new double**[nRes];
|
xue@1
|
856 lSpecs[0]=new double*[nRes*N/2], rSpecs[0]=new double*[nRes*N/2]; for (int i=1; i<nRes; i++) lSpecs[i]=&lSpecs[0][i*N/2], rSpecs[i]=&rSpecs[0][i*N/2];
|
xue@1
|
857 for (int i=0, Fr=1; i<nRes; i++, Fr*=2)
|
xue@1
|
858 for (int j=0; j<Fr; j++)
|
xue@1
|
859 lSpecs[i][j]=Specs[i+1][j], rSpecs[i][j]=Specs[i+1][j+Fr];
|
xue@1
|
860 }//VSplitSpecs
|
xue@1
|
861
|
xue@1
|
862
|