monoscope: rework the scaling code
authorStefan Sauer <ensonic@users.sf.net>
Fri, 12 Feb 2016 19:57:29 +0000 (20:57 +0100)
committerStefan Sauer <ensonic@users.sf.net>
Fri, 12 Feb 2016 20:01:03 +0000 (21:01 +0100)
The running average was wrong and the resulting scaling factor was only held in
place using the CLAMP. In addtion we are now convering quickly to volume
changes.

FInally now with this change, we can change the resolution defines and
everythign adjusts.

gst/monoscope/monoscope.c

index 90c012b..3500879 100644 (file)
@@ -99,7 +99,7 @@ monoscope_update (struct monoscope_state *stateptr, gint16 data[convolver_big])
   int hh1 = hh - 1;
   guint32 *loc;
 
-  int factor;
+  double factor;
   int max = 1;
   short *thisEq = stateptr->copyEq;
 
@@ -108,21 +108,26 @@ monoscope_update (struct monoscope_state *stateptr, gint16 data[convolver_big])
 
   memset (stateptr->display, 0, scope_width * scope_height * sizeof (guint32));
   for (i = 0; i < convolver_small; i++) {
-    avg = thisEq[i] + (stateptr->avgEq[i] >> 1);
+    avg = (thisEq[i] + stateptr->avgEq[i]) >> 1;
     stateptr->avgEq[i] = avg;
     avg = abs (avg);
     max = MAX (max, avg);
   }
-  stateptr->avgMax += max - (stateptr->avgMax >> 8);
-  if (stateptr->avgMax < max)
-    stateptr->avgMax = max;     /* Avoid overflow */
-  factor = 0x7fffffff / stateptr->avgMax;
-  /* Keep the scaling sensible. */
-  factor = CLAMP (factor, (1 << 8), (1 << 18));
+  /* running average, 4 values is enough to make it follow volume changes
+   * if this value is too large it will converge slowly
+   */
+  stateptr->avgMax += (max / 4) - (stateptr->avgMax / 4);
+
+  /* input is +/- avgMax, output is +/- hh */
+  if (stateptr->avgMax) {
+    factor = (gdouble) hh / stateptr->avgMax;
+  } else {
+    factor = 1.0;
+  }
 
   for (i = 0; i < scope_width; i++) {
+    /* scale 16bit signed audio values to scope_height */
     foo = stateptr->avgEq[i] * factor;
-    foo >>= 18;
     foo = CLAMP (foo, -hh1, hh1);
     bar = (i + ((foo + hh) * scope_width));
     if ((bar > 0) && (bar < (scope_width * scope_height))) {