mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Begin adding vendor:miniaudio
This commit is contained in:
+8
-1
@@ -2,9 +2,16 @@
|
|||||||
|
|
||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
|
rem build the .lib files already exist
|
||||||
|
|
||||||
if not exist "vendor\stb\lib\*.lib" (
|
if not exist "vendor\stb\lib\*.lib" (
|
||||||
rem build the .lib fiels already exist
|
|
||||||
pushd vendor\stb\src
|
pushd vendor\stb\src
|
||||||
call build.bat
|
call build.bat
|
||||||
popd
|
popd
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not exist "vendor\miniaudio\lib\*.lib" (
|
||||||
|
pushd vendor\miniaudio\src
|
||||||
|
call build.bat
|
||||||
|
popd
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//+build darwin
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
package unix;
|
//+build freebsd
|
||||||
|
package unix
|
||||||
|
|
||||||
import "core:c";
|
import "core:c";
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//+build linux
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//+build linux, darwin, freebsd
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
foreign import "system:pthread"
|
foreign import "system:pthread"
|
||||||
|
|||||||
Vendored
+432
@@ -0,0 +1,432 @@
|
|||||||
|
package miniaudio
|
||||||
|
|
||||||
|
import "core:c"
|
||||||
|
|
||||||
|
when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
|
||||||
|
|
||||||
|
handle :: distinct rawptr
|
||||||
|
|
||||||
|
|
||||||
|
/* SIMD alignment in bytes. Currently set to 64 bytes in preparation for future AVX-512 optimizations. */
|
||||||
|
SIMD_ALIGNMENT :: 64
|
||||||
|
|
||||||
|
LOG_LEVEL_DEBUG :: 4
|
||||||
|
LOG_LEVEL_INFO :: 3
|
||||||
|
LOG_LEVEL_WARNING :: 2
|
||||||
|
LOG_LEVEL_ERROR :: 1
|
||||||
|
|
||||||
|
|
||||||
|
channel :: enum u8 {
|
||||||
|
NONE = 0,
|
||||||
|
MONO = 1,
|
||||||
|
FRONT_LEFT = 2,
|
||||||
|
FRONT_RIGHT = 3,
|
||||||
|
FRONT_CENTER = 4,
|
||||||
|
LFE = 5,
|
||||||
|
BACK_LEFT = 6,
|
||||||
|
BACK_RIGHT = 7,
|
||||||
|
FRONT_LEFT_CENTER = 8,
|
||||||
|
FRONT_RIGHT_CENTER = 9,
|
||||||
|
BACK_CENTER = 10,
|
||||||
|
SIDE_LEFT = 11,
|
||||||
|
SIDE_RIGHT = 12,
|
||||||
|
TOP_CENTER = 13,
|
||||||
|
TOP_FRONT_LEFT = 14,
|
||||||
|
TOP_FRONT_CENTER = 15,
|
||||||
|
TOP_FRONT_RIGHT = 16,
|
||||||
|
TOP_BACK_LEFT = 17,
|
||||||
|
TOP_BACK_CENTER = 18,
|
||||||
|
TOP_BACK_RIGHT = 19,
|
||||||
|
AUX_0 = 20,
|
||||||
|
AUX_1 = 21,
|
||||||
|
AUX_2 = 22,
|
||||||
|
AUX_3 = 23,
|
||||||
|
AUX_4 = 24,
|
||||||
|
AUX_5 = 25,
|
||||||
|
AUX_6 = 26,
|
||||||
|
AUX_7 = 27,
|
||||||
|
AUX_8 = 28,
|
||||||
|
AUX_9 = 29,
|
||||||
|
AUX_10 = 30,
|
||||||
|
AUX_11 = 31,
|
||||||
|
AUX_12 = 32,
|
||||||
|
AUX_13 = 33,
|
||||||
|
AUX_14 = 34,
|
||||||
|
AUX_15 = 35,
|
||||||
|
AUX_16 = 36,
|
||||||
|
AUX_17 = 37,
|
||||||
|
AUX_18 = 38,
|
||||||
|
AUX_19 = 39,
|
||||||
|
AUX_20 = 40,
|
||||||
|
AUX_21 = 41,
|
||||||
|
AUX_22 = 42,
|
||||||
|
AUX_23 = 43,
|
||||||
|
AUX_24 = 44,
|
||||||
|
AUX_25 = 45,
|
||||||
|
AUX_26 = 46,
|
||||||
|
AUX_27 = 47,
|
||||||
|
AUX_28 = 48,
|
||||||
|
AUX_29 = 49,
|
||||||
|
AUX_30 = 50,
|
||||||
|
AUX_31 = 51,
|
||||||
|
LEFT = FRONT_LEFT,
|
||||||
|
RIGHT = FRONT_RIGHT,
|
||||||
|
POSITION_COUNT = AUX_31 + 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
result :: enum c.int {
|
||||||
|
SUCCESS = 0,
|
||||||
|
ERROR = -1, /* A generic error. */
|
||||||
|
INVALID_ARGS = -2,
|
||||||
|
INVALID_OPERATION = -3,
|
||||||
|
OUT_OF_MEMORY = -4,
|
||||||
|
OUT_OF_RANGE = -5,
|
||||||
|
ACCESS_DENIED = -6,
|
||||||
|
DOES_NOT_EXIST = -7,
|
||||||
|
ALREADY_EXISTS = -8,
|
||||||
|
TOO_MANY_OPEN_FILES = -9,
|
||||||
|
INVALID_FILE = -10,
|
||||||
|
TOO_BIG = -11,
|
||||||
|
PATH_TOO_LONG = -12,
|
||||||
|
NAME_TOO_LONG = -13,
|
||||||
|
NOT_DIRECTORY = -14,
|
||||||
|
IS_DIRECTORY = -15,
|
||||||
|
DIRECTORY_NOT_EMPTY = -16,
|
||||||
|
AT_END = -17,
|
||||||
|
NO_SPACE = -18,
|
||||||
|
BUSY = -19,
|
||||||
|
IO_ERROR = -20,
|
||||||
|
INTERRUPT = -21,
|
||||||
|
UNAVAILABLE = -22,
|
||||||
|
ALREADY_IN_USE = -23,
|
||||||
|
BAD_ADDRESS = -24,
|
||||||
|
BAD_SEEK = -25,
|
||||||
|
BAD_PIPE = -26,
|
||||||
|
DEADLOCK = -27,
|
||||||
|
TOO_MANY_LINKS = -28,
|
||||||
|
NOT_IMPLEMENTED = -29,
|
||||||
|
NO_MESSAGE = -30,
|
||||||
|
BAD_MESSAGE = -31,
|
||||||
|
NO_DATA_AVAILABLE = -32,
|
||||||
|
INVALID_DATA = -33,
|
||||||
|
TIMEOUT = -34,
|
||||||
|
NO_NETWORK = -35,
|
||||||
|
NOT_UNIQUE = -36,
|
||||||
|
NOT_SOCKET = -37,
|
||||||
|
NO_ADDRESS = -38,
|
||||||
|
BAD_PROTOCOL = -39,
|
||||||
|
PROTOCOL_UNAVAILABLE = -40,
|
||||||
|
PROTOCOL_NOT_SUPPORTED = -41,
|
||||||
|
PROTOCOL_FAMILY_NOT_SUPPORTED = -42,
|
||||||
|
ADDRESS_FAMILY_NOT_SUPPORTED = -43,
|
||||||
|
SOCKET_NOT_SUPPORTED = -44,
|
||||||
|
CONNECTION_RESET = -45,
|
||||||
|
ALREADY_CONNECTED = -46,
|
||||||
|
NOT_CONNECTED = -47,
|
||||||
|
CONNECTION_REFUSED = -48,
|
||||||
|
NO_HOST = -49,
|
||||||
|
IN_PROGRESS = -50,
|
||||||
|
CANCELLED = -51,
|
||||||
|
MEMORY_ALREADY_MAPPED = -52,
|
||||||
|
|
||||||
|
/* General miniaudio-specific errors. */
|
||||||
|
FORMAT_NOT_SUPPORTED = -100,
|
||||||
|
DEVICE_TYPE_NOT_SUPPORTED = -101,
|
||||||
|
SHARE_MODE_NOT_SUPPORTED = -102,
|
||||||
|
NO_BACKEND = -103,
|
||||||
|
NO_DEVICE = -104,
|
||||||
|
API_NOT_FOUND = -105,
|
||||||
|
INVALID_DEVICE_CONFIG = -106,
|
||||||
|
LOOP = -107,
|
||||||
|
|
||||||
|
/* State errors. */
|
||||||
|
DEVICE_NOT_INITIALIZED = -200,
|
||||||
|
DEVICE_ALREADY_INITIALIZED = -201,
|
||||||
|
DEVICE_NOT_STARTED = -202,
|
||||||
|
DEVICE_NOT_STOPPED = -203,
|
||||||
|
|
||||||
|
/* Operation errors. */
|
||||||
|
FAILED_TO_INIT_BACKEND = -300,
|
||||||
|
FAILED_TO_OPEN_BACKEND_DEVICE = -301,
|
||||||
|
FAILED_TO_START_BACKEND_DEVICE = -302,
|
||||||
|
FAILED_TO_STOP_BACKEND_DEVICE = -303,
|
||||||
|
}
|
||||||
|
|
||||||
|
MIN_CHANNELS :: 1
|
||||||
|
MAX_CHANNELS :: 32
|
||||||
|
|
||||||
|
MAX_FILTER_ORDER :: 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
stream_format :: enum c.int {
|
||||||
|
pcm = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_layout :: enum c.int {
|
||||||
|
interleaved = 0,
|
||||||
|
deinterleaved,
|
||||||
|
}
|
||||||
|
|
||||||
|
dither_mode :: enum c.int {
|
||||||
|
none = 0,
|
||||||
|
rectangle,
|
||||||
|
triangle,
|
||||||
|
}
|
||||||
|
|
||||||
|
format :: enum c.int {
|
||||||
|
/*
|
||||||
|
I like to keep these explicitly defined because they're used as a key into a lookup table. When items are
|
||||||
|
added to this, make sure there are no gaps and that they're added to the lookup table in ma_get_bytes_per_sample().
|
||||||
|
*/
|
||||||
|
unknown = 0, /* Mainly used for indicating an error, but also used as the default for the output format for decoders. */
|
||||||
|
u8 = 1,
|
||||||
|
s16 = 2, /* Seems to be the most widely supported format. */
|
||||||
|
s24 = 3, /* Tightly packed. 3 bytes per sample. */
|
||||||
|
s32 = 4,
|
||||||
|
f32 = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
standard_sample_rate :: enum u32 {
|
||||||
|
/* Standard rates need to be in priority order. */
|
||||||
|
rate_48000 = 48000, /* Most common */
|
||||||
|
rate_44100 = 44100,
|
||||||
|
|
||||||
|
rate_32000 = 32000, /* Lows */
|
||||||
|
rate_24000 = 24000,
|
||||||
|
rate_22050 = 22050,
|
||||||
|
|
||||||
|
rate_88200 = 88200, /* Highs */
|
||||||
|
rate_96000 = 96000,
|
||||||
|
rate_176400 = 176400,
|
||||||
|
rate_192000 = 192000,
|
||||||
|
|
||||||
|
rate_16000 = 16000, /* Extreme lows */
|
||||||
|
rate_11025 = 11250,
|
||||||
|
rate_8000 = 8000,
|
||||||
|
|
||||||
|
rate_352800 = 352800, /* Extreme highs */
|
||||||
|
rate_384000 = 384000,
|
||||||
|
|
||||||
|
rate_min = rate_8000,
|
||||||
|
rate_max = rate_384000,
|
||||||
|
rate_count = 14, /* Need to maintain the count manually. Make sure this is updated if items are added to enum. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
channel_mix_mode :: enum c.int {
|
||||||
|
rectangular = 0, /* Simple averaging based on the plane(s) the channel is sitting on. */
|
||||||
|
simple, /* Drop excess channels; zeroed out extra channels. */
|
||||||
|
custom_weights, /* Use custom weights specified in ma_channel_router_config. */
|
||||||
|
planar_blend = rectangular,
|
||||||
|
default = rectangular,
|
||||||
|
}
|
||||||
|
|
||||||
|
standard_channel_map :: enum c.int {
|
||||||
|
microsoft,
|
||||||
|
alsa,
|
||||||
|
rfc3551, /* Based off AIFF. */
|
||||||
|
flac,
|
||||||
|
vorbis,
|
||||||
|
sound4, /* FreeBSD's sound(4). */
|
||||||
|
sndio, /* www.sndio.org/tips.html */
|
||||||
|
webaudio = flac, /* https://webaudio.github.io/web-audio-api/#ChannelOrdering. Only 1, 2, 4 and 6 channels are defined, but can fill in the gaps with logical assumptions. */
|
||||||
|
default = microsoft,
|
||||||
|
}
|
||||||
|
|
||||||
|
performance_profile :: enum c.int {
|
||||||
|
low_latency = 0,
|
||||||
|
conservative,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
allocation_callbacks :: struct {
|
||||||
|
pUserData: rawptr,
|
||||||
|
onMalloc: proc "c" (sz: c.size_t, pUserData: rawptr) -> rawptr,
|
||||||
|
onRealloc: proc "c" (p: rawptr, sz: c.size_t, pUserData: rawptr) -> rawptr,
|
||||||
|
onFree: proc "c" (p: rawptr, pUserData: rawptr),
|
||||||
|
}
|
||||||
|
|
||||||
|
lcg :: struct {
|
||||||
|
state: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
NO_THREADING :: false
|
||||||
|
|
||||||
|
when !NO_THREADING {
|
||||||
|
/* Thread priorities should be ordered such that the default priority of the worker thread is 0. */
|
||||||
|
thread_priority :: enum c.int {
|
||||||
|
idle = -5,
|
||||||
|
lowest = -4,
|
||||||
|
low = -3,
|
||||||
|
normal = -2,
|
||||||
|
high = -1,
|
||||||
|
highest = 0,
|
||||||
|
realtime = 1,
|
||||||
|
default = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spinlocks are 32-bit for compatibility reasons. */
|
||||||
|
spinlock :: distinct u32
|
||||||
|
|
||||||
|
when ODIN_OS == "windows" {
|
||||||
|
thread :: distinct rawptr
|
||||||
|
mutex :: distinct rawptr
|
||||||
|
event :: distinct rawptr
|
||||||
|
semaphore :: distinct rawptr
|
||||||
|
} else {
|
||||||
|
import "core:sys/unix"
|
||||||
|
|
||||||
|
thread :: unix.pthread_t
|
||||||
|
mutex :: unix.pthread_mutex_t
|
||||||
|
event :: struct {
|
||||||
|
value: u32,
|
||||||
|
lock: unix.pthread_mutex_t,
|
||||||
|
cond: unix.pthread_cond_t,
|
||||||
|
}
|
||||||
|
semaphore :: struct {
|
||||||
|
value: c.int,
|
||||||
|
lock: unix.pthread_mutex_t,
|
||||||
|
cond: unix.pthread_cond_t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
/*
|
||||||
|
Locks a spinlock.
|
||||||
|
*/
|
||||||
|
spinlock_lock :: proc(/*volatile*/ pSpinlock: ^spinlock) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Locks a spinlock, but does not yield() when looping.
|
||||||
|
*/
|
||||||
|
spinlock_lock_noyield :: proc(/*volatile*/ pSpinlock: ^spinlock) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Unlocks a spinlock.
|
||||||
|
*/
|
||||||
|
spinlock_unlock :: proc(/*volatile*/ pSpinlock: ^spinlock) -> result ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Creates a mutex.
|
||||||
|
|
||||||
|
A mutex must be created from a valid context. A mutex is initially unlocked.
|
||||||
|
*/
|
||||||
|
mutex_init :: proc(pMutex: ^mutex) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Deletes a mutex.
|
||||||
|
*/
|
||||||
|
mutex_uninit :: proc(pMutex: ^mutex) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Locks a mutex with an infinite timeout.
|
||||||
|
*/
|
||||||
|
mutex_lock :: proc(pMutex: ^mutex) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Unlocks a mutex.
|
||||||
|
*/
|
||||||
|
mutex_unlock :: proc(pMutex: ^mutex) ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initializes an auto-reset event.
|
||||||
|
*/
|
||||||
|
event_init :: proc(pEvent: ^event) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Uninitializes an auto-reset event.
|
||||||
|
*/
|
||||||
|
event_uninit :: proc(pEvent: ^event) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Waits for the specified auto-reset event to become signalled.
|
||||||
|
*/
|
||||||
|
event_wait :: proc(pEvent: ^event) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Signals the specified auto-reset event.
|
||||||
|
*/
|
||||||
|
event_signal :: proc(pEvent: ^event) -> result ---
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* NO_THREADING */
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
version :: proc(pMajor, pMinor, pRevision: ^u32) ---
|
||||||
|
version_string :: proc() -> cstring ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Miscellaneous Helpers
|
||||||
|
|
||||||
|
************************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
/*
|
||||||
|
Retrieves a human readable description of the given result code.
|
||||||
|
*/
|
||||||
|
result_description :: proc(result: result) -> cstring ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
malloc(). Calls MA_MALLOC().
|
||||||
|
*/
|
||||||
|
malloc :: proc(sz: c.size_t, pAllocationCallbacks: ^allocation_callbacks) -> rawptr ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
realloc(). Calls MA_REALLOC().
|
||||||
|
*/
|
||||||
|
realloc :: proc(p: rawptr, sz: c.size_t, pAllocationCallbacks: ^allocation_callbacks) -> rawptr ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
free(). Calls MA_FREE().
|
||||||
|
*/
|
||||||
|
free :: proc(p: rawptr, pAllocationCallbacks: ^allocation_callbacks) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Performs an aligned malloc, with the assumption that the alignment is a power of 2.
|
||||||
|
*/
|
||||||
|
aligned_malloc :: proc(sz, alignment: c.size_t, pAllocationCallbacks: ^allocation_callbacks) -> rawptr ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Free's an aligned malloc'd buffer.
|
||||||
|
*/
|
||||||
|
aligned_free :: proc(p: rawptr, pAllocationCallbacks: ^allocation_callbacks) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves a friendly name for a format.
|
||||||
|
*/
|
||||||
|
get_format_name :: proc(format: format) -> cstring ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Blends two frames in floating point format.
|
||||||
|
*/
|
||||||
|
blend_f32 :: proc(pOut, pInA, pInB: ^f32, factor: f32, channels: u32) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves the size of a sample in bytes for the given format.
|
||||||
|
|
||||||
|
This API is efficient and is implemented using a lookup table.
|
||||||
|
|
||||||
|
Thread Safety: SAFE
|
||||||
|
This API is pure.
|
||||||
|
*/
|
||||||
|
get_bytes_per_sample :: proc(format: format) -> u32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Converts a log level to a string.
|
||||||
|
*/
|
||||||
|
log_level_to_string :: proc(logLevel: u32) -> cstring ---
|
||||||
|
}
|
||||||
|
|
||||||
|
get_bytes_per_frame :: #force_inline proc "c" (format: format, channels: u32) -> u32 { return get_bytes_per_sample(format) * channels }
|
||||||
+509
@@ -0,0 +1,509 @@
|
|||||||
|
package miniaudio
|
||||||
|
|
||||||
|
import "core:c"
|
||||||
|
|
||||||
|
when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
|
||||||
|
|
||||||
|
/************************************************************************************************************************************************************
|
||||||
|
*************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
DATA CONVERSION
|
||||||
|
===============
|
||||||
|
|
||||||
|
This section contains the APIs for data conversion. You will find everything here for channel mapping, sample format conversion, resampling, etc.
|
||||||
|
|
||||||
|
*************************************************************************************************************************************************************
|
||||||
|
************************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Resampling
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
linear_resampler_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRateIn: u32,
|
||||||
|
sampleRateOut: u32,
|
||||||
|
lpfOrder: u32, /* The low-pass filter order. Setting this to 0 will disable low-pass filtering. */
|
||||||
|
lpfNyquistFactor: f64, /* 0..1. Defaults to 1. 1 = Half the sampling frequency (Nyquist Frequency), 0.5 = Quarter the sampling frequency (half Nyquest Frequency), etc. */
|
||||||
|
}
|
||||||
|
|
||||||
|
linear_resampler :: struct {
|
||||||
|
config: linear_resampler_config,
|
||||||
|
inAdvanceInt: u32,
|
||||||
|
inAdvanceFrac: u32,
|
||||||
|
inTimeInt: u32,
|
||||||
|
inTimeFrac: u32,
|
||||||
|
x0: struct #raw_union {
|
||||||
|
f32: [MAX_CHANNELS]f32,
|
||||||
|
s16: [MAX_CHANNELS]i16,
|
||||||
|
}, /* The previous input frame. */
|
||||||
|
x1: struct #raw_union {
|
||||||
|
f32: [MAX_CHANNELS]f32,
|
||||||
|
s16: [MAX_CHANNELS]i16,
|
||||||
|
}, /* The next input frame. */
|
||||||
|
lpf: lpf,
|
||||||
|
}
|
||||||
|
|
||||||
|
resample_algorithm :: enum {
|
||||||
|
linear = 0, /* Fastest, lowest quality. Optional low-pass filtering. Default. */
|
||||||
|
speex,
|
||||||
|
}
|
||||||
|
|
||||||
|
resampler_config :: struct {
|
||||||
|
format: format, /* Must be either ma_format_f32 or ma_format_s16. */
|
||||||
|
channels: u32,
|
||||||
|
sampleRateIn: u32,
|
||||||
|
sampleRateOut: u32,
|
||||||
|
algorithm: resample_algorithm,
|
||||||
|
linear: struct {
|
||||||
|
lpfOrder: u32,
|
||||||
|
lpfNyquistFactor: f64,
|
||||||
|
},
|
||||||
|
speex: struct {
|
||||||
|
quality: c.int, /* 0 to 10. Defaults to 3. */
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resampler :: struct {
|
||||||
|
config: resampler_config,
|
||||||
|
state: struct #raw_union {
|
||||||
|
linear: linear_resampler,
|
||||||
|
speex: struct {
|
||||||
|
pSpeexResamplerState: rawptr, /* SpeexResamplerState* */
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
linear_resampler_config_init :: proc(format: format, channels: u32, sampleRateIn, sampleRateOut: u32) -> linear_resampler_config ---
|
||||||
|
|
||||||
|
linear_resampler_init :: proc(pConfig: ^linear_resampler_config, pResampler: ^linear_resampler) -> result ---
|
||||||
|
linear_resampler_uninit :: proc(pResampler: ^linear_resampler) ---
|
||||||
|
linear_resampler_process_pcm_frames :: proc(pResampler: ^linear_resampler, pFramesIn: rawptr, pFrameCountIn: ^u64, pFramesOut: rawptr, pFrameCountOut: ^u64) -> result ---
|
||||||
|
linear_resampler_set_rate :: proc(pResampler: ^linear_resampler, sampleRateIn, sampleRateOut: u32) -> result ---
|
||||||
|
linear_resampler_set_rate_ratio :: proc(pResampler: ^linear_resampler, ratioInOut: f32) -> result ---
|
||||||
|
linear_resampler_get_required_input_frame_count :: proc(pResampler: ^linear_resampler, outputFrameCount: u64) -> u64 ---
|
||||||
|
linear_resampler_get_expected_output_frame_count :: proc(pResampler: ^linear_resampler, inputFrameCount: u64) -> u64 ---
|
||||||
|
linear_resampler_get_input_latency :: proc(pResampler: ^linear_resampler) -> u64 ---
|
||||||
|
linear_resampler_get_output_latency :: proc(pResampler: ^linear_resampler) -> u64 ---
|
||||||
|
|
||||||
|
resampler_config_init :: proc(format: format, channels: u32, sampleRateIn, sampleRateOut: u32, algorithm: resample_algorithm) -> resampler_config ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initializes a new resampler object from a config.
|
||||||
|
*/
|
||||||
|
resampler_init :: proc(pConfig: ^resampler_config, pResampler: ^resampler) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Uninitializes a resampler.
|
||||||
|
*/
|
||||||
|
resampler_uninit :: proc(pResampler: ^resampler) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Converts the given input data.
|
||||||
|
|
||||||
|
Both the input and output frames must be in the format specified in the config when the resampler was initilized.
|
||||||
|
|
||||||
|
On input, [pFrameCountOut] contains the number of output frames to process. On output it contains the number of output frames that
|
||||||
|
were actually processed, which may be less than the requested amount which will happen if there's not enough input data. You can use
|
||||||
|
ma_resampler_get_expected_output_frame_count() to know how many output frames will be processed for a given number of input frames.
|
||||||
|
|
||||||
|
On input, [pFrameCountIn] contains the number of input frames contained in [pFramesIn]. On output it contains the number of whole
|
||||||
|
input frames that were actually processed. You can use ma_resampler_get_required_input_frame_count() to know how many input frames
|
||||||
|
you should provide for a given number of output frames. [pFramesIn] can be NULL, in which case zeroes will be used instead.
|
||||||
|
|
||||||
|
If [pFramesOut] is NULL, a seek is performed. In this case, if [pFrameCountOut] is not NULL it will seek by the specified number of
|
||||||
|
output frames. Otherwise, if [pFramesCountOut] is NULL and [pFrameCountIn] is not NULL, it will seek by the specified number of input
|
||||||
|
frames. When seeking, [pFramesIn] is allowed to NULL, in which case the internal timing state will be updated, but no input will be
|
||||||
|
processed. In this case, any internal filter state will be updated as if zeroes were passed in.
|
||||||
|
|
||||||
|
It is an error for [pFramesOut] to be non-NULL and [pFrameCountOut] to be NULL.
|
||||||
|
|
||||||
|
It is an error for both [pFrameCountOut] and [pFrameCountIn] to be NULL.
|
||||||
|
*/
|
||||||
|
resampler_process_pcm_frames :: proc(pResampler: ^resampler, pFramesIn: rawptr, pFrameCountIn: ^u64, pFramesOut: rawptr, pFrameCountOut: ^u64) -> result ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sets the input and output sample sample rate.
|
||||||
|
*/
|
||||||
|
resampler_set_rate :: proc(pResampler: ^resampler, sampleRateIn, sampleRateOut: u32) -> result ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sets the input and output sample rate as a ratio.
|
||||||
|
|
||||||
|
The ration is in/out.
|
||||||
|
*/
|
||||||
|
resampler_set_rate_ratio :: proc(pResampler: ^resampler, ratio: f32) -> result ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculates the number of whole input frames that would need to be read from the client in order to output the specified
|
||||||
|
number of output frames.
|
||||||
|
|
||||||
|
The returned value does not include cached input frames. It only returns the number of extra frames that would need to be
|
||||||
|
read from the input buffer in order to output the specified number of output frames.
|
||||||
|
*/
|
||||||
|
resampler_get_required_input_frame_count :: proc(pResampler: ^resampler, outputFrameCount: u64) -> u64 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculates the number of whole output frames that would be output after fully reading and consuming the specified number of
|
||||||
|
input frames.
|
||||||
|
*/
|
||||||
|
resampler_get_expected_output_frame_count :: proc(pResampler: ^resampler, inputFrameCount: u64) -> u64 ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves the latency introduced by the resampler in input frames.
|
||||||
|
*/
|
||||||
|
resampler_get_input_latency :: proc(pResampler: ^resampler) -> u64 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves the latency introduced by the resampler in output frames.
|
||||||
|
*/
|
||||||
|
resampler_get_output_latency :: proc(pResampler: ^resampler) -> u64 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Channel Conversion
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
channel_converter_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channelsIn: u32,
|
||||||
|
channelsOut: u32,
|
||||||
|
channelMapIn: [MAX_CHANNELS]channel,
|
||||||
|
channelMapOut: [MAX_CHANNELS]channel,
|
||||||
|
mixingMode: channel_mix_mode,
|
||||||
|
weights: [MAX_CHANNELS][MAX_CHANNELS]f32, /* [in][out]. Only used when mixingMode is set to ma_channel_mix_mode_custom_weights. */
|
||||||
|
}
|
||||||
|
|
||||||
|
channel_converter :: struct {
|
||||||
|
format: format,
|
||||||
|
channelsIn: u32,
|
||||||
|
channelsOut: u32,
|
||||||
|
channelMapIn: [MAX_CHANNELS]channel,
|
||||||
|
channelMapOut: [MAX_CHANNELS]channel,
|
||||||
|
mixingMode: channel_mix_mode,
|
||||||
|
weights: struct #raw_union {
|
||||||
|
f32: [MAX_CHANNELS][MAX_CHANNELS]f32,
|
||||||
|
s16: [MAX_CHANNELS][MAX_CHANNELS]i32,
|
||||||
|
},
|
||||||
|
isPassthrough: b8,
|
||||||
|
isSimpleShuffle: b8,
|
||||||
|
isSimpleMonoExpansion: b8,
|
||||||
|
isStereoToMono: b8,
|
||||||
|
shuffleTable: [MAX_CHANNELS]u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
channel_converter_config_init :: proc(format: format, channelsIn: u32, pChannelMapIn: ^channel, channelsOut: u32, pChannelMapOut: ^channel, mixingMode: channel_mix_mode) -> channel_converter_config ---
|
||||||
|
|
||||||
|
channel_converter_init :: proc(pConfig: ^channel_converter_config, pConverter: ^channel_converter) -> result ---
|
||||||
|
channel_converter_uninit :: proc(pConverter: ^channel_converter) ---
|
||||||
|
channel_converter_process_pcm_frames :: proc(pConverter: ^channel_converter, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Data Conversion
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
data_converter_config :: struct {
|
||||||
|
formatIn: format,
|
||||||
|
formatOut: format,
|
||||||
|
channelsIn: u32,
|
||||||
|
channelsOut: u32,
|
||||||
|
sampleRateIn: u32,
|
||||||
|
sampleRateOut: u32,
|
||||||
|
channelMapIn: [MAX_CHANNELS]channel,
|
||||||
|
channelMapOut: [MAX_CHANNELS]channel,
|
||||||
|
ditherMode: dither_mode,
|
||||||
|
channelMixMode: channel_mix_mode,
|
||||||
|
channelWeights: [MAX_CHANNELS][MAX_CHANNELS]f32, /* [in][out]. Only used when channelMixMode is set to ma_channel_mix_mode_custom_weights. */
|
||||||
|
resampling: struct {
|
||||||
|
algorithm: resample_algorithm,
|
||||||
|
allowDynamicSampleRate: b32,
|
||||||
|
linear: struct {
|
||||||
|
lpfOrderL: u32,
|
||||||
|
lpfNyquistFactor: f64,
|
||||||
|
},
|
||||||
|
speex: struct {
|
||||||
|
quality: c.int,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
data_converter :: struct {
|
||||||
|
config: data_converter_config,
|
||||||
|
channelConverter: channel_converter,
|
||||||
|
resampler: resampler,
|
||||||
|
hasPreFormatConversion: b8,
|
||||||
|
hasPostFormatConversion: b8,
|
||||||
|
hasChannelConverter: b8,
|
||||||
|
hasResampler: b8,
|
||||||
|
isPassthrough: b8,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
data_converter_config_init_default :: proc() -> data_converter_config ---
|
||||||
|
data_converter_config_init :: proc(formatIn, formatOut: format, channelsIn, channelsOut: u32, sampleRateIn, sampleRateOut: u32) -> data_converter_config ---
|
||||||
|
|
||||||
|
data_converter_init :: proc(pConfig: ^data_converter_config, pConverter: ^data_converter) -> result ---
|
||||||
|
data_converter_uninit :: proc(pConverter: ^data_converter) ---
|
||||||
|
data_converter_process_pcm_frames :: proc(pConverter: ^data_converter, pFramesIn: rawptr, pFrameCountIn: ^u64, pFramesOut: rawptr, pFrameCountOut: ^u64) -> result ---
|
||||||
|
data_converter_set_rate :: proc(pConverter: ^data_converter, sampleRateIn, sampleRateOut: u32) -> result ---
|
||||||
|
data_converter_set_rate_ratio :: proc(pConverter: ^data_converter, ratioInOut: f32) -> result ---
|
||||||
|
data_converter_get_required_input_frame_count :: proc(pConverter: ^data_converter, outputFrameCount: u64) -> u64 ---
|
||||||
|
data_converter_get_expected_output_frame_count :: proc(pConverter: ^data_converter, inputFrameCount: u64) -> u64 ---
|
||||||
|
data_converter_get_input_latency :: proc(pConverter: ^data_converter) -> u64 ---
|
||||||
|
data_converter_get_output_latency :: proc(pConverter: ^data_converter) -> u64 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Format Conversion
|
||||||
|
|
||||||
|
************************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
pcm_u8_to_s16 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_u8_to_s24 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_u8_to_s32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_u8_to_f32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s16_to_u8 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s16_to_s24 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s16_to_s32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s16_to_f32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s24_to_u8 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s24_to_s16 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s24_to_s32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s24_to_f32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s32_to_u8 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s32_to_s16 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s32_to_s24 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_s32_to_f32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_f32_to_u8 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_f32_to_s16 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_f32_to_s24 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_f32_to_s32 :: proc(pOut: rawptr, pIn: rawptr, count: u64, ditherMode: dither_mode) ---
|
||||||
|
pcm_convert :: proc(pOut: rawptr, formatOut: format, pIn: rawptr, formatIn: format, sampleCount: u64, ditherMode: dither_mode) ---
|
||||||
|
convert_pcm_frames_format :: proc(pOut: rawptr, formatOut: format, pIn: rawptr, formatIn: format, frameCount: u64, channels: u32, ditherMode: dither_mode) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Deinterleaves an interleaved buffer.
|
||||||
|
*/
|
||||||
|
deinterleave_pcm_frames :: proc(format: format, channels: u32, frameCount: u64, pInterleavedPCMFrames: rawptr, ppDeinterleavedPCMFrames: ^rawptr) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Interleaves a group of deinterleaved buffers.
|
||||||
|
*/
|
||||||
|
interleave_pcm_frames :: proc(format: format, channels: u32, frameCount: u64, ppDeinterleavedPCMFrames: ^rawptr, pInterleavedPCMFrames: rawptr) ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Channel Maps
|
||||||
|
|
||||||
|
************************************************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
This is used in the shuffle table to indicate that the channel index is undefined and should be ignored.
|
||||||
|
*/
|
||||||
|
CHANNEL_INDEX_NULL :: 255
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
/* Retrieves the channel position of the specified channel based on miniaudio's default channel map. */
|
||||||
|
channel_map_get_default_channel :: proc(channelCount: u32, channelIndex: u32) -> channel ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieves the channel position of the specified channel in the given channel map.
|
||||||
|
|
||||||
|
The pChannelMap parameter can be null, in which case miniaudio's default channel map will be assumed.
|
||||||
|
*/
|
||||||
|
channel_map_get_channel :: proc(pChannelMap: ^channel, channelCount: u32, channelIndex: u32) -> channel ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initializes a blank channel map.
|
||||||
|
|
||||||
|
When a blank channel map is specified anywhere it indicates that the native channel map should be used.
|
||||||
|
*/
|
||||||
|
channel_map_init_blank :: proc(channels: u32, pChannelMap: ^channel) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for retrieving a standard channel map.
|
||||||
|
|
||||||
|
The output channel map buffer must have a capacity of at least `channels`.
|
||||||
|
*/
|
||||||
|
get_standard_channel_map :: proc(standardChannelMap: standard_channel_map, channels: u32, pChannelMap: ^channel) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copies a channel map.
|
||||||
|
|
||||||
|
Both input and output channel map buffers must have a capacity of at at least `channels`.
|
||||||
|
*/
|
||||||
|
channel_map_copy :: proc(pOut: ^channel, pIn: ^channel, channels: u32) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copies a channel map if one is specified, otherwise copies the default channel map.
|
||||||
|
|
||||||
|
The output buffer must have a capacity of at least `channels`. If not NULL, the input channel map must also have a capacity of at least `channels`.
|
||||||
|
*/
|
||||||
|
channel_map_copy_or_default :: proc(pOut: ^channel, pIn: ^channel, channels: u32) ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Determines whether or not a channel map is valid.
|
||||||
|
|
||||||
|
A blank channel map is valid (all channels set to MA_CHANNEL_NONE). The way a blank channel map is handled is context specific, but
|
||||||
|
is usually treated as a passthrough.
|
||||||
|
|
||||||
|
Invalid channel maps:
|
||||||
|
- A channel map with no channels
|
||||||
|
- A channel map with more than one channel and a mono channel
|
||||||
|
|
||||||
|
The channel map buffer must have a capacity of at least `channels`.
|
||||||
|
*/
|
||||||
|
channel_map_valid :: proc(channels: u32, pChannelMap: ^channel) -> b32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for comparing two channel maps for equality.
|
||||||
|
|
||||||
|
This assumes the channel count is the same between the two.
|
||||||
|
|
||||||
|
Both channels map buffers must have a capacity of at least `channels`.
|
||||||
|
*/
|
||||||
|
channel_map_equal :: proc(channels: u32, pChannelMapA, pChannelMapB: ^channel) -> b32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for determining if a channel map is blank (all channels set to MA_CHANNEL_NONE).
|
||||||
|
|
||||||
|
The channel map buffer must have a capacity of at least `channels`.
|
||||||
|
*/
|
||||||
|
channel_map_blank :: proc(channels: u32, pChannelMap: ^channel) -> b32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for determining whether or not a channel is present in the given channel map.
|
||||||
|
|
||||||
|
The channel map buffer must have a capacity of at least `channels`.
|
||||||
|
*/
|
||||||
|
channel_map_contains_channel_position :: proc(channels: u32, pChannelMap: ^channel, channelPosition: channel) -> b32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Conversion Helpers
|
||||||
|
|
||||||
|
************************************************************************************************************************************************************/
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
/*
|
||||||
|
High-level helper for doing a full format conversion in one go. Returns the number of output frames. Call this with pOut set to NULL to
|
||||||
|
determine the required size of the output buffer. frameCountOut should be set to the capacity of pOut. If pOut is NULL, frameCountOut is
|
||||||
|
ignored.
|
||||||
|
|
||||||
|
A return value of 0 indicates an error.
|
||||||
|
|
||||||
|
This function is useful for one-off bulk conversions, but if you're streaming data you should use the ma_data_converter APIs instead.
|
||||||
|
*/
|
||||||
|
convert_frames :: proc(pOut: rawptr, frameCountOut: u64, formatOut: format, channelsOut: u32, sampleRateOut: u32, pIn: rawptr, frameCountIn: u64, formatIn: format, channelsIn: u32, sampleRateIn: u32) -> u64 ---
|
||||||
|
convert_frames_ex :: proc(pOut: rawptr, frameCountOut: u64, pIn: rawptr, frameCountIn: u64, pConfig: ^data_converter_config) -> u64 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Ring Buffer
|
||||||
|
|
||||||
|
************************************************************************************************************************************************************/
|
||||||
|
rb :: struct {
|
||||||
|
pBuffer: rawptr,
|
||||||
|
subbufferSizeInBytes: u32,
|
||||||
|
subbufferCount: u32,
|
||||||
|
subbufferStrideInBytes: u32,
|
||||||
|
encodedReadOffset: u32, /*atomic*/ /* Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
|
||||||
|
encodedWriteOffset: u32, /*atomic*/ /* Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
|
||||||
|
ownsBuffer: b8, /* Used to know whether or not miniaudio is responsible for free()-ing the buffer. */
|
||||||
|
clearOnWriteAcquire: b8, /* When set, clears the acquired write buffer before returning from ma_rb_acquire_write(). */
|
||||||
|
allocationCallbacks: allocation_callbacks,
|
||||||
|
}
|
||||||
|
|
||||||
|
pcm_rb :: struct {
|
||||||
|
rb: rb,
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
rb_init_ex :: proc(subbufferSizeInBytes, subbufferCount, subbufferStrideInBytes: c.size_t, pOptionalPreallocatedBuffer: rawptr, pAllocationCallbacks: ^allocation_callbacks, pRB: ^rb) -> result ---
|
||||||
|
rb_init :: proc(bufferSizeInBytes: c.size_t, pOptionalPreallocatedBuffer: rawptr, pAllocationCallbacks: ^allocation_callbacks, pRB: ^rb) -> result ---
|
||||||
|
rb_uninit :: proc(pRB: ^rb) ---
|
||||||
|
rb_reset :: proc(pRB: ^rb) ---
|
||||||
|
rb_acquire_read :: proc(pRB: ^rb, pSizeInBytes: ^c.size_t, ppBufferOut: ^rawptr) -> result ---
|
||||||
|
rb_commit_read :: proc(pRB: ^rb, sizeInBytes: c.size_t, pBufferOut: rawptr) -> result ---
|
||||||
|
rb_acquire_write :: proc(pRB: ^rb, pSizeInBytes: ^c.size_t, ppBufferOut: ^rawptr) -> result ---
|
||||||
|
rb_commit_write :: proc(pRB: ^rb, sizeInBytes: c.size_t, pBufferOut: rawptr) -> result ---
|
||||||
|
rb_seek_read :: proc(pRB: ^rb, offsetInBytes: c.size_t) -> result ---
|
||||||
|
rb_seek_write :: proc(pRB: ^rb, offsetInBytes: c.size_t) -> result ---
|
||||||
|
rb_pointer_distance :: proc(pRB: ^rb) -> i32 --- /* Returns the distance between the write pointer and the read pointer. Should never be negative for a correct program. Will return the number of bytes that can be read before the read pointer hits the write pointer. */
|
||||||
|
rb_available_read :: proc(pRB: ^rb) -> u32 ---
|
||||||
|
rb_available_write :: proc(pRB: ^rb) -> u32 ---
|
||||||
|
rb_get_subbuffer_size :: proc(pRB: ^rb) -> c.size_t ---
|
||||||
|
rb_get_subbuffer_stride :: proc(pRB: ^rb) -> c.size_t ---
|
||||||
|
rb_get_subbuffer_offset :: proc(pRB: ^rb, subbufferIndex: c.size_t) -> c.size_t ---
|
||||||
|
rb_get_subbuffer_ptr :: proc(pRB: ^rb, subbufferIndex: c.size_t, pBuffer: rawptr) -> rawptr ---
|
||||||
|
|
||||||
|
pcm_rb_init_ex :: proc(format: format, channels: u32, subbufferSizeInFrames, subbufferCount, subbufferStrideInFrames: u32, pOptionalPreallocatedBuffer: rawptr, pAllocationCallbacks: ^allocation_callbacks, pRB: ^pcm_rb) -> result ---
|
||||||
|
pcm_rb_init :: proc(format: format, channels: u32, bufferSizeInFrames: u32, pOptionalPreallocatedBuffer: rawptr, pAllocationCallbacks: ^allocation_callbacks, pRB: ^pcm_rb) -> result ---
|
||||||
|
pcm_rb_uninit :: proc(pRB: ^pcm_rb) ---
|
||||||
|
pcm_rb_reset :: proc(pRB: ^pcm_rb) ---
|
||||||
|
pcm_rb_acquire_read :: proc(pRB: ^pcm_rb, pSizeInFrames: ^u32, ppBufferOut: ^rawptr) -> result ---
|
||||||
|
pcm_rb_commit_read :: proc(pRB: ^pcm_rb, sizeInFrames: u32, pBufferOut: rawptr) -> result ---
|
||||||
|
pcm_rb_acquire_write :: proc(pRB: ^pcm_rb, pSizeInFrames: ^u32, ppBufferOut: ^rawptr) -> result ---
|
||||||
|
pcm_rb_commit_write :: proc(pRB: ^pcm_rb, sizeInFrames: u32, pBufferOut: rawptr) -> result ---
|
||||||
|
pcm_rb_seek_read :: proc(pRB: ^pcm_rb, offsetInFrames: u32) -> result ---
|
||||||
|
pcm_rb_seek_write :: proc(pRB: ^pcm_rb, offsetInFrames: u32) -> result ---
|
||||||
|
pcm_rb_pointer_distance :: proc(pRB: ^pcm_rb) -> i32 --- /* Return value is in frames. */
|
||||||
|
pcm_rb_available_read :: proc(pRB: ^pcm_rb) -> u32 ---
|
||||||
|
pcm_rb_available_write :: proc(pRB: ^pcm_rb) -> u32 ---
|
||||||
|
pcm_rb_get_subbuffer_size :: proc(pRB: ^pcm_rb) -> u32 ---
|
||||||
|
pcm_rb_get_subbuffer_stride :: proc(pRB: ^pcm_rb) -> u32 ---
|
||||||
|
pcm_rb_get_subbuffer_offset :: proc(pRB: ^pcm_rb, subbufferIndex: u32) -> u32 ---
|
||||||
|
pcm_rb_get_subbuffer_ptr :: proc(pRB: ^pcm_rb, subbufferIndex: u32, pBuffer: rawptr) -> rawptr ---
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The idea of the duplex ring buffer is to act as the intermediary buffer when running two asynchronous devices in a duplex set up. The
|
||||||
|
capture device writes to it, and then a playback device reads from it.
|
||||||
|
|
||||||
|
At the moment this is just a simple naive implementation, but in the future I want to implement some dynamic resampling to seamlessly
|
||||||
|
handle desyncs. Note that the API is work in progress and may change at any time in any version.
|
||||||
|
|
||||||
|
The size of the buffer is based on the capture side since that's what'll be written to the buffer. It is based on the capture period size
|
||||||
|
in frames. The internal sample rate of the capture device is also needed in order to calculate the size.
|
||||||
|
*/
|
||||||
|
duplex_rb :: struct {
|
||||||
|
rb: pcm_rb,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
duplex_rb_init :: proc(captureFormat: format, captureChannels: u32, sampleRate: u32, captureInternalSampleRate, captureInternalPeriodSizeInFrames: u32, pAllocationCallbacks: ^allocation_callbacks, pRB: ^duplex_rb) -> result ---
|
||||||
|
duplex_rb_uninit :: proc(pRB: ^duplex_rb) -> result ---
|
||||||
|
}
|
||||||
|
|
||||||
+1476
File diff suppressed because it is too large
Load Diff
+1144
File diff suppressed because it is too large
Load Diff
Vendored
+1490
File diff suppressed because it is too large
Load Diff
Vendored
+352
@@ -0,0 +1,352 @@
|
|||||||
|
package miniaudio
|
||||||
|
|
||||||
|
when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Biquad Filtering
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
biquad_coefficient :: struct #raw_union {
|
||||||
|
f32: f32,
|
||||||
|
s32: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
biquad_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
b0: f64,
|
||||||
|
b1: f64,
|
||||||
|
b2: f64,
|
||||||
|
a0: f64,
|
||||||
|
a1: f64,
|
||||||
|
a2: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
biquad :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
b0: biquad_coefficient,
|
||||||
|
b1: biquad_coefficient,
|
||||||
|
b2: biquad_coefficient,
|
||||||
|
a1: biquad_coefficient,
|
||||||
|
a2: biquad_coefficient,
|
||||||
|
r1: [MAX_CHANNELS]biquad_coefficient,
|
||||||
|
r2: [MAX_CHANNELS]biquad_coefficient,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
biquad_config_init :: proc(format: format, channels: u32, b0, b1, b2, a0, a1, a2: f64) -> biquad_config ---
|
||||||
|
|
||||||
|
biquad_init :: proc(pConfig: ^biquad_config, pBQ: ^biquad) -> result ---
|
||||||
|
biquad_reinit :: proc(pConfig: ^biquad_config, pBQ: ^biquad) -> result ---
|
||||||
|
biquad_process_pcm_frames :: proc(pBQ: ^biquad, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
biquad_get_latency :: proc(pBQ: ^biquad) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Low-Pass Filtering
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
lpf1_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
cutoffFrequency: f64,
|
||||||
|
q: f64,
|
||||||
|
}
|
||||||
|
lpf2_config :: lpf1_config
|
||||||
|
|
||||||
|
lpf1 :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
a: biquad_coefficient,
|
||||||
|
r1: [MAX_CHANNELS]biquad_coefficient,
|
||||||
|
}
|
||||||
|
|
||||||
|
lpf2 :: struct {
|
||||||
|
bq: biquad, /* The second order low-pass filter is implemented as a biquad filter. */
|
||||||
|
}
|
||||||
|
|
||||||
|
lpf_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
cutoffFrequency: f64,
|
||||||
|
order: u32, /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
|
||||||
|
}
|
||||||
|
|
||||||
|
lpf :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
lpf1Count: u32,
|
||||||
|
lpf2Count: u32,
|
||||||
|
lpf1: [1]lpf1,
|
||||||
|
lpf2: [MAX_FILTER_ORDER/2]lpf2,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
lpf1_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency: f64) -> lpf1_config ---
|
||||||
|
lpf2_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency, q: f64) -> lpf2_config ---
|
||||||
|
|
||||||
|
lpf1_init :: proc(pConfig: ^lpf1_config, pLPF: ^lpf1) -> result ---
|
||||||
|
lpf1_reinit :: proc(pConfig: ^lpf1_config, pLPF: ^lpf1) -> result ---
|
||||||
|
lpf1_process_pcm_frames :: proc(pLPF: ^lpf1, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
lpf1_get_latency :: proc(pLPF: ^lpf1) -> u32 ---
|
||||||
|
|
||||||
|
lpf2_init :: proc(pConfig: ^lpf2_config, pLPF: ^lpf2) -> result ---
|
||||||
|
lpf2_reinit :: proc(pConfig: ^lpf2_config, pLPF: ^lpf2) -> result ---
|
||||||
|
lpf2_process_pcm_frames :: proc(pLPF: ^lpf2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
lpf2_get_latency :: proc(pLPF: ^lpf2) -> u32 ---
|
||||||
|
|
||||||
|
lpf_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency: f64, order: u32) -> lpf_config ---
|
||||||
|
|
||||||
|
lpf_init :: proc(pConfig: ^lpf_config, pLPF: ^lpf) -> result ---
|
||||||
|
lpf_reinit :: proc(pConfig: ^lpf_config, pLPF: ^lpf) -> result ---
|
||||||
|
lpf_process_pcm_frames :: proc(pLPF: ^lpf, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
lpf_get_latency :: proc(pLPF: ^lpf) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
High-Pass Filtering
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
hpf1_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
cutoffFrequency: f64,
|
||||||
|
q: f64,
|
||||||
|
}
|
||||||
|
hpf2_config :: hpf1_config
|
||||||
|
|
||||||
|
hpf1 :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
a: biquad_coefficient,
|
||||||
|
r1: [MAX_CHANNELS]biquad_coefficient,
|
||||||
|
}
|
||||||
|
|
||||||
|
hpf2 :: struct {
|
||||||
|
bq: biquad, /* The second order low-pass filter is implemented as a biquad filter. */
|
||||||
|
}
|
||||||
|
|
||||||
|
hpf_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
cutoffFrequency: f64,
|
||||||
|
order: u32, /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
|
||||||
|
}
|
||||||
|
|
||||||
|
hpf :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
hpf1Count: u32,
|
||||||
|
hpf2Count: u32,
|
||||||
|
hpf1: [1]hpf1,
|
||||||
|
hpf2: [MAX_FILTER_ORDER/2]hpf2,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
hpf1_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency: f64) -> hpf1_config ---
|
||||||
|
hpf2_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency, q: f64) -> hpf2_config ---
|
||||||
|
|
||||||
|
hpf1_init :: proc(pConfig: ^hpf1_config, pHPF: ^hpf1) -> result ---
|
||||||
|
hpf1_reinit :: proc(pConfig: ^hpf1_config, pHPF: ^hpf1) -> result ---
|
||||||
|
hpf1_process_pcm_frames :: proc(pHPF: ^hpf1, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
hpf1_get_latency :: proc(pHPF: ^hpf1) -> u32 ---
|
||||||
|
|
||||||
|
hpf2_init :: proc(pConfig: ^hpf2_config, pHPF: ^hpf2) -> result ---
|
||||||
|
hpf2_reinit :: proc(pConfig: ^hpf2_config, pHPF: ^hpf2) -> result ---
|
||||||
|
hpf2_process_pcm_frames :: proc(pHPF: ^hpf2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
hpf2_get_latency :: proc(pHPF: ^hpf2) -> u32 ---
|
||||||
|
|
||||||
|
hpf_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency: f64, order: u32) -> hpf_config ---
|
||||||
|
|
||||||
|
hpf_init :: proc(pConfig: ^hpf_config, pHPF: ^hpf) -> result ---
|
||||||
|
hpf_reinit :: proc(pConfig: ^hpf_config, pHPF: ^hpf) -> result ---
|
||||||
|
hpf_process_pcm_frames :: proc(pHPF: ^hpf, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
hpf_get_latency :: proc(pHPF: ^hpf) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Band-Pass Filtering
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
bpf2_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
cutoffFrequency: f64,
|
||||||
|
q: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf2 :: struct {
|
||||||
|
bq: biquad, /* The second order band-pass filter is implemented as a biquad filter. */
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
cutoffFrequency: f64,
|
||||||
|
order: u32, /* If set to 0, will be treated as a passthrough (no filtering will be applied). */
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
bpf2Count: u32,
|
||||||
|
bpf2: [MAX_FILTER_ORDER/2]bpf2,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
bpf2_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency: f64, q: f64) -> bpf2_config ---
|
||||||
|
|
||||||
|
bpf2_init :: proc(pConfig: ^bpf2_config, pBPF: ^bpf2) -> result ---
|
||||||
|
bpf2_reinit :: proc(pConfig: ^bpf2_config, pBPF: ^bpf2) -> result ---
|
||||||
|
bpf2_process_pcm_frames :: proc(pBPF: ^bpf2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
bpf2_get_latency :: proc(pBPF: ^bpf2) -> u32 ---
|
||||||
|
|
||||||
|
bpf_config_init :: proc(format: format, channels: u32, sampleRate: u32, cutoffFrequency: f64, order: u32) -> bpf_config ---
|
||||||
|
|
||||||
|
bpf_init :: proc(pConfig: ^bpf_config, pBPF: ^bpf) -> result ---
|
||||||
|
bpf_reinit :: proc(pConfig: ^bpf_config, pBPF: ^bpf) -> result ---
|
||||||
|
bpf_process_pcm_frames :: proc(pBPF: ^bpf, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
bpf_get_latency :: proc(pBPF: ^bpf) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Notching Filter
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
notch_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
q: f64,
|
||||||
|
frequency: f64,
|
||||||
|
}
|
||||||
|
notch2_config :: notch_config
|
||||||
|
|
||||||
|
notch2 :: struct {
|
||||||
|
bq: biquad,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
notch2_config_init :: proc(format: format, channels: u32, sampleRate: u32, q: f64, frequency: f64) -> notch2_config ---
|
||||||
|
|
||||||
|
notch2_init :: proc(pConfig: ^notch2_config, pFilter: ^notch2) -> result ---
|
||||||
|
notch2_reinit :: proc(pConfig: ^notch2_config, pFilter: ^notch2) -> result ---
|
||||||
|
notch2_process_pcm_frames :: proc(pFilter: ^notch2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
notch2_get_latency :: proc(pFilter: ^notch2) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Peaking EQ Filter
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
peak_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
gainDB: f64,
|
||||||
|
q: f64,
|
||||||
|
frequency: f64,
|
||||||
|
}
|
||||||
|
peak2_config :: peak_config
|
||||||
|
|
||||||
|
peak2 :: struct {
|
||||||
|
bq: biquad,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
peak2_config_init :: proc(format: format, channels: u32, sampleRate: u32, gainDB, q, frequency: f64) -> peak2_config ---
|
||||||
|
|
||||||
|
peak2_init :: proc(pConfig: ^peak2_config, pFilter: ^peak2) -> result ---
|
||||||
|
peak2_reinit :: proc(pConfig: ^peak2_config, pFilter: ^peak2) -> result ---
|
||||||
|
peak2_process_pcm_frames :: proc(pFilter: ^peak2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
peak2_get_latency :: proc(pFilter: ^peak2) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
Low Shelf Filter
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
loshelf_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
gainDB: f64,
|
||||||
|
shelfSlope: f64,
|
||||||
|
frequency: f64,
|
||||||
|
}
|
||||||
|
loshelf2_config :: loshelf_config
|
||||||
|
|
||||||
|
loshelf2 :: struct {
|
||||||
|
bq: biquad,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
loshelf2_config_init :: proc(format: format, channels: u32, sampleRate: u32, gainDB, shelfSlope, frequency: f64) -> loshelf2_config ---
|
||||||
|
|
||||||
|
loshelf2_init :: proc(pConfig: ^loshelf2_config, pFilter: ^loshelf2) -> result ---
|
||||||
|
loshelf2_reinit :: proc(pConfig: ^loshelf2_config, pFilter: ^loshelf2) -> result ---
|
||||||
|
loshelf2_process_pcm_frames :: proc(pFilter: ^loshelf2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
loshelf2_get_latency :: proc(pFilter: ^loshelf2) -> u32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************************************
|
||||||
|
|
||||||
|
High Shelf Filter
|
||||||
|
|
||||||
|
**************************************************************************************************************************************************************/
|
||||||
|
hishelf_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sampleRate: u32,
|
||||||
|
gainDB: f64,
|
||||||
|
shelfSlope: f64,
|
||||||
|
frequency: f64,
|
||||||
|
}
|
||||||
|
hishelf2_config :: hishelf_config
|
||||||
|
|
||||||
|
hishelf2 :: struct {
|
||||||
|
bq: biquad,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
hishelf2_config_init :: proc(format: format, channels: u32, sampleRate: u32, gainDB, shelfSlope, frequency: f64) -> hishelf2_config ---
|
||||||
|
|
||||||
|
hishelf2_init :: proc(pConfig: ^hishelf2_config, pFilter: ^hishelf2) -> result ---
|
||||||
|
hishelf2_reinit :: proc(pConfig: ^hishelf2_config, pFilter: ^hishelf2) -> result ---
|
||||||
|
hishelf2_process_pcm_frames :: proc(pFilter: ^hishelf2, pFramesOut: rawptr, pFramesIn: rawptr, frameCount: u64) -> result ---
|
||||||
|
hishelf2_get_latency :: proc(pFilter: ^hishelf2) -> u32 ---
|
||||||
|
}
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package miniaudio
|
||||||
|
|
||||||
|
import c "core:c/libc"
|
||||||
|
|
||||||
|
when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
|
||||||
|
|
||||||
|
MAX_LOG_CALLBACKS :: 4
|
||||||
|
|
||||||
|
log_callback_proc :: proc "c" (pUserData: rawptr, level: u32, pMessage: cstring)
|
||||||
|
|
||||||
|
log_callback :: struct {
|
||||||
|
onLog: log_callback_proc,
|
||||||
|
pUserData: rawptr,
|
||||||
|
}
|
||||||
|
|
||||||
|
log :: struct {
|
||||||
|
callbacks: [MAX_LOG_CALLBACKS]log_callback,
|
||||||
|
callbackCount: u32,
|
||||||
|
allocationCallbacks: allocation_callbacks, /* Need to store these persistently because log_postv() might need to allocate a buffer on the heap. */
|
||||||
|
lock: (struct {} when NO_THREADING else mutex),
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
log_callback_init :: proc(onLog: log_callback_proc, pUserData: rawptr) -> log_callback ---
|
||||||
|
|
||||||
|
log_init :: proc(pAllocationCallbacks: ^allocation_callbacks, pLog: ^log) -> result ---
|
||||||
|
log_uninit :: proc(pLog: ^log) ---
|
||||||
|
log_register_callback :: proc(pLog: ^log, callback: log_callback) -> result ---
|
||||||
|
log_unregister_callback :: proc(pLog: ^log, callback: log_callback) -> result ---
|
||||||
|
log_post :: proc(pLog: ^log, level: u32, pMessage: cstring) -> result ---
|
||||||
|
log_postv :: proc(pLog: ^log, level: u32, pFormat: cstring, args: c.va_list) -> result ---
|
||||||
|
log_postf :: proc(pLog: ^log, level: u32, pFormat: cstring, #c_vararg args: ..any) -> result ---
|
||||||
|
}
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
all:
|
||||||
|
mkdir -p ../lib
|
||||||
|
gcc -c -O2 -Os -fPIC miniaudio.c
|
||||||
|
ar rcs ../lib/miniaudio.a miniaudio.o
|
||||||
|
#gcc -fPIC -shared -Wl,-soname=miniaudio.so -o ../lib/miniaudio.so miniaudio.o
|
||||||
|
rm *.o
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
if not exist "..\lib" mkdir ..\lib
|
||||||
|
|
||||||
|
cl -nologo -MT -TC -O2 -c miniaudio.c
|
||||||
|
lib -nologo miniaudio.obj -out:..\lib\miniaudio.lib
|
||||||
|
|
||||||
|
del *.obj
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#define STB_VORBIS_HEADER_ONLY
|
||||||
|
#include "../../stb/src/stb_vorbis.c" /* Enables Vorbis decoding. */
|
||||||
|
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include "miniaudio.h"
|
||||||
|
|
||||||
|
/* stb_vorbis implementation must come after the implementation of miniaudio. */
|
||||||
|
#undef STB_VORBIS_HEADER_ONLY
|
||||||
|
#include "../../stb/src/stb_vorbis.c"
|
||||||
Vendored
+70273
File diff suppressed because it is too large
Load Diff
Vendored
+230
@@ -0,0 +1,230 @@
|
|||||||
|
package miniaudio
|
||||||
|
|
||||||
|
when ODIN_OS == "windows" { foreign import lib "../lib/miniaudio.lib" }
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
/*
|
||||||
|
Adjust buffer size based on a scaling factor.
|
||||||
|
|
||||||
|
This just multiplies the base size by the scaling factor, making sure it's a size of at least 1.
|
||||||
|
*/
|
||||||
|
scale_buffer_size :: proc(baseBufferSize: u32, scale: f32) -> u32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculates a buffer size in milliseconds from the specified number of frames and sample rate.
|
||||||
|
*/
|
||||||
|
calculate_buffer_size_in_milliseconds_from_frames :: proc(bufferSizeInFrames: u32, sampleRate: u32) -> u32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculates a buffer size in frames from the specified number of milliseconds and sample rate.
|
||||||
|
*/
|
||||||
|
calculate_buffer_size_in_frames_from_milliseconds :: proc(bufferSizeInMilliseconds: u32, sampleRate: u32) -> u32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copies PCM frames from one buffer to another.
|
||||||
|
*/
|
||||||
|
copy_pcm_frames :: proc(dst: rawptr, src: rawptr, frameCount: u64, format: format, channels: u32) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copies silent frames into the given buffer.
|
||||||
|
|
||||||
|
Remarks
|
||||||
|
-------
|
||||||
|
For all formats except `ma_format_u8`, the output buffer will be filled with 0. For `ma_format_u8` it will be filled with 128. The reason for this is that it
|
||||||
|
makes more sense for the purpose of mixing to initialize it to the center point.
|
||||||
|
*/
|
||||||
|
silence_pcm_frames :: proc(p: rawptr, frameCount: u64, format: format, channels: u32) ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Offsets a pointer by the specified number of PCM frames.
|
||||||
|
*/
|
||||||
|
offset_pcm_frames_ptr :: proc(p: rawptr, offsetInFrames: u64, format: format, channels: u32) -> rawptr ---
|
||||||
|
offset_pcm_frames_const_ptr :: proc(p: rawptr, offsetInFrames: u64, format: format, channels: u32) -> rawptr ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Clips f32 samples.
|
||||||
|
*/
|
||||||
|
clip_samples_f32 :: proc(p: [^]f32, sampleCount: u64) ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for applying a volume factor to samples.
|
||||||
|
|
||||||
|
Note that the source and destination buffers can be the same, in which case it'll perform the operation in-place.
|
||||||
|
*/
|
||||||
|
copy_and_apply_volume_factor_u8 :: proc(pSamplesOut, pSamplesIn: [^]u8, sampleCount: u64, factor: f64) ---
|
||||||
|
copy_and_apply_volume_factor_s16 :: proc(pSamplesOut, pSamplesIn: [^]i16, sampleCount: u64, factor: f64) ---
|
||||||
|
copy_and_apply_volume_factor_s24 :: proc(pSamplesOut, pSamplesIn: rawptr, sampleCount: u64, factor: f64) ---
|
||||||
|
copy_and_apply_volume_factor_s32 :: proc(pSamplesOut, pSamplesIn: [^]i32, sampleCount: u64, factor: f64) ---
|
||||||
|
copy_and_apply_volume_factor_f32 :: proc(pSamplesOut, pSamplesIn: [^]f32, sampleCount: u64, factor: f64) ---
|
||||||
|
|
||||||
|
apply_volume_factor_u8 :: proc(pSamples: [^]u8, sampleCount: u64, factor: f32) ---
|
||||||
|
apply_volume_factor_s16 :: proc(pSamples: [^]i16, sampleCount: u64, factor: f32) ---
|
||||||
|
apply_volume_factor_s24 :: proc(pSamples: rawptr, sampleCount: u64, factor: f32) ---
|
||||||
|
apply_volume_factor_s32 :: proc(pSamples: [^]i32, sampleCount: u64, factor: f32) ---
|
||||||
|
apply_volume_factor_f32 :: proc(pSamples: [^]f32, sampleCount: u64, factor: f32) ---
|
||||||
|
|
||||||
|
copy_and_apply_volume_factor_pcm_frames_u8 :: proc(pPCMFramesOut, pPCMFramesIn: [^]u8, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
copy_and_apply_volume_factor_pcm_frames_s16 :: proc(pPCMFramesOut, pPCMFramesIn: [^]i16, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
copy_and_apply_volume_factor_pcm_frames_s24 :: proc(pPCMFramesOut, pPCMFramesIn: rawptr, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
copy_and_apply_volume_factor_pcm_frames_s32 :: proc(pPCMFramesOut, pPCMFramesIn: [^]i32, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
copy_and_apply_volume_factor_pcm_frames_f32 :: proc(pPCMFramesOut, pPCMFramesIn: [^]f32, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
copy_and_apply_volume_factor_pcm_frames :: proc(pFramesOut, pFramesIn: rawptr, frameCount: u64, format: format, channels: u32, factor: f32) ---
|
||||||
|
|
||||||
|
apply_volume_factor_pcm_frames_u8 :: proc(pFrames: [^]u8, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
apply_volume_factor_pcm_frames_s16 :: proc(pFrames: [^]i16, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
apply_volume_factor_pcm_frames_s24 :: proc(pFrames: rawptr, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
apply_volume_factor_pcm_frames_s32 :: proc(pFrames: [^]i32, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
apply_volume_factor_pcm_frames_f32 :: proc(pFrames: [^]f32, frameCount: u64, channels: u32, factor: f32) ---
|
||||||
|
apply_volume_factor_pcm_frames :: proc(pFrames: rawptr, frameCount: u64, format: format, channels: u32, factor: f32) ---
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for converting a linear factor to gain in decibels.
|
||||||
|
*/
|
||||||
|
factor_to_gain_db :: proc(factor: f32) -> f32 ---
|
||||||
|
|
||||||
|
/*
|
||||||
|
Helper for converting gain in decibels to a linear factor.
|
||||||
|
*/
|
||||||
|
gain_db_to_factor :: proc(gain: f32) -> f32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
zero_pcm_frames :: #force_inline proc "c" (p: rawptr, frameCount: u64, format: format, channels: u32) {
|
||||||
|
silence_pcm_frames(p, frameCount, format, channels)
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_pcm_frames_ptr_f32 :: #force_inline proc "c" (p: [^]f32, offsetInFrames: u64, channels: u32) -> [^]f32 {
|
||||||
|
return cast([^]f32)offset_pcm_frames_ptr(p, offsetInFrames, .f32, channels)
|
||||||
|
}
|
||||||
|
offset_pcm_frames_const_ptr_f32 :: #force_inline proc "c" (p: [^]f32, offsetInFrames: u64, channels: u32) -> [^]f32 {
|
||||||
|
return cast([^]f32)offset_pcm_frames_ptr(p, offsetInFrames, .f32, channels)
|
||||||
|
}
|
||||||
|
|
||||||
|
clip_pcm_frames_f32 :: #force_inline proc "c" (p: [^]f32, frameCount: u64, channels: u32) {
|
||||||
|
clip_samples_f32(p, frameCount*u64(channels))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
data_source :: struct {}
|
||||||
|
|
||||||
|
data_source_vtable :: struct {
|
||||||
|
onRead: proc "c" (pDataSource: ^data_source, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> result,
|
||||||
|
onSeek: proc "c" (pDataSource: ^data_source, frameIndex: u64) -> result,
|
||||||
|
onMap: proc "c" (pDataSource: ^data_source, ppFramesOut: ^rawptr, pFrameCount: ^u64) -> result, /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||||
|
onUnmap: proc "c" (pDataSource: ^data_source, frameCount: u64) -> result,
|
||||||
|
onGetDataFormat: proc "c" (pDataSource: ^data_source, pFormat: ^format, pChannels: ^u32, pSampleRate: ^u32) -> result,
|
||||||
|
onGetCursor: proc "c" (pDataSource: ^data_source, pCursor: ^u64) -> result,
|
||||||
|
onGetLength: proc "c" (pDataSource: ^data_source, pLength: ^u64) -> result,
|
||||||
|
}
|
||||||
|
data_source_callbacks :: data_source_vtable /* TODO: Remove ma_data_source_callbacks in version 0.11. */
|
||||||
|
|
||||||
|
data_source_get_next_proc :: proc "c" (pDataSource: ^data_source) -> ^data_source
|
||||||
|
|
||||||
|
data_source_config :: struct {
|
||||||
|
vtable: ^data_source_vtable, /* Can be null, which is useful for proxies. */
|
||||||
|
}
|
||||||
|
|
||||||
|
data_source_base :: struct {
|
||||||
|
cb: data_source_callbacks, /* TODO: Remove this. */
|
||||||
|
|
||||||
|
/* Variables below are placeholder and not yet used. */
|
||||||
|
vtable: ^data_source_vtable,
|
||||||
|
rangeBegInFrames: u64,
|
||||||
|
rangeEndInFrames: u64, /* Set to -1 for unranged (default). */
|
||||||
|
loopBegInFrames: u64, /* Relative to rangeBegInFrames. */
|
||||||
|
loopEndInFrames: u64, /* Relative to rangeBegInFrames. Set to -1 for the end of the range. */
|
||||||
|
pCurrent: ^data_source, /* When non-NULL, the data source being initialized will act as a proxy and will route all operations to pCurrent. Used in conjunction with pNext/onGetNext for seamless chaining. */
|
||||||
|
pNext: ^data_source, /* When set to NULL, onGetNext will be used. */
|
||||||
|
onGetNext: ^data_source_get_next_proc, /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
ma_data_source_config_init :: proc() -> data_source_config ---
|
||||||
|
|
||||||
|
data_source_init :: proc(pConfig: ^data_source_config, pDataSource: ^data_source) -> result ---
|
||||||
|
data_source_uninit :: proc(pDataSource: ^data_source) ---
|
||||||
|
data_source_read_pcm_frames :: proc(pDataSource: ^data_source, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64, loop: b32) -> result --- /* Must support pFramesOut = NULL in which case a forward seek should be performed. */
|
||||||
|
data_source_seek_pcm_frames :: proc(pDataSource: ^data_source, frameCount: u64, pFramesSeeked: ^u64, loop: b32) -> result --- /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount); */
|
||||||
|
data_source_seek_to_pcm_frame :: proc(pDataSource: ^data_source, frameIndex: u64) -> result ---
|
||||||
|
data_source_map :: proc(pDataSource: ^data_source, ppFramesOut: ^rawptr, pFrameCount: ^u64) -> result --- /* Returns MA_NOT_IMPLEMENTED if mapping is not supported. */
|
||||||
|
data_source_unmap :: proc(pDataSource: ^data_source, frameCount: u64) -> result --- /* Returns MA_AT_END if the end has been reached. */
|
||||||
|
data_source_get_data_format :: proc(pDataSource: ^data_source, pFormat: ^format, pChannels: ^u32, pSampleRate: ^u32) -> result ---
|
||||||
|
data_source_get_cursor_in_pcm_frames :: proc(pDataSource: ^data_source, pCursor: ^u64) -> result ---
|
||||||
|
data_source_get_length_in_pcm_frames :: proc(pDataSource: ^data_source, pLength: ^u64) -> result --- /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */
|
||||||
|
// #if defined(MA_EXPERIMENTAL__DATA_LOOPING_AND_CHAINING)
|
||||||
|
// MA_API ma_result ma_data_source_set_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 rangeBegInFrames, ma_uint64 rangeEndInFrames);
|
||||||
|
// MA_API void ma_data_source_get_range_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pRangeBegInFrames, ma_uint64* pRangeEndInFrames);
|
||||||
|
// MA_API ma_result ma_data_source_set_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64 loopBegInFrames, ma_uint64 loopEndInFrames);
|
||||||
|
// MA_API void ma_data_source_get_loop_point_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLoopBegInFrames, ma_uint64* pLoopEndInFrames);
|
||||||
|
// MA_API ma_result ma_data_source_set_current(ma_data_source* pDataSource, ma_data_source* pCurrentDataSource);
|
||||||
|
// MA_API ma_data_source* ma_data_source_get_current(ma_data_source* pDataSource);
|
||||||
|
// MA_API ma_result ma_data_source_set_next(ma_data_source* pDataSource, ma_data_source* pNextDataSource);
|
||||||
|
// MA_API ma_data_source* ma_data_source_get_next(ma_data_source* pDataSource);
|
||||||
|
// MA_API ma_result ma_data_source_set_next_callback(ma_data_source* pDataSource, ma_data_source_get_next_proc onGetNext);
|
||||||
|
// MA_API ma_data_source_get_next_proc ma_data_source_get_next_callback(ma_data_source* pDataSource);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
audio_buffer_ref :: struct {
|
||||||
|
ds: data_source_base,
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
cursor: u64,
|
||||||
|
sizeInFrames: u64,
|
||||||
|
pData: rawptr,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
audio_buffer_ref_init :: proc(format: format, channels: u32, pData: rawptr, sizeInFrames: u64, pAudioBufferRef: ^audio_buffer_ref) -> result ---
|
||||||
|
audio_buffer_ref_uninit :: proc(pAudioBufferRef: ^audio_buffer_ref) ---
|
||||||
|
audio_buffer_ref_set_data :: proc(pAudioBufferRef: ^audio_buffer_ref, pData: rawptr, sizeInFrames: u64) -> result ---
|
||||||
|
audio_buffer_ref_read_pcm_frames :: proc(pAudioBufferRef: ^audio_buffer_ref, pFramesOut: rawptr, frameCount: u64, loop: b32) -> u64 ---
|
||||||
|
audio_buffer_ref_seek_to_pcm_frame :: proc(pAudioBufferRef: ^audio_buffer_ref, frameIndex: u64) -> result ---
|
||||||
|
audio_buffer_ref_map :: proc(pAudioBufferRef: ^audio_buffer_ref, ppFramesOut: ^rawptr, pFrameCount: ^u64) -> result ---
|
||||||
|
audio_buffer_ref_unmap :: proc(pAudioBufferRef: ^audio_buffer_ref, frameCount: u64) -> result --- /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||||
|
audio_buffer_ref_at_end :: proc(pAudioBufferRef: ^audio_buffer_ref) -> b32 ---
|
||||||
|
audio_buffer_ref_get_cursor_in_pcm_frames :: proc(pAudioBufferRef: ^audio_buffer_ref, pCursor: ^u64) -> result ---
|
||||||
|
audio_buffer_ref_get_length_in_pcm_frames :: proc(pAudioBufferRef: ^audio_buffer_ref, pLength: ^u64) -> result ---
|
||||||
|
audio_buffer_ref_get_available_frames :: proc(pAudioBufferRef: ^audio_buffer_ref, pAvailableFrames: ^u64) -> result ---
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
audio_buffer_config :: struct {
|
||||||
|
format: format,
|
||||||
|
channels: u32,
|
||||||
|
sizeInFrames: u64,
|
||||||
|
pData: rawptr, /* If set to NULL, will allocate a block of memory for you. */
|
||||||
|
allocationCallbacks: allocation_callbacks,
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_buffer :: struct {
|
||||||
|
ref: audio_buffer_ref,
|
||||||
|
allocationCallbacks: allocation_callbacks,
|
||||||
|
ownsData: b32, /* Used to control whether or not miniaudio owns the data buffer. If set to true, pData will be freed in ma_audio_buffer_uninit(). */
|
||||||
|
_pExtraData: [1]u8, /* For allocating a buffer with the memory located directly after the other memory of the structure. */
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c", link_prefix="ma_")
|
||||||
|
foreign lib {
|
||||||
|
audio_buffer_config_init :: proc(format: format, channels: u32, sizeInFrames: u64, pData: rawptr, pAllocationCallbacks: ^allocation_callbacks) -> audio_buffer_config ---
|
||||||
|
|
||||||
|
audio_buffer_init :: proc(pConfig: ^audio_buffer_config, pAudioBuffer: ^audio_buffer) -> result ---
|
||||||
|
audio_buffer_init_copy :: proc(pConfig: ^audio_buffer_config, pAudioBuffer: ^audio_buffer) -> result ---
|
||||||
|
audio_buffer_alloc_and_init :: proc(pConfig: ^audio_buffer_config, ppAudioBuffer: ^^audio_buffer) -> result --- /* Always copies the data. Doesn't make sense to use this otherwise. Use ma_audio_buffer_uninit_and_free() to uninit. */
|
||||||
|
audio_buffer_uninit :: proc(pAudioBuffer: ^audio_buffer) ---
|
||||||
|
audio_buffer_uninit_and_free :: proc(pAudioBuffer: ^audio_buffer) ---
|
||||||
|
audio_buffer_read_pcm_frames :: proc(pAudioBuffer: ^audio_buffer, pFramesOut: rawptr, frameCount: u64, loop: b32) -> u64 ---
|
||||||
|
audio_buffer_seek_to_pcm_frame :: proc(pAudioBuffer: ^audio_buffer, frameIndex: u64) -> result ---
|
||||||
|
audio_buffer_map :: proc(pAudioBuffer: ^audio_buffer, ppFramesOut: ^rawptr, pFrameCount: ^u64) -> result ---
|
||||||
|
audio_buffer_unmap :: proc(pAudioBuffer: ^audio_buffer, frameCount: u64) -> result --- /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||||
|
audio_buffer_at_end :: proc(pAudioBuffer: ^audio_buffer) -> b32 ---
|
||||||
|
audio_buffer_get_cursor_in_pcm_frames :: proc(pAudioBuffer: ^audio_buffer, pCursor: ^u64) -> result ---
|
||||||
|
audio_buffer_get_length_in_pcm_frames :: proc(pAudioBuffer: ^audio_buffer, pLength: ^u64) -> result ---
|
||||||
|
audio_buffer_get_available_frames :: proc(pAudioBuffer: ^audio_buffer, pAvailableFrames: ^u64) -> result ---
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user