mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
Version 0.11.14
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
miniaudio - v0.11.13 - 2023-03-23
|
||||
miniaudio - v0.11.14 - 2023-03-29
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -2596,6 +2596,13 @@ Atomics
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
#if defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wc++11-long-long"
|
||||
#endif
|
||||
#endif
|
||||
typedef signed char c89atomic_int8;
|
||||
typedef unsigned char c89atomic_uint8;
|
||||
typedef signed short c89atomic_int16;
|
||||
@@ -2606,18 +2613,8 @@ typedef unsigned int c89atomic_uint32;
|
||||
typedef signed __int64 c89atomic_int64;
|
||||
typedef unsigned __int64 c89atomic_uint64;
|
||||
#else
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wlong-long"
|
||||
#if defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wc++11-long-long"
|
||||
#endif
|
||||
#endif
|
||||
typedef signed long long c89atomic_int64;
|
||||
typedef unsigned long long c89atomic_uint64;
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
typedef int c89atomic_memory_order;
|
||||
typedef unsigned char c89atomic_bool;
|
||||
@@ -3982,7 +3979,7 @@ typedef unsigned char c89atomic_bool;
|
||||
#endif
|
||||
#if !defined(C89ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE)
|
||||
#if defined(C89ATOMIC_HAS_8)
|
||||
c89atomic_bool c89atomic_compare_exchange_strong_explicit_8(volatile c89atomic_uint8* dst, c89atomic_uint8* expected, c89atomic_uint8 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_8(volatile c89atomic_uint8* dst, c89atomic_uint8* expected, c89atomic_uint8 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
{
|
||||
c89atomic_uint8 expectedValue;
|
||||
c89atomic_uint8 result;
|
||||
@@ -3999,7 +3996,7 @@ typedef unsigned char c89atomic_bool;
|
||||
}
|
||||
#endif
|
||||
#if defined(C89ATOMIC_HAS_16)
|
||||
c89atomic_bool c89atomic_compare_exchange_strong_explicit_16(volatile c89atomic_uint16* dst, c89atomic_uint16* expected, c89atomic_uint16 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_16(volatile c89atomic_uint16* dst, c89atomic_uint16* expected, c89atomic_uint16 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
{
|
||||
c89atomic_uint16 expectedValue;
|
||||
c89atomic_uint16 result;
|
||||
@@ -4016,7 +4013,7 @@ typedef unsigned char c89atomic_bool;
|
||||
}
|
||||
#endif
|
||||
#if defined(C89ATOMIC_HAS_32)
|
||||
c89atomic_bool c89atomic_compare_exchange_strong_explicit_32(volatile c89atomic_uint32* dst, c89atomic_uint32* expected, c89atomic_uint32 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_32(volatile c89atomic_uint32* dst, c89atomic_uint32* expected, c89atomic_uint32 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
{
|
||||
c89atomic_uint32 expectedValue;
|
||||
c89atomic_uint32 result;
|
||||
@@ -4033,7 +4030,7 @@ typedef unsigned char c89atomic_bool;
|
||||
}
|
||||
#endif
|
||||
#if defined(C89ATOMIC_HAS_64)
|
||||
c89atomic_bool c89atomic_compare_exchange_strong_explicit_64(volatile c89atomic_uint64* dst, volatile c89atomic_uint64* expected, c89atomic_uint64 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
static C89ATOMIC_INLINE c89atomic_bool c89atomic_compare_exchange_strong_explicit_64(volatile c89atomic_uint64* dst, volatile c89atomic_uint64* expected, c89atomic_uint64 desired, c89atomic_memory_order successOrder, c89atomic_memory_order failureOrder)
|
||||
{
|
||||
c89atomic_uint64 expectedValue;
|
||||
c89atomic_uint64 result;
|
||||
@@ -4511,6 +4508,9 @@ static C89ATOMIC_INLINE void c89atomic_spinlock_unlock(volatile c89atomic_spinlo
|
||||
{
|
||||
c89atomic_flag_clear_explicit(pSpinlock, c89atomic_memory_order_release);
|
||||
}
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -4586,7 +4586,10 @@ MA_ATOMIC_SAFE_TYPE_IMPL(i32, int32)
|
||||
MA_ATOMIC_SAFE_TYPE_IMPL(64, uint64)
|
||||
MA_ATOMIC_SAFE_TYPE_IMPL(f32, float)
|
||||
MA_ATOMIC_SAFE_TYPE_IMPL(32, bool32)
|
||||
|
||||
#if !defined(MA_NO_DEVICE_IO)
|
||||
MA_ATOMIC_SAFE_TYPE_IMPL(i32, device_state)
|
||||
#endif
|
||||
|
||||
|
||||
MA_API ma_uint64 ma_calculate_frame_count_after_resampling(ma_uint32 sampleRateOut, ma_uint32 sampleRateIn, ma_uint64 frameCountIn)
|
||||
@@ -4719,23 +4722,28 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
|
||||
/* We successfully initialized our attributes object so we can assign the pointer so it's passed into pthread_create(). */
|
||||
pAttr = &attr;
|
||||
|
||||
if (priority == ma_thread_priority_idle) {
|
||||
#ifdef SCHED_IDLE
|
||||
if (pthread_attr_setschedpolicy(&attr, SCHED_IDLE) == 0) {
|
||||
scheduler = SCHED_IDLE;
|
||||
/* We need to set the scheduler policy. Only do this if the OS supports pthread_attr_setschedpolicy() */
|
||||
#if !defined(MA_BEOS)
|
||||
{
|
||||
if (priority == ma_thread_priority_idle) {
|
||||
#ifdef SCHED_IDLE
|
||||
if (pthread_attr_setschedpolicy(&attr, SCHED_IDLE) == 0) {
|
||||
scheduler = SCHED_IDLE;
|
||||
}
|
||||
#endif
|
||||
} else if (priority == ma_thread_priority_realtime) {
|
||||
#ifdef SCHED_FIFO
|
||||
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0) {
|
||||
scheduler = SCHED_FIFO;
|
||||
}
|
||||
#endif
|
||||
#ifdef MA_LINUX
|
||||
} else {
|
||||
scheduler = sched_getscheduler(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else if (priority == ma_thread_priority_realtime) {
|
||||
#ifdef SCHED_FIFO
|
||||
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0) {
|
||||
scheduler = SCHED_FIFO;
|
||||
}
|
||||
#endif
|
||||
#ifdef MA_LINUX
|
||||
} else {
|
||||
scheduler = sched_getscheduler(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (stackSize > 0) {
|
||||
pthread_attr_setstacksize(&attr, stackSize);
|
||||
@@ -5129,6 +5137,12 @@ static ma_result ma_thread_create(ma_thread* pThread, ma_thread_priority priorit
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
#if defined(MA_THREAD_DEFAULT_STACK_SIZE)
|
||||
if (stackSize == 0) {
|
||||
stackSize = MA_THREAD_DEFAULT_STACK_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
pProxyData->entryProc = entryProc;
|
||||
pProxyData->pData = pData;
|
||||
ma_allocation_callbacks_init_copy(&pProxyData->allocationCallbacks, pAllocationCallbacks);
|
||||
@@ -18819,7 +18833,6 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
|
||||
ma_pa_channel_map cmap;
|
||||
ma_pa_buffer_attr attr;
|
||||
const ma_pa_sample_spec* pActualSS = NULL;
|
||||
const ma_pa_channel_map* pActualCMap = NULL;
|
||||
const ma_pa_buffer_attr* pActualAttr = NULL;
|
||||
ma_uint32 iChannel;
|
||||
ma_pa_stream_flags_t streamFlags;
|
||||
@@ -18875,6 +18888,14 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
|
||||
ss = sourceInfo.sample_spec;
|
||||
cmap = sourceInfo.channel_map;
|
||||
|
||||
/* Use the requested channel count if we have one. */
|
||||
if (pDescriptorCapture->channels != 0) {
|
||||
ss.channels = pDescriptorCapture->channels;
|
||||
}
|
||||
|
||||
/* Use a default channel map. */
|
||||
((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MA_PA_CHANNEL_MAP_DEFAULT);
|
||||
|
||||
/* Use the requested sample rate if one was specified. */
|
||||
if (pDescriptorCapture->sampleRate != 0) {
|
||||
ss.rate = pDescriptorCapture->sampleRate;
|
||||
@@ -18969,11 +18990,6 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
|
||||
fixed sooner than later. I might remove this hack later.
|
||||
*/
|
||||
if (pDescriptorCapture->channels > 2) {
|
||||
pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||
if (pActualCMap != NULL) {
|
||||
cmap = *pActualCMap;
|
||||
}
|
||||
|
||||
for (iChannel = 0; iChannel < pDescriptorCapture->channels; ++iChannel) {
|
||||
pDescriptorCapture->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
|
||||
}
|
||||
@@ -19016,6 +19032,15 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
|
||||
ss = sinkInfo.sample_spec;
|
||||
cmap = sinkInfo.channel_map;
|
||||
|
||||
/* Use the requested channel count if we have one. */
|
||||
if (pDescriptorPlayback->channels != 0) {
|
||||
ss.channels = pDescriptorPlayback->channels;
|
||||
}
|
||||
|
||||
/* Use a default channel map. */
|
||||
((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MA_PA_CHANNEL_MAP_DEFAULT);
|
||||
|
||||
|
||||
/* Use the requested sample rate if one was specified. */
|
||||
if (pDescriptorPlayback->sampleRate != 0) {
|
||||
ss.rate = pDescriptorPlayback->sampleRate;
|
||||
@@ -19114,11 +19139,6 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
|
||||
fixed sooner than later. I might remove this hack later.
|
||||
*/
|
||||
if (pDescriptorPlayback->channels > 2) {
|
||||
pActualCMap = ((ma_pa_stream_get_channel_map_proc)pDevice->pContext->pulse.pa_stream_get_channel_map)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||
if (pActualCMap != NULL) {
|
||||
cmap = *pActualCMap;
|
||||
}
|
||||
|
||||
for (iChannel = 0; iChannel < pDescriptorPlayback->channels; ++iChannel) {
|
||||
pDescriptorPlayback->channelMap[iChannel] = ma_channel_position_from_pulse(cmap.map[iChannel]);
|
||||
}
|
||||
@@ -39001,6 +39021,26 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer,
|
||||
/* Clamp the gain. */
|
||||
gain = ma_clamp(gain, ma_spatializer_get_min_gain(pSpatializer), ma_spatializer_get_max_gain(pSpatializer));
|
||||
|
||||
/*
|
||||
The gain needs to be applied per-channel here. The spatialization code below will be changing the per-channel
|
||||
gains which will then eventually be passed into the gainer which will deal with smoothing the gain transitions
|
||||
to avoid harsh changes in gain.
|
||||
*/
|
||||
for (iChannel = 0; iChannel < channelsOut; iChannel += 1) {
|
||||
pSpatializer->pNewChannelGainsOut[iChannel] = gain;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert to our output channel count. If the listener is disabled we just output silence here. We cannot ignore
|
||||
the whole section of code here because we need to update some internal spatialization state.
|
||||
*/
|
||||
if (ma_spatializer_listener_is_enabled(pListener)) {
|
||||
ma_channel_map_apply_f32((float*)pFramesOut, pChannelMapOut, channelsOut, (const float*)pFramesIn, pChannelMapIn, channelsIn, frameCount, ma_channel_mix_mode_rectangular, ma_mono_expansion_mode_default);
|
||||
} else {
|
||||
ma_silence_pcm_frames(pFramesOut, frameCount, ma_format_f32, pSpatializer->channelsOut);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Panning. This is where we'll apply the gain and convert to the output channel count. We have an optimized path for
|
||||
when we're converting to a mono stream. In that case we don't really need to do any panning - we just apply the
|
||||
@@ -39022,19 +39062,6 @@ MA_API ma_result ma_spatializer_process_pcm_frames(ma_spatializer* pSpatializer,
|
||||
be +1 on the X axis. A dot product is performed against the direction vector of the channel and the normalized
|
||||
position of the sound.
|
||||
*/
|
||||
for (iChannel = 0; iChannel < channelsOut; iChannel += 1) {
|
||||
pSpatializer->pNewChannelGainsOut[iChannel] = gain;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert to our output channel count. If the listener is disabled we just output silence here. We cannot ignore
|
||||
the whole section of code here because we need to update some internal spatialization state.
|
||||
*/
|
||||
if (ma_spatializer_listener_is_enabled(pListener)) {
|
||||
ma_channel_map_apply_f32((float*)pFramesOut, pChannelMapOut, channelsOut, (const float*)pFramesIn, pChannelMapIn, channelsIn, frameCount, ma_channel_mix_mode_rectangular, ma_mono_expansion_mode_default);
|
||||
} else {
|
||||
ma_silence_pcm_frames(pFramesOut, frameCount, ma_format_f32, pSpatializer->channelsOut);
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate our per-channel gains. We do this based on the normalized relative position of the sound and it's
|
||||
@@ -45058,6 +45085,85 @@ MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pB
|
||||
|
||||
|
||||
|
||||
static ma_result ma_pcm_rb_data_source__on_read(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead)
|
||||
{
|
||||
/* Since there's no notion of an end, we don't ever want to return MA_AT_END here. But it is possible to return 0. */
|
||||
ma_pcm_rb* pRB = (ma_pcm_rb*)pDataSource;
|
||||
ma_result result;
|
||||
ma_uint64 totalFramesRead;
|
||||
|
||||
MA_ASSERT(pRB != NULL);
|
||||
|
||||
/* We need to run this in a loop since the ring buffer itself may loop. */
|
||||
totalFramesRead = 0;
|
||||
while (totalFramesRead < frameCount) {
|
||||
void* pMappedBuffer;
|
||||
ma_uint32 mappedFrameCount;
|
||||
ma_uint64 framesToRead = frameCount - totalFramesRead;
|
||||
if (framesToRead > 0xFFFFFFFF) {
|
||||
framesToRead = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
mappedFrameCount = (ma_uint32)framesToRead;
|
||||
result = ma_pcm_rb_acquire_read(pRB, &mappedFrameCount, &pMappedBuffer);
|
||||
if (result != MA_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (mappedFrameCount == 0) {
|
||||
break; /* <-- End of ring buffer. */
|
||||
}
|
||||
|
||||
ma_copy_pcm_frames(ma_offset_pcm_frames_ptr(pFramesOut, totalFramesRead, pRB->format, pRB->channels), pMappedBuffer, mappedFrameCount, pRB->format, pRB->channels);
|
||||
|
||||
result = ma_pcm_rb_commit_read(pRB, mappedFrameCount);
|
||||
if (result != MA_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
totalFramesRead += mappedFrameCount;
|
||||
}
|
||||
|
||||
*pFramesRead = totalFramesRead;
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_pcm_rb_data_source__on_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
|
||||
{
|
||||
ma_pcm_rb* pRB = (ma_pcm_rb*)pDataSource;
|
||||
MA_ASSERT(pRB != NULL);
|
||||
|
||||
if (pFormat != NULL) {
|
||||
*pFormat = pRB->format;
|
||||
}
|
||||
|
||||
if (pChannels != NULL) {
|
||||
*pChannels = pRB->channels;
|
||||
}
|
||||
|
||||
if (pSampleRate != NULL) {
|
||||
*pSampleRate = pRB->sampleRate;
|
||||
}
|
||||
|
||||
/* Just assume the default channel map. */
|
||||
if (pChannelMap != NULL) {
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, pChannelMap, channelMapCap, pRB->channels);
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_data_source_vtable ma_gRBDataSourceVTable =
|
||||
{
|
||||
ma_pcm_rb_data_source__on_read,
|
||||
NULL, /* onSeek */
|
||||
ma_pcm_rb_data_source__on_get_data_format,
|
||||
NULL, /* onGetCursor */
|
||||
NULL, /* onGetLength */
|
||||
NULL, /* onSetLooping */
|
||||
0
|
||||
};
|
||||
|
||||
static MA_INLINE ma_uint32 ma_pcm_rb_get_bpf(ma_pcm_rb* pRB)
|
||||
{
|
||||
MA_ASSERT(pRB != NULL);
|
||||
@@ -45086,8 +45192,21 @@ MA_API ma_result ma_pcm_rb_init_ex(ma_format format, ma_uint32 channels, ma_uint
|
||||
return result;
|
||||
}
|
||||
|
||||
pRB->format = format;
|
||||
pRB->channels = channels;
|
||||
pRB->format = format;
|
||||
pRB->channels = channels;
|
||||
pRB->sampleRate = 0; /* The sample rate is not passed in as a parameter. */
|
||||
|
||||
/* The PCM ring buffer is a data source. We need to get that set up as well. */
|
||||
{
|
||||
ma_data_source_config dataSourceConfig = ma_data_source_config_init();
|
||||
dataSourceConfig.vtable = &ma_gRBDataSourceVTable;
|
||||
|
||||
result = ma_data_source_init(&dataSourceConfig, &pRB->ds);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_rb_uninit(&pRB->rb);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
@@ -45103,6 +45222,7 @@ MA_API void ma_pcm_rb_uninit(ma_pcm_rb* pRB)
|
||||
return;
|
||||
}
|
||||
|
||||
ma_data_source_uninit(&pRB->ds);
|
||||
ma_rb_uninit(&pRB->rb);
|
||||
}
|
||||
|
||||
@@ -45254,6 +45374,42 @@ MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferInde
|
||||
return ma_rb_get_subbuffer_ptr(&pRB->rb, subbufferIndex, pBuffer);
|
||||
}
|
||||
|
||||
MA_API ma_format ma_pcm_rb_get_format(const ma_pcm_rb* pRB)
|
||||
{
|
||||
if (pRB == NULL) {
|
||||
return ma_format_unknown;
|
||||
}
|
||||
|
||||
return pRB->format;
|
||||
}
|
||||
|
||||
MA_API ma_uint32 ma_pcm_rb_get_channels(const ma_pcm_rb* pRB)
|
||||
{
|
||||
if (pRB == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pRB->channels;
|
||||
}
|
||||
|
||||
MA_API ma_uint32 ma_pcm_rb_get_sample_rate(const ma_pcm_rb* pRB)
|
||||
{
|
||||
if (pRB == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pRB->sampleRate;
|
||||
}
|
||||
|
||||
MA_API void ma_pcm_rb_set_sample_rate(ma_pcm_rb* pRB, ma_uint32 sampleRate)
|
||||
{
|
||||
if (pRB == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pRB->sampleRate = sampleRate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MA_API ma_result ma_duplex_rb_init(ma_format captureFormat, ma_uint32 captureChannels, ma_uint32 sampleRate, ma_uint32 captureInternalSampleRate, ma_uint32 captureInternalPeriodSizeInFrames, const ma_allocation_callbacks* pAllocationCallbacks, ma_duplex_rb* pRB)
|
||||
@@ -47201,7 +47357,7 @@ MA_API ma_result ma_vfs_read(ma_vfs* pVFS, ma_vfs_file file, void* pDst, size_t
|
||||
{
|
||||
ma_vfs_callbacks* pCallbacks = (ma_vfs_callbacks*)pVFS;
|
||||
ma_result result;
|
||||
size_t bytesRead;
|
||||
size_t bytesRead = 0;
|
||||
|
||||
if (pBytesRead != NULL) {
|
||||
*pBytesRead = 0;
|
||||
@@ -63156,16 +63312,36 @@ MA_API ma_node* ma_engine_get_endpoint(ma_engine* pEngine)
|
||||
return ma_node_graph_get_endpoint(&pEngine->nodeGraph);
|
||||
}
|
||||
|
||||
MA_API ma_uint64 ma_engine_get_time(const ma_engine* pEngine)
|
||||
MA_API ma_uint64 ma_engine_get_time_in_pcm_frames(const ma_engine* pEngine)
|
||||
{
|
||||
return ma_node_graph_get_time(&pEngine->nodeGraph);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_engine_set_time(ma_engine* pEngine, ma_uint64 globalTime)
|
||||
MA_API ma_uint64 ma_engine_get_time_in_milliseconds(const ma_engine* pEngine)
|
||||
{
|
||||
return ma_engine_get_time_in_pcm_frames(pEngine) * 1000 / ma_engine_get_sample_rate(pEngine);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_engine_set_time_in_pcm_frames(ma_engine* pEngine, ma_uint64 globalTime)
|
||||
{
|
||||
return ma_node_graph_set_time(&pEngine->nodeGraph, globalTime);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_engine_set_time_in_milliseconds(ma_engine* pEngine, ma_uint64 globalTime)
|
||||
{
|
||||
return ma_engine_set_time_in_pcm_frames(pEngine, globalTime * ma_engine_get_sample_rate(pEngine) / 1000);
|
||||
}
|
||||
|
||||
MA_API ma_uint64 ma_engine_get_time(const ma_engine* pEngine)
|
||||
{
|
||||
return ma_engine_get_time_in_pcm_frames(pEngine);
|
||||
}
|
||||
|
||||
MA_API ma_result ma_engine_set_time(ma_engine* pEngine, ma_uint64 globalTime)
|
||||
{
|
||||
return ma_engine_set_time_in_pcm_frames(pEngine, globalTime);
|
||||
}
|
||||
|
||||
MA_API ma_uint32 ma_engine_get_channels(const ma_engine* pEngine)
|
||||
{
|
||||
return ma_node_graph_get_channels(&pEngine->nodeGraph);
|
||||
@@ -64386,7 +64562,7 @@ MA_API ma_bool32 ma_sound_is_playing(const ma_sound* pSound)
|
||||
return MA_FALSE;
|
||||
}
|
||||
|
||||
return ma_node_get_state_by_time(pSound, ma_engine_get_time(ma_sound_get_engine(pSound))) == ma_node_state_started;
|
||||
return ma_node_get_state_by_time(pSound, ma_engine_get_time_in_pcm_frames(ma_sound_get_engine(pSound))) == ma_node_state_started;
|
||||
}
|
||||
|
||||
MA_API ma_uint64 ma_sound_get_time_in_pcm_frames(const ma_sound* pSound)
|
||||
@@ -65593,10 +65769,14 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||
{
|
||||
drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
|
||||
drwav_uint64 totalBytesRead = 0;
|
||||
size_t bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
|
||||
size_t bytesJustRead;
|
||||
if (pMetadata == NULL) {
|
||||
return 0;
|
||||
}
|
||||
bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
|
||||
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
|
||||
DRWAV_ASSERT(pChunkHeader != NULL);
|
||||
if (bytesJustRead == sizeof(smplHeaderData)) {
|
||||
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
||||
drwav_uint32 iSampleLoop;
|
||||
pMetadata->type = drwav_metadata_type_smpl;
|
||||
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
||||
@@ -65637,7 +65817,11 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parse
|
||||
{
|
||||
drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
|
||||
drwav_uint64 totalBytesRead = 0;
|
||||
size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData, sizeof(cueHeaderSectionData), &totalBytesRead);
|
||||
size_t bytesJustRead;
|
||||
if (pMetadata == NULL) {
|
||||
return 0;
|
||||
}
|
||||
bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData, sizeof(cueHeaderSectionData), &totalBytesRead);
|
||||
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
|
||||
if (bytesJustRead == sizeof(cueHeaderSectionData)) {
|
||||
pMetadata->type = drwav_metadata_type_cue;
|
||||
@@ -65672,7 +65856,11 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parse
|
||||
DRWAV_PRIVATE drwav_uint64 drwav__read_inst_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
|
||||
{
|
||||
drwav_uint8 instData[DRWAV_INST_BYTES];
|
||||
drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, instData, sizeof(instData), NULL);
|
||||
drwav_uint64 bytesRead;
|
||||
if (pMetadata == NULL) {
|
||||
return 0;
|
||||
}
|
||||
bytesRead = drwav__metadata_parser_read(pParser, instData, sizeof(instData), NULL);
|
||||
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
|
||||
if (bytesRead == sizeof(instData)) {
|
||||
pMetadata->type = drwav_metadata_type_inst;
|
||||
@@ -65689,7 +65877,11 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_inst_to_metadata_obj(drwav__metadata_pars
|
||||
DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
|
||||
{
|
||||
drwav_uint8 acidData[DRWAV_ACID_BYTES];
|
||||
drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
|
||||
drwav_uint64 bytesRead;
|
||||
if (pMetadata == NULL) {
|
||||
return 0;
|
||||
}
|
||||
bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
|
||||
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
|
||||
if (bytesRead == sizeof(acidData)) {
|
||||
pMetadata->type = drwav_metadata_type_acid;
|
||||
|
||||
+243
-208
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
miniaudio - v0.11.13 - 2023-03-23
|
||||
miniaudio - v0.11.14 - 2023-03-29
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -20,7 +20,7 @@ extern "C" {
|
||||
|
||||
#define MA_VERSION_MAJOR 0
|
||||
#define MA_VERSION_MINOR 11
|
||||
#define MA_VERSION_REVISION 13
|
||||
#define MA_VERSION_REVISION 14
|
||||
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
@@ -100,7 +100,18 @@ typedef double ma_double;
|
||||
|
||||
typedef void* ma_handle;
|
||||
typedef void* ma_ptr;
|
||||
|
||||
/*
|
||||
ma_proc is annoying because when compiling with GCC we get pendantic warnings about converting
|
||||
between `void*` and `void (*)()`. We can't use `void (*)()` with MSVC however, because we'll get
|
||||
warning C4191 about "type cast between incompatible function types". To work around this I'm going
|
||||
to use a different data type depending on the compiler.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
typedef void (*ma_proc)(void);
|
||||
#else
|
||||
typedef void* ma_proc;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_WCHAR_T_DEFINED)
|
||||
typedef ma_uint16 wchar_t;
|
||||
@@ -150,31 +161,39 @@ typedef ma_uint16 wchar_t;
|
||||
typedef union ma_pthread_cond_t { char __data[48]; ma_uint64 __alignment; } ma_pthread_cond_t;
|
||||
#endif
|
||||
|
||||
#ifdef __unix__
|
||||
#if defined(__unix__)
|
||||
#define MA_UNIX
|
||||
#ifdef __ORBIS__
|
||||
#define MA_ORBIS
|
||||
#elif defined(__PROSPERO__)
|
||||
#define MA_PROSPERO
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#define MA_BSD
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__)
|
||||
#define MA_LINUX
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__)
|
||||
#define MA_APPLE
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#define MA_BSD
|
||||
#endif
|
||||
#if defined(__ANDROID__)
|
||||
#define MA_ANDROID
|
||||
#endif
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
#define MA_EMSCRIPTEN
|
||||
#endif
|
||||
#if defined(__ORBIS__)
|
||||
#define MA_ORBIS
|
||||
#endif
|
||||
#if defined(__PROSPERO__)
|
||||
#define MA_PROSPERO
|
||||
#endif
|
||||
#if defined(__NX__)
|
||||
#define MA_NX
|
||||
#endif
|
||||
#if defined(__BEOS__) || defined(__HAIKU__)
|
||||
#define MA_BEOS
|
||||
#endif
|
||||
#if defined(__HAIKU__)
|
||||
#define MA_HAIKU
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__has_c_attribute)
|
||||
@@ -2022,6 +2041,197 @@ MA_API ma_uint64 ma_convert_frames(void* pOut, ma_uint64 frameCountOut, ma_forma
|
||||
MA_API ma_uint64 ma_convert_frames_ex(void* pOut, ma_uint64 frameCountOut, const void* pIn, ma_uint64 frameCountIn, const ma_data_converter_config* pConfig);
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
|
||||
Data Source
|
||||
|
||||
************************************************************************************************************************************************************/
|
||||
typedef void ma_data_source;
|
||||
|
||||
#define MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT 0x00000001
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_result (* onRead)(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
|
||||
ma_result (* onSeek)(ma_data_source* pDataSource, ma_uint64 frameIndex);
|
||||
ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
|
||||
ma_result (* onGetCursor)(ma_data_source* pDataSource, ma_uint64* pCursor);
|
||||
ma_result (* onGetLength)(ma_data_source* pDataSource, ma_uint64* pLength);
|
||||
ma_result (* onSetLooping)(ma_data_source* pDataSource, ma_bool32 isLooping);
|
||||
ma_uint32 flags;
|
||||
} ma_data_source_vtable;
|
||||
|
||||
typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ma_data_source_vtable* vtable;
|
||||
} ma_data_source_config;
|
||||
|
||||
MA_API ma_data_source_config ma_data_source_config_init(void);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ma_data_source_vtable* vtable;
|
||||
ma_uint64 rangeBegInFrames;
|
||||
ma_uint64 rangeEndInFrames; /* Set to -1 for unranged (default). */
|
||||
ma_uint64 loopBegInFrames; /* Relative to rangeBegInFrames. */
|
||||
ma_uint64 loopEndInFrames; /* Relative to rangeBegInFrames. Set to -1 for the end of the range. */
|
||||
ma_data_source* pCurrent; /* 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. */
|
||||
ma_data_source* pNext; /* When set to NULL, onGetNext will be used. */
|
||||
ma_data_source_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
|
||||
MA_ATOMIC(4, ma_bool32) isLooping;
|
||||
} ma_data_source_base;
|
||||
|
||||
MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource);
|
||||
MA_API void ma_data_source_uninit(ma_data_source* pDataSource);
|
||||
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */
|
||||
MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, &framesRead); */
|
||||
MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
|
||||
MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength); /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */
|
||||
MA_API ma_result ma_data_source_get_cursor_in_seconds(ma_data_source* pDataSource, float* pCursor);
|
||||
MA_API ma_result ma_data_source_get_length_in_seconds(ma_data_source* pDataSource, float* pLength);
|
||||
MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping);
|
||||
MA_API ma_bool32 ma_data_source_is_looping(const ma_data_source* pDataSource);
|
||||
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(const 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(const 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(const 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(const 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(const ma_data_source* pDataSource);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint64 cursor;
|
||||
ma_uint64 sizeInFrames;
|
||||
const void* pData;
|
||||
} ma_audio_buffer_ref;
|
||||
|
||||
MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef);
|
||||
MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref* pAudioBufferRef);
|
||||
MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames);
|
||||
MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
|
||||
MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount);
|
||||
MA_API ma_result ma_audio_buffer_ref_unmap(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||
MA_API ma_bool32 ma_audio_buffer_ref_at_end(const ma_audio_buffer_ref* pAudioBufferRef);
|
||||
MA_API ma_result ma_audio_buffer_ref_get_cursor_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_audio_buffer_ref_get_length_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pLength);
|
||||
MA_API ma_result ma_audio_buffer_ref_get_available_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pAvailableFrames);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint64 sizeInFrames;
|
||||
const void* pData; /* If set to NULL, will allocate a block of memory for you. */
|
||||
ma_allocation_callbacks allocationCallbacks;
|
||||
} ma_audio_buffer_config;
|
||||
|
||||
MA_API ma_audio_buffer_config ma_audio_buffer_config_init(ma_format format, ma_uint32 channels, ma_uint64 sizeInFrames, const void* pData, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_audio_buffer_ref ref;
|
||||
ma_allocation_callbacks allocationCallbacks;
|
||||
ma_bool32 ownsData; /* Used to control whether or not miniaudio owns the data buffer. If set to true, pData will be freed in ma_audio_buffer_uninit(). */
|
||||
ma_uint8 _pExtraData[1]; /* For allocating a buffer with the memory located directly after the other memory of the structure. */
|
||||
} ma_audio_buffer;
|
||||
|
||||
MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_result ma_audio_buffer_init_copy(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_result ma_audio_buffer_alloc_and_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer** ppAudioBuffer); /* Always copies the data. Doesn't make sense to use this otherwise. Use ma_audio_buffer_uninit_and_free() to uninit. */
|
||||
MA_API void ma_audio_buffer_uninit(ma_audio_buffer* pAudioBuffer);
|
||||
MA_API void ma_audio_buffer_uninit_and_free(ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
|
||||
MA_API ma_result ma_audio_buffer_seek_to_pcm_frame(ma_audio_buffer* pAudioBuffer, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount);
|
||||
MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer* pAudioBuffer, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||
MA_API ma_bool32 ma_audio_buffer_at_end(const ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_result ma_audio_buffer_get_cursor_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_audio_buffer_get_length_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pLength);
|
||||
MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames);
|
||||
|
||||
|
||||
/*
|
||||
Paged Audio Buffer
|
||||
==================
|
||||
A paged audio buffer is made up of a linked list of pages. It's expandable, but not shrinkable. It
|
||||
can be used for cases where audio data is streamed in asynchronously while allowing data to be read
|
||||
at the same time.
|
||||
|
||||
This is lock-free, but not 100% thread safe. You can append a page and read from the buffer across
|
||||
simultaneously across different threads, however only one thread at a time can append, and only one
|
||||
thread at a time can read and seek.
|
||||
*/
|
||||
typedef struct ma_paged_audio_buffer_page ma_paged_audio_buffer_page;
|
||||
struct ma_paged_audio_buffer_page
|
||||
{
|
||||
MA_ATOMIC(MA_SIZEOF_PTR, ma_paged_audio_buffer_page*) pNext;
|
||||
ma_uint64 sizeInFrames;
|
||||
ma_uint8 pAudioData[1];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_paged_audio_buffer_page head; /* Dummy head for the lock-free algorithm. Always has a size of 0. */
|
||||
MA_ATOMIC(MA_SIZEOF_PTR, ma_paged_audio_buffer_page*) pTail; /* Never null. Initially set to &head. */
|
||||
} ma_paged_audio_buffer_data;
|
||||
|
||||
MA_API ma_result ma_paged_audio_buffer_data_init(ma_format format, ma_uint32 channels, ma_paged_audio_buffer_data* pData);
|
||||
MA_API void ma_paged_audio_buffer_data_uninit(ma_paged_audio_buffer_data* pData, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_head(ma_paged_audio_buffer_data* pData);
|
||||
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_tail(ma_paged_audio_buffer_data* pData);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_get_length_in_pcm_frames(ma_paged_audio_buffer_data* pData, ma_uint64* pLength);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_allocate_page(ma_paged_audio_buffer_data* pData, ma_uint64 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks, ma_paged_audio_buffer_page** ppPage);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_free_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_append_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_allocate_and_append_page(ma_paged_audio_buffer_data* pData, ma_uint32 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_paged_audio_buffer_data* pData; /* Must not be null. */
|
||||
} ma_paged_audio_buffer_config;
|
||||
|
||||
MA_API ma_paged_audio_buffer_config ma_paged_audio_buffer_config_init(ma_paged_audio_buffer_data* pData);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
ma_paged_audio_buffer_data* pData; /* Audio data is read from here. Cannot be null. */
|
||||
ma_paged_audio_buffer_page* pCurrent;
|
||||
ma_uint64 relativeCursor; /* Relative to the current page. */
|
||||
ma_uint64 absoluteCursor;
|
||||
} ma_paged_audio_buffer;
|
||||
|
||||
MA_API ma_result ma_paged_audio_buffer_init(const ma_paged_audio_buffer_config* pConfig, ma_paged_audio_buffer* pPagedAudioBuffer);
|
||||
MA_API void ma_paged_audio_buffer_uninit(ma_paged_audio_buffer* pPagedAudioBuffer);
|
||||
MA_API ma_result ma_paged_audio_buffer_read_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Returns MA_AT_END if no more pages available. */
|
||||
MA_API ma_result ma_paged_audio_buffer_seek_to_pcm_frame(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_paged_audio_buffer_get_cursor_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_paged_audio_buffer_get_length_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pLength);
|
||||
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
|
||||
Ring Buffer
|
||||
@@ -2061,9 +2271,11 @@ MA_API void* ma_rb_get_subbuffer_ptr(ma_rb* pRB, size_t subbufferIndex, void* pB
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
ma_rb rb;
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate; /* Not required for the ring buffer itself, but useful for associating the data with some sample rate, particularly for data sources. */
|
||||
} ma_pcm_rb;
|
||||
|
||||
MA_API ma_result ma_pcm_rb_init_ex(ma_format format, ma_uint32 channels, ma_uint32 subbufferSizeInFrames, ma_uint32 subbufferCount, ma_uint32 subbufferStrideInFrames, void* pOptionalPreallocatedBuffer, const ma_allocation_callbacks* pAllocationCallbacks, ma_pcm_rb* pRB);
|
||||
@@ -2083,6 +2295,10 @@ MA_API ma_uint32 ma_pcm_rb_get_subbuffer_size(ma_pcm_rb* pRB);
|
||||
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_stride(ma_pcm_rb* pRB);
|
||||
MA_API ma_uint32 ma_pcm_rb_get_subbuffer_offset(ma_pcm_rb* pRB, ma_uint32 subbufferIndex);
|
||||
MA_API void* ma_pcm_rb_get_subbuffer_ptr(ma_pcm_rb* pRB, ma_uint32 subbufferIndex, void* pBuffer);
|
||||
MA_API ma_format ma_pcm_rb_get_format(const ma_pcm_rb* pRB);
|
||||
MA_API ma_uint32 ma_pcm_rb_get_channels(const ma_pcm_rb* pRB);
|
||||
MA_API ma_uint32 ma_pcm_rb_get_sample_rate(const ma_pcm_rb* pRB);
|
||||
MA_API void ma_pcm_rb_set_sample_rate(ma_pcm_rb* pRB, ma_uint32 sampleRate);
|
||||
|
||||
|
||||
/*
|
||||
@@ -5843,195 +6059,6 @@ This will run on an optimized path when the volume is equal to 1.
|
||||
MA_API ma_result ma_mix_pcm_frames_f32(float* pDst, const float* pSrc, ma_uint64 frameCount, ma_uint32 channels, float volume);
|
||||
|
||||
|
||||
/**************************************************************************************************
|
||||
|
||||
Data Source
|
||||
|
||||
**************************************************************************************************/
|
||||
typedef void ma_data_source;
|
||||
|
||||
#define MA_DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT 0x00000001
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_result (* onRead)(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
|
||||
ma_result (* onSeek)(ma_data_source* pDataSource, ma_uint64 frameIndex);
|
||||
ma_result (* onGetDataFormat)(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
|
||||
ma_result (* onGetCursor)(ma_data_source* pDataSource, ma_uint64* pCursor);
|
||||
ma_result (* onGetLength)(ma_data_source* pDataSource, ma_uint64* pLength);
|
||||
ma_result (* onSetLooping)(ma_data_source* pDataSource, ma_bool32 isLooping);
|
||||
ma_uint32 flags;
|
||||
} ma_data_source_vtable;
|
||||
|
||||
typedef ma_data_source* (* ma_data_source_get_next_proc)(ma_data_source* pDataSource);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ma_data_source_vtable* vtable;
|
||||
} ma_data_source_config;
|
||||
|
||||
MA_API ma_data_source_config ma_data_source_config_init(void);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ma_data_source_vtable* vtable;
|
||||
ma_uint64 rangeBegInFrames;
|
||||
ma_uint64 rangeEndInFrames; /* Set to -1 for unranged (default). */
|
||||
ma_uint64 loopBegInFrames; /* Relative to rangeBegInFrames. */
|
||||
ma_uint64 loopEndInFrames; /* Relative to rangeBegInFrames. Set to -1 for the end of the range. */
|
||||
ma_data_source* pCurrent; /* 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. */
|
||||
ma_data_source* pNext; /* When set to NULL, onGetNext will be used. */
|
||||
ma_data_source_get_next_proc onGetNext; /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
|
||||
MA_ATOMIC(4, ma_bool32) isLooping;
|
||||
} ma_data_source_base;
|
||||
|
||||
MA_API ma_result ma_data_source_init(const ma_data_source_config* pConfig, ma_data_source* pDataSource);
|
||||
MA_API void ma_data_source_uninit(ma_data_source* pDataSource);
|
||||
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Must support pFramesOut = NULL in which case a forward seek should be performed. */
|
||||
MA_API ma_result ma_data_source_seek_pcm_frames(ma_data_source* pDataSource, ma_uint64 frameCount, ma_uint64* pFramesSeeked); /* Can only seek forward. Equivalent to ma_data_source_read_pcm_frames(pDataSource, NULL, frameCount, &framesRead); */
|
||||
MA_API ma_result ma_data_source_seek_to_pcm_frame(ma_data_source* pDataSource, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_data_source_get_data_format(ma_data_source* pDataSource, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
|
||||
MA_API ma_result ma_data_source_get_cursor_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_data_source_get_length_in_pcm_frames(ma_data_source* pDataSource, ma_uint64* pLength); /* Returns MA_NOT_IMPLEMENTED if the length is unknown or cannot be determined. Decoders can return this. */
|
||||
MA_API ma_result ma_data_source_get_cursor_in_seconds(ma_data_source* pDataSource, float* pCursor);
|
||||
MA_API ma_result ma_data_source_get_length_in_seconds(ma_data_source* pDataSource, float* pLength);
|
||||
MA_API ma_result ma_data_source_set_looping(ma_data_source* pDataSource, ma_bool32 isLooping);
|
||||
MA_API ma_bool32 ma_data_source_is_looping(const ma_data_source* pDataSource);
|
||||
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(const 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(const 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(const 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(const 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(const ma_data_source* pDataSource);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint64 cursor;
|
||||
ma_uint64 sizeInFrames;
|
||||
const void* pData;
|
||||
} ma_audio_buffer_ref;
|
||||
|
||||
MA_API ma_result ma_audio_buffer_ref_init(ma_format format, ma_uint32 channels, const void* pData, ma_uint64 sizeInFrames, ma_audio_buffer_ref* pAudioBufferRef);
|
||||
MA_API void ma_audio_buffer_ref_uninit(ma_audio_buffer_ref* pAudioBufferRef);
|
||||
MA_API ma_result ma_audio_buffer_ref_set_data(ma_audio_buffer_ref* pAudioBufferRef, const void* pData, ma_uint64 sizeInFrames);
|
||||
MA_API ma_uint64 ma_audio_buffer_ref_read_pcm_frames(ma_audio_buffer_ref* pAudioBufferRef, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
|
||||
MA_API ma_result ma_audio_buffer_ref_seek_to_pcm_frame(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_audio_buffer_ref_map(ma_audio_buffer_ref* pAudioBufferRef, void** ppFramesOut, ma_uint64* pFrameCount);
|
||||
MA_API ma_result ma_audio_buffer_ref_unmap(ma_audio_buffer_ref* pAudioBufferRef, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||
MA_API ma_bool32 ma_audio_buffer_ref_at_end(const ma_audio_buffer_ref* pAudioBufferRef);
|
||||
MA_API ma_result ma_audio_buffer_ref_get_cursor_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_audio_buffer_ref_get_length_in_pcm_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pLength);
|
||||
MA_API ma_result ma_audio_buffer_ref_get_available_frames(const ma_audio_buffer_ref* pAudioBufferRef, ma_uint64* pAvailableFrames);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint64 sizeInFrames;
|
||||
const void* pData; /* If set to NULL, will allocate a block of memory for you. */
|
||||
ma_allocation_callbacks allocationCallbacks;
|
||||
} ma_audio_buffer_config;
|
||||
|
||||
MA_API ma_audio_buffer_config ma_audio_buffer_config_init(ma_format format, ma_uint32 channels, ma_uint64 sizeInFrames, const void* pData, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_audio_buffer_ref ref;
|
||||
ma_allocation_callbacks allocationCallbacks;
|
||||
ma_bool32 ownsData; /* Used to control whether or not miniaudio owns the data buffer. If set to true, pData will be freed in ma_audio_buffer_uninit(). */
|
||||
ma_uint8 _pExtraData[1]; /* For allocating a buffer with the memory located directly after the other memory of the structure. */
|
||||
} ma_audio_buffer;
|
||||
|
||||
MA_API ma_result ma_audio_buffer_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_result ma_audio_buffer_init_copy(const ma_audio_buffer_config* pConfig, ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_result ma_audio_buffer_alloc_and_init(const ma_audio_buffer_config* pConfig, ma_audio_buffer** ppAudioBuffer); /* Always copies the data. Doesn't make sense to use this otherwise. Use ma_audio_buffer_uninit_and_free() to uninit. */
|
||||
MA_API void ma_audio_buffer_uninit(ma_audio_buffer* pAudioBuffer);
|
||||
MA_API void ma_audio_buffer_uninit_and_free(ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_uint64 ma_audio_buffer_read_pcm_frames(ma_audio_buffer* pAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_bool32 loop);
|
||||
MA_API ma_result ma_audio_buffer_seek_to_pcm_frame(ma_audio_buffer* pAudioBuffer, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_audio_buffer_map(ma_audio_buffer* pAudioBuffer, void** ppFramesOut, ma_uint64* pFrameCount);
|
||||
MA_API ma_result ma_audio_buffer_unmap(ma_audio_buffer* pAudioBuffer, ma_uint64 frameCount); /* Returns MA_AT_END if the end has been reached. This should be considered successful. */
|
||||
MA_API ma_bool32 ma_audio_buffer_at_end(const ma_audio_buffer* pAudioBuffer);
|
||||
MA_API ma_result ma_audio_buffer_get_cursor_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_audio_buffer_get_length_in_pcm_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pLength);
|
||||
MA_API ma_result ma_audio_buffer_get_available_frames(const ma_audio_buffer* pAudioBuffer, ma_uint64* pAvailableFrames);
|
||||
|
||||
|
||||
/*
|
||||
Paged Audio Buffer
|
||||
==================
|
||||
A paged audio buffer is made up of a linked list of pages. It's expandable, but not shrinkable. It
|
||||
can be used for cases where audio data is streamed in asynchronously while allowing data to be read
|
||||
at the same time.
|
||||
|
||||
This is lock-free, but not 100% thread safe. You can append a page and read from the buffer across
|
||||
simultaneously across different threads, however only one thread at a time can append, and only one
|
||||
thread at a time can read and seek.
|
||||
*/
|
||||
typedef struct ma_paged_audio_buffer_page ma_paged_audio_buffer_page;
|
||||
struct ma_paged_audio_buffer_page
|
||||
{
|
||||
MA_ATOMIC(MA_SIZEOF_PTR, ma_paged_audio_buffer_page*) pNext;
|
||||
ma_uint64 sizeInFrames;
|
||||
ma_uint8 pAudioData[1];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_paged_audio_buffer_page head; /* Dummy head for the lock-free algorithm. Always has a size of 0. */
|
||||
MA_ATOMIC(MA_SIZEOF_PTR, ma_paged_audio_buffer_page*) pTail; /* Never null. Initially set to &head. */
|
||||
} ma_paged_audio_buffer_data;
|
||||
|
||||
MA_API ma_result ma_paged_audio_buffer_data_init(ma_format format, ma_uint32 channels, ma_paged_audio_buffer_data* pData);
|
||||
MA_API void ma_paged_audio_buffer_data_uninit(ma_paged_audio_buffer_data* pData, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_head(ma_paged_audio_buffer_data* pData);
|
||||
MA_API ma_paged_audio_buffer_page* ma_paged_audio_buffer_data_get_tail(ma_paged_audio_buffer_data* pData);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_get_length_in_pcm_frames(ma_paged_audio_buffer_data* pData, ma_uint64* pLength);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_allocate_page(ma_paged_audio_buffer_data* pData, ma_uint64 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks, ma_paged_audio_buffer_page** ppPage);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_free_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_append_page(ma_paged_audio_buffer_data* pData, ma_paged_audio_buffer_page* pPage);
|
||||
MA_API ma_result ma_paged_audio_buffer_data_allocate_and_append_page(ma_paged_audio_buffer_data* pData, ma_uint32 pageSizeInFrames, const void* pInitialData, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_paged_audio_buffer_data* pData; /* Must not be null. */
|
||||
} ma_paged_audio_buffer_config;
|
||||
|
||||
MA_API ma_paged_audio_buffer_config ma_paged_audio_buffer_config_init(ma_paged_audio_buffer_data* pData);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_data_source_base ds;
|
||||
ma_paged_audio_buffer_data* pData; /* Audio data is read from here. Cannot be null. */
|
||||
ma_paged_audio_buffer_page* pCurrent;
|
||||
ma_uint64 relativeCursor; /* Relative to the current page. */
|
||||
ma_uint64 absoluteCursor;
|
||||
} ma_paged_audio_buffer;
|
||||
|
||||
MA_API ma_result ma_paged_audio_buffer_init(const ma_paged_audio_buffer_config* pConfig, ma_paged_audio_buffer* pPagedAudioBuffer);
|
||||
MA_API void ma_paged_audio_buffer_uninit(ma_paged_audio_buffer* pPagedAudioBuffer);
|
||||
MA_API ma_result ma_paged_audio_buffer_read_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); /* Returns MA_AT_END if no more pages available. */
|
||||
MA_API ma_result ma_paged_audio_buffer_seek_to_pcm_frame(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64 frameIndex);
|
||||
MA_API ma_result ma_paged_audio_buffer_get_cursor_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pCursor);
|
||||
MA_API ma_result ma_paged_audio_buffer_get_length_in_pcm_frames(ma_paged_audio_buffer* pPagedAudioBuffer, ma_uint64* pLength);
|
||||
|
||||
|
||||
|
||||
/************************************************************************************************************************************************************
|
||||
@@ -7243,13 +7270,17 @@ typedef struct ma_sound ma_sound;
|
||||
/* Sound flags. */
|
||||
typedef enum
|
||||
{
|
||||
/* Resource manager flags. */
|
||||
MA_SOUND_FLAG_STREAM = 0x00000001, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM */
|
||||
MA_SOUND_FLAG_DECODE = 0x00000002, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE */
|
||||
MA_SOUND_FLAG_ASYNC = 0x00000004, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC */
|
||||
MA_SOUND_FLAG_WAIT_INIT = 0x00000008, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT */
|
||||
MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT = 0x00000010, /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */
|
||||
MA_SOUND_FLAG_NO_PITCH = 0x00000020, /* Disable pitch shifting with ma_sound_set_pitch() and ma_sound_group_set_pitch(). This is an optimization. */
|
||||
MA_SOUND_FLAG_NO_SPATIALIZATION = 0x00000040 /* Disable spatialization. */
|
||||
MA_SOUND_FLAG_UNKNOWN_LENGTH = 0x00000010, /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH */
|
||||
|
||||
/* ma_sound specific flags. */
|
||||
MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT = 0x00001000, /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */
|
||||
MA_SOUND_FLAG_NO_PITCH = 0x00002000, /* Disable pitch shifting with ma_sound_set_pitch() and ma_sound_group_set_pitch(). This is an optimization. */
|
||||
MA_SOUND_FLAG_NO_SPATIALIZATION = 0x00004000 /* Disable spatialization. */
|
||||
} ma_sound_flags;
|
||||
|
||||
#ifndef MA_ENGINE_MAX_LISTENERS
|
||||
@@ -7439,8 +7470,12 @@ MA_API ma_resource_manager* ma_engine_get_resource_manager(ma_engine* pEngine);
|
||||
MA_API ma_device* ma_engine_get_device(ma_engine* pEngine);
|
||||
MA_API ma_log* ma_engine_get_log(ma_engine* pEngine);
|
||||
MA_API ma_node* ma_engine_get_endpoint(ma_engine* pEngine);
|
||||
MA_API ma_uint64 ma_engine_get_time(const ma_engine* pEngine);
|
||||
MA_API ma_result ma_engine_set_time(ma_engine* pEngine, ma_uint64 globalTime);
|
||||
MA_API ma_uint64 ma_engine_get_time_in_pcm_frames(const ma_engine* pEngine);
|
||||
MA_API ma_uint64 ma_engine_get_time_in_milliseconds(const ma_engine* pEngine);
|
||||
MA_API ma_result ma_engine_set_time_in_pcm_frames(ma_engine* pEngine, ma_uint64 globalTime);
|
||||
MA_API ma_result ma_engine_set_time_in_milliseconds(ma_engine* pEngine, ma_uint64 globalTime);
|
||||
MA_API ma_uint64 ma_engine_get_time(const ma_engine* pEngine); /* Deprecated. Use ma_engine_get_time_in_pcm_frames(). Will be removed in version 0.12. */
|
||||
MA_API ma_result ma_engine_set_time(ma_engine* pEngine, ma_uint64 globalTime); /* Deprecated. Use ma_engine_set_time_in_pcm_frames(). Will be removed in version 0.12. */
|
||||
MA_API ma_uint32 ma_engine_get_channels(const ma_engine* pEngine);
|
||||
MA_API ma_uint32 ma_engine_get_sample_rate(const ma_engine* pEngine);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user