changeset 20:0b04bc5d2e53

Update to use Block tagged types throughout
author Chris Cannam
date Thu, 20 Dec 2012 11:58:48 +0000
parents 327dac3a8e1f
children 6c5d2fe1b260
files audiofile.yeti block.yeti blockmatrix.yeti channels.yeti fmatrix.yeti framer.yeti fvector.yeti playback.yeti stream.yeti syntheticstream.yeti
diffstat 10 files changed, 111 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- a/audiofile.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/audiofile.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -9,8 +9,9 @@
 
 import java.nio: ByteBuffer, ByteOrder;
 
-mat = load fmatrix;
+str = load stream;
 ch = load channels;
+block = load block;
 
 decode8u bytes doubles n is ~byte[] -> ~double[] -> number -> () =
    (for [0..n-1] do i:
@@ -59,25 +60,25 @@
     bytesPerSample = format#getSampleSizeInBits() / 8;
     bytes = new byte[nframes * channels * bytesPerSample];
     bytesRead = stream#read(bytes);
-    if bytesRead <= 0 then new double[0];
+    if bytesRead <= 0 then block.zeros 0;
     else
         n = int(bytesRead / bytesPerSample);
         doubles = new double[n];
         decode { format } bytes doubles n;
-        doubles;
+        block.block doubles;
     fi;
    );
 
 read' { format is ~AudioFormat, stream is ~AudioInputStream } n =
