|
Packit |
4aff17 |
new_file_type.HOWTO
|
|
Packit |
4aff17 |
===================
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Original : Wed May 23 19:05:07 EST 2001
|
|
Packit |
4aff17 |
Update 1 : Fri Jul 11 22:12:38 EST 2003
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
This document will attempt to explain as fully as possible how to add code to
|
|
Packit |
4aff17 |
libsndfile to allow the reading and writing of new file types. By new file
|
|
Packit |
4aff17 |
type I particularly mean a new header type rather than a new encoding method
|
|
Packit |
4aff17 |
for an existing file type.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
This HOWTO will take the form of a step by step guide. It will assume that you
|
|
Packit |
4aff17 |
have all required tools including :
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
- gcc
|
|
Packit |
4aff17 |
- make (should really be the GNU version)
|
|
Packit |
4aff17 |
- autoconf
|
|
Packit |
4aff17 |
- automake
|
|
Packit |
4aff17 |
- libtool
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
These should all be available on the GNU ftp site: ftp://ftp.gnu.org/pub/gnu/.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
To help make these steps clearer let's suppose we are adding support for the
|
|
Packit |
4aff17 |
Whacky file format whose files contain 'W','A','C' and 'K' as the first four
|
|
Packit |
4aff17 |
bytes of the file format. Lets also assume that Whacky files contain PCM encoded
|
|
Packit |
4aff17 |
data.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Step 1
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
Create a new .c file in the src/ directory of the libsndfile source tree. The
|
|
Packit |
4aff17 |
file name should be reasonable descriptive so that is is obvious that files of
|
|
Packit |
4aff17 |
the new type are handled by this file. In this particular case the file might
|
|
Packit |
4aff17 |
be named 'whacky.c'.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Step 2
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
Add your new source code file to the build process.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Edit the file src/Makefile.am and add the name of your file handler to the
|
|
Packit |
4aff17 |
FILESPECIFIC list of handlers. This list looks something like this:
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
FILESPECIFIC = aiff.c au.c au_g72x.c nist.c paf.c raw.c samplitude.c \
|
|
Packit |
4aff17 |
svx.c wav.c wav_float.c wav_gsm610.c wav_ima_adpcm.c \
|
|
Packit |
4aff17 |
wav_ms_adpcm.c
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Then, run the script named 'reconf' in the libsndfile top level directory,
|
|
Packit |
4aff17 |
which will run autoconf and other associated tools. Finally run "./configure"
|
|
Packit |
4aff17 |
in the top level directory. You may want to use the "--disable-gcc-opt" option
|
|
Packit |
4aff17 |
to disable gcc optimisations and make debugging with gdb/ddd easier.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Step 3
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
Add a unique identifier for the new file type.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Edit src/sndfile.h.in and find the enum containing the SF_FORMAT_XXX identifiers.
|
|
Packit |
4aff17 |
Since you will be adding a major file type you should add your identifier to the
|
|
Packit |
4aff17 |
top part of the list where the values are above 0x10000 in value. The easiest
|
|
Packit |
4aff17 |
way to do this is to find the largest value in the list, add 0x10000 to it and
|
|
Packit |
4aff17 |
make that your new identifier value. The identifier should be something like
|
|
Packit |
4aff17 |
SF_FORMAT_WACK.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Step 4
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
Add code to the file type recogniser function.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Edit src/sndfile.c and find the function guess_file_type (). This function
|
|
Packit |
4aff17 |
reads the first 3 ints of the file and from that makes a guess at the file
|
|
Packit |
4aff17 |
type. In our case we would add:
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
if (buffer [0] == MAKE_MARKER ('W','A','C','K'))
|
|
Packit |
4aff17 |
return SF_FORMAT_WACK ;
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
The use of the MAKE_MARKER macro should be pretty obvious and it is defined at the
|
|
Packit |
4aff17 |
top of file should you need to have a look at it.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Step 5
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
Add a call to your open function from psf_open_file ().
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Edit src/sndfile.c and find the switch statement in psf_open_file (). It starts
|
|
Packit |
4aff17 |
like this:
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
switch (filetype)
|
|
Packit |
4aff17 |
{ case SF_FORMAT_WAV :
|
|
Packit |
4aff17 |
error = wav_open (psf) ;
|
|
Packit |
4aff17 |
break ;
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
case SF_FORMAT_AIFF :
|
|
Packit |
4aff17 |
error = aiff_open (psf) ;
|
|
Packit |
4aff17 |
break ;
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Towards the bottom of this switch statement your should add one for the new file
|
|
Packit |
4aff17 |
type. Something like:
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
case SF_FORMAT_WACK :
|
|
Packit |
4aff17 |
sf_errno = whacky_open (psf) ;
|
|
Packit |
4aff17 |
break ;
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Setp 6
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
Add prototypes for new open read and open write functions.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Edit src/common.h, go to the bottom of the file and add something like
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
int whacky_open (SF_PRIVATE *psf) ;
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Step 7
|
|
Packit |
4aff17 |
------
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Implement your open read function. The best way to do this is by coding
|
|
Packit |
4aff17 |
something much like one of the other file formats. The file src/au.c might be
|
|
Packit |
4aff17 |
a good place to start.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
In src/whacky.c you should now implement the function whacky_open() which
|
|
Packit |
4aff17 |
was prototyped in src/common.h. This function should return 0 on success and
|
|
Packit |
4aff17 |
a non-zero number on error.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
Error values are defined in src/common.h in a enum which starts at SFE_NO_ERROR.
|
|
Packit |
4aff17 |
When adding a new error value, you also need to add an error string to the
|
|
Packit |
4aff17 |
SndfileErrors array in src/sndfile.c.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
To parse the header of your new file type you should avoid using standard read/
|
|
Packit |
4aff17 |
write/seek functions (and the fread/fwrite/fseek etc) and instead use
|
|
Packit |
4aff17 |
psf_binheader_readf () which is implemented and documented in src/common.h.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
During the parsing process, you should also print logging information to
|
|
Packit |
4aff17 |
libsndfile's internal log buffer using the psf_log_printf() function.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
At the end of the open read process, you should have set a number of fields in the
|
|
Packit |
4aff17 |
SF_PRIVATE structure pointed to by psf.
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
|
|
Packit |
4aff17 |
*** THIS FILE IS INCOMPLETE ***
|