/* * SilenceAudioInputStream.java * * This file is part of jsresources.org */ /* * Copyright (c) 2003 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.InputStream; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; /** @author Matthias Pfisterer */ public class SilenceAudioInputStream extends AudioInputStream { // private static final boolean DEBUG = false; public SilenceAudioInputStream(AudioFormat audioFormat, long lLengthInMilliseconds) { super(new SilenceInputStream(audioFormat), audioFormat, calculateFrameLengthFromDuration(lLengthInMilliseconds, audioFormat.getFrameRate()) ); } private static long calculateFrameLengthFromDuration(long lLengthInMilliseconds, float fFrameRate) { return (long) (lLengthInMilliseconds * fFrameRate / 1000); } private static class SilenceInputStream extends InputStream { private byte[] m_abOneFrameBuffer; public SilenceInputStream(AudioFormat audioFormat) { m_abOneFrameBuffer = new byte[audioFormat.getFrameSize()]; if (audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) { /* We don't need to do anything here, since the elements of m_abOneFrameBuffer are already initialized to zero. */ } else if (audioFormat.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)) { int nSampleSizeInBits = audioFormat.getSampleSizeInBits(); int nSampleSizeInBytes = audioFormat.getFrameSize() / audioFormat.getChannels(); switch (nSampleSizeInBits) { case 8: m_abOneFrameBuffer[0] = (byte) 0x80; break; case 16: if (audioFormat.isBigEndian()) { m_abOneFrameBuffer[0] = (byte) 0x80; m_abOneFrameBuffer[1] = (byte) 0x00; } else { m_abOneFrameBuffer[0] = (byte) 0x00; m_abOneFrameBuffer[1] = (byte) 0x80; } break; case 24: if (audioFormat.isBigEndian()) { m_abOneFrameBuffer[0] = (byte) 0x80; m_abOneFrameBuffer[1] = (byte) 0x00; m_abOneFrameBuffer[2] = (byte) 0x00; } else { m_abOneFrameBuffer[0] = (byte) 0x00; m_abOneFrameBuffer[1] = (byte) 0x00; m_abOneFrameBuffer[2] = (byte) 0x80; } break; case 32: if (audioFormat.isBigEndian()) { m_abOneFrameBuffer[0] = (byte) 0x80; m_abOneFrameBuffer[1] = (byte) 0x00; m_abOneFrameBuffer[2] = (byte) 0x00; m_abOneFrameBuffer[3] = (byte) 0x00; } else { m_abOneFrameBuffer[0] = (byte) 0x00; m_abOneFrameBuffer[1] = (byte) 0x00; m_abOneFrameBuffer[2] = (byte) 0x00; m_abOneFrameBuffer[3] = (byte) 0x80; } break; default: throw new IllegalArgumentException("sample size not supported"); } /* Inside the switch statement above, the values have been set for the first channel. If there is more than one, we have to duplicate the values for the other channels. */ for (int i = 1; i < audioFormat.getChannels(); i++) { System.arraycopy(m_abOneFrameBuffer, 0, m_abOneFrameBuffer, i * nSampleSizeInBytes, nSampleSizeInBytes); } } else { throw new IllegalArgumentException("encoding is not PCM_SIGNED or PCM_UNSIGNED"); } } public int read() throws IOException { /* Here, we assum that this method is only called if the frame size is one. AudioInputStream should guarantee this. */ return m_abOneFrameBuffer[0]; } public int read(byte[] abBuffer, int nOffset, int nLength) { /* Here, we assume that nLength is a multiple of the frame size. AudioInputStream should guarantee this. */ int nFrameSize = m_abOneFrameBuffer.length; for (int nBufferPosition = 0; nBufferPosition < nLength; nBufferPosition += nFrameSize) { System.arraycopy(m_abOneFrameBuffer, 0, abBuffer, nOffset + nBufferPosition, nFrameSize); } return nLength; } /* We return the maximum of complete frames that fit into an int. */ public int available() { int nFrameSize = m_abOneFrameBuffer.length; return (Integer.MAX_VALUE / nFrameSize) * nFrameSize; } } private static void out(String strMessage) { System.out.println(strMessage); } } /*** SilenceAudioInputStream.java ***/