de.sciss.io
Class AudioFile

java.lang.Object
  extended by de.sciss.io.AudioFile
All Implemented Interfaces:
InterleavedStreamFile

public class AudioFile
extends java.lang.Object
implements InterleavedStreamFile

The AudioFile allows reading and writing of sound files. It wraps a RandomAccessFile and delegates the I/O to subclasses which deal with the specific sample format and endianess.

Currently supported formats are: AIFF, IRCAM, NeXT/Sun (.au), WAVE, and Wave64. Supported resolutions are 8/16/24/32 bit integer and 32/64 bit floating point. However not all audio formats support all bit depths.

Not all format combinations are supported, for example the rather exotic little-endian AIFF, but also little-endian SND, WAVE 8-bit.

In order to simplify communication with CSound, raw output files are supported, raw input files however are not recognized.

To create a new AudioFile you call one of its static methods openAsRead or openAsWrite. The format description is handled by an AudioFileDescr object. This object also contains information about what special tags are read/written for which format. For example, AIFF can read/write markers, and application-specific chunk, and a gain tag. WAVE can read/write markers and regions, and a gain tag, etc.

The AudioFile implements the generic interface InterleavedStreamFile (which is likely to be modified in the future) to allow clients to deal more easily with different sorts of streaming files, not just audio files.

Version:
0.38, 26-Jun-09
Author:
Hanns Holger Rutz
See Also:
AudioFileDescr
Todo:
more flexible handling of endianess, at least SND and IRCAM should support both versions., more tags, like peak information and channel panning., (faster) low-level direct file-to-file copy in the copyFrames method

Field Summary
protected  AudioFileDescr afd
           
protected  java.nio.ByteBuffer byteBuf
           
protected  int bytesPerFrame
           
protected  int channels
           
protected  java.nio.channels.FileChannel fch
           
protected  int frameBufCapacity
           
protected  java.io.RandomAccessFile raf
           
 
Method Summary
 void cleanUp()
          Flushes and closes the file.
 void close()
          Flushes and closes the file
 void copyFrames(InterleavedStreamFile target, long length)
          Copies sample frames from a source sound file to a target file (either another sound file or any other class implementing the InterleavedStreamFile interface).
 void flush()
          Flushes pending buffer content, and updates the sound file header information (i.e. length fields).
 int getChannelNum()
          Returns the number of channels in the file.
 AudioFileDescr getDescr()
          Returns a description of the audio file's format.
 java.io.File getFile()
          Returns the file that was used to open the audio file.
 long getFrameNum()
          Returns the number of frames in the file.
 long getFramePosition()
          Returns the current file pointer in sample frames
protected static java.lang.String getResourceString(java.lang.String key)
           
static AudioFile openAsRead(java.io.File f)
          Opens an audio file for reading.
static AudioFile openAsWrite(AudioFileDescr afd)
          Opens an audio file for reading/writing.
 void readAppCode()
          Reads application specific code into the audio file description if there is such code.
 void readFrames(float[][] data, int offset, int length)
          Reads sample frames from the current position
 void readMarkers()
          Reads markers into the audio file description if there are any.
static int retrieveType(java.io.File f)
          Determines the type of audio file.
 void seekFrame(long frame)
          Moves the file pointer to a specific frame.
 void setFrameNum(long frame)
           
 void truncate()
          Truncates the file to the size represented by the current file position.
 void writeFrames(float[][] data, int offset, int length)
          Writes sample frames to the file starting at the current position.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

raf

protected final java.io.RandomAccessFile raf

fch

protected final java.nio.channels.FileChannel fch

afd

protected AudioFileDescr afd

byteBuf

protected java.nio.ByteBuffer byteBuf

bytesPerFrame

protected int bytesPerFrame

frameBufCapacity

protected int frameBufCapacity

channels

protected int channels
Method Detail

openAsRead

public static AudioFile openAsRead(java.io.File f)
                            throws java.io.IOException
Opens an audio file for reading.

Parameters:
f - the path name of the file
Returns:
a new AudioFile object whose header is already parsed and can be obtained through the getDescr method.
Throws:
java.io.IOException - if the file was not found, could not be read or has an unknown or unsupported format

openAsWrite

public static AudioFile openAsWrite(AudioFileDescr afd)
                             throws java.io.IOException
Opens an audio file for reading/writing. The pathname is determined by the file field of the provided AudioFileDescr. If a file denoted by this path already exists, it will be deleted before opening.

Note that the initial audio file header is written immediately. Special tags for the header thus need to be set in the AudioFileDescr before calling this method, including markers and regions. It is not possible to write markers and regions after the file has been opened (since the header size has to be constant).

Parameters:
afd - format and resolution of the new audio file. the header is immediatly written to the harddisc
Throws:
java.io.IOException - if the file could not be created or the format is unsupported

retrieveType

public static int retrieveType(java.io.File f)
                        throws java.io.IOException
Determines the type of audio file.

Parameters:
f - the path name of the file
Returns:
the type code as defined in AudioFileDescr, e.g. TYPE_AIFF. Returns TYPE_UNKNOWN if the file could not be identified.
Throws:
java.io.IOException - if the file could not be read

getDescr

public AudioFileDescr getDescr()
Returns a description of the audio file's format. Fields which are guaranteed to be filled in, are the type (use getType), channels, bitsPerSample, sampleFormat, rate and length.

Returns:
an AudioFileDescr describing this audio file.
Warning:
the returned description is not immutable but should be considered read only, do not modify it. the fields may change dynamically if the file is modified, e.g. the length field for a writable file.

