samer@0: /* samer@0: * AudioSink.java samer@0: * samer@0: * Copyright (c) 2000, Samer Abdallah, King's College London. samer@0: * All rights reserved. samer@0: * samer@0: * This software is provided AS iS and WITHOUT ANY WARRANTY; samer@0: * without even the implied warranty of MERCHANTABILITY or samer@0: * FITNESS FOR A PARTICULAR PURPOSE. samer@0: */ samer@0: samer@46: package ishara.audio; samer@0: import javax.sound.sampled.AudioFormat; samer@0: samer@0: /** samer@0: General interface for objects that accept a stream of samer@0: samples. samer@0: */ samer@0: samer@0: public abstract class AudioSink samer@0: { samer@0: AudioFormat format; samer@0: double scale; samer@0: samer@0: public AudioSink(AudioFormat f) { format=f; } samer@0: public AudioFormat getFormat() { return format; } samer@0: samer@0: public double getScale() { return scale; } samer@0: public void setScale(double s) { scale=s; } samer@0: samer@0: public abstract void dispose(); samer@0: public abstract void start(); samer@0: public abstract void stop(); samer@0: public abstract int bwrite(byte [] bbuf, int offs, int len) throws Exception; samer@0: samer@0: /** Return a task which takes samples from the given buffer samer@0: * The idea is that the audio sink can choose the right samer@0: * kind of writer depending on the format of the audio stream, samer@0: * and then handle any conversions automatically. samer@0: * Should return the number of samples NOT written. samer@0: */ samer@0: samer@0: public Writer writer(int len) { samer@0: return new Writer(len,format.getSampleSizeInBits()/8); samer@0: } samer@0: samer@0: public class Writer { samer@0: byte[] bbuf; samer@0: int bps; samer@0: Converter conv; samer@0: samer@0: public Writer(int len, int bps) { samer@0: this.bps=bps; samer@0: bbuf=new byte[len*bps]; samer@0: conv=getConverter(bbuf,bps); samer@0: } samer@0: samer@0: public int write(double dbuf[]) throws Exception { return write(dbuf,0,dbuf.length); } samer@0: public int write(double dbuf[], int off, int len) throws Exception { samer@0: conv.convert(dbuf,off,len); samer@0: int rem=len*bps, pos=0; samer@0: while (rem>0) { samer@0: int count = bwrite(bbuf, pos, rem); samer@0: if (count<=0) { return rem; } samer@0: rem -= count; pos += count; samer@0: } samer@0: return 0; samer@0: } samer@0: } samer@0: samer@0: private interface Converter { public void convert(double [] dbuf, int offset, int count); } samer@0: private Converter getConverter(final byte [] b,final int bps) { samer@0: switch (bps) { samer@0: case 1: return new Converter() { public void convert(double[] d,int i, int n) { Util.doubleToByte(d,b,i,n,scale); } }; samer@0: case 2: return new Converter() { public void convert(double[] d,int i, int n) { Util.doubleToShort(d,b,i,n,scale); } }; samer@0: case 3: return new Converter() { public void convert(double[] d,int i, int n) { Util.doubleToMedium(d,b,i,n,scale); } }; samer@0: case 4: return new Converter() { public void convert(double[] d,int i, int n) { Util.doubleToInt(d,b,i,n,scale); } }; samer@0: } samer@0: throw new Error("Unrecognised sample format"); samer@0: } samer@0: samer@0: protected static void print(String msg) { System.out.println(msg); } samer@0: } samer@0: