annotate yetilab/stream/framer.yeti @ 158:b6db07468ed1

Rework stream to support indefinite-length streams and handle multiple channels in framer. Make compile, but some tests fail (and others are still missing).
author Chris Cannam
date Wed, 01 May 2013 12:03:45 +0100
parents cb5ab186f146
children 97df257b32d3
rev   line source
Chris@8 1
Chris@93 2 module yetilab.stream.framer;
Chris@8 3
Chris@25 4 /**
Chris@25 5 * Framer expresses a stream (or a file) as a lazy list of (possibly
Chris@158 6 * overlapping) frames of data.
Chris@25 7 */
Chris@25 8
Chris@93 9 block = load yetilab.block.block;
Chris@93 10 bf = load yetilab.block.blockfuncs;
Chris@93 11 af = load yetilab.stream.audiofile;
Chris@93 12 win = load yetilab.transform.window;
Chris@93 13 fft = load yetilab.transform.fft;
Chris@158 14 mat = load yetilab.matrix.matrix;
Chris@158 15 ch = load yetilab.stream.channels;
Chris@8 16
Chris@32 17 blockList framesize stream =
Chris@14 18 if stream.finished? then
Chris@158 19 stream.close ();
Chris@158 20 [ mat.zeroMatrix { rows = stream.channels, columns = 0 } ]
Chris@13 21 else
Chris@158 22 mat.resizedTo { rows = stream.channels, columns = framesize }
Chris@158 23 (stream.read framesize)
Chris@32 24 :. \(blockList framesize stream);
Chris@13 25 fi;
Chris@13 26
Chris@47 27 overlappingBlockList size hop stream valid buffer =
Chris@29 28 (
Chris@158 29 m = stream.read hop;
Chris@158 30 obtained = mat.width m;
Chris@23 31
Chris@32 32 // Retain framesize - hop samples from old buffer, add hop samples
Chris@29 33 // (zero-padded if necessary) just read
Chris@158 34 buffer = map2
Chris@158 35 do buf row:
Chris@158 36 block.concat
Chris@158 37 [block.rangeOf buf hop (size-hop),
Chris@158 38 block.resizedTo hop (m.getRow row)];
Chris@158 39 done buffer [0..stream.channels-1];
Chris@23 40
Chris@23 41 // Number of "valid" elements (not tail-end zero-padding) left in buffer
Chris@24 42 remaining = valid - (hop - obtained);
Chris@23 43
Chris@23 44 if remaining <= 0 then
Chris@23 45 stream.close ();
Chris@23 46 [];
Chris@12 47 else
Chris@158 48 mat.newMatrix (RowMajor ()) (map block.list buffer)
Chris@158 49 :. \(overlappingBlockList size hop stream remaining buffer);
Chris@23 50 fi);
Chris@14 51
Chris@32 52 frames { framesize, hop } stream =
Chris@32 53 if framesize == hop then
Chris@32 54 blockList framesize stream
Chris@30 55 else
Chris@32 56 overlappingBlockList framesize hop stream
Chris@158 57 framesize (map \(block.zeros framesize) [0..stream.channels-1]);
Chris@30 58 fi;
Chris@14 59
Chris@158 60 monoFrames params stream =
Chris@158 61 map ch.mixedDown (frames params stream);
Chris@158 62
Chris@49 63 windowedFrames { framesize, hop, window } stream =
Chris@49 64 (win = window framesize;
Chris@158 65 map (bf.multiply win) (monoFrames { framesize, hop } stream));
Chris@49 66
Chris@49 67 frequencyDomainFrames { framesize, hop } stream =
Chris@49 68 (f = fft.realForward framesize;
Chris@49 69 map f (windowedFrames { framesize, hop, window = win.hann } stream));
Chris@23 70
Chris@11 71 {
Chris@30 72 frames,
Chris@158 73 monoFrames,
Chris@49 74 windowedFrames,
Chris@49 75 frequencyDomainFrames,
Chris@49 76
Chris@49 77 framesOfFile parameters filename =
Chris@146 78 frames parameters (af.open filename),
Chris@49 79
Chris@158 80 monoFramesOfFile parameters filename =
Chris@158 81 monoFrames parameters (af.open filename),
Chris@158 82
Chris@49 83 windowedFramesOfFile parameters filename =
Chris@146 84 windowedFrames parameters (af.open filename),
Chris@49 85
Chris@49 86 frequencyDomainFramesOfFile parameters filename =
Chris@146 87 frequencyDomainFrames parameters (af.open filename),
Chris@11 88 }
Chris@8 89