ptolemy.media.javasound
Class LiveSound

java.lang.Object
  extended by ptolemy.media.javasound.LiveSound

public class LiveSound
extends java.lang.Object

This class supports live capture and playback of audio samples. For audio capture, audio samples are captured from the audio input port of the computer. The audio input port is typically associated with the line-in port, microphone-in port, or cdrom audio-in port. For audio playback, audio samples are written to the audio output port. The audio output port is typically associated with the headphones jack or the internal speaker of the computer.

Format of audio samples

In this class, audio samples are double-valued and have a valid range of [-1.0, 1.0]. Thus when this class is used for audio capture, the returned samples will all range in value from -1.0 to 1.0. When this class is used for audio playback, the valid range of input samples is from -1.0 to 1.0. Any samples that are outside of this range will be hard-clipped to fall within this range.

Supported audio formats

This class supports the subset of the hardware supported audio formats that are also supported under Java. Provided that the computer has a sound card that was manufactured after 1998, the following formats are likely to be supported.

Input/output latency

When capturing audio samples, there will be some delay (latency) from the time the sound arrives at the input port to the time that the corresponding audio samples are available from this class. Likewise, there will be some delay from the time sample are written until the corresponding audio signal reaches the output port (e.g., the speaker). This is because an internal buffer is used to temporarily store audio samples when they are captured or played. The size of this internal buffer affects the latency in that a lower bound on the capture (playback) latency is given by (bufferSize / sampleRate) seconds. Here, bufferSize parameter is the size of the buffer in samples per channel. This class provides a method, setBufferSize(), to simultaneously set the size of internal capture buffer and the internal playback buffer. The method getBufferSize() may be used to read the buffer size. The default size of the internal buffer is 4096 samples.

Constraints

This class requires that the sample rate, number of channels, bit resolution, and internal buffer size be the same for both capture and playback. The motivation for this constraint is to simplify usage. Most audio hardware requires this anyway.

Usage: audio capture

First, call the appropriate methods to set the desired audio format parameters such as sample rate, channels, bit resolution if values other than the defaults are desired. The setTransferSize() method should also be invoked to set the size of the array (in samples per channel) that is returned when audio samples are captured. The default value is 128 samples per channel. Then invoke the startCapture(consumer) method to start the audio capture process. This class will be ready to capture audio immediately after startCapture() returns. Note that startCapture() takes an Object parameter, consumer. In addition to starting the audio capture process, startCapture() also grants an object permission to capture audio.

After calling startCapture(consumer), the consumer object can capture audio from the input port by calling getSamples(consumer). The getSamples() method returns an array of samples from the input port. The getSamples() blocks until the requested number of samples (which is set by the setTransferSize method) are available. Thus, it is not possible to call this method too frequently. Note that if getSamples() is not called frequently enough, the internal buffer will overflow and some audio data will be lost, which is generally undersirable. After the consumer object no longer wishes to capture audio, it should free up the audio system resources by calling the stopCapture(consumer) method. It should be noted that only one object may capture audio simultaneously from the audio input port. A future version of this class may support multiple objects capturing from the input port simultaneously.

Usage: audio Playback

First, call the appropriate methods to set the desired audio format parameters such as sample rate, channels, bit resolution if values other than the defaults are desired. The setTransferSize() method should also be invoked to set the size of the array (in samples per channel) that is supplied when audio samples are played. The default value is 128 samples per channel. Then invoke the startPlayback(producer) method to start the audio playback process. This class will be ready to playback audio immediately after startPlayback() returns. Note that startPlayback() takes an Object parameter, producer. In addition to starting the audio playback process, startPlayback() also grants an object permission to playback audio.

After calling startPlayback(producer), the producer object can playback audio to the output port by calling putSamples(producer). The putSamples() method takes an array of samples and sends the audio data to the output port. The putSamples() method blocks until the requested number of samples (which is set by the setTransferSize method) have been written to the output port. Thus, it is not possible to call this method too frequently. Note that if putSamples() is not called frequently enough, the internal buffer will underflow, causing audible artifacts in the output signal. After the producer object no longer wishes to playback audio, it should free up the audio system resources by calling the stopPlayback(producer) method. It should be noted that only one object may playback audio simultaneously to the audio output port. A future version of this class may support multiple objects playing to the output port simultaneously.

