package vendor:stb/vorbis

Types

Error ¶

Error :: enum i32 {
	none                             = 0, 
	need_more_data                   = 1,  // not a real error
	invalid_api_mixing,                    // can't mix API modes
	outofmem,                              // not enough memory
	feature_not_supported,                 // uses floor 0
	too_many_channels,                     // MAX_CHANNELS is too small
	file_open_failure,                     // fopen() failed
	seek_without_length,                   // can't seek in unknown-length file
	unexpected_eof                   = 10, // file is truncated?
	seek_invalid,                          // seek past EOF
	// vorbis errors:
	invalid_setup                    = 20, 
	invalid_stream, 
	// ogg errors:
	missing_capture_pattern          = 30, 
	invalid_stream_structure_version, 
	continued_packet_flag_invalid, 
	incorrect_stream_serial_number, 
	invalid_first_page, 
	bad_packet_type, 
	cant_find_last_page, 
	seek_failed, 
	ogg_skeleton_not_supported, 
}

vorbis ¶

vorbis :: struct($Key: typeid, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {}

vorbis_alloc ¶

vorbis_alloc :: struct {
	alloc_buffer:                 [^]u8,
	alloc_buffer_length_in_bytes: i32,
}

vorbis_comment ¶

vorbis_comment :: struct {
	vendor:              cstring,
	comment_list_length: i32,
	comment_list:        [^]cstring,
}

vorbis_info ¶

vorbis_info :: struct {
	sample_rate:                u32,
	channels:                   i32,
	setup_memory_required:      u32,
	setup_temp_memory_required: u32,
	temp_memory_required:       u32,
	max_frame_size:             i32,
}

Constants

FAST_HUFFMAN_LENGTH ¶

FAST_HUFFMAN_LENGTH :: 10
 

FAST_HUFFMAN_LENGTH [number] sets the log size of the huffman-acceleration table. Maximum supported value is 24. with larger numbers, more decodings are O(1), but the table size is larger so worse cache missing, so you'll have to probe (and try multiple ogg vorbis files) to find the sweet spot.

MAX_CHANNELS ¶

MAX_CHANNELS :: 16
 

MAX_CHANNELS [number] globally define this to the maximum number of channels you need. The spec does not put a restriction on channels except that the count is stored in a byte, so 255 is the hard limit. Reducing this saves about 16 bytes per value, so using 16 saves (255-16)*16 or around 4KB. Plus anything other memory usage I forgot to account for. Can probably go as low as 8 (7.1 audio), 6 (5.1 audio), or 2 (stereo only).

PUSHDATA_CRC_COUNT ¶

PUSHDATA_CRC_COUNT :: 4
 

PUSHDATA_CRC_COUNT [number] after a flush_pushdata(), stb_vorbis begins scanning for the next valid page, without backtracking. when it finds something that looks like a page, it streams through it and verifies its CRC32. Should that validation fail, it keeps scanning. But it's possible that _while_ streaming through to check the CRC32 of one candidate page, it sees another candidate page. This #define determines how many "overlapping" candidate pages it can search at once. Note that "real" pages are typically ~4KB to ~8KB, whereas garbage pages could be as big as 64KB, but probably average ~16KB. So don't hose ourselves by scanning an apparent 64KB page and missing a ton of real ones in the interim; so minimum of 2

Variables

This section is empty.

Procedures

close ¶

close :: proc "cdecl" (f: ^vorbis) ---
 

close an ogg vorbis file and free all memory in use

decode_filename ¶

decode_filename :: proc "cdecl" (filename: cstring, channels, sample_rate: ^i32, output: ^[^]i16) -> i32 ---
 

decode an entire file and output the data interleaved into a malloc()ed buffer stored in *output. 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. When you're done with it, just free() the pointer returned in *output.

decode_frame_pushdata ¶

decode_frame_pushdata :: proc "cdecl" (
	f:                         ^vorbis, 
	datablock:                 [^]u8, 
	datablock_length_in_bytes: i32, 
	channels:                  ^i32, 
	output:                    ^[^]^f32, 
) -> i32 ---
 

decode a frame of audio sample data if possible from the passed-in data block

return value: number of bytes we used from datablock

possible cases: 0 bytes used, 0 samples output (need more data) N bytes used, 0 samples output (resynching the stream, keep going) N bytes used, M samples output (one frame of data) note that after opening a file, you will ALWAYS get one N-bytes,0-sample frame, because Vorbis always "discards" the first frame.

Note that on resynch, stb_vorbis will rarely consume all of the buffer, instead only datablock_length_in_bytes-3 or less. This is because it wants to avoid missing parts of a page header if they cross a datablock boundary, without writing state-machiney code to record a partial detection.

The number of channels returned are stored in *channels (which can be NULL--it is always the same as the number of channels reported by get_info). *output will contain an array of float* buffers, one per channel. In other words, (*output)[0][0] contains the first sample from the first channel, and (*output)[1][0] contains the first sample from the second channel.

*output points into stb_vorbis's internal output buffer storage; these buffers are owned by stb_vorbis and application code should not free them or modify their contents. They are transient and will be overwritten once you ask for more data to get decoded, so be sure to grab any data you need before then.

decode_memory ¶

decode_memory :: proc "cdecl" (mem: [^]u8, len: i32, channels, sample_rate: ^i32, output: ^[^]i16) -> i32 ---

flush_pushdata ¶

flush_pushdata :: proc "cdecl" (f: ^vorbis) ---
 

inform stb_vorbis that your next datablock will not be contiguous with previous ones (e.g. you've seeked in the data); future attempts to decode frames will cause stb_vorbis to resynchronize (as noted above), and once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it will begin decoding the _next_ frame.

if you want to seek using pushdata, you need to seek in your file, then call stb_vorbis_flush_pushdata(), then start calling decoding, then once decoding is returning you data, call stb_vorbis_get_sample_offset, and if you don't like the result, seek your file again and repeat.

get_comment ¶

get_comment :: proc "cdecl" (f: ^vorbis) -> vorbis_comment ---
 

get ogg comments

get_error ¶

get_error :: proc "cdecl" (f: ^vorbis) -> i32 ---
 

get the last error detected (clears it, too)

get_file_offset ¶

get_file_offset :: proc "cdecl" (f: ^vorbis) -> u32 ---
 

returns the current seek point within the file, or offset from the beginning of the memory buffer. In pushdata mode it returns 0.

get_frame_float ¶

get_frame_float :: proc "cdecl" (f: ^vorbis, channels: ^i32, output: ^[^]^f32) -> i32 ---
 

decode the next frame and return the number of samples. the number of channels returned are stored in *channels (which can be NULL--it is always the same as the number of channels reported by get_info). *output will contain an array of float* buffers, one per channel. These outputs will be overwritten on the next call to stb_vorbis_get_frame_*.

You generally should not intermix calls to stb_vorbis_get_frame_*() and stb_vorbis_get_samples_*(), since the latter calls the former.

get_frame_short ¶

get_frame_short :: proc "cdecl" (f: ^vorbis, num_c: i32, buffer: ^[^]i16, num_samples: i32) -> i32 ---

get_frame_short_interleaved ¶

get_frame_short_interleaved :: proc "cdecl" (f: ^vorbis, num_c: i32, buffer: [^]i16, num_shorts: i32) -> i32 ---
 

decode the next frame and return the number of *samples* per channel. Note that for interleaved data, you pass in the number of shorts (the size of your array), but the return value is the number of samples per channel, not the total number of samples.

The data is coerced to the number of channels you request according to the channel coercion rules (see below). You must pass in the size of your buffer(s) so that stb_vorbis will not overwrite the end of the buffer. The maximum buffer size needed can be gotten from get_info(); however, the Vorbis I specification implies an absolute maximum of 4096 samples per channel.

get_info ¶

get_info :: proc "cdecl" (f: ^vorbis) -> vorbis_info ---
 

get general information about the file

get_sample_offset ¶

get_sample_offset :: proc "cdecl" (f: ^vorbis) -> i32 ---
 

this function returns the offset (in samples) from the beginning of the file that will be returned by the next decode, if it is known, or -1 otherwise. after a flush_pushdata() call, this may take a while before it becomes valid again. NOT WORKING YET after a seek with PULLDATA API

get_samples_float ¶

get_samples_float :: proc "cdecl" (f: ^vorbis, channels: i32, buffer: ^[^]f32, num_samples: i32) -> i32 ---

get_samples_float_interleaved ¶

get_samples_float_interleaved :: proc "cdecl" (f: ^vorbis, channels: i32, buffer: [^]f32, num_floats: i32) -> i32 ---
 

gets num_samples samples, not necessarily on a frame boundary--this requires buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES. Returns the number of samples stored per channel; it may be less than requested at the end of the file. If there are no more samples in the file, returns 0.

get_samples_short ¶

get_samples_short :: proc "cdecl" (f: ^vorbis, num_c: i32, buffer: ^[^]i16, num_samples: i32) -> i32 ---

get_samples_short_interleaved ¶

get_samples_short_interleaved :: proc "cdecl" (f: ^vorbis, num_c: i32, buffer: [^]i16, num_shorts: i32) -> i32 ---
 

gets num_samples samples, not necessarily on a frame boundary--this requires buffering so you have to supply the buffers. Applies the coercion rules above to produce 'channels' channels. Returns the number of samples stored per channel; it may be less than requested at the end of the file. If there are no more samples in the file, returns 0.

open_file ¶

open_file :: proc "cdecl" (f: ^libc.FILE, close_handle_on_close: b32, error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis ---
 

create an ogg vorbis decoder from an open FILE *, looking for a stream at the _current_ seek point (ftell). on failure, returns NULL and sets *error. note that stb_vorbis must "own" this stream; if you seek it in between calls to stb_vorbis, it will become confused. Moreover, if you attempt to perform stb_vorbis_seek_*() operations on this file, it will assume it owns the _entire_ rest of the file after the start point. Use the next function, stb_vorbis_open_file_section(), to limit it.

open_file_section ¶

open_file_section :: proc "cdecl" (f: ^libc.FILE, close_handle_on_close: b32, error: ^Error, alloc_buffer: ^vorbis_alloc, len: u32) -> ^vorbis ---
 

create an ogg vorbis decoder from an open FILE *, looking for a stream at the _current_ seek point (ftell); the stream will be of length 'len' bytes. on failure, returns NULL and sets *error. note that stb_vorbis must "own" this stream; if you seek it in between calls to stb_vorbis, it will become confused.

open_filename ¶

open_filename :: proc "cdecl" (filename: cstring, error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis ---
 

create an ogg vorbis decoder from a filename via fopen(). on failure, returns NULL and sets *error (possibly to VORBIS_file_open_failure).

open_memory ¶

open_memory :: proc "cdecl" (data: [^]u8, len: i32, error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis ---
 

create an ogg vorbis decoder from an ogg vorbis stream in memory (note this must be the entire stream!). on failure, returns NULL and sets *error

open_pushdata ¶

open_pushdata :: proc "cdecl" (datablock: [^]u8, datablock_length_in_bytes: i32, datablock_memory_consumed_in_bytes: ^i32, error: ^Error, alloc_buffer: ^vorbis_alloc) -> ^vorbis ---
 

create a vorbis decoder by passing in the initial data block containing the ogg&vorbis headers (you don't need to do parse them, just provide the first N bytes of the file--you're told if it's not enough, see below) on success, returns an stb_vorbis *, does not set error, returns the amount of data parsed/consumed on this call in *datablock_memory_consumed_in_bytes; on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed if returns NULL and *error is VORBIS_need_more_data, then the input block was incomplete and you need to pass in a larger block from the start of the file

seek ¶

seek :: proc "cdecl" (f: ^vorbis, sample_number: u32) -> i32 ---

seek_frame ¶

seek_frame :: proc "cdecl" (f: ^vorbis, sample_number: u32) -> i32 ---
 

these functions seek in the Vorbis file to (approximately) 'sample_number'. after calling seek_frame(), the next call to get_frame_*() will include the specified sample. after calling stb_vorbis_seek(), the next call to stb_vorbis_get_samples_* will start with the specified sample. If you do not need to seek to EXACTLY the target sample when using get_samples_*, you can also use seek_frame().

seek_start ¶

seek_start :: proc "cdecl" (f: ^vorbis) -> i32 ---
 

this function is equivalent to stb_vorbis_seek(f,0)

stream_length_in_samples ¶

stream_length_in_samples :: proc "cdecl" (f: ^vorbis) -> u32 ---
 

these functions return the total length of the vorbis stream

stream_length_in_seconds ¶

stream_length_in_seconds :: proc "cdecl" (f: ^vorbis) -> f32 ---

Procedure Groups

This section is empty.

Source Files

Generation Information

Generated with odin version dev-2022-10 (vendor "odin") Windows_amd64 @ 2022-10-05 21:11:47.822436300 +0000 UTC