comparison yeti/timefreq.yeti @ 12:0f6db1895e1c

Prepare the ground for cqt and templates
author Chris Cannam
date Fri, 21 Mar 2014 17:14:44 +0000
parents
children
comparison
equal deleted inserted replaced
11:f268212ac499 12:0f6db1895e1c
1
2 module timefreq;
3
4 // Obtain the time-frequency representation (based on constant-Q
5 // transform) as transcription input
6
7 af = load may.stream.audiofile;
8 mat = load may.matrix;
9 plot = load may.plot;
10 vec = load may.vector;
11
12 { pow } = load may.mathmisc;
13
14 { resampledTo } = load may.stream.resample;
15
16 { cqt } = load cqt;
17
18 prepareTimeFrequency wavfile =
19 (stream = resampledTo 44100 (af.openMono wavfile);
20
21 streamLength =
22 case stream.available of
23 Known n: n;
24 _: failWith "Audio file length unknown?!";
25 esac;
26
27 eprintln "streamLength = \(streamLength)";
28
29 //!!! original also scales to peak = 0.5
30
31 cq = cqt {
32 maxFreq = stream.sampleRate / 3,
33 minFreq = 27.5,
34 binsPerOctave = 60
35 } stream;
36
37 //!!! note: original also modifies the Q and atomHopFactor
38 eprintln "atomSpacing = \(cq.kernel.atomSpacing)";
39
40 matrices = case cq.output (Spectrogram ()) of
41 Real mm: mm;
42 _: failWith "Expected real";
43 esac;
44
45 eprintln "have \(length matrices) matrices of size \(mat.size (head matrices)), isRowMajor? = \(mat.isRowMajor? (head matrices))";
46
47 levels = concatMap do m:
48 map do c: vec.sum c done (mat.asColumns m);
49 done matrices;
50
51 nztail = find (> 0.1) levels;
52 nzonly = reverse (find (> 0.1) (reverse nztail));
53
54 eprintln "non-zero columns start at \(length levels - length nztail), go on for \(length nzonly) [of \(length levels)]";
55
56 nzstart = (length levels - length nztail) * cq.kernel.atomSpacing;
57 nzduration = (length nzonly) * cq.kernel.atomSpacing;
58
59 // Get a stream of columns at 25 per second.
60 //
61 // The original picks samples at a rate of 100-per-second then
62 // median filters to reduce noise then picks samples again at
63 // 25-per-second. We don't do that (yet)
64
65 samplesPerCol = stream.sampleRate / 25;
66 var sample = samplesPerCol - nzstart;
67
68 columns = take (nzduration / samplesPerCol)
69 (concatMap do m:
70 concatMap do col:
71 sample := sample + cq.kernel.atomSpacing;
72 if sample >= samplesPerCol then
73 sample := sample - samplesPerCol;
74 [col]
75 else
76 []
77 fi;
78 done (mat.asColumns m);
79 done matrices);
80
81 eprintln "have \(length columns) columns of \(vec.length (head columns)) values each";
82
83 // drop the lowest 55 of the 600 bins
84 columns = map do c:
85 vec.slice c 55 (vec.length c);
86 done columns;
87
88 eprintln "now have \(length columns) columns of \(vec.length (head columns))";
89
90 // plot.plot [ Grid (mat.fromColumns columns) ];
91
92 columns);
93
94
95 {
96 prepareTimeFrequency
97 }
98