Since:
Ptolemy II 1.0
Version:
$Id: LiveSound.java 57040 2010-01-27 20:52:32Z cxh $
Author:
Brian K. Vogel and Neil E. Turner and Steve Neuendorffer, Edward A. Lee
See Also:
SoundReader, SoundWriter
Accepted Rating:
Red (cxh)
Proposed Rating:
Yellow (net)

Field Summary
private static double[][] _audioInDoubleArray
          Array of audio samples in double format.
private static int _bitsPerSample
          The number of bits per sample.
private static int _bufferSize
          The requested buffer size in samples per channel.
private static int _bytesPerSample
          The number of bytes per sample, default 2.
private static byte[] _captureData
          Array of audio samples in byte format.
private static boolean _captureIsActive
          true is audio capture is currently active.
private static int _channels
          The number of channels.
private static java.util.List _liveSoundListeners
           
private static double _maxSample
           
private static double _maxSampleReciprocal
           
private static byte[] _playbackData
          Byte buffer used for playback data.
private static boolean _playbackIsActive
           
private static float _sampleRate
           
private static java.util.List _soundConsumers
           
private static javax.sound.sampled.SourceDataLine _sourceLine
          Interface to the hardware for reading data.
private static javax.sound.sampled.TargetDataLine _targetLine
          Interface to the hardware for producing sound.
private static int _transferSize
          The number of audio samples to transfer per channel when getSamples() is invoked.
 
Constructor Summary
LiveSound()
           
 
Method Summary
private static void _byteArrayToDoubleArray(double[][] doubleArray, byte[] byteArray)
           
private static byte[] _doubleArrayToByteArray(double[][] doubleArray)
           
private static java.lang.String _encodings(javax.sound.sampled.AudioFormat format)
          Return a string that describes the possible encodings for an AudioFormat.
private static void _flushCaptureBuffer()
           
private static void _flushPlaybackBuffer()
           
private static void _notifyLiveSoundListeners(int parameter)
          Notify the live sound listeners about a change in an audio parameter.
private static void _startCapture()
          Start audio capture.
private static void _startPlayback()
          Start audio playback.
private static void _stopCapture()
          Stop audio capture.
private static void _stopPlayback()
          Stop audio playback.
static void addLiveSoundListener(LiveSoundListener listener)
          Add a live sound listener.
static void flushCaptureBuffer(java.lang.Object consumer)
          Flush queued data from the capture buffer.
static void flushPlaybackBuffer(java.lang.Object producer)
          Flush queued data from the playback buffer.
static int getBitsPerSample()
          Return the number of bits per audio sample, which is set by the setBitsPerSample() method.
static int getBufferSize()
          Return the suggested size of the internal capture and playback audio buffers, in samples per channel.
static int getBufferSizeCapture()
          Return the size of the internal capture audio buffer, in samples per channel.
static int getBufferSizePlayback()
          Return the size of the internal playback audio buffer, in samples per channel.
static int getChannels()
          Return the number of audio channels, which is set by the setChannels() method.
static int getSampleRate()
          Return the current sampling rate in Hz, which is set by the setSampleRate() method.
static double[][] getSamples(java.lang.Object consumer)
          Return an array of captured audio samples.
static int getTransferSize()
          Get the array length (in samples per channel) to use for capturing and playing samples via the putSamples() and getSamples() methods.
static boolean isCaptureActive()
          Return true if audio capture is currently active.
static boolean isPlaybackActive()
          Return true if audio playback is currently active.
static void putSamples(java.lang.Object producer, double[][] samplesArray)
          Play an array of audio samples.
static void removeLiveSoundListener(LiveSoundListener listener)
          Remove a live sound listener.
static void resetCapture()
          Stop audio capture.
static void resetPlayback()
          Stop audio playback.
static void setBitsPerSample(int bitsPerSample)
          Set the number of bits per sample to use for audio capture and playback and notify any registered listeners of the change.
static void setBufferSize(int bufferSize)
          Request that the internal capture and playback audio buffers have bufferSize samples per channel and notify the registered listeners of the change.
static void setChannels(int channels)
          Set the number of audio channels to use for capture and playback and notify any registered listeners of the change.
static void setSampleRate(int sampleRate)
          Set the sample rate to use for audio capture and playback and notify an registered listeners of the change.
