c@37
|
1
|
c@37
|
2 program test;
|
c@37
|
3
|
c@37
|
4 af = load may.stream.audiofile;
|
c@37
|
5 plot = load may.plot;
|
c@37
|
6 cm = load may.matrix.complex;
|
c@37
|
7 mat = load may.matrix;
|
c@37
|
8 vec = load may.vector;
|
c@59
|
9 win = load may.signal.window;
|
c@60
|
10 test = load may.test.test;
|
c@59
|
11 mm = load may.mathmisc;
|
c@37
|
12 manipulate = load may.stream.manipulate;
|
c@37
|
13 syn = load may.stream.syntheticstream;
|
c@37
|
14
|
c@60
|
15 { cqtkernel } = load cqtkernel;
|
c@37
|
16 { cqt } = load cqt;
|
c@37
|
17
|
c@60
|
18 // We want to test:
|
c@60
|
19 //
|
c@60
|
20 // Kernel design -- check size (number of bins, number of atoms);
|
c@60
|
21 // check an example kernel against known data
|
c@60
|
22 //
|
c@60
|
23 // Time alignment -- feed a dirac train, check that peaks in all bins
|
c@60
|
24 // align
|
c@60
|
25 //
|
c@60
|
26 // Frequency discrimination -- feed a sinusoid, check peaks
|
c@60
|
27 //
|
c@60
|
28 // Latency compensation -- for dirac at 0, check peak can be found at
|
c@60
|
29 // 0 plus the declared latency
|
c@60
|
30 //
|
c@60
|
31 // Signal-noise ratio
|
c@60
|
32 //
|
c@60
|
33 // Specimen output for simple test case
|
c@60
|
34
|
c@60
|
35 /*
|
c@60
|
36
|
c@59
|
37 // Test with a single windowed sinusoid, repeating at various frequencies
|
c@59
|
38
|
c@59
|
39 sinTestStream sampleRate duration signalFreq = // duration is in samples
|
c@59
|
40 (sin = syn.sinusoid sampleRate signalFreq;
|
c@59
|
41 chunk = mat.getRow 0 (sin.read duration);
|
c@59
|
42 syn.precalculatedMono sampleRate (win.windowed win.hann chunk));
|
c@59
|
43
|
c@59
|
44 // We want to make a CQ transform spanning more than one octave, but
|
c@59
|
45 // not going all the way to fs/2 so we can test it also with
|
c@59
|
46 // frequencies above and below its extents
|
c@59
|
47
|
c@59
|
48 sampleRate = 100;
|
c@59
|
49
|
c@59
|
50 // fs/2 = 50 so 10->40 gives us 2 octaves
|
c@59
|
51 cqmin = 10;
|
c@59
|
52 cqmax = 40;
|
c@59
|
53 bpo = 4; // fairly arbitrary
|
c@59
|
54
|
c@59
|
55 testFreqs = map (* 5) [ 0..10 ];
|
c@59
|
56 duration = sampleRate * 2;
|
c@59
|
57
|
c@59
|
58 streamBuilder = sinTestStream sampleRate duration;
|
c@59
|
59
|
c@59
|
60 binForFreq f =
|
c@59
|
61 mm.round (bpo * mm.log2 (f / cqmin)) - 1;
|
c@59
|
62
|
c@59
|
63 for testFreqs do f:
|
c@59
|
64 str = streamBuilder f;
|
c@59
|
65 cq = cqt { maxFreq = cqmax, minFreq = cqmin, binsPerOctave = bpo } str;
|
c@59
|
66 m = mat.concatHorizontal (map cm.magnitudes cq.output);
|
c@59
|
67 println "binFrequencies = \(cq.kernel.binFrequencies)";
|
c@59
|
68 println "binForFreq \(f) = \(binForFreq f)";
|
c@59
|
69 success = all id
|
c@59
|
70 (map do c:
|
c@59
|
71 // passes test if the correct max bin, or the expected max
|
c@59
|
72 // is out of range, or if all bins are below a threshold
|
c@59
|
73 expected = binForFreq f;
|
c@59
|
74 good =
|
c@59
|
75 (expected < 0 or expected >= vec.length c) or
|
c@59
|
76 (vec.max c < 0.001) or
|
c@59
|
77 (vec.maxindex c == binForFreq f);
|
c@59
|
78 if (not good) then
|
c@59
|
79 println " * bad! maxindex \(vec.maxindex c) != expected \(binForFreq f) for freq \(f) in column: \(vec.list c)";
|
c@59
|
80 // println "matrix is:";
|
c@59
|
81 // mat.print m;
|
c@59
|
82 else
|
c@59
|
83 print "✓";
|
c@59
|
84 fi;
|
c@59
|
85 good;
|
c@59
|
86 done (mat.asColumns m));
|
c@59
|
87 println " success = \(success) for freq \(f)";
|
c@59
|
88 done;
|
c@59
|
89
|
c@59
|
90
|
c@59
|
91
|
c@59
|
92 /*
|
c@37
|
93 //testStream = manipulate.withDuration 96000 (syn.sinusoid 48000 500);
|
c@37
|
94 //testStream = manipulate.withDuration 96000 (syn.pulseTrain 48000 4);
|
c@44
|
95 testStream = af.open "sweep-48000.wav";
|
c@37
|
96 //testStream = af.open "sweep.wav";
|
c@37
|
97
|
c@43
|
98 // So the stream is [ 0, 1, 0, -1, 0, 1, 0, -1, ... ] :
|
c@44
|
99 //testStream = manipulate.withDuration 64 (syn.sinusoid 8 2);
|
c@38
|
100
|
c@56
|
101 testStream = manipulate.withDuration 32 (syn.pulseTrain 8 0.001);
|
c@37
|
102
|
c@37
|
103 eprintln "have test stream";
|
c@37
|
104
|
c@44
|
105 cq = cqt { maxFreq = testStream.sampleRate/2, minFreq = 50, binsPerOctave = 24 } testStream;
|
c@37
|
106
|
c@40
|
107 eprintln "bin frequencies: \(cq.kernel.binFrequencies)";
|
c@40
|
108
|
c@40
|
109 bigM = mat.concatHorizontal (map cm.magnitudes cq.output);
|
c@37
|
110
|
c@38
|
111 eprintln "overall output size = \(mat.size bigM)";
|
c@38
|
112
|
c@39
|
113 mat.print bigM;
|
c@38
|
114
|
c@38
|
115 //\() (plot.plot [Contour bigM]);
|
c@56
|
116 \() (plot.plot [Grid bigM]);
|
c@59
|
117 */
|
c@37
|
118 ()
|
c@37
|
119
|