getFile

public java.io.File getFile()
Returns the file that was used to open the audio file. Note that this simply returns getDescr().file, so it's not a good idea to modify this field after opening the audio file.

Specified by:
getFile in interface InterleavedStreamFile
Returns:
the File that was used in the static constructor methods. Can be used to query the pathname or to delete the file after it has been closed

seekFrame

public void seekFrame(long frame)
               throws java.io.IOException
Moves the file pointer to a specific frame.

Specified by:
seekFrame in interface InterleavedStreamFile
Parameters:
frame - the sample frame which should be the new file position. this is really the sample index and not the physical file pointer.
Throws:
java.io.IOException - when a seek error occurs or you try to seek past the file's end.

flush

public void flush()
           throws java.io.IOException
Flushes pending buffer content, and updates the sound file header information (i.e. length fields). Usually you will not have to call this method directly, unless you pause writing for some time and want the file information to appear as accurate as possible.

Specified by:
flush in interface InterleavedStreamFile
Throws:
java.io.IOException

getFramePosition

public long getFramePosition()
                      throws java.io.IOException
Returns the current file pointer in sample frames

Specified by:
getFramePosition in interface InterleavedStreamFile
Returns:
the sample frame index which is the offset for the next read or write operation.
Throws:
java.io.IOException - when the position cannot be queried

readFrames

public void readFrames(float[][] data,
                       int offset,
                       int length)
                throws java.io.IOException
Reads sample frames from the current position

Specified by:
readFrames in interface InterleavedStreamFile
Parameters:
data - buffer to hold the frames read from harddisc. the samples will be deinterleaved such that data[0][] holds the first channel, data[1][] holds the second channel etc. ; it is allowed to have null arrays in the data (e.g. data[0] == null), in which case these channels are skipped when reading
offset - offset in the buffer in sample frames, such that he first frame of the first channel will be placed in data[0][offset] etc.
length - number of continuous frames to read.
Throws:
java.io.IOException - if a read error or end-of-file occurs.

writeFrames

public void writeFrames(float[][] data,
                        int offset,
                        int length)
                 throws java.io.IOException
Writes sample frames to the file starting at the current position. If you write past the previous end of the file, the length field of the internal AudioFileDescr is updated. Since you get a reference from getDescr and not a copy, using this reference to the description will automatically give you the correct file length.

Specified by:
writeFrames in interface InterleavedStreamFile
Parameters:
data - buffer holding the frames to write to harddisc. the samples must be deinterleaved such that data[0][] holds the first channel, data[1][] holds the second channel etc.
offset - offset in the buffer in sample frames, such that he first frame of the first channel will be read from data[0][offset] etc.
length - number of continuous frames to write.
Throws:
java.io.IOException - if a write error occurs.

getFrameNum

public long getFrameNum()
                 throws java.io.IOException
Returns the number of frames in the file.

Specified by:
getFrameNum in interface InterleavedStreamFile
Returns:
the number of sample frames in the file. includes pending buffer content
Throws:
java.io.IOException - this is never thrown but declared as of the InterleavedStreamFile interface

setFrameNum

public void setFrameNum(long frame)
                 throws java.io.IOException
Specified by:
setFrameNum in interface InterleavedStreamFile
Throws:
java.io.IOException

getChannelNum

public int getChannelNum()
Returns the number of channels in the file.

Specified by:
getChannelNum in interface InterleavedStreamFile
Returns:
the number of channels

truncate

public void truncate()
              throws java.io.IOException
Truncates the file to the size represented by the current file position. The file must have been opened in write mode. Truncation occurs only if frames exist beyond the current file position, which implicates that you have set the position using seekFrame to a location before the end of the file. The header information is immediately updated.

Specified by:
truncate in interface InterleavedStreamFile
Throws:
java.io.IOException - if truncation fails

copyFrames

public void copyFrames(InterleavedStreamFile target,
                       long length)
                throws java.io.IOException
Copies sample frames from a source sound file to a target file (either another sound file or any other class implementing the InterleavedStreamFile interface). Both files must have the same number of channels.

Specified by:
copyFrames in interface InterleavedStreamFile
Parameters:
target - to file to copy to from this audio file
length - the number of frames to copy. Reading and writing begins at the current positions of both files.
Throws:
java.io.IOException - if a read or write error occurs

close

public void close()
           throws java.io.IOException
Flushes and closes the file

Specified by:
close in interface InterleavedStreamFile
Throws:
java.io.IOException - if an error occurs during buffer flush or closing the file.

cleanUp

public void cleanUp()
Flushes and closes the file. As opposed to close(), this does not throw any exceptions but simply ignores any errors.

See Also:
close()

readMarkers

public void readMarkers()
                 throws java.io.IOException
Reads markers into the audio file description if there are any. This method sets the KEY_MARKERS property of the afd, if markers are available. It sets the KEY_LOOP property if a loop span is available.

Throws:
java.io.IOException - if a read or parsing error occurs
See Also:
getDescr(), AudioFileDescr.KEY_MARKERS, AudioFileDescr.KEY_LOOP

readAppCode

public void readAppCode()
                 throws java.io.IOException
Reads application specific code into the audio file description if there is such code. This method sets the KEY_APPCODE property of the afd. The caller can check the appCode field of the afd to ensure that potential app code is relevant to it.

Throws:
java.io.IOException - if a read or parsing error occurs
See Also:
getDescr(), AudioFileDescr.KEY_APPCODE, AudioFileDescr.appCode

getResourceString

protected static final java.lang.String getResourceString(java.lang.String key)