diff src/samer/audio/LineSink.java @ 0:bf79fb79ee13

Initial Mercurial check in.
author samer
date Tue, 17 Jan 2012 17:50:20 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/samer/audio/LineSink.java	Tue Jan 17 17:50:20 2012 +0000
@@ -0,0 +1,129 @@
+/*
+ *	LineSink.java
+ *
+ *	Copyright (c) 2000, Samer Abdallah, King's College London.
+ *	All rights reserved.
+ *
+ *	This software is provided AS iS and WITHOUT ANY WARRANTY;
+ *	without even the implied warranty of MERCHANTABILITY or
+ *	FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+package samer.audio;
+import  samer.core.*;
+import  samer.core.types.*;
+import  samer.tools.*;
+import  java.io.*;
+import  javax.sound.sampled.*;
+
+/**
+	An AudioSink that sends samples to a Java Sound SourceDataLine.
+	Audio format can be determined in several ways (see below).
+	<p> Object is a Viewable, and is called "lineout".
+	Reads property "scale" from current environment, but scale
+	can be adjusted afterwards.
+	@see samer.audio.AudioSink
+*/
+
+public class LineSink extends VLine implements AudioSink
+{
+	private SourceDataLine	line;
+	private AudioFormat	   fmt;
+	private int             bufsize=0;
+	private VDouble			scale;
+
+	/** Create LineSink reading from given TargetDataLine */
+	public LineSink(SourceDataLine l, AudioFormat f) throws Exception {
+		super("lineout"); 
+		line=l; fmt=f;
+		Shell.push(getNode());
+		scale=new VDouble("scale",1.0,0);
+		Shell.pop();
+	}
+
+	public DataLine getLine() { return line; }
+	public boolean isOpen() { return line.isOpen(); }
+	public void setBufferSize(int b) { bufsize=b; }
+
+	/**
+	 * Returns the object used to store the scale factor for conversion from
+	 * doubles/floats to shorts/bytes. This is multiplied by 128 for conversion
+	 * to 8 bit audio, or 32768 for conversion to 16 bit audio.
+	*/
+	public VDouble getScale() { return scale; }
+
+	public void dispose() { scale.dispose(); super.dispose(); }
+
+	/** Open the line using either the current format or the line's default format if
+	*	none has been set.
+	*/
+	public void openImpl() throws Exception {
+		if (bufsize==0) line.open(fmt); else line.open(fmt,bufsize);
+	}
+
+	public void closeImpl() throws Exception { line.close(); }
+
+	/** Commands are :"set scale". */
+	public void getCommands(Registry r) {
+		r.add("set scale").group();
+		super.getCommands(r);
+	}
+
+	public void execute(String cmd, Environment env) throws Exception {
+		if (cmd.equals("set scale")) { env.datum().get(scale); }
+		else super.execute(cmd,env);
+	}
+
+	public Task writer(final double dbuf[], final int off, final int len) {
+		return new Writer(2*len) {
+			public void write(double dbuf[], int off, int len) throws Exception {
+				Util.doubleToShort(dbuf,buf,off,len,scale.value);
+				super.write(2*len);
+			}
+			public void run() throws Exception {
+				super.run();	Util.doubleToShort(dbuf,buf,off,len,scale.value);
+			}
+		};
+	}
+
+	public Task writer(final float dbuf[], final int off, final int len) {
+		return new Writer(2*len) {
+			public void write(float dbuf[], int off, int len) throws Exception {
+				Util.floatToShort(dbuf,buf,off,len,(float)scale.value);
+				super.write(2*len);
+			}
+			public void run() throws Exception {
+				super.run();	Util.floatToShort(dbuf,buf,off,len,(float)scale.value);
+			}
+		};
+	}
+
+	protected class Writer implements Task {
+		byte buf[];
+		int		size;
+
+		public Writer(int bufsize) { size=bufsize; buf=new byte[size]; }
+
+		public void starting() { start(); }
+		public void stopping() { stop(); }
+		public void dispose() {}
+		public void run() throws Exception {
+			if (line.write(buf,0,size)<=0) throw new EOFException();
+			changed();
+		}
+
+		public void write(int size) throws Exception {
+			if (line.write(buf,0,size)<=0) throw new EOFException();
+			changed();
+		}
+	}
+
+	public static DataLine.Info lineInfo(AudioFormat fmt) {
+		return new DataLine.Info( SourceDataLine.class, fmt); 
+	}
+
+	public static DataLine.Info lineInfo(AudioFormat fmt, int bufsize) {
+		return new DataLine.Info( SourceDataLine.class, fmt, bufsize); 
+	}
+}
+