package uk.co.mmscomputing.sound.provider; import java.io.IOException; import java.util.Vector; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.LineUnavailableException; import uk.co.mmscomputing.concurrent.*; class Clip extends DataLine implements javax.sound.sampled.Clip,Runnable{ private Object[] chunks = null; private int curindex = 0; private Semaphore blocker = new Semaphore(0,true); private int loopstart=0,loopend=0,loops=0; public Clip(){ super(); } public void open()throws LineUnavailableException{ throw new IllegalArgumentException( getClass().getName()+".open() :\n\t." +"This method is not supported.[Hint:Need some data for a clip.]" ); } public void open(AudioFormat format)throws LineUnavailableException{ throw new IllegalArgumentException( getClass().getName()+".open(AudioFormat format) :\n\t." +"This method is not supported.[Hint:Need some data for a clip.]" ); } // following method not tested yet. public void open(AudioFormat format,byte[] b,int off,int len)throws LineUnavailableException{ if(!Mixer.format.matches(format)){ throw new IllegalArgumentException(getClass().getName()+".open(AudioFormat format,byte[] data,int offset,int bufferSize)\t\n"+ "Format 'format' does not match Mixer.format [\n\t"+Mixer.format+"\n\t]" ); } int bufSize;byte[] buf;Vector cv; cv=new Vector(); bufSize=getBufferSize(); int max=len/bufSize; for(int i=0;i<max;i++){ buf=new byte[bufSize]; System.arraycopy(b,off,buf,0,bufSize); cv.add(buf); off+=bufSize; } buf=new byte[bufSize]; System.arraycopy(b,off,buf,0,len%bufSize); cv.add(buf); super.open(); chunks=cv.toArray(); } public void open(AudioInputStream in)throws LineUnavailableException,IOException{ if(!Mixer.format.matches(in.getFormat())){ throw new IllegalArgumentException(getClass().getName()+".open(AudioInputStream in)\t\n"+ "Format of audio input stream does not match Mixer.format [\n\t"+Mixer.format+"\n\t]" ); } int count;byte[] buf;Vector cv; int bufSize=getBufferSize(); cv=new Vector(); try{ while(true){ buf=new byte[bufSize]; count=in.read(buf,0,buf.length); if(count==-1){break;} cv.add(buf); } super.open(); }catch(Exception e){ cv.add(new byte[bufSize]); e.printStackTrace(); } chunks=cv.toArray(); } public long getMicrosecondLength(){ double len=(getFrameLength()*1000000.0)/Mixer.format.getFrameRate(); return (long)len; } public void setMicrosecondPosition(long microseconds){ long framepos=(microseconds*getFrameLength())/getMicrosecondLength(); setFramePosition((int)framepos); } public int getFramePosition(){ return curindex*getBufferSize()/Mixer.format.getFrameSize(); } public void setFramePosition(int frames){ flush(); curindex=(frames*Mixer.format.getFrameSize())/getBufferSize(); } public int getFrameLength(){ return chunks.length*getBufferSize()/Mixer.format.getFrameSize(); } public void setLoopPoints(int start,int end){ loopstart=start;loopend=end; if(loopend==-1){loopend=chunks.length;} } public void loop(int count){ loops=count; } public void start(){ if(!isrunning){ new Thread(this).start();} if(!isactive){ super.start(); // activate blocker.release(); } } public void stop(){ setLoopPoints(0,0);loop(0); super.stop(); speaker.flush(this); } public void run(){ isrunning = true; curindex = 0; try{ while(isrunning){ if(!isactive){ blocker.acquire(); } if(curindex==(loopend/getBufferSize())){ if(loops==LOOP_CONTINUOUSLY){ setFramePosition(loopstart); }else if(loops>0){ loops--; setFramePosition(loopstart); }//else{} // run to end of clip } if(chunks.length<=curindex){ stop(); // isactive=false }else{ speaker.put(this,(byte[])chunks[curindex]); curindex++; } } }catch(Exception e){ e.printStackTrace(); } } } /* javax.sound.sampled.LineUnavailableException: Failed to allocate clip data: Requested buffer too large. */