[MPlayer-dev-eng] Re: [PATCH] Simple 2:1 Audio Downsampling Plugin

Philip Chong pchong at ic.EECS.Berkeley.EDU
Thu Dec 20 23:56:18 CET 2001


Hi Steve:

Thanks for the feedback regarding the patch.  I fixed it up to work for
an arbitrary number of channels, as well as all bit sizes.  I'd also
modified the "autohalfrate" flag to be an int, so that one can now
specify what the maximum acceptable frequency should be;
"aop=list=halfrate:autohalfrate=44100" should be effective for most
evil sound cards.

I didn't know there was someone else working on a general resampler;
I'd only just started on this mailing list.  I notice the resampling
code has just been checked into CVS;  I'll take a look at it right
away.  Two things I'd like are to be able to not use filtering, to
minimize CPU usage (if I could afford a faster CPU, I'd get a new
soundcard too :) ), and to have the resampling automatically disabled
if unneeded;  I'll see if this can be added to what's currently there.
I hope I'm not stepping on anyone's toes with this.

-- 
Philip Chong
pchong at eecs.berkeley.edu
-------------- next part --------------
diff -urN -X ignore main/cfg-mplayer.h devel/cfg-mplayer.h
--- main/cfg-mplayer.h	Thu Dec 20 14:15:15 2001
+++ devel/cfg-mplayer.h	Thu Dec 20 14:16:30 2001
@@ -83,6 +83,7 @@
 	{"list", &ao_plugin_cfg.plugin_list, CONF_TYPE_STRING, 0, 0, 0},
 	{"delay", &ao_plugin_cfg.pl_delay_len, CONF_TYPE_INT, CONF_MIN, 0, 0},
 	{"format", &ao_plugin_cfg.pl_format_type, CONF_TYPE_INT, CONF_MIN, 0, 0},
+	{"autohalfrate", &ao_plugin_cfg.pl_autohalfrate, CONF_TYPE_INT, CONF_RANGE, 0, 48000},
 	{"fout", &ao_plugin_cfg.pl_resample_fout, CONF_TYPE_INT, CONF_MIN, 0, 0},
 	{NULL, NULL, 0, 0, 0, 0}
 };
diff -urN -X ignore main/libao2/Makefile devel/libao2/Makefile
--- main/libao2/Makefile	Thu Dec 20 14:15:15 2001
+++ devel/libao2/Makefile	Thu Dec 20 14:21:28 2001
@@ -4,8 +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 $(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_halfrate.c pl_surround.c remez.c pl_resample.c $(OPTIONAL_SRCS)
 OBJS=$(SRCS:.c=.o)
 
 CFLAGS  = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC)
diff -urN -X ignore main/libao2/audio_plugin.h devel/libao2/audio_plugin.h
--- main/libao2/audio_plugin.h	Thu Dec 20 14:15:15 2001
+++ devel/libao2/audio_plugin.h	Thu Dec 20 14:23:34 2001
@@ -34,6 +34,7 @@
   char* plugin_list; 	// List of used plugins read from cfg
   int pl_format_type;	// Output format
   int pl_delay_len;	// Number of samples to delay sound output
+  int pl_autohalfrate;  // Turns on rate autodetection
   int pl_resample_fout;	// Output frequency from resampling
 } ao_plugin_cfg_t;
 
@@ -50,10 +51,11 @@
 // This block should not be available in the pl_xxxx files
 // due to compilation issues
 #ifndef PLUGIN
-#define NPL 4+1 // Number of PLugins ( +1 list ends with NULL )
+#define NPL 5+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; 
+extern ao_plugin_functions_t audio_plugin_halfrate; 
 extern ao_plugin_functions_t audio_plugin_surround;
 extern ao_plugin_functions_t audio_plugin_resample;
 
@@ -61,6 +63,7 @@
 #define AO_PLUGINS { \
    &audio_plugin_delay, \
    &audio_plugin_format, \
+   &audio_plugin_halfrate, \
    &audio_plugin_surround, \
    &audio_plugin_resample, \
    NULL \
