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

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;
	}

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy