/* * Copyright 2006, United States Government as represented by the Administrator * for the National Aeronautics and Space Administration. No copyright is * claimed in the United States under Title 17, U.S. Code. All Other Rights * Reserved. */ package gov.nasa.ial.mde.sound; import java.io.ByteArrayInputStream; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; /** * A class used to generate the audio as an audio input stream. * * @author Dr. Robert Shelton * @version 1.0 * @since 1.0 */ public class Generator extends AudioInputStream { private float amplitude; private float amplitudeFraction; /** * Constructs a <code>Generator</code> with the specified audio format and volum. * * @param f the audio format to use. * @param volume the volume to use. */ public Generator(AudioFormat f, float volume) { super(new ByteArrayInputStream( new byte[0]), new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, f.getSampleRate(), 16, 2, 4, f.getFrameRate(), f.isBigEndian()), AudioSystem.NOT_SPECIFIED); amplitudeFraction = amplitude = volume * (float)Math.pow(2.0, getFormat().getSampleSizeInBits() - 1.0); } // end Generator /** * Sets the volume level. * * @param v the volume level. */ public void setVolume(float v) { float f = (float)Math.max(0.0, Math.min(1.0, v)); amplitudeFraction = f * amplitude; } // end setVolume /** * Number of bytes available which is always <code>Integer.MAX_VALUE</code>. * * @return always <code>Integer.MAX_VALUE</code>. */ public int available() { return Integer.MAX_VALUE; } // end available /** * Always throws an IOException since we do not support this method for the * stream. * * @exception java.io.IOException always thrown. */ public int read() throws IOException { throw new IOException("Cannot use this method now"); } // end read /** * Reads the speificed number of items from the stream and places them into * the buffer at the specified offset. * * @param b the buffer to place the read items into. * @param off the offset with in the buffer to place the items. * @param len the number of items to read. * @return number of items read * @exception java.io.IOException is thrown if the length is not an integer * multiple of frame size. */ public int read(byte[] b, int off, int len) throws IOException { int fs = getFormat().getFrameSize(); if ((len % fs) != 0) { throw new IOException("Length must be an integer multiple of frame size"); } for (int i = 0; i < len; i += fs) { byte[] r = convert(nextFloat()); System.arraycopy(r, 0, b, i, fs); } // end for i return len; } // end read private final byte[] convert(float f) { int v = Math.round(f * amplitudeFraction); byte low = (byte) (v & 0xFF); byte high = (byte) ((v >>> 8) & 0xFF); byte[] r = { low, high, low, high }; return r; } // end convert /** * The next floating point value of the waveform. * * @return the next floating point value of the waveform. */ protected float nextFloat() { return 0f; } // end nextFloat } // end class Generator