Commit a26d41ed authored by David Reid's avatar David Reid

Fix a bug relating to the handling of looping sounds.

parent 7858e098
......@@ -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 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_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_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. */
......@@ -7445,7 +7445,7 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
if (pDataBuffer->seekToCursorOnNextRead) {
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) {
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) {
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) {
/* Don't try reading more than the available frame count. */
if (frameCount > availableFrames) {
frameCount = availableFrames;
isDecodedBufferBusy = (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY);
if (!isDecodedBufferBusy && availableFrames == 0) {
result = MA_AT_END;
}
} else {
isDecodedBufferBusy = MA_FALSE; /* We have enough frames available in the buffer to avoid a MA_BUSY status. */
}
}
}
if (result == MA_SUCCESS) {
result = ma_resource_manager_data_buffer_get_looping(pDataBuffer, &isLooping);
if (result != MA_SUCCESS) {
return result;
}
result = ma_data_source_read_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFramesOut, frameCount, &framesRead, isLooping);
pDataBuffer->cursorInPCMFrames += framesRead;
result = ma_resource_manager_data_buffer_get_looping(pDataBuffer, &isLooping);
if (result != MA_SUCCESS) {
return result;
}
/*
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.
*/
if (result == MA_AT_END) {
if (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY) {
result = MA_BUSY;
}
}
result = ma_data_source_read_pcm_frames(ma_resource_manager_data_buffer_get_connector(pDataBuffer), pFramesOut, frameCount, &framesRead, isLooping);
if (isDecodedBufferBusy) {
/*
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.
*/
if (result == MA_AT_END) {
if (ma_resource_manager_data_buffer_node_result(pDataBuffer->pNode) == MA_BUSY) {
result = MA_BUSY;
}
}
if (pFramesRead != NULL) {
*pFramesRead = framesRead;
}
if (isDecodedBufferBusy) {
result = MA_BUSY;
}
if (pFramesRead != NULL) {
*pFramesRead = framesRead;
}
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 (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;
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;
}
pDataBuffer->cursorInPCMFrames = frameIndex;
pDataBuffer->seekTargetInPCMFrames = ~(ma_uint64)0; /* <-- For identification purposes. */
pDataBuffer->seekToCursorOnNextRead = MA_FALSE;
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;
}
*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)
......@@ -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:
{
if (pDataBuffer->pNode->data.decoded.decodedFrameCount > pDataBuffer->cursorInPCMFrames) {
*pAvailableFrames = pDataBuffer->pNode->data.decoded.decodedFrameCount - pDataBuffer->cursorInPCMFrames;
} else {
*pAvailableFrames = 0;
}
return MA_SUCCESS;
return ma_audio_buffer_get_available_frames(&pDataBuffer->connector.buffer, pAvailableFrames);
};
case ma_resource_manager_data_supply_type_decoded_paged:
{
if (pDataBuffer->pNode->data.decodedPaged.decodedFrameCount > pDataBuffer->cursorInPCMFrames) {
*pAvailableFrames = pDataBuffer->pNode->data.decodedPaged.decodedFrameCount - pDataBuffer->cursorInPCMFrames;
ma_uint64 cursor;
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 {
*pAvailableFrames = 0;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment