From eca87665455f6d5a3092e90150e5a7929045cf1a Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 10 Mar 2023 22:19:28 +0100 Subject: [PATCH] Compute buffering and compensation without lock Once underflow has been read with a lock, the buffering and compensation may be performed without shared variables. --- app/src/audio_player.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/app/src/audio_player.c b/app/src/audio_player.c index d9aba58a..1bff2b76 100644 --- a/app/src/audio_player.c +++ b/app/src/audio_player.c @@ -180,6 +180,8 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink, // Read with lock held, to be used after unlocking bool played = ap->played; + uint32_t underflow = ap->underflow; + if (played) { uint32_t max_buffered_samples = ap->target_buffering + 12 * SC_AUDIO_OUTPUT_BUFFER_MS * ap->sample_rate / 1000 @@ -191,23 +193,8 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink, " samples", skip_samples); } - // Number of samples added (or removed, if negative) for compensation - int32_t instant_compensation = - (int32_t) samples_written - frame->nb_samples; - int32_t inserted_silence = (int32_t) ap->underflow; - - // The compensation must apply instantly, it must not be smoothed - ap->avg_buffering.avg += instant_compensation + inserted_silence; - - ap->underflow = 0; // reset - - // However, the buffering level must be smoothed - sc_average_push(&ap->avg_buffering, buffered_samples); - -#ifndef SC_AUDIO_PLAYER_NDEBUG - LOGD("[Audio] buffered_samples=%" PRIu32 " avg_buffering=%f", - buffered_samples, sc_average_get(&ap->avg_buffering)); -#endif + // reset (the current value was copied to a local variable) + ap->underflow = 0; } else { // SDL playback not started yet, do not accumulate more than // max_initial_buffering samples, this would cause unnecessary delay @@ -230,6 +217,23 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink, SDL_UnlockAudioDevice(ap->device); if (played) { + // Number of samples added (or removed, if negative) for compensation + int32_t instant_compensation = + (int32_t) samples_written - frame->nb_samples; + int32_t inserted_silence = (int32_t) underflow; + + // The compensation must apply instantly, it must not be smoothed + ap->avg_buffering.avg += instant_compensation + inserted_silence; + + + // However, the buffering level must be smoothed + sc_average_push(&ap->avg_buffering, buffered_samples); + +#ifndef SC_AUDIO_PLAYER_NDEBUG + LOGD("[Audio] buffered_samples=%" PRIu32 " avg_buffering=%f", + buffered_samples, sc_average_get(&ap->avg_buffering)); +#endif + ap->samples_since_resync += samples_written; if (ap->samples_since_resync >= ap->sample_rate) { // Recompute compensation every second