ptolemy.media.javasound
Class SoundWriter

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

public class SoundWriter
extends java.lang.Object

This class is a buffer that supports the writing of audio samples to a sound file. Specifically, this buffer supports the writing of double-valued audio samples. The maximum valid range of sample values is from -1.0 to 1.0. Any values outside of this range will be hard-clipped to fall within this range.

Supported file types

Valid sound file formats are WAVE (.wav), AIFF (.aif, .aiff), AU (.au). Valid sample rates are 8000, 11025, 22050, 44100, and 48000 Hz. Both 8 bit and 16 bit audio are supported. Mono and stereo files are supported.

Usage

The path to the sound file to write is given as a constructor parameter, along with parameters that specify the desired audio format. The constructor also takes an array length parameter, which is explained below.

After invoking the constructor, the putSamples() method should be repeatedly invoked to write samples to the specified sound file. This method is blocking, so it will not return until the samples have been written. The putSamples() method takes a multidimensional array as a parameter. The first index represents the channel number (0 for first channel, 1 for second channel, etc.). The second index represents the sample index within a channel. For each channel i, the size of the array, putSamplesArray[i].length, must be equal to the constructor parameter putSamplesArraySize. Otherwise an exception will occur. Thus, each call to putSamples() writes putSamplesArraySize on each channel. It should be noted that the putSamples() method does not write samples directly to a sound file, but instead writes samples to an internal array. The internal array of samples is written to the sound file by the closeFile() method.

The closeFile() method should be invoked when no more samples need to be written. This method will write the internal array of samples to the output file and close the file. It is not possible to write any more samples after closeFile() has been called. An exception will occur if putSamples() is invoked at any point after closeFile() is invoked.

Security issues

Applications have no restrictions on the capturing or playback of audio. Applet code is not allowed to write native files by default. The .java.policy file must be modified to grant applets more privileges.

Note: Requires Java 2 v1.3.0 or later.

Since:
Ptolemy II 1.0
Version:
$Id: SoundWriter.java 57040 2010-01-27 20:52:32Z cxh $
Author:
Brian K. Vogel
See Also:
SoundCapture
Accepted Rating:
Red (cxh)
Proposed Rating:
Red (vogel)

Field Summary
private  int _bitsPerSample
           
private  int _bytesPerSample
           
private  int _channels
           
private  byte[] _data
           
private  boolean _debug
           
private  java.lang.String _fileName
           
private  int _frameSizeInBytes
           
private  boolean _isAudioWriterActive
           
private  javax.sound.sampled.AudioFormat _playToFileFormat
           
private  float _sampleRate
           
private  java.util.ArrayList _toFileBuffer
           
private  java.io.File outFile
           
 
Constructor Summary
SoundWriter(java.lang.String fileName, float sampleRate, int bitsPerSample, int channels, int putSamplesArraySize)
          Construct a sound writer object with the specified name.
 
Method Summary
private  byte[] _doubleArrayToByteArray(double[][] doubleArray, int bytesPerSample, int channels)
           
private  void _initializeAudio()
          Perform initialization that must be done before putSamples() can be invoked.
private  void _stopPlaybackToFile()
          Open a the file specified in the constructor for writing, write the accumulated audio samples (obtained via putSamples()) to the file specified in the constructor, and close the file.
 void closeFile()
          Open a the file specified in the constructor for writing, write the accumulated audio samples (obtained via putSamples()) to the file specified in the constructor, and close the file.
 void putSamples(double[][] putSamplesArray)
          Append the audio data contained in putSamplesArray to an internal array.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

outFile

private java.io.File outFile

_fileName

private java.lang.String _fileName

_bitsPerSample

private int _bitsPerSample

_sampleRate

private float _sampleRate

_channels

private int _channels

_data

private byte[] _data

_frameSizeInBytes

private int _frameSizeInBytes

_toFileBuffer

private java.util.ArrayList _toFileBuffer

_playToFileFormat

private javax.sound.sampled.AudioFormat _playToFileFormat

_bytesPerSample

private int _bytesPerSample

_isAudioWriterActive

private boolean _isAudioWriterActive

_debug

private boolean _debug
Constructor Detail

SoundWriter

public SoundWriter(java.lang.String fileName,
                   float sampleRate,
                   int bitsPerSample,
                   int channels,
                   int putSamplesArraySize)
Construct a sound writer object with the specified name. Valid sound file formats are WAVE (.wav), AIFF (.aif, .aiff), AU (.au). The file format is automatically determined from the file extension.

Parameters:
fileName - The file name to create. If the file already exists, overwrite it. Valid sound file formats are WAVE (.wav), AIFF (.aif, .aiff), AU (.au). The file format to write is determined automatically from the file extension.
sampleRate - Sample rate in Hz. Must be in the range: 8000 to 48000.
bitsPerSample - Number of bits per sample (valid choices are 8 or 16).
channels - Number of audio channels. 1 for mono, 2 for stereo.
putSamplesArraySize - Size of the array parameter of putSamples(). There is no restriction on the value of this parameter, but typical values are 64-2024.
Method Detail

putSamples

public void putSamples(double[][] putSamplesArray)
                throws java.lang.IllegalStateException
Append the audio data contained in putSamplesArray to an internal array. The audio samples in this array will be written to the sound file specified in the constructor when the closeFile() method is invoked.

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.

Parameters:
putSamplesArray - A two dimensional array containing the samples to play or write to a file. The first index represents the channel number (0 for first channel, 1 for second channel, etc.). 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. putSamplesArray should be a rectangular array such that putSamplesArray.length() gives the number of channels and putSamplesArray[n].length() is equal to putSamplesSize, for all channels n. An exception will occur if this is not the case.
Throws:
java.lang.IllegalStateException - If closeFile() has already been called.

closeFile

public void closeFile()
               throws java.io.IOException
Open a the file specified in the constructor for writing, write the accumulated audio samples (obtained via putSamples()) to the file specified in the constructor, and close the file. This method should be called when no more calls to putSamples() are required. An exception will occur if putSamples() is called after this method is invoked.

Throws:
java.io.IOException - If there is a problem closing the audio resources, or if the "write audio data to file" constructor was used and the sound file has an unsupported format.

_initializeAudio

private void _initializeAudio()
Perform initialization that must be done before putSamples() can be invoked.


_stopPlaybackToFile

private void _stopPlaybackToFile()
                          throws java.io.IOException
Open a the file specified in the constructor for writing, write the accumulated audio samples (obtained via putSamples()) to the file specified in the constructor, and close the file. This method should be called when no more calls to putSamples() are required.

Throws:
java.io.IOException

_doubleArrayToByteArray

private byte[] _doubleArrayToByteArray(double[][] doubleArray,
                                       int bytesPerSample,
                                       int channels)