Blame doc/new_file_type.HOWTO

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 ***