[MPlayer-dev-eng] [PATCH 5/7] af_scale*: af_scalerate

Robert Juliano juliano.1 at osu.edu
Mon Jun 11 06:53:14 CEST 2007


af_scalerate

This is the old behavior implemented as a filter.  Enable
with -af scalerate.

This patch adds stream to af_instance_t and adds af_create
to af.h to allow one filter to swallow another.  This is
needed by the next patch as well.

I found that the build system didn't catch making af_create
non-static.  If you have problems, run:
# make -C libaf clean
# make

That's it for tonight.  Robert.

Files:
  libaf/Makefile
  libaf/af.c
  libaf/af.h
  libaf/af_scalerate.c
  libaf/control.h

Index: mplayer-HEAD/libaf/Makefile
===================================================================
--- mplayer-HEAD.orig/libaf/Makefile	2007-06-10 16:35:02.000000000 -0400
+++ mplayer-HEAD/libaf/Makefile	2007-06-10 17:05:32.000000000 -0400
@@ -16,6 +16,7 @@
               af_karaoke.c \
               af_pan.c \
               af_resample.c \
+              af_scalerate.c \
               af_scaletempo.c \
               af_sinesuppress.c \
               af_sub.c \
Index: mplayer-HEAD/libaf/af.c
===================================================================
--- mplayer-HEAD.orig/libaf/af.c	2007-06-10 16:52:58.000000000 -0400
+++ mplayer-HEAD/libaf/af.c	2007-06-10 17:04:45.000000000 -0400
@@ -33,6 +33,7 @@
 extern af_info_t af_info_sinesuppress;
 extern af_info_t af_info_karaoke;
 extern af_info_t af_info_scaletempo;
+extern af_info_t af_info_scalerate;
 
 static af_info_t* filter_list[]={ 
    &af_info_dummy,
@@ -64,6 +65,7 @@
    &af_info_sinesuppress,
    &af_info_karaoke,
    &af_info_scaletempo,
+   &af_info_scalerate,
    NULL 
 };
 
@@ -103,7 +105,7 @@
 
 /*/ Function for creating a new filter of type name. The name may
   contain the commandline parameters for the filter */
