annotate yeti/test_frequency.yeti @ 65:bb1799a6d690

Pull out tests
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 14 Feb 2014 11:55:03 +0000
parents
children d6dd6e1cc00e
rev   line source
c@65 1
c@65 2 module test_frequency;
c@65 3
c@65 4 mat = load may.matrix;
c@65 5 vec = load may.vector;
c@65 6 win = load may.signal.window;
c@65 7 mm = load may.mathmisc;
c@65 8 cm = load may.matrix.complex;
c@65 9 syn = load may.stream.syntheticstream;
c@65 10
c@65 11 { cqt } = load cqt;
c@65 12
c@65 13 // Test with a single windowed sinusoid, repeating at various frequencies
c@65 14
c@65 15 sinTestStream sampleRate duration signalFreq = // duration is in samples
c@65 16 (sin = syn.sinusoid sampleRate signalFreq;
c@65 17 chunk = mat.getRow 0 (sin.read duration);
c@65 18 syn.precalculatedMono sampleRate (win.windowed win.hann chunk));
c@65 19
c@65 20 // We want to make a CQ transform spanning more than one octave, but
c@65 21 // not going all the way to fs/2 so we can test it also with
c@65 22 // frequencies above and below its extents
c@65 23
c@65 24 sampleRate = 100;
c@65 25
c@65 26 // fs/2 = 50 so 10->40 gives us 2 octaves
c@65 27 cqmin = 10;
c@65 28 cqmax = 40;
c@65 29 bpo = 4; // fairly arbitrary
c@65 30
c@65 31 testFreqs = map (* 5) [ 0..10 ];
c@65 32 duration = sampleRate * 2;
c@65 33
c@65 34 streamBuilder = sinTestStream sampleRate duration;
c@65 35
c@65 36 binForFreq f =
c@65 37 mm.round (bpo * mm.log2 (f / cqmin)) - 1;
c@65 38
c@65 39 tests = mapIntoHash
c@65 40 do f: "freq_\(f)" done
c@65 41 do f: \(
c@65 42 str = streamBuilder f;
c@65 43 cq = cqt { maxFreq = cqmax, minFreq = cqmin, binsPerOctave = bpo } str;
c@65 44 m = mat.concatHorizontal (map cm.magnitudes cq.output);
c@65 45 // println "binFrequencies = \(cq.kernel.binFrequencies)";
c@65 46 // println "binForFreq \(f) = \(binForFreq f)";
c@65 47 success = all id
c@65 48 (map do c:
c@65 49 // passes test if the correct max bin, or the expected max
c@65 50 // is out of range, or if all bins are below a threshold
c@65 51 expected = binForFreq f;
c@65 52 good =
c@65 53 (expected < 0 or expected >= vec.length c) or
c@65 54 (vec.max c < 0.001) or
c@65 55 (vec.maxindex c == binForFreq f);
c@65 56 if (not good) then
c@65 57 println " * bad! maxindex \(vec.maxindex c) != expected \(binForFreq f) for freq \(f) in column: \(vec.list c)";
c@65 58 println "matrix is:";
c@65 59 mat.print m;
c@65 60 else
c@65 61 print "✓";
c@65 62 fi;
c@65 63 good;
c@65 64 done (mat.asColumns m));
c@65 65 success;
c@65 66 ) done
c@65 67 testFreqs;
c@65 68
c@65 69 tests is hash<string, () -> boolean>