diff options
Diffstat (limited to 'src/sf.zig')
-rw-r--r-- | src/sf.zig | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/sf.zig b/src/sf.zig new file mode 100644 index 0000000..d38446c --- /dev/null +++ b/src/sf.zig @@ -0,0 +1,94 @@ +// libsndfile wrapper +// Copyright (C) 2021 Nguyễn Gia Phong +// +// This file is part of zeal. +// +// Zeal is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Zeal is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with zeal. If not, see <https://www.gnu.org/licenses/>. + +const Allocator = @import("std").mem.Allocator; + +usingnamespace @cImport(@cInclude("sndfile.h")); + +pub const Mode = enum { + read, + write, + read_write, +}; + +pub const Error = error { + UnrecognizedFormat, + SystemError, + MalformedFile, + UnsupportedEncoding, +}; + +pub const SndFile = struct { + pimpl: *SNDFILE, + frames: usize, + sample_rate: c_int, + channels: c_int, + format: c_int, + sections: c_int, + seekable: bool, + + /// Open the sound file at the specified path. + pub fn open(path: [:0]const u8, mode: Mode) Error!SndFile { + const c_mode = switch (mode) { + .read => SFM_READ, + .write => SFM_WRITE, + .read_write => SFM_RDWR, + }; + + var info: SF_INFO = undefined; + const pimpl = sf_open(path.ptr, c_mode, &info); + return SndFile { + .pimpl = pimpl orelse return switch (sf_error(null)) { + SF_ERR_UNRECOGNISED_FORMAT => Error.UnrecognizedFormat, + SF_ERR_SYSTEM => Error.SystemError, + SF_ERR_MALFORMED_FILE => Error.MalformedFile, + SF_ERR_UNSUPPORTED_ENCODING => Error.UnsupportedEncoding, + else => unreachable, + }, + .frames = @intCast(usize, info.frames), + .sample_rate = info.samplerate, + .channels = info.channels, + .format = info.format, + .sections = info.sections, + .seekable = if (info.seekable == 0) false else true, + }; + } + + /// Read the requested number of frames. + /// The returned memory is managed by the caller. + pub fn read(self: SndFile, allocator: *Allocator, + frames: usize) Allocator.Error![]const i16 { + const items = frames * @intCast(usize, self.channels); + const memory = try allocator.alloc(i16, items); + const n = sf_read_short(self.pimpl, memory.ptr, @intCast(i64, items)); + return try allocator.realloc(memory, @intCast(usize, n)); + } + + /// Read the entire file. The returned memory is managed by the caller. + pub fn readAll(self: SndFile, + allocator: *Allocator) Allocator.Error![]const i16 { + return self.read(allocator, self.frames); + } + + /// Close the file and deallocate its internal buffers. + /// Like std.os.close, this function does not return + /// any indication of failure. + pub fn close(self: SndFile) void { + _ = sf_close(self.pimpl); + } +}; |