static void setTransferSize(int transferSize)
          Set the array length (in samples per channel) to use for capturing and playing samples via the putSamples() and getSamples() methods.
static void startCapture(java.lang.Object consumer)
          Start audio capture.
static void startPlayback(java.lang.Object producer)
          Start audio playback.
static void stopCapture(java.lang.Object consumer)
          Stop audio capture.
static void stopPlayback(java.lang.Object producer)
          Stop audio playback.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

_audioInDoubleArray

private static double[][] _audioInDoubleArray
Array of audio samples in double format.


_bitsPerSample

private static int _bitsPerSample
The number of bits per sample. Default is 16.


_bufferSize

private static int _bufferSize
The requested buffer size in samples per channel.


_bytesPerSample

private static int _bytesPerSample
The number of bytes per sample, default 2.


_captureIsActive

private static boolean _captureIsActive
true is audio capture is currently active.


_channels

private static int _channels
The number of channels. Deafult is 1.


_captureData

private static byte[] _captureData
Array of audio samples in byte format.


_playbackData

private static byte[] _playbackData
Byte buffer used for playback data.


_liveSoundListeners

private static java.util.List _liveSoundListeners

_maxSampleReciprocal

private static double _maxSampleReciprocal

_maxSample

private static double _maxSample

_playbackIsActive

private static boolean _playbackIsActive

_sampleRate

private static float _sampleRate

_soundConsumers

private static java.util.List _soundConsumers

_sourceLine

private static javax.sound.sampled.SourceDataLine _sourceLine
Interface to the hardware for reading data.


_targetLine

private static javax.sound.sampled.TargetDataLine _targetLine
Interface to the hardware for producing sound.


_transferSize

private static int _transferSize
The number of audio samples to transfer per channel when getSamples() is invoked.

Constructor Detail

LiveSound

public LiveSound()
Method Detail

addLiveSoundListener

public static void addLiveSoundListener(LiveSoundListener listener)
Add a live sound listener. The listener will be notified of all changes in live audio parameters. If the listener is already listening, then do nothing.

Parameters:
listener - The LiveSoundListener to add.
See Also:
removeLiveSoundListener(LiveSoundListener)

flushCaptureBuffer

public static void flushCaptureBuffer(java.lang.Object consumer)
                               throws java.io.IOException,
                                      java.lang.IllegalStateException
Flush queued data from the capture buffer. The flushed data is discarded. It is only legal to flush the capture buffer after startCapture() is called. Flushing an active audio buffer is likely to cause a discontinuity in the data, resulting in a perceptible click.

Note that only the object with the exclusive lock on the capture audio resources is allowed to invoke this method. An exception will occur if the specified object does not have the lock on the playback audio resources.

Parameters:
consumer - The object that has an exclusive lock on the capture audio resources.
Throws:
java.lang.IllegalStateException - If audio capture is currently inactive. That is, if startCapture() has not yet been called or if stopCapture() has already been called.
java.io.IOException - If the calling program does not have permission to access the audio capture resources.

flushPlaybackBuffer

public static void flushPlaybackBuffer(java.lang.Object producer)
                                throws java.io.IOException,
                                       java.lang.IllegalStateException
Flush queued data from the playback buffer. The flushed data is discarded. It is only legal to flush the playback buffer after startPlayback() is called, and only makes sense to do so (but is not required) after putSamples() is called. Flushing an active audio buffer is likely to cause a discontinuity in the data, resulting in a perceptible click.

Note that only the object with the exclusive lock on the playback audio resources is allowed to invoke this method. An exception will occur if the specified object does not have the lock on the playback audio resources.

Parameters:
producer - The object that has an exclusive lock on the playback audio resources.
Throws:
java.lang.IllegalStateException - If audio playback is currently inactive. That is, if startPlayback() has not yet been called or if stopPlayback() has already been called.
java.io.IOException - If the calling program does not have permission to access the audio playback resources.

getBitsPerSample

public static int getBitsPerSample()
Return the number of bits per audio sample, which is set by the setBitsPerSample() method. The default value of this parameter is 16 bits.

Returns:
The sample size in bits.
See Also:
setBitsPerSample(int)

getBufferSize

