gst_plugins_base/gst/audioresample/resample_chunk.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_chunk (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 * 1000;
       
    74     r->buffer = malloc (r->buffer_len);
       
    75     memset (r->buffer, 0, r->buffer_len);
       
    76 
       
    77     r->i_inc = r->o_rate / r->i_rate;
       
    78     r->o_inc = r->i_rate / r->o_rate;
       
    79     RESAMPLE_DEBUG ("i_inc %g o_inc %g", r->i_inc, r->o_inc);
       
    80 
       
    81     r->i_start = -r->i_inc * r->filter_length;
       
    82 
       
    83     r->need_reinit = 0;
       
    84 
       
    85 #if 0
       
    86     if (r->i_inc < 1.0) {
       
    87       r->sinc_scale = r->i_inc;
       
    88       if (r->sinc_scale == 0.5) {
       
    89         /* strange things happen at integer multiples */
       
    90         r->sinc_scale = 1.0;
       
    91       }
       
    92     } else {
       
    93       r->sinc_scale = 1.0;
       
    94     }
       
    95 #else
       
    96     r->sinc_scale = 1.0;
       
    97 #endif
       
    98   }
       
    99 
       
   100   while (r->o_size > 0) {
       
   101     double midpoint;
       
   102     int i;
       
   103     int j;
       
   104 
       
   105     RESAMPLE_DEBUG ("i_start %g", r->i_start);
       
   106     midpoint = r->i_start + (r->filter_length - 1) * 0.5 * r->i_inc;
       
   107     if (midpoint > 0.5 * r->i_inc) {
       
   108       RESAMPLE_ERROR ("inconsistent state");
       
   109     }
       
   110     while (midpoint < -0.5 * r->i_inc) {
       
   111       AudioresampleBuffer *buffer;
       
   112 
       
   113       buffer = audioresample_buffer_queue_pull (r->queue, r->sample_size);
       
   114       if (buffer == NULL) {
       
   115         RESAMPLE_ERROR ("buffer_queue_pull returned NULL");
       
   116         return;
       
   117       }
       
   118 
       
   119       r->i_start += r->i_inc;
       
   120       RESAMPLE_DEBUG ("pulling (i_start = %g)", r->i_start);
       
   121 
       
   122       midpoint += r->i_inc;
       
   123       memmove (r->buffer, r->buffer + r->sample_size,
       
   124           r->buffer_len - r->sample_size);
       
   125 
       
   126       memcpy (r->buffer + r->buffer_len - r->sample_size, buffer->data,
       
   127           r->sample_size);
       
   128       audioresample_buffer_unref (buffer);
       
   129     }
       
   130 
       
   131     switch (r->format) {
       
   132       case RESAMPLE_FORMAT_S16:
       
   133         for (i = 0; i < r->n_channels; i++) {
       
   134           double acc = 0;
       
   135           double offset;
       
   136           double x;
       
   137 
       
   138           for (j = 0; j < r->filter_length; j++) {
       
   139             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   140             x = *(int16_t *) (r->buffer + i * sizeof (int16_t) +
       
   141                 j * r->sample_size);
       
   142             acc +=
       
   143                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   144                 r->sinc_scale) * x;
       
   145           }
       
   146           if (acc < -32768.0)
       
   147             acc = -32768.0;
       
   148           if (acc > 32767.0)
       
   149             acc = 32767.0;
       
   150 
       
   151           *(int16_t *) (r->o_buf + i * sizeof (int16_t)) = rint (acc);
       
   152         }
       
   153         break;
       
   154       case RESAMPLE_FORMAT_S32:
       
   155         for (i = 0; i < r->n_channels; i++) {
       
   156           double acc = 0;
       
   157           double offset;
       
   158           double x;
       
   159 
       
   160           for (j = 0; j < r->filter_length; j++) {
       
   161             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   162             x = *(int32_t *) (r->buffer + i * sizeof (int32_t) +
       
   163                 j * r->sample_size);
       
   164             acc +=
       
   165                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   166                 r->sinc_scale) * x;
       
   167           }
       
   168           if (acc < -2147483648.0)
       
   169             acc = -2147483648.0;
       
   170           if (acc > 2147483647.0)
       
   171             acc = 2147483647.0;
       
   172 
       
   173           *(int32_t *) (r->o_buf + i * sizeof (int32_t)) = rint (acc);
       
   174         }
       
   175         break;
       
   176       case RESAMPLE_FORMAT_F32:
       
   177         for (i = 0; i < r->n_channels; i++) {
       
   178           double acc = 0;
       
   179           double offset;
       
   180           double x;
       
   181 
       
   182           for (j = 0; j < r->filter_length; j++) {
       
   183             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   184             x = *(float *) (r->buffer + i * sizeof (float) +
       
   185                 j * r->sample_size);
       
   186             acc +=
       
   187                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   188                 r->sinc_scale) * x;
       
   189           }
       
   190 
       
   191           *(float *) (r->o_buf + i * sizeof (float)) = acc;
       
   192         }
       
   193         break;
       
   194       case RESAMPLE_FORMAT_F64:
       
   195         for (i = 0; i < r->n_channels; i++) {
       
   196           double acc = 0;
       
   197           double offset;
       
   198           double x;
       
   199 
       
   200           for (j = 0; j < r->filter_length; j++) {
       
   201             offset = (r->i_start + j * r->i_inc) * r->o_inc;
       
   202             x = *(double *) (r->buffer + i * sizeof (double) +
       
   203                 j * r->sample_size);
       
   204             acc +=
       
   205                 resample_sinc_window (offset, r->filter_length * 0.5,
       
   206                 r->sinc_scale) * x;
       
   207           }
       
   208 
       
   209           *(double *) (r->o_buf + i * sizeof (double)) = acc;
       
   210         }
       
   211         break;
       
   212     }
       
   213 
       
   214     r->i_start -= 1.0;
       
   215     r->o_buf += r->sample_size;
       
   216     r->o_size -= r->sample_size;
       
   217   }
       
   218 
       
   219 }