1
0
Fork
You've already forked ogg
0
Implements a reader for the Ogg container format.
  • Zig 100%
Find a file
2026年07月05日 13:41:49 -04:00
src flattened Page.Header into Page 2026年07月05日 13:35:59 -04:00
.gitignore initial commit with project boilerplate 2026年07月03日 18:14:11 -04:00
build.zig finalizing details for initial release 2026年07月05日 00:09:06 -04:00
build.zig.zon version bump to v1.1.0 2026年07月05日 13:41:49 -04:00
CHANGELOG.md version bump to v1.1.0 2026年07月05日 13:41:49 -04:00
LICENSE initial commit with project boilerplate 2026年07月03日 18:14:11 -04:00
README.md version bump to v1.1.0 2026年07月05日 13:41:49 -04:00

ogg

A zero-allocation, stream-oriented parser for structural Ogg containers. Fully implements the RFC-3533 specification.

Features

  • Zero Allocation: Operates entirely on stream cursors and user-provided stack/heap buffers.
  • PacketReader API: Streams logical packets, isolating their payloads into child Packet types, which are essentially bounded child-readers that implement a std.Io.Reader interface, but isolated only to the payload of the packet. This API is suitable for encodings that rely upon packet-based structures, such as Vorbis and Opus.
  • Reader API: Streams the data of the container as one continuous stream of bytes, transparently handling all pages, lacing values, and packets, implemented as a std.Io.Reader interface. This API is suitable for encodings that perform their own framing, such as Ogg/FLAC.
  • 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.
  • No AI/LLM Code: 100% of the code is both inspired and written by a human.

Installation

Add ogg to your build.zig.zon dependencies:

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

Expose the module in your build.zig:

constogg_dep=b.dependency("ogg",.{.target=target,.optimize=optimize,});exe.root_module.addImport("ogg",ogg_dep.module("ogg"));

Quick Start

PacketReader API

The PacketReader is an iterative reader that yields logical packets in the stream. A Packet is not actually read out of the stream ahead of time, nor require any allocation. It only logically creates the boundaries of the packet based on the Ogg pages encountered in the stream, which is completely transparent to the user.

conststd=@import("std");constogg=@import("ogg");pubfnmain(_:std.process.Init)!void{// Accepts any data source in a std.Io.Reader.vardata=@embedFile("filename.ogg");varreader:std.Io.Reader=.fixed(data);// Initialize the packet iteratorvarpacket_buffer:[4096]u8=undefined;varpacket_reader:ogg.PacketReader=.{.source=&reader,.buffer=&packet_buffer,};// Read packets in a loopwhile(trypacket_reader.next())|packet|{// Read packet as normal std.Io.Readerconstnumber=packet.reader.takeInt(u32,.big);constarray=packet.reader.takeArray(16);// The packet reader ensures that packets are fully consumed before// reading the next, but it hurts nothing to do so yourself._=trypacket.reader.discardRemaining();}}

Reader API

The Reader provides a basic "dumb" std.Io.Reader that views the Ogg stream as a contiguous stream of bytes that are being provided in a container. Packets pass through it seamlessly as pure data, the caller need not concern themselves when one packet begins and another ends, or when a new page boundary is crossed.

conststd=@import("std");constogg=@import("ogg");pubfnmain(_:std.process.Init)!void{// Accepts any data source in a std.Io.Reader.vardata=@embedFile("filename.ogg");varreader:std.Io.Reader=.fixed(data);// Initialize the Ogg readervarbuffer:[4096]u8=undefined;varogg_reader=ogg.Reader.init(&reader,&buffer);// Example scratch buffer for reading intovarread_buffer:[16384]u8=undefined;while(true){// Use interface field to access std.Io.Reader implementation.constn=tryogg_reader.interface.readSliceShort(&read_buffer);if(n<read_buffer.len)break;// Process data as contiguous stream of bytes for whatever you need}}

Seeking

The Ogg container itself does not implement any seek functionality, as this is dependent on the encoding of the data it contains, which implements its own logic.

That said, and regardless of which API you choose, each has a resync function implemented to synchronize the stream from an arbitrary offset in the reader. So whether you are picking up in the middle of a network stream or had to drop a corrupted packet, both APIs are capable of recovering and returning to a valid state.


License

This project is licensed under the MIT License.