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

org.refcodes.audio.LineOutSoundSampleWriter Maven / Gradle / Ivy

Go to download

Artifact providing audio provessing functionality such as generating sine waves or writing raw audio samples to WAV files.

The newest version!
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.audio;

import java.io.IOException;

import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

import org.refcodes.numerical.NumericalUtility;

/**
 * The {@link LineOutSoundSampleWriter} provides means to write sound samples to
 * a line-out device.
 */
public class LineOutSoundSampleWriter extends AbstractLineOutSampleWriter implements SoundSampleWriter {

	// /////////////////////////////////////////////////////////////////////////
	// VARIABLES:
	// /////////////////////////////////////////////////////////////////////////

	private final SoundSampleBuilder _soundSample = new SoundSampleBuilderImpl( 0, SamplingRate.AUDIO_CD.getSamplesPerSecond() );
	private SourceDataLine _lineOut = null;

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * {@inheritDoc}
	 */
	@Override
	public LineOutSoundSampleWriter withBitsPerSample( BitsPerSample aBitsPerSample ) {
		setBitsPerSample( aBitsPerSample );
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void writeNext( double... aSampleData ) throws IOException {
		if ( aSampleData == null || aSampleData.length == 0 ) {
			throw new IllegalArgumentException( "You must provide at least one sample value, bit you provided " + ( aSampleData == null ? "" : " an empty array" ) + "!" );
		}
		_soundSample.setSampleData( aSampleData );
		_soundSample.updateTimeStamp();
		writeNext( _soundSample );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void writeNext( SoundSample aSample ) throws IOException {

		if ( aSample != _soundSample ) {
			if ( aSample.getIndex() != -1 ) {
				_soundSample.setIndex( aSample.getIndex() );
			}
			if ( aSample.getSamplingRate() != -1 ) {
				_soundSample.setSamplingRate( aSample.getSamplingRate() );
			}
			if ( aSample.getTimeStamp() != -1 ) {
				_soundSample.setTimeStamp( aSample.getTimeStamp() );
			}
			else {
				_soundSample.updateTimeStamp();
			}
			_soundSample.setSampleData( aSample.getSampleData() );
		}
		byte[] eBytes;
		long eValue;
		for ( int i = 0; i < _soundSample.getChannelCount(); i++ ) {
			eValue = toWavSample( _soundSample.getSampleData()[i] );
			eBytes = NumericalUtility.toBigEndianBytes( eValue, _bitsPerSample.getByteCount() );
			try {
				final SourceDataLine theLineOut = getLineOut();
				// theLineOut.drain();
				while ( theLineOut.getBufferSize() < eBytes.length ) {
					try {
						Thread.sleep( 10 );
					}
					catch ( InterruptedException ignore ) {}
				}
				theLineOut.write( eBytes, 0, eBytes.length );
			}
			catch ( LineUnavailableException e ) {
				throw new IOException( "The audio-out line" + ( _lineOut != null ? " <" + _lineOut.toString() + ">" : "" ) + " is unavailable!", e );
			}
		}
		_soundSample.increaseIndex();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getSamplingRate() {
		return _soundSample.getSamplingRate();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setSamplingRate( int aSamplingRate ) {
		if ( aSamplingRate != -1 && aSamplingRate != _soundSample.getSamplingRate() ) {
			_soundSample.setSamplingRate( aSamplingRate );
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public LineOutSoundSampleWriter withSamplingRate( int aSamplingRate ) {
		setSamplingRate( aSamplingRate );
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void close() throws IOException {
		if ( _lineOut != null ) {
			_lineOut.stop();
			_lineOut.close();
		}
	}

	// /////////////////////////////////////////////////////////////////////////
	// HELPER:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Produces a line-out {@link SourceDataLine} instance for writing samples
	 * to.
	 * 
	 * @return The {@link SourceDataLine} upon success.
	 * 
	 * @throws LineUnavailableException thrown in case the audio-line cannot be
	 *         acquired.
	 */
	protected SourceDataLine getLineOut() throws LineUnavailableException {
		if ( _lineOut == null ) {
			synchronized ( this ) {
				if ( _lineOut == null ) {
					_lineOut = toLineOut( _soundSample, _bitsPerSample );
				}
			}
		}
		return _lineOut;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy