Josh Green
2004-Sep-10 16:45 UTC
[Flac-dev] Developing SoundFont FLAC compressor using libFLAC
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
Josh Coalson
2004-Sep-10 16:45 UTC
[Flac-dev] Developing SoundFont FLAC compressor using libFLAC
--- Josh Green <jgreen@users.sourceforge.net> wrote:> 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. > > ... > > 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 :)Have you seen the API changes in 1.0.3? Now all metadata is parsed and at each decoder layer you can specify which blocks get passed up to the metadata callback. See the *_decoder_set_metadata_respond/ignore functions. Also, on the encoder size, you can now pass a list of arbitrary metadata blocks to encode, instead of just padding and seektable.> 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!It's on my TODO list but kind of far down :) If you want to have a crack at it and send me a patch that's fine also. The decoders should be OK, there's just some extra logic that would have to be peppered around the stream encoder. Josh __________________________________________________ Do You Yahoo!? Yahoo! Autos - Get free new car price quotes http://autos.yahoo.com
Josh Green
2004-Sep-10 16:45 UTC
[Flac-dev] Developing SoundFont FLAC compressor using libFLAC
On Wed, 2002-07-17 at 15:34, Josh Coalson wrote:> > Have you seen the API changes in 1.0.3? Now all metadata is > parsed and at each decoder layer you can specify which blocks > get passed up to the metadata callback. See the > *_decoder_set_metadata_respond/ignore functions. > > Also, on the encoder size, you can now pass a list of arbitrary > metadata blocks to encode, instead of just padding and seektable. >Rock on! No, I missed the fact that 1.0.3 has been released :)> > 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! > > It's on my TODO list but kind of far down :) If you want to > have a crack at it and send me a patch that's fine also. The > decoders should be OK, there's just some extra logic that > would have to be peppered around the stream encoder. >Yeah, no problem. FLAC gives a nice decrease in size as is and adding this kind of support wouldn't break the SF-FLAC format in the future.> Josh >I'll let the list know when SF-FLAC is finished, should anyone be interested. I'm considering starting a FREE SoundFont compressor campaign, so users will stop using SoundFont encoders that aren't available on platforms such as Linux. This would also pressure some of the existing formats to release Linux versions. In order to do this I need to program a stand alone compressor/de-compressor utility that can work in Windows, OSX, etc. So I will probably working to get libFLAC to compile with MingW32 (has this been tried?) Cheers! Josh Green