1
0
Fork
You've already forked riff
0
Implements reading Resource Interchange File Format (RIFF) containers, including classic RIFF, RIFX, RF64, AIFF, and W64.
  • Zig 100%
Find a file
2026年07月03日 15:20:43 -04:00
src marked InitError as public 2026年07月03日 14:52:31 -04:00
tests added test files and updated root with public types 2026年06月25日 00:45:40 -04:00
.gitignore initial commit with project boilerplate 2026年06月22日 13:40:16 -04:00
build.zig removed unused lib artifact from build.zig 2026年07月03日 14:55:31 -04:00
build.zig.zon initial commit with project boilerplate 2026年06月22日 13:40:16 -04:00
CHANGELOG.md fixed date in CHANGELOG 2026年07月03日 15:20:43 -04:00
LICENSE added LICENSE and README 2026年06月24日 23:57:29 -04:00
README.md updated README to reflect 2.0 changes 2026年07月03日 14:53:42 -04:00

riff

A zero-allocation, stream-oriented parser for structural multimedia containers. It provides a generic, un-opinionated engine to safely traverse and isolate chunk layouts across the RIFF/IFF file ecosystem without loading entire payloads into memory.

Features

  • Zero Allocation: Operates entirely on stream cursors and user-provided stack/heap buffers.
  • Format Agnostic: Treats layout symmetrically across Big-Endian and Little-Endian boundaries.
  • Clean Domain Separation: Focuses exclusively on file structure layout; interpreting data schemas (like audio decoding or text metadata parsing) is completely deferred to your application logic.

Supported Container Formats

The library handles all structural variations of the classic Interchange File Format (IFF) architecture:

Format / Profile Endianness Common Target Extensions
RIFF Little-Endian .wav, .avi, .webp
RIFX Big-Endian .wav (Big-Endian variant)
RF64 Little-Endian .wav (EBU standard for files > 4GB)
FORM Big-Endian .aif, .aiff, .iff
WAVE64 Little-Endian .w64 (Sony standard for files > 4GB)

Installation

Add riff to your build.zig.zon dependencies:

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

Expose the module in your build.zig:

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

Quick Start

The core workflow involves initializing a Demuxer on an active stream, iterating through top-level chunks, and cleanly spawning a sub-isolated List type when a nested collection container is encountered.

conststd=@import("std");constriff=@import("riff");pubfnmain(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.wav",.{});deferfile.close(io);varfile_buffer:[4096]u8=undefined;varreader=file.reader(io,&file_buffer);// Initialize the demuxer to read the chunks of the containervarbuffer:[4096]u8=undefined;vardemuxer=tryriff.Demuxer.init(&reader.interface,&buffer);// Iterate the chunks of the containerwhile(trydemuxer.next())|chunk|{// Print child chunkstd.debug.print("{f}\n",.{chunk.id});// Process chunkvarlimited:Reader.Limited=chunk.payload(reader,&.{});// TODO: Process chunk payload// Ensure chunk is fully consumed, leaving reader aligned to next chunk_=trylimited.interface.discardRemaining();tryreader.discardAll(chunk.padding);}}

API Reference

Demuxer

The top-level stream coordinator. It reads the file header to establish the byte-ordering flavor and acts as a layout engine over the root chunks.

  • pub fn init(reader: *std.Io.Reader, buffer: []u8) !Demuxer
    Initializes the parser from any active std.Io.Reader interface. Parses the root magic header (RIFF, FORM, etc.) to self-configure.
  • pub fn next(self: *Demuxer) !?Chunk
    Advances the stream cursor to the next valid chunk header. Returns null when the stream is exhausted.

License

This project is licensed under the MIT License.