annotate yeti/cqt.yeti @ 10:3dd3008f3b19

Start on code to apply the transform
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 25 Oct 2013 16:57:04 +0100
parents
children d7af615c2cc1
rev   line source
c@10 1
c@10 2 module cqt;
c@10 3
c@10 4 cqtkernel = load cqtkernel;
c@10 5 resample = load may.stream.resample;
c@10 6 manipulate = load may.stream.manipulate;
c@10 7 syn = load may.stream.syntheticstream;
c@10 8 cm = load may.matrix.complex;
c@10 9 mat = load may.matrix;
c@10 10 framer = load may.stream.framer;
c@10 11 cplx = load may.complex;
c@10 12 fft = load may.transform.fft;
c@10 13 vec = load may.vector;
c@10 14
c@10 15 { pow, round, floor, ceil, log2, nextPowerOfTwo } = load may.mathmisc;
c@10 16
c@10 17 cqt str =
c@10 18 (sampleRate = str.sampleRate;
c@10 19 maxFreq = sampleRate/2;
c@10 20 minFreq = 40;
c@10 21 binsPerOctave = 24;
c@10 22
c@10 23 println "Here";
c@10 24
c@10 25 octaves = ceil (log2 (maxFreq / minFreq));
c@10 26
c@10 27 println "Here: about to calculate stuff with \(octaves)";
c@10 28
c@10 29 actualMinFreq = (maxFreq / (pow 2 octaves)) * (pow 2 (1/binsPerOctave));
c@10 30
c@10 31 println "sampleRate = \(sampleRate), maxFreq = \(maxFreq), minFreq = \(minFreq), actualMinFreq = \(actualMinFreq), octaves = \(octaves), binsPerOctave = \(binsPerOctave)";
c@10 32
c@10 33 kdata = cqtkernel.makeKernel { sampleRate, maxFreq, binsPerOctave };
c@10 34
c@10 35 streams = manipulate.duplicated octaves str;
c@10 36
c@10 37 //!!! can't be right!
c@10 38 kernel = cm.transposed (cm.conjugateTransposed kdata.kernel);
c@10 39
c@10 40 println "have kernel";
c@10 41
c@10 42 fftFunc = fft.forward kdata.fftSize;
c@10 43
c@10 44 cqblocks =
c@10 45 map do octave:
c@10 46 frames = framer.monoFrames //!!! mono for now
c@10 47 { framesize = kdata.fftSize, hop = kdata.fftHop }
c@10 48 (resample.decimated (pow 2 octave) streams[octave]);
c@10 49 map do frame:
c@10 50 freq = fftFunc (cplx.complexArray frame (vec.zeros kdata.fftSize));
c@10 51 cm.product kernel (cm.newComplexColumnVector freq);
c@10 52 done frames;
c@10 53 done [0..octaves-1];
c@10 54
c@10 55 //!!! The comment below isn't true -- this is based on traditional
c@10 56 // cqt -- the atom hop structure for this version is different
c@10 57 // though so review later on
c@10 58
c@10 59 // Each (2^(octaves-1) * fftHop) input frames gives us an output
c@10 60 // structure conceptually like this:
c@10 61 //
c@10 62 // [][][][][][][][] <- fftHop frames per highest-octave output value
c@10 63 // [][][][][][][][] layered as many times as binsPerOctave (here 2)
c@10 64 // [--][--][--][--] <- fftHop*2 frames for the next lower octave
c@10 65 // [--][--][--][--] etc
c@10 66 // [------][------]
c@10 67 // [------][------]
c@10 68 // [--------------]
c@10 69 // [--------------]
c@10 70 //
c@10 71 // Our input is as a set of lazy frame lists, one list per octave.
c@10 72 // For each frame in the lowest octave
c@10 73
c@10 74 println "prepared block list";
c@10 75
c@10 76 cqblocks;
c@10 77
c@10 78 );
c@10 79
c@10 80 testStream = manipulate.withDuration 96000 (syn.sinusoid 48000 500);
c@10 81
c@10 82 println "have test stream";
c@10 83
c@10 84 cqt testStream;
c@10 85
c@10 86
c@10 87