https://github.com/jprjr/miniflac
Single-file FLAC decoder with a push-style API
https://github.com/jprjr/miniflac
audio c codec decoder flac minimal music single-header single-header-lib single-header-library sound tiny
Last synced: 3 months ago
JSON representation
Single-file FLAC decoder with a push-style API
- Host: GitHub
- URL: https://github.com/jprjr/miniflac
- Owner: jprjr
- License: 0bsd
- Created: 2021-07-02T18:19:46.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2025-02-16T16:22:33.000Z (4 months ago)
- Last Synced: 2025-03-18T21:54:46.607Z (3 months ago)
- Topics: audio, c, codec, decoder, flac, minimal, music, single-header, single-header-lib, single-header-library, sound, tiny
- Language: C
- Homepage:
- Size: 306 KB
- Stars: 31
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 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:
* [`STREAMINFO`](https://xiph.org/flac/format.html#metadata_block_streaminfo)
* [`VORBIS_COMMENT`](https://xiph.org/flac/format.html#metadata_block_vorbis_comment)
* [`PICTURE`](https://xiph.org/flac/format.html#metadata_block_picture)
* [`CUESHEET`](https://xiph.org/flac/format.html#metadata_block_cuesheet)
* [`SEEKTABLE`](https://xiph.org/flac/format.html#metadata_block_seektable)
* [`APPLICATION`](https://xiph.org/flac/format.html#metadata_block_application)## Future Improvements
* Speed optimizations
* Memory reduction## Usage
In one C file define `MINIFLAC_IMPLEMENTATION` before including `miniflac.h`.
```c
#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`:```c
#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).