[Flac-dev] Developing SoundFont FLAC compressor using libFLAC

Josh Green jgreen at users.sourceforge.net
Wed Jul 17 12:17:05 PDT 2002


Its been a while since I was discussing a SoundFont compressor based on
FLAC. I've recently implemented the compressor using an application
metadata block with the ID 'SFFL' that I registered, which contains my
own header and a block of zlib (gzip) compressed SoundFont info. The
audio chunk (a block of consecutive 16 bit signed samples separated by
46 zero samples) is then encoded with FLAC. For the most part using
libFLAC has been fairly straight forward. But I find the handling of
metadata lacking in functionality, although I could be overlooking
something. I admit I'm a bit lazy in not wanting to implement my own
metadata processing routines, although I will do this if there is no
other means. 

On the encoder side I have resorted to manually writing the application
metadata header (pretty easy actually, since its just a big endian
uint32). Writing the StreamMetaData poses a bigger pain though.
Thankfully these were the only 2 problems I had (right now I just don't
write the StreamMetaData, which I would like to in the future). 

Unfortunately the decoder has given me the most trouble (also related to
metadata). It appears that all the variations of decoders (stream,
seekable-stream and file) don't handle application metadata. Looking at
the code it seems it is just skipped over
(stream_decoder_read_metadata_). In my case I could probably just use
the file decoder, except it is impossible to get the application
metadata or even a file descriptor. 

My proposal for libFLAC is to provide a couple functions, something like
these: 

/* 
* Saves a metadata header to a buffer which is suitable for 
* writing to a FLAC stream. 
* 
* Returns: A buffer with the encoded metadata header or NULL on error, 
*   Buffer should be freed when finished with. 
*/ 
FLAC__byte *FLAC__metadata_to_stream (FLAC__StreamMetaData *metadata); 


/* 
* Parses a metadata header byte stream and populates the passed 
* 'metadata' structure. If 'header_size' is not NULL then the size of 
* the parsed header is stored there. 
* 
* Returns: TRUE on success, FALSE if metadata_stream does not contain a 
* valid metadata header. 
*/ 
FLAC__bool FLAC__metadata_parse_stream (FLAC__byte *metadata_stream, 
FLAC__StreamMetaData *metadata, unsigned *header_size); 



For the decoder a way to get application metadata via the metadata
callback would be nice. The way I see this being implemented would be to
have libFLAC parse the header up to (and including) the application ID
and then give control to the user's metadata callback. A function would
then be provided that would allow the user to read the variable length
data following the header (for application or padding metadata). libFLAC
would keep some state data about the current metadata block being
processed and how much variable length data is left. The metadata read
function would do some error checking in regards to how much data is
left, etc and if the user doesn't read all the data it is automatically
skipped apon return from the metadata callback. 

/* 
* Read variable length data following application metadata blocks from 
* the metadata callback. 'bytes' is the amount of data to read which 
* might be updated if less data is available. 'buffer' should contain 
* enough space for the requested amount of data. This function can be 
* called multiple times to retrieve the data in blocks. Returning from 
* the metadata callback without reading all the data will cause it to 
* be skipped. 
* 
* Returns: TRUE on success, FALSE on error 
*/ 
FLAC__bool FLAC__stream_decoder_read_metadata (FLAC__StreamDecoder
*decoder, FLAC__byte buffer[], unsigned *bytes) 


One of these functions for each decoder type would be cool. 

Anyways, what do you think of my proposal? Besides the metadata stuff,
libFLAC has been really nice to work with, and theres nothing like
getting a 128MB SoundFont down to 67MB :) 

BTW any plans yet for allowing changing of audio parameters while
encoding. I think this would give a significant increase in compression
for some SoundFonts because the SoundFont sample chunk is multiple
consecutive samples and stereo pairs can be determined from the
SoundFont information. Cheers! 
Josh Green





More information about the Flac-dev mailing list