Mercurial > hg > jslab
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; + } +}