/*
* Copyright (c) 2007 - 2008 by Damien Di Fede <ddf@compartmental.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package ddf.minim;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.Mixer;
import org.tritonus.share.sampled.AudioUtils;
import ddf.minim.javasound.JSMinim;
import ddf.minim.spi.AudioOut;
import ddf.minim.spi.AudioRecording;
import ddf.minim.spi.AudioRecordingStream;
import ddf.minim.spi.AudioStream;
import ddf.minim.spi.MinimServiceProvider;
import ddf.minim.spi.SampleRecorder;
/**
* <p>
* The <code>Minim</code> class is the starting point for most everything
* you will do with this library. There are methods for obtaining objects for playing audio files:
* AudioSample and AudioPlayer. There are methods for obtaining an AudioRecorder,
* which is how you record audio to disk. There are methods for obtaining an AudioInput,
* which is how you can monitor the computer's line-in or microphone, depending on what the
* user has set as the record source. Finally there are methods for obtaining an AudioOutput,
* which is how you can play audio generated by your program, typically by connecting classes
* found in the ugens package.
* </p>
* <p>
* Minim keeps references to all of the resources that are
* returned from these various methods so that you don't have to worry about closing them.
* Instead, when your application ends you can simply call the stop method of your Minim instance.
* Processing users <em>do not</em> need to do this because Minim detects when a PApplet is passed
* to the contructor and registers for a notification of application shutdown.
* </p>
* <p>
* Minim requires an Object that can handle two important
* file system operations so that it doesn't have to worry about details of
* the current environment. These two methods are:
* </p>
* <pre>
* String sketchPath( String fileName )
* InputStream createInput( String fileName )
* </pre>
* <p>
* These are methods that are defined in Processing, which Minim was originally
* designed to cleanly interface with. The <code>sketchPath</code> method is
* expected to transform a filename into an absolute path and is used when
* attempting to create an AudioRecorder. The <code>createInput</code> method
* is used when loading files and is expected to take a filename, which is
* not necessarily an absolute path, and return an <code>InputStream</code>
* that can be used to read the file. For example, in Processing, the <code>createInput</code>
* method will search in the data folder, the sketch folder, handle URLs, and absolute paths.
* If you are using Minim outside of Processing, you can handle whatever cases are
* appropriate for your project.
* </p>
*
* @example Basics/PlayAFile
*
* @author Damien Di Fede
*/
public class Minim
{
/** Specifies that you want a MONO AudioInput or AudioOutput */
public static final int MONO = 1;
/** Specifies that you want a STEREO AudioInput or AudioOutput */
public static final int STEREO = 2;
public static final int LOOP_CONTINUOUSLY = -1;
/** The .wav file format. */
public static AudioFileFormat.Type WAV = AudioFileFormat.Type.WAVE;
/** The .aiff file format. */
public static AudioFileFormat.Type AIFF = AudioFileFormat.Type.AIFF;
/** The .aifc file format. */
public static AudioFileFormat.Type AIFC = AudioFileFormat.Type.AIFC;
/** The .au file format. */
public static AudioFileFormat.Type AU = AudioFileFormat.Type.AU;
/** The .snd file format. */
public static AudioFileFormat.Type SND = AudioFileFormat.Type.SND;
private static boolean DEBUG = false;
private MinimServiceProvider mimp = null;
// we keep track of all the resources we are asked to create
// so that when shutting down the library, users can simply call stop(),
// and don't have to call close() on all of the things they've created.
// in the event that they *do* call close() on resource we've created,
// it will be removed from this list.
private ArrayList<AudioSource> sources = new ArrayList<AudioSource>();
// and unfortunately we have to track stream separately
private ArrayList<AudioStream> streams = new ArrayList<AudioStream>();
/**
* Creates an instance of Minim.
* <p>
* Minim requires an Object that can handle two important
* file system operations so that it doesn't have to worry about details of
* the current environment. These two methods are:
* </p>
* <pre>
* String sketchPath( String fileName )
* InputStream createInput( String fileName )
* </pre>
* <p>
* These are methods that are defined in Processing, which Minim was originally
* designed to cleanly interface with. The <code>sketchPath</code> method is
* expected to transform a filename into an absolute path and is used when
* attempting to create an AudioRecorder. The <code>createInput</code> method
* is used when loading files and is expected to take a filename, which is
* not necessarily an absolute path, and return an <code>InputStream</code>
* that can be used to read the file. For example, in Processing, the <code>createInput</code>
* method will search in the data folder, the sketch folder, handle URLs, and absolute paths.
* If you are using Minim outside of Processing, you can handle whatever cases are
* appropriate for your project.
* </p>
*
* @param fileSystemHandler
* The Object that will be used for file operations.
* When using Processing, simply pass <strong>this</strong> to Minim's constructor.
*/
public Minim( Object fileSystemHandler )
{
this( new JSMinim(fileSystemHandler) );
// see if we're dealing with Processing and register for a dispose call if we are
Class<?> superClass = fileSystemHandler.getClass().getSuperclass();
if( superClass.getName() == "processing.core.PApplet" )
{
try
{
Method registerDispose = superClass.getMethod( "registerMethod", String.class, Object.class );
registerDispose.invoke( fileSystemHandler, "dispose", this );
}
catch ( SecurityException e )
{
e.printStackTrace();
}
catch ( NoSuchMethodException e )
{
e.printStackTrace();
}
catch ( IllegalArgumentException e )
{
e.printStackTrace();
}
catch ( IllegalAccessException e )
{
e.printStackTrace();
}
catch ( InvocationTargetException e )
{
e.printStackTrace();
}
}
}
/** @invisible
*
* Creates an instance of Minim that will use the provided implementation
* for audio.
*
* @param implementation
* the MinimServiceProvider that will be used for returning audio
* resources
*/
public Minim( MinimServiceProvider implementation )
{
mimp = implementation;
mimp.start();
}
/** @invisible
*
* Used internally to report error messages. These error messages will
* appear in the console area of the PDE if you are running a sketch from
* the PDE, otherwise they will appear in the Java Console.
*
* @param message
* the error message to report
*/
public static void error(String message)
{
System.out.println( "=== Minim Error ===" );
System.out.println( "=== " + message );
System.out.println();
}
/** @invisible
*
* Displays a debug message, but only if {@link #debugOn()} has been called.
* The message will be displayed in the console area of the PDE, if you are
* running your sketch from the PDE. Otherwise, it will be displayed in the
* Java Console.
*
* @param message
* the message to display
* @see #debugOn()
*/
public static void debug(String message)
{
if ( DEBUG )
{
String[] lines = message.split( "\n" );
System.out.println( "=== Minim Debug ===" );
for ( int i = 0; i < lines.length; i++ )
{
System.out.println( "=== " + lines[i] );
}
System.out.println();
}
}
/**
* Turns on debug messages.
*/
public void debugOn()
{
DEBUG = true;
if ( mimp != null )
{
mimp.debugOn();
}
}
/**
* Turns off debug messages.
*
*/
public void debugOff()
{
DEBUG = false;
if ( mimp != null )
{
mimp.debugOff();
}
}
/** @invisible
*
* Library callback used by Processing when a sketch is being shutdown.
* It is not necessary to call this directly. It simply calls stop().
*
*
*/
public void dispose()
{
stop();
}
/**
*
* Stops Minim and releases all audio resources.
* <p>
* If using Minim outside of Processing, you must call this to
* release all of the audio resources that Minim has generated.
* It will call close() on all of them for you.
*
*/
public void stop()
{
debug( "Stopping Minim..." );
// close all sources and release them
for( AudioSource s : sources )
{
// null the parent so the AudioSource doesn't try to call removeSource
s.parent = null;
s.close();
}
sources.clear();
for( AudioStream s : streams )
{
s.close();
}
// stop the implementation
mimp.stop();
}
void addSource( AudioSource s )
{
sources.add( s );
s.parent = this;
}
void removeSource( AudioSource s )
{
sources.remove( s );
}
/**
* When using the JavaSound implementation of Minim, this sets the JavaSound Mixer
* that will be used for obtaining input sources such as AudioInputs.
* THIS METHOD WILL BE REPLACED IN A FUTURE VERSION.
*
* @param mixer
* The Mixer we should try to acquire inputs from.
*/
@Deprecated
public void setInputMixer(Mixer mixer)
{
if ( mimp instanceof JSMinim )
{
( (JSMinim)mimp ).setInputMixer( mixer );
}
}
/**
* When using the JavaSound implementation of Minim, this sets the JavaSound Mixer
* that will be used for obtain output destinations such as those required by AudioOuput,
* AudioPlayer, AudioSample, and so forth.
* THIS METHOD WILL BE REPLACED IN A FUTURE VERSION.
*
* @param mixer
* The Mixer we should try to acquire outputs from.
*/
@Deprecated
public void setOutputMixer(Mixer mixer)
{
if ( mimp instanceof JSMinim )
{
( (JSMinim)mimp ).setOutputMixer( mixer );
}
}
/**
* Creates an AudioSample using the provided sample data and AudioFormat.
* When a buffer size is not provided, it defaults to 1024. The buffer size
* of a sample controls the size of the left, right, and mix AudioBuffer
* fields of the returned AudioSample.
*
* @shortdesc Creates an AudioSample using the provided sample data and AudioFormat.
*
* @param sampleData
* float[]: the single channel of sample data
* @param format
* the AudioFormat describing the sample data
*
* @return an AudioSample that can be triggered to make sound
*
* @example Advanced/CreateAudioSample
*
* @related AudioSample
*/
public AudioSample createSample(float[] sampleData, AudioFormat format)
{
return createSample( sampleData, format, 1024 );
}
/**
* Creates an AudioSample using the provided sample data and
* AudioFormat, with the desired output buffer size.
*
* @param sampleData
* float[]: the single channel of sample data
* @param format
* the AudioFormat describing the sample data
* @param bufferSize
* int: the output buffer size to use,
* which controls the size of the left, right, and mix AudioBuffer
* fields of the returned AudioSample.
*
* @return an AudioSample that can be triggered to make sound
*/
public AudioSample createSample( float[] sampleData, AudioFormat format, int bufferSize )
{
AudioSample sample = mimp.getAudioSample( sampleData, format, bufferSize );
addSource( sample );
return sample;
}
/**
* Creates an AudioSample using the provided left and right channel
* sample data with an output buffer size of 1024.
*
* @param leftSampleData
* float[]: the left channel of the sample data
* @param rightSampleData
* float[]: the right channel of the sample data
* @param format
* the AudioFormat describing the sample data
*
* @return an AudioSample that can be triggered to make sound
*/
public AudioSample createSample( float[] leftSampleData, float[] rightSampleData, AudioFormat format )
{
return createSample( leftSampleData, rightSampleData, format, 1024 );
}
/**
* Creates an AudioSample using the provided left and right channel
* sample data.
*
* @param leftSampleData
* float[]: the left channel of the sample data
* @param rightSampleData
* float[]: the right channel of the sample data
* @param format
* the AudioFormat describing the sample data
* @param bufferSize
* int: the output buffer size to use,
* which controls the size of the left, right, and mix AudioBuffer
* fields of the returned AudioSample.
*
* @return an AudioSample that can be triggered to make sound
*/
public AudioSample createSample(float[] leftSampleData, float[] rightSampleData, AudioFormat format, int bufferSize)
{
AudioSample sample = mimp.getAudioSample( leftSampleData, rightSampleData, format, bufferSize );
addSource( sample );
return sample;
}
/**
* Loads the requested file into an AudioSample.
* By default, the buffer size used is 1024.
*
* @shortdesc Loads the requested file into an AudioSample.
*
* @param filename
* the file or URL that you want to load
*
* @return an AudioSample that can be triggered to make sound
*
* @example Basics/TriggerASample
*
* @see #loadSample(String, int)
* @see AudioSample
* @related AudioSample
*/
public AudioSample loadSample(String filename)
{
return loadSample( filename, 1024 );
}
/**
* Loads the requested file into an AudioSample.
*
* @param filename
* the file or URL that you want to load
* @param bufferSize
* int: The sample buffer size you want.
* This controls the size of the left, right, and mix
* AudioBuffer fields of the returned AudioSample.
*
* @return an AudioSample that can be triggered to make sound
*/
public AudioSample loadSample(String filename, int bufferSize)
{
AudioSample sample = mimp.getAudioSample( filename, bufferSize );
addSource( sample );
return sample;
}
/** @invisible
* Loads the requested file into an {@link AudioSnippet}
*
* @param filename
* the file or URL you want to load
* @return an <code>AudioSnippet</code> of the requested file or URL
*/
@Deprecated
public AudioSnippet loadSnippet(String filename)
{
AudioRecording c = mimp.getAudioRecording( filename );
if ( c != null )
{
return new AudioSnippet( c );
}
else
{
Minim.error( "Couldn't load the file " + filename );
}
return null;
}
/**
* Loads the requested file into an AudioPlayer.
* The default buffer size is 1024 samples and the
* buffer size determines the size of the left, right,
* and mix AudioBuffer fields on the returned AudioPlayer.
*
* @shortdesc Loads the requested file into an AudioPlayer.
*
* @example Basics/PlayAFile
*
* @param filename
* the file or URL you want to load
* @return an <code>AudioPlayer</code> that plays the file
*
* @related AudioPlayer
*
* @see #loadFile(String, int)
*/
public AudioPlayer loadFile(String filename)
{
return loadFile( filename, 1024 );
}
/**
* Loads the requested file into an {@link AudioPlayer} with the request
* buffer size.
*
* @param filename
* the file or URL you want to load
* @param bufferSize
* int: the sample buffer size you want, which determines the
* size of the left, right, and mix AudioBuffer fields of the
* returned AudioPlayer.
*
* @return an <code>AudioPlayer</code> with a sample buffer of the requested
* size, or null if we were unable to load the file
*/
public AudioPlayer loadFile(String filename, int bufferSize)
{
AudioPlayer player = null;
AudioRecordingStream rec = mimp.getAudioRecordingStream( filename, bufferSize, false );
if ( rec != null )
{
AudioFormat format = rec.getFormat();
AudioOut out = mimp.getAudioOutput( format.getChannels(),
bufferSize,
format.getSampleRate(),
format.getSampleSizeInBits() );
if ( out != null )
{
player = new AudioPlayer( rec, out );
}
else
{
rec.close();
}
}
if ( player != null )
{
addSource( player );
}
else
{
error( "Couldn't load the file " + filename );
}
return player;
}
/**
* Loads the file into an AudioRecordingStream, which allows you to stream
* audio data from the file yourself. Note that doing this will not
* result in any sound coming out of your speakers, unless of course you
* send it there. You would primarily use this to perform offline-analysis
* of a file or for very custom sound streaming schemes.
*
* @shortdesc Loads the file into an AudioRecordingStream.
*
* @example Analysis/offlineAnalysis
*
* @param filename
* the file to load
* @param bufferSize
* int: the bufferSize to use, which controls how much
* of the streamed file is stored in memory at a time.
* @param inMemory
* boolean: whether or not the file should be cached in memory as it is read
*
* @return an AudioRecordingStream that you can use to read from the file.
*
*
*/
public AudioRecordingStream loadFileStream(String filename, int bufferSize, boolean inMemory)
{
AudioRecordingStream stream = mimp.getAudioRecordingStream( filename, bufferSize, inMemory );
streams.add( stream );
return stream;
}
/**
* Load the file into an AudioRecordingStream with a buffer size of 1024
* samples.
*
* @param filename
* the file to load
* @return an AudioRecordingStream that you can use to read from the file
*/
public AudioRecordingStream loadFileStream(String filename)
{
return loadFileStream(filename,1024,false);
}
/**
* Loads the requested file into a MultiChannelBuffer. The buffer's channel count
* and buffer size will be adjusted to match the file.
*
* @shortdesc Loads the requested file into a MultiChannelBuffer.
*
* @example Advanced/loadFileIntoBuffer
*
* @param filename
* the file to load
* @param outBuffer
* the MultiChannelBuffer to fill with the file's audio samples
*
* @return the sample rate of audio samples in outBuffer, or 0 if the load failed.
*
* @related MultiChannelBuffer
*/
public float loadFileIntoBuffer( String filename, MultiChannelBuffer outBuffer )
{
final int readBufferSize = 4096;
float sampleRate = 0;
AudioRecordingStream stream = mimp.getAudioRecordingStream( filename, readBufferSize, false );
if ( stream != null )
{
//stream.open();
stream.play();
sampleRate = stream.getFormat().getSampleRate();
final int channelCount = stream.getFormat().getChannels();
// for reading the file in, in chunks.
MultiChannelBuffer readBuffer = new MultiChannelBuffer( channelCount, readBufferSize );
// make sure the out buffer is the correct size and type.
outBuffer.setChannelCount( channelCount );
// how many samples to read total
long totalSampleCount = stream.getSampleFrameLength();
if ( totalSampleCount == -1 )
{
totalSampleCount = AudioUtils.millis2Frames( stream.getMillisecondLength(), stream.getFormat() );
}
debug( "Total sample count for " + filename + " is " + totalSampleCount );
outBuffer.setBufferSize( (int)totalSampleCount );
// now read in chunks.
long totalSamplesRead = 0;
while( totalSamplesRead < totalSampleCount )
{
// is the remainder smaller than our buffer?
if ( totalSampleCount - totalSamplesRead < readBufferSize )
{
readBuffer.setBufferSize( (int)(totalSampleCount - totalSamplesRead) );
}
int samplesRead = stream.read( readBuffer );
if ( samplesRead == 0 )
{
debug( "loadSampleIntoBuffer: got 0 samples read" );
break;
}
// copy data from one buffer to the other.
for(int i = 0; i < channelCount; ++i)
{
// a faster way to do this would be nice.
for(int s = 0; s < samplesRead; ++s)
{
outBuffer.setSample( i, (int)totalSamplesRead+s, readBuffer.getSample( i, s ) );
}
}
totalSamplesRead += samplesRead;
}
if ( totalSamplesRead != totalSampleCount )
{
outBuffer.setBufferSize( (int)totalSamplesRead );
}
debug("loadSampleIntoBuffer: final output buffer size is " + outBuffer.getBufferSize() );
stream.close();
}
else
{
debug("Unable to load an AudioRecordingStream for " + filename);
}
return sampleRate;
}
/**
* Creates an AudioRecorder that will use the provided Recordable object as its
* record source and that will save to the file name specified. Recordable
* classes in Minim include AudioOutput, AudioInput, AudioPlayer, and AudioSample.
* The format of the file will be inferred from the extension in the file name.
* If the extension is not a recognized file type, this will return null.
*
* @shortdesc Creates an AudioRecorder.
*
* @example Basics/RecordAudioOutput
*
* @param source
* the <code>Recordable</code> object you want to use as a record source
* @param fileName
* the name of the file to record to
*
* @return an <code>AudioRecorder</code> for the record source
*
* @related AudioRecorder
*/
public AudioRecorder createRecorder( Recordable source, String fileName )
{
return createRecorder( source, fileName, false );
}
/**
* Creates an AudioRecorder that will use the provided Recordable object as its
* record source and that will save to the file name specified. Recordable
* classes in Minim include AudioOutput, AudioInput, AudioPlayer, and AudioSample.
* The format of the file will be inferred from the extension in the file name.
* If the extension is not a recognized file type, this will return null. Be aware
* that if you choose buffered recording the call to AudioRecorder's save method
* will block until the entire buffer is written to disk.
* In the event that the buffer is very large, your app will noticeably hang.
*
* @shortdesc Creates an AudioRecorder.
*
* @example Basics/RecordAudioOutput
*
* @param source
* the <code>Recordable</code> object you want to use as a record source
* @param fileName
* the name of the file to record to
* @param buffered
* boolean: whether or not to use buffered recording
*
* @return an <code>AudioRecorder</code> for the record source
*
* @related AudioRecorder
* @invisible
*/
public AudioRecorder createRecorder(Recordable source, String fileName, boolean buffered)
{
SampleRecorder rec = mimp.getSampleRecorder( source, fileName, buffered );
if ( rec != null )
{
return new AudioRecorder( source, rec );
}
else
{
error( "Couldn't create an AudioRecorder for " + fileName + "." );
}
return null;
}
/**
* An AudioInput is used when you want to monitor the active audio input
* of the computer. On a laptop, for instance, this will typically be
* the built-in microphone. On a desktop it might be the line-in
* port on the soundcard. The default values are for a stereo input
* with a 1024 sample buffer (ie the size of left, right, and mix
* buffers), sample rate of 44100 and bit depth of 16. Generally
* speaking, you will not want to specify these things, but it's
* there if you need it.
*
* @shortdesc get an AudioInput that reads from the active audio input of the soundcard
*
* @return an AudioInput that reads from the active audio input of the soundcard
*
* @see #getLineIn(int, int, float, int)
* @related AudioInput
* @example Basics/MonitorInput
*/
public AudioInput getLineIn()
{
return getLineIn( STEREO );
}
/**
* Gets either a MONO or STEREO {@link AudioInput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @return an <code>AudioInput</code> with the requested type, a 1024 sample
* buffer, a sample rate of 44100 and a bit depth of 16
* @see #getLineIn(int, int, float, int)
*/
public AudioInput getLineIn(int type)
{
return getLineIn( type, 1024, 44100, 16 );
}
/**
* Gets an {@link AudioInput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the <code>AudioInput</code>'s sample buffer
* to be (ie the size of left, right, and mix buffers)
* @return an <code>AudioInput</code> with the requested attributes, a
* sample rate of 44100 and a bit depth of 16
* @see #getLineIn(int, int, float, int)
*/
public AudioInput getLineIn(int type, int bufferSize)
{
return getLineIn( type, bufferSize, 44100, 16 );
}
/**
* Gets an {@link AudioInput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the <code>AudioInput</code>'s sample buffer
* to be (ie the size of left, right, and mix buffers)
* @param sampleRate
* float: the desired sample rate in Hertz (typically 44100)
* @return an <code>AudioInput</code> with the requested attributes and a
* bit depth of 16
* @see #getLineIn(int, int, float, int)
*/
public AudioInput getLineIn(int type, int bufferSize, float sampleRate)
{
return getLineIn( type, bufferSize, sampleRate, 16 );
}
/**
* Gets an {@link AudioInput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the <code>AudioInput</code>'s sample buffer
* to be (ie the size of left, right, and mix buffers)
* @param sampleRate
* float: the desired sample rate in Hertz (typically 44100)
* @param bitDepth
* int: the desired bit depth (typically 16)
* @return an <code>AudioInput</code> with the requested attributes
*/
public AudioInput getLineIn(int type, int bufferSize, float sampleRate, int bitDepth)
{
AudioInput input = null;
AudioStream stream = mimp.getAudioInput( type, bufferSize, sampleRate, bitDepth );
if ( stream != null )
{
AudioOut out = mimp.getAudioOutput( type, bufferSize, sampleRate, bitDepth );
// couldn't get an output, the system might not have one available
// so in that case we provide a basic audio out to the input
// that will pull samples from it and so forth
if ( out == null )
{
out = new BasicAudioOut(stream.getFormat(), bufferSize);
}
input = new AudioInput( stream, out );
}
if ( input != null )
{
addSource( input );
}
else
{
error( "Minim.getLineIn: attempt failed, could not secure an AudioInput." );
}
return input;
}
/**
* Get the input as an AudioStream that you can read from yourself, rather
* than wrapped in an AudioInput that does that work for you.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the AudioStream's interal
* buffer to be.
* @param sampleRate
* float: the desired sample rate in Hertz (typically 44100)
* @param bitDepth
* int: the desired bit depth (typically 16)
* @return an AudioStream that reads from the input source of the soundcard.
*/
public AudioStream getInputStream(int type, int bufferSize, float sampleRate, int bitDepth)
{
AudioStream stream = mimp.getAudioInput( type, bufferSize, sampleRate, bitDepth );
streams.add( stream );
return stream;
}
/**
* An AudioOutput is used to generate sound in real-time and output it to
* the soundcard. Usually, the sound generated by an AudioOutput will be
* heard through the speakers or headphones attached to a computer. The
* default parameters for an AudioOutput are STEREO sound, a 1024 sample
* buffer (ie the size of the left, right, and mix buffers), a sample
* rate of 44100, and a bit depth of 16. To actually generate sound
* with an AudioOutput you need to patch at least one sound generating
* UGen to it, such as an Oscil.
* <p>
* Using setOutputMixer you can also create AudioOutputs that
* send sound to specific output channels of a soundcard.
*
* @example Basics/SynthesizeSound
*
* @shortdesc get an AudioOutput that can be used to generate audio
*
* @return an AudioOutput that can be used to generate audio
* @see #getLineOut(int, int, float, int)
* @related AudioOutput
* @related UGen
*/
public AudioOutput getLineOut()
{
return getLineOut( STEREO );
}
/**
* Gets an {@link AudioOutput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @return an <code>AudioOutput</code> with the requested type, a 1024
* sample buffer, a sample rate of 44100 and a bit depth of 16
* @see #getLineOut(int, int, float, int)
*/
public AudioOutput getLineOut(int type)
{
return getLineOut( type, 1024, 44100, 16 );
}
/**
* Gets an {@link AudioOutput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the AudioOutput's sample buffer
* to be (ie the size of the left, right, and mix buffers)
* @return an <code>AudioOutput</code> with the requested attributes, a
* sample rate of 44100 and a bit depth of 16
* @see #getLineOut(int, int, float, int)
*/
public AudioOutput getLineOut(int type, int bufferSize)
{
return getLineOut( type, bufferSize, 44100, 16 );
}
/**
* Gets an {@link AudioOutput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the AudioOutput's sample buffer
* to be (ie the size of the left, right, and mix buffers)
* @param sampleRate
* float: the desired sample rate in Hertz (typically 44100)
* @return an <code>AudioOutput</code> with the requested attributes and a
* bit depth of 16
* @see #getLineOut(int, int, float, int)
*/
public AudioOutput getLineOut(int type, int bufferSize, float sampleRate)
{
return getLineOut( type, bufferSize, sampleRate, 16 );
}
/**
* Gets an {@link AudioOutput}.
*
* @param type
* Minim.MONO or Minim.STEREO
* @param bufferSize
* int: how long you want the AudioOutput's sample buffer
* to be (ie the size of the left, right, and mix buffers)
* @param sampleRate
* float: the desired sample rate in Hertz (typically 44100)
* @param bitDepth
* int: the desired bit depth (typically 16)
* @return an <code>AudioOutput</code> with the requested attributes
*/
public AudioOutput getLineOut(int type, int bufferSize, float sampleRate, int bitDepth)
{
AudioOut out = mimp.getAudioOutput( type, bufferSize, sampleRate, bitDepth );
if ( out != null )
{
AudioOutput output = new AudioOutput( out );
addSource( output );
return output;
}
error( "Minim.getLineOut: attempt failed, could not secure a LineOut." );
return null;
}
}