Fix a bug relating to the handling of looping sounds.

This commit is contained in:
David Reid
2021-06-13 12:50:27 +10:00
parent 7858e098f5
commit a26d41ed11
+61 -41
View File
@@ -1367,7 +1367,7 @@ struct ma_resource_manager_data_buffer
ma_uint32 flags; /* The flags that were passed used to initialize the buffer. */ ma_uint32 flags; /* The flags that were passed used to initialize the buffer. */
ma_uint32 executionCounter; /* For allocating execution orders for jobs. */ ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */ ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
ma_uint64 cursorInPCMFrames; /* Only updated by the public API. Never written nor read from the job thread. */ ma_uint64 seekTargetInPCMFrames; /* Only updated by the public API. Never written nor read from the job thread. */
ma_bool32 seekToCursorOnNextRead; /* On the next read we need to seek to the frame cursor. */ ma_bool32 seekToCursorOnNextRead; /* On the next read we need to seek to the frame cursor. */
MA_ATOMIC ma_result result; /* Keeps track of a result of decoding. Set to MA_BUSY while the buffer is still loading. Set to MA_SUCCESS when loading is finished successfully. Otherwise set to some other code. */ MA_ATOMIC ma_result result; /* Keeps track of a result of decoding. Set to MA_BUSY while the buffer is still loading. Set to MA_SUCCESS when loading is finished successfully. Otherwise set to some other code. */
MA_ATOMIC ma_bool32 isLooping; /* Can be read and written by different threads at the same time. Must be used atomically. */ MA_ATOMIC ma_bool32 isLooping; /* Can be read and written by different threads at the same time. Must be used atomically. */
@@ -7445,7 +7445,7 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
if (pDataBuffer->seekToCursorOnNextRead) { if (pDataBuffer->seekToCursorOnNextRead) {
pDataBuffer->seekToCursorOnNextRead = MA_FALSE; pDataBuffer->seekToCursorOnNextRead = MA_FALSE;
result = ma_data_source_seek_to_pcm_frame(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pDataBuffer->cursorInPCMFrames); result = ma_data_source_seek_to_pcm_frame(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pDataBuffer->seekTargetInPCMFrames);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
@@ -7457,45 +7457,42 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
*/ */
if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_decoded) { if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_decoded) {
ma_uint64 availableFrames; ma_uint64 availableFrames;
isDecodedBufferBusy = (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY);
if (ma_resource_manager_data_buffer_get_available_frames(pDataBuffer, &availableFrames) == MA_SUCCESS) { if (ma_resource_manager_data_buffer_get_available_frames(pDataBuffer, &availableFrames) == MA_SUCCESS) {
/* Don't try reading more than the available frame count. */ /* Don't try reading more than the available frame count. */
if (frameCount > availableFrames) { if (frameCount > availableFrames) {
frameCount = availableFrames; frameCount = availableFrames;
isDecodedBufferBusy = (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY); } else {
isDecodedBufferBusy = MA_FALSE; /* We have enough frames available in the buffer to avoid a MA_BUSY status. */
if (!isDecodedBufferBusy && availableFrames == 0) {
result = MA_AT_END;
}
} }
} }
} }
if (result == MA_SUCCESS) { result = ma_resource_manager_data_buffer_get_looping(pDataBuffer, &isLooping);
result = ma_resource_manager_data_buffer_get_looping(pDataBuffer, &isLooping); if (result != MA_SUCCESS) {
if (result != MA_SUCCESS) { return result;
return result; }
}
result = ma_data_source_read_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFramesOut, frameCount, &framesRead, isLooping); result = ma_data_source_read_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFramesOut, frameCount, &framesRead, isLooping);
pDataBuffer->cursorInPCMFrames += framesRead;
/* /*
If we returned MA_AT_END, but the node is still loading, we don't want to return that code or else the caller will interpret the sound If we returned MA_AT_END, but the node is still loading, we don't want to return that code or else the caller will interpret the sound
as at the end and terminate decoding. as at the end and terminate decoding.
*/ */
if (result == MA_AT_END) { if (result == MA_AT_END) {
if (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY) { if (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY) {
result = MA_BUSY;
}
}
if (isDecodedBufferBusy) {
result = MA_BUSY; result = MA_BUSY;
} }
}
if (pFramesRead != NULL) { if (isDecodedBufferBusy) {
*pFramesRead = framesRead; result = MA_BUSY;
} }
if (pFramesRead != NULL) {
*pFramesRead = framesRead;
} }
return result; return result;
@@ -7510,7 +7507,7 @@ MA_API ma_result ma_resource_manager_data_buffer_seek_to_pcm_frame(ma_resource_m
/* If we haven't yet got a connector we need to abort. */ /* If we haven't yet got a connector we need to abort. */
if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_unknown) { if (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode) == ma_resource_manager_data_supply_type_unknown) {
pDataBuffer->cursorInPCMFrames = frameIndex; pDataBuffer->seekTargetInPCMFrames = frameIndex;
pDataBuffer->seekToCursorOnNextRead = MA_TRUE; pDataBuffer->seekToCursorOnNextRead = MA_TRUE;
return MA_BUSY; /* Still loading. */ return MA_BUSY; /* Still loading. */
} }
@@ -7520,7 +7517,7 @@ MA_API ma_result ma_resource_manager_data_buffer_seek_to_pcm_frame(ma_resource_m
return result; return result;
} }
pDataBuffer->cursorInPCMFrames = frameIndex; pDataBuffer->seekTargetInPCMFrames = ~(ma_uint64)0; /* <-- For identification purposes. */
pDataBuffer->seekToCursorOnNextRead = MA_FALSE; pDataBuffer->seekToCursorOnNextRead = MA_FALSE;
return MA_SUCCESS; return MA_SUCCESS;
@@ -7576,9 +7573,35 @@ MA_API ma_result ma_resource_manager_data_buffer_get_cursor_in_pcm_frames(ma_res
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
*pCursor = pDataBuffer->cursorInPCMFrames; *pCursor = 0;
return MA_SUCCESS; switch (ma_resource_manager_data_buffer_node_get_data_supply_type(pDataBuffer->pNode))
{
case ma_resource_manager_data_supply_type_encoded:
{
return ma_decoder_get_cursor_in_pcm_frames(&pDataBuffer->connector.decoder, pCursor);
};
case ma_resource_manager_data_supply_type_decoded:
{
return ma_audio_buffer_get_cursor_in_pcm_frames(&pDataBuffer->connector.buffer, pCursor);
};
case ma_resource_manager_data_supply_type_decoded_paged:
{
return ma_paged_audio_buffer_get_cursor_in_pcm_frames(&pDataBuffer->connector.pagedBuffer, pCursor);
};
case ma_resource_manager_data_supply_type_unknown:
{
return MA_BUSY;
};
default:
{
return MA_INVALID_ARGS;
}
}
} }
MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength) MA_API ma_result ma_resource_manager_data_buffer_get_length_in_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pLength)
@@ -7663,19 +7686,16 @@ MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resourc
case ma_resource_manager_data_supply_type_decoded: case ma_resource_manager_data_supply_type_decoded:
{ {
if (pDataBuffer->pNode->data.decoded.decodedFrameCount > pDataBuffer->cursorInPCMFrames) { return ma_audio_buffer_get_available_frames(&pDataBuffer->connector.buffer, pAvailableFrames);
*pAvailableFrames = pDataBuffer->pNode->data.decoded.decodedFrameCount - pDataBuffer->cursorInPCMFrames;
} else {
*pAvailableFrames = 0;
}
return MA_SUCCESS;
}; };
case ma_resource_manager_data_supply_type_decoded_paged: case ma_resource_manager_data_supply_type_decoded_paged:
{ {
if (pDataBuffer->pNode->data.decodedPaged.decodedFrameCount > pDataBuffer->cursorInPCMFrames) { ma_uint64 cursor;
*pAvailableFrames = pDataBuffer->pNode->data.decodedPaged.decodedFrameCount - pDataBuffer->cursorInPCMFrames; ma_paged_audio_buffer_get_cursor_in_pcm_frames(&pDataBuffer->connector.pagedBuffer, &cursor);
if (pDataBuffer->pNode->data.decodedPaged.decodedFrameCount > cursor) {
*pAvailableFrames = pDataBuffer->pNode->data.decodedPaged.decodedFrameCount - cursor;
} else { } else {
*pAvailableFrames = 0; *pAvailableFrames = 0;
} }