media: Format description struct, stubs for more formats
This commit is contained in:
@@ -1,8 +1,27 @@
|
||||
const std = @import("std");
|
||||
|
||||
const Format = @import("Format.zig");
|
||||
|
||||
const format: Format = .{
|
||||
.magic_length = magic.len,
|
||||
// 4B - sample count
|
||||
// 1B - channels
|
||||
// 3B - sample rate
|
||||
.info_length = magic.len + 8,
|
||||
.extension = "qoa",
|
||||
.media_type = "audio/qoa",
|
||||
.isFormat = isQoa,
|
||||
};
|
||||
|
||||
const magic = "qoaf";
|
||||
|
||||
const Header = union(enum) {
|
||||
streaming: HeaderStreaming,
|
||||
static: HeaderStatic,
|
||||
|
||||
pub fn initStatic(static: HeaderStatic) Header {
|
||||
return .{ .static = static };
|
||||
}
|
||||
};
|
||||
|
||||
const HeaderStreaming = void;
|
||||
@@ -19,30 +38,38 @@ const HeaderStatic = struct {
|
||||
}
|
||||
};
|
||||
|
||||
/// The caller asserts that the buffer is at least 12 bytes long, which can
|
||||
/// contain the entirety of a QOA file header and the relevant information in
|
||||
/// the first frame header.
|
||||
pub fn info(buffer: []const u8) ?Header {
|
||||
std.debug.assert(buffer.len >= 12);
|
||||
/// The caller asserts that the buffer is at least `format.magic_length` bytes
|
||||
/// long.
|
||||
pub fn isQoa(buffer: []const u8) bool {
|
||||
return std.mem.eql(u8, buffer[0..format.magic_length], magic);
|
||||
}
|
||||
|
||||
/// The caller asserts that the buffer is at least `format.info_length` bytes
|
||||
/// long.
|
||||
pub fn info(buffer: []const u8) ?Header {
|
||||
std.debug.assert(buffer.len >= format.info_length);
|
||||
|
||||
if (!isQoa(buffer)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const magic = buffer[0..4];
|
||||
const samples = std.mem.readInt(u32, buffer[4..8], .big);
|
||||
const channels = buffer[8];
|
||||
const sample_rate = std.mem.readInt(u24, buffer[9..12], .big);
|
||||
|
||||
if (!std.mem.eql(u8, magic, "qoaf") or channels == 0 or channels > 8 or sample_rate == 0) {
|
||||
if (channels == 0 or channels > 8 or
|
||||
sample_rate == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (samples == 0) {
|
||||
return .streaming;
|
||||
} else {
|
||||
return .{
|
||||
.static = .{
|
||||
.samples = samples,
|
||||
.channels = channels,
|
||||
.sample_rate = sample_rate,
|
||||
},
|
||||
};
|
||||
return .initStatic(.{
|
||||
.samples = samples,
|
||||
.channels = channels,
|
||||
.sample_rate = sample_rate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user