mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-25 04:14:57 +00:00
Begin adding vendor:miniaudio
This commit is contained in:
@@ -2,9 +2,16 @@
|
||||
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
rem build the .lib files already exist
|
||||
|
||||
if not exist "vendor\stb\lib\*.lib" (
|
||||
rem build the .lib fiels already exist
|
||||
pushd vendor\stb\src
|
||||
call build.bat
|
||||
popd
|
||||
)
|
||||
|
||||
if not exist "vendor\miniaudio\lib\*.lib" (
|
||||
pushd vendor\miniaudio\src
|
||||
call build.bat
|
||||
popd
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//+build darwin
|
||||
package unix
|
||||
|
||||
import "core:c"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package unix;
|
||||
//+build freebsd
|
||||
package unix
|
||||
|
||||
import "core:c";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//+build linux
|
||||
package unix
|
||||
|
||||
import "core:c"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//+build linux, darwin, freebsd
|
||||
package unix
|
||||
|
||||
foreign import "system:pthread"
|
||||
|
||||
432
vendor/miniaudio/common.odin
vendored
Normal file
432
vendor/miniaudio/common.odin
vendored
Normal file
@@ -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
vendor/miniaudio/data_conversion.odin
vendored
Normal file
509
vendor/miniaudio/data_conversion.odin
vendored
Normal file
@@ -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
vendor/miniaudio/device_io_procs.odin
vendored
Normal file
1476
vendor/miniaudio/device_io_procs.odin
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1144
vendor/miniaudio/device_io_types.odin
vendored
Normal file
1144
vendor/miniaudio/device_io_types.odin
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1490
vendor/miniaudio/doc.odin
vendored
Normal file
1490
vendor/miniaudio/doc.odin
vendored
Normal file
File diff suppressed because it is too large
Load Diff
352
vendor/miniaudio/filtering.odin
vendored
Normal file
352
vendor/miniaudio/filtering.odin
vendored
Normal file
@@ -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 ---
|
||||
}
|
||||
BIN
vendor/miniaudio/lib/miniaudio.lib
vendored
Normal file
BIN
vendor/miniaudio/lib/miniaudio.lib
vendored
Normal file
Binary file not shown.
34
vendor/miniaudio/logging.odin
vendored
Normal file
34
vendor/miniaudio/logging.odin
vendored
Normal file
@@ -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 ---
|
||||
}
|
||||
6
vendor/miniaudio/src/Makefile
vendored
Normal file
6
vendor/miniaudio/src/Makefile
vendored
Normal file
@@ -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
|
||||
8
vendor/miniaudio/src/build.bat
vendored
Normal file
8
vendor/miniaudio/src/build.bat
vendored
Normal file
@@ -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
|
||||
9
vendor/miniaudio/src/miniaudio.c
vendored
Normal file
9
vendor/miniaudio/src/miniaudio.c
vendored
Normal file
@@ -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"
|
||||
70273
vendor/miniaudio/src/miniaudio.h
vendored
Normal file
70273
vendor/miniaudio/src/miniaudio.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
230
vendor/miniaudio/utilities.odin
vendored
Normal file
230
vendor/miniaudio/utilities.odin
vendored
Normal file
@@ -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