changeset 3:29e39209360b

Actual audio file read code; implement deinterleaved
author Chris Cannam
date Thu, 06 Dec 2012 22:19:29 +0000
parents 51c7fea7d805
children 0009af03700e
files audio.yeti matrix.yeti
diffstat 2 files changed, 91 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/audio.yeti	Sun Dec 02 12:09:32 2012 +0000
+++ b/audio.yeti	Thu Dec 06 22:19:29 2012 +0000
@@ -2,30 +2,95 @@
 module audio;
 
 import javax.sound.sampled:
-     AudioSystem, AudioInputStream, AudioFormat, UnsupportedAudioFileException;
+     AudioSystem, AudioInputStream, AudioFormat, AudioFormat$Encoding,
+     UnsupportedAudioFileException;
 
 import java.io: File, IOException;
 
+import java.nio: ByteBuffer, ByteOrder;
+
 mat = load matrix;
 
-openAudioFile name is string -> 'a = 
+open name is string -> 'a = 
    (f = new File(name);
     stream = AudioSystem#getAudioInputStream(f);
     format = stream#getFormat();
     { stream, format } );
 
-read file n is { .format is ~AudioFormat, .stream is ~AudioInputStream } ->
-    number -> 'a =
-   (ch = file.format#getChannels();
-    bbuf = new byte[n * ch * file.format#sampleSizeInBits() / 8];
-    fbuf = new float[n * ch];
-    file.f#read(bbuf);
-    //!!! magic here
-    mat.uninterleave ch fbuf;
+close { stream is ~AudioInputStream } =
+    stream#close();
+
+decode8u bytes floats n is ~byte[] -> ~float[] -> number -> () =
+   (for [0..n-1] do i:
+       floats[i] := (bytes[i] / 128.0) - 1.0;
+    done
    );
 
+decode16s bytes floats n is ~byte[] -> ~float[] -> number -> () =
+   (bb = ByteBuffer#wrap(bytes, 0, n * 2);
+    bb#order(ByteOrder#LITTLE_ENDIAN);
+    for [0..n-1] do i:
+       floats[i] := bb#getShort(i*2) / 32768.0;
+    done
+   );
+
+decode32f bytes floats n is ~byte[] -> ~float[] -> number -> () =
+   (bb = ByteBuffer#wrap(bytes, 0, n * 4);
+    bb#order(ByteOrder#LITTLE_ENDIAN);
+    for [0..n-1] do i:
+       floats[i] := bb#getFloat(i*4);
+    done
+   );
+
+decodeFail () = 
+    throw new UnsupportedAudioFileException("File format not supported. Supported formats are 8-bit unsigned PCM, 16-bit signed little-endian PCM, or IEEE float");
+
+decode { format is ~AudioFormat } bytes floats n = 
+   (if format#isBigEndian() then
+        decodeFail()
+    else
+        enc = format#getEncoding();
+        bits = format#getSampleSizeInBits();
+        if bits == 32 then
+            decode32f bytes floats n;
+        elif bits == 16 and enc == AudioFormat$Encoding#PCM_SIGNED then
+            decode16s bytes floats n;
+        elif bits == 8 and enc == AudioFormat$Encoding#PCM_UNSIGNED then
+            decode8u bytes floats n;
+        else
+            decodeFail();
+        fi
+    fi);
+
+readInterleaved { format is ~AudioFormat, stream is ~AudioInputStream } nframes =
+   (channels = format#getChannels();
+    bytesPerSample = format#getSampleSizeInBits() / 8;
+    bytes = new byte[nframes * channels * bytesPerSample];
+    bytesRead = stream#read(bytes);
+    n = bytesRead / bytesPerSample;
+    floats = new float[n];
+    decode { format } bytes floats n;
+    floats;
+   );
+
+read { format is ~AudioFormat, stream is ~AudioInputStream } n =
+   (floats = readInterleaved { format, stream } n;
+    channels = format#getChannels();
+    mat.deinterleaved channels (array floats); //!!! want to pass just floats
+   );
+
+readAllInterleaved { format is ~AudioFormat, stream is ~AudioInputStream } =
+   readInterleaved { format, stream } stream#getFrameLength();
+
+readAll { format is ~AudioFormat, stream is ~AudioInputStream } =
+   read { format, stream } stream#getFrameLength();
+
 {
-    openAudioFile,
-    read
+    open,
+    read,
+    readAll,
+    readInterleaved,
+    readAllInterleaved,
+    close
 }
 
--- a/matrix.yeti	Sun Dec 02 12:09:32 2012 +0000
+++ b/matrix.yeti	Thu Dec 06 22:19:29 2012 +0000
@@ -19,6 +19,8 @@
 
 height m = length m;
 
+dimensions m = { cols = width m, rows = height m };
+
 transposed m = array
    (map do n: array
        (map do a: a[n-1] done m)
@@ -26,5 +28,16 @@
 
 interleaved m = array(concat(transposed m));
 
-{ generateMatrix, constMatrix, randomMatrix, zeroMatrix, identityMatrix, interleaved, width, height, zeros, ones, transposed }
+deinterleaved rows v =
+    generateMatrix do row col:
+        v[rows * col + row]
+    done rows (length v / rows);
 
+{
+zeros, ones,
+generateMatrix, constMatrix, randomMatrix, zeroMatrix, identityMatrix,
+width, height, dimensions,
+transposed,
+interleaved, deinterleaved,
+}
+