diff src/samer/audio/FileSink.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/FileSink.java	Tue Jan 17 17:50:20 2012 +0000
@@ -0,0 +1,150 @@
+/*
+ *	FileSink.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.core.util.*;
+import  samer.tools.*;
+import  javax.sound.sampled.*;
+import  java.io.*;
+
+import  org.tritonus.share.sampled.AudioSystemShadow;
+import  org.tritonus.share.sampled.file.AudioOutputStream;
+
+/**
+	An AudioSink that writes to a wav file.
+	Viewable name: "wavewriter"<br>
+	Properties read from current environment:
+	<dl>
+	<dt>filesink.current
+		<dd>Current file (String)
+	<dt>filesink.scale
+		<dd>scale factor for converting floats/doubles (Double)
+	</dl>
+*/
+
+public class FileSink extends Viewable implements AudioSink, Agent
+{
+	VFile					file;
+	AudioOutputStream	out=null;
+	AudioFormat			format;
+	VDouble				scale;
+
+	public FileSink(String filename, AudioFormat fmt) throws Exception {
+		this(fmt); file.setFile(new File(filename)); 
+	}
+
+	public FileSink(AudioFormat fmt)
+	{
+		super("filessink");
+
+		Shell.push(node);
+		file=new VFile("file","",0);
+		scale=new VDouble("scale",1.0,0);
+		Shell.push("audio");
+		format=fmt;
+		Shell.pop();
+		Shell.pop();
+
+		setAgent(this);
+		Shell.registerViewable(this);
+	}
+
+	public void dispose() {
+		close();
+		Shell.deregisterViewable(this);
+		file.dispose();
+	}
+
+	public VDouble getScale() { return scale; }
+	public void setFormat(AudioFormat f) { format=f; }
+
+	public boolean isOpen() { return out!=null; }
+	public void open() throws Exception { open(file.getFile()); }
+	public synchronized  void open(File file) throws Exception
+	{
+		Shell.trace("wave writer opening "+file+" as "+format);
+
+		out=AudioSystemShadow.getAudioOutputStream(
+			AudioFileFormat.Type.WAVE,format,AudioSystem.NOT_SPECIFIED,
+				new BufferedOutputStream(
+					new FileOutputStream(file)));
+		this.file.setFile(file);
+	}
+
+	public synchronized void close() {
+		try { if (out!=null) out.close(); out=null; }
+		catch (IOException ex) { Shell.trace("*** Error closing: "+ex); }
+	}
+
+	public Task writer(final double [] dbuf, final int off, final int len) {
+		return new AnonymousTask() {
+			byte [] bbuf = new byte[2*len];
+
+			public void write(double dbuf[], int off, int len) throws Exception {
+				synchronized (FileSink.this) {
+					Util.doubleToShort(dbuf,bbuf,off,len,scale.value);
+					writeBytes(bbuf, 2*len);
+				}
+			}
+			public void run() throws Exception {
+				synchronized (FileSink.this) {
+					Util.doubleToShort(dbuf,bbuf,off,len,scale.value);
+					writeBytes(bbuf, bbuf.length);
+				}
+			}
+		};
+	}
+
+	public Task writer(final float [] dbuf, final int off, final int len) {
+		return new AnonymousTask() {
+			byte [] bbuf = new byte[2*len];
+
+			public void write(float dbuf[], int off, int len) throws Exception {
+				synchronized (FileSink.this) {
+					Util.floatToShort(dbuf,bbuf,off,len,(float)scale.value);
+					writeBytes(bbuf, 2*len);
+				}
+			}
+			public void run() throws Exception {
+				synchronized (FileSink.this) {
+					Util.floatToShort(dbuf,bbuf,off,len,(float)scale.value);
+					writeBytes(bbuf, bbuf.length);
+				}
+			}
+		};
+	}
+
+	private void writeBytes(byte [] buf,int len) throws Exception {
+		int count = out.write(buf, 0, len);
+		for (int n=count; n<len; n+=count) {
+			count = out.write(buf, n, len - n);
+			if (count<=0) throw new Exception("Write failed");
+		}
+	}
+
+	public void getCommands(Agent.Registry r) { r.add("open").add("close").add("set scale"); }
+	public void execute(String cmd, Environment env) throws Exception {
+		if (cmd.equals("open")) {close(); open(); }
+		else if (cmd.equals("close")) close();
+		else if (cmd.equals("set scale")) { env.datum().get(scale); }
+	}
+
+	// Viewable
+	public Viewer getViewer() {
+		DefaultViewer vwr=new DefaultViewer(this);
+		vwr.add(file);
+		vwr.add(Shell.createButtonsFor(this));
+		return vwr;
+	}
+}