Mercurial > hg > jslab
diff src/samer/audio/FileSource.java @ 1:5df24c91468d
Oh my what a mess.
author | samer |
---|---|
date | Fri, 05 Apr 2019 16:26:00 +0100 |
parents | bf79fb79ee13 |
children |
line wrap: on
line diff
--- a/src/samer/audio/FileSource.java Tue Jan 17 17:50:20 2012 +0000 +++ b/src/samer/audio/FileSource.java Fri Apr 05 16:26:00 2019 +0100 @@ -19,6 +19,7 @@ import javax.swing.*; import java.io.*; import java.util.*; +import java.nio.ByteBuffer; /** An AudioSource that read from multiple audio files. Can read any @@ -45,13 +46,13 @@ { List<File> list=null; ListIterator<File> it=null; - boolean loop; + boolean loop, buffered=true; int channelsToMix; VFile curFile; InputStream in=null; - AudioFormat format=null; + AudioFormat format=null, inFormat=null; byte[] byte_buf=null; - int chunk=0; + int chunk=0, bytesPerSample=0; /** * Construct a FileSource initialised with current file and loop initialised @@ -72,15 +73,26 @@ Shell.registerViewable(this); } + // AudioSource interface methods public void dispose() { close(); Shell.deregisterViewable(this); curFile.dispose(); } + public int getChannels() { return format.getChannels(); } + public float getRate() { return format.getFrameRate(); } + /** Returns current file */ public File getFile() { return curFile.getFile(); } - public void setTargetFormat(AudioFormat f) { format=f; } + public void setBuffering(boolean b) { buffered=b; } + + /** The actual format of the stream in. May not be same as target format. **/ + public AudioFormat getStreamFormat() { return inFormat; } + + /** The requested audio format. **/ + public AudioFormat getTargetFormat() { return format; } + public void setTargetFormat(AudioFormat f) { format=f; } /** If true then loop playlist, otherwise, an Exception will be thrown * when the end of the playlist is reached. If there is no playlist, then @@ -153,39 +165,47 @@ private synchronized void openCurrent() throws Exception { File file=curFile.getFile(); - Shell.trace("\nOpening audio file: "+file); + Shell.trace("\nFileSource:Opening audio file "+file); AudioInputStream s=AudioSystem.getAudioInputStream(file); - AudioFormat af=s.getFormat(); - long frames=file.length()/af.getFrameSize(); + AudioFormat fmt1, af=s.getFormat(); Shell.trace(" format: "+af); - Shell.trace(" duration: "+(long)(frames/af.getFrameRate())+" s"); // convert to target format if required if (format!=null) { if (!format.equals(af)) { Shell.trace(" converting to "+format); if (af.getChannels()>format.getChannels()) { + int frameSize = af.getChannels()*format.getSampleSizeInBits()/8; Shell.trace(" channels mix down required."); - AudioFormat fmt1 = new AudioFormat( format.getEncoding(), format.getSampleRate(), + fmt1 = new AudioFormat( format.getEncoding(), format.getSampleRate(), format.getSampleSizeInBits(), - af.getChannels(), format.getFrameSize(), format.getFrameRate(), format.isBigEndian()); + af.getChannels(), frameSize, format.getFrameRate(), format.isBigEndian()); channelsToMix = af.getChannels(); - s=convertFormat(s,af,fmt1); } else { channelsToMix = 0; - s=convertFormat(s,af,format); + fmt1=format; } + Shell.trace(" converting via "+fmt1); + s=convertFormat(s,af,fmt1); + inFormat = fmt1; + } else { + Shell.trace(" no formation conversion required"); + channelsToMix = 0; + inFormat = af; } + } else { + Shell.trace(" using stream native format"); + channelsToMix = 0; + inFormat = af; } + in=s; + if (buffered) in = new BufferedInputStream(in,64*1024); // If we have a reader task, then update the byte buffer if (chunk>0) setByteBuffer(); - - // Shell.trace("stream format: "+s.getFormat()); - in = new BufferedInputStream(s,16*1024); } /** Returns number of bytes available in current file */ @@ -194,33 +214,44 @@ /** Reopen current file, so that next read will be from head of file. */ public synchronized void reopen() throws Exception { close(); openCurrent(); } - private void setChunkSize(int s) { chunk=s; } + private void setBlockSize(int s) { chunk=s; } private void setByteBuffer() { - byte_buf = new byte[2*chunk*(channelsToMix>0 ? channelsToMix : 1)]; + bytesPerSample = 2*(channelsToMix>0 ? channelsToMix : 1); + byte_buf = new byte[chunk*bytesPerSample]; + } + + public int readInto(ByteBuffer buf, int offset, int len) throws IOException { + return in.read(buf.array(), offset, len); } /** Returns a Task which copies samples as doubles into the given * buffer between the given positions. */ public Task reader(final double [] dbuf, final int off, final int len) { - setChunkSize(len); + setBlockSize(len); if (in!=null) setByteBuffer(); return new AnonymousTask() { public void run() throws Exception { - int n = 0; + synchronized (FileSource.this) { + // loop until len samples copied into dbuf + int rem=len, pos=off; + while (rem>0) { + int bytesRead = in.read(byte_buf, 0, rem*bytesPerSample); + if (bytesRead > 0) { // append this chunk to output + int count=bytesRead/bytesPerSample; + if (channelsToMix>0) { + Util.shortToDoubleMixDown(byte_buf,dbuf,pos,count,channelsToMix); + } else { + Util.shortToDouble(byte_buf,dbuf,pos,count); + } + pos+=count; rem-=count; + } else if (it!=null) next(); // next file if there is one + else if (!loop) throw new EOFException(); // not looping and no more files + else reopen(); // back to first file - synchronized (FileSource.this) { - int blen = byte_buf.length; - while (n < blen) { - int count = in.read(byte_buf, n, blen - n); - if (count > 0) n+=count; - else if (it!=null) next(); - else if (!loop) throw new EOFException(); - else reopen(); + // if (rem>0) Shell.trace("Read "+bytesRead+" bytes, need "+rem+" more samples."); } } - if (channelsToMix>0) Util.shortToDoubleMixDown(byte_buf,dbuf,off,len,channelsToMix); - else Util.shortToDouble(byte_buf,dbuf,off,len); } }; } @@ -228,25 +259,29 @@ /** Returns a Task which copies samples as floats into the given * buffer between the given positions. */ public Task reader(final float [] dbuf, final int off, final int len) { - setChunkSize(len); + setBlockSize(len); if (in!=null) setByteBuffer(); return new AnonymousTask() { public synchronized void run() throws Exception { - int n = 0; - synchronized (FileSource.this) { - int blen = byte_buf.length; - while (n < blen) { - int count = in.read(byte_buf, n, blen - n); - if (count > 0) n+=count; - else if (it!=null) next(); + // loop until len samples copied into dbuf + int rem=len, pos=off; + while (rem>0) { + int bytesRead = in.read(byte_buf, 0, rem*bytesPerSample); + if (bytesRead > 0) { + int count=bytesRead/bytesPerSample; + if (channelsToMix>0) { + Util.shortToFloatMixDown(byte_buf,dbuf,pos,count,channelsToMix); + } else { + Util.shortToFloat(byte_buf,dbuf,pos,count); + } + pos+=count; rem-=count; + } else if (it!=null) next(); else if (!loop) throw new EOFException(); else reopen(); } } - if (channelsToMix>0) Util.shortToFloatMixDown(byte_buf,dbuf,off,len,channelsToMix); - else Util.shortToFloat(byte_buf,dbuf,off,len); } }; } @@ -318,26 +353,33 @@ private static AudioInputStream convertFormat(AudioInputStream sin, AudioFormat fin, AudioFormat fout) throws Exception { - if (fin==fout) return sin; + Shell.trace("\nconvertFormat:"); + Shell.trace(" | source: "+fin.toString()); + Shell.trace(" | target: "+fout.toString()); + + if (fin.equals(fout)) return sin; else if (fin.getEncoding()==AudioFormat.Encoding.PCM_SIGNED) { - try { return AudioSystem.getAudioInputStream(fout,sin); } + try { + Shell.trace(" | Trying direct (PCM) from "+fin.getEncoding().toString()); + return AudioSystem.getAudioInputStream(fout,sin); + } catch (IllegalArgumentException ex) { Shell.trace("Direct conversion failed"); } AudioFormat fint = new AudioFormat( // PCM fout.getSampleRate(), fout.getSampleSizeInBits(), fin.getChannels(), true, fout.isBigEndian()); - Shell.trace("Trying PCM conversion via "+fint.toString()); + Shell.trace(" | Trying PCM conversion via "+fint.toString()); return AudioSystem.getAudioInputStream(fout,AudioSystem.getAudioInputStream(fint,sin)); } else { // First, check for MP3 - if so, cannot convert number of channels if (fin.getChannels()==fout.getChannels() && fin.getSampleRate()==fout.getSampleRate()) { - Shell.trace("Trying direct decoding from "+fin.getEncoding().toString()); + Shell.trace(" | Trying decoding from "+fin.getEncoding().toString()); return AudioSystem.getAudioInputStream(fout,sin); } else { AudioFormat fint = new AudioFormat( fin.getSampleRate(), fout.getSampleSizeInBits(), fin.getChannels(), true, fout.isBigEndian()); - Shell.trace("Trying conversion via "+fint.toString()); + Shell.trace(" | Trying recursive via "+fint.toString()); return convertFormat(AudioSystem.getAudioInputStream(fint,sin),fint,fout); } }