mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Version 0.11.15
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.14 - 2023-03-29
|
||||
miniaudio - v0.11.15 - 2023-04-30
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@@ -3454,10 +3454,26 @@ typedef unsigned char c89atomic_bool;
|
||||
#define c89atomic_fetch_and_explicit_16(dst, src, order) __atomic_fetch_and(dst, src, order)
|
||||
#define c89atomic_fetch_and_explicit_32(dst, src, order) __atomic_fetch_and(dst, src, order)
|
||||
#define c89atomic_fetch_and_explicit_64(dst, src, order) __atomic_fetch_and(dst, src, order)
|
||||
#define c89atomic_compare_and_swap_8 (dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
|
||||
#define c89atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
|
||||
#define c89atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
|
||||
#define c89atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
|
||||
static C89ATOMIC_INLINE c89atomic_uint8 c89atomic_compare_and_swap_8(volatile c89atomic_uint8* dst, c89atomic_uint8 expected, c89atomic_uint8 desired)
|
||||
{
|
||||
__atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
return expected;
|
||||
}
|
||||
static C89ATOMIC_INLINE c89atomic_uint16 c89atomic_compare_and_swap_16(volatile c89atomic_uint16* dst, c89atomic_uint16 expected, c89atomic_uint16 desired)
|
||||
{
|
||||
__atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
return expected;
|
||||
}
|
||||
static C89ATOMIC_INLINE c89atomic_uint32 c89atomic_compare_and_swap_32(volatile c89atomic_uint32* dst, c89atomic_uint32 expected, c89atomic_uint32 desired)
|
||||
{
|
||||
__atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
return expected;
|
||||
}
|
||||
static C89ATOMIC_INLINE c89atomic_uint64 c89atomic_compare_and_swap_64(volatile c89atomic_uint64* dst, c89atomic_uint64 expected, c89atomic_uint64 desired)
|
||||
{
|
||||
__atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
|
||||
return expected;
|
||||
}
|
||||
typedef c89atomic_uint8 c89atomic_flag;
|
||||
#define c89atomic_flag_test_and_set_explicit(dst, order) (c89atomic_bool)__atomic_test_and_set(dst, order)
|
||||
#define c89atomic_flag_clear_explicit(dst, order) __atomic_clear(dst, order)
|
||||
@@ -10647,6 +10663,7 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device
|
||||
ma_WASAPIDeviceInterface* pDeviceInterface = NULL;
|
||||
ma_IAudioClient2* pAudioClient2;
|
||||
ma_uint32 nativeSampleRate;
|
||||
ma_bool32 usingProcessLoopback = MA_FALSE;
|
||||
|
||||
MA_ASSERT(pContext != NULL);
|
||||
MA_ASSERT(pData != NULL);
|
||||
@@ -10656,6 +10673,8 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
usingProcessLoopback = deviceType == ma_device_type_loopback && pData->loopbackProcessID != 0 && pDeviceID == NULL;
|
||||
|
||||
pData->pAudioClient = NULL;
|
||||
pData->pRenderClient = NULL;
|
||||
pData->pCaptureClient = NULL;
|
||||
@@ -10742,9 +10761,44 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device
|
||||
MA_WAVEFORMATEXTENSIBLE* pNativeFormat = NULL;
|
||||
hr = ma_IAudioClient_GetMixFormat((ma_IAudioClient*)pData->pAudioClient, (MA_WAVEFORMATEX**)&pNativeFormat);
|
||||
if (hr != S_OK) {
|
||||
result = MA_FORMAT_NOT_SUPPORTED;
|
||||
/* When using process-specific loopback, GetMixFormat() seems to always fail. */
|
||||
if (usingProcessLoopback) {
|
||||
wf.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
wf.nChannels = 2;
|
||||
wf.nSamplesPerSec = 44100;
|
||||
wf.wBitsPerSample = 32;
|
||||
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
|
||||
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
|
||||
wf.cbSize = sizeof(MA_WAVEFORMATEX);
|
||||
|
||||
result = MA_SUCCESS;
|
||||
} else {
|
||||
result = MA_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
} else {
|
||||
MA_COPY_MEMORY(&wf, pNativeFormat, sizeof(wf));
|
||||
/*
|
||||
I've seen cases where cbSize will be set to sizeof(WAVEFORMATEX) even though the structure itself
|
||||
is given the format tag of WAVE_FORMAT_EXTENSIBLE. If the format tag is WAVE_FORMAT_EXTENSIBLE
|
||||
want to make sure we copy the whole WAVEFORMATEXTENSIBLE structure. Otherwise we'll have to be
|
||||
safe and only copy the WAVEFORMATEX part.
|
||||
*/
|
||||
if (pNativeFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
MA_COPY_MEMORY(&wf, pNativeFormat, sizeof(MA_WAVEFORMATEXTENSIBLE));
|
||||
} else {
|
||||
/* I've seen a case where cbSize was set to 0. Assume sizeof(WAVEFORMATEX) in this case. */
|
||||
size_t cbSize = pNativeFormat->cbSize;
|
||||
if (cbSize == 0) {
|
||||
cbSize = sizeof(MA_WAVEFORMATEX);
|
||||
}
|
||||
|
||||
/* Make sure we don't copy more than the capacity of `wf`. */
|
||||
if (cbSize > sizeof(wf)) {
|
||||
cbSize = sizeof(wf);
|
||||
}
|
||||
|
||||
MA_COPY_MEMORY(&wf, pNativeFormat, cbSize);
|
||||
}
|
||||
|
||||
result = MA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -10789,8 +10843,16 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device
|
||||
pData->channelsOut = wf.nChannels;
|
||||
pData->sampleRateOut = wf.nSamplesPerSec;
|
||||
|
||||
/* Get the internal channel map based on the channel mask. */
|
||||
ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
|
||||
/*
|
||||
Get the internal channel map based on the channel mask. There is a possibility that GetMixFormat() returns
|
||||
a WAVEFORMATEX instead of a WAVEFORMATEXTENSIBLE, in which case the channel mask will be undefined. In this
|
||||
case we'll just use the default channel map.
|
||||
*/
|
||||
if (wf.wFormatTag == WAVE_FORMAT_EXTENSIBLE || wf.cbSize >= sizeof(MA_WAVEFORMATEXTENSIBLE)) {
|
||||
ma_channel_mask_to_channel_map__win32(wf.dwChannelMask, pData->channelsOut, pData->channelMapOut);
|
||||
} else {
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_microsoft, pData->channelMapOut, ma_countof(pData->channelMapOut), pData->channelsOut);
|
||||
}
|
||||
|
||||
/* Period size. */
|
||||
pData->periodsOut = (pData->periodsIn != 0) ? pData->periodsIn : MA_DEFAULT_PERIODS;
|
||||
@@ -10963,13 +11025,22 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device
|
||||
}
|
||||
|
||||
if (!wasInitializedUsingIAudioClient3) {
|
||||
ma_uint32 bufferSizeInFrames;
|
||||
ma_uint32 bufferSizeInFrames = 0;
|
||||
hr = ma_IAudioClient_GetBufferSize((ma_IAudioClient*)pData->pAudioClient, &bufferSizeInFrames);
|
||||
if (FAILED(hr)) {
|
||||
errorMsg = "[WASAPI] Failed to get audio client's actual buffer size.", result = ma_result_from_HRESULT(hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
When using process loopback mode, retrieval of the buffer size seems to result in totally
|
||||
incorrect values. In this case we'll just assume it's the same size as what we requested
|
||||
when we initialized the client.
|
||||
*/
|
||||
if (usingProcessLoopback) {
|
||||
bufferSizeInFrames = (ma_uint32)((periodDurationInMicroseconds * pData->periodsOut) * pData->sampleRateOut / 1000000);
|
||||
}
|
||||
|
||||
pData->periodSizeInFramesOut = bufferSizeInFrames / pData->periodsOut;
|
||||
}
|
||||
|
||||
@@ -29309,7 +29380,7 @@ static ma_result ma_device__post_init_setup(ma_device* pDevice, ma_device_type d
|
||||
pDevice->playback.inputCacheConsumed = 0;
|
||||
pDevice->playback.inputCacheRemaining = 0;
|
||||
|
||||
if ((pDevice->type == ma_device_type_duplex && ma_context_is_backend_asynchronous(pDevice->pContext)) || /* Duplex with asynchronous backend. */
|
||||
if (pDevice->type == ma_device_type_duplex || /* Duplex. backend may decide to use ma_device_handle_backend_data_callback() which will require this cache. */
|
||||
ma_data_converter_get_required_input_frame_count(&pDevice->playback.converter, 1, &unused) != MA_SUCCESS) /* Data conversion required input frame calculation not supported. */
|
||||
{
|
||||
/* We need a heap allocated cache. We want to size this based on the period size. */
|
||||
@@ -37299,7 +37370,7 @@ static /*__attribute__((noinline))*/ ma_result ma_gainer_process_pcm_frames_inte
|
||||
|
||||
/* Initialize the running gain. */
|
||||
for (iChannel = 0; iChannel < pGainer->config.channels; iChannel += 1) {
|
||||
float t = (pGainer->pOldGains[iChannel] - pGainer->pNewGains[iChannel]) * pGainer->masterVolume;
|
||||
float t = (pGainer->pNewGains[iChannel] - pGainer->pOldGains[iChannel]) * pGainer->masterVolume;
|
||||
pRunningGainDelta[iChannel] = t * d;
|
||||
pRunningGain[iChannel] = (pGainer->pOldGains[iChannel] * pGainer->masterVolume) + (t * a);
|
||||
}
|
||||
@@ -62170,8 +62241,16 @@ static ma_result ma_engine_node_set_volume(ma_engine_node* pEngineNode, float vo
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
/* We should always have an active spatializer because it can be enabled and disabled dynamically. We can just use that for hodling our volume. */
|
||||
ma_spatializer_set_master_volume(&pEngineNode->spatializer, volume);
|
||||
ma_atomic_float_set(&pEngineNode->volume, volume);
|
||||
|
||||
/* If we're not smoothing we should bypass the volume gainer entirely. */
|
||||
if (pEngineNode->volumeSmoothTimeInPCMFrames == 0) {
|
||||
/* We should always have an active spatializer because it can be enabled and disabled dynamically. We can just use that for hodling our volume. */
|
||||
ma_spatializer_set_master_volume(&pEngineNode->spatializer, volume);
|
||||
} else {
|
||||
/* We're using volume smoothing, so apply the master volume to the gainer. */
|
||||
ma_gainer_set_gain(&pEngineNode->volumeGainer, volume);
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
@@ -62188,7 +62267,9 @@ static ma_result ma_engine_node_get_volume(const ma_engine_node* pEngineNode, fl
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
return ma_spatializer_get_master_volume(&pEngineNode->spatializer, pVolume);
|
||||
*pVolume = ma_atomic_float_get((ma_atomic_float*)&pEngineNode->volume);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -62204,6 +62285,7 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
|
||||
ma_bool32 isFadingEnabled;
|
||||
ma_bool32 isSpatializationEnabled;
|
||||
ma_bool32 isPanningEnabled;
|
||||
ma_bool32 isVolumeSmoothingEnabled;
|
||||
|
||||
frameCountIn = *pFrameCountIn;
|
||||
frameCountOut = *pFrameCountOut;
|
||||
@@ -62214,10 +62296,11 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
|
||||
totalFramesProcessedIn = 0;
|
||||
totalFramesProcessedOut = 0;
|
||||
|
||||
isPitchingEnabled = ma_engine_node_is_pitching_enabled(pEngineNode);
|
||||
isFadingEnabled = pEngineNode->fader.volumeBeg != 1 || pEngineNode->fader.volumeEnd != 1;
|
||||
isSpatializationEnabled = ma_engine_node_is_spatialization_enabled(pEngineNode);
|
||||
isPanningEnabled = pEngineNode->panner.pan != 0 && channelsOut != 1;
|
||||
isPitchingEnabled = ma_engine_node_is_pitching_enabled(pEngineNode);
|
||||
isFadingEnabled = pEngineNode->fader.volumeBeg != 1 || pEngineNode->fader.volumeEnd != 1;
|
||||
isSpatializationEnabled = ma_engine_node_is_spatialization_enabled(pEngineNode);
|
||||
isPanningEnabled = pEngineNode->panner.pan != 0 && channelsOut != 1;
|
||||
isVolumeSmoothingEnabled = pEngineNode->volumeSmoothTimeInPCMFrames > 0;
|
||||
|
||||
/* Keep going while we've still got data available for processing. */
|
||||
while (totalFramesProcessedOut < frameCountOut) {
|
||||
@@ -62293,6 +62376,19 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If we're using smoothing, we won't be applying volume via the spatializer, but instead from a ma_gainer. In this case
|
||||
we'll want to apply our volume now.
|
||||
*/
|
||||
if (isVolumeSmoothingEnabled) {
|
||||
if (isWorkingBufferValid) {
|
||||
ma_gainer_process_pcm_frames(&pEngineNode->volumeGainer, pWorkingBuffer, pWorkingBuffer, framesJustProcessedOut);
|
||||
} else {
|
||||
ma_gainer_process_pcm_frames(&pEngineNode->volumeGainer, pWorkingBuffer, pRunningFramesIn, framesJustProcessedOut);
|
||||
isWorkingBufferValid = MA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If at this point we still haven't actually done anything with the working buffer we need
|
||||
to just read straight from the input buffer.
|
||||
@@ -62324,11 +62420,21 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
|
||||
|
||||
if (channelsIn == channelsOut) {
|
||||
/* No channel conversion required. Just copy straight to the output buffer. */
|
||||
ma_copy_and_apply_volume_factor_f32(pRunningFramesOut, pWorkingBuffer, framesJustProcessedOut * channelsOut, volume);
|
||||
if (isVolumeSmoothingEnabled) {
|
||||
/* Volume has already been applied. Just copy straight to the output buffer. */
|
||||
ma_copy_pcm_frames(pRunningFramesOut, pWorkingBuffer, framesJustProcessedOut * channelsOut, ma_format_f32, channelsOut);
|
||||
} else {
|
||||
/* Volume has not been applied yet. Copy and apply volume in the same pass. */
|
||||
ma_copy_and_apply_volume_factor_f32(pRunningFramesOut, pWorkingBuffer, framesJustProcessedOut * channelsOut, volume);
|
||||
}
|
||||
} else {
|
||||
/* Channel conversion required. TODO: Add support for channel maps here. */
|
||||
ma_channel_map_apply_f32(pRunningFramesOut, NULL, channelsOut, pWorkingBuffer, NULL, channelsIn, framesJustProcessedOut, ma_channel_mix_mode_simple, pEngineNode->monoExpansionMode);
|
||||
ma_apply_volume_factor_f32(pRunningFramesOut, framesJustProcessedOut * channelsOut, volume);
|
||||
|
||||
/* If we're using smoothing, the volume will have already been applied. */
|
||||
if (!isVolumeSmoothingEnabled) {
|
||||
ma_apply_volume_factor_f32(pRunningFramesOut, framesJustProcessedOut * channelsOut, volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62552,6 +62658,7 @@ typedef struct
|
||||
size_t baseNodeOffset;
|
||||
size_t resamplerOffset;
|
||||
size_t spatializerOffset;
|
||||
size_t gainerOffset;
|
||||
} ma_engine_node_heap_layout;
|
||||
|
||||
static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pConfig, ma_engine_node_heap_layout* pHeapLayout)
|
||||
@@ -62561,6 +62668,7 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo
|
||||
ma_node_config baseNodeConfig;
|
||||
ma_linear_resampler_config resamplerConfig;
|
||||
ma_spatializer_config spatializerConfig;
|
||||
ma_gainer_config gainerConfig;
|
||||
ma_uint32 channelsIn;
|
||||
ma_uint32 channelsOut;
|
||||
ma_channel defaultStereoChannelMap[2] = {MA_CHANNEL_SIDE_LEFT, MA_CHANNEL_SIDE_RIGHT}; /* <-- Consistent with the default channel map of a stereo listener. Means channel conversion can run on a fast path. */
|
||||
@@ -62626,6 +62734,20 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo
|
||||
pHeapLayout->sizeInBytes += ma_align_64(tempHeapSize);
|
||||
|
||||
|
||||
/* Gainer. Will not be used if we are not using smoothing. */
|
||||
if (pConfig->volumeSmoothTimeInPCMFrames > 0) {
|
||||
gainerConfig = ma_gainer_config_init(channelsIn, pConfig->volumeSmoothTimeInPCMFrames);
|
||||
|
||||
result = ma_gainer_get_heap_size(&gainerConfig, &tempHeapSize);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
pHeapLayout->gainerOffset = pHeapLayout->sizeInBytes;
|
||||
pHeapLayout->sizeInBytes += ma_align_64(tempHeapSize);
|
||||
}
|
||||
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -62659,6 +62781,7 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p
|
||||
ma_fader_config faderConfig;
|
||||
ma_spatializer_config spatializerConfig;
|
||||
ma_panner_config pannerConfig;
|
||||
ma_gainer_config gainerConfig;
|
||||
ma_uint32 channelsIn;
|
||||
ma_uint32 channelsOut;
|
||||
ma_channel defaultStereoChannelMap[2] = {MA_CHANNEL_SIDE_LEFT, MA_CHANNEL_SIDE_RIGHT}; /* <-- Consistent with the default channel map of a stereo listener. Means channel conversion can run on a fast path. */
|
||||
@@ -62681,15 +62804,17 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p
|
||||
pEngineNode->_pHeap = pHeap;
|
||||
MA_ZERO_MEMORY(pHeap, heapLayout.sizeInBytes);
|
||||
|
||||
pEngineNode->pEngine = pConfig->pEngine;
|
||||
pEngineNode->sampleRate = (pConfig->sampleRate > 0) ? pConfig->sampleRate : ma_engine_get_sample_rate(pEngineNode->pEngine);
|
||||
pEngineNode->monoExpansionMode = pConfig->monoExpansionMode;
|
||||
pEngineNode->pitch = 1;
|
||||
pEngineNode->oldPitch = 1;
|
||||
pEngineNode->oldDopplerPitch = 1;
|
||||
pEngineNode->isPitchDisabled = pConfig->isPitchDisabled;
|
||||
pEngineNode->isSpatializationDisabled = pConfig->isSpatializationDisabled;
|
||||
pEngineNode->pinnedListenerIndex = pConfig->pinnedListenerIndex;
|
||||
pEngineNode->pEngine = pConfig->pEngine;
|
||||
pEngineNode->sampleRate = (pConfig->sampleRate > 0) ? pConfig->sampleRate : ma_engine_get_sample_rate(pEngineNode->pEngine);
|
||||
pEngineNode->volumeSmoothTimeInPCMFrames = pConfig->volumeSmoothTimeInPCMFrames;
|
||||
pEngineNode->monoExpansionMode = pConfig->monoExpansionMode;
|
||||
ma_atomic_float_set(&pEngineNode->volume, 1);
|
||||
pEngineNode->pitch = 1;
|
||||
pEngineNode->oldPitch = 1;
|
||||
pEngineNode->oldDopplerPitch = 1;
|
||||
pEngineNode->isPitchDisabled = pConfig->isPitchDisabled;
|
||||
pEngineNode->isSpatializationDisabled = pConfig->isSpatializationDisabled;
|
||||
pEngineNode->pinnedListenerIndex = pConfig->pinnedListenerIndex;
|
||||
|
||||
channelsIn = (pConfig->channelsIn != 0) ? pConfig->channelsIn : ma_engine_get_channels(pConfig->pEngine);
|
||||
channelsOut = (pConfig->channelsOut != 0) ? pConfig->channelsOut : ma_engine_get_channels(pConfig->pEngine);
|
||||
@@ -62769,6 +62894,18 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p
|
||||
goto error3;
|
||||
}
|
||||
|
||||
|
||||
/* We'll need a gainer for smoothing out volume changes if we have a non-zero smooth time. We apply this before converting to the output channel count. */
|
||||
if (pConfig->volumeSmoothTimeInPCMFrames > 0) {
|
||||
gainerConfig = ma_gainer_config_init(channelsIn, pConfig->volumeSmoothTimeInPCMFrames);
|
||||
|
||||
result = ma_gainer_init_preallocated(&gainerConfig, ma_offset_ptr(pHeap, heapLayout.gainerOffset), &pEngineNode->volumeGainer);
|
||||
if (result != MA_SUCCESS) {
|
||||
goto error3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return MA_SUCCESS;
|
||||
|
||||
/* No need for allocation callbacks here because we use a preallocated heap. */
|
||||
@@ -62817,6 +62954,10 @@ MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocati
|
||||
ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
|
||||
|
||||
/* Now that the node has been uninitialized we can safely uninitialize the rest. */
|
||||
if (pEngineNode->volumeSmoothTimeInPCMFrames > 0) {
|
||||
ma_gainer_uninit(&pEngineNode->volumeGainer, pAllocationCallbacks);
|
||||
}
|
||||
|
||||
ma_spatializer_uninit(&pEngineNode->spatializer, pAllocationCallbacks);
|
||||
ma_linear_resampler_uninit(&pEngineNode->resampler, pAllocationCallbacks);
|
||||
|
||||
@@ -62940,6 +63081,7 @@ MA_API ma_result ma_engine_init(const ma_engine_config* pConfig, ma_engine* pEng
|
||||
}
|
||||
|
||||
pEngine->monoExpansionMode = engineConfig.monoExpansionMode;
|
||||
pEngine->defaultVolumeSmoothTimeInPCMFrames = engineConfig.defaultVolumeSmoothTimeInPCMFrames;
|
||||
ma_allocation_callbacks_init_copy(&pEngine->allocationCallbacks, &engineConfig.allocationCallbacks);
|
||||
|
||||
#if !defined(MA_NO_RESOURCE_MANAGER)
|
||||
@@ -63755,9 +63897,14 @@ static ma_result ma_sound_init_from_data_source_internal(ma_engine* pEngine, con
|
||||
source that provides this information upfront.
|
||||
*/
|
||||
engineNodeConfig = ma_engine_node_config_init(pEngine, type, pConfig->flags);
|
||||
engineNodeConfig.channelsIn = pConfig->channelsIn;
|
||||
engineNodeConfig.channelsOut = pConfig->channelsOut;
|
||||
engineNodeConfig.monoExpansionMode = pConfig->monoExpansionMode;
|
||||
engineNodeConfig.channelsIn = pConfig->channelsIn;
|
||||
engineNodeConfig.channelsOut = pConfig->channelsOut;
|
||||
engineNodeConfig.volumeSmoothTimeInPCMFrames = pConfig->volumeSmoothTimeInPCMFrames;
|
||||
engineNodeConfig.monoExpansionMode = pConfig->monoExpansionMode;
|
||||
|
||||
if (engineNodeConfig.volumeSmoothTimeInPCMFrames == 0) {
|
||||
engineNodeConfig.volumeSmoothTimeInPCMFrames = pEngine->defaultVolumeSmoothTimeInPCMFrames;
|
||||
}
|
||||
|
||||
/* If we're loading from a data source the input channel count needs to be the data source's native channel count. */
|
||||
if (pConfig->pDataSource != NULL) {
|
||||
@@ -63957,10 +64104,11 @@ MA_API ma_result ma_sound_init_copy(ma_engine* pEngine, const ma_sound* pExistin
|
||||
}
|
||||
|
||||
config = ma_sound_config_init_2(pEngine);
|
||||
config.pDataSource = pSound->pResourceManagerDataSource;
|
||||
config.flags = flags;
|
||||
config.pInitialAttachment = pGroup;
|
||||
config.monoExpansionMode = pExistingSound->engineNode.monoExpansionMode;
|
||||
config.pDataSource = pSound->pResourceManagerDataSource;
|
||||
config.flags = flags;
|
||||
config.pInitialAttachment = pGroup;
|
||||
config.monoExpansionMode = pExistingSound->engineNode.monoExpansionMode;
|
||||
config.volumeSmoothTimeInPCMFrames = pExistingSound->engineNode.volumeSmoothTimeInPCMFrames;
|
||||
|
||||
result = ma_sound_init_from_data_source_internal(pEngine, &config, pSound);
|
||||
if (result != MA_SUCCESS) {
|
||||
|
||||
Reference in New Issue
Block a user