public static int getBufferSize()
Return the suggested size of the internal capture and playback audio buffers, in samples per channel. This parameter is set by the setBufferSize() method. There is no guarantee that the value returned is the actual buffer size used for capture and playback. Furthermore, the buffers used for capture and playback may have different sizes. The default value of this parameter is 4096.

Returns:
The suggested internal buffer size in samples per channel.
See Also:
setBufferSize(int)

getBufferSizeCapture

public static int getBufferSizeCapture()
                                throws java.lang.IllegalStateException
Return the size of the internal capture audio buffer, in samples per channel.

Returns:
The internal buffer size in samples per channel.
Throws:
java.lang.IllegalStateException - If audio capture is inactive.

getBufferSizePlayback

public static int getBufferSizePlayback()
Return the size of the internal playback audio buffer, in samples per channel. This may differ from the requested buffer size if the hardware does not support the requested buffer size. If playback has not been started, then will simply return the requested buffer size.

Returns:
The internal buffer size in samples per channel.
Throws:
java.lang.IllegalStateException - If audio playback is inactive.

getChannels

public static int getChannels()
Return the number of audio channels, which is set by the setChannels() method. The default value of this parameter is 1 (for mono audio).

Returns:
The number of audio channels.
See Also:
setChannels(int)

getSampleRate

public static int getSampleRate()
Return the current sampling rate in Hz, which is set by the setSampleRate() method. The default value of this parameter is 8000 Hz.

Returns:
The sample rate in Hz.
See Also:
setSampleRate(int)

getSamples

public static double[][] getSamples(java.lang.Object consumer)
                             throws java.io.IOException,
                                    java.lang.IllegalStateException
Return an array of captured audio samples. This method should be repeatedly called to obtain audio data. The returned audio samples will have values in the range [-1, 1], regardless of the audio bit resolution (bits per sample). This method should be called often enough to prevent overflow of the internal audio buffer. If overflow occurs, some audio data will be lost but no exception or other error condition will occur. If the audio data is not yet available, then this method will block until the data is available.

The first index of the returned array represents the channel number (0 for first channel, 1 for second channel). The number of channels is set by the setChannels() method. The second index represents the sample index within a channel. For example, returned array[n][m] contains the (m+1)th sample of the (n+1)th channel. For each channel, n, the length of returned array[n] is equal to the value returned by the getTransferSize() method. The size of the 2nd dimension of the returned array is set by the setTransferSize() method.

Note that only the object with the exclusive lock on the captured audio resources is allowed to invoked this method. An exception will occur if the specified object does not have the lock on the captured audio resources.

Parameters:
consumer - The object that has an exclusive lock on the capture audio resources.
Returns:
Two dimensional array of captured audio samples.
Throws:
java.lang.IllegalStateException - If audio capture is currently inactive. That is, if startCapture() has not yet been called or if stopCapture() has already been called.
java.io.IOException - If the calling program does not have permission to access the audio capture resources.

getTransferSize

public static int getTransferSize()
Get the array length (in samples per channel) to use for capturing and playing samples via the putSamples() and getSamples() methods. This method gets the size of the 2nd dimension of the 2-dimensional array used by the putSamples() and getSamples() methods. This method returns the value that was set by the setTransferSize(). If setTransferSize() was not invoked, the default value of 128 is returned.

Returns:
The size of the 2nd dimension of the 2-dimensional array used by the putSamples() and getSamples() methods.
See Also:
setTransferSize(int)

isCaptureActive

public static boolean isCaptureActive()
Return true if audio capture is currently active. Otherwise return false.

Returns:
True If audio capture is currently active. Otherwise return false.

isPlaybackActive

public static boolean isPlaybackActive()
Return true if audio playback is currently active. Otherwise return false.

Returns:
True If audio playback is currently active. Otherwise return false.

putSamples

public static void putSamples(java.lang.Object producer,
                              double[][] samplesArray)
                       throws java.io.IOException,
                              java.lang.IllegalStateException
Play an array of audio samples. There will be a delay before the audio data is actually heard, since the audio data in samplesArray is queued to an internal audio buffer. The setBufferSize() method suggests a size for the internal buffer. An upper bound on the latency is given by (bufferSize / sampleRate) seconds. This method should be invoked often enough to prevent underflow of the internal audio buffer. Underflow is undesirable since it will cause audible gaps in audio playback, but no exception or error condition will occur. If the caller attempts to write more data than can be written, this method blocks until the data can be written to the internal audio buffer.