-static af_instance_t* af_create(af_stream_t* s, char* name)
+af_instance_t* af_create(af_stream_t* s, char* name)
 {
   char* cmdline = name;
 
@@ -134,6 +136,8 @@
   
   af_msg(AF_MSG_VERBOSE,"[libaf] Adding filter %s \n",name);
   
+  new->stream = s;
+
   // Initialize the new filter
   if(AF_OK == new->info->open(new) && 
      AF_ERROR < new->control(new,AF_CONTROL_POST_CREATE,&s->cfg)){
Index: mplayer-HEAD/libaf/af.h
===================================================================
--- mplayer-HEAD.orig/libaf/af.h	2007-06-10 16:30:35.000000000 -0400
+++ mplayer-HEAD/libaf/af.h	2007-06-10 16:55:06.000000000 -0400
@@ -64,6 +64,7 @@
   af_data_t* data; // configuration for outgoing data stream
   struct af_instance_s* next;
   struct af_instance_s* prev;  
+  struct af_stream_s* stream; // allow filters to create, add, etc. other filters
   double delay; // Delay caused by the filter [ms]
   frac_t mul; /* length multiplier: how much does this instance change
 		 the length of the buffer. */
@@ -173,6 +174,16 @@
 void af_remove(af_stream_t* s, af_instance_t* af);
 
 /**
+ * \brief create instance of filter
+ * \param name name of filter to create with command line paramters
+ * \return pointer to the new filter, NULL if failed
+ *
+ * Does not add filter to filter chain.  Useful for swallowing other
+ * filters.  Use af_add to add filter to filter chain.
+ */
+af_instance_t* af_create(af_stream_t* s, char* name);
+
+/**
  * \brief find filter in chain by name
  * \param name name of the filter to find
  * \return first filter with right name or NULL if not found
Index: mplayer-HEAD/libaf/af_scalerate.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ mplayer-HEAD/libaf/af_scalerate.c	2007-06-10 16:55:06.000000000 -0400
@@ -0,0 +1,135 @@
+/*
+ *  (cc) GPL 2007 MPlayer / Robert Juliano
+ *
+ *  License: GPL http://creativecommons.org/licenses/GPL/2.0/
+ *
+ *  scale rate (both time and tempo) (i.e. chipmunk effect)
+ *
+ *  basic technique:
+ *    pretend input rate is scaled rate and resample to input rate
+ *
+ *  Changelog
+ *  2007-06-10  Initial release
+ *
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "af.h"
+
+#ifdef USE_LIBAVCODEC
+  #define RESAMPLER "lavcresample"
+#else
+  #define RESAMPLER "resample"
+#endif
+
+// Data for specific instances of this filter
+typedef struct af_scalerate_s
+{
+  af_instance_t* resampler;
+  float  speed;
+  int    base_rate;
+} af_scalerate_t;
+
+// Initialization and runtime control
+static int control(struct af_instance_s* af, int cmd, void* arg)
+{
+  af_scalerate_t* s   = (af_scalerate_t*)af->setup;
+  af_instance_t* resampler  = s->resampler;
+  switch(cmd){
+  case AF_CONTROL_REINIT:{
+    af_data_t* c = (af_data_t*)arg;
+    int rv;
+
+    s->base_rate = c->rate;
+    c->rate = s->base_rate * s->speed;
+    af_msg(AF_MSG_DEBUG0,"[scalerate] Was reinitialized: %.3f speed %i Hz (%i base)\n", s->speed, c->rate, s->base_rate);
+
+    resampler->control(resampler, AF_CONTROL_RESAMPLE_RATE, &(s->base_rate));
+    rv = resampler->control(resampler, AF_CONTROL_REINIT, c);
+    if (rv == AF_DETACH) {
+      memcpy(af->data, c, sizeof(af_data_t));
+      af->mul.n = af->mul.d = 1;
+      af->delay = 0;
+      return AF_OK;
+    }
+    if (rv == AF_ERROR) return rv;
+
+    memcpy(af->data, resampler->data, sizeof(af_data_t));
+    af->data->rate = c->rate = s->base_rate;
+    af->mul.n = resampler->mul.n;
+    af->mul.d = resampler->mul.d;
+    af->delay = resampler->delay;
+
+    return af_test_output(af,(af_data_t*)arg);
+  }
+  case AF_CONTROL_SCALERATE_AMOUNT | AF_CONTROL_SET:
+  case AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET:{
+    s->speed = *(float*)arg;
+    return AF_OK;
+  }
+  case AF_CONTROL_SCALERATE_AMOUNT | AF_CONTROL_GET:{
+    *(float*)arg = s->speed;
+    return AF_OK;
+  }
+  }
+  return AF_UNKNOWN;
+}
+
+// Deallocate memory
+static void uninit(struct af_instance_s* af)
+{
+  af_scalerate_t* s   = (af_scalerate_t*)af->setup;
+  if(af->data)
+    free(af->data);
+  if(s->resampler) {
+    s->resampler->uninit(s->resampler);
+    free(s->resampler);
+  }
+  if(af->setup)
+    free(af->setup);
+}
+
+// Filter data through filter
+static af_data_t* play(struct af_instance_s* af, af_data_t* data)
+{
+  af_scalerate_t* s   = (af_scalerate_t*)af->setup;
+  if (s->speed == 1.0) return data;
+  return s->resampler->play(s->resampler, data);
+}
+
+// Allocate memory and set function pointers
+static int af_open(af_instance_t* af){
+  af_scalerate_t* s;
+
+  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=malloc(sizeof(af_scalerate_t));
+  if(af->data == NULL || af->setup == NULL)
+    return AF_ERROR;
+
+  s = (af_scalerate_t*)af->setup;
+  s->speed = 1.0;
+  s->base_rate = 0;
+  s->resampler = af_create(af->stream, RESAMPLER);
+  if (!s->resampler)
+    return AF_ERROR;
+
+  return AF_OK;
+}
+
+// Description of this filter
+af_info_t af_info_scalerate = {
+  "Scales audio rate (both pitch and tempo) (i.e. chipmunk effect)",
+  "scalerate",
+  "Robert Juliano",
+  "",
+  AF_FLAGS_NOT_REENTRANT,
+  af_open
+};
Index: mplayer-HEAD/libaf/control.h
===================================================================
--- mplayer-HEAD.orig/libaf/control.h	2007-06-10 16:35:02.000000000 -0400
+++ mplayer-HEAD/libaf/control.h	2007-06-10 17:04:45.000000000 -0400
@@ -232,7 +232,8 @@
 // Generic: respond to change in playback_speed
 #define AF_CONTROL_PLAYBACK_SPEED	0x00002500 | AF_CONTROL_FILTER_SPECIFIC
 
-// ScaleTempo
+// Scale Tempo, Rate
 #define AF_CONTROL_SCALETEMPO_AMOUNT	0x00002600 | AF_CONTROL_FILTER_SPECIFIC
+#define AF_CONTROL_SCALERATE_AMOUNT	0x00002700 | AF_CONTROL_FILTER_SPECIFIC
 
 #endif /*__af_control_h */



More information about the MPlayer-dev-eng mailing list