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 ...@@ -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 ...@@ -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,27 +7457,25 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man ...@@ -7457,27 +7457,25 @@ 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
...@@ -7496,7 +7494,6 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man ...@@ -7496,7 +7494,6 @@ MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_man
if (pFramesRead != NULL) { if (pFramesRead != NULL) {
*pFramesRead = framesRead; *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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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;
} }
......
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