MiniAiff – Reading and Writing Soundfiles Made Easy
Have you ever wondered if there’s a way to access sound files as easily as reading and writing plain text files? Did you ever need to try out some DSP code and finally found yourself struggling with code from others just to get the sound file format right?
If you have, here’s something for you.
I’m happy to present MiniAiff, world’s simplest AIFF sound file interface. It is cross platform, which means it works on any operating system, any computer (well, all of those I had access to, that is…) and it’s so simple to use you cannot do a thing wrong. And, above all, it’s entirely free. Play with the fun stuff and let the computer do the nasty bit twiddling for you to stream the data of your application to an AIFF sound file, without even knowing what an “AIFF” is and what it means exactly.
What is it?
To see if this is really for you, here’s what it is: MiniAiff is a set of routines written in the C programming language that allow reading from and writing to sound files in AIFF fomat. It comes as as static library (.LIB) that links against your existing C or C++ project. At the time of writing, I provide the MiniAiff static library for the following platforms and compilers:
- MacOS X Universal 32/64bit Binary with Xcode
- x86 Linux with gcc
- Win9x, XP, Vista under Microsoft Visual C++ 6 and Visual Studio 2008
I might provide support for other platforms soon when I have some time to get it done. If you need the library for a different platform and it’s not available here give me a buzz and I’ll see what I can do.
Why AIFF files?
Well, honestly, I’m kind of a Mac dude so this choice was pretty obvious. The truth is, I had the AIFF code I wrote sitting around for quite some time now and I was fed up re-using it and tweaking it whenever I needed to add soundfile functionality to my projects. So I decided to make it a library of easy to use routines and be done with it once and for all. Since I figured others might have the same problem, here I am sharing it with you.
AIFF is a very common standard, just like the “Wave” file format. Most players and software programs can play and convert both types of files, so the difference is purely one of my personal taste. “AIFF” means Audio Interchange File Format, which also has a nice ring to it when we’re talking about a cross-platform library.
Anyway, here it is – enjoy!
What do I need to use it?
Well, first of all, a computer, obviously. You also need a development environment such as Microsoft Visual C or Xcode/gcc. MiniAiff makes calls to fread(), fwrite() so you need to include the stdio libraries in your project or you will get a link error. Usually, they are linked against by default so you don’t have to do anything special, but I thought I’d mention it again.
How do I use it?
There are example applications included with the library. I suggest you download them and have a look. I will explain the functions contained in the library in greater detail below – you will also find these explanations in the accompanying .h files.
|const char *mAiffGetVersion(void);||Returns a pointer to a string containing the current library version|
|int mAiffReadData(char *filename, float **data, unsigned long startFrame, int numFrames, int numChannels);
int mAiffReadDataFromChannel(char *filename, float *data, unsigned long startFrame, int numFrames, int channel);
|Reads data from the position “startFrame” in the AIFF file specified in *filename, converts it into the range [-1.0, +1.0) and returns it as float in data[0...numChannels-1][0...numFrames-1]. If an error occurs, mAiffReadData() returns a negative error code. If all goes well, mAiffReadData() returns the number of frames actually read. If it returns with 0, the end of the file has been reached or exceeded by your request. If numChannels is different from the number of channels in the file only the channels that are available in the file will be read.mAiffReadDataFromChannel is optional and allows specifying a channel to read from if the file is a multi-channel audio file. If the desired channel is not available the function reads data from the highest numbered channel.|
|int mAiffInitFile(char *filename, float sampleRate, int sampleSize, int numChannels);||Opens and clears a new file for writing. If you do not call this function prior to writing to an audio file with mAiffWriteData(), the data you write will be appended to the file. If the file does not exist and you do not call mAiffInitFile() prior to calling mAiffWriteData() writing to the file will fail.|
|int mAiffWriteData(char *filename, float **data, int numFrames, int numChannels);||Appends the data in data[0...numChannels-1][0...numFrames-1] to the audio file specified with *filename. If it completes successfully, it returns the actual number of frames appended to the file. If it fails, it returns an error code. If numChannels is different from the number of channels in the file only the channels that are available in the file will be filled with data.
|float **mAiffAllocateAudioBuffer(int numChannels, int numFrames);void mAiffDeallocateAudioBuffer(int numChannels);||Utility functions to allocate/deallocate a two-dimensional data array (each dimension being used as a separate audio channel).|
|int mAiffGetNumberOfFrames(char *filename);||Returns the number of sample frames contained in the specified file. If it fails, it returns an error code.|
|int mAiffGetNumberOfChannels(char *filename);||Returns the number of audio channels contained in the specified file.If it fails, it returns an error code.|
|int mAiffGetWordlength(char *filename);||Returns the wordlength of the audio data contained in the specified file. Possible wordlengths are 8bit, 16bit, 24bit and 32bit. If it fails, it returns an error code.|
|int mAiffGetSampleRate(char *filename);||Returns the sample rate of the audio data contained in the specified file. Although MiniAiff reads all sample rates, the files written will all be 44.1kHz at the moment. If your original sound file wasn’t recorded at 44.1kHz, you will experience a change in pitch of your audio material when you copy the input to the output. If it fails, it returns an error code.|
|int mAiffWriteAppData(char *filename, void *data, int numBytes);||Writes a chunk of data to an AIFF file’s application specific chunk (APPL). No byte reversing is carried out – this is rather experimental and should only be used if you know what you’re doing. It is great for saving settings or other stuff to a file. An existing file with the same name will be overwritten.Only one chunk of appspecific data per file is supported – each call to this function initializes the file.Any data previously contained in that file may be lost – so you are advised to call this function BEFORE you add audio data to the file if you wish to add both audio and app specific data. If it fails, it returns an error code.|
|int mAiffReadAppData(char *filename, void *data, unsigned long start, int numBytes);||Reads a chunk of data from an AIFF file’s application specific chunk (APPL). No byte reversing is carried out – this is rather experimental and should only be used if you know what you’re doing. It is great for loading settings or other stuff from a file. If it fails, it returns an error code.|
|int mAiffGetLowKey(char *filename);
int mAiffGetHighKey(char *filename);
int mAiffGetRootKey(char *filename);
int mAiffGetGain(char *filename);
int mAiffGetDetune(char *filename);
|Return the specified information from an AIFF files’ instrument chunk. If an error occurs, an error code is returned. If no instrument chunk is present, the functions return 0.|
|int mAiffPutFilename(char *filename);
int mAiffGetFilename (char *filename);
|*** discontinued in version 2.0 *** Brings up an “Open File” or “Save File” dialog that lets you choose an input and output file. If a file was chosen and no error occurred, the function returns with a result != 0 and the path (including the selected files’ name) in “filename”. If the dialog was cancelled or an error occurred, it returns with 0 and an empty string (“”) in “filename”.|
|Please note on file and path naming conventions: In the “traditional” MacOS, directories are separated by a colon (“:”), while on the PC they are separated by a backslash (“\”). So if your audio file is named “song.aif” and is located in the folder “my audio” on your harddisk “my harddisk”, the path on the MacOS reads: “my harddisk:my audio:song.aif”. On the PC assuming “C” ist your hard disk, this path would be “C:\my audio\song.aif”. Note that in Xcode in OS X path names use the UNIX-type forward slash, so in this case your path from the above example would be “/Volumes/my harddisk/my audio/song.aif”|