gst_plugins_base/gst/audioresample/resample_functable.c
branchRCL_3
changeset 30 7e817e7e631c
parent 0 0e761a78d257
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
       
     1 /* Resampling library
       
     2  * Copyright (C) <2001> David A. Schleef <ds@schleef.org>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 #ifdef HAVE_CONFIG_H
       
    21 #ifndef __SYMBIAN32__
       
    22 #include <config.h>
       
    23 #else
       
    24 #include "config.h"
       
    25 #endif
       
    26 #endif
       
    27 
       
    28 
       
    29 #include <string.h>
       
    30 #include <math.h>
       
    31 #include <stdio.h>
       
    32 #include <stdlib.h>
       
    33 #include <limits.h>
       
    34 #ifndef __SYMBIAN32__
       
    35 #include <liboil/liboil.h>
       
    36 #endif
       
    37 
       
    38 #include "resample.h"
       
    39 #include "buffer.h"
       
    40 #include "debug.h"
       
    41 
       
    42 static void
       
    43 func_sinc (double *fx, double *dfx, double x, void *closure)
       
    44 {
       
    45   //double scale = *(double *)closure;
       
    46   double scale = M_PI;
       
    47 
       
    48   if (x == 0) {
       
    49     *fx = 1;
       
    50     *dfx = 0;
       
    51     return;
       
    52   }
       
    53 
       
    54   x *= scale;
       
    55   *fx = sin (x) / x;
       
    56   *dfx = scale * (cos (x) - sin (x) / x) / x;
       
    57 }
       
    58 
       
    59 static void
       
    60 func_hanning (double *fx, double *dfx, double x, void *closure)
       
    61 {
       
    62   double width = *(double *) closure;
       
    63 
       
    64   if (x < width && x > -width) {
       
    65     x /= width;
       
    66     *fx = (1 - x * x) * (1 - x * x);
       
    67     *dfx = -2 * 2 * x / width * (1 - x * x);
       
    68   } else {
       
    69     *fx = 0;
       
    70     *dfx = 0;
       
    71   }
       
    72 }
       
    73 
       
    74 #if 0
       
    75 static double
       
    76 resample_sinc_window (double x, double halfwidth, double scale)
       
    77 {
       
    78   double y;
       
    79 
       
    80   if (x == 0)
       
    81     return 1.0;
       
    82   if (x < -halfwidth || x > halfwidth)
       
    83     return 0.0;
       
    84 
       
    85   y = sin (x * M_PI * scale) / (x * M_PI * scale) * scale;
       
    86 
       
    87   x /= halfwidth;
       
    88   y *= (1 - x * x) * (1 - x * x);
       
    89 
       
    90   return y;
       
    91 }
       
    92 #endif
       
    93 
       
    94 #if 0
       
    95 static void
       
    96 functable_test (Functable * ft, double halfwidth)
       
    97 {
       
    98   int i;
       
    99   double x;
       
   100 
       
   101   for (i = 0; i < 100; i++) {
       
   102     x = i * 0.1;
       
   103     printf ("%d %g %g\n", i, resample_sinc_window (x, halfwidth, 1.0),
       
   104         functable_evaluate (ft, x));
       
   105   }
       
   106   exit (0);
       
   107 
       
   108 }
       
   109 #endif
       
   110 
       
   111 #ifdef __SYMBIAN32__
       
   112 EXPORT_C
       
   113 #endif
       
   114 void
       
   115 resample_scale_functable (ResampleState * r)
       
   116 {
       
   117   if (r->need_reinit) {
       
   118     double hanning_width;
       
   119 
       
   120     RESAMPLE_DEBUG ("sample size %d", r->sample_size);
       
   121 
       
   122     if (r->buffer)
       
   123       free (r->buffer);
       
   124     r->buffer_len = r->sample_size * r->filter_length;
       
   125     r->buffer = malloc (r->buffer_len);
       
   126     memset (r->buffer, 0, r->buffer_len);
       
   127 
       
   128     r->i_inc = r->o_rate / r->i_rate;
       
   129     r->o_inc = r->i_rate / r->o_rate;
       
   130     RESAMPLE_DEBUG ("i_inc %g o_inc %g", r->i_inc, r->o_inc);
       
   131 
       
   132     r->i_start = -r->i_inc * r->filter_length;
       
   133 
       
   134     if (r->ft) {
       
   135       functable_free (r->ft);
       
   136     }
       
   137     r->ft = functable_new ();
       
   138     functable_set_length (r->ft, r->filter_length * 16);
       
   139     functable_set_offset (r->ft, -r->filter_length / 2);
       
   140     functable_set_multiplier (r->ft, 1 / 16.0);
       
   141 
       
   142     hanning_width = r->filter_length / 2;
       
   143     functable_calculate (r->ft, func_sinc, NULL);
       
   144     functable_calculate_multiply (r->ft, func_hanning, &hanning_width);
       
   145 
       
   146     //functable_test(r->ft, 0.5 * r->filter_length);
       
   147 #if 0
       
   148     if (r->i_inc < 1.0) {
       
   149       r->sinc_scale = r->i_inc;
       
   150       if (r->sinc_scale == 0.5) {
       
   151         /* strange things happen at integer multiples */
       
   152         r->sinc_scale = 1.0;
       
   153       }
       
   154     } else {
       
   155       r->sinc_scale = 1.0;
       
   156     }
       
   157 #else
       
   158     r->sinc_scale = 1.0;
       
   159 #endif
       
   160 
       
   161     r->need_reinit = 0;
       
   162   }
       
   163 
       
   164   while (r->o_size > 0) {
       
   165     double midpoint;
       
   166     int i;
       
   167     int j;
       
   168 
       
   169     RESAMPLE_DEBUG ("i_start %g", r->i_start);
       
   170     midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
       
   171     if (midpoint > 0.5 * r->i_inc) {
       
   172       RESAMPLE_ERROR ("inconsistent state");
       
   173     }
       
   174     while (midpoint < -0.5 * r->i_inc) {
       
   175       AudioresampleBuffer *buffer;
       
   176 
       
   177       buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
       
   178       if (buffer == NULL) {
       
   179         RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
       
   180         return;
       
   181       }
       
   182 
       
   183       r->i_start += r->i_inc;
       
   184       RESAMPLE_DEBUG ("pulling (i_start = %g)", r->i_start);
       
   185 
       
   186       midpoint += r->i_inc;
       
   187       memmove (r->buffer, r->buffer + r->sample_size,
       
   188           r->buffer_len - r->sample_size);
       
   189 
       
   190       memcpy (r->buffer + r->buffer_len - r->sample_size, buffer->data,
       
   191           r->sample_size);
       
   192       audioresample_buffer_unref (buffer);
       
   193     }
       
   194 
       
   195     switch (r->format) {
       
   196       case RESAMPLE_FORMAT_S16:
       
   197         for (i = 0; i < r->n_channels; i++) {
       
   198           double acc = 0;
       
   199           double offset;
       
   200           double x;
       
   201 
       
   202           for (j = 0; j < r->filter_length; j++) {
       
   203             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   204             x = *(int16_t *) (r->buffer + i * sizeof (int16_t) +
       
   205                 j * r->sample_size);
       
   206             acc += functable_evaluate (r->ft, offset) * x;
       
   207             //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
       
   208           }
       
   209           if (acc < -32768.0)
       
   210             acc = -32768.0;
       
   211           if (acc > 32767.0)
       
   212             acc = 32767.0;
       
   213 
       
   214           *(int16_t *) (r->o_buf + i * sizeof (int16_t)) = rint (acc);
       
   215         }
       
   216         break;
       
   217       case RESAMPLE_FORMAT_S32:
       
   218         for (i = 0; i < r->n_channels; i++) {
       
   219           double acc = 0;
       
   220           double offset;
       
   221           double x;
       
   222 
       
   223           for (j = 0; j < r->filter_length; j++) {
       
   224             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   225             x = *(int32_t *) (r->buffer + i * sizeof (int32_t) +
       
   226                 j * r->sample_size);
       
   227             acc += functable_evaluate (r->ft, offset) * x;
       
   228             //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
       
   229           }
       
   230           if (acc < -2147483648.0)
       
   231             acc = -2147483648.0;
       
   232           if (acc > 2147483647.0)
       
   233             acc = 2147483647.0;
       
   234 
       
   235           *(int32_t *) (r->o_buf + i * sizeof (int32_t)) = rint (acc);
       
   236         }
       
   237         break;
       
   238       case RESAMPLE_FORMAT_F32:
       
   239         for (i = 0; i < r->n_channels; i++) {
       
   240           double acc = 0;
       
   241           double offset;
       
   242           double x;
       
   243 
       
   244           for (j = 0; j < r->filter_length; j++) {
       
   245             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   246             x = *(float *) (r->buffer + i * sizeof (float) +
       
   247                 j * r->sample_size);
       
   248             acc += functable_evaluate (r->ft, offset) * x;
       
   249             //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
       
   250           }
       
   251 
       
   252           *(float *) (r->o_buf + i * sizeof (float)) = acc;
       
   253         }
       
   254         break;
       
   255       case RESAMPLE_FORMAT_F64:
       
   256         for (i = 0; i < r->n_channels; i++) {
       
   257           double acc = 0;
       
   258           double offset;
       
   259           double x;
       
   260 
       
   261           for (j = 0; j < r->filter_length; j++) {
       
   262             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   263             x = *(double *) (r->buffer + i * sizeof (double) +
       
   264                 j * r->sample_size);
       
   265             acc += functable_evaluate (r->ft, offset) * x;
       
   266             //acc += resample_sinc_window (offset, r->filter_length * 0.5, r->sinc_scale) * x;
       
   267           }
       
   268 
       
   269           *(double *) (r->o_buf + i * sizeof (double)) = acc;
       
   270         }
       
   271         break;
       
   272     }
       
   273 
       
   274     r->i_start -= 1.0;
       
   275     r->o_buf += r->sample_size;
       
   276     r->o_size -= r->sample_size;
       
   277   }
       
   278 
       
   279 }