Skip to content
/ miniflac Public

Single-file FLAC decoder with a push-style API

License

Notifications You must be signed in to change notification settings

jprjr/miniflac

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

66 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

miniflac

A single-file C library for decoding FLAC streams. Does not use any C library functions, does not allocate any memory.

Features

  • push-style API or pull-style API
  • does not allocate memory or use any c library functions
  • handles native FLAC as well as Ogg FLAC
  • supports Ogg files with multiple bitstreams (only decodes the first FLAC bitstream)
  • supports chained ogg files, including chained multi-bitstream files
  • single C file
  • metadata decoding for:

Future Improvements

  • Speed optimizations
  • Memory reduction

Usage

In one C file define MINIFLAC_IMPLEMENTATION before including miniflac.h.

#define MINIFLAC_IMPLEMENTATION
#include "miniflac.h"

Push-style API

To use the push-style API, allocate a miniflac_t struct, call miniflac_init to initialize the struct, and use functions prefixed with miniflac_.

All functions follow a similar paradigm - you provide a buffer of data, the length of the buffer, and an out-variable to record the amount of data consumed. If more bytes are needed, functions return MINIFLAC_CONTINUE. You can loop around these functions until they return something other than MINIFLAC_CONTINUE.

miniflac_sync will read data until it parses a metadata header or audio frame header. You can inspect the struct to determine if you're in a metadata block or audio frame, and respond accordingly.

miniflac_decode will read data until it's decoded an audio frame. You can check the size of the audio frame by inspecting the frame.header struct.

See the example programs under the examples directory.

Pull-style API

To use the pull-style API, allocate a mflac_t struct, call mflac_init with your data-reading callback and userdata, then use functions prefixed with mflac_t

All the pull-style functions follow a similar style - you call the function with any needed out-variables. If you're out of data, the functions will return MFLAC_EOF, otherwise they should return MFLAC_OK or MFLAC_METADATA_END (in the case of an iterator-type function). Any other result can be cast into a MINIFLAC_RESULT enum.

Using the pull-style API is similar to the push - you call mflac_sync, which will read data using your callback until it parses a metadata header or audio frame header. You inspect the struct to determine the kind of block, or use the convenience status functions (mflac_is_metadata, mflac_is_frame, etc).

See the example program basic-decoder-mflac in the examples directory.

Tips

It's possible to build the library using the individual sources and headers under the /src directory. Essentially, flac.h functions similarly as miniflac.h.

Because of this, some functions aren't inlined, you can get a considerable speed improvement by overriding the MINIFLAC_API and MINIFLAC_PRIVATE defines, and set MINIFLAC_PRIVATE to static inline:

#define MINIFLAC_IMPLEMENTATION
#define MINIFLAC_API
#define MINIFLAC_PRIVATE static inline
#include "miniflac.h"

On my tests, this results in about a 4x speed improvement.

Details

miniflac offers a "push-style" interface. After initializing the decoder, you give it a chunk of data. It will consume some amount of data (not necessarily all) and decode audio. You'll need to keep track of how much data was consumed, and hold on to any un-consumed bytes for the next function call.

There's no callbacks involved, and you can provide as little as one byte at a time.

This library does not perform any data allocations, everything can be statically allocated if you like. A library user will need to provide a buffer for writing decoded audio samples. FLAC supports up to 8 channels of audio, and up to 65535 samples per frame of audio, so the maximum required audio buffer is:

(8 channels) * (65535 samples) * (4 bytes/sample) = 2097120 bytes

In practice you often need less, most FLAC files are in the "streamable" subset, which limits the frame size to 16384 samples, or 4608 samples if the sample rate is <= 48kHz, and probably only 2 channels.

LICENSE

BSD Zero Clause (see the LICENSE file).