mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Try fixing a bug where a sound is never unmarked as mixing.
This should fix a deadlock when uninitializing a sound after it's reached the end.
This commit is contained in:
+55
-55
@@ -8338,72 +8338,72 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s
|
|||||||
ma_uint64 framesProcessed;
|
ma_uint64 framesProcessed;
|
||||||
|
|
||||||
/* If we're marked at the end we need to stop the sound and do nothing. */
|
/* If we're marked at the end we need to stop the sound and do nothing. */
|
||||||
if (pSound->atEnd) {
|
if (!pSound->atEnd) {
|
||||||
ma_sound_stop_internal(pSound);
|
/* If we're seeking, do so now before reading. */
|
||||||
return;
|
if (pSound->seekTarget != MA_SEEK_TARGET_NONE) {
|
||||||
}
|
pSound->seekTarget = MA_SEEK_TARGET_NONE;
|
||||||
|
ma_data_source_seek_to_pcm_frame(pSound->pDataSource, pSound->seekTarget);
|
||||||
/* If we're seeking, do so now before reading. */
|
|
||||||
if (pSound->seekTarget != MA_SEEK_TARGET_NONE) {
|
|
||||||
pSound->seekTarget = MA_SEEK_TARGET_NONE;
|
|
||||||
ma_data_source_seek_to_pcm_frame(pSound->pDataSource, pSound->seekTarget);
|
|
||||||
|
|
||||||
/* Any time-dependant effects need to have their times updated. */
|
/* Any time-dependant effects need to have their times updated. */
|
||||||
ma_engine_effect_set_time(&pSound->effect, pSound->seekTarget);
|
ma_engine_effect_set_time(&pSound->effect, pSound->seekTarget);
|
||||||
}
|
|
||||||
|
|
||||||
/* If the sound is being delayed we don't want to mix anything, nor do we want to advance time forward from the perspective of the data source. */
|
|
||||||
if ((pSound->runningTimeInEngineFrames + frameCount) > pSound->startDelayInEngineFrames) {
|
|
||||||
/* We're not delayed so we can mix or seek. In order to get frame-exact playback timing we need to start mixing from an offset. */
|
|
||||||
ma_uint64 currentTimeInFrames;
|
|
||||||
ma_uint64 offsetInFrames;
|
|
||||||
|
|
||||||
offsetInFrames = 0;
|
|
||||||
if (pSound->startDelayInEngineFrames > pSound->runningTimeInEngineFrames) {
|
|
||||||
offsetInFrames = pSound->startDelayInEngineFrames - pSound->runningTimeInEngineFrames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_ASSERT(offsetInFrames < frameCount);
|
/* If the sound is being delayed we don't want to mix anything, nor do we want to advance time forward from the perspective of the data source. */
|
||||||
|
if ((pSound->runningTimeInEngineFrames + frameCount) > pSound->startDelayInEngineFrames) {
|
||||||
|
/* We're not delayed so we can mix or seek. In order to get frame-exact playback timing we need to start mixing from an offset. */
|
||||||
|
ma_uint64 currentTimeInFrames;
|
||||||
|
ma_uint64 offsetInFrames;
|
||||||
|
|
||||||
/*
|
offsetInFrames = 0;
|
||||||
An obvious optimization is to skip mixing if the sound is not audible. The problem with this, however, is that the effect may need to update some
|
if (pSound->startDelayInEngineFrames > pSound->runningTimeInEngineFrames) {
|
||||||
internal state such as timing information for things like fades, delays, echos, etc. We're going to always mix the sound if it's active and trust
|
offsetInFrames = pSound->startDelayInEngineFrames - pSound->runningTimeInEngineFrames;
|
||||||
the mixer to optimize the volume = 0 case, and let the effect do it's own internal optimizations in non-audible cases.
|
}
|
||||||
*/
|
|
||||||
result = ma_mixer_mix_data_source(&pGroup->mixer, pSound->pDataSource, offsetInFrames, (frameCount - offsetInFrames), &framesProcessed, pSound->volume, &pSound->effect, pSound->isLooping);
|
MA_ASSERT(offsetInFrames < frameCount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
An obvious optimization is to skip mixing if the sound is not audible. The problem with this, however, is that the effect may need to update some
|
||||||
|
internal state such as timing information for things like fades, delays, echos, etc. We're going to always mix the sound if it's active and trust
|
||||||
|
the mixer to optimize the volume = 0 case, and let the effect do it's own internal optimizations in non-audible cases.
|
||||||
|
*/
|
||||||
|
result = ma_mixer_mix_data_source(&pGroup->mixer, pSound->pDataSource, offsetInFrames, (frameCount - offsetInFrames), &framesProcessed, pSound->volume, &pSound->effect, pSound->isLooping);
|
||||||
|
|
||||||
/* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */
|
/* If we reached the end of the sound we'll want to mark it as at the end and stop it. This should never be returned for looping sounds. */
|
||||||
if (result == MA_AT_END) {
|
if (result == MA_AT_END) {
|
||||||
c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* This will be set to false in ma_sound_start(). */
|
c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* This will be set to false in ma_sound_start(). */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For the benefit of the main effect we need to ensure the local time is updated explicitly. This is required for allowing time-based effects to
|
For the benefit of the main effect we need to ensure the local time is updated explicitly. This is required for allowing time-based effects to
|
||||||
support loop transitions properly.
|
support loop transitions properly.
|
||||||
*/
|
*/
|
||||||
result = ma_sound_get_cursor_in_pcm_frames(pSound, ¤tTimeInFrames);
|
result = ma_sound_get_cursor_in_pcm_frames(pSound, ¤tTimeInFrames);
|
||||||
if (result == MA_SUCCESS) {
|
if (result == MA_SUCCESS) {
|
||||||
ma_engine_effect_set_time(&pSound->effect, currentTimeInFrames);
|
ma_engine_effect_set_time(&pSound->effect, currentTimeInFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
pSound->runningTimeInEngineFrames += offsetInFrames + framesProcessed;
|
pSound->runningTimeInEngineFrames += offsetInFrames + framesProcessed;
|
||||||
} else {
|
|
||||||
/* The sound hasn't started yet. Just keep advancing time forward, but leave the data source alone. */
|
|
||||||
pSound->runningTimeInEngineFrames += frameCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're stopping after a delay we need to check if the delay has expired and if so, stop for real. */
|
|
||||||
if (pSound->stopDelayInEngineFramesRemaining > 0) {
|
|
||||||
if (pSound->stopDelayInEngineFramesRemaining >= frameCount) {
|
|
||||||
pSound->stopDelayInEngineFramesRemaining -= frameCount;
|
|
||||||
} else {
|
} else {
|
||||||
pSound->stopDelayInEngineFramesRemaining = 0;
|
/* The sound hasn't started yet. Just keep advancing time forward, but leave the data source alone. */
|
||||||
|
pSound->runningTimeInEngineFrames += frameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop the sound if the delay has been reached. */
|
/* If we're stopping after a delay we need to check if the delay has expired and if so, stop for real. */
|
||||||
if (pSound->stopDelayInEngineFramesRemaining == 0) {
|
if (pSound->stopDelayInEngineFramesRemaining > 0) {
|
||||||
ma_sound_stop_internal(pSound);
|
if (pSound->stopDelayInEngineFramesRemaining >= frameCount) {
|
||||||
|
pSound->stopDelayInEngineFramesRemaining -= frameCount;
|
||||||
|
} else {
|
||||||
|
pSound->stopDelayInEngineFramesRemaining = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the sound if the delay has been reached. */
|
||||||
|
if (pSound->stopDelayInEngineFramesRemaining == 0) {
|
||||||
|
ma_sound_stop_internal(pSound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* The sound is at the end. Make sure it's marked as stopped. */
|
||||||
|
ma_sound_stop_internal(pSound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user