All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yestech.multimedia.video.mpeg4.audio.AudioDataInputStream Maven / Gradle / Ivy

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