mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Fix some node timing errors.
This commit fixes a bug relating to nodes with a scheduled start/stop time. Whether or not the node is considered started or stopped is being incorrectly reported by `ma_node_get_state_by_time_range()`. Another issue is fixed in `ma_node_read_pcm_frames()`, which is related to the fix above, where the frame count can underflow thereby resulting in a crash. Public issue https://github.com/mackron/miniaudio/issues/969
This commit is contained in:
+19
-9
@@ -74965,12 +74965,12 @@ MA_API ma_node_state ma_node_get_state_by_time_range(const ma_node* pNode, ma_ui
|
|||||||
its start time not having been reached yet. Also, the stop time may have also been reached in
|
its start time not having been reached yet. Also, the stop time may have also been reached in
|
||||||
which case it'll be considered stopped.
|
which case it'll be considered stopped.
|
||||||
*/
|
*/
|
||||||
if (ma_node_get_state_time(pNode, ma_node_state_started) > globalTimeBeg) {
|
if (ma_node_get_state_time(pNode, ma_node_state_stopped) < globalTimeBeg) {
|
||||||
return ma_node_state_stopped; /* Start time has not yet been reached. */
|
return ma_node_state_stopped; /* End time is before the start of the range. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ma_node_get_state_time(pNode, ma_node_state_stopped) <= globalTimeEnd) {
|
if (ma_node_get_state_time(pNode, ma_node_state_started) > globalTimeEnd) {
|
||||||
return ma_node_state_stopped; /* Stop time has been reached. */
|
return ma_node_state_stopped; /* Start time is after the end of the range. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Getting here means the node is marked as started and is within its start/stop times. */
|
/* Getting here means the node is marked as started and is within its start/stop times. */
|
||||||
@@ -75050,14 +75050,14 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
|
|||||||
return MA_INVALID_ARGS; /* Invalid output bus index. */
|
return MA_INVALID_ARGS; /* Invalid output bus index. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalTimeBeg = globalTime;
|
||||||
|
globalTimeEnd = globalTime + frameCount;
|
||||||
|
|
||||||
/* Don't do anything if we're in a stopped state. */
|
/* Don't do anything if we're in a stopped state. */
|
||||||
if (ma_node_get_state_by_time_range(pNode, globalTime, globalTime + frameCount) != ma_node_state_started) {
|
if (ma_node_get_state_by_time_range(pNode, globalTimeBeg, globalTimeEnd) != ma_node_state_started) {
|
||||||
return MA_SUCCESS; /* We're in a stopped state. This is not an error - we just need to not read anything. */
|
return MA_SUCCESS; /* We're in a stopped state. This is not an error - we just need to not read anything. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
globalTimeBeg = globalTime;
|
|
||||||
globalTimeEnd = globalTime + frameCount;
|
|
||||||
startTime = ma_node_get_state_time(pNode, ma_node_state_started);
|
startTime = ma_node_get_state_time(pNode, ma_node_state_started);
|
||||||
stopTime = ma_node_get_state_time(pNode, ma_node_state_stopped);
|
stopTime = ma_node_get_state_time(pNode, ma_node_state_stopped);
|
||||||
|
|
||||||
@@ -75070,11 +75070,16 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
|
|||||||
therefore need to offset it by a number of frames to accommodate. The same thing applies for
|
therefore need to offset it by a number of frames to accommodate. The same thing applies for
|
||||||
the stop time.
|
the stop time.
|
||||||
*/
|
*/
|
||||||
timeOffsetBeg = (globalTimeBeg < startTime) ? (ma_uint32)(globalTimeEnd - startTime) : 0;
|
timeOffsetBeg = (globalTimeBeg < startTime) ? (ma_uint32)(startTime - globalTimeBeg) : 0;
|
||||||
timeOffsetEnd = (globalTimeEnd > stopTime) ? (ma_uint32)(globalTimeEnd - stopTime) : 0;
|
timeOffsetEnd = (globalTimeEnd > stopTime) ? (ma_uint32)(globalTimeEnd - stopTime) : 0;
|
||||||
|
|
||||||
/* Trim based on the start offset. We need to silence the start of the buffer. */
|
/* Trim based on the start offset. We need to silence the start of the buffer. */
|
||||||
if (timeOffsetBeg > 0) {
|
if (timeOffsetBeg > 0) {
|
||||||
|
MA_ASSERT(timeOffsetBeg <= frameCount);
|
||||||
|
if (timeOffsetBeg > frameCount) {
|
||||||
|
timeOffsetBeg = frameCount;
|
||||||
|
}
|
||||||
|
|
||||||
ma_silence_pcm_frames(pFramesOut, timeOffsetBeg, ma_format_f32, ma_node_get_output_channels(pNode, outputBusIndex));
|
ma_silence_pcm_frames(pFramesOut, timeOffsetBeg, ma_format_f32, ma_node_get_output_channels(pNode, outputBusIndex));
|
||||||
pFramesOut += timeOffsetBeg * ma_node_get_output_channels(pNode, outputBusIndex);
|
pFramesOut += timeOffsetBeg * ma_node_get_output_channels(pNode, outputBusIndex);
|
||||||
frameCount -= timeOffsetBeg;
|
frameCount -= timeOffsetBeg;
|
||||||
@@ -75082,6 +75087,11 @@ static ma_result ma_node_read_pcm_frames(ma_node* pNode, ma_uint32 outputBusInde
|
|||||||
|
|
||||||
/* Trim based on the end offset. We don't need to silence the tail section because we'll just have a reduced value written to pFramesRead. */
|
/* Trim based on the end offset. We don't need to silence the tail section because we'll just have a reduced value written to pFramesRead. */
|
||||||
if (timeOffsetEnd > 0) {
|
if (timeOffsetEnd > 0) {
|
||||||
|
MA_ASSERT(timeOffsetEnd <= frameCount);
|
||||||
|
if (timeOffsetEnd > frameCount) {
|
||||||
|
timeOffsetEnd = frameCount;
|
||||||
|
}
|
||||||
|
|
||||||
frameCount -= timeOffsetEnd;
|
frameCount -= timeOffsetEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user