/*
* SequenceAudioInputStream.java
*
* This file is part of jsresources.org
*/
/*
* Copyright (c) 1999 - 2001 by Matthias Pfisterer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
|<--- this code is formatted to fit into 80 columns --->|
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
public class SequenceAudioInputStream
extends AudioInputStream
{
private static final boolean DEBUG = true;
private List m_audioInputStreamList;
private int m_nCurrentStream;
public SequenceAudioInputStream(AudioFormat audioFormat, Collection audioInputStreams)
{
super(new ByteArrayInputStream(new byte[0]), audioFormat, AudioSystem.NOT_SPECIFIED);
m_audioInputStreamList = new ArrayList(audioInputStreams);
m_nCurrentStream = 0;
}
// TODO: remove
private boolean addAudioInputStream(AudioInputStream audioStream)
{
if (DEBUG)
{
out("SequenceAudioInputStream.addAudioInputStream(): called.");
}
// Contract.check(audioStream != null);
if (!getFormat().matches(audioStream.getFormat()))
{
if (DEBUG)
{
out("SequenceAudioInputStream.addAudioInputStream(): audio formats do not match, trying to convert.");
}
AudioInputStream asold = audioStream;
audioStream = AudioSystem.getAudioInputStream(getFormat(), asold);
if (audioStream == null)
{
out("### SequenceAudioInputStream.addAudioInputStream(): could not convert.");
return false;
}
if (DEBUG)
{
out(" converted");
}
}
// Contract.check(audioStream != null);
synchronized (m_audioInputStreamList)
{
m_audioInputStreamList.add(audioStream);
m_audioInputStreamList.notifyAll();
}
if (DEBUG)
{
out("SequenceAudioInputStream.addAudioInputStream(): enqueued " + audioStream);
}
return true;
}
private AudioInputStream getCurrentStream()
{
return (AudioInputStream) m_audioInputStreamList.get(m_nCurrentStream);
}
private boolean advanceStream()
{
m_nCurrentStream++;
boolean bAnotherStreamAvailable = (m_nCurrentStream < m_audioInputStreamList.size());
return bAnotherStreamAvailable;
}
public long getFrameLength()
{
long lLengthInFrames = 0;
Iterator streamIterator = m_audioInputStreamList.iterator();
while (streamIterator.hasNext())
{
AudioInputStream stream = (AudioInputStream) streamIterator.next();
long lLength = stream.getFrameLength();
if (lLength == AudioSystem.NOT_SPECIFIED)
{
return AudioSystem.NOT_SPECIFIED;
}
else
{
lLengthInFrames += lLength;
}
}
return lLengthInFrames;
}
public int read()
throws IOException
{
AudioInputStream stream = getCurrentStream();
int nByte = stream.read();
if (nByte == -1)
{
/*
The end of the current stream has been signaled.
We try to advance to the next stream.
*/
boolean bAnotherStreamAvailable = advanceStream();
if (bAnotherStreamAvailable)
{
/*
There is another stream. We recurse into this method
to read from it.
*/
return read();
}
else
{
/*
No more data. We signal EOF.
*/
return -1;
}
}
else
{
/*
The most common case: We return the byte.
*/
return nByte;
}
}
public int read(byte[] abData, int nOffset, int nLength)
throws IOException
{
AudioInputStream stream = getCurrentStream();
int nBytesRead = stream.read(abData, nOffset, nLength);
if (nBytesRead == -1)
{
/*
The end of the current stream has been signaled.
We try to advance to the next stream.
*/
boolean bAnotherStreamAvailable = advanceStream();
if (bAnotherStreamAvailable)
{
/*
There is another stream. We recurse into this method
to read from it.
*/
return read(abData, nOffset, nLength);
}
else
{
/*
No more data. We signal EOF.
*/
return -1;
}
}
else
{
/*
The most common case: We return the length.
*/
return nBytesRead;
}
}
public long skip(long lLength)
throws IOException
{
throw new IOException("skip() is not implemented in class SequenceInputStream. Mail if you need this feature.");
}
public int available()
throws IOException
{
return getCurrentStream().available();
}
public void close()
throws IOException
{
// TODO: should we close all streams in the list?
}
public void mark(int nReadLimit)
{
throw new RuntimeException("mark() is not implemented in class SequenceInputStream. Mail if you need this feature.");
}
public void reset()
throws IOException
{
throw new IOException("reset() is not implemented in class SequenceInputStream. Mail if you need this feature.");
}
public boolean markSupported()
{
return false;
}
private static void out(String strMessage)
{
System.out.println(strMessage);
}
}
/*** SequenceAudioInputStream.java ***/