-   (doubles = readInterleaved' { format, stream } n;
+   (b = readInterleaved' { format, stream } n;
     channels = format#getChannels();
-    ch.deinterleaved channels doubles;
+    ch.deinterleaved channels b;
    );
 
 readMono' { format is ~AudioFormat, stream is ~AudioInputStream } n =
-   (doubles = readInterleaved' { format, stream } n;
+   (b = readInterleaved' { format, stream } n;
     channels = format#getChannels();
-    ch.mixedDownFromInterleaved channels doubles;
+    ch.mixedDownFromInterleaved channels b;
    );
 
 // Note, all this assumes the stream is non-blocking (i.e. available()
@@ -105,19 +106,18 @@
    (f = new File(name);
     stream = AudioSystem#getAudioInputStream(f);
     format = stream#getFormat();
-    {
+    len = available' { format, stream }; // at start of stream
+    str.stream {
         stream,
         format,
-        get channels () = format#getChannels(),
-        get sampleRate () = format#getSampleRate(),
+        len,
+        rate = format#getSampleRate(),
+        channels = format#getChannels(),
+        get position () = len - available' { stream, format },
         get available () = available' { stream, format },
-        get finished? () = finished?' { stream },
         read = read' { stream, format },
-        readAll () = readAll' { stream, format },
         readInterleaved = readInterleaved' { stream, format },
-        readAllInterleaved () = readAllInterleaved' { stream, format },
         readMono = readMono' { stream, format },
-        readAllMono () = readAllMono' { stream, format },
         close () = close' { stream },
     } );
 
--- a/block.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/block.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -1,42 +1,27 @@
 module block;
 
-import java.util: Arrays;
+vec = load fvector;
 
-zeros n = 
-    Block new double[n];
+zeros = Block . vec.zeros;
+ones  = Block . vec.ones;
+
+block v is ~double[] -> (Block ~double[]) = 
+    Block v;
 
 unblock b is (Block ~double[]) -> ~double[] =
     case b of Block a: a esac;
 
-ones n = 
-   (v = unblock (zeros n);
-    for [0..n-1] do i: v[i] := 1.0 done;
-    Block v);
+list' b = vec.list (unblock b);
+length' b = vec.length (unblock b);
 
-block l is list?<number> -> (Block ~double[]) =
-   (arr = array(l);
-    len = length arr;
-    v = unblock (zeros len);
-    for [0..len-1] do i: v[i] := arr[i] done;
-    Block v);
-
-norec list b is (Block ~double[]) -> list<number> =
-    list (unblock b);
-
-norec length b = 
-    length (list b);
-
-copyOf b is (Block ~double[]) -> (Block ~double[]) = 
-   (v = unblock b;
-    Block Arrays#copyOf(v, length b));
-
-subset b start len is (Block ~double[]) -> number -> number -> (Block ~double[]) = 
-    Block Arrays#copyOfRange(unblock b, start, start + len);
+copyOf b = Block (vec.copyOf (unblock b));
+subset b start len = Block (vec.subset (unblock b) start len);
 
 {
 zeros, ones,
 block, unblock,
-length,
+length = length',
+list = list',
 copyOf, subset,
 }
 
--- a/blockmatrix.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-module blockmatrix;
-
-// Basic matrices using a Block for each row. I don't like this one,
-// it's clumsy
-
-block = load block;
-
-zeroMatrix rows cols = array (map \(block.zeros cols) [1..rows]);
-
-generateMatrix f rows cols =
-   (m = zeroMatrix rows cols;
-    for [0..rows-1] do row:
-       (rb = block.unblock m[row];
-        for [0..cols-1] do col:
-            rb[col] := f row col;
-        done);
-    done;
-    m);
-
-constMatrix n = generateMatrix do row col: n done;
-randomMatrix = generateMatrix do row col: Math#random() done;
-identityMatrix = constMatrix 1;
-
-width m = if length m > 0 then block.length m[0] else 0 fi;
-cols = width;
-
-height m = length m;
-rows = height;
-
-dimensions m = { cols = width m, rows = height m };
-
-copyOfMatrix m = array (map block.copyOf m);
-
-cell m row col = 
-   (rb = block.unblock m[col];
-    rb[row]);
-
-transposed m is array<Block ~double[]> -> array<Block ~double[]> = 
-    generateMatrix do row col: cell m row col done (cols m) (rows m);
-
-{
-generateMatrix, constMatrix, randomMatrix, zeroMatrix, identityMatrix,
-width, cols, height, rows, dimensions,
-copyOfMatrix,
-transposed,
-}
-
--- a/channels.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/channels.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -2,6 +2,7 @@
 module channels;
 
 vec = load fvector;
+block = load block;
 mat = load fmatrix;
         
 interleaved m = 
@@ -12,42 +13,45 @@
             v[col * rows + row] := m[row][col];
         done;
     done;
-    v);
+    block.block v);
 
-deinterleaved rows v is number -> ~double[] -> array<~double[]> =
-    mat.generateMatrix do row col:
+deinterleaved rows b =
+   (v = block.unblock b;
+    mat.generate do row col:
         v[rows * col + row]
-    done rows ((vec.vectorLength v) / rows);
+    done rows ((vec.length v) / rows));
 
 mixedDown m =
-   (if empty? m then vec.zeros 0 else
+   (if empty? m then block.zeros 0 else
         { cols, rows } = mat.dimensions m;
-        v = vec.copyOfVector m[0];
+        v = vec.copyOf m[0];
         for [1..rows-1] do row:
             for [0..cols-1] do col:
                 v[col] := v[col] + m[row][col];
             done;
         done;
-        v;
+        block.block v;
     fi);
 
-mixedDownFromInterleaved rows v is number -> ~double[] -> ~double[] =
-   (cols = ((vec.vectorLength v) / rows);
+mixedDownFromInterleaved rows b =
+   (v = block.unblock b;
+    cols = ((vec.length v) / rows);
     v' = vec.zeros cols;
     for [0..rows-1] do row:
         for [0..cols-1] do col:
             v'[col] := v'[col] + v[col * rows + row];
         done;
     done;
-    v');
+    block.block v');
 
-mixedFromInterleavedTo targetRows rows v is number -> number -> ~double[] -> ~double[] = 
+mixedFromInterleavedTo targetRows rows b = 
     if targetRows == rows then
-        v;
+        b;
     elif targetRows == 1 then
-        mixedDownFromInterleaved rows v;
+        mixedDownFromInterleaved rows b;
     else
-        cols = ((vec.vectorLength v) / rows);
+        v = block.unblock b;
+        cols = ((vec.length v) / rows);
         v' = vec.zeros (cols * targetRows);
         for [0..targetRows-1] do target:
             for [0..cols-1] do col:
@@ -58,7 +62,7 @@
                 fi
             done
         done;
-        v';
+        block.block v';
     fi;
 
 {
--- a/fmatrix.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/fmatrix.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -6,7 +6,7 @@
 
 zeroMatrix rows cols = array (map \(vec.zeros cols) [1..rows]);
 
-generateMatrix f rows cols =
+generate f rows cols =
    (m = zeroMatrix rows cols;
     for [0..rows-1] do row:
         for [0..cols-1] do col:
@@ -15,11 +15,11 @@
     done;
     m);
 
-constMatrix n = generateMatrix do row col: n done;
-randomMatrix = generateMatrix do row col: Math#random() done;
+constMatrix n = generate do row col: n done;
+randomMatrix = generate do row col: Math#random() done;
 identityMatrix = constMatrix 1;
 
-width m = if length m > 0 then vec.vectorLength m[0] else 0 fi;
+width m = if length m > 0 then vec.length m[0] else 0 fi;
 cols = width;
 
 height m = length m;
@@ -27,15 +27,15 @@
 
 dimensions m = { cols = width m, rows = height m };
 
-copyOfMatrix m = array (map vec.copyOfVector m);
+copyOf m = array (map vec.copyOf m);
 
 transposed m is array<~double[]> -> array<~double[]> = 
-    generateMatrix do row col: m[col][row] done (cols m) (rows m);
+    generate do row col: m[col][row] done (cols m) (rows m);
 
 {
-generateMatrix, constMatrix, randomMatrix, zeroMatrix, identityMatrix,
+generate, constMatrix, randomMatrix, zeroMatrix, identityMatrix,
 width, cols, height, rows, dimensions,
-copyOfMatrix,
+copyOf,
 transposed,
 }
 
--- a/framer.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/framer.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -2,6 +2,7 @@
 module framer;
 
 vec = load fvector;
+block = load block;
 af = load audiofile;
 
 blockList blocksize stream =
@@ -16,24 +17,25 @@
     if stream.finished? then
        (stream.close (); [] ); //!!! wrong! need unit tests! need to read from any stream, not only a file, to facilitate that
     else
-        block = stream.readMono hopsize;
-        blen = vec.vectorLength block;
-        for [0..blen-1] do i: buffer[blocksize - hopsize + i] := block[i] done;
+        b = stream.readMono hopsize;
+        samples = block.unblock b;
+        blen = block.length b;
+        for [0..blen-1] do i: buffer[blocksize - hopsize + i] := samples[i] done;
         for [blen..hopsize-1] do i: buffer[blocksize - hopsize + i] := 0.0 done;
-        v = vec.subVector buffer 0 blocksize;
+        v = Block (vec.subset buffer 0 blocksize);
         for [hopsize..blocksize-1] do i: buffer[i - hopsize] := buffer[i] done;
         v :. \(overlappingBlockList blocksize hopsize stream buffer);
     fi;
 
 overlappingFrames blocksize hopsize stream =
-    overlappingBlockList blocksize hopsize stream (new double[blocksize]);
+    overlappingBlockList blocksize hopsize stream (vec.zeros blocksize);
 
 frames blocksize stream =
     blockList blocksize stream;
 
 overlappingFramesOfFile blocksize hopsize filename =
     overlappingBlockList blocksize hopsize (af.open filename)
-        (new double[blocksize]);
+        (vec.zeros blocksize);
 
 framesOfFile blocksize filename =
     blockList blocksize (af.open filename);
--- a/fvector.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/fvector.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -2,27 +2,42 @@
 
 import java.util: Arrays;
 
-zeros n = new double[n];
-ones  n = (a = zeros n; for [0..n-1] do i: a[i] := 1.0 done; a);
+zeros n =
+    new double[n];
+
+ones n =
+   (a = zeros n;
+    for [0..n-1] do i:
+        a[i] := 1.0;
+    done;
+    a);
 
 vector l is list?<number> -> ~double[] =
    (arr = array(l);
     len = length arr;
     v = zeros len;
-    for [0..len-1] do i: v[i] := arr[i] done;
+    for [0..len-1] do i:
+        v[i] := arr[i];
+    done;
     v);
 
-listWrap a is ~double[] -> list<number> = list a;
+list' a is ~double[] -> list<number> =
+    list a;
 
-vectorLength v = length (listWrap v);
+length' =
+    length . list';
 
-copyOfVector v is ~double[] -> ~double[] = Arrays#copyOf(v, length(listWrap v));
+copyOf v is ~double[] -> ~double[] =
+    Arrays#copyOf(v, list' v |> length);
 
-subVector v start len is ~double[] -> number -> number -> ~double[] = Arrays#copyOfRange(v, start, start + len);
+subset v start len is ~double[] -> number -> number -> ~double[] =
+    Arrays#copyOfRange(v, start, start + len);
 
 {
-zeros, ones, vector,
-vectorLength,
-copyOfVector, subVector,
+zeros, ones,
+vector,
+length = length',
+list = list',
+copyOf, subset,
 }
 
--- a/playback.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/playback.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -1,7 +1,7 @@
 
 module playback;
 
-vec = load fvector;
+block = load block;
 fr = load framer;
 af = load audiofile;
 ch = load channels;
@@ -11,7 +11,7 @@
 
 import java.nio: ByteBuffer, ByteOrder;
 
-open rate channels = 
+open { rate, channels } = 
    (format = new AudioFormat(AudioFormat$Encoding#PCM_SIGNED, rate, 16,
                              channels, channels * 2, rate, false);
     line = AudioSystem#getSourceDataLine(format);
@@ -23,8 +23,9 @@
         close () = line#close(),
     });
 
-play { line is ~SourceDataLine } samples =
-   (len = vec.vectorLength samples;
+playBlock { line is ~SourceDataLine } b =
+   (len = block.length b;
+    samples = block.unblock b;
     nb = len * 2;
     bytes = new byte[nb];
     bb = ByteBuffer#wrap(bytes, 0, nb);
@@ -34,14 +35,14 @@
     println "writing \(nb) bytes";
     actual = line#write(bytes, 0, nb); 
     ());
+
+play line blocks = for blocks (playBlock line);
     
 playStream stream =
-   (line = open stream.sampleRate stream.channels;
+   (line = open { rate = stream.sampleRate, channels = stream.channels };
     blocksize = 10240;
-    frames = fr.frames blocksize stream;
-    for frames do frame:
-        play line (ch.mixedFromInterleavedTo line.channels stream.channels frame)
-    done;
+    play line (map (ch.mixedFromInterleavedTo line.channels stream.channels)
+                   (fr.frames blocksize stream));
     line.close());
 
 playFile filename = playStream (af.open filename);
--- a/stream.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/stream.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -1,8 +1,6 @@
 
 module stream;
 
-vec = load fvector;
-
 monoStream box =
    (readAll box = box.read (box.len - box.position);
     {
@@ -10,12 +8,14 @@
         get channels () = 1,
         get sampleRate () = box.rate,
         get available () = box.len - box.position,
+        get finished? () = not (box.len > box.position),
         read = box.read,
         readInterleaved = box.read,
         readMono = box.read,
         readAll = readAll box,
         readAllInterleaved = readAll box,
         readAllMono = readAll box,
+        close = box.close,
     });
 
 stream box = 
@@ -25,12 +25,14 @@
         get channels () = box.channels,
         get sampleRate () = box.rate,
         get available () = box.len - box.position,
+        get finished? () = not (box.len > box.position),
         read = box.read,
         readInterleaved = box.readInterleaved,
         readMono = box.readMono,
         readAll = box.read (box.len - box.position),
         readAllInterleaved = box.readInterleaved (box.len - box.position),
         readAllMono = box.readMono (box.len - box.position),
+        close = box.close,
     });
 
 { monoStream, stream }
--- a/syntheticstream.yeti	Mon Dec 17 16:00:12 2012 +0000
+++ b/syntheticstream.yeti	Thu Dec 20 11:58:48 2012 +0000
@@ -3,6 +3,7 @@
 
 str = load stream;
 vec = load fvector;
+block = load block;
 
 generated rate generator seconds =
     str.monoStream {
@@ -16,26 +17,28 @@
                 result[i] := generator ((position + i) / rate)
             done;
             position := position + rc;
-            result),
+            block.block result),
+        close = \(),
         };
 
-sinusoid rate freq =
-    generated rate (sin . (* (freq / (2*pi * rate))));
+sinusoid rate freq seconds =
+    generated rate (sin . (* (freq / (2*pi * rate)))) seconds;
 
-whiteNoise rate =
-    generated rate \((Math#random() * 2.0) - 1.0);
+whiteNoise rate seconds =
+    generated rate \((Math#random() * 2.0) - 1.0) seconds;
 
 precalculated rate data is number -> ~double[] -> 'a =
-   (n = vec.vectorLength data;
+   (n = vec.length data;
     str.monoStream {
         var position = 0,
         len = n,
         rate,
         read count = 
            (rc = min count (len - position);
-            result = vec.subVector data position rc;
+            result = vec.subset data position rc;
             position := position + rc;
-            result),
+            block.block result),
+        close = \(),
     });
 
 {