Mercurial > hg > silvet
comparison constant-q-cpp/misc/yeti/cqtkernel.yeti @ 366:5d0a2ebb4d17
Bring dependent libraries in to repo
author | Chris Cannam |
---|---|
date | Fri, 24 Jun 2016 14:47:45 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
365:112766f4c34b | 366:5d0a2ebb4d17 |
---|---|
1 /* | |
2 Constant-Q library | |
3 Copyright (c) 2013-2014 Queen Mary, University of London | |
4 | |
5 Permission is hereby granted, free of charge, to any person | |
6 obtaining a copy of this software and associated documentation | |
7 files (the "Software"), to deal in the Software without | |
8 restriction, including without limitation the rights to use, copy, | |
9 modify, merge, publish, distribute, sublicense, and/or sell copies | |
10 of the Software, and to permit persons to whom the Software is | |
11 furnished to do so, subject to the following conditions: | |
12 | |
13 The above copyright notice and this permission notice shall be | |
14 included in all copies or substantial portions of the Software. | |
15 | |
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
21 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
23 | |
24 Except as contained in this notice, the names of the Centre for | |
25 Digital Music; Queen Mary, University of London; and Chris Cannam | |
26 shall not be used in advertising or otherwise to promote the sale, | |
27 use or other dealings in this Software without prior written | |
28 authorization. | |
29 */ | |
30 | |
31 module cqtkernel; | |
32 | |
33 vec = load may.vector; | |
34 complex = load may.complex; | |
35 window = load may.signal.window; | |
36 fft = load may.transform.fft; | |
37 cm = load may.matrix.complex; | |
38 | |
39 { pow, round, floor, ceil, nextPowerOfTwo } = load may.mathmisc; | |
40 | |
41 makeKernel { sampleRate, maxFreq, binsPerOctave } = | |
42 (q = 1; | |
43 atomHopFactor = 0.25; | |
44 thresh = 0.0005; | |
45 minFreq = (maxFreq/2) * (pow 2 (1/binsPerOctave)); | |
46 bigQ = q / ((pow 2 (1/binsPerOctave)) - 1); | |
47 | |
48 maxNK = round(bigQ * sampleRate / minFreq); | |
49 minNK = round(bigQ * sampleRate / | |
50 (minFreq * (pow 2 ((binsPerOctave-1) / binsPerOctave)))); | |
51 | |
52 atomHop = round(minNK * atomHopFactor); | |
53 | |
54 firstCentre = atomHop * (ceil ((ceil (maxNK/2)) / atomHop)); | |
55 | |
56 fftSize = nextPowerOfTwo (firstCentre + ceil (maxNK/2)); | |
57 | |
58 // eprintln "sampleRate = \(sampleRate), maxFreq = \(maxFreq), binsPerOctave = \(binsPerOctave), q = \(q), atomHopFactor = \(atomHopFactor), thresh = \(thresh)"; | |
59 // eprintln "minFreq = \(minFreq), bigQ = \(bigQ), maxNK = \(maxNK), minNK = \(minNK), atomHop = \(atomHop), firstCentre = \(firstCentre), fftSize = \(fftSize)"; | |
60 | |
61 winNr = floor((fftSize - ceil(maxNK/2) - firstCentre) / atomHop) + 1; | |
62 | |
63 lastCentre = firstCentre + (winNr - 1) * atomHop; | |
64 | |
65 fftHop = (lastCentre + atomHop) - firstCentre; | |
66 | |
67 // eprintln "winNr = \(winNr), lastCentre = \(lastCentre), fftHop = \(fftHop)"; | |
68 | |
69 fftFunc = fft.forward fftSize; | |
70 | |
71 // Note the MATLAB uses exp(2*pi*1i*x) for a complex generating | |
72 // function. We can't do that here; we need to generate real and imag | |
73 // parts separately as real = cos(2*pi*x), imag = sin(2*pi*x). | |
74 | |
75 binFrequencies = array []; | |
76 | |
77 kernels = map do k: | |
78 | |
79 nk = round(bigQ * sampleRate / (minFreq * (pow 2 ((k-1)/binsPerOctave)))); | |
80 | |
81 // the cq MATLAB toolbox uses a symmetric window for | |
82 // blackmanharris -- which is odd because it uses a periodic one | |
83 // for other types. Oh well | |
84 win = vec.divideBy nk | |
85 (vec.sqrt | |
86 (window.windowFunction (BlackmanHarris ()) [Symmetric true] nk)); | |
87 | |
88 fk = minFreq * (pow 2 ((k-1)/binsPerOctave)); | |
89 | |
90 push binFrequencies fk; | |
91 | |
92 genKernel f = vec.multiply | |
93 [win, | |
94 vec.fromList | |
95 (map do i: f (2 * pi * fk * i / sampleRate) done [0..nk-1])]; | |
96 | |
97 reals = genKernel cos; | |
98 imags = genKernel sin; | |
99 | |
100 atomOffset = firstCentre - ceil(nk/2); | |
101 | |
102 map do i: | |
103 | |
104 shift = vec.zeros (atomOffset + ((i-1) * atomHop)); | |
105 | |
106 specKernel = fftFunc | |
107 (complex.complexArray | |
108 (vec.concat [shift, reals]) | |
109 (vec.concat [shift, imags])); | |
110 | |
111 map do c: | |
112 if complex.magnitude c <= thresh then complex.zero else c fi | |
113 done specKernel; | |
114 | |
115 done [1..winNr]; | |
116 | |
117 done [1..binsPerOctave]; | |
118 | |
119 kmat = cm.toSparse (cm.scaled (1/fftSize) (cm.fromRows (concat kernels))); | |
120 | |
121 // eprintln "density = \(cm.density kmat) (\(cm.nonZeroValues kmat) of \(cm.width kmat * cm.height kmat))"; | |
122 | |
123 // Normalisation | |
124 | |
125 wx1 = vec.maxindex (complex.magnitudes (cm.getRow 0 kmat)); | |
126 wx2 = vec.maxindex (complex.magnitudes (cm.getRow (cm.height kmat - 1) kmat)); | |
127 | |
128 subset = cm.flipped (cm.columnSlice kmat wx1 (wx2+1)); | |
129 square = cm.product (cm.conjugateTransposed subset) subset; | |
130 | |
131 diag = complex.magnitudes (cm.getDiagonal 0 square); | |
132 wK = vec.slice diag (round(1/q)) (vec.length diag - round(1/q) - 2); | |
133 | |
134 weight = (fftHop / fftSize) / (vec.mean (vec.abs wK)); | |
135 weight = sqrt(weight); | |
136 | |
137 kernel = cm.scaled weight kmat; | |
138 | |
139 // eprintln "weight = \(weight)"; | |
140 | |
141 { | |
142 kernel, | |
143 fftSize, | |
144 fftHop, | |
145 binsPerOctave, | |
146 atomsPerFrame = winNr, | |
147 atomSpacing = atomHop, | |
148 firstCentre, | |
149 maxFrequency = maxFreq, | |
150 minFrequency = minFreq, | |
151 binFrequencies, | |
152 bigQ | |
153 }); | |
154 | |
155 { | |
156 makeKernel | |
157 } | |
158 |