mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Engine: Fix some bugs with effects.
This commit is contained in:
@@ -12,11 +12,19 @@ typedef struct
|
||||
ma_sound* pSound;
|
||||
} sound_loaded_notification;
|
||||
|
||||
void on_sound_loaded(ma_async_notification* pNotification)
|
||||
void on_sound_loaded(ma_async_notification* pNotification, int code)
|
||||
{
|
||||
sound_loaded_notification* pLoadedNotification = (sound_loaded_notification*)pNotification;
|
||||
ma_uint64 lengthInPCMFrames;
|
||||
|
||||
if (code == MA_NOTIFICATION_INIT) {
|
||||
|
||||
} else if (code == MA_NOTIFICATION_COMPLETE) {
|
||||
|
||||
}
|
||||
|
||||
(void)code;
|
||||
|
||||
/*
|
||||
This will be fired when the sound has finished loading. We should be able to retrieve the length of the sound at this point. Here we'll just set
|
||||
the fade out time.
|
||||
|
||||
+74
-31
@@ -1049,15 +1049,30 @@ MA_API ma_result ma_slot_allocator_alloc(ma_slot_allocator* pAllocator, ma_uint6
|
||||
MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 slot);
|
||||
|
||||
|
||||
/* Notification codes for ma_async_notification. Used to allow some granularity for notification callbacks. */
|
||||
#define MA_NOTIFICATION_COMPLETE 0 /* Operation has fully completed. */
|
||||
#define MA_NOTIFICATION_INIT 1 /* Object has been initialized, but operation not fully completed yet. */
|
||||
#define MA_NOTIFICATION_FAILED 2 /* Failed to initialize. */
|
||||
|
||||
|
||||
/*
|
||||
Notification callback for asynchronous operations.
|
||||
*/
|
||||
typedef void ma_async_notification;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (* onSignal)(ma_async_notification* pNotification);
|
||||
void (* onSignal)(ma_async_notification* pNotification, int code);
|
||||
} ma_async_notification_callbacks;
|
||||
|
||||
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification);
|
||||
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification, int code);
|
||||
|
||||
|
||||
/*
|
||||
Event Notification
|
||||
|
||||
This notification signals an event internally on the MA_NOTIFICATION_COMPLETE and MA_NOTIFICATION_FAILED codes. All other codes are ignored.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ma_async_notification_callbacks cb;
|
||||
@@ -1920,7 +1935,7 @@ MA_API ma_result ma_effect_process_pcm_frames_ex(ma_effect* pEffect, const void*
|
||||
return result;
|
||||
}
|
||||
|
||||
if (effectFormatIn == formatIn && effectChannelsIn == channelsIn && effectFormatOut == formatOut && effectChannelsOut) {
|
||||
if (effectFormatIn == formatIn && effectChannelsIn == channelsIn && effectFormatOut == formatOut && effectChannelsOut == channelsOut) {
|
||||
/* Fast path. No need for any data conversion. */
|
||||
return ma_effect_process_pcm_frames(pEffect, pFramesIn, pFrameCountIn, pFramesOut, pFrameCountOut);
|
||||
} else {
|
||||
@@ -4129,7 +4144,7 @@ MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64
|
||||
|
||||
|
||||
|
||||
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification)
|
||||
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification, int code)
|
||||
{
|
||||
ma_async_notification_callbacks* pNotificationCallbacks = (ma_async_notification*)pNotification;
|
||||
|
||||
@@ -4141,11 +4156,18 @@ MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotificati
|
||||
return MA_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
pNotificationCallbacks->onSignal(pNotification);
|
||||
pNotificationCallbacks->onSignal(pNotification, code);
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
|
||||
static void ma_async_notification_event__on_signal(ma_async_notification* pNotification, int code)
|
||||
{
|
||||
if (code == MA_NOTIFICATION_COMPLETE || code == MA_NOTIFICATION_FAILED) {
|
||||
ma_async_notification_event_signal((ma_async_notification_event*)pNotification);
|
||||
}
|
||||
}
|
||||
|
||||
MA_API ma_result ma_async_notification_event_init(ma_async_notification_event* pNotificationEvent)
|
||||
{
|
||||
ma_result result;
|
||||
@@ -4154,7 +4176,7 @@ MA_API ma_result ma_async_notification_event_init(ma_async_notification_event* p
|
||||
return MA_INVALID_ARGS;
|
||||
}
|
||||
|
||||
pNotificationEvent->cb.onSignal = ma_async_notification_event_signal;
|
||||
pNotificationEvent->cb.onSignal = ma_async_notification_event__on_signal;
|
||||
|
||||
result = ma_event_init(&pNotificationEvent->e);
|
||||
if (result != MA_SUCCESS) {
|
||||
@@ -4990,7 +5012,7 @@ static ma_result ma_resource_manager__init_decoder(ma_resource_manager* pResourc
|
||||
return ma_decoder_init_vfs(pResourceManager->config.pVFS, pFilePath, &config, pDecoder);
|
||||
}
|
||||
|
||||
static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_manager_data_buffer* pDataBuffer)
|
||||
static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_manager_data_buffer* pDataBuffer, ma_async_notification* pNotification)
|
||||
{
|
||||
ma_result result;
|
||||
|
||||
@@ -5059,6 +5081,16 @@ static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_mana
|
||||
pDataBuffer->ds.onMap = NULL;
|
||||
pDataBuffer->ds.onUnmap = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
Initialization of the connector is when we can fire the MA_NOTIFICATION_INIT notification. This will give the application access to
|
||||
the format/channels/rate of the data source.
|
||||
*/
|
||||
if (result == MA_SUCCESS) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point the backend should be initialized. We do *not* want to set pDataSource->result here - that needs to be done at a higher level to ensure it's done as the last step. */
|
||||
return result;
|
||||
@@ -5173,14 +5205,14 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
|
||||
ma_yield();
|
||||
}
|
||||
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pNotification);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_resource_manager_data_buffer_node_free(pDataBuffer->pResourceManager, pDataBuffer->pNode);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
} else {
|
||||
/* Slow path. The data for this buffer has not yet been initialized. The first thing to do is allocate the new data buffer and insert it into the BST. */
|
||||
@@ -5217,7 +5249,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
|
||||
pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
|
||||
if (pFilePathCopy == NULL) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
|
||||
@@ -5235,7 +5267,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
|
||||
if (result != MA_SUCCESS) {
|
||||
/* Failed to post the job to the queue. Probably ran out of space. */
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
|
||||
@@ -5360,7 +5392,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
|
||||
|
||||
/* When loading synchronously we need to initialize the connector straight away. */
|
||||
if (result == MA_SUCCESS) {
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pNotification);
|
||||
}
|
||||
|
||||
pDataBuffer->pNode->result = result;
|
||||
@@ -5369,7 +5401,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
|
||||
/* If we failed to initialize make sure we fire the event and free memory. */
|
||||
if (result != MA_SUCCESS) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
|
||||
@@ -5377,10 +5409,10 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
|
||||
return result;
|
||||
}
|
||||
|
||||
/* It's not really necessary, but for completeness we'll want to fire the event if we have one in synchronous mode. */
|
||||
/* We'll need to fire the event if we have one in synchronous mode. */
|
||||
if (async == MA_FALSE) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5636,7 +5668,17 @@ MA_API ma_result ma_resource_manager_data_buffer_get_data_format(ma_resource_man
|
||||
return MA_BUSY; /* Still loading. */
|
||||
}
|
||||
|
||||
return ma_data_source_get_data_format(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFormat, pChannels, pSampleRate);
|
||||
if (pDataBuffer->connectorType == ma_resource_manager_data_buffer_connector_buffer) {
|
||||
MA_ASSERT(pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_decoded);
|
||||
|
||||
*pFormat = pDataBuffer->pNode->data.decoded.format;
|
||||
*pChannels = pDataBuffer->pNode->data.decoded.channels;
|
||||
*pSampleRate = pDataBuffer->pNode->data.decoded.sampleRate;
|
||||
|
||||
return MA_SUCCESS;
|
||||
} else {
|
||||
return ma_data_source_get_data_format(&pDataBuffer->connector.decoder, pFormat, pChannels, pSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pCursor)
|
||||
@@ -5894,7 +5936,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
|
||||
|
||||
if (pDataStream == NULL) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
return MA_INVALID_ARGS;
|
||||
@@ -5915,7 +5957,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
|
||||
|
||||
if (pResourceManager == NULL || pFilePath == NULL) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
return MA_INVALID_ARGS;
|
||||
@@ -5927,7 +5969,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
|
||||
pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
|
||||
if (pFilePathCopy == NULL) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_FAILED);
|
||||
}
|
||||
|
||||
return MA_OUT_OF_MEMORY;
|
||||
@@ -5942,7 +5984,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
|
||||
result = ma_resource_manager_post_job(pResourceManager, &job);
|
||||
if (result != MA_SUCCESS) {
|
||||
if (pNotification != NULL) {
|
||||
ma_async_notification_signal(pNotification);
|
||||
ma_async_notification_signal(pNotification, MA_NOTIFICATION_FAILED);
|
||||
}
|
||||
|
||||
ma__free_from_callbacks(pFilePathCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
|
||||
@@ -6651,7 +6693,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m
|
||||
pDataBuffer->pNode->data.encoded.sizeInBytes = sizeInBytes;
|
||||
}
|
||||
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->loadDataBuffer.pNotification);
|
||||
} else {
|
||||
/* Decoding. */
|
||||
ma_uint64 dataSizeInFrames;
|
||||
@@ -6737,7 +6779,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m
|
||||
ma_decoder_uninit(pDecoder);
|
||||
ma__free_from_callbacks(pDecoder, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODER*/);
|
||||
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->loadDataBuffer.pNotification);
|
||||
goto done;
|
||||
} else {
|
||||
/* We've still got more to decode. We just set the result to MA_BUSY which will tell the next section below to post a paging event. */
|
||||
@@ -6747,7 +6789,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m
|
||||
/* If we successfully initialized and the sound is of a known length we can start initialize the connector. */
|
||||
if (result == MA_SUCCESS || result == MA_BUSY) {
|
||||
if (pDataBuffer->pNode->data.decoded.decodedFrameCount > 0) {
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->loadDataBuffer.pNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6800,7 +6842,7 @@ done:
|
||||
pDataBuffer->pNode->data.decoded.decodedFrameCount = framesRead;
|
||||
|
||||
/* The sound is of a known length so we can go ahead and initialize the connector now. */
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->loadDataBuffer.pNotification);
|
||||
} else {
|
||||
pageDataBufferJob.pageDataBuffer.isUnknownLength = MA_TRUE;
|
||||
|
||||
@@ -6831,7 +6873,7 @@ done:
|
||||
|
||||
/* Only signal the other threads after the result has been set just for cleanliness sake. */
|
||||
if (pJob->loadDataBuffer.pNotification != NULL) {
|
||||
ma_async_notification_signal(pJob->loadDataBuffer.pNotification);
|
||||
ma_async_notification_signal(pJob->loadDataBuffer.pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
c89atomic_fetch_add_32(&pDataBuffer->pNode->executionPointer, 1);
|
||||
@@ -6976,7 +7018,7 @@ static ma_result ma_resource_manager_process_job__page_data_buffer(ma_resource_m
|
||||
|
||||
/* If it was an unknown length, we can finally initialize the connector. For sounds of a known length, the connector was initialized when the first page was decoded in MA_JOB_LOAD_DATA_BUFFER. */
|
||||
if (jobCopy.pageDataBuffer.isUnknownLength) {
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
|
||||
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->pageDataBuffer.pCompletedNotification);
|
||||
}
|
||||
|
||||
/* We need to set the status of the page so other things can know about it. We can only change the status away from MA_BUSY. If it's anything else it cannot be changed. */
|
||||
@@ -6984,7 +7026,7 @@ static ma_result ma_resource_manager_process_job__page_data_buffer(ma_resource_m
|
||||
|
||||
/* We need to signal an event to indicate that we're done. */
|
||||
if (jobCopy.pageDataBuffer.pCompletedNotification != NULL) {
|
||||
ma_async_notification_signal(jobCopy.pageDataBuffer.pCompletedNotification);
|
||||
ma_async_notification_signal(jobCopy.pageDataBuffer.pCompletedNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7056,7 +7098,8 @@ done:
|
||||
|
||||
/* Only signal the other threads after the result has been set just for cleanliness sake. */
|
||||
if (pJob->loadDataStream.pNotification != NULL) {
|
||||
ma_async_notification_signal(pJob->loadDataStream.pNotification);
|
||||
ma_async_notification_signal(pJob->loadDataStream.pNotification, MA_NOTIFICATION_INIT);
|
||||
ma_async_notification_signal(pJob->loadDataStream.pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);
|
||||
@@ -7091,7 +7134,7 @@ static ma_result ma_resource_manager_process_job__free_data_stream(ma_resource_m
|
||||
|
||||
/* The event needs to be signalled last. */
|
||||
if (pJob->freeDataStream.pNotification != NULL) {
|
||||
ma_async_notification_signal(pJob->freeDataStream.pNotification);
|
||||
ma_async_notification_signal(pJob->freeDataStream.pNotification, MA_NOTIFICATION_COMPLETE);
|
||||
}
|
||||
|
||||
/*c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);*/
|
||||
@@ -8029,7 +8072,7 @@ static ma_result ma_engine_effect__on_process_pcm_frames__general(ma_engine_effe
|
||||
break;
|
||||
}
|
||||
|
||||
totalFramesProcessedIn += frameCountOutThisIteration;
|
||||
totalFramesProcessedOut += frameCountOutThisIteration;
|
||||
}
|
||||
|
||||
|
||||
@@ -8112,7 +8155,7 @@ static ma_result ma_engine_effect__on_get_input_data_format(ma_effect* pEffect,
|
||||
MA_ASSERT(pEffect != NULL);
|
||||
|
||||
if (pEngineEffect->pPreEffect != NULL) {
|
||||
return ma_engine_effect__on_get_input_data_format(pEffect, pFormat, pChannels, pSampleRate);
|
||||
return ma_effect_get_input_data_format(pEngineEffect->pPreEffect, pFormat, pChannels, pSampleRate);
|
||||
} else {
|
||||
*pFormat = pEngineEffect->converter.config.formatIn;
|
||||
*pChannels = pEngineEffect->converter.config.channelsIn;
|
||||
|
||||
Reference in New Issue
Block a user