[MPlayer-dev-eng] [PATCH] Simple 2:1 Audio Downsampling Plugin
Philip Chong
pchong at ic.EECS.Berkeley.EDU
Thu Dec 20 07:32:01 CET 2001
Hi there:
Currently I've got one of those miserable sound cards which is limited
to a 44.1 kHz maximum rate. Needless to say, this makes a lot of stuff
unplayable (at decent quality, anyways) under MPlayer. Despite the
assurances of sound.html in the docs, I was unable to figure out where
the downsampling was happening in the SDL driver, or how even to turn
this on. So, I wrote an audio plugin to do simple 2:1 downsampling,
and can now play 48 kHz audio (downsampled to 24 kHz, but still
"reasonable" quality).
The audio plugin is turned on with the label "halfrate". There is also
a plugin flag "autohalfrate", which enables autodetection and disables
the plugin if the original sample rate is less than or equal to 44.1
kHz. This means you can simply put "aop=list=halfrate:autohalfrate=1"
in the config file, and be assured that downsampling will only happen
when it is needed.
Hope this patch is of some use. The diff is against CVS sources.
--
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 Sun Dec 16 15:59:28 2001
+++ devel/cfg-mplayer.h Wed Dec 19 21:53:49 2001
@@ -83,6 +83,8 @@
{"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_FLAG, 0, 0, 1},
+ {"noautohalfrate", &ao_plugin_cfg.pl_autohalfrate, CONF_TYPE_FLAG, 0, 1, 0},
{NULL, NULL, 0, 0, 0, 0}
};
diff -urN -X ignore main/libao2/Makefile devel/libao2/Makefile
--- main/libao2/Makefile Thu Dec 13 15:36:36 2001
+++ devel/libao2/Makefile Wed Dec 19 21:03:28 2001
@@ -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 $(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 $(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 Wed Dec 5 02:31:10 2001
+++ devel/libao2/audio_plugin.h Wed Dec 19 21:06:55 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
} ao_plugin_cfg_t;
extern volatile ao_plugin_cfg_t ao_plugin_cfg;
@@ -48,16 +49,18 @@
// This block should not be available in the pl_xxxx files
// due to compilation issues
#ifndef PLUGIN
-#define NPL 3+1 // Number of PLugins ( +1 list ends with NULL )
+#define NPL 4+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;
#define AO_PLUGINS { \
&audio_plugin_delay, \
&audio_plugin_format, \
+ &audio_plugin_halfrate, \
&audio_plugin_surround, \
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 Wed Dec 19 21:17:56 2001
@@ -0,0 +1,118 @@
+/* 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
+} pl_halfrate_t;
+
+static pl_halfrate_t pl_halfrate = {NULL, 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() {
+ switch (ao_plugin_data.format) {
+ case AFMT_U8:
+ case AFMT_S8:
+ case AFMT_S32_LE:
+ case AFMT_S32_BE:
+ printf("[pl_halfrate] Error: 16-bit input required for now\n");
+ return 0;
+ default:
+ break;
+ }
+ printf("[pl_halfrate] 2:1 audio downsampler: ");
+ if (ao_plugin_cfg.pl_autohalfrate && ao_plugin_data.rate <= 44100) {
+ // rate is low enough that we need not enable this filter
+ pl_halfrate.disabled = 1;
+ printf("autodetect disabled\n");
+ }
+ else {
+ ao_plugin_data.rate /= 2;
+ ao_plugin_data.sz_mult *= 2;
+ printf("enabled\n");
+ }
+ 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;
+ char *p1, *p2;
+
+ if (!pl_halfrate.disabled) {
+ p1 = pl_halfrate.data;
+ p2 = ao_plugin_data.data;
+ for (i=ao_plugin_data.len/4; i--; ) {
+ (*p1++) = (*p2++);
+ (*p1++) = (*p2++);
+ p2 += 2;
+ }
+
+ ao_plugin_data.data = pl_halfrate.data;
+ ao_plugin_data.len /= 2;
+ }
+
+ return 1;
+}
More information about the MPlayer-dev-eng
mailing list