Begin adding vendor:miniaudio

This commit is contained in:
gingerBill
2021-09-17 12:57:52 +01:00
parent 4cb7f05644
commit f38b7ebf42
18 changed files with 75976 additions and 2 deletions

View File

@@ -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
)

View File

@@ -1,3 +1,4 @@
//+build darwin
package unix
import "core:c"

View File

@@ -1,4 +1,5 @@
package unix;
//+build freebsd
package unix
import "core:c";

View File

@@ -1,3 +1,4 @@
//+build linux
package unix
import "core:c"

View File

@@ -1,3 +1,4 @@
//+build linux, darwin, freebsd
package unix
foreign import "system:pthread"

432
vendor/miniaudio/common.odin vendored Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

352
vendor/miniaudio/filtering.odin vendored Normal file
View 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

Binary file not shown.

34
vendor/miniaudio/logging.odin vendored Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

230
vendor/miniaudio/utilities.odin vendored Normal file
View 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 ---
}