diff -urN -X ignore main/libao2/pl_halfrate.c devel/libao2/pl_halfrate.c
--- main/libao2/pl_halfrate.c	Wed Dec 31 16:00:00 1969
+++ devel/libao2/pl_halfrate.c	Thu Dec 20 12:14:14 2001
@@ -0,0 +1,126 @@
+/* Halfrate plugin:  Simple 2:1 downsampling
+   Useful for bringing 48kHz audio down to 24kHz for playing on soundcards
+   limited to 44.1kHz audio
+   Philip Chong <pchong at eecs.berkeley.edu>
+*/
+
+#define PLUGIN
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "audio_out.h"
+#include "audio_plugin.h"
+#include "audio_plugin_internal.h"
+#include "afmt.h"
+
+static ao_info_t info =
+{
+        "Halfrate audio plugin",
+        "halfrate",
+        "Philip Chong <pchong at eecs.berkeley.edu>",
+        ""
+};
+
+LIBAO_PLUGIN_EXTERN(halfrate)
+
+// local data
+typedef struct pl_halfrate_s
+{
+  void* data;       // local audio data block
+  int len;          // local buffer length
+  int disabled;     // indicates filter is disabled because of autodetect
+  int bytes;        // bytes per sample
+} pl_halfrate_t;
+
+static pl_halfrate_t pl_halfrate = {NULL, 0, 0, 0};
+
+// to set/get/query special features/parameters
+static int control(int cmd,int arg) {
+  switch (cmd) {
+  case AOCONTROL_PLUGIN_SET_LEN:
+    if (!pl_halfrate.disabled) {
+      pl_halfrate.len = ao_plugin_data.len;
+      ao_plugin_data.len *= 2;
+      if (pl_halfrate.data) 
+	free (pl_halfrate.data);
+      pl_halfrate.data = (void*) malloc(ao_plugin_data.len);
+      if (!pl_halfrate.data)
+	return CONTROL_ERROR;
+    }
+    return CONTROL_OK;
+  }
+  return -1;
+}
+
+// open & setup audio device
+// return: 1=success 0=fail
+static int init() {
+  printf("[pl_halfrate] 2:1 audio downsampler: ");
+  if (ao_plugin_cfg.pl_autohalfrate &&
+      ao_plugin_data.rate <= ao_plugin_cfg.pl_autohalfrate) {
+    // rate is low enough that we need not enable this filter
+    pl_halfrate.disabled = 1;
+    printf("disabled by autodetect\n");
+  }
+  else {
+    ao_plugin_data.rate /= 2;
+    ao_plugin_data.sz_mult *= 2;
+    printf("enabled\n");
+    // figure out how many bytes per sample we need
+    switch (ao_plugin_data.format) {
+      case AFMT_U8:
+      case AFMT_S8:
+	pl_halfrate.bytes = 1;
+	break;
+      case AFMT_S32_LE:
+      case AFMT_S32_BE:
+	pl_halfrate.bytes = 4;
+	break;
+      default:
+	pl_halfrate.bytes = 2;
+	break;
+    }
+    pl_halfrate.bytes *= ao_plugin_data.channels;
+  }
+  return 1;
+}
+
+// close plugin
+static void uninit() {
+  if (pl_halfrate.data) {
+    free (pl_halfrate.data);
+  }
+  pl_halfrate.data = NULL;
+  pl_halfrate.len = 0;
+}
+
+// empty buffers
+static void reset() {
+  if (pl_halfrate.data) {
+    memset (pl_halfrate.data, 0, pl_halfrate.len);
+  }
+}
+
+// processes 'ao_plugin_data.len' bytes of 'data'
+// called for every block of data
+static int play() {
+  int i, j;
+  char *p1, *p2;
+
+  if (!pl_halfrate.disabled) {
+    p1 = pl_halfrate.data;
+    p2 = ao_plugin_data.data;
+    for (i=ao_plugin_data.len/(2*pl_halfrate.bytes); i--; ) {
+      for (j=pl_halfrate.bytes; j--; ) {
+	(*p1++) = (*p2++);
+      }
+      p2 += pl_halfrate.bytes;
+    }
+
+    ao_plugin_data.data = pl_halfrate.data;
+    ao_plugin_data.len /= 2;
+  }
+
+  return 1;
+}


More information about the MPlayer-dev-eng mailing list