mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-04 16:39:39 +00:00
c4763dbb33
Original commit message from CVS: port audioresample to basetransform
254 lines
4.7 KiB
C
254 lines
4.7 KiB
C
/* Resampling library
|
|
* Copyright (C) <2001> David A. Schleef <ds@schleef.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "functable.h"
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
void
|
|
functable_func_sinc (double *fx, double *dfx, double x, void *closure)
|
|
{
|
|
if (x == 0) {
|
|
*fx = 1;
|
|
*dfx = 0;
|
|
return;
|
|
}
|
|
|
|
*fx = sin (x) / x;
|
|
*dfx = (cos (x) - sin (x) / x) / x;
|
|
}
|
|
|
|
void
|
|
functable_func_boxcar (double *fx, double *dfx, double x, void *closure)
|
|
{
|
|
double width = *(double *) closure;
|
|
|
|
if (x < width && x > -width) {
|
|
*fx = 1;
|
|
} else {
|
|
*fx = 0;
|
|
}
|
|
*dfx = 0;
|
|
}
|
|
|
|
void
|
|
functable_func_hanning (double *fx, double *dfx, double x, void *closure)
|
|
{
|
|
double width = *(double *) closure;
|
|
|
|
if (x < width && x > -width) {
|
|
x /= width;
|
|
*fx = (1 - x * x) * (1 - x * x);
|
|
*dfx = -2 * 2 * x / width * (1 - x * x);
|
|
} else {
|
|
*fx = 0;
|
|
*dfx = 0;
|
|
}
|
|
}
|
|
|
|
|
|
Functable *
|
|
functable_new (void)
|
|
{
|
|
Functable *ft;
|
|
|
|
ft = malloc (sizeof (Functable));
|
|
memset (ft, 0, sizeof (Functable));
|
|
|
|
return ft;
|
|
}
|
|
|
|
void
|
|
functable_free (Functable * ft)
|
|
{
|
|
free (ft);
|
|
}
|
|
|
|
void
|
|
functable_set_length (Functable * t, int length)
|
|
{
|
|
t->length = length;
|
|
}
|
|
|
|
void
|
|
functable_set_offset (Functable * t, double offset)
|
|
{
|
|
t->offset = offset;
|
|
}
|
|
|
|
void
|
|
functable_set_multiplier (Functable * t, double multiplier)
|
|
{
|
|
t->multiplier = multiplier;
|
|
}
|
|
|
|
void
|
|
functable_calculate (Functable * t, FunctableFunc func, void *closure)
|
|
{
|
|
int i;
|
|
double x;
|
|
|
|
if (t->fx)
|
|
free (t->fx);
|
|
if (t->dfx)
|
|
free (t->dfx);
|
|
|
|
t->fx = malloc (sizeof (double) * (t->length + 1));
|
|
t->dfx = malloc (sizeof (double) * (t->length + 1));
|
|
|
|
t->inv_multiplier = 1.0 / t->multiplier;
|
|
|
|
for (i = 0; i < t->length + 1; i++) {
|
|
x = t->offset + t->multiplier * i;
|
|
|
|
func (&t->fx[i], &t->dfx[i], x, closure);
|
|
}
|
|
}
|
|
|
|
void
|
|
functable_calculate_multiply (Functable * t, FunctableFunc func, void *closure)
|
|
{
|
|
int i;
|
|
double x;
|
|
|
|
for (i = 0; i < t->length + 1; i++) {
|
|
double afx, adfx, bfx, bdfx;
|
|
|
|
afx = t->fx[i];
|
|
adfx = t->dfx[i];
|
|
x = t->offset + t->multiplier * i;
|
|
func (&bfx, &bdfx, x, closure);
|
|
t->fx[i] = afx * bfx;
|
|
t->dfx[i] = afx * bdfx + adfx * bfx;
|
|
}
|
|
|
|
}
|
|
|
|
double
|
|
functable_evaluate (Functable * t, double x)
|
|
{
|
|
int i;
|
|
double f0, f1, w0, w1;
|
|
double x2, x3;
|
|
double w;
|
|
|
|
if (x < t->offset || x > (t->offset + t->length * t->multiplier)) {
|
|
RESAMPLE_DEBUG ("x out of range %g", x);
|
|
}
|
|
|
|
x -= t->offset;
|
|
x *= t->inv_multiplier;
|
|
i = floor (x);
|
|
x -= i;
|
|
|
|
x2 = x * x;
|
|
x3 = x2 * x;
|
|
|
|
f1 = 3 * x2 - 2 * x3;
|
|
f0 = 1 - f1;
|
|
w0 = (x - 2 * x2 + x3) * t->multiplier;
|
|
w1 = (-x2 + x3) * t->multiplier;
|
|
|
|
w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->dfx[i] * w0 + t->dfx[i + 1] * w1;
|
|
|
|
/*w = t->fx[i] * (1-x) + t->fx[i+1] * x; */
|
|
|
|
return w;
|
|
}
|
|
|
|
|
|
double
|
|
functable_fir (Functable * t, double x, int n, double *data, int len)
|
|
{
|
|
int i, j;
|
|
double f0, f1, w0, w1;
|
|
double x2, x3;
|
|
double w;
|
|
double sum;
|
|
|
|
x -= t->offset;
|
|
x /= t->multiplier;
|
|
i = floor (x);
|
|
x -= i;
|
|
|
|
x2 = x * x;
|
|
x3 = x2 * x;
|
|
|
|
f1 = 3 * x2 - 2 * x3;
|
|
f0 = 1 - f1;
|
|
w0 = (x - 2 * x2 + x3) * t->multiplier;
|
|
w1 = (-x2 + x3) * t->multiplier;
|
|
|
|
sum = 0;
|
|
for (j = 0; j < len; j++) {
|
|
w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->dfx[i] * w0 + t->dfx[i + 1] * w1;
|
|
sum += data[j * 2] * w;
|
|
i += n;
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
void
|
|
functable_fir2 (Functable * t, double *r0, double *r1, double x,
|
|
int n, double *data, int len)
|
|
{
|
|
int i, j;
|
|
double f0, f1, w0, w1;
|
|
double x2, x3;
|
|
double w;
|
|
double sum0, sum1;
|
|
double floor_x;
|
|
|
|
x -= t->offset;
|
|
x *= t->inv_multiplier;
|
|
floor_x = floor (x);
|
|
i = floor_x;
|
|
x -= floor_x;
|
|
|
|
x2 = x * x;
|
|
x3 = x2 * x;
|
|
|
|
f1 = 3 * x2 - 2 * x3;
|
|
f0 = 1 - f1;
|
|
w0 = (x - 2 * x2 + x3) * t->multiplier;
|
|
w1 = (-x2 + x3) * t->multiplier;
|
|
|
|
sum0 = 0;
|
|
sum1 = 0;
|
|
for (j = 0; j < len; j++) {
|
|
w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->dfx[i] * w0 + t->dfx[i + 1] * w1;
|
|
sum0 += data[j * 2] * w;
|
|
sum1 += data[j * 2 + 1] * w;
|
|
i += n;
|
|
}
|
|
|
|
*r0 = sum0;
|
|
*r1 = sum1;
|
|
}
|