00001 package org.dronus.al;
00002
00003 import java.nio.ByteBuffer;
00004 import java.nio.ByteOrder;
00005 import java.nio.IntBuffer;
00006
00007 import org.hfbk.util.Sleeper;
00008 import org.hfbk.vis.Prefs;
00009 import org.lwjgl.openal.AL;
00010 import org.lwjgl.openal.AL10;
00011
00012 public abstract class ALAudioThread extends Thread {
00013
00014 static ByteBuffer silence;
00015 static{
00016 silence=ByteBuffer.allocateDirect(1024);
00017 silence.clear();
00018 silence.rewind();
00019 }
00020
00021 int actBuffer=0;
00022
00023
00024
00025 abstract protected ByteBuffer poll();
00026
00027 ByteBuffer toPlay;
00028
00029 int buffers[];
00030 public int source=-1;
00031 public boolean running=true, playing=true;
00032
00033 int samplingRate, format, bytes;
00034
00035 public ALAudioThread(int samplingRate, int sampleBits, int channels) {
00036 super("AudioThread");
00037 setDaemon(true);
00038
00039 this.samplingRate=samplingRate;
00040
00041 IntBuffer tmp=intBuf(new int[1]);
00042 AL10.alGenSources(tmp);
00043 source=tmp.get(0);
00044
00045
00046
00047
00048 if (sampleBits==16)
00049 if (channels==2){
00050 format=AL10.AL_FORMAT_STEREO16;
00051 bytes=4;
00052 }else{
00053 format=AL10.AL_FORMAT_MONO16;
00054 bytes=2;
00055 }
00056 else if (sampleBits==8)
00057 if (channels==2){
00058 format=AL10.AL_FORMAT_STEREO8;
00059 bytes=2;
00060 }else{
00061 format=AL10.AL_FORMAT_MONO8;
00062 bytes=1;
00063 }
00064 else throw new RuntimeException("invalid channels: "+channels+" @ "+sampleBits+" bit.");
00065
00066 IntBuffer buffer=intBuf(new int[2]);
00067 AL10.alGenBuffers(buffer);
00068 buffers=new int[2];
00069 buffer.get(buffers);
00070 for (int buf: buffers){
00071 AL10.alBufferData(buf, format, silence, samplingRate);
00072 }
00073 buffer.rewind();
00074 AL10.alSourceQueueBuffers(source, buffer);
00075
00076 toPlay=ByteBuffer.allocateDirect(100000);
00077
00078 }
00079
00080
00081
00082
00083
00084 public void run() {
00085
00086 while (running && AL.isCreated()) {
00087
00088 int state=AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE);
00089 if ( playing && state!= AL10.AL_PLAYING) AL10.alSourcePlay(source);
00090 else if (!playing && state== AL10.AL_PLAYING) AL10.alSourcePause(source);
00091 ByteBuffer polled;
00092
00093 int ready;
00094 synchronized(AL10.class) { ready=AL10.alGetSourcei(source, AL10.AL_BUFFERS_PROCESSED); }
00095 if (ready>0){
00096
00097 polled=poll();
00098
00099 if (polled==null) polled=silence;
00100
00101
00102 synchronized(AL10.class){
00103 IntBuffer lastBuffer=intBuf(new int[1]);
00104 AL10.alSourceUnqueueBuffers(source, lastBuffer);
00105 AL10.alBufferData(lastBuffer.get(0), format, polled, samplingRate);
00106 AL10.alSourceQueueBuffers(source, lastBuffer);
00107 }
00108
00109 }
00110
00111 Sleeper.sleep(1);
00112 }
00113
00114
00115 if(Prefs.current.debug) System.out.println("Audio finished.");
00116 synchronized(AL10.class){
00117 AL10.alSourceStop(source);
00118 AL10.alDeleteSources(intBuf(new int[]{source}));
00119 AL10.alDeleteBuffers(intBuf(buffers));
00120 }
00121 if(Prefs.current.debug) System.out.println("Audio down!");
00122 }
00123
00124 public void tick(int time){}
00125
00126 IntBuffer intBuf(int[] i){
00127 ByteBuffer bb= ByteBuffer.allocateDirect(4 * i.length);
00128 bb.order(ByteOrder.nativeOrder());
00129 IntBuffer ib=bb.asIntBuffer();
00130 ib.put(i);
00131 ib.flip();
00132 return ib;
00133 }
00134 }