
org.yestech.multimedia.video.mpeg4.audio.AudioDataInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yesmultimedia Show documentation
Show all versions of yesmultimedia Show documentation
Framework targeted a multimedia formats
The newest version!
/*
* Copyright LGPL3
* YES Technology Association
* http://yestech.org
*
* http://www.opensource.org/licenses/lgpl-3.0.html
*/
package org.yestech.multimedia.video.mpeg4.audio;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/**
* The AudioDataInputStream
realizes the 8khz mono ulaw audio stream
* which gets the data from connected by a pipe the mono or stereo 16 bit linear source audio stream.
* It also implements the control of the playback (start, pause/continue, stop), the mute on/off
* and the volume functionalitities.
*/
public final class AudioDataInputStream extends PipedInputStream {
/** Constant, the size of the piped buffer for audio samples. */
protected final static int PIPED_SIZE = 1048576; // 1000K
/** Constant, the zero value in the 8 bit ulaw format. */
public final static int ULAW_ZERO = 127;
/** Constant, the add-in bias for 16 bit samples. */
private final static int BIAS = 0x84;
/** Constant, the max value of the magnitude. */
private final static int CLIP = 32635;
/** The table that is used for look-up of the exponenta for a byte. */
private final static int[] exp_lut =
{0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
/** The number of channels in the source audio stream (1 - mono or 2 - stereo). */
private int channelCount;
/** The step between the samples in the source audio stream. */
private int sampleStep = (8000 << 16) / 44100;
/** The current sample position in the source audio stream. */
private int samplePosition = 0;
/** True, if the audio device plays the audio. */
private boolean playing = false;
/** The mute status of the audio device (equals true if no audio). */
private boolean mute = false;
/** The current volume of the audio device. */
private int volume = 100;
/** True, if the audio data stream is closed, false otherwise. */
private boolean closed = false;
/** The source audio stream in the pipe with samples in the 16 bit linear format. */
private PipedOutputStream source;
/** The reference to the Java1AudioDevice
audio device. */
private Java1AudioDevice audioDevice;
/** True, if any samples haven't been read from the audio data stream, false otherwise. */
private boolean firstLoop = true;
/**
* Constructs an AudioDataInputStream
object and inits it using
* the specified Java1AudioDevice
audio device and the source audio stream.
* @param audioDevice the Java1AudioDevice
audio device.
* @param audioDataOutputStream the source audio stream with samples in the 16 bit linear format.
* @throws IOException raises if there is an I/O error occurs.
*/
public AudioDataInputStream(Java1AudioDevice audioDevice, PipedOutputStream audioDataOutputStream) throws IOException {
super(audioDataOutputStream);
this.audioDevice = audioDevice;
this.source = audioDataOutputStream;
this.buffer = new byte[PIPED_SIZE];
}
/**
* Inits the piped stream (writes to the source audio stream and reads from the input audio data stream 1 byte).
* @throws IOException raises if there is an I/O error occurs.
*/
public void init_stream() throws IOException {
source.write(0);
super.read();
}
/**
* Reads the next audio sample in the 8 bit ulaw format of 8khz mono audio data stream.
* Implements the playback start, pause/continue, stop, the mute on/off and
* the volume functionalities.
* Converts the mono or stereo input audio stream from the 16 bit linear format
* into the 8khz mono format with 8 bit ulaw samples.
* @return the next audio sample in the 8 bit ulaw format, or -1 the audio data stream is closed.
* @throws IOException raises if there is an I/O error occurs.
*/
public int read() throws IOException {
int sample = 0;
int currentSamplePosition = samplePosition >> 16;
int sample_size = channelCount == 2 ? 4 : 2;
int samples_count = 0;
int samples_summa = 0;
try {
while(!playing && !closed) {
synchronized(audioDevice) {
audioDevice.wait();
}
}
} catch (InterruptedException ex) {
throw new InterruptedIOException(ex.getMessage());
}
int available = available();
while(currentSamplePosition == (samplePosition >> 16)) {
if(available < sample_size) {
return ULAW_ZERO;
}
sample = (short)(super.read() + (super.read() << 8));
if(channelCount == 2) {
sample = (sample + (short)(super.read() + (super.read() << 8))) >> 1;
}
available -= sample_size;
samples_count++;
samples_summa += sample;
samplePosition += sampleStep;
}
sample = samples_summa / samples_count;
if(closed) {
return -1;
}
if(mute) {
return ULAW_ZERO;
} else {
sample = sample * volume / 100;
return linear2ulaw(sample);
}
}
/**
* Reads up to len
audio samples in the 8 bit ulaw format
* into the buffer b
starting from the offset off
.
* @param b the buffer to store the readed audio samples.
* @param off the offset in the buffer to store the samples.
* @param len the number of samples to read.
* @return the number of samples which have been read or
* -1 if any samples haven't been read from the stream.
* @throws IOException raises if there is an I/O error occurs.
*/
public int read(byte[] b, int off, int len) throws IOException {
firstLoop = false;
for(int i = 0; i < len; i++) {
int sample = read();
if(sample == -1) {
if(i == 0) {
return -1;
} else {
return i;
}
}
b[i + off] = (byte)sample;
}
return len;
}
/*
** Source: http://www.speech.cs.cmu.edu/comp.speech/Section2/Q2.7.html
**
** This routine converts from linear to ulaw
**
** Craig Reese: IDA/Supercomputing Research Center
** Joe Campbell: Department of Defense
** 29 September 1989
**
** References:
** 1) CCITT Recommendation G.711 (very difficult to follow)
** 2) "A New Digital Technique for Implementation of Any
** Continuous PCM Companding Law," Villeret, Michel,
** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
** 1973, pg. 11.12-11.17
** 3) MIL-STD-188-113,"Interoperability and Performance Standards
** for Analog-to_Digital Conversion Techniques,"
** 17 February 1987
**
** Input: Signed 16 bit linear sample
** Output: 8 bit ulaw sample
*/
/*
* Constant, set to true if you want to turn on the trap as per the MIL-STD
* private final static boolean ZEROTRAP = true;
*/
/**
* Converts the audio sample from the signed 16 bit linear format to the 8 bit ulaw format.
* @param sample the signed 16 bit linear sample.
* @return the 8 bit ulaw sample.
*/
private int linear2ulaw(int sample) {
/* Get the sample into sign-magnitude. */
int sign = (sample >> 8) & 0x80; /* set aside the sign */
if (sign != 0) sample = -sample; /* get magnitude */
if (sample > CLIP) sample = CLIP; /* clip the magnitude */
/* Convert from 16 bit linear to ulaw. */
sample = sample + BIAS;
int exponent = exp_lut[(sample >> 7) & 0xFF];
int mantissa = (sample >> (exponent + 3)) & 0x0F;
int ulawbyte = (~(sign | (exponent << 4) | mantissa)) & 0xff;
/*
* if(ZEROTRAP) {
* if (ulawbyte <= 0) ulawbyte = 0x02; // optional CCITT trap
* }
*/
return ulawbyte;
}
/**
* Sets the playing status of the audio device (true, if the audio device plays the audio).
* @param playing the playing status to set.
*/
public void setPlaying(boolean playing) {
this.playing = playing;
}
/**
* Sets the mute state of the audio device.
* @param mute the mute state to set.
*/
public void setMute(boolean mute) {
this.mute = mute;
}
/**
* Sets the volume of the audio stream.
* @param volume the volume to set.
*/
public void setVolume(int volume) {
this.volume = volume;
}
/**
* Sets the number of channels of the input audio stream.
* @param channelCount the number of channels to set.
*/
public void setChannelCount(int channelCount) {
this.channelCount = channelCount;
}
/**
* Sets the sample frequency of the input audio stream.
* @param sampleFrequency the sample frequency to set.
*/
public void setSampleFrequency(int sampleFrequency) {
this.sampleStep = (8000 << 16) / sampleFrequency;
}
/**
* Closes the audio data stream.
*/
public void close() throws IOException {
closed = true;
synchronized(audioDevice) {
audioDevice.notifyAll();
}
super.close();
}
/**
* Returns true, if any samples haven't been read from the audio data stream.
*/
public boolean isFirstLoop() {
return firstLoop;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy