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