changeset 15:0ddc2aa8885d

Pull out channel mixers to new file, add synthetic streams, start on playback
author Chris Cannam
date Sat, 15 Dec 2012 00:00:22 +0000
parents ff66f7df30bf
children e8d404787c35
files audiofile.yeti channels.yeti fmatrix.yeti playback.yeti syntheticstream.yeti
diffstat 5 files changed, 168 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/audiofile.yeti	Fri Dec 14 10:20:00 2012 +0000
+++ b/audiofile.yeti	Sat Dec 15 00:00:22 2012 +0000
@@ -10,6 +10,7 @@
 import java.nio: ByteBuffer, ByteOrder;
 
 mat = load fmatrix;
+ch = load channels;
 
 decode8u bytes doubles n is ~byte[] -> ~double[] -> number -> () =
    (for [0..n-1] do i:
@@ -70,13 +71,13 @@
 read' { format is ~AudioFormat, stream is ~AudioInputStream } n =
    (doubles = readInterleaved' { format, stream } n;
     channels = format#getChannels();
-    mat.deinterleaved channels doubles;
+    ch.deinterleaved channels doubles;
    );
 
 readMono' { format is ~AudioFormat, stream is ~AudioInputStream } n =
    (doubles = readInterleaved' { format, stream } n;
     channels = format#getChannels();
-    mat.mixedDownFromInterleaved channels doubles;
+    ch.mixedDownFromInterleaved channels doubles;
    );
 
 // Note, all this assumes the stream is non-blocking (i.e. available()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/channels.yeti	Sat Dec 15 00:00:22 2012 +0000
@@ -0,0 +1,68 @@
+
+module channels;
+
+vec = load fvector;
+mat = load fmatrix;
+        
+interleaved m = 
+   ({ cols, rows } = mat.dimensions m;
+    v = vec.zeros (cols * rows);
+    for [0..rows-1] do row:
+        for [0..cols-1] do col:
+            v[col * rows + row] := m[row][col];
+        done;
+    done;
+    v);
+
+deinterleaved rows v is number -> ~double[] -> array<~double[]> =
+    mat.generateMatrix do row col:
+        v[rows * col + row]
+    done rows ((vec.vectorLength v) / rows);
+
+mixedDown m =
+   (if empty? m then vec.zeros 0 else
+        { cols, rows } = mat.dimensions m;
+        v = vec.copyOfVector m[0];
+        for [1..rows-1] do row:
+            for [0..cols-1] do col:
+                v[col] := v[col] + m[row][col];
+            done;
+        done;
+        v;
+    fi);
+
+mixedDownFromInterleaved rows v is number -> ~double[] -> ~double[] =
+   (cols = ((vec.vectorLength 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');
+
+mixedFromInterleavedTo targetRows rows v is number -> number -> ~double[] -> ~double[] = 
+    if targetRows == rows then
+        v;
+    elif targetRows == 1 then
+        mixedDownFromInterleaved rows v;
+    else
+        cols = ((vec.vectorLength v) / rows);
+        v' = vec.zeros (cols * targetRows);
+        for [0..targetRows-1] do target:
+            for [0..cols-1] do col:
+                if target < rows then
+                    v'[col * targetRows + target] := v[col * rows + target];
+                elif rows == 1 then
+                    v'[col * targetRows + target] := v[col * rows];
+                fi
+            done
+        done;
+        v';
+    fi;
+
+{
+    interleaved, deinterleaved,
+    mixedDown, mixedDownFromInterleaved, mixedFromInterleavedTo,
+}
+
--- a/fmatrix.yeti	Fri Dec 14 10:20:00 2012 +0000
+++ b/fmatrix.yeti	Sat Dec 15 00:00:22 2012 +0000
@@ -29,49 +29,11 @@
 
 transposed m is array<~double[]> -> array<~double[]> = 
     generateMatrix do row col: m[col][row] done (cols m) (rows m);
-        
-interleaved m = 
-   ({ cols, rows } = dimensions m;
-    v = vec.zeros (cols * rows);
-    for [0..rows-1] do row:
-        for [0..cols-1] do col:
-            v[col * rows + row] := m[row][col];
-        done;
-    done;
-    v);
-
-deinterleaved rows v is number -> ~double[] -> array<~double[]> =
-    generateMatrix do row col:
-        v[rows * col + row]
-    done rows ((vec.vectorLength v) / rows);
-
-mixedDown m =
-   (if empty? m then vec.zeros 0 else
-        { cols, rows } = dimensions m;
-        v = vec.copyOfVector m[0];
-        for [1..rows-1] do row:
-            for [0..cols-1] do col:
-                v[col] := v[col] + m[row][col];
-            done;
-        done;
-        v;
-    fi);
-
-mixedDownFromInterleaved rows v is number -> ~double[] -> ~double[] =
-   (cols = ((vec.vectorLength 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');
 
 {
 generateMatrix, constMatrix, randomMatrix, zeroMatrix, identityMatrix,
 width, cols, height, rows, dimensions,
 copyOfMatrix,
-transposed, interleaved, deinterleaved,
-mixedDown, mixedDownFromInterleaved,
+transposed,
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/playback.yeti	Sat Dec 15 00:00:22 2012 +0000
@@ -0,0 +1,52 @@
+
+module playback;
+
+vec = load fvector;
+fr = load framer;
+af = load audiofile;
+ch = load channels;
+
+import javax.sound.sampled:
+    AudioSystem, AudioFormat, AudioFormat$Encoding, SourceDataLine;
+
+import java.nio: ByteBuffer, ByteOrder;
+
+open rate channels = 
+   (format = new AudioFormat(AudioFormat$Encoding#PCM_SIGNED, rate, 16,
+                             channels, channels * 2, rate, false);
+    line = AudioSystem#getSourceDataLine(format);
+    line#open(format);
+    line#start();
+    {
+        line,
+        channels = line#getFormat()#getChannels(),
+        close () = line#close(),
+    });
+
+play { line is ~SourceDataLine } samples =
+   (len = vec.vectorLength samples;
+    nb = len * 2;
+    bytes = new byte[nb];
+    bb = ByteBuffer#wrap(bytes, 0, nb);
+    bb#order(ByteOrder#LITTLE_ENDIAN);
+    sb = bb#asShortBuffer();
+    for [0..len-1] do i: sb#put(i, samples[i] * 32767.0); () done;
+    println "writing \(nb) bytes";
+    actual = line#write(bytes, 0, nb); 
+    ());
+    
+playStream stream =
+   (line = open stream.sampleRate stream.channels;
+    blocksize = 10240;
+    frames = fr.frames blocksize stream;
+    for frames do frame:
+        play line (ch.mixedFromInterleavedTo line.channels stream.channels frame)
+    done;
+    line.close());
+
+playFile filename = playStream (af.open filename);
+
+{
+    open, play, playStream, playFile,
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/syntheticstream.yeti	Sat Dec 15 00:00:22 2012 +0000
@@ -0,0 +1,44 @@
+
+module syntheticstream;
+
+vec = load fvector;
+
+monoStream generator rate seconds =
+   (n = seconds * rate;
+    box = {
+        var position = 0,
+        readInterleaved count = 
+           (rc = if position + count > n then n - position else count fi;
+            result = vec.zeros rc;
+            for [0..rc-1] do i:
+                result[i] := generator ((position + i) / rate)
+            done;
+            position := position + rc;
+            result),
+        get available () = n - position,
+    };
+    { 
+        box,
+        get channels () = 1,
+        get sampleRate () = rate,
+        get available () = box.available,
+        get finished? () = n <= box.position,
+        readInterleaved = box.readInterleaved,
+        read = box.readInterleaved,
+        readMono = box.readInterleaved,
+        readAll () = box.readInterleaved box.available,
+        readAllInterleaved () = box.readInterleaved box.available,
+        readAllMono () = box.readInterleaved box.available,
+        close = id,
+    });
+
+sinusoid freq rate =
+    monoStream (sin . (* (freq / (2*pi * rate)))) rate;
+
+whiteNoise =
+    monoStream \((Math#random() * 2.0) - 1.0);
+
+{
+    monoStream, sinusoid, whiteNoise,
+}
+