[MPlayer-dev-eng] Re: [PATCH] ao effect plugin: volnorm (or a simple & naive volume normalizer)

pl p_l at gmx.fr
Mon Mar 4 00:19:32 CET 2002


On Sun, Mar 03, 2002 at 11:43:51PM +0100, pl wrote:
> Here is a patch to "normalize" audio output, which means your playback
> should sound almost the same level.  Well... it's designed to do that,
> YMMV :)

Damn silences :) The new attached patch should improve this and be
slightly less reactive.

-- 
Best regards,
  pl
-------------- next part --------------
diff -x CVS -x *.mak -x *.o -ruN main+/libao2-orig/Makefile main+/libao2/Makefile
--- main+/libao2-orig/Makefile	Sun Mar  3 22:32:43 2002
+++ main+/libao2/Makefile	Sun Mar  3 22:40:27 2002
@@ -4,7 +4,7 @@
 LIBNAME = libao2.a
 
 # TODO: moveout ao_sdl.c so it's only used when SDL is detected
-SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_plugin.c pl_delay.c pl_format.c pl_surround.c remez.c pl_resample.c pl_volume.c pl_extrastereo.c $(OPTIONAL_SRCS)
+SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_plugin.c pl_delay.c pl_format.c pl_surround.c remez.c pl_resample.c pl_volume.c pl_extrastereo.c pl_volnorm.c $(OPTIONAL_SRCS)
 
 OBJS=$(SRCS:.c=.o)
 
diff -x CVS -x *.mak -x *.o -ruN main+/libao2-orig/audio_plugin.h main+/libao2/audio_plugin.h
--- main+/libao2-orig/audio_plugin.h	Sun Mar  3 22:32:47 2002
+++ main+/libao2/audio_plugin.h	Sun Mar  3 22:40:27 2002
@@ -54,7 +54,7 @@
 // This block should not be available in the pl_xxxx files
 // due to compilation issues
 #ifndef PLUGIN
-#define NPL 6+1 // Number of PLugins ( +1 list ends with NULL )
+#define NPL 7+1 // Number of PLugins ( +1 list ends with NULL )
 // List of plugins 
 extern ao_plugin_functions_t audio_plugin_delay;
 extern ao_plugin_functions_t audio_plugin_format; 
@@ -62,6 +62,7 @@
 extern ao_plugin_functions_t audio_plugin_resample;
 extern ao_plugin_functions_t audio_plugin_volume;
 extern ao_plugin_functions_t audio_plugin_extrastereo;
+extern ao_plugin_functions_t audio_plugin_volnorm;
 
 
 #define AO_PLUGINS { \
@@ -71,6 +72,7 @@
    &audio_plugin_resample, \
    &audio_plugin_volume, \
    &audio_plugin_extrastereo, \
+   &audio_plugin_volnorm, \
    NULL \
 }
 #endif /* PLUGIN */
