v2 / vlib / encoding / vorbis / vorbis.c.v
252 lines · 219 sloc · 13.67 KB · 8287d5dd97821042e05ac55803af906c9276825c
Raw
1// Copyright (c) 2025 Delyan Angelov. All rights reserved. Use of this source code
2// is governed by an MIT license that can be found in the LICENSE file.
3module vorbis
4
5#flag -I @VEXEROOT/thirdparty/stb_vorbis
6#flag @VEXEROOT/thirdparty/stb_vorbis/stb_vorbis.o
7#include "stb_vorbis.h"
8
9@[typedef]
10pub struct C.stb_vorbis_alloc {
11pub mut:
12 alloc_buffer &char
13 alloc_buffer_length_in_bytes i32
14}
15
16@[typedef]
17pub struct C.stb_vorbis {}
18
19@[typedef]
20pub struct C.stb_vorbis_info {
21pub mut:
22 sample_rate u32
23 channels i32
24 setup_memory_required u32
25 setup_temp_memory_required u32
26 max_frame_size i32
27}
28
29@[typedef]
30struct C.stb_vorbis_comment {
31pub mut:
32 vendor &char
33 comment_list_length i32
34 comment_list &&char
35}
36
37pub enum VorbisErrorCode {
38 no_error
39 need_more_data = 1 // not a real error
40 invalid_api_mixing // can not mix API modes
41 out_of_memory // not enough memory
42 not_supported // uses floor 0
43 too_many_channels // STB_VORBIS_MAX_CHANNELS is too small
44 file_open_failure // fopen() failed
45 seek_without_length // can't seek in unknown-length file
46 unexpected_eof = 10 // file is truncated?
47 seek_invalid // seek past EOF
48 vorbis_invalid_setup = 20 // vorbis decoding error (corrupt/invalid stream)
49 vorbis_invalid_stream // vorbis decoding error
50 ogg_missing_capture_pattern = 30
51 ogg_invalid_stream_structure_version
52 ogg_continued_packet_flag_invalid
53 ogg_incorrect_stream_serial_number
54 ogg_invalid_first_page
55 ogg_bad_packet_type
56 ogg_cant_find_last_page
57 ogg_seek_failed
58 ogg_skeleton_not_supported
59}
60
61// stb_vorbis_get_info retrieve general information about the file
62pub fn C.stb_vorbis_get_info(f &C.stb_vorbis) C.stb_vorbis_info
63
64// stb_vorbis_get_comment retrieve ogg comments
65pub fn C.stb_vorbis_get_comment(f &C.stb_vorbis) C.stb_vorbis_comment
66
67// stb_vorbis_get_error return the last detected error (and clears it too)
68pub fn C.stb_vorbis_get_error(f &C.stb_vorbis) VorbisErrorCode
69
70// stb_vorbis_close closes an ogg vorbis file and frees all the memory used for it
71pub fn C.stb_vorbis_close(f &C.stb_vorbis)
72
73// stb_vorbis_get_sample_offset returns the offset in samples, from the start of the file,
74// that will be returned by the next decode, if it is known or -1 otherwise.
75// NOTE: NOT WORKING YET after a seek with PULLDATA API
76pub fn C.stb_vorbis_get_sample_offset(f &C.stb_vorbis) i32
77
78// stb_vorbis_get_file_offset returns the current seek point within the file, or offset
79// from the beginning of the memory buffer. In pushdata mode it returns 0.
80pub fn C.stb_vorbis_get_file_offset(f &C.stb_vorbis) u32
81
82// stb_vorbis_open_pushdata create a vorbis decoder by passing in the initial data block
83// containing the ogg&vorbis headers (you don't need to do parse them, just provide
84// the first N bytes of the file--you're told if it's not enough, see below)
85// on success, returns an stb_vorbis *, does not set error, returns the amount of
86// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
87// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
88// if returns NULL and *error is VORBIS_need_more_data, then the input block was
89// incomplete and you need to pass in a larger block from the start of the file
90pub fn C.stb_vorbis_open_pushdata(const_datablock &u8, datablock_length_in_bytes i32, datablock_memory_consumed_in_bytes &i32, xerror &VorbisErrorCode, const_alloc_buffer &C.stb_vorbis_alloc) &C.stb_vorbis
91
92// stb_vorbis_decode_frame_pushdata decode a frame of audio sample data if possible from the passed-in data block
93// Returns the number of bytes we used from `const_datablock`.
94// possible cases:
95// 0 bytes used, 0 samples output (need more data)
96// N bytes used, 0 samples output (resynching the stream, keep going)
97// N bytes used, M samples output (one frame of data)
98// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
99// frame, because Vorbis always "discards" the first frame.
100//
101// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
102// instead only datablock_length_in_bytes-3 or less. This is because it wants
103// to avoid missing parts of a page header if they cross a datablock boundary,
104// without writing state-machiney code to record a partial detection.
105//
106// The number of channels returned are stored in *channels (which can be
107// NULL -- it is always the same as the number of channels reported by
108// get_info). *output will contain an array of float* buffers, one per
109// channel. In other words, (*output)[0][0] contains the first sample from
110// the first channel, and (*output)[1][0] contains the first sample from
111// the second channel.
112//
113// *output points into stb_vorbis's internal output buffer storage; these
114// buffers are owned by stb_vorbis and application code should not free
115// them or modify their contents. They are transient and will be overwritten
116// once you ask for more data to get decoded, so be sure to grab any data
117// you need before then.
118// `channels` is a place to write number of float * buffers
119// `output` is a place to write float ** array of float * buffers
120// `samples` is a place to write number of output samples
121pub fn C.stb_vorbis_decode_frame_pushdata(f &C.stb_vorbis, const_datablock &u8, datablock_length_in_bytes i32, channels &i32, output &&&f32, samples &i32) i32
122
123// stb_vorbis_flush_pushdata inform stb_vorbis that your next datablock will not be contiguous with
124// previous ones (e.g. you've seeked in the data); future attempts to decode
125// frames will cause stb_vorbis to resynchronize (as noted above), and
126// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
127// will begin decoding the _next_ frame.
128// If you want to seek using pushdata, you need to seek in your file, then
129// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
130// decoding is returning you data, call stb_vorbis_get_sample_offset, and
131// if you don't like the result, seek your file again and repeat.
132pub fn C.stb_vorbis_flush_pushdata(f &C.stb_vorbis)
133
134// stb_vorbis_decode_filename assumes stb_vorbis is allowed to pull data
135// from a source: either a block of memory containing the _entire_ vorbis stream,
136// or a &C.FILE that you or it create, or possibly some other reading mechanism
137// if you go modify the source to replace the &C.FILE case with some kind
138// of callback to your code. (But if you don't support seeking, you may
139// just want to go ahead and use pushdata.)
140// The return value is the number of samples decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
141// When you're done with it, just C.free() the pointer returned in *output.
142pub fn C.stb_vorbis_decode_filename(const_filename &char, channels &i32, sample_rate &i32, output &&i16) i32
143
144// stb_vorbis_decode_memory decodes an entire file and output the data interleaved
145// into a malloc()ed buffer stored in *output.
146// The return value is the number of samples decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
147// When you're done with it, just C.free() the pointer returned in *output.
148pub fn C.stb_vorbis_decode_memory(const_mem &u8, len i32, channels &i32, sample_rate &i32, output &&i16) i32
149
150// stb_vorbis_open_memory creates an ogg vorbis decoder from an ogg vorbis stream
151// in memory (note this must be the entire stream!).
152// On failure, returns NULL and sets *error
153pub fn C.stb_vorbis_open_memory(const_data &u8, len i32, xerror &VorbisErrorCode, const_alloc_buffer &C.stb_vorbis_alloc) &C.stb_vorbis
154
155// stb_vorbis_open_filename creates an ogg vorbis decoder from a filename via fopen().
156// On failure, returns NULL and sets *error (possibly to VORBIS_file_open_failure).
157pub fn C.stb_vorbis_open_filename(const_filename &char, xerror &VorbisErrorCode, const_alloc_buffer &C.stb_vorbis_alloc) &C.stb_vorbis
158
159// stb_vorbis_open_file creates an ogg vorbis decoder from an open &C.FILE,
160// looking for a stream at the _current_ seek point (ftell).
161// On failure, returns NULL and sets *error.
162// Note: stb_vorbis must "own" this stream; if you seek it in between
163// calls to stb_vorbis, it will become confused. Moreover, if you attempt to
164// perform stb_vorbis_seek_*() operations on this file, it will assume it
165// owns the _entire_ rest of the file after the start point. Use the next
166// function, stb_vorbis_open_file_section(), to limit it.
167pub fn C.stb_vorbis_open_file(f &C.FILE, close_handle_on_close i32, xerror &VorbisErrorCode, const_alloc_buffer &C.stb_vorbis_alloc) &C.stb_vorbis
168
169// stb_vorbis_open_file_section creates an ogg vorbis decoder from an open &C.FILE,
170// looking for a stream at the _current_ seek point (ftell).
171// The stream will be of length 'len' bytes.
172// On failure, returns NULL and sets *error.
173// Note: stb_vorbis must "own" this stream; if you seek it in between calls to stb_vorbis,
174// it will become confused.
175pub fn C.stb_vorbis_open_file_section(f &C.FILE, close_handle_on_close i32, xerror &VorbisErrorCode, const_alloc_buffer &C.stb_vorbis_alloc, len u32) &C.stb_vorbis
176
177// stb_vorbis_seek_frame seeks in the Vorbis file to (approximately) 'sample_number'.
178// After calling seek_frame(), the next call to get_frame_*() will include
179// the specified sample.
180pub fn C.stb_vorbis_seek_frame(f &C.stb_vorbis, sample_number u32) i32
181
182// stb_vorbis_seek seeks in the Vorbis file to (approximately) 'sample_number'.
183// After calling stb_vorbis_seek(), the next call to stb_vorbis_get_samples_*
184// will start with the specified sample. If you do not need to seek to EXACTLY
185// the target sample when using get_samples_*, you can also use seek_frame().
186pub fn C.stb_vorbis_seek(f &C.stb_vorbis, sample_number u32) i32
187
188// stb_vorbis_seek_start is equivalent to stb_vorbis_seek(f,0)
189pub fn C.stb_vorbis_seek_start(f &C.stb_vorbis) i32
190
191// stb_vorbis_stream_length_in_samples returns the total length of the vorbis stream in samples
192pub fn C.stb_vorbis_stream_length_in_samples(f &C.stb_vorbis) u32
193
194// stb_vorbis_stream_length_in_seconds returns the total length of the vorbis stream in seconds
195pub fn C.stb_vorbis_stream_length_in_seconds(f &C.stb_vorbis) f32
196
197// stb_vorbis_get_frame_float decodes the next frame and returns the number of samples.
198// The number of channels returned are stored in *channels (which can be NULL;
199// it is always the same as the number of channels reported by get_info).
200// `*output` will contain an array of float* buffers, one per channel.
201// These outputs will be overwritten on the next call to stb_vorbis_get_frame_*.
202// You generally should not intermix calls to stb_vorbis_get_frame_*()
203// and stb_vorbis_get_samples_*(), since the latter calls the former.
204pub fn C.stb_vorbis_get_frame_float(f &C.stb_vorbis, channels &i32, output &&&f32) i32
205
206// stb_vorbis_get_frame_short_interleaved decodes the next frame and returns the number
207// of *samples* per channel.
208// Note that for interleaved data, you pass in the number of shorts (the
209// size of your array), but the return value is the number of samples per
210// channel, not the total number of samples.//
211// The data is coerced to the number of channels you request according to the
212// channel coercion rules (see below). You must pass in the size of your
213// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
214// The maximum buffer size needed can be gotten from get_info(); however,
215// the Vorbis I specification implies an absolute maximum of 4096 samples
216// per channel.
217// Channel coercion rules:
218// Let M be the number of channels requested, and N the number of channels present,
219// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
220// and stereo R be the sum of all R and center channels (channel assignment from the
221// vorbis spec).
222// M N output
223// 1 k sum(Ck) for all k
224// 2 * stereo L, stereo R
225// k l k > l, the first l channels, then 0s
226// k l k <= l, the first k channels
227// Note that this is not _good_ surround etc. mixing at all! It's just so
228// you get something useful.
229pub fn C.stb_vorbis_get_frame_short_interleaved(f &C.stb_vorbis, num_c i32, buffer &i16, num_shorts i32) i32
230
231// stb_vorbis_get_frame_short similar to stb_vorbis_get_frame_short_interleaved, but without interleaving.
232pub fn C.stb_vorbis_get_frame_short(f &C.stb_vorbis, num_c i32, buffer &&i16, num_samples i32) i32
233
234// stb_vorbis_get_samples_float_interleaved gets num_floats, not necessarily on a frame boundary.
235// This requires buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
236// Returns the number of samples stored per channel; it may be less than requested
237// at the end of the file. If there are no more samples in the file, returns 0.
238pub fn C.stb_vorbis_get_samples_float_interleaved(f &C.stb_vorbis, channels i32, buffer &f32, num_floats i32) i32
239
240// stb_vorbis_get_samples_float gets num_samples samples, not necessarily on a frame boundary.
241// See also stb_vorbis_get_samples_float_interleaved.
242pub fn C.stb_vorbis_get_samples_float(f &C.stb_vorbis, channels i32, buffer &&f32, num_samples i32) i32
243
244// stb_vorbis_get_samples_short_interleaved gets num_samples samples, not necessarily on a frame boundary.
245// This requires buffering so you have to supply the buffers. Applies the coercion rules above
246// to produce 'channels' channels. Returns the number of samples stored per channel;
247// it may be less than requested at the end of the file. If there are no more
248// samples in the file, returns 0.
249pub fn C.stb_vorbis_get_samples_short_interleaved(f &C.stb_vorbis, channels i32, buffer &i16, num_shorts i32) i32
250
251// stb_vorbis_get_samples_short is similar to stb_vorbis_get_samples_short_interleaved .
252pub fn C.stb_vorbis_get_samples_short(f &C.stb_vorbis, channels i32, buffer &&i16, num_samples i32) i32
253