From 3888125a24efa31e55aa1e05fd6b08c7e134a6a4 Mon Sep 17 00:00:00 2001 From: Mike Brady Date: Wed, 1 Aug 2018 09:35:28 +0100 Subject: [PATCH] Change calculation order to prevent overflow after about 26 hours at 44,100 fps in the frame rate calculations. Calculate frame rates whether statistcs are requested or not. Clean up some fps rate availability flags. --- audio_alsa.c | 4 +++- player.c | 53 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/audio_alsa.c b/audio_alsa.c index 27995d57..4ab704fe 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -894,14 +894,16 @@ int delay(long *the_delay) { } int get_rate_information(uint64_t *elapsed_time, uint64_t *frames_played) { + int response = 0; // zero means okay if (measurement_data_is_valid) { *elapsed_time = measurement_time - measurement_start_time; *frames_played = frames_played_at_measurement_time - frames_played_at_measurement_start_time; } else { *elapsed_time = 0; *frames_played = 0; + response = -1; } - return 0; + return response; } static int play(void *buf, int samples) { diff --git a/player.c b/player.c index 956a4dbd..3dd1ac4b 100644 --- a/player.c +++ b/player.c @@ -1445,7 +1445,7 @@ void player_thread_cleanup_handler(void *arg) { int elapsedHours = rawSeconds / 3600; int elapsedMin = (rawSeconds / 60) % 60; int elapsedSec = rawSeconds % 60; - if (conn->frame_rate_status == 0) + if (conn->frame_rate_status) inform("Playback Stopped. Total playing time %02d:%02d:%02d. Input: %0.2f, output: %0.2f frames per second.", elapsedHours, elapsedMin, elapsedSec, conn->input_frame_rate, conn->frame_rate); else @@ -1611,7 +1611,10 @@ void *player_thread_func(void *arg) { conn->playstart = time(NULL); conn->frame_rate = 0.0; - conn->frame_rate_status = -1; // zero means okay + conn->frame_rate_status = 0; + + conn->input_frame_rate = 0.0; + conn->input_frame_rate_status = 0; conn->buffer_occupancy = 0; @@ -2299,6 +2302,35 @@ void *player_thread_func(void *arg) { } } if (play_number % print_interval == 0) { + + // here, calculate the input and output frame rates, where possible, even if statistics have not been requested + // this is to calculate them in case they are needed by the D-Bus interface or elsewhere. + + if (conn->input_frame_rate_status) { + uint64_t elapsed_reception_time, frames_received; + elapsed_reception_time = conn->frames_inward_measurement_time - conn->frames_inward_measurement_start_time; + frames_received = conn->frames_inward_frames_received_at_measurement_time - conn->frames_inward_frames_received_at_measurement_start_time; + conn->input_frame_rate = (1.0 * frames_received) / elapsed_reception_time; // an IEEE double calculation with two 64-bit integers + conn->input_frame_rate = conn->input_frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected. + } + + if ((config.output->delay) && (config.no_sync == 0) && (config.output->rate_info)) { + uint64_t elapsed_play_time, frames_played; + if (config.output->rate_info(&elapsed_play_time, &frames_played)==0) + conn->frame_rate_status = 1; + else + conn->frame_rate_status = 0; + if (conn->frame_rate_status) { + conn->frame_rate = + (1.0 * frames_played) / elapsed_play_time; // an IEEE double calculation with two 64-bit integers + conn->frame_rate = + conn->frame_rate * (uint64_t)0x100000000; // this should just change the [binary] exponent in the IEEE FP representation; the mantissa should be unaffected. + } else { + conn->frame_rate = 0.0; + } + } + + // we can now calculate running averages for sync error (frames), corrections (ppm), // insertions plus deletions (ppm), drift (ppm) double moving_average_sync_error = (1.0 * tsum_of_sync_errors) / number_of_statistics; @@ -2309,26 +2341,9 @@ void *player_thread_func(void *arg) { // if ((play_number/print_interval)%20==0) if (config.statistics_requested) { if (at_least_one_frame_seen) { - if (conn->input_frame_rate_status == 1) { - uint64_t elapsed_reception_time, frames_received; - elapsed_reception_time = conn->frames_inward_measurement_time - conn->frames_inward_measurement_start_time; - frames_received = conn->frames_inward_frames_received_at_measurement_time - conn->frames_inward_frames_received_at_measurement_start_time; - conn->input_frame_rate = 1.0 * (frames_received * (uint64_t)0x100000000) / elapsed_reception_time; - } else { - conn->input_frame_rate = 0.0; - } if ((config.output->delay)) { if (config.no_sync == 0) { - if (config.output->rate_info) { - uint64_t elapsed_play_time, frames_played; - conn->frame_rate_status = - config.output->rate_info(&elapsed_play_time, &frames_played); - if (conn->frame_rate_status == 0) { - conn->frame_rate = - 1.0 * (frames_played * (uint64_t)0x100000000) / elapsed_play_time; - } - } inform("%*.1f," /* Sync error in milliseconds */ "%*.1f," /* net correction in ppm */ "%*.1f," /* corrections in ppm */