The samples should be in the range (-1, 1). Samples that are outside this range will be hard-clipped so that they fall within this range.

The first index of the specified array represents the channel number (0 for first channel, 1 for second channel, etc.). The number of channels is set by the setChannels() method. The second index represents the sample index within a channel. For example, putSamplesArray[n][m] contains the (m+1)th sample of the (n+1)th channel.

Note that only the object with the exclusive lock on the playback audio resources is allowed to invoke this method. An exception will occur if the specified object does not have the lock on the playback audio resources.

Parameters:
producer - The object that has an exclusive lock on the playback audio resources.
samplesArray - A two dimensional array containing the samples to play or write to a file.
Throws:
java.io.IOException - If the calling program does not have permission to access the audio playback resources.
java.lang.IllegalStateException - If audio playback is currently inactive. That is, If startPlayback() has not yet been called or if stopPlayback() has already been called.

removeLiveSoundListener

public static void removeLiveSoundListener(LiveSoundListener listener)
Remove a live sound listener. If the listener is is not listening, then do nothing.

Parameters:
listener - The LiveSoundListener to remove.
See Also:
addLiveSoundListener(LiveSoundListener)

resetCapture

public static void resetCapture()
Stop audio capture. If audio capture is already inactive, then do nothing. This method should generally not be used, but it may be needed to turn of audio capture for the case where an ill-behaved application exits without calling stopCapture(). The preferred way of stopping audio capture is by calling the stopCapture() method.


resetPlayback

public static void resetPlayback()
Stop audio playback. If audio playback is already inactive, then do nothing. This method should generally not be used, but it may be needed to turn of audio playback for the case where an ill-behaved application exits without calling stopPlayback(). The preferred way of stopping audio playback is by calling the stopPlayback() method.


setBitsPerSample

public static void setBitsPerSample(int bitsPerSample)
                             throws java.io.IOException
Set the number of bits per sample to use for audio capture and playback and notify any registered listeners of the change. Allowable values include 8 and 16 bits. If this method is not invoked, then the default value of 16 bits is used.

Parameters:
bitsPerSample - The number of bits per sample.
Throws:
java.io.IOException - If the specified bits per sample is not supported by the audio hardware or by Java.
See Also:
getBitsPerSample()

setBufferSize

public static void setBufferSize(int bufferSize)
                          throws java.io.IOException
Request that the internal capture and playback audio buffers have bufferSize samples per channel and notify the registered listeners of the change. If this method is not invoked, the default value of 1024 is used.

Parameters:
bufferSize - The suggested size of the internal capture and playback audio buffers, in samples per channel.
Throws:
java.io.IOException - If the specified number of channels is not supported by the audio hardware or by Java.
See Also:
getBufferSize()

setChannels

public static void setChannels(int channels)
                        throws java.io.IOException
Set the number of audio channels to use for capture and playback and notify any registered listeners of the change. Allowable values are 1 (for mono) and 2 (for stereo). If this method is not invoked, the default value of 1 audio channel is used. Note that this method sets the size of the first dimension of the 2-dimensional array used by the putSamples() and getSamples() methods.

Parameters:
channels - The number audio channels.
Throws:
java.io.IOException - If the specified number of channels is not supported by the audio hardware or by Java.
See Also:
getChannels()

setSampleRate

public static void setSampleRate(int sampleRate)
                          throws java.io.IOException
Set the sample rate to use for audio capture and playback and notify an registered listeners of the change. Allowable values for this parameter are 8000, 11025, 22050, 44100, and 48000 Hz. If this method is not invoked, then the default value of 8000 Hz is used.

Parameters:
sampleRate - Sample rate in Hz.
Throws:
java.io.IOException - If the specified sample rate is not supported by the audio hardware or by Java.
See Also:
getSampleRate()

setTransferSize

public static void setTransferSize(int transferSize)
                            throws java.lang.IllegalStateException
Set the array length (in samples per channel) to use for capturing and playing samples via the putSamples() and getSamples() methods. This method sets the size of the 2nd dimension of the 2-dimensional array used by the putSamples() and getSamples() methods. If this method is not invoked, the default value of 128 is used.

This method should only be called while audio capture and playback are inactive. Otherwise an exception will occur.

