mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 04:50:29 +00:00
Add vendor:stb/vorbis
This commit is contained in:
22
vendor/stb/src/Makefile
vendored
22
vendor/stb/src/Makefile
vendored
@@ -1,12 +1,16 @@
|
||||
all:
|
||||
mkdir -p ../lib
|
||||
gcc -c -O2 -march=native -Os -fPIC stb_image.c stb_image_write.c stb_truetype.c stb_rect_pack.c
|
||||
ar rcs ../lib/stb_image.a stb_image.o
|
||||
ar rcs ../lib/stb_image_write.a stb_image_write.o
|
||||
ar rcs ../lib/stb_truetype.a stb_truetype.o
|
||||
ar rcs ../lib/stb_rect_pack.a stb_rect_pack.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_image.so -o ../lib/stb_image.so stb_image.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_image_write.so -o ../lib/stb_image_write.so stb_image_write.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_truetype.so -o ../lib/stb_truetype.so stb_image_truetype.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_rect_pack.so -o ../lib/stb_rect_pack.so stb_rect_packl.o
|
||||
gcc -c -O2 -march=native -Os -fPIC stb_image.c stb_image_write.c stb_image_resize.c stb_truetype.c stb_rect_pack.c stb_vorbis.c
|
||||
ar rcs ../lib/stb_image.a stb_image.o
|
||||
ar rcs ../lib/stb_image_write.a stb_image_write.o
|
||||
ar rcs ../lib/stb_image_resize.a stb_image_resize.o
|
||||
ar rcs ../lib/stb_truetype.a stb_truetype.o
|
||||
ar rcs ../lib/stb_rect_pack.a stb_rect_pack.o
|
||||
ar rcs ../lib/stb_vorbis_pack.a stb_vorbis_pack.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_image.so -o ../lib/stb_image.so stb_image.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_image_write.so -o ../lib/stb_image_write.so stb_image_write.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_image_resize.so -o ../lib/stb_image_resize.so stb_image_resize.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_truetype.so -o ../lib/stb_truetype.so stb_image_truetype.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_rect_pack.so -o ../lib/stb_rect_pack.so stb_rect_packl.o
|
||||
#gcc -fPIC -shared -Wl,-soname=stb_vorbis.so -o ../lib/stb_vorbis.so stb_vorbisl.o
|
||||
rm *.o
|
||||
|
||||
3
vendor/stb/src/build.bat
vendored
3
vendor/stb/src/build.bat
vendored
@@ -2,11 +2,12 @@
|
||||
|
||||
if not exist "..\lib" mkdir ..\lib
|
||||
|
||||
cl -nologo -MT -TC -O2 -c stb_image.c stb_image_write.c stb_image_resize.c stb_truetype.c stb_rect_pack.c
|
||||
cl -nologo -MT -TC -O2 -c stb_image.c stb_image_write.c stb_image_resize.c stb_truetype.c stb_rect_pack.c stb_vorbis.c
|
||||
lib -nologo stb_image.obj -out:..\lib\stb_image.lib
|
||||
lib -nologo stb_image_write.obj -out:..\lib\stb_image_write.lib
|
||||
lib -nologo stb_image_resize.obj -out:..\lib\stb_image_resize.lib
|
||||
lib -nologo stb_truetype.obj -out:..\lib\stb_truetype.lib
|
||||
lib -nologo stb_rect_pack.obj -out:..\lib\stb_rect_pack.lib
|
||||
lib -nologo stb_vorbis.obj -out:..\lib\stb_vorbis.lib
|
||||
|
||||
del *.obj
|
||||
|
||||
5584
vendor/stb/src/stb_vorbis.c
vendored
Normal file
5584
vendor/stb/src/stb_vorbis.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
352
vendor/stb/vorbis/stb_vorbis.odin
vendored
Normal file
352
vendor/stb/vorbis/stb_vorbis.odin
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
package stb_vorbis
|
||||
|
||||
import c "core:c/libc"
|
||||
|
||||
|
||||
when ODIN_OS == "windows" { foreign import lib "../lib/stb_vorbis.lib" }
|
||||
when ODIN_OS == "linux" { foreign import lib "../lib/stb_vorbis.a" }
|
||||
|
||||
|
||||
|
||||
/////////// THREAD SAFETY
|
||||
|
||||
// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
|
||||
// them from multiple threads at the same time. However, you can have multiple
|
||||
// stb_vorbis* handles and decode from them independently in multiple thrads.
|
||||
|
||||
|
||||
/////////// MEMORY ALLOCATION
|
||||
|
||||
// normally stb_vorbis uses malloc() to allocate memory at startup,
|
||||
// and alloca() to allocate temporary memory during a frame on the
|
||||
// stack. (Memory consumption will depend on the amount of setup
|
||||
// data in the file and how you set the compile flags for speed
|
||||
// vs. size. In my test files the maximal-size usage is ~150KB.)
|
||||
//
|
||||
// You can modify the wrapper functions in the source (setup_malloc,
|
||||
// setup_temp_malloc, temp_malloc) to change this behavior, or you
|
||||
// can use a simpler allocation model: you pass in a buffer from
|
||||
// which stb_vorbis will allocate _all_ its memory (including the
|
||||
// temp memory). "open" may fail with a VORBIS_outofmem if you
|
||||
// do not pass in enough data; there is no way to determine how
|
||||
// much you do need except to succeed (at which point you can
|
||||
// query get_info to find the exact amount required. yes I know
|
||||
// this is lame).
|
||||
//
|
||||
// If you pass in a non-NULL buffer of the type below, allocation
|
||||
// will occur from it as described above. Otherwise just pass NULL
|
||||
// to use malloc()/alloca()
|
||||
|
||||
vorbis_alloc :: struct {
|
||||
alloc_buffer: [^]byte,
|
||||
alloc_buffer_length_in_bytes: c.int,
|
||||
}
|
||||
|
||||
vorbis :: struct {}
|
||||
|
||||
vorbis_info :: struct {
|
||||
sample_rate: c.uint,
|
||||
channels: c.int,
|
||||
|
||||
setup_memory_required: c.uint,
|
||||
setup_temp_memory_required: c.uint,
|
||||
temp_memory_required: c.uint,
|
||||
|
||||
max_frame_size: c.int,
|
||||
}
|
||||
|
||||
vorbis_comment :: struct {
|
||||
vendor: cstring,
|
||||
|
||||
comment_list_length: c.int,
|
||||
comment_list: [^]cstring,
|
||||
}
|
||||
|
||||
@(default_calling_convention="c", link_prefix="stb_vorbis_")
|
||||
foreign lib {
|
||||
// get general information about the file
|
||||
get_info :: proc(f: ^vorbis) -> vorbis_info ---
|
||||
|
||||
// get ogg comments
|
||||
get_comment :: proc(f: ^vorbis) -> vorbis_comment ---
|
||||
|
||||
// get the last error detected (clears it, too)
|
||||
get_error :: proc(f: ^vorbis) -> c.int ---
|
||||
|
||||
// close an ogg vorbis file and free all memory in use
|
||||
close :: proc(f: ^vorbis) ---
|
||||
|
||||
// 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_sample_offset :: proc(f: ^vorbis) -> c.int ---
|
||||
|
||||
// returns the current seek point within the file, or offset from the beginning
|
||||
// of the memory buffer. In pushdata mode it returns 0.
|
||||
get_file_offset :: proc(f: ^vorbis) -> c.uint ---
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////// PUSHDATA API
|
||||
|
||||
// this API allows you to get blocks of data from any source and hand
|
||||
// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
|
||||
// you how much it used, and you have to give it the rest next time;
|
||||
// and stb_vorbis may not have enough data to work with and you will
|
||||
// need to give it the same data again PLUS more. Note that the Vorbis
|
||||
// specification does not bound the size of an individual frame.
|
||||
|
||||
@(default_calling_convention="c", link_prefix="stb_vorbis_")
|
||||
foreign lib {
|
||||
// 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
|
||||
open_pushdata :: proc(
|
||||
datablock: [^]byte, datablock_length_in_bytes: c.int,
|
||||
datablock_memory_consumed_in_bytes: ^c.int,
|
||||
error: ^Error,
|
||||
alloc_buffer: ^vorbis_alloc,
|
||||
) -> ^vorbis ---
|
||||
|
||||
// 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_frame_pushdata :: proc(
|
||||
f: ^vorbis,
|
||||
datablock: [^]byte, datablock_length_in_bytes: c.int,
|
||||
channels: ^c.int, // place to write number of float * buffers
|
||||
output: ^[^]^f32, // place to write float ** array of float * buffers
|
||||
samples: ^c.int, // place to write number of output samples
|
||||
) -> c.int ---
|
||||
|
||||
// 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.
|
||||
flush_pushdata :: proc(f: ^vorbis) ---
|
||||
}
|
||||
|
||||
|
||||
////////// PULLING INPUT API
|
||||
|
||||
// This API assumes stb_vorbis is allowed to pull data from a source--
|
||||
// either a block of memory containing the _entire_ vorbis stream, or a
|
||||
// FILE * that you or it create, or possibly some other reading mechanism
|
||||
// if you go modify the source to replace the FILE * case with some kind
|
||||
// of callback to your code. (But if you don't support seeking, you may
|
||||
// just want to go ahead and use pushdata.)
|
||||
|
||||
@(default_calling_convention="c", link_prefix="stb_vorbis_")
|
||||
foreign lib {
|
||||
// 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_filename :: proc(filename: cstring, channels, sample_rate: ^c.int, output: ^[^]c.short) -> c.int ---
|
||||
decode_memory :: proc(mem: [^]byte, len: c.int, channels, sample_rate: ^c.int, output: ^[^]c.short) -> c.int ---
|
||||
|
||||
|
||||
|
||||
// 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_memory :: proc(data: [^]byte, len: c.int,
|
||||
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_filename :: proc(filename: cstring,
|
||||
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 :: proc(f: ^c.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); 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_file_section :: proc(f: ^c.FILE, close_handle_on_close: b32,
|
||||
error: ^Error, alloc_buffer: ^vorbis_alloc, len: c.uint) -> ^vorbis ---
|
||||
|
||||
// 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_frame :: proc(f: ^vorbis, sample_number: c.uint) -> c.int ---
|
||||
seek :: proc(f: ^vorbis, sample_number: c.uint) -> c.int ---
|
||||
|
||||
// this function is equivalent to stb_vorbis_seek(f,0)
|
||||
seek_start :: proc(f: ^vorbis) -> c.int ---
|
||||
|
||||
// these functions return the total length of the vorbis stream
|
||||
stream_length_in_samples :: proc(f: ^vorbis) -> c.uint ---
|
||||
stream_length_in_seconds :: proc(f: ^vorbis) -> f32 ---
|
||||
|
||||
// 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_float :: proc(f: ^vorbis, channels: ^c.int, output: ^[^]^f32) -> c.int ---
|
||||
|
||||
// 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_frame_short_interleaved :: proc(f: ^vorbis, num_c: c.int, buffer: [^]c.short, num_shorts: c.int) -> c.int ---
|
||||
get_frame_short :: proc(f: ^vorbis, num_c: c.int, buffer: ^[^]c.short, num_samples: c.int) -> c.int ---
|
||||
|
||||
// Channel coercion rules:
|
||||
// Let M be the number of channels requested, and N the number of channels present,
|
||||
// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
|
||||
// and stereo R be the sum of all R and center channels (channel assignment from the
|
||||
// vorbis spec).
|
||||
// M N output
|
||||
// 1 k sum(Ck) for all k
|
||||
// 2 * stereo L, stereo R
|
||||
// k l k > l, the first l channels, then 0s
|
||||
// k l k <= l, the first k channels
|
||||
// Note that this is not _good_ surround etc. mixing at all! It's just so
|
||||
// you get something useful.
|
||||
|
||||
// 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_float_interleaved :: proc(f: ^vorbis, channels: c.int, buffer: [^]f32, num_floats: c.int) -> c.int ---
|
||||
get_samples_float :: proc(f: ^vorbis, channels: c.int, buffer: ^[^]f32, num_samples: c.int) -> c.int ---
|
||||
|
||||
// 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.
|
||||
get_samples_short_interleaved :: proc(f: ^vorbis, channels: c.int, buffer: [^]c.short, num_shorts: c.int) -> c.int ---
|
||||
get_samples_short :: proc(f: ^vorbis, channels: c.int, buffer: ^[^]c.short, num_samples: c.int) -> c.int ---
|
||||
|
||||
}
|
||||
|
||||
Error :: enum c.int {
|
||||
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
|
||||
|
||||
// decoding errors (corrupt/invalid stream) -- you probably
|
||||
// don't care about the exact details of these
|
||||
|
||||
// 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,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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).
|
||||
MAX_CHANNELS :: 16 // enough for anyone?
|
||||
|
||||
// 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
|
||||
PUSHDATA_CRC_COUNT :: 4
|
||||
|
||||
// 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.
|
||||
FAST_HUFFMAN_LENGTH :: 10
|
||||
Reference in New Issue
Block a user