Mercurial > hg > jslab
view src/samer/audio/StreamSource.java @ 5:b67a33c44de7
Remove some crap, etc
author | samer |
---|---|
date | Fri, 05 Apr 2019 21:34:25 +0100 |
parents | 15b93db27c04 |
children |
line wrap: on
line source
/* * StreamSource.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.core.util.*; import samer.tools.*; import javax.sound.sampled.*; import javax.swing.*; import java.io.*; import java.net.URL; import java.util.*; /** An AudioSource that read from an input stream. Can read any format for which the appropriate JavaSound plug-in is installed on your system, eg WAV, AU, MP3, OGG. The implementation of AudioSource.reader() returns a Task which gets samples from the audio files, going through the play list one by one. If the loop flag is true, then samples are returned indefinitely by looping through the playlist; otherwise, an EOFException is thrown if an attempt is made to read beyond the end of the last file. Properties read from current environment: <dl> <dt>current<dd>Current file (String) <dt>loop<dd>Loop playlist? (Boolean) [true] </dl> */ public class StreamSource implements AudioSource { int channelsToMix; AudioInputStream source; InputStream in=null; AudioFormat format=null; byte[] byte_buf=null; int chunk=0; /** * Construct a StreamSource initialised with current file and loop initialised * from the current Environment. No exception is thrown if the current file */ public StreamSource(AudioInputStream s) throws Exception { source=s; } public StreamSource(InputStream s) throws Exception { source=AudioSystem.getAudioInputStream(s); } public StreamSource(File file) throws Exception { source=AudioSystem.getAudioInputStream(file); } public StreamSource(URL url) throws Exception { source=AudioSystem.getAudioInputStream(url); } public void dispose() { close(); } /** Returns current file */ public void setTargetFormat(AudioFormat f) { format=f; } public AudioFormat getFormat() { return format; } public boolean isOpen() { return in!=null; } /** Closes current input stream */ public synchronized void close() { try { if (in!=null) { Shell.trace("Closing audio stream..."); in.close(); in=null; byte_buf=null; } } catch (IOException ex) {} } /** Opens the playlist starting with the first file. */ public synchronized void open() throws Exception { if (!isOpen()) openCurrent(); } /** Opens the current file. Next read will returns samples * from head of given file. If setFormat() was called previously, then * we will attempt to do format conversion. */ private synchronized void openCurrent() throws Exception { AudioInputStream s=source; AudioFormat fmt1, af=s.getFormat(); Shell.trace(" format: "+af); // convert to target format if required if (format!=null) { if (!format.equals(af)) { Shell.trace(" converting to "+format); if (af.getChannels()>format.getChannels()) { Shell.trace(" channels mix down required."); fmt1 = new AudioFormat( format.getEncoding(), format.getSampleRate(), format.getSampleSizeInBits(), af.getChannels(), format.getFrameSize(), format.getFrameRate(), format.isBigEndian()); channelsToMix = af.getChannels(); } else { channelsToMix = 0; fmt1=format; } s=convertFormat(s,af,fmt1); } } // 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,64*1024); } /** Returns number of bytes available in current file */ public int available() throws Exception { return in.available(); } public float getRate() { return source.getFormat().getFrameRate(); } public int getChannels() { return source.getFormat().getChannels(); } private void setChunkSize(int s) { chunk=s; } private void setByteBuffer() { byte_buf = new byte[2*chunk*(channelsToMix>0 ? channelsToMix : 1)]; } /** 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); if (in!=null) setByteBuffer(); return new AnonymousTask() { public void run() throws Exception { int n = 0; synchronized (StreamSource.this) { int blen = byte_buf.length; while (n < blen) { int count = in.read(byte_buf, n, blen - n); if (count > 0) n+=count; else throw new EOFException(); } } if (channelsToMix>0) Util.shortToDoubleMixDown(byte_buf,dbuf,off,len,channelsToMix); else Util.shortToDouble(byte_buf,dbuf,off,len); } }; } /** 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); if (in!=null) setByteBuffer(); return new AnonymousTask() { public synchronized void run() throws Exception { int n = 0; synchronized (StreamSource.this) { int blen = byte_buf.length; while (n < blen) { int count = in.read(byte_buf, n, blen - n); if (count > 0) n+=count; else throw new EOFException(); } } if (channelsToMix>0) Util.shortToFloatMixDown(byte_buf,dbuf,off,len,channelsToMix); else Util.shortToFloat(byte_buf,dbuf,off,len); } }; } private static AudioInputStream convertFormat(AudioInputStream sin, AudioFormat fin, AudioFormat fout) throws Exception { if (fin.equals(fout)) return sin; else if (fin.getEncoding()==AudioFormat.Encoding.PCM_SIGNED) { try { 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()); 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()); 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()); return convertFormat(AudioSystem.getAudioInputStream(fint,sin),fint,fout); } } } }