mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
runloop: the audio pace bit reads whether a write happened, not who might have written
RUNLOOP_PACE_AUDIO required runloop_is_libretro_running(), on the theory that with the core paused nothing writes to the driver. Wrong: audio_driver_menu_sample() feeds a frame of silence every menu iteration the core is not running, with the mixer, menu sounds and thumbnail video audio mixed in, through the same blocking audio_driver_flush() funnel. Audio holds the menu loop too, and the overlay said it did not. Stop predicting and record the fact. AUDIO_FLAG_WROTE is set at the three driver write sites, cleared at the top of runloop_iterate() alongside the pace reset, and the bit reads it. Whatever path reached the write - core, menu silence, mixer - the answer is the same.
This commit is contained in:
1 parent
ee439c5ee8
commit
c8f05b12f2
3 files changed
+20
-7
No files matched your search
+10
-1
@@ -175,7 +175,16 @@ enum audio_driver_state_flags
|
||||
* The threaded pipeline's producer only waits for ring space while
|
||||
* this is set: with the consumer parked, waiting could never end.
|
||||
*/
|
||||
AUDIO_FLAG_STARTED = (1 << 9)
|
||||
AUDIO_FLAG_STARTED = (1 << 9),
|
||||
/**
|
||||
* A driver write happened since the runloop last cleared this. Set at
|
||||
* the write sites, whichever path reached them - core audio, or the
|
||||
* frame of silence audio_driver_menu_sample() feeds while the core is
|
||||
* paused with the mixer and thumbnail audio mixed in. Read by the
|
||||
* runloop's pace record so "audio is holding the loop" is a fact
|
||||
* about this iteration rather than a guess about who wrote.
|
||||
*/
|
||||
AUDIO_FLAG_WROTE = (1 << 10)
|
||||
};
|
||||
|
||||
typedef struct audio_statistics
|
||||
|
||||
@@ -1248,6 +1248,7 @@ static void audio_driver_flush(audio_driver_state_t *audio_st,
|
||||
out_frames, mixer_gain, override);
|
||||
}
|
||||
#endif
|
||||
AUDIO_FLAGS_SET(audio_st, AUDIO_FLAG_WROTE);
|
||||
audio->write(audio_st->context_audio_data,
|
||||
audio_st->output_samples_buf,
|
||||
out_frames * 2 * sizeof(float));
|
||||
@@ -1321,6 +1322,7 @@ static void audio_driver_flush(audio_driver_state_t *audio_st,
|
||||
mixer_gain, override);
|
||||
}
|
||||
#endif
|
||||
AUDIO_FLAGS_SET(audio_st, AUDIO_FLAG_WROTE);
|
||||
audio->write(audio_st->context_audio_data,
|
||||
audio_st->output_samples_int16,
|
||||
out_frames * 2 * sizeof(int16_t));
|
||||
@@ -1738,6 +1740,7 @@ static void audio_driver_flush(audio_driver_state_t *audio_st,
|
||||
output_frames *= sizeof(int16_t); /* Unit: bytes */
|
||||
}
|
||||
|
||||
AUDIO_FLAGS_SET(audio_st, AUDIO_FLAG_WROTE);
|
||||
audio->write(audio_st->context_audio_data,
|
||||
output_data, output_frames * 2);
|
||||
}
|
||||
|
||||
@@ -7933,6 +7933,7 @@ int runloop_iterate(void)
|
||||
* than path, so it is set here and holds for those early returns:
|
||||
* they do rely on it. */
|
||||
runloop_st->pace = RUNLOOP_PACE_NONE;
|
||||
AUDIO_FLAGS_CLEAR(audio_st, AUDIO_FLAG_WROTE);
|
||||
if ( settings->bools.video_vsync
|
||||
&& !(input_st->flags & INP_FLAG_NONBLOCKING)
|
||||
&& !(runloop_st->flags & RUNLOOP_FLAG_FORCE_NONBLOCK))
|
||||
@@ -8287,14 +8288,14 @@ end:
|
||||
* puts the driver into non-blocking mode for a few frames while
|
||||
* audio_sync stays true, and during those frames audio is not
|
||||
* holding anything. */
|
||||
/* ...and a write actually happened this iteration. Not a predicate
|
||||
* on who might have written: the menu feeds a frame of silence
|
||||
* through the same blocking funnel while the core is paused, with
|
||||
* the mixer and thumbnail audio mixed in, so "libretro running" was
|
||||
* the wrong test. The flag is set at the write sites. */
|
||||
if ( (AUDIO_FLAGS_GET(audio_st) & AUDIO_FLAG_ACTIVE)
|
||||
&& !(AUDIO_FLAGS_GET(audio_st) & AUDIO_FLAG_NONBLOCK)
|
||||
/* ...and the core is actually writing samples this frame. In
|
||||
* the menu with the core paused the driver stays in blocking
|
||||
* mode but nothing calls audio_driver_write(). Same predicate
|
||||
* the RUNLOOP_STATE_MENU throttle uses for this question. */
|
||||
&& runloop_is_libretro_running(runloop_st,
|
||||
settings->bools.menu_pause_libretro))
|
||||
&& (AUDIO_FLAGS_GET(audio_st) & AUDIO_FLAG_WROTE))
|
||||
runloop_st->pace |= RUNLOOP_PACE_AUDIO;
|
||||
/* Mirrors the gate at the video_driver_scanline_after_frame() call
|
||||
* site, which skips the wait under fast-forward. A failed
|
||||
|
||||
Reference in new issue
Block a user