c@10: c@10: module cqt; c@10: c@10: cqtkernel = load cqtkernel; c@10: resample = load may.stream.resample; c@10: manipulate = load may.stream.manipulate; c@10: syn = load may.stream.syntheticstream; c@10: cm = load may.matrix.complex; c@10: mat = load may.matrix; c@10: framer = load may.stream.framer; c@10: cplx = load may.complex; c@10: fft = load may.transform.fft; c@10: vec = load may.vector; c@10: c@10: { pow, round, floor, ceil, log2, nextPowerOfTwo } = load may.mathmisc; c@10: c@10: cqt str = c@10: (sampleRate = str.sampleRate; c@10: maxFreq = sampleRate/2; c@10: minFreq = 40; c@10: binsPerOctave = 24; c@10: c@10: println "Here"; c@10: c@10: octaves = ceil (log2 (maxFreq / minFreq)); c@10: c@10: println "Here: about to calculate stuff with \(octaves)"; c@10: c@10: actualMinFreq = (maxFreq / (pow 2 octaves)) * (pow 2 (1/binsPerOctave)); c@10: c@10: println "sampleRate = \(sampleRate), maxFreq = \(maxFreq), minFreq = \(minFreq), actualMinFreq = \(actualMinFreq), octaves = \(octaves), binsPerOctave = \(binsPerOctave)"; c@10: c@10: kdata = cqtkernel.makeKernel { sampleRate, maxFreq, binsPerOctave }; c@10: c@10: streams = manipulate.duplicated octaves str; c@10: c@10: //!!! can't be right! c@10: kernel = cm.transposed (cm.conjugateTransposed kdata.kernel); c@10: c@10: println "have kernel"; c@10: c@10: fftFunc = fft.forward kdata.fftSize; c@10: c@10: cqblocks = c@10: map do octave: c@10: frames = framer.monoFrames //!!! mono for now c@10: { framesize = kdata.fftSize, hop = kdata.fftHop } c@10: (resample.decimated (pow 2 octave) streams[octave]); c@10: map do frame: c@10: freq = fftFunc (cplx.complexArray frame (vec.zeros kdata.fftSize)); c@10: cm.product kernel (cm.newComplexColumnVector freq); c@10: done frames; c@10: done [0..octaves-1]; c@10: c@10: //!!! The comment below isn't true -- this is based on traditional c@10: // cqt -- the atom hop structure for this version is different c@10: // though so review later on c@10: c@10: // Each (2^(octaves-1) * fftHop) input frames gives us an output c@10: // structure conceptually like this: c@10: // c@10: // [][][][][][][][] <- fftHop frames per highest-octave output value c@10: // [][][][][][][][] layered as many times as binsPerOctave (here 2) c@10: // [--][--][--][--] <- fftHop*2 frames for the next lower octave c@10: // [--][--][--][--] etc c@10: // [------][------] c@10: // [------][------] c@10: // [--------------] c@10: // [--------------] c@10: // c@10: // Our input is as a set of lazy frame lists, one list per octave. c@10: // For each frame in the lowest octave c@10: c@10: println "prepared block list"; c@10: c@10: cqblocks; c@10: c@10: ); c@10: c@10: testStream = manipulate.withDuration 96000 (syn.sinusoid 48000 500); c@10: c@10: println "have test stream"; c@10: c@10: cqt testStream; c@10: c@10: c@10: