gst_plugins_base/gst/audioresample/resample_ref.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 
       
    43 static double
       
    44 resample_sinc_window (double x, double halfwidth, double scale)
       
    45 {
       
    46   double y;
       
    47 
       
    48   if (x == 0)
       
    49     return 1.0;
       
    50   if (x < -halfwidth || x > halfwidth)
       
    51     return 0.0;
       
    52 
       
    53   y = sin (x * M_PI * scale) / (x * M_PI * scale) * scale;
       
    54 
       
    55   x /= halfwidth;
       
    56   y *= (1 - x * x) * (1 - x * x);
       
    57 
       
    58   return y;
       
    59 }
       
    60 #ifdef __SYMBIAN32__
       
    61 EXPORT_C
       
    62 #endif
       
    63 
       
    64 
       
    65 void
       
    66 resample_scale_ref (ResampleState * r)
       
    67 {
       
    68   if (r->need_reinit) {
       
    69     RESAMPLE_DEBUG ("sample size %d", r->sample_size);
       
    70 
       
    71     if (r->buffer)
       
    72       free (r->buffer);
       
    73     r->buffer_len = r->sample_size * r->filter_length;
       
    74     r->buffer = malloc (r->buffer_len);
       
    75     memset (r->buffer, 0, r->buffer_len);
       
    76     r->buffer_filled = 0;
       
    77 
       
    78     r->i_inc = r->o_rate / r->i_rate;
       
    79     r->o_inc = r->i_rate / r->o_rate;
       
    80     RESAMPLE_DEBUG ("i_inc %g o_inc %g", r->i_inc, r->o_inc);
       
    81 
       
    82     r->i_start = -r->i_inc * r->filter_length;
       
    83 
       
    84     r->need_reinit = 0;
       
    85 
       
    86 #if 0
       
    87     if (r->i_inc < 1.0) {
       
    88       r->sinc_scale = r->i_inc;
       
    89       if (r->sinc_scale == 0.5) {
       
    90         /* strange things happen at integer multiples */
       
    91         r->sinc_scale = 1.0;
       
    92       }
       
    93     } else {
       
    94       r->sinc_scale = 1.0;
       
    95     }
       
    96 #else
       
    97     r->sinc_scale = 1.0;
       
    98 #endif
       
    99   }
       
   100 
       
   101   RESAMPLE_DEBUG ("asked to resample %d bytes", r->o_size);
       
   102   RESAMPLE_DEBUG ("%d bytes in queue",
       
   103       audioresample_buffer_queue_get_depth (r->queue));
       
   104 
       
   105   while (r->o_size >= r->sample_size) {
       
   106     double midpoint;
       
   107     int i;
       
   108     int j;
       
   109 
       
   110     midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
       
   111     RESAMPLE_DEBUG
       
   112         ("still need to output %d bytes, %d input left, i_start %g, midpoint %f",
       
   113         r->o_size, audioresample_buffer_queue_get_depth (r->queue), r->i_start,
       
   114         midpoint);
       
   115     if (midpoint > 0.5 * r->i_inc) {
       
   116       RESAMPLE_ERROR ("inconsistent state");
       
   117     }
       
   118     while (midpoint < -0.5 * r->i_inc) {
       
   119       AudioresampleBuffer *buffer;
       
   120 
       
   121       RESAMPLE_DEBUG ("midpoint %f < %f, r->i_inc %f", midpoint,
       
   122           -0.5 * r->i_inc, r->i_inc);
       
   123       buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
       
   124       if (buffer == NULL) {
       
   125         /* FIXME: for the first buffer, this isn't necessarily an error,
       
   126          * since because of the filter length we'll output less buffers.
       
   127          * deal with that so we don't print to console */
       
   128         RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
       
   129         return;
       
   130       }
       
   131 
       
   132       r->i_start += r->i_inc;
       
   133       RESAMPLE_DEBUG ("pulling (i_start = %g)", r->i_start);
       
   134 
       
   135       midpoint += r->i_inc;
       
   136       memmove (r->buffer, r->buffer + r->sample_size,
       
   137           r->buffer_len - r->sample_size);
       
   138 
       
   139       memcpy (r->buffer + r->buffer_len - r->sample_size, buffer->data,
       
   140           r->sample_size);
       
   141       r->buffer_filled = MIN (r->buffer_filled + r->sample_size, r->buffer_len);
       
   142 
       
   143       audioresample_buffer_unref (buffer);
       
   144     }
       
   145 
       
   146     switch (r->format) {
       
   147       case RESAMPLE_FORMAT_S16:
       
   148         for (i = 0; i < r->n_channels; i++) {
       
   149           double acc = 0;
       
   150           double offset;
       
   151           double x;
       
   152 
       
   153           for (j = 0; j < r->filter_length; j++) {
       
   154             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   155             x = *(int16_t *) (r->buffer + i * sizeof (int16_t) +
       
   156                 j * r->sample_size);
       
   157             acc +=
       
   158                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   159                 r->sinc_scale) * x;
       
   160           }
       
   161           if (acc < -32768.0)
       
   162             acc = -32768.0;
       
   163           if (acc > 32767.0)
       
   164             acc = 32767.0;
       
   165 
       
   166           *(int16_t *) (r->o_buf + i * sizeof (int16_t)) = rint (acc);
       
   167         }
       
   168         break;
       
   169       case RESAMPLE_FORMAT_S32:
       
   170         for (i = 0; i < r->n_channels; i++) {
       
   171           double acc = 0;
       
   172           double offset;
       
   173           double x;
       
   174 
       
   175           for (j = 0; j < r->filter_length; j++) {
       
   176             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   177             x = *(int32_t *) (r->buffer + i * sizeof (int32_t) +
       
   178                 j * r->sample_size);
       
   179             acc +=
       
   180                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   181                 r->sinc_scale) * x;
       
   182           }
       
   183           if (acc < -2147483648.0)
       
   184             acc = -2147483648.0;
       
   185           if (acc > 2147483647.0)
       
   186             acc = 2147483647.0;
       
   187 
       
   188           *(int32_t *) (r->o_buf + i * sizeof (int32_t)) = rint (acc);
       
   189         }
       
   190         break;
       
   191       case RESAMPLE_FORMAT_F32:
       
   192         for (i = 0; i < r->n_channels; i++) {
       
   193           double acc = 0;
       
   194           double offset;
       
   195           double x;
       
   196 
       
   197           for (j = 0; j < r->filter_length; j++) {
       
   198             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   199             x = *(float *) (r->buffer + i * sizeof (float) +
       
   200                 j * r->sample_size);
       
   201             acc +=
       
   202                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   203                 r->sinc_scale) * x;
       
   204           }
       
   205 
       
   206           *(float *) (r->o_buf + i * sizeof (float)) = acc;
       
   207         }
       
   208         break;
       
   209       case RESAMPLE_FORMAT_F64:
       
   210         for (i = 0; i < r->n_channels; i++) {
       
   211           double acc = 0;
       
   212           double offset;
       
   213           double x;
       
   214 
       
   215           for (j = 0; j < r->filter_length; j++) {
       
   216             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   217             x = *(double *) (r->buffer + i * sizeof (double) +
       
   218                 j * r->sample_size);
       
   219             acc +=
       
   220                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   221                 r->sinc_scale) * x;
       
   222           }
       
   223 
       
   224           *(double *) (r->o_buf + i * sizeof (double)) = acc;
       
   225         }
       
   226         break;
       
   227     }
       
   228 
       
   229     r->i_start -= 1.0;
       
   230     r->o_buf += r->sample_size;
       
   231     r->o_size -= r->sample_size;
       
   232   }
       
   233 }