]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Be more careful with changing precision. Stop using snd_pcm_status_get_driver_htstamp.
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Sat, 27 Mar 2021 15:37:29 +0000 (15:37 +0000)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Sat, 27 Mar 2021 15:37:29 +0000 (15:37 +0000)
audio_alsa.c

index 69722d12f8836f9b031e942784b616967ebcad64..45a51321e52e7b658993e2ca347e533017b07214 100644 (file)
@@ -1456,18 +1456,23 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
   if (ret == 0) {
 
 // must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
-#if SND_LIB_MINOR == 0
+//#if SND_LIB_MINOR == 0
     snd_pcm_status_get_htstamp(alsa_snd_pcm_status, &update_timestamp);
-#else
-    snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &update_timestamp);
-#endif
+//#else
+//    snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &update_timestamp);
+//#endif
 
     *state = snd_pcm_status_get_state(alsa_snd_pcm_status);
 
     if ((*state == SND_PCM_STATE_RUNNING) || (*state == SND_PCM_STATE_DRAINING)) {
 
-      uint64_t update_timestamp_ns =
-          update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
+ //     uint64_t update_timestamp_ns =
+ //         update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
+
+      uint64_t update_timestamp_ns = update_timestamp.tv_sec;
+      update_timestamp_ns = update_timestamp_ns * 1000000000;
+      update_timestamp_ns = update_timestamp_ns + update_timestamp.tv_nsec;
+
 
       // if the update_timestamp is zero, we take this to mean that the device doesn't report
       // interrupt timings. (It could be that it's not a real hardware device.)
@@ -1497,7 +1502,7 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
       if (update_timestamp_ns == 0) {
         ret = snd_pcm_delay(alsa_handle, delay);
       } else {
-        *delay = snd_pcm_status_get_delay(alsa_snd_pcm_status);
+        snd_pcm_sframes_t delay_temp = snd_pcm_status_get_delay(alsa_snd_pcm_status);
 
         /*
         // It seems that the alsa library uses CLOCK_REALTIME before 1.0.28, even though
@@ -1514,11 +1519,15 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
         else
           clock_gettime(CLOCK_REALTIME, &tn);
 
-        uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
+        // uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
+        uint64_t time_now_ns = tn.tv_sec;
+        time_now_ns = time_now_ns * 1000000000;
+        time_now_ns = time_now_ns + tn.tv_nsec;
+
 
         // see if it's stalled
 
-        if ((stall_monitor_start_time != 0) && (stall_monitor_frame_count == *delay)) {
+        if ((stall_monitor_start_time != 0) && (stall_monitor_frame_count == delay_temp)) {
           // hasn't outputted anything since the last call to delay()
 
           if (((update_timestamp_ns - stall_monitor_start_time) > stall_monitor_error_threshold) ||
@@ -1539,19 +1548,27 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
           }
         } else {
           stall_monitor_start_time = update_timestamp_ns;
-          stall_monitor_frame_count = *delay;
+          stall_monitor_frame_count = delay_temp;
         }
 
         if (ret == 0) {
           uint64_t delta = time_now_ns - update_timestamp_ns;
 
-          uint64_t frames_played_since_last_interrupt =
-              ((uint64_t)config.output_rate * delta) / 1000000000;
+//          uint64_t frames_played_since_last_interrupt =
+//              ((uint64_t)config.output_rate * delta) / 1000000000;
+
+            uint64_t frames_played_since_last_interrupt = config.output_rate;
+            frames_played_since_last_interrupt = frames_played_since_last_interrupt * delta;
+            frames_played_since_last_interrupt = frames_played_since_last_interrupt / 1000000000;
+
+
           snd_pcm_sframes_t frames_played_since_last_interrupt_sized =
               frames_played_since_last_interrupt;
-
-          *delay = *delay - frames_played_since_last_interrupt_sized;
+          if ((frames_played_since_last_interrupt_sized < 0) || ((uint64_t)frames_played_since_last_interrupt_sized != frames_played_since_last_interrupt))
+            debug(1,"overflow resizing frames_played_since_last_interrupt % " PRIx64 " to frames_played_since_last_interrupt %lx.", frames_played_since_last_interrupt, frames_played_since_last_interrupt_sized);
+          delay_temp = delay_temp - frames_played_since_last_interrupt_sized;
         }
+        *delay = delay_temp;
       }
     } else { // not running, thus no delay information, thus can't check for
              // stall