Parameters:
transferSize - The size of the 2nd dimension of the 2-dimensional array used by the putSamples() and getSamples() methods
Throws:
java.lang.IllegalStateException - If this method is called while audio capture or playback are active.
See Also:
getTransferSize()

startCapture

public static void startCapture(java.lang.Object consumer)
                         throws java.io.IOException,
                                java.lang.IllegalStateException
Start audio capture. The specified object will be given an exclusive lock on the audio capture resources until the stopCapture() method is called with the same object reference. After this method returns, the getSamples() method may be repeatedly invoked (using the object reference as a parameter) to capture audio.

If audio capture is already active, then an exception will occur.

Parameters:
consumer - The object to be given exclusive access to the captured audio resources.
Throws:
java.io.IOException - If another object currently has access to the audio capture resources or if starting the capture or playback throws it.
java.lang.IllegalStateException - If this method is called while audio capture is already active.

startPlayback

public static void startPlayback(java.lang.Object producer)
                          throws java.io.IOException,
                                 java.lang.IllegalStateException
Start audio playback. The specified object will be given an exclusive lock on the audio playback resources until the stopPlayback() method is called with the same object reference. After this method returns, the putSamples() method may be repeatedly invoked (using the object reference as a parameter) to playback audio.

If audio playback is already active, then an exception will occur.

Parameters:
producer - The object to be given exclusive access to the playback resources.
Throws:
java.io.IOException - If another object currently has access to the audio capture resources or if starting the playback throws it.
java.lang.IllegalStateException - If this method is called while audio playback is already active.

stopCapture

public static void stopCapture(java.lang.Object consumer)
                        throws java.io.IOException,
                               java.lang.IllegalStateException
Stop audio capture. If the specified object has the lock on audio capture when this method is invoked, then stop audio capture. Otherwise an exception will occur.

Parameters:
consumer - The object that held on exclusive lock on the captured audio resources when this method was invoked.
Throws:
java.io.IOException - If another object currently has access to the audio capture resources or if stopping the capture throws it.
java.lang.IllegalStateException - If the specified object did not hold an exclusive lock on the captured audio resources when this method was invoked.

stopPlayback

public static void stopPlayback(java.lang.Object producer)
                         throws java.io.IOException,
                                java.lang.IllegalStateException
Stop audio playback. If the specified object has the lock on audio playback when this method is invoked, then stop audio playback. Otherwise an exception will occur.

Parameters:
producer - The object that held on exclusive lock on the playback audio resources when this method was invoked.
Throws:
java.io.IOException - If another object currently has access to the audio capture resources or if stopping the playback throws it.
java.lang.IllegalStateException - If the specified object did not hold an exclusive lock on the playback audio resources when this method was invoked.

_byteArrayToDoubleArray

private static void _byteArrayToDoubleArray(double[][] doubleArray,
                                            byte[] byteArray)

_doubleArrayToByteArray

private static byte[] _doubleArrayToByteArray(double[][] doubleArray)
                                       throws java.lang.IllegalArgumentException
Throws:
java.lang.IllegalArgumentException

_encodings

private static java.lang.String _encodings(javax.sound.sampled.AudioFormat format)
Return a string that describes the possible encodings for an AudioFormat.

Parameters:
format - The audio format.
Returns:
A string describing the audio formats available.

_flushCaptureBuffer

private static void _flushCaptureBuffer()

_flushPlaybackBuffer

private static void _flushPlaybackBuffer()

_notifyLiveSoundListeners

private static void _notifyLiveSoundListeners(int parameter)
Notify the live sound listeners about a change in an audio parameter.

Parameters:
parameter - The audio parameter of LiveSound that has changed. The value of parameter should be one of LiveSoundEvent.SAMPLE_RATE, LiveSoundEvent.CHANNELS, LiveSoundEvent.BUFFER_SIZE, or LiveSoundEvent.BITS_PER_SAMPLE.
Throws:
java.lang.Exception - If a listener has a problem responding to the change.

_startCapture

private static void _startCapture()
                           throws java.io.IOException
Start audio capture.

Throws:
java.io.IOException

_startPlayback

private static void _startPlayback()
                            throws java.io.IOException
Start audio playback.

Throws:
java.io.IOException

_stopPlayback

private static void _stopPlayback()
Stop audio playback.


_stopCapture

private static void _stopCapture()
Stop audio capture.