swr: resampling: add filter type and Kaiser window beta to AVOptions
authorJustin Ruggles <justin.ruggles@gmail.com>
Sat, 26 May 2012 18:50:02 +0000 (14:50 -0400)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 23 Jul 2012 17:23:39 +0000 (19:23 +0200)
libswresample/resample.c
libswresample/swresample.c
libswresample/swresample.h
libswresample/swresample_internal.h

index 4aa53ee..cef2a81 100644 (file)
@@ -29,9 +29,6 @@
 #include "libavutil/avassert.h"
 #include "swresample_internal.h"
 
-#define WINDOW_TYPE 9
-
-
 
 typedef struct ResampleContext {
     const AVClass *av_class;
@@ -47,6 +44,8 @@ typedef struct ResampleContext {
     int phase_shift;
     int phase_mask;
     int linear;
+    enum SwrFilterType filter_type;
+    int kaiser_beta;
     double factor;
     enum AVSampleFormat format;
     int felem_size;
@@ -87,10 +86,12 @@ static double bessel(double x){
  * builds a polyphase filterbank.
  * @param factor resampling factor
  * @param scale wanted sum of coefficients for each filter
- * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16
+ * @param filter_type  filter type
+ * @param kaiser_beta  kaiser window beta
  * @return 0 on success, negative on error
  */
-static int build_filter(ResampleContext *c, void *filter, double factor, int tap_count, int alloc, int phase_count, int scale, int type){
+static int build_filter(ResampleContext *c, void *filter, double factor, int tap_count, int alloc, int phase_count, int scale,
+                        int filter_type, int kaiser_beta){
     int ph, i;
     double x, y, w;
     double *tab = av_malloc(tap_count * sizeof(*tab));
@@ -109,21 +110,23 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
             x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor;
             if (x == 0) y = 1.0;
             else        y = sin(x) / x;
-            switch(type){
-            case 0:{
+            switch(filter_type){
+            case SWR_FILTER_TYPE_CUBIC:{
                 const float d= -0.5; //first order derivative = -0.5
                 x = fabs(((double)(i - center) - (double)ph / phase_count) * factor);
                 if(x<1.0) y= 1 - 3*x*x + 2*x*x*x + d*(            -x*x + x*x*x);
                 else      y=                       d*(-4 + 8*x - 5*x*x + x*x*x);
                 break;}
-            case 1:
+            case SWR_FILTER_TYPE_BLACKMAN_NUTTALL:
                 w = 2.0*x / (factor*tap_count) + M_PI;
                 y *= 0.3635819 - 0.4891775 * cos(w) + 0.1365995 * cos(2*w) - 0.0106411 * cos(3*w);
                 break;
-            default:
+            case SWR_FILTER_TYPE_KAISER:
                 w = 2.0*x / (factor*tap_count*M_PI);
-                y *= bessel(type*sqrt(FFMAX(1-w*w, 0)));
+                y *= bessel(kaiser_beta*sqrt(FFMAX(1-w*w, 0)));
                 break;
+            default:
+                av_assert0(0);
             }
 
             tab[i] = y;
@@ -191,12 +194,14 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
     return 0;
 }
 
-ResampleContext *swri_resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff, enum AVSampleFormat format){
+ResampleContext *swri_resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
+                                    double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, int kaiser_beta){
     double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
     int phase_count= 1<<phase_shift;
 
     if (!c || c->phase_shift != phase_shift || c->linear!=linear || c->factor != factor
-           || c->filter_length != FFMAX((int)ceil(filter_size/factor), 1) || c->format != format) {
+           || c->filter_length != FFMAX((int)ceil(filter_size/factor), 1) || c->format != format
+           || c->filter_type != filter_type || c->kaiser_beta != kaiser_beta) {
         c = av_mallocz(sizeof(*c));
         if (!c)
             return NULL;
@@ -228,9 +233,11 @@ ResampleContext *swri_resample_init(ResampleContext *c, int out_rate, int in_rat
         c->filter_length = FFMAX((int)ceil(filter_size/factor), 1);
         c->filter_alloc  = FFALIGN(c->filter_length, 8);
         c->filter_bank   = av_mallocz(c->filter_alloc*(phase_count+1)*c->felem_size);
+        c->filter_type   = filter_type;
+        c->kaiser_beta   = kaiser_beta;
         if (!c->filter_bank)
             goto error;
-        if (build_filter(c, (void*)c->filter_bank, factor, c->filter_length, c->filter_alloc, phase_count, 1<<c->filter_shift, WINDOW_TYPE))
+        if (build_filter(c, (void*)c->filter_bank, factor, c->filter_length, c->filter_alloc, phase_count, 1<<c->filter_shift, filter_type, kaiser_beta))
             goto error;
         memcpy(c->filter_bank + (c->filter_alloc*phase_count+1)*c->felem_size, c->filter_bank, (c->filter_alloc-1)*c->felem_size);
         memcpy(c->filter_bank + (c->filter_alloc*phase_count  )*c->felem_size, c->filter_bank + (c->filter_alloc - 1)*c->felem_size, c->felem_size);
index 0c869f9..89fe0f7 100644 (file)
@@ -88,6 +88,11 @@ static const AVOption options[]={
                                               , OFFSET(soft_compensation_duration),AV_OPT_TYPE_FLOAT ,{.dbl=1                     }, 0      , INT_MAX   , PARAM },
 {"max_soft_comp"        , "Maximum factor by which data is stretched/squeezed to make it match the timestamps."
                                                    , OFFSET(max_soft_compensation),AV_OPT_TYPE_FLOAT ,{.dbl=0                     }, INT_MIN, INT_MAX   , PARAM },
+{ "filter_type"         , "Filter Type"                 , OFFSET(filter_type)    , AV_OPT_TYPE_INT  , { SWR_FILTER_TYPE_KAISER }, SWR_FILTER_TYPE_CUBIC, SWR_FILTER_TYPE_KAISER, PARAM, "filter_type" },
+    { "cubic"           , "Cubic"                       , 0                      , AV_OPT_TYPE_CONST, { SWR_FILTER_TYPE_CUBIC            }, INT_MIN, INT_MAX, PARAM, "filter_type" },
+    { "blackman_nuttall", "Blackman Nuttall Windowed Sinc", 0                    , AV_OPT_TYPE_CONST, { SWR_FILTER_TYPE_BLACKMAN_NUTTALL }, INT_MIN, INT_MAX, PARAM, "filter_type" },
+    { "kaiser"          , "Kaiser Windowed Sinc"        , 0                      , AV_OPT_TYPE_CONST, { SWR_FILTER_TYPE_KAISER           }, INT_MIN, INT_MAX, PARAM, "filter_type" },
+{ "kaiser_beta"         , "Kaiser Window Beta"          ,OFFSET(kaiser_beta)     , AV_OPT_TYPE_INT  , {.dbl=9                     }, 2      , 16        , PARAM },
 
 {0}
 };
@@ -244,7 +249,7 @@ int swr_init(struct SwrContext *s){
     set_audiodata_fmt(&s->out, s->out_sample_fmt);
 
     if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
-        s->resample = swri_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt);
+        s->resample = swri_resample_init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta);
     }else
         swri_resample_free(&s->resample);
     if(    s->int_sample_fmt != AV_SAMPLE_FMT_S16P
index 85a337a..73dcae3 100644 (file)
@@ -53,6 +53,13 @@ enum SwrDitherType {
     SWR_DITHER_NB,              ///< not part of API/ABI
 };
 
+/** Resampling Filter Types */
+enum SwrFilterType {
+    SWR_FILTER_TYPE_CUBIC,              /**< Cubic */
+    SWR_FILTER_TYPE_BLACKMAN_NUTTALL,   /**< Blackman Nuttall Windowed Sinc */
+    SWR_FILTER_TYPE_KAISER,             /**< Kaiser Windowed Sinc */
+};
+
 typedef struct SwrContext SwrContext;
 
 /**
index 52b60ce..e569a44 100644 (file)
@@ -63,6 +63,8 @@ struct SwrContext {
     int phase_shift;                                /**< log2 of the number of entries in the resampling polyphase filterbank */
     int linear_interp;                              /**< if 1 then the resampling FIR filter will be linearly interpolated */
     double cutoff;                                  /**< resampling cutoff frequency. 1.0 corresponds to half the output sample rate */
+    enum SwrFilterType filter_type;                 /**< resampling filter type */
+    int kaiser_beta;                                /**< beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */
 
     float min_compensation;                         ///< minimum below which no compensation will happen
     float min_hard_compensation;                    ///< minimum below which no silence inject / sample drop will happen
@@ -109,7 +111,7 @@ struct SwrContext {
     /* TODO: callbacks for ASM optimizations */
 };
 
-struct ResampleContext *swri_resample_init(struct ResampleContext *, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff, enum AVSampleFormat);
+struct ResampleContext *swri_resample_init(struct ResampleContext *, int out_rate, int in_rate, int filter_size, int phase_shift, int linear, double cutoff, enum AVSampleFormat, enum SwrFilterType, int kaiser_beta);
 void swri_resample_free(struct ResampleContext **c);
 int swri_multiple_resample(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed);
 void swri_resample_compensate(struct ResampleContext *c, int sample_delta, int compensation_distance);