]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/time-smoother.c
export card information for sinks/sources and number of sinks/sources a profile would...
[pulseaudio] / src / pulsecore / time-smoother.c
index 2723edbad51feee873dc4f875f3473dcac6900f5..6562194893710fde54bd3beaf5f0f1099167025e 100644 (file)
@@ -209,8 +209,8 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
     i = s->history_idx;
     for (j = s->n_history; j > 0; j--) {
 
-        ax += s->history_x[i];
-        ay += s->history_y[i];
+        ax += (int64_t) s->history_x[i];
+        ay += (int64_t) s->history_y[i];
         c++;
 
         REDUCE_INC(i);
@@ -236,7 +236,7 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
         REDUCE_INC(i);
     }
 
-    r = (double) k / t;
+    r = (double) k / (double) t;
 
     return (s->monotonic && r < 0) ? 0 : r;
 }
@@ -268,8 +268,8 @@ static void calc_abc(pa_smoother *s) {
 
     /* Calculate a, b, c for y=ax^3+bx^2+cx */
     s->c = de;
-    s->b = (((double) (3*ky)/kx - dp - 2*de)) / kx;
-    s->a = (dp/kx - 2*s->b - de/kx) / (3*kx);
+    s->b = (((double) (3*ky)/ (double) kx - dp - (double) (2*de))) / (double) kx;
+    s->a = (dp/(double) kx - 2*s->b - de/(double) kx) / (double) (3*kx);
 
     s->abc_valid = TRUE;
 }
@@ -284,7 +284,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
         /* The requested point is right of the point where we wanted
          * to be on track again, thus just linearly estimate */
 
-        t = (int64_t) s->py + (int64_t) (s->dp * (x - s->px));
+        t = (int64_t) s->py + (int64_t) llrint(s->dp * (double) (x - s->px));
 
         if (t < 0)
             t = 0;
@@ -295,24 +295,29 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
             *deriv = s->dp;
 
     } else {
+        double tx, ty;
 
         /* Ok, we're not yet on track, thus let's interpolate, and
          * make sure that the first derivative is smooth */
 
         calc_abc(s);
 
+        tx = (double) x;
+
         /* Move to origin */
-        x -= s->ex;
+        tx -= (double) s->ex;
 
         /* Horner scheme */
-        *y = (pa_usec_t) ((double) x * (s->c + (double) x * (s->b + (double) x * s->a)));
+        ty = (tx * (s->c + tx * (s->b + tx * s->a)));
 
         /* Move back from origin */
-        *y += s->ey;
+        ty += (double) s->ey;
+
+        *y = ty >= 0 ? (pa_usec_t) llrint(ty) : 0;
 
         /* Horner scheme */
         if (deriv)
-            *deriv = s->c + ((double) x * (s->b*2 + (double) x * s->a*3));
+            *deriv = s->c + (tx * (s->b*2 + tx * s->a*3));
     }
 
     /* Guarantee monotonicity */
@@ -355,7 +360,7 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
 
     /* And calculate when we want to be on track again */
     s->px = s->ex + s->adjust_time;
-    s->py = s->ry + s->dp *s->adjust_time;
+    s->py = s->ry + (pa_usec_t) llrint(s->dp * (double) s->adjust_time);
 
     s->abc_valid = FALSE;
 
@@ -373,12 +378,15 @@ pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
 
     x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
 
+    if (s->monotonic)
+        if (x <= s->last_x)
+            x = s->last_x;
+
     estimate(s, x, &y, NULL);
 
     if (s->monotonic) {
 
         /* Make sure the querier doesn't jump forth and back. */
-        pa_assert(x >= s->last_x);
         s->last_x = x;
 
         if (y < s->last_y)
@@ -418,7 +426,8 @@ void pa_smoother_resume(pa_smoother *s, pa_usec_t x) {
     if (!s->paused)
         return;
 
-    pa_assert(x >= s->pause_time);
+    if (x < s->pause_time)
+        x = s->pause_time;
 
 /*     pa_log_debug("resume(%llu)", (unsigned long long) x); */
 
@@ -447,5 +456,12 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay)
 
 /*     pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / nde), nde); */
 
-    return (pa_usec_t) ((double) y_delay / nde);
+    return (pa_usec_t) llrint((double) y_delay / nde);
+}
+
+void pa_smoother_reset(pa_smoother *s) {
+    pa_assert(s);
+
+    s->n_history = 0;
+    s->abc_valid = FALSE;
 }