mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-21 15:56:58 +02:00
Add support for pre-allocation to engine nodes.
This commit is contained in:
+174
-36
@@ -1878,8 +1878,14 @@ typedef struct
|
|||||||
MA_ATOMIC ma_bool8 isPitchDisabled; /* When set to true, pitching will be disabled which will allow the resampler to be bypassed to save some computation. */
|
MA_ATOMIC ma_bool8 isPitchDisabled; /* When set to true, pitching will be disabled which will allow the resampler to be bypassed to save some computation. */
|
||||||
MA_ATOMIC ma_bool8 isSpatializationDisabled; /* Set to false by default. When set to false, will not have spatialisation applied. */
|
MA_ATOMIC ma_bool8 isSpatializationDisabled; /* Set to false by default. When set to false, will not have spatialisation applied. */
|
||||||
MA_ATOMIC ma_uint8 pinnedListenerIndex; /* The index of the listener this node should always use for spatialization. If set to (ma_uint8)-1 the engine will use the closest listener. */
|
MA_ATOMIC ma_uint8 pinnedListenerIndex; /* The index of the listener this node should always use for spatialization. If set to (ma_uint8)-1 the engine will use the closest listener. */
|
||||||
|
|
||||||
|
/* Memory management. */
|
||||||
|
void* _pHeap;
|
||||||
|
ma_bool32 _ownsHeap;
|
||||||
} ma_engine_node;
|
} ma_engine_node;
|
||||||
|
|
||||||
|
MA_API ma_result ma_engine_node_get_heap_size(const ma_engine_node_config* pConfig, size_t* pHeapSizeInBytes);
|
||||||
|
MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* pConfig, void* pHeap, ma_engine_node* pEngineNode);
|
||||||
MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_engine_node* pEngineNode);
|
MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_engine_node* pEngineNode);
|
||||||
MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocation_callbacks* pAllocationCallbacks);
|
MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocation_callbacks* pAllocationCallbacks);
|
||||||
|
|
||||||
@@ -12329,9 +12335,115 @@ static ma_node_vtable g_ma_engine_node_vtable__group =
|
|||||||
MA_NODE_FLAG_DIFFERENT_PROCESSING_RATES /* The engine node does resampling so should let miniaudio know about it. */
|
MA_NODE_FLAG_DIFFERENT_PROCESSING_RATES /* The engine node does resampling so should let miniaudio know about it. */
|
||||||
};
|
};
|
||||||
|
|
||||||
MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_engine_node* pEngineNode)
|
|
||||||
|
|
||||||
|
static ma_node_config ma_engine_node_base_node_config_init(const ma_engine_node_config* pConfig)
|
||||||
|
{
|
||||||
|
ma_node_config baseNodeConfig;
|
||||||
|
|
||||||
|
if (pConfig->type == ma_engine_node_type_sound) {
|
||||||
|
/* Sound. */
|
||||||
|
baseNodeConfig = ma_node_config_init();
|
||||||
|
baseNodeConfig.vtable = &g_ma_engine_node_vtable__sound;
|
||||||
|
baseNodeConfig.initialState = ma_node_state_stopped; /* Sounds are stopped by default. */
|
||||||
|
} else {
|
||||||
|
/* Group. */
|
||||||
|
baseNodeConfig = ma_node_config_init();
|
||||||
|
baseNodeConfig.vtable = &g_ma_engine_node_vtable__group;
|
||||||
|
baseNodeConfig.initialState = ma_node_state_started; /* Groups are started by default. */
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseNodeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ma_spatializer_config ma_engine_node_spatializer_config_init(const ma_node_config* pBaseNodeConfig)
|
||||||
|
{
|
||||||
|
return ma_spatializer_config_init(pBaseNodeConfig->pInputChannels[0], pBaseNodeConfig->pOutputChannels[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t sizeInBytes;
|
||||||
|
size_t baseNodeOffset;
|
||||||
|
size_t spatializerOffset;
|
||||||
|
} 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)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
|
size_t tempHeapSize;
|
||||||
|
ma_node_config baseNodeConfig;
|
||||||
|
ma_spatializer_config spatializerConfig;
|
||||||
|
ma_uint32 channelsIn;
|
||||||
|
ma_uint32 channelsOut;
|
||||||
|
|
||||||
|
MA_ASSERT(pHeapLayout);
|
||||||
|
|
||||||
|
MA_ZERO_OBJECT(pHeapLayout);
|
||||||
|
|
||||||
|
if (pConfig == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pConfig->pEngine == NULL) {
|
||||||
|
return MA_INVALID_ARGS; /* An engine must be specified. */
|
||||||
|
}
|
||||||
|
|
||||||
|
pHeapLayout->sizeInBytes = 0;
|
||||||
|
|
||||||
|
channelsIn = (pConfig->channelsIn != 0) ? pConfig->channelsIn : ma_engine_get_channels(pConfig->pEngine);
|
||||||
|
channelsOut = (pConfig->channelsOut != 0) ? pConfig->channelsOut : ma_engine_get_channels(pConfig->pEngine);
|
||||||
|
|
||||||
|
|
||||||
|
/* Base node. */
|
||||||
|
baseNodeConfig = ma_engine_node_base_node_config_init(pConfig);
|
||||||
|
baseNodeConfig.pInputChannels = &channelsIn;
|
||||||
|
baseNodeConfig.pOutputChannels = &channelsOut;
|
||||||
|
|
||||||
|
pHeapLayout->baseNodeOffset = pHeapLayout->sizeInBytes;
|
||||||
|
pHeapLayout->sizeInBytes += 0; /* TODO: Implement pre-allocation for nodes. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Spatializer. */
|
||||||
|
spatializerConfig = ma_engine_node_spatializer_config_init(&baseNodeConfig);
|
||||||
|
|
||||||
|
result = ma_spatializer_get_heap_size(&spatializerConfig, &tempHeapSize);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result; /* Failed to retrieve the size of the heap for the spatializer. */
|
||||||
|
}
|
||||||
|
|
||||||
|
pHeapLayout->spatializerOffset = pHeapLayout->sizeInBytes;
|
||||||
|
pHeapLayout->sizeInBytes += tempHeapSize;
|
||||||
|
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_engine_node_get_heap_size(const ma_engine_node_config* pConfig, size_t* pHeapSizeInBytes)
|
||||||
|
{
|
||||||
|
ma_result result;
|
||||||
|
ma_engine_node_heap_layout heapLayout;
|
||||||
|
|
||||||
|
if (pHeapSizeInBytes == NULL) {
|
||||||
|
return MA_INVALID_ARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pHeapSizeInBytes = 0;
|
||||||
|
|
||||||
|
result = ma_engine_node_get_heap_layout(pConfig, &heapLayout);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pHeapSizeInBytes = heapLayout.sizeInBytes;
|
||||||
|
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* pConfig, void* pHeap, ma_engine_node* pEngineNode)
|
||||||
|
{
|
||||||
|
ma_result result;
|
||||||
|
ma_engine_node_heap_layout heapLayout;
|
||||||
ma_node_config baseNodeConfig;
|
ma_node_config baseNodeConfig;
|
||||||
ma_resampler_config resamplerConfig;
|
ma_resampler_config resamplerConfig;
|
||||||
ma_fader_config faderConfig;
|
ma_fader_config faderConfig;
|
||||||
@@ -12346,43 +12458,16 @@ MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const
|
|||||||
|
|
||||||
MA_ZERO_OBJECT(pEngineNode);
|
MA_ZERO_OBJECT(pEngineNode);
|
||||||
|
|
||||||
if (pConfig == NULL) {
|
result = ma_engine_node_get_heap_layout(pConfig, &heapLayout);
|
||||||
return MA_INVALID_ARGS; /* Config must be specified. */
|
if (result != MA_SUCCESS) {
|
||||||
}
|
return result;
|
||||||
|
|
||||||
if (pConfig->pEngine == NULL) {
|
|
||||||
return MA_INVALID_ARGS; /* An engine must be specified. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pConfig->pinnedListenerIndex != (ma_uint8)-1 && pConfig->pinnedListenerIndex >= ma_engine_get_listener_count(pConfig->pEngine)) {
|
if (pConfig->pinnedListenerIndex != (ma_uint8)-1 && pConfig->pinnedListenerIndex >= ma_engine_get_listener_count(pConfig->pEngine)) {
|
||||||
return MA_INVALID_ARGS; /* Invalid listener. */
|
return MA_INVALID_ARGS; /* Invalid listener. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assume the engine channel count if no channels were specified. */
|
pEngineNode->_pHeap = pHeap;
|
||||||
channelsIn = (pConfig->channelsIn != 0) ? pConfig->channelsIn : ma_engine_get_channels(pConfig->pEngine);
|
|
||||||
channelsOut = (pConfig->channelsOut != 0) ? pConfig->channelsOut : ma_engine_get_channels(pConfig->pEngine);
|
|
||||||
|
|
||||||
if (pConfig->type == ma_engine_node_type_sound) {
|
|
||||||
/* Sound. */
|
|
||||||
baseNodeConfig = ma_node_config_init();
|
|
||||||
baseNodeConfig.vtable = &g_ma_engine_node_vtable__sound;
|
|
||||||
baseNodeConfig.pInputChannels = &channelsIn;
|
|
||||||
baseNodeConfig.pOutputChannels = &channelsOut;
|
|
||||||
baseNodeConfig.initialState = ma_node_state_stopped; /* Sounds are stopped by default. */
|
|
||||||
} else {
|
|
||||||
/* Group. */
|
|
||||||
baseNodeConfig = ma_node_config_init();
|
|
||||||
baseNodeConfig.vtable = &g_ma_engine_node_vtable__group;
|
|
||||||
baseNodeConfig.pInputChannels = &channelsIn;
|
|
||||||
baseNodeConfig.pOutputChannels = &channelsOut;
|
|
||||||
baseNodeConfig.initialState = ma_node_state_started; /* Groups are started by default. */
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ma_node_init(&pConfig->pEngine->nodeGraph, &baseNodeConfig, pAllocationCallbacks, &pEngineNode->baseNode);
|
|
||||||
if (result != MA_SUCCESS) {
|
|
||||||
goto error0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pEngineNode->pEngine = pConfig->pEngine;
|
pEngineNode->pEngine = pConfig->pEngine;
|
||||||
pEngineNode->sampleRate = (pConfig->sampleRate > 0) ? pConfig->sampleRate : ma_engine_get_sample_rate(pEngineNode->pEngine);
|
pEngineNode->sampleRate = (pConfig->sampleRate > 0) ? pConfig->sampleRate : ma_engine_get_sample_rate(pEngineNode->pEngine);
|
||||||
pEngineNode->pitch = 1;
|
pEngineNode->pitch = 1;
|
||||||
@@ -12392,6 +12477,22 @@ MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const
|
|||||||
pEngineNode->isSpatializationDisabled = pConfig->isSpatializationDisabled;
|
pEngineNode->isSpatializationDisabled = pConfig->isSpatializationDisabled;
|
||||||
pEngineNode->pinnedListenerIndex = pConfig->pinnedListenerIndex;
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
/* Base node. */
|
||||||
|
baseNodeConfig = ma_engine_node_base_node_config_init(pConfig);
|
||||||
|
baseNodeConfig.pInputChannels = &channelsIn;
|
||||||
|
baseNodeConfig.pOutputChannels = &channelsOut;
|
||||||
|
|
||||||
|
result = ma_node_init(&pConfig->pEngine->nodeGraph, &baseNodeConfig, &pEngineNode->pEngine->allocationCallbacks, &pEngineNode->baseNode); /* TODO: Implement pre-allocation for nodes. */
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
goto error0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We can now initialize the effects we need in order to implement the engine node. There's a
|
We can now initialize the effects we need in order to implement the engine node. There's a
|
||||||
defined order of operations here, mainly centered around when we convert our channels from the
|
defined order of operations here, mainly centered around when we convert our channels from the
|
||||||
@@ -12423,10 +12524,10 @@ MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const
|
|||||||
Spatialization comes next. We spatialize based ont he node's output channel count. It's up the caller to
|
Spatialization comes next. We spatialize based ont he node's output channel count. It's up the caller to
|
||||||
ensure channels counts link up correctly in the node graph.
|
ensure channels counts link up correctly in the node graph.
|
||||||
*/
|
*/
|
||||||
spatializerConfig = ma_spatializer_config_init(baseNodeConfig.pInputChannels[0], baseNodeConfig.pOutputChannels[0]);
|
spatializerConfig = ma_engine_node_spatializer_config_init(&baseNodeConfig);
|
||||||
spatializerConfig.gainSmoothTimeInFrames = pEngineNode->pEngine->gainSmoothTimeInFrames;
|
spatializerConfig.gainSmoothTimeInFrames = pEngineNode->pEngine->gainSmoothTimeInFrames;
|
||||||
|
|
||||||
result = ma_spatializer_init(&spatializerConfig, pAllocationCallbacks, &pEngineNode->spatializer); /* TODO: Use a preallocated heap for this. */
|
result = ma_spatializer_init_preallocated(&spatializerConfig, ma_offset_ptr(pHeap, heapLayout.spatializerOffset), &pEngineNode->spatializer);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
goto error2;
|
goto error2;
|
||||||
}
|
}
|
||||||
@@ -12440,16 +12541,47 @@ MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const
|
|||||||
|
|
||||||
result = ma_panner_init(&pannerConfig, &pEngineNode->panner);
|
result = ma_panner_init(&pannerConfig, &pEngineNode->panner);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
goto error2;
|
goto error3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
|
|
||||||
|
error3: ma_spatializer_uninit(&pEngineNode->spatializer, NULL); /* <-- No need for allocation callbacks here because we use a preallocated heap. */
|
||||||
error2: ma_resampler_uninit(&pEngineNode->resampler);
|
error2: ma_resampler_uninit(&pEngineNode->resampler);
|
||||||
error1: ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
|
error1: ma_node_uninit(&pEngineNode->baseNode, NULL); /* <-- No need for allocation callbacks here because we use a preallocated heap. */
|
||||||
error0: return result;
|
error0: return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MA_API ma_result ma_engine_node_init(const ma_engine_node_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_engine_node* pEngineNode)
|
||||||
|
{
|
||||||
|
ma_result result;
|
||||||
|
size_t heapSizeInBytes;
|
||||||
|
void* pHeap;
|
||||||
|
|
||||||
|
result = ma_engine_node_get_heap_size(pConfig, &heapSizeInBytes);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heapSizeInBytes > 0) {
|
||||||
|
pHeap = ma_malloc(heapSizeInBytes, pAllocationCallbacks);
|
||||||
|
if (pHeap == NULL) {
|
||||||
|
return MA_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pHeap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ma_engine_node_init_preallocated(pConfig, pHeap, pEngineNode);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
ma_free(pHeap, pAllocationCallbacks);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pEngineNode->_ownsHeap = MA_TRUE;
|
||||||
|
return MA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocation_callbacks* pAllocationCallbacks)
|
MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocation_callbacks* pAllocationCallbacks)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -12459,7 +12591,13 @@ MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocati
|
|||||||
ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
|
ma_node_uninit(&pEngineNode->baseNode, pAllocationCallbacks);
|
||||||
|
|
||||||
/* Now that the node has been uninitialized we can safely uninitialize the rest. */
|
/* Now that the node has been uninitialized we can safely uninitialize the rest. */
|
||||||
|
ma_spatializer_uninit(&pEngineNode->spatializer, NULL);
|
||||||
ma_resampler_uninit(&pEngineNode->resampler);
|
ma_resampler_uninit(&pEngineNode->resampler);
|
||||||
|
|
||||||
|
/* Free the heap last. */
|
||||||
|
if (pEngineNode->_pHeap != NULL && pEngineNode->_ownsHeap) {
|
||||||
|
ma_free(pEngineNode->_pHeap, pAllocationCallbacks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user