org.yestech.multimedia.video.mpeg4.audio.Java2AudioDevice Maven / Gradle / Ivy
/*
* 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.InterruptedIOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.BooleanControl;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
/**
* The Java2AudioDevice
class realizes the sound device
* (implements the AudioDevice
interface) through Java2 Sound API.
*/
public final class Java2AudioDevice implements AudioDevice {
/** Constant, the size of the inner buffer with audio samples. */
public final int BUFFER_SIZE = 102400; // 100K
/** The audio line to output the audio data. */
private SourceDataLine sourceDataLine = null;
/** The current volume of the player. */
private int volume = 100;
/** 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;
/** True, if the audio device is opened. */
private boolean opened = false;
/**
* Constructs an Java2AudioDevice
object
* and checks if a free audio channel is exist.
* @throws Exception raises if there is an error occurs
* (in most cases if no free audio channels have been found).
*/
public Java2AudioDevice() throws Exception {
super();
SourceDataLine sourceDataLine = getSourceDataLine(new AudioFormat(44100, 16, 2, true, false));
sourceDataLine.open();
sourceDataLine.close();
}
/**
* Gets an available audio channel (SourceDataLine
) for specified audio stream's format.
* @param format the format of the audio stream.
* @return the available audio channel.
* @throws LineUnavailableException raises if no available audio channels
* have been found for the specified format.
*/
private SourceDataLine getSourceDataLine(AudioFormat format) throws LineUnavailableException {
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
if(!AudioSystem.isLineSupported(info)) {
throw new LineUnavailableException ("Unable to find the Java 2 audio channel");
}
return (SourceDataLine)AudioSystem.getLine(info);
}
/**
* Starts the playback of the audio stream.
*/
public void play() {
playing = true;
if(sourceDataLine != null) {
sourceDataLine.start();
}
synchronized(this) {
notifyAll();
}
}
/**
* Opens the output audio channel and initializes it with the specified sample frequency
* and the number of channels of the audio stream.
* @param sampleFrequency the sample frequency of the audio stream.
* @param channelCount the number of channels of the audio stream.
*/
public void open(int sampleFrequency, int channelCount) {
try {
if(sourceDataLine == null) {
AudioFormat format = new AudioFormat(sampleFrequency, 16, channelCount, true, false);
sourceDataLine = getSourceDataLine(format);
sourceDataLine.open(format, BUFFER_SIZE);
opened = true;
setMute(mute);
setVolume(volume);
if(playing) {
sourceDataLine.start();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Writes the next portion of audio samples into the audio device.
* @param buffer the array with the audio samples' data.
* @param size the size of the audio samples' data.
* @throws InterruptedIOException raises if the current thread has been interrupted.
*/
public void write(byte[] buffer, int size) throws InterruptedIOException {
try {
sourceDataLine.write(buffer, 0, size);
synchronized(this) {
while(playing == false) {
wait();
}
}
} catch (InterruptedException ex) {
throw new InterruptedIOException(ex.getMessage());
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Pauses the playback of the audio stream.
*/
public void pause() {
playing = false;
if(sourceDataLine != null) {
sourceDataLine.stop();
}
}
/**
* Closes the audio device.
*/
public void close() {
if(sourceDataLine != null) {
sourceDataLine.close();
sourceDataLine = null;
opened = false;
}
}
/**
* Sets the mute state of the audio device.
* @param mute the mute state to set.
*/
public void setMute(boolean mute) {
this.mute = mute;
if(sourceDataLine != null) {
BooleanControl muteCtrl = (BooleanControl)sourceDataLine.getControl(BooleanControl.Type.MUTE);
muteCtrl.setValue(mute);
if(!mute) {
setVolume(volume);
}
}
}
/**
* Sets the volume of the audio stream.
* @param volume the volume to set.
*/
public void setVolume(int volume){
this.volume = volume;
if((sourceDataLine != null) && !mute) {
FloatControl volumeCtrl = (FloatControl)sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
float GainDb = (float)(20.d * Math.log(volume == 0 ? Double.MIN_VALUE: ((double)volume / 100.d)) / Math.log(10));
volumeCtrl.setValue(GainDb);
}
}
/**
* Returns true, if the audio device is opened, false otherwise.
*/
public boolean isOpened() {
return opened;
}
/**
* Returns true, if the audio device is ready to play the audio stream, false otherwise.
*/
public boolean isReady() {
return opened;
}
}