1
1
Fork
You've already forked qoa
0
Provdies zero-allocation, stream-oriented decoder for the QOA (Quite Okay Audio Format).
  • Zig 100%
Find a file
2026年06月25日 02:03:14 -04:00
src exposed public API and referenced tests 2026年06月25日 01:51:18 -04:00
tests added test files 2026年06月25日 01:00:45 -04:00
.gitignore initial commit with project boilerplate 2026年06月22日 04:20:12 -04:00
build.zig added test files 2026年06月25日 01:00:45 -04:00
build.zig.zon initial commit with project boilerplate 2026年06月22日 04:20:12 -04:00
README.md added links to QOA homepage 2026年06月25日 02:03:14 -04:00

qoa

A zero-allocation, stream-oriented implementation of the Quite OK Audio Format (QOA) decoder written in pure Zig.

This decoder uses compile-time parameters to scale its static internal cache size, completely eliminating the need for runtime memory allocation. It decodes audio packages straight from any underlying stream directly into a user-supplied frame buffer.

Features

  • Zero Allocation: Completely bypasses the allocator pattern; operates entirely via stack or static inline allocation.
  • Predictable Memory Footprint: Buffer scaling is configured at compile time based on channel requirements (~5 kB memory footprint per supported channel).
  • Interleaved Layout Output: Yields native i16 multi-channel interleaved signed PCM blocks ready to be dropped into an audio device ring buffer.

Installation

Add qoa to your build.zig.zon dependencies:

.dependencies=.{.qoa=.{.url="https://codeberg.org/audiophile/qoa/archive/v1.0.0.tar.gz",// .hash = "...",},},

Expose the module in your build.zig:

constqoa=b.dependency("qoa",.{.target=target,.optimize=optimize,});exe.root_module.addImport("qoa",qoa.module("qoa"));

Quick Start

conststd=@import("std");constqoa=@import("qoa");fnmain(init:std.process.Init)!void{// Boilerplate to open a file and initialize/cleanup its readerconstio=init.io;constcwd=std.Io.Dir.cwd();constfile=trycwd.openFile(io,"filename.qoa",.{});deferfile.close(io);varfile_buffer:[4096]u8=undefined;varreader=file.reader(io,&file_buffer);// Initialize decodervarsample_buffer:[2048]i16=undefined;vardecoder=tryqoa.Decoder(2).init(&reader.interface);// Read PCM sampleswhile(true){constsamples=trydecoder.read(&sample_buffer);// Do whatever you need with samplesif(samples.len<sample_buffer.len)break;}}

API Reference

Decoder(max_channels: comptime_int) type

A compile-time type generator that constructs an optimization-tuned QOA parsing instance.

  • Parameters:
    • max_channels: The maximum number of channels the decoder instance will support (valid range: 1 to 8).
  • Memory Bounds: The internal decoding cache scales statically based on this value, increasing the instance struct size by approximately 5 kB for each supported channel.
// Generates a decoder type optimized strictly for Stereo (2-channel) streamsconstStereoDecoder=qoa.Decoder(2);

pub fn read(self: *Decoder, buffer: []i16) DecodeError![]i16

Decodes interleaved signed 16-bit integer PCM samples directly into the provided slice.

The engine steps through the compressed source stream, handles slice limits safely, and populates the destination buffer up to its absolute sample frame capacity.

  • Parameters:
    • buffer: The destination slice to receive the uncompressed audio frames.
  • Returns: A sub-slice of the user-provided buffer, trimmed to point precisely at the valid multi-channel samples successfully written during the operation. Returns an empty slice &.{} when the file or stream bounds are reached.

License

This project is licensed under the MIT License.