Mercurial > hg > silvet
comparison constant-q-cpp/misc/yeti/icqt.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 icqt; | |
32 | |
33 cqt = load cqt; | |
34 cm = load may.matrix.complex; | |
35 framer = load may.stream.framer; | |
36 win = load may.signal.window; | |
37 mm = load may.mathmisc; | |
38 vec = load may.vector; | |
39 resamp = load may.stream.resample; | |
40 manip = load may.stream.manipulate; | |
41 mat = load may.matrix; | |
42 | |
43 icqt cq = | |
44 (kdata = cq.kernel; | |
45 | |
46 // kdata.kernel is the kernel matrix for a single octave. It has | |
47 // width kdata.fftSize and height kdata.binsPerOctave * | |
48 // kdata.atomsPerFrame. | |
49 // | |
50 // kdata.fftHop is the overlap between kernel matrices in a single | |
51 // octave. | |
52 // | |
53 // cq.sampleRate is the output stream sample rate and cq.octaves | |
54 // the number of octaves. | |
55 // | |
56 // cq.cqComplex is the list of complex matrices containing the CQ | |
57 // output. Each has width kdata.atomsPerFrame * 2^(cq.octaves-1) | |
58 // and height kdata.binsPerOctave * cq.octaves. | |
59 | |
60 bpo = kdata.binsPerOctave; | |
61 atomsPerFrame = kdata.atomsPerFrame; | |
62 octaves = cq.octaves; | |
63 | |
64 // transform a single block, all octaves tall, into an array | |
65 // (indexed by octave) of lists of individual columns (valid | |
66 // values for that octave only) | |
67 decomposeOctaves mat = array | |
68 (map do oct: | |
69 inverted = cm.fromRows (reverse (cm.asRows mat)); | |
70 octMat = cm.rowSlice inverted (bpo * oct) (bpo * (oct + 1)); | |
71 gap = (mm.pow 2 oct) - 1; | |
72 pickFrom cols = | |
73 case cols of | |
74 c::cs: c::(pickFrom (drop gap cs)); | |
75 _: []; | |
76 esac; | |
77 pickFrom (cm.asColumns octMat); | |
78 done [0..octaves-1]); | |
79 | |
80 // transform a list of the arrays produced by decomposeOctaves | |
81 // into a single array (indexed by octave) of lists of the | |
82 // individual columns | |
83 flattenOctaves decomposed = | |
84 (flattenAux acc decomposed = | |
85 case decomposed of | |
86 chunk::rest: | |
87 flattenAux | |
88 (array | |
89 (map do oct: | |
90 acc[oct] ++ chunk[oct] | |
91 done [0..octaves-1])) | |
92 rest; | |
93 _: acc; | |
94 esac; | |
95 flattenAux (array (map \[] [0..octaves-1])) decomposed); | |
96 | |
97 // given a list of columns, deinterleave and pile up each sequence | |
98 // of atomsPerFrame columns into a single tall column and return | |
99 // the resulting list of tall columns | |
100 pile cols = | |
101 (pileAux acc cols = | |
102 if (length cols) >= atomsPerFrame then | |
103 atoms = take atomsPerFrame cols; | |
104 juggled = concat (reverse (cm.asRows (cm.fromColumns atoms))); | |
105 pileAux (juggled :: acc) (drop atomsPerFrame cols); | |
106 else | |
107 reverse acc | |
108 fi; | |
109 pileAux [] cols); | |
110 | |
111 octaveColumnLists = | |
112 map pile (list (flattenOctaves (map decomposeOctaves cq.cqComplex))); | |
113 | |
114 for octaveColumnLists do l: println "octave column list length: \(length l)" done; | |
115 | |
116 kernel = cm.transposed kdata.kernel; // right way around for the multiply | |
117 | |
118 spectra = | |
119 map do l: | |
120 map do col: | |
121 res = cm.transposed (cm.product kernel (cm.newComplexColumnVector col)); | |
122 cm.columnSlice res 0 (kdata.fftSize / 2 + 1) | |
123 done l; | |
124 done octaveColumnLists; | |
125 | |
126 eprintln "calculated spectra, now to ifft, overlap-add..."; | |
127 | |
128 rates = map do oct: cq.sampleRate / (mm.pow 2 oct) done [0..cq.octaves-1]; | |
129 | |
130 resynthesised = | |
131 map2 do frames rate: | |
132 framer.complexStreamed rate kdata.fftSize | |
133 [ FrequencyDomain true, Window win.boxcar, Hop kdata.fftHop ] | |
134 frames; | |
135 done spectra rates; | |
136 | |
137 eprintln "have streams:"; | |
138 for resynthesised eprintln; | |
139 | |
140 resampled = map (resamp.resampledTo cq.sampleRate) resynthesised; | |
141 | |
142 manip.sum resampled; | |
143 ); | |
144 | |
145 {icqt} |