[MPlayer-dev-eng] [PATCH] simple 3-band equalizer

Nicolas George nicolas.george at ens.fr
Mon May 28 13:50:15 CEST 2007


Hi.

Here is a patch implementing a simple 3-band equalizer based on the
simulation of the RLC electronic circuit.

It is used this way: -af rlceq=440:1:0:0 . That will keep only the bass, the
cut-off frequencies being 440/2 and 440*2.

It appears to be much faster than -af equalizer (a quick benchmark tells me
five times faster). Furthermore, for certain values of the center-frequency,
it could be done with pure integer arithmetic.

Before submitting a complete patch, with manual page and algorithmic
comments, especially about the way the float format is selected.

Regards,

-- 
  Nicolas George


Index: libaf/Makefile
===================================================================
--- libaf/Makefile	(revision 23396)
+++ libaf/Makefile	(working copy)
@@ -16,6 +16,7 @@
               af_karaoke.c \
               af_pan.c \
               af_resample.c \
+              af_rlceq.c \
               af_sinesuppress.c \
               af_sub.c \
               af_surround.c \
Index: libaf/af_rlceq.c
===================================================================
--- libaf/af_rlceq.c	(revision 0)
+++ libaf/af_rlceq.c	(revision 0)
@@ -0,0 +1,165 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "af.h"
+
+typedef struct af_rlceq_state_s {
+    float old_u, old_du;
+    float uc, duc;
+    /*float ur, dur;*/
+    float ul, dul;
+} af_rlceq_state_t;
+
+typedef struct af_rlceq_s {
+    float mul_c, mul_r, mul_l;
+    float base_freq;
+    float k, k2;
+    af_rlceq_state_t *state;
+} af_rlceq_t;
+
+static int
+control_reinit(af_instance_t *af, af_data_t *data)
+{
+    af_rlceq_t *setup;
+    int i;
+
+    *af->data = *data;
+    af->data->format = AF_FORMAT_FLOAT_NE;
+    setup = af->setup;
+    if(setup->state != NULL)
+	free(setup->state);
+    setup->state = malloc(data->nch * sizeof(af_rlceq_state_t));
+    if(setup->state == NULL)
+	return(AF_ERROR);
+    for(i = 0; i < data->nch; i++) {
+	setup->state[i].old_u = 0;
+	setup->state[i].old_du = 0;
+	setup->state[i].uc = 0;
+	setup->state[i].duc = 0;
+	/*setup->state[i].ur = 0;
+	setup->state[i].dur = 0;*/
+	setup->state[i].ul = 0;
+	setup->state[i].dul = 0;
+    }
+    setup->k = 2 * 3.14159265 * setup->base_freq / data->rate;
+    setup->k2 = setup->k * setup->k;
+    return(af_test_output(af, data));
+}
+
+static int
+control_command_line(af_instance_t *af, const char *arg)
+{
+    af_rlceq_t *setup;
+
+    setup = af->setup;
+    sscanf(arg, "%f:%f:%f:%f", &setup->base_freq,
+	&setup->mul_c, &setup->mul_r, &setup->mul_l);
+    return(AF_OK);
+}
+
+static int
+control(struct af_instance_s *af, int cmd, void *arg)
+{
+    switch(cmd) {
+	case AF_CONTROL_REINIT:
+	    return(control_reinit(af, arg));
+	case AF_CONTROL_COMMAND_LINE:
+	    return(control_command_line(af, arg));
+    }
+    return(AF_UNKNOWN);
+}
+
+static void
+uninit(struct af_instance_s *af)
+{
+    af_rlceq_t *setup;
+
+    if(af->data != NULL)
+	free(af->data);
+    setup = af->setup;
+    if(setup != NULL) {
+	if(setup->state != NULL)
+	    free(setup->state);
+	free(af->setup);
+    }
+}
+
+static af_data_t *
+play(struct af_instance_s *af, af_data_t *data)
+{
+    int len;
+    int i, j;
+    float *a;
+    int nc;
+    float u, du, d2u;
+    float d2uc, /*d2ur,*/ d2ul;
+    float k, k2, mul_c, mul_r, mul_l;
+    af_rlceq_t *setup;
+    af_rlceq_state_t *s;
+    float ur;
+
+    setup = af->setup;
+    k = setup->k;
+    k2 = setup->k2;
+    mul_c = setup->mul_c;
+    mul_r = setup->mul_r;
+    mul_l = setup->mul_l;
+    len = data->len / sizeof(float);
+    nc = data->nch;
+    a = data->audio;
+    for(i = 0; i < len; i += nc) {
+	for(j = 0; j < nc; j++) {
+	    s = &setup->state[j];
+	    u = *a;
+	    du = u - s->old_u;
+	    d2u = du - s->old_du;
+	    d2uc = - k2 * s->uc - 2 * k * s->duc + k2 * u;
+	    /*d2ur = - k2 * s->ur - 2 * k * s->dur + 2 * k * du;*/
+	    d2ul = - k2 * s->ul - 2 * k * s->dul + d2u;
+	    s->duc += d2uc;
+	    /*s->dur += d2ur;*/
+	    s->dul += d2ul;
+	    s->uc += s->duc;
+	    /*s->ur += s->dur;*/
+	    s->ul += s->dul;
+	    //ur = u - ul - uc;
+	    s->old_u = u;
+	    s->old_du = du;
+	    ur = u - s->uc - s->ul;
+	    *a = mul_c * s->uc + mul_r * /*s->*/ur + mul_l * s->ul;
+	    a++;
+	}
+    }
+    return(data);
+}
+
+static int
+af_open(af_instance_t *af){
+    af_rlceq_t *setup;
+
+    af->control = control;
+    af->uninit = uninit;
+    af->play = play;
+    af->mul.d = 1;
+    af->mul.n = 1;
+    af->data = malloc(sizeof(af_data_t));
+    af->setup = setup = malloc(sizeof(af_rlceq_state_t));
+    if(af->data == NULL || af->setup == NULL)
+	return(AF_ERROR);
+    setup->mul_c = 1;
+    setup->mul_r = 1;
+    setup->mul_l = 1;
+    setup->base_freq = 440;
+    setup->state = NULL;
+    return(AF_OK);
+}
+
+af_info_t af_info_rlceq = {
+    "RLC-based equalizer",
+    "rlceq",
+    "Nicolas George",
+    "",
+    AF_FLAGS_REENTRANT,
+    af_open
+};
Index: libaf/af.c
===================================================================
--- libaf/af.c	(revision 23396)
+++ libaf/af.c	(working copy)
@@ -31,6 +31,7 @@
 extern af_info_t af_info_center;
 extern af_info_t af_info_sinesuppress;
 extern af_info_t af_info_karaoke;
+extern af_info_t af_info_rlceq;
 
 static af_info_t* filter_list[]={ 
    &af_info_dummy,
@@ -61,6 +62,7 @@
    &af_info_center,
    &af_info_sinesuppress,
    &af_info_karaoke,
+   &af_info_rlceq,
    NULL 
 };
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 185 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/attachments/20070528/c237c793/attachment.pgp>


More information about the MPlayer-dev-eng mailing list