Binary files main+/libao2-orig/libao2.a and main+/libao2/libao2.a differ
diff -x CVS -x *.mak -x *.o -ruN main+/libao2-orig/pl_volnorm.c main+/libao2/pl_volnorm.c
--- main+/libao2-orig/pl_volnorm.c	Thu Jan  1 01:00:00 1970
+++ main+/libao2/pl_volnorm.c	Mon Mar  4 00:08:52 2002
@@ -0,0 +1,172 @@
+/* Normalizer plugin
+ * 
+ * Limitations: 
+ *  - only AFMT_S16_LE supported
+ *  - no parameters yet => tweak the values by editing the #defines
+ *
+ * License: GPLv2
+ * Author: pl <p_l at gmx.fr> (c) 2002 and beyond...
+ *
+ * Sources: some ideas from volnorm for xmms
+ *
+ * */
+
+#define PLUGIN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <math.h>	// for sqrt()
+
+#include "audio_out.h"
+#include "audio_plugin.h"
+#include "audio_plugin_internal.h"
+#include "afmt.h"
+
+static ao_info_t info = {
+        "Volume normalizer",
+        "volnorm",
+        "pl <p_l at gmx.fr>",
+        ""
+};
+
+LIBAO_PLUGIN_EXTERN(volnorm)
+
+// mul is the value by which the samples are scaled
+// and has to be in [MUL_MIN, MUL_MAX]
+#define MUL_INIT 1.0
+#define MUL_MIN 0.1
+#define MUL_MAX 15.0
+static float mul;
+
+// "history" value of the filter
+static float lastavg;
+
+// SMOOTH_* must be in ]0.0, 1.0[
+// The new value accounts for SMOOTH_MUL in the value and history
+#define SMOOTH_MUL 0.02
+#define SMOOTH_LASTAVG 0.02
+
+// ideal average level
+#define MID_S16 (INT16_MAX * 0.25)
+
+// silence level
+#define SIL_S16 (INT16_MAX * 0.03)
+
+// local data
+static struct {
+  int      inuse;     	// This plugin is in use TRUE, FALSE
+  int      format;	// sample fomat
+} pl_volnorm = {0, 0};
+
+
+// minimal interface
+static int control(int cmd,int arg){
+  switch(cmd){
+  case AOCONTROL_PLUGIN_SET_LEN:
+    return CONTROL_OK;
+  }
+  return CONTROL_UNKNOWN;
+}
+
+// minimal interface
+// open & setup audio device
+// return: 1=success 0=fail
+static int init(){
+  switch(ao_plugin_data.format){
+    case(AFMT_S16_LE):
+      break;
+    default:
+      fprintf(stderr,"[pl_volnorm] Audio format not yet supported.\n");
+      return 0;
+  }
+
+  pl_volnorm.format = ao_plugin_data.format;
+  pl_volnorm.inuse = 1;
+
+  reset();
+
+  printf("[pl_volnorm] Normalizer plugin in use.\n");
+  return 1;
+}
+
+// close plugin
+static void uninit(){
+  pl_volnorm.inuse=0;
+}
+
+// empty buffers
+static void reset(){
+  mul = MUL_INIT;
+  switch(ao_plugin_data.format) {
+    case(AFMT_S16_LE):
+      lastavg = MID_S16;
+      break;
+    default:
+      fprintf(stderr,"[pl_volnorm] internal inconsistency - please bugreport.\n");
+      *(char *) 0 = 0;
+  }
+}
+
+// processes 'ao_plugin_data.len' bytes of 'data'
+// called for every block of data
+static int play(){
+
+  switch(pl_volnorm.format){
+  case(AFMT_S16_LE): {
+
+#define CLAMP(x,m,M) do { if ((x)<(m)) (x) = (m); else if ((x)>(M)) (x) = (M); } while(0)
+
+    int16_t* data=(int16_t*)ao_plugin_data.data;
+    int len=ao_plugin_data.len / 2; // 16 bits samples
+
+    int32_t i;
+    register int32_t tmp;
+    register float curavg;
+    float newavg;
+    float neededmul;
+
+    // average of the current samples
+    curavg = 0.0;
+    for (i = 0; i < len ; ++i) {
+      tmp = data[i];
+      curavg += tmp * tmp;
+    }
+    curavg = sqrt(curavg / (float) len);
+
+    if (curavg > SIL_S16) {
+      neededmul = MID_S16 / ( curavg * mul);
+      mul = (1.0 - SMOOTH_MUL) * mul + SMOOTH_MUL * neededmul;
+
+      // Clamp the mul coefficient
+      CLAMP(mul, MUL_MIN, MUL_MAX);
+    }
+
+    // Scale & clamp the samples
+    for (i=0; i < len ; ++i) {
+      tmp = data[i] * mul;
+      CLAMP(tmp, INT16_MIN, INT16_MAX);
+      data[i] = tmp;
+    }
+
+    // evaluation of newavg (is not exact because of samples clamping)
+    newavg = mul * curavg;
+
+#if 0
+    printf("time = %d len = %d curavg = %6.0f lastavg = %6.0f newavg = %6.0f\n"
+           " needed_m = %2.2f m = %2.2f\n\n",
+            time(NULL), len, curavg, lastavg, newavg, neededmul, mul);
+#endif
+
+    lastavg = (1.0 - SMOOTH_LASTAVG) * lastavg + SMOOTH_LASTAVG * newavg;
+    
+    break;
+  }
+  default:
+    return 0;
+  }
+  return 1;
+
+}
+
+


More information about the MPlayer-dev-eng mailing list