From 8be52e0b7350dc27e8620d2e9e409ea54d409887 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Wed, 30 Nov 2005 01:04:28 +0000 Subject: [PATCH] gst/audioscale/: remove Original commit message from CVS: * gst/audioscale/.cvsignore: * gst/audioscale/Makefile.am: * gst/audioscale/README: * gst/audioscale/audioscale.vcproj: * gst/audioscale/dtof.c: * gst/audioscale/dtos.c: * gst/audioscale/functable.c: * gst/audioscale/gstaudioscale.c: * gst/audioscale/gstaudioscale.h: * gst/audioscale/private.h: * gst/audioscale/resample.c: * gst/audioscale/resample.h: * gst/audioscale/test.c: remove --- ChangeLog | 17 + gst/audioscale/.gitignore | 7 - gst/audioscale/Makefile.am | 14 - gst/audioscale/README | 62 --- gst/audioscale/audioscale.vcproj | 148 ------- gst/audioscale/dtof.c | 74 ---- gst/audioscale/dtos.c | 217 --------- gst/audioscale/functable.c | 322 -------------- gst/audioscale/gstaudioscale.c | 735 ------------------------------- gst/audioscale/gstaudioscale.h | 81 ---- gst/audioscale/private.h | 118 ----- gst/audioscale/resample.c | 929 --------------------------------------- gst/audioscale/resample.h | 111 ----- gst/audioscale/test.c | 375 ---------------- 14 files changed, 17 insertions(+), 3193 deletions(-) delete mode 100644 gst/audioscale/.gitignore delete mode 100644 gst/audioscale/Makefile.am delete mode 100644 gst/audioscale/README delete mode 100644 gst/audioscale/audioscale.vcproj delete mode 100644 gst/audioscale/dtof.c delete mode 100644 gst/audioscale/dtos.c delete mode 100644 gst/audioscale/functable.c delete mode 100644 gst/audioscale/gstaudioscale.c delete mode 100644 gst/audioscale/gstaudioscale.h delete mode 100644 gst/audioscale/private.h delete mode 100644 gst/audioscale/resample.c delete mode 100644 gst/audioscale/resample.h delete mode 100644 gst/audioscale/test.c diff --git a/ChangeLog b/ChangeLog index da19f29..18e1732 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2005-11-30 Thomas Vander Stichele + + * gst/audioscale/.cvsignore: + * gst/audioscale/Makefile.am: + * gst/audioscale/README: + * gst/audioscale/audioscale.vcproj: + * gst/audioscale/dtof.c: + * gst/audioscale/dtos.c: + * gst/audioscale/functable.c: + * gst/audioscale/gstaudioscale.c: + * gst/audioscale/gstaudioscale.h: + * gst/audioscale/private.h: + * gst/audioscale/resample.c: + * gst/audioscale/resample.h: + * gst/audioscale/test.c: + remove + 2005-11-30 Edward Hervey * gst-libs/gst/netbuffer/Makefile.am: diff --git a/gst/audioscale/.gitignore b/gst/audioscale/.gitignore deleted file mode 100644 index 08f5ed3..0000000 --- a/gst/audioscale/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile -Makefile.in -*.o -*.lo -*.la -.deps -.libs diff --git a/gst/audioscale/Makefile.am b/gst/audioscale/Makefile.am deleted file mode 100644 index 2790ffe..0000000 --- a/gst/audioscale/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -#plugin_LTLIBRARIES = libgstaudioscale.la -noinst_LTLIBRARIES = libgstresample.la - -#libgstaudioscale_la_SOURCES = gstaudioscale.c -#libgstaudioscale_la_CFLAGS = $(GST_CFLAGS) -#libgstaudioscale_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -#libgstaudioscale_la_LIBADD = $(GST_LIBS) - -noinst_HEADERS = gstaudioscale.h private.h - -libgstresample_la_SOURCES = dtos.c dtof.c functable.c resample.c resample.h -libgstresample_la_LIBADD = $(GST_LIBS) -libgstresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstresample_la_CFLAGS = $(GST_CFLAGS) diff --git a/gst/audioscale/README b/gst/audioscale/README deleted file mode 100644 index f7db110..0000000 --- a/gst/audioscale/README +++ /dev/null @@ -1,62 +0,0 @@ - -This is a snapshot of my current work developing an audio -resampling library. While working on this library, I started -writing lots of general purpose functions that should really -be part of a larger library. Rather than have a constantly -changing library, and since the current code is capable, I -decided to freeze this codebase for use with gstreamer, and -move active development of the code elsewhere. - -The algorithm used is based on Shannon's theorem, which says -that you can recreate an input signal from equidistant samples -using a sin(x)/x filter; thus, you can create new samples from -the regenerated input signal. Since sin(x)/x is expensive to -evaluate, an interpolated lookup table is used. Also, a -windowing function (1-x^2)^2 is used, which aids the convergence -of sin(x)/x for lower frequencies at the expense of higher. - -There is one tunable parameter, which is the filter length. -Longer filter lengths are obviously slower, but more accurate. -There's not much reason to use a filter length longer than 64, -since other approximations start to dominate. Filter lengths -as short as 8 are audially acceptable, but should not be -considered for serious work. - -Performance: A PowerPC G4 at 400 Mhz can resample 2 audio -channels at almost 10x speed with a filter length of 64, without -using Altivec extensions. (My goal was 10x speed, which I almost -reached. Maybe later.) - -Limitations: Currently only supports streams in the form of -interleaved signed 16-bit samples. - -The test.c program is a simple regression test. It creates a -test input pattern (1 sec at 48 khz) that is a frequency ramp -from 0 to 24000 hz, and then converts it to 44100 hz using a -filter length of 64. It then compares the result to the same -pattern generated at 44100 hz, and outputs the result to the -file "out". - -A graph of the correct output should have field 2 and field 4 -almost equal (plus/minus 1) up to about sample 40000 (which -corresponds to 20 khz), and then field 2 should be close to 0 -above that. Running the test program will print to stdout -something like the following: - - time 0.112526 - average error 10k=0.4105 22k=639.34 - -The average error is RMS error over the range [0-10khz] and -[0-22khz], and is expressed in sample values, for an input -amplitude of 16000. Note that RMS errors below 1.0 can't -really be compared, but basically this shows that below -10 khz, the resampler is nearly perfect. Most of the error -is concentrated above 20 khz. - -If the average error is significantly larger after modifying -the code, it's probably not good. - - - -dave... - diff --git a/gst/audioscale/audioscale.vcproj b/gst/audioscale/audioscale.vcproj deleted file mode 100644 index 6ee7035..0000000 --- a/gst/audioscale/audioscale.vcproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gst/audioscale/dtof.c b/gst/audioscale/dtof.c deleted file mode 100644 index 8353492..0000000 --- a/gst/audioscale/dtof.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Resampling library - * Copyright (C) <2001> David A. Schleef - * - * 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 -#include -#include -#include - -/*#include */ -#include "private.h" - -void -conv_double_float_ref (double *dest, float *src, int n) -{ - int i; - - for (i = 0; i < n; i++) { - dest[i] = src[i]; - } -} - -void -conv_float_double_ref (float *dest, double *src, int n) -{ - int i; - - for (i = 0; i < n; i++) { - dest[i] = src[i]; - } -} - -void -conv_double_float_dstr (double *dest, float *src, int n, int dstr) -{ - int i; - void *d = dest; - - for (i = 0; i < n; i++) { - (*(double *) d) = *src++; - d += dstr; - } -} - -void -conv_float_double_sstr (float *dest, double *src, int n, int sstr) -{ - int i; - void *s = src; - - for (i = 0; i < n; i++) { - *dest++ = *(double *) s; - s += sstr; - } -} diff --git a/gst/audioscale/dtos.c b/gst/audioscale/dtos.c deleted file mode 100644 index f1e2278..0000000 --- a/gst/audioscale/dtos.c +++ /dev/null @@ -1,217 +0,0 @@ -/* Resampling library - * Copyright (C) <2001> David A. Schleef - * - * 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 -#endif - -#include -#include -#include -#include - -/*#include */ -#include - - - -#define short_to_double_table -/*#define short_to_double_altivec */ -#define short_to_double_unroll - -#ifdef short_to_double_table -static float ints_high[256]; -static float ints_low[256]; - -void -conv_double_short_table (double *dest, short *src, int n) -{ - static int init = 0; - int i; - unsigned int idx; - - if (!init) { - for (i = 0; i < 256; i++) { - ints_high[i] = 256.0 * ((i < 128) ? i : i - 256); - ints_low[i] = i; - } - init = 1; - } - - if (n & 1) { - idx = (unsigned short) *src++; - *dest++ = ints_high[(idx >> 8)] + ints_low[(idx & 0xff)]; - n -= 1; - } - for (i = 0; i < n; i += 2) { - idx = (unsigned short) *src++; - *dest++ = ints_high[(idx >> 8)] + ints_low[(idx & 0xff)]; - idx = (unsigned short) *src++; - *dest++ = ints_high[(idx >> 8)] + ints_low[(idx & 0xff)]; - } -} - -#endif - -#ifdef short_to_double_unroll -void -conv_double_short_unroll (double *dest, short *src, int n) -{ - if (n & 1) { - *dest++ = *src++; - n--; - } - if (n & 2) { - *dest++ = *src++; - *dest++ = *src++; - n -= 2; - } - while (n > 0) { - *dest++ = *src++; - *dest++ = *src++; - *dest++ = *src++; - *dest++ = *src++; - n -= 4; - } -} -#endif - -void -conv_double_short_ref (double *dest, short *src, int n) -{ - int i; - - for (i = 0; i < n; i++) { - dest[i] = src[i]; - } -} - -#ifdef HAVE_CPU_PPC -#if 0 -static union -{ - int i[4]; - float f[4]; -} -av_tmp __attribute__ ((__aligned__ (16))); - -void -conv_double_short_altivec (double *dest, short *src, int n) -{ - int i; - - for (i = 0; i < n; i += 4) { - av_tmp.i[0] = src[0]; - av_tmp.i[1] = src[1]; - av_tmp.i[2] = src[2]; - av_tmp.i[3] = src[3]; - - asm (" lvx 0,0,%0\n" " vcfsx 1,0,0\n" " stvx 1,0,%0\n": :"r" (&av_tmp) - ); - - dest[0] = av_tmp.f[0]; - dest[1] = av_tmp.f[1]; - dest[2] = av_tmp.f[2]; - dest[3] = av_tmp.f[3]; - src += 4; - dest += 4; - } -} -#endif -#endif - - - -/* double to short */ - -void -conv_short_double_ref (short *dest, double *src, int n) -{ - int i; - double x; - - for (i = 0; i < n; i++) { - x = *src++; - if (x < -32768.0) - x = -32768.0; - if (x > 32767.0) - x = 32767.0; - *dest++ = rint (x); - } -} - -/* #ifdef HAVE_CPU_PPC */ -#if 0 -void -conv_short_double_ppcasm (short *dest, double *src, int n) -{ - int tmp[2]; - double min = -32768.0; - double max = 32767.0; - double ftmp0, ftmp1; - - asm __volatile__ ("\taddic. %3,%3,-8\n" - "\taddic. %6,%6,-2\n" - "loop:\n" - "\tlfdu %0,8(%3)\n" - "\tfsub %1,%0,%4\n" - "\tfsel %0,%1,%0,%4\n" - "\tfsub %1,%0,%5\n" - "\tfsel %0,%1,%5,%0\n" - "\tfctiw %1,%0\n" - "\taddic. 5,5,-1\n" - "\tstfd %1,0(%2)\n" - "\tlhz 9,6(%2)\n" - "\tsthu 9,2(%6)\n" "\tbne loop\n":"=&f" (ftmp0), "=&f" (ftmp1) - :"b" (tmp), "r" (src), "f" (min), "f" (max), "r" (dest) - :"r9", "r5"); - -} -#endif - - -void -conv_double_short_dstr (double *dest, short *src, int n, int dstr) -{ - int i; - void *d = dest; - - for (i = 0; i < n; i++) { - (*(double *) d) = *src++; - d += dstr; - } -} - -void -conv_short_double_sstr (short *dest, double *src, int n, int sstr) -{ - int i; - double x; - void *s = src; - - for (i = 0; i < n; i++) { - x = *(double *) s; - if (x < -32768.0) - x = -32768.0; - if (x > 32767.0) - x = 32767.0; - *dest++ = rint (x); - s += sstr; - } -} diff --git a/gst/audioscale/functable.c b/gst/audioscale/functable.c deleted file mode 100644 index 29ce041..0000000 --- a/gst/audioscale/functable.c +++ /dev/null @@ -1,322 +0,0 @@ -/* Resampling library - * Copyright (C) <2001> David A. Schleef - * - * 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 -#include -#include -#include - -#include "private.h" - - - -double -functable_sinc (void *p, double x) -{ - if (x == 0) - return 1; - return sin (x) / x; -} - -double -functable_dsinc (void *p, double x) -{ - if (x == 0) - return 0; - return cos (x) / x - sin (x) / (x * x); -} - -double -functable_window_boxcar (void *p, double x) -{ - if (x < -1 || x > 1) - return 0; - return 1; -} - -double -functable_window_dboxcar (void *p, double x) -{ - return 0; -} - -double -functable_window_std (void *p, double x) -{ - if (x < -1 || x > 1) - return 0; - return (1 - x * x) * (1 - x * x); -} - -double -functable_window_dstd (void *p, double x) -{ - if (x < -1 || x > 1) - return 0; - return -4 * x * (1 - x * x); -} - - - -void -functable_init (functable_t * t) -{ - int i; - double x; - - t->fx = malloc (sizeof (double) * (t->len + 1)); - t->fdx = malloc (sizeof (double) * (t->len + 1)); - - t->invoffset = 1.0 / t->offset; - - for (i = 0; i < t->len + 1; i++) { - x = t->start + t->offset * i; - x *= t->scale; - - t->fx[i] = t->func_x (t->priv, x); - t->fdx[i] = t->scale * t->func_dx (t->priv, x); - } - if (t->func2_x) { - double f1x, f1dx; - double f2x, f2dx; - - for (i = 0; i < t->len + 1; i++) { - x = t->start + t->offset * i; - x *= t->scale2; - - f2x = t->func2_x (t->priv, x); - f2dx = t->scale2 * t->func2_dx (t->priv, x); - - f1x = t->fx[i]; - f1dx = t->fdx[i]; - - t->fx[i] = f1x * f2x; - t->fdx[i] = f1x * f2dx + f1dx * f2x; - } - } -} - -double -functable_eval (functable_t * t, double x) -{ - int i; - double f0, f1, w0, w1; - double x2, x3; - double w; - - if (x < t->start || x > (t->start + (t->len + 1) * t->offset)) { - printf ("x out of range %g\n", x); - } - x -= t->start; - x /= t->offset; - 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->offset; - w1 = (-x2 + x3) * t->offset; - - /*printf("i=%d x=%g f0=%g f1=%g w0=%g w1=%g\n",i,x,f0,f1,w0,w1); */ - - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - - /*w = t->fx[i] * (1-x) + t->fx[i+1] * x; */ - - return w; -} - - -double -functable_fir (functable_t * 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->start; - x /= t->offset; - 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->offset; - w1 = (-x2 + x3) * t->offset; - - sum = 0; - for (j = 0; j < len; j++) { - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - sum += data[j * 2] * w; - i += n; - } - - return sum; -} - -void -functable_fir2 (functable_t * 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->start; - x *= t->invoffset; - 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->offset; - w1 = (-x2 + x3) * t->offset; - - sum0 = 0; - sum1 = 0; - for (j = 0; j < len; j++) { - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - sum0 += data[j * 2] * w; - sum1 += data[j * 2 + 1] * w; - i += n; - -#define unroll2 -#define unroll3 -#define unroll4 -#ifdef unroll2 - j++; - - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - sum0 += data[j * 2] * w; - sum1 += data[j * 2 + 1] * w; - i += n; -#endif -#ifdef unroll3 - j++; - - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - sum0 += data[j * 2] * w; - sum1 += data[j * 2 + 1] * w; - i += n; -#endif -#ifdef unroll4 - j++; - - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - sum0 += data[j * 2] * w; - sum1 += data[j * 2 + 1] * w; - i += n; -#endif - } - - *r0 = sum0; - *r1 = sum1; -} - - - -#ifdef unused -void -functable_fir2_altivec (functable_t * t, float *r0, float *r1, - double x, int n, float *data, int len) -{ - int i, j; - double f0, f1, w0, w1; - double x2, x3; - double w; - double sum0, sum1; - double floor_x; - - x -= t->start; - x *= t->invoffset; - 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->offset; - w1 = (-x2 + x3) * t->offset; - - sum0 = 0; - sum1 = 0; - for (j = 0; j < len; j++) { - /* t->fx, t->fdx needs to be multiplexed by n */ - /* we need 5 consecutive floats, which fit into 2 vecs */ - /* load v0, t->fx[i] */ - /* load v1, t->fx[i+n] */ - /* v2 = v0 (not correct) */ - /* v3 = (v0>>32) || (v1<<3*32) (not correct) */ - /* */ - /* load v4, t->dfx[i] */ - /* load v5, t->dfx[i+n] */ - /* v6 = v4 (not correct) */ - /* v7 = (v4>>32) || (v5<<3*32) (not correct) */ - /* */ - /* v8 = splat(f0) */ - /* v9 = splat(f1) */ - /* v10 = splat(w0) */ - /* v11 = splat(w1) */ - /* */ - /* v12 = v2 * v8 */ - /* v12 += v3 * v9 */ - /* v12 += v6 * v10 */ - /* v12 += v7 * v11 */ - - w = t->fx[i] * f0 + t->fx[i + 1] * f1 + t->fdx[i] * w0 + t->fdx[i + 1] * w1; - - /* v13 = data[j*2] */ - /* v14 = data[j*2+4] */ - /* v15 = deinterlace_high(v13,v14) */ - /* v16 = deinterlace_low(v13,v14) */ - /* (sum0) v17 += multsum(v13,v15) */ - /* (sum1) v18 += multsum(v14,v16) */ - - sum0 += data[j * 2] * w; - sum1 += data[j * 2 + 1] * w; - i += n; - - } - - *r0 = sum0; - *r1 = sum1; -} -#endif diff --git a/gst/audioscale/gstaudioscale.c b/gst/audioscale/gstaudioscale.c deleted file mode 100644 index 160c4ab..0000000 --- a/gst/audioscale/gstaudioscale.c +++ /dev/null @@ -1,735 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * - * 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 (at your option) 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. - */ -/* Element-Checklist-Version: 5 */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include - -/*#define DEBUG_ENABLED */ -#include "gstaudioscale.h" -#include -#include - -GST_DEBUG_CATEGORY_STATIC (audioscale_debug); -#define GST_CAT_DEFAULT audioscale_debug - -/* elementfactory information */ -static GstElementDetails gst_audioscale_details = -GST_ELEMENT_DETAILS ("Audio scaler", - "Filter/Converter/Audio", - "Resample audio", - "David Schleef "); - -/* Audioscale signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_FILTERLEN, - ARG_METHOD - /* FILL ME */ -}; - -#define SUPPORTED_CAPS \ - GST_STATIC_CAPS (\ - "audio/x-raw-int, " \ - "rate = (int) [ 1, MAX ], " \ - "channels = (int) [ 1, MAX ], " \ - "endianness = (int) BYTE_ORDER, " \ - "width = (int) 16, " \ - "depth = (int) 16, " \ - "signed = (boolean) true") -#if 0 - /* disabled because it segfaults */ -#define NOTHING "audio/x-raw-float, " \ - "rate = (int) [ 1, MAX ], " \ - "channels = (int) [ 1, MAX ], " \ - "endianness = (int) BYTE_ORDER, " "width = (int) 32") -#endif -static GstStaticPadTemplate gst_audioscale_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS); - -static GstStaticPadTemplate gst_audioscale_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, GST_PAD_ALWAYS, SUPPORTED_CAPS); - -#define GST_TYPE_AUDIOSCALE_METHOD (gst_audioscale_method_get_type()) -static GType -gst_audioscale_method_get_type (void) -{ - static GType audioscale_method_type = 0; - static GEnumValue audioscale_methods[] = { - {GST_RESAMPLE_NEAREST, "Nearest", "nearest"}, - {GST_RESAMPLE_BILINEAR, "Bilinear", "bilinear"}, - {GST_RESAMPLE_SINC, "Sinc", "sinc"}, - {0, NULL, NULL}, - }; - - if (!audioscale_method_type) { - audioscale_method_type = g_enum_register_static ("GstAudioscaleMethod", - audioscale_methods); - } - return audioscale_method_type; -} - -static void gst_audioscale_base_init (gpointer g_class); -static void gst_audioscale_class_init (AudioscaleClass * klass); -static void gst_audioscale_init (Audioscale * audioscale); -static void gst_audioscale_dispose (GObject * object); - -static void gst_audioscale_chain (GstPad * pad, GstData * _data); -static GstStateChangeReturn gst_audioscale_change_state (GstElement * element, - GstStateChange transition); - -static void gst_audioscale_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_audioscale_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static void *gst_audioscale_get_buffer (void *priv, unsigned int size); - -static GstElementClass *parent_class = NULL; - -/*static guint gst_audioscale_signals[LAST_SIGNAL] = { 0 }; */ - -GType -audioscale_get_type (void) -{ - static GType audioscale_type = 0; - - if (!audioscale_type) { - static const GTypeInfo audioscale_info = { - sizeof (AudioscaleClass), - gst_audioscale_base_init, - NULL, - (GClassInitFunc) gst_audioscale_class_init, - NULL, - NULL, - sizeof (Audioscale), 0, (GInstanceInitFunc) gst_audioscale_init, - }; - - audioscale_type = - g_type_register_static (GST_TYPE_ELEMENT, "Audioscale", - &audioscale_info, 0); - } - return audioscale_type; -} - -static void -gst_audioscale_base_init (gpointer g_class) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_audioscale_src_template)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&gst_audioscale_sink_template)); - - gst_element_class_set_details (gstelement_class, &gst_audioscale_details); -} - -static void -gst_audioscale_class_init (AudioscaleClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->set_property = gst_audioscale_set_property; - gobject_class->get_property = gst_audioscale_get_property; - gobject_class->dispose = gst_audioscale_dispose; - gstelement_class->change_state = gst_audioscale_change_state; - - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILTERLEN, - g_param_spec_int ("filter_length", "filter_length", "filter_length", - 0, G_MAXINT, 16, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METHOD, - g_param_spec_enum ("method", "method", "method", - GST_TYPE_AUDIOSCALE_METHOD, GST_RESAMPLE_SINC, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); - - GST_DEBUG_CATEGORY_INIT (audioscale_debug, "audioscale", 0, - "audioscale element"); -} - -static GstStaticCaps gst_audioscale_passthru_caps = -GST_STATIC_CAPS ("audio/x-raw-int, channels = [ 3, MAX ]"); -static GstStaticCaps gst_audioscale_convert_caps = -GST_STATIC_CAPS ("audio/x-raw-int, channels = [ 1, 2 ]"); - -static GstCaps * -gst_audioscale_expand_caps (const GstCaps * caps) -{ - GstCaps *caps1, *caps2; - int i; - - caps1 = gst_caps_intersect (caps, - gst_static_caps_get (&gst_audioscale_passthru_caps)); - caps2 = gst_caps_intersect (caps, - gst_static_caps_get (&gst_audioscale_convert_caps)); - - for (i = 0; i < gst_caps_get_size (caps2); i++) { - GstStructure *structure = gst_caps_get_structure (caps2, i); - - gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - NULL); - } - - gst_caps_append (caps1, caps2); - - return caps1; -} - -static GstCaps * -gst_audioscale_getcaps (GstPad * pad) -{ - Audioscale *audioscale; - GstPad *otherpad; - GstCaps *othercaps; - GstCaps *caps; - - audioscale = GST_AUDIOSCALE (gst_pad_get_parent (pad)); - - otherpad = (pad == audioscale->srcpad) ? audioscale->sinkpad : - audioscale->srcpad; - othercaps = gst_pad_get_allowed_caps (otherpad); - caps = gst_audioscale_expand_caps (othercaps); - gst_caps_free (othercaps); - - return caps; -} - -static GstCaps * -gst_audioscale_fixate (GstPad * pad, const GstCaps * caps) -{ - Audioscale *audioscale; - gst_resample_t *r; - GstPad *otherpad; - int rate; - GstCaps *copy; - GstStructure *structure; - - audioscale = GST_AUDIOSCALE (gst_pad_get_parent (pad)); - r = &(audioscale->gst_resample_template); - if (pad == audioscale->srcpad) { - otherpad = audioscale->sinkpad; - rate = r->i_rate; - } else { - otherpad = audioscale->srcpad; - rate = r->o_rate; - } - if (!GST_PAD_IS_NEGOTIATING (otherpad)) - return NULL; - if (gst_caps_get_size (caps) > 1) - return NULL; - - copy = gst_caps_copy (caps); - structure = gst_caps_get_structure (copy, 0); - if (gst_structure_fixate_field_nearest_int (structure, "rate", rate)) - return copy; - gst_caps_free (copy); - return NULL; -} - -static GstPadLinkReturn -gst_audioscale_link (GstPad * pad, const GstCaps * caps) -{ - Audioscale *audioscale; - gst_resample_t *r; - GstStructure *structure; - double *rate, *otherrate; - double temprate; - - int temp; - gboolean ret; - GstPadLinkReturn link_ret; - GstPad *otherpad; - GstCaps *copy; - - audioscale = GST_AUDIOSCALE (gst_pad_get_parent (pad)); - r = &(audioscale->gst_resample_template); - - if (pad == audioscale->srcpad) { - otherpad = audioscale->sinkpad; - rate = &r->o_rate; - otherrate = &r->i_rate; - } else { - otherpad = audioscale->srcpad; - rate = &r->i_rate; - otherrate = &r->o_rate; - } - - structure = gst_caps_get_structure (caps, 0); - ret = gst_structure_get_int (structure, "rate", &temp); - ret &= gst_structure_get_int (structure, "channels", &r->channels); - g_return_val_if_fail (ret, GST_PAD_LINK_REFUSED); - *rate = (double) temp; - - copy = gst_audioscale_expand_caps (caps); - link_ret = gst_pad_try_set_caps_nonfixed (otherpad, copy); - gst_caps_free (copy); - if (GST_PAD_LINK_FAILED (link_ret)) - return link_ret; - - caps = gst_pad_get_negotiated_caps (otherpad); - g_return_val_if_fail (caps, GST_PAD_LINK_REFUSED); - structure = gst_caps_get_structure (caps, 0); - ret = gst_structure_get_int (structure, "rate", &temp); - g_return_val_if_fail (ret, GST_PAD_LINK_REFUSED); - *otherrate = (double) temp; - if (g_str_equal (gst_structure_get_name (structure), "audio/x-raw-float")) { - r->format = GST_RESAMPLE_FLOAT; - } else { - r->format = GST_RESAMPLE_S16; - } - - audioscale->passthru = (r->i_rate == r->o_rate); - audioscale->increase = (r->o_rate >= r->i_rate); - /* now create audioscale iterations */ - audioscale->num_iterations = 0; - - temprate = r->i_rate; - while (TRUE) { - if (r->o_rate > r->i_rate) { - if (temprate >= r->o_rate) - break; - temprate *= 2; - } else { - if (temprate <= r->o_rate) - break; - temprate /= 2; - } - audioscale->num_iterations++; - } - - - - - if (audioscale->num_iterations > 0) { - audioscale->offsets = g_new0 (gint64, audioscale->num_iterations); - audioscale->gst_resample = g_new0 (gst_resample_t, 1); - audioscale->gst_resample->priv = audioscale; - audioscale->gst_resample->get_buffer = gst_audioscale_get_buffer; - audioscale->gst_resample->method = r->method; - audioscale->gst_resample->channels = r->channels; - audioscale->gst_resample->filter_length = r->filter_length; - audioscale->gst_resample->format = r->format; - if (audioscale->increase) { - temprate = r->o_rate; - - while (temprate / 2 >= r->i_rate) { - temprate = temprate / 2; - } - /* now temprate is output rate of gstresample */ - GST_DEBUG ("gstresample will increase rate from %f to %f", r->i_rate, - temprate); - audioscale->gst_resample->o_rate = temprate; - audioscale->gst_resample->i_rate = r->i_rate; - } else { - temprate = r->i_rate; - - while (temprate / 2 >= r->o_rate) { - temprate = temprate / 2; - } - /* now temprate is input rate of gstresample */ - GST_DEBUG ("gstresample will decrease rate from %f to %f", temprate, - r->o_rate); - audioscale->gst_resample->o_rate = r->o_rate; - audioscale->gst_resample->i_rate = temprate; - } - audioscale->passthru = - (audioscale->gst_resample->i_rate == audioscale->gst_resample->o_rate); - if (!audioscale->passthru) - audioscale->num_iterations--; - GST_DEBUG ("Number of iterations: %d", audioscale->num_iterations); - - gst_resample_init (audioscale->gst_resample); - } - - return link_ret; -} - -static void * -gst_audioscale_get_buffer (void *priv, unsigned int size) -{ - Audioscale *audioscale = priv; - - GST_DEBUG ("size requested: %u irate: %f orate: %f", size, - audioscale->gst_resample->i_rate, audioscale->gst_resample->o_rate); - audioscale->outbuf = gst_buffer_new (); - GST_BUFFER_SIZE (audioscale->outbuf) = size; - GST_BUFFER_DATA (audioscale->outbuf) = g_malloc (size); - GST_BUFFER_TIMESTAMP (audioscale->outbuf) = - audioscale->gst_resample_offset * GST_SECOND / - audioscale->gst_resample->o_rate; - audioscale->gst_resample_offset += - size / sizeof (gint16) / audioscale->gst_resample->channels; - - return GST_BUFFER_DATA (audioscale->outbuf); -} - -/* reduces rate by factor of 2 */ -GstBuffer * -gst_audioscale_decrease_rate (Audioscale * audioscale, - GstBuffer * buf, double outrate, int cur_iteration) -{ - gint i, j, curoffset; - GstBuffer *outbuf = gst_buffer_new (); - gint16 *outdata; - gint16 *indata; - - GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf) / 2; - outdata = g_malloc (GST_BUFFER_SIZE (outbuf)); - indata = (gint16 *) GST_BUFFER_DATA (buf); - - GST_DEBUG - ("iteration = %d channels = %d in size = %d out size = %d outrate = %f", - cur_iteration, audioscale->gst_resample_template.channels, - GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (outbuf), outrate); - curoffset = 0; - for (i = 0; i < GST_BUFFER_SIZE (buf) / (sizeof (gint16)); - i += 2 * audioscale->gst_resample_template.channels) { - for (j = 0; j < audioscale->gst_resample_template.channels; j++) { - outdata[curoffset + j] = - (indata[i + j] + indata[i + j + - audioscale->gst_resample_template.channels]) / 2; - } - curoffset += audioscale->gst_resample_template.channels; - } - - GST_BUFFER_DATA (outbuf) = (gpointer) outdata; - GST_BUFFER_TIMESTAMP (outbuf) = - audioscale->offsets[cur_iteration] * GST_SECOND / outrate; - audioscale->offsets[cur_iteration] += - GST_BUFFER_SIZE (outbuf) / sizeof (gint16) / - audioscale->gst_resample->channels; - return outbuf; -} - -/* increases rate by factor of 2 */ -GstBuffer * -gst_audioscale_increase_rate (Audioscale * audioscale, - GstBuffer * buf, double outrate, int cur_iteration) -{ - gint i, j, curoffset; - GstBuffer *outbuf = gst_buffer_new (); - gint16 *outdata; - gint16 *indata; - - GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf) * 2; - outdata = g_malloc (GST_BUFFER_SIZE (outbuf)); - indata = (gint16 *) GST_BUFFER_DATA (buf); - - GST_DEBUG - ("iteration = %d channels = %d in size = %d out size = %d out rate = %f", - cur_iteration, audioscale->gst_resample_template.channels, - GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (outbuf), outrate); - curoffset = 0; - for (i = 0; i < GST_BUFFER_SIZE (buf) / (sizeof (gint16)); - i += audioscale->gst_resample_template.channels) { - for (j = 0; j < audioscale->gst_resample_template.channels; j++) { - outdata[curoffset] = indata[i + j]; - outdata[curoffset + audioscale->gst_resample_template.channels] = - indata[i + j]; - curoffset++; - } - curoffset += audioscale->gst_resample_template.channels; - } - - GST_BUFFER_DATA (outbuf) = (gpointer) outdata; - GST_BUFFER_TIMESTAMP (outbuf) = - audioscale->offsets[cur_iteration] * GST_SECOND / outrate; - audioscale->offsets[cur_iteration] += - GST_BUFFER_SIZE (outbuf) / sizeof (gint16) / - audioscale->gst_resample->channels; - return outbuf; -} - -static void -gst_audioscale_init (Audioscale * audioscale) -{ - gst_resample_t *r; - - audioscale->num_iterations = 1; - - audioscale->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_audioscale_sink_template), "sink"); - gst_element_add_pad (GST_ELEMENT (audioscale), audioscale->sinkpad); - gst_pad_set_chain_function (audioscale->sinkpad, gst_audioscale_chain); - gst_pad_set_link_function (audioscale->sinkpad, gst_audioscale_link); - gst_pad_set_getcaps_function (audioscale->sinkpad, gst_audioscale_getcaps); - gst_pad_set_fixate_function (audioscale->sinkpad, gst_audioscale_fixate); - - audioscale->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get - (&gst_audioscale_src_template), "src"); - - gst_element_add_pad (GST_ELEMENT (audioscale), audioscale->srcpad); - gst_pad_set_link_function (audioscale->srcpad, gst_audioscale_link); - gst_pad_set_getcaps_function (audioscale->srcpad, gst_audioscale_getcaps); - gst_pad_set_fixate_function (audioscale->srcpad, gst_audioscale_fixate); - - r = &(audioscale->gst_resample_template); - - r->priv = audioscale; - r->get_buffer = gst_audioscale_get_buffer; - r->method = GST_RESAMPLE_SINC; - r->channels = 0; - r->filter_length = 16; - r->i_rate = -1; - r->o_rate = -1; - r->format = GST_RESAMPLE_S16; - /*r->verbose = 1; */ - - audioscale->gst_resample = NULL; - audioscale->outbuf = NULL; - audioscale->offsets = NULL; - audioscale->gst_resample_offset = 0; - audioscale->increase = FALSE; - - GST_OBJECT_FLAG_SET (audioscale, GST_ELEMENT_EVENT_AWARE); -} - -static void -gst_audioscale_dispose (GObject * object) -{ - Audioscale *audioscale = GST_AUDIOSCALE (object); - - if (audioscale->gst_resample) { - gst_resample_close (audioscale->gst_resample); - g_free (audioscale->gst_resample); - audioscale->gst_resample = NULL; - } - if (audioscale->offsets) { - g_free (audioscale->offsets); - audioscale->offsets = NULL; - } - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_audioscale_chain (GstPad * pad, GstData * _data) -{ - GstBuffer *buf = GST_BUFFER (_data); - GstBuffer *tempbuf, *tempbuf2; - GstClockTime outduration; - - Audioscale *audioscale; - guchar *data; - gulong size; - gint i; - double outrate; - - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - audioscale = GST_AUDIOSCALE (gst_pad_get_parent (pad)); - - if (GST_IS_EVENT (_data)) { - GstEvent *e = GST_EVENT (_data); - - switch (GST_EVENT_TYPE (e)) { - case GST_EVENT_DISCONTINUOUS:{ - gint64 new_off = 0; - - if (!audioscale->gst_resample) { - GST_LOG ("Discont before negotiation took place - ignoring"); - } else if (gst_event_discont_get_value (e, GST_FORMAT_TIME, &new_off)) { - /* time -> out-sample */ - new_off = new_off * audioscale->gst_resample->o_rate / GST_SECOND; - } else if (gst_event_discont_get_value (e, - GST_FORMAT_DEFAULT, &new_off)) { - /* in-sample -> out-sample */ - new_off *= audioscale->gst_resample->o_rate; - new_off /= audioscale->gst_resample->i_rate; - } else if (gst_event_discont_get_value (e, GST_FORMAT_BYTES, &new_off)) { - new_off /= audioscale->gst_resample->channels; - new_off /= - (audioscale->gst_resample->format == GST_RESAMPLE_S16) ? 2 : 4; - new_off *= audioscale->gst_resample->o_rate; - new_off /= audioscale->gst_resample->i_rate; - } else { - /* *sigh* */ - GST_DEBUG ("Discont without value - ignoring"); - } - audioscale->gst_resample_offset = new_off; - /* fall-through */ - } - default: - gst_pad_event_default (pad, e); - break; - } - return; - } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buf) && audioscale->gst_resample) { - /* update time for out-sample */ - audioscale->gst_resample_offset = GST_BUFFER_TIMESTAMP (buf) * - audioscale->gst_resample->o_rate / GST_SECOND; - } - - if (audioscale->passthru && audioscale->num_iterations == 0) { - gst_pad_push (audioscale->srcpad, GST_DATA (buf)); - return; - } - - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); - outduration = GST_BUFFER_DURATION (buf); - - GST_DEBUG ("gst_audioscale_chain: got buffer of %ld bytes in '%s'\n", - size, gst_element_get_name (GST_ELEMENT (audioscale))); - - tempbuf = buf; - outrate = audioscale->gst_resample_template.i_rate; - if (audioscale->increase && !audioscale->passthru) { - GST_DEBUG ("doing gstresample"); - gst_resample_scale (audioscale->gst_resample, data, size); - tempbuf = audioscale->outbuf; - gst_buffer_unref (buf); - outrate = audioscale->gst_resample->o_rate; - } - for (i = 0; i < audioscale->num_iterations; i++) { - tempbuf2 = tempbuf; - GST_DEBUG ("doing %s", - audioscale-> - increase ? "gst_audioscale_increase_rate" : - "gst_audioscale_decrease_rate"); - - if (audioscale->increase) { - outrate *= 2; - tempbuf = gst_audioscale_increase_rate (audioscale, tempbuf, outrate, i); - } else { - outrate /= 2; - tempbuf = gst_audioscale_decrease_rate (audioscale, tempbuf, outrate, i); - } - - gst_buffer_unref (tempbuf2); - data = GST_BUFFER_DATA (tempbuf); - size = GST_BUFFER_SIZE (tempbuf); - } - if (!audioscale->increase && !audioscale->passthru) { - gst_resample_scale (audioscale->gst_resample, data, size); - gst_buffer_unref (tempbuf); - tempbuf = audioscale->outbuf; - } - GST_BUFFER_DURATION (tempbuf) = outduration; - gst_pad_push (audioscale->srcpad, GST_DATA (tempbuf)); - -} - -static GstStateChangeReturn -gst_audioscale_change_state (GstElement * element, GstStateChange transition) -{ - Audioscale *audioscale = GST_AUDIOSCALE (element); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - audioscale->gst_resample_offset = 0; - break; - default: - break; - } - - return parent_class->change_state (element, transition); -} - -static void -gst_audioscale_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - Audioscale *src; - gst_resample_t *r; - - g_return_if_fail (GST_IS_AUDIOSCALE (object)); - src = GST_AUDIOSCALE (object); - r = &(src->gst_resample_template); - - switch (prop_id) { - case ARG_FILTERLEN: - r->filter_length = g_value_get_int (value); - GST_DEBUG_OBJECT (GST_ELEMENT (src), "new filter length %d\n", - r->filter_length); - break; - case ARG_METHOD: - r->method = g_value_get_enum (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - gst_resample_reinit (r); -} - -static void -gst_audioscale_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - Audioscale *src; - gst_resample_t *r; - - src = GST_AUDIOSCALE (object); - r = &(src->gst_resample_template); - - switch (prop_id) { - case ARG_FILTERLEN: - g_value_set_int (value, r->filter_length); - break; - case ARG_METHOD: - g_value_set_enum (value, r->method); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "audioscale", GST_RANK_SECONDARY, - GST_TYPE_AUDIOSCALE)) { - return FALSE; - } - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "audioscale", - "Resamples audio", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, - GST_PACKAGE_ORIGIN) diff --git a/gst/audioscale/gstaudioscale.h b/gst/audioscale/gstaudioscale.h deleted file mode 100644 index 29d6edd..0000000 --- a/gst/audioscale/gstaudioscale.h +++ /dev/null @@ -1,81 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen - * - * 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 (at your option) 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. - */ - - -#ifndef __AUDIOSCALE_H__ -#define __AUDIOSCALE_H__ - - -#include - -#include - - -G_BEGIN_DECLS - - -#define GST_TYPE_AUDIOSCALE \ - (audioscale_get_type()) -#define GST_AUDIOSCALE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIOSCALE,Audioscale)) -#define GST_AUDIOSCALE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIOSCALE,Audioscale)) -#define GST_IS_AUDIOSCALE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIOSCALE)) -#define GST_IS_AUDIOSCALE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIOSCALE)) - -typedef enum { - GST_AUDIOSCALE_NEAREST, - GST_AUDIOSCALE_BILINEAR, - GST_AUDIOSCALE_SINC, -} GstAudioScaleMethod; - -typedef struct _Audioscale Audioscale; -typedef struct _AudioscaleClass AudioscaleClass; - -struct _Audioscale { - GstElement element; - - GstPad *sinkpad,*srcpad; - - /* audio state */ - gboolean passthru; - gint64 gst_resample_offset; - - gint64* offsets; - gboolean increase; /* is the rate change an increase */ - gint num_iterations; /* number of iterations through gst_audioscale/(increase|decrease)_rate */ - - gst_resample_t gst_resample_template; - gst_resample_t* gst_resample; - GstBuffer* outbuf; -}; - -struct _AudioscaleClass { - GstElementClass parent_class; -}; - -GType gst_audioscale_get_type(void); - - -G_END_DECLS - - -#endif /* __AUDIOSCALE_H__ */ diff --git a/gst/audioscale/private.h b/gst/audioscale/private.h deleted file mode 100644 index 20339c1..0000000 --- a/gst/audioscale/private.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Resampling library - * Copyright (C) <2001> David Schleef - * - * 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. - */ - - -#ifndef __PRIVATE_H__ -#define __PRIVATE_H__ - -#include "resample.h" - -G_BEGIN_DECLS - -void gst_resample_nearest_s16(gst_resample_t *r); -void gst_resample_bilinear_s16(gst_resample_t *r); -void gst_resample_sinc_s16(gst_resample_t *r); -void gst_resample_sinc_slow_s16(gst_resample_t *r); -void gst_resample_sinc_ft_s16(gst_resample_t * r); - -void gst_resample_nearest_float(gst_resample_t *r); -void gst_resample_bilinear_float(gst_resample_t *r); -void gst_resample_sinc_float(gst_resample_t *r); -void gst_resample_sinc_slow_float(gst_resample_t *r); -void gst_resample_sinc_ft_float(gst_resample_t * r); - - -typedef struct functable_s functable_t; -struct functable_s { - double start; - double offset; - int len; - - double invoffset; - - double scale; - double scale2; - - double (*func_x)(void *,double x); - double (*func_dx)(void *,double x); - - double (*func2_x)(void *,double x); - double (*func2_dx)(void *,double x); - - double *fx; - double *fdx; - - void *priv; -}; - -void functable_init(functable_t *t); -double functable_eval(functable_t *t,double x); - -double functable_fir(functable_t *t,double x0,int n,double *data,int len); -void functable_fir2(functable_t *t,double *r0, double *r1, double x0, - int n,double *data,int len); - -double functable_sinc(void *p, double x); -double functable_dsinc(void *p, double x); -double functable_window_std(void *p, double x); -double functable_window_dstd(void *p, double x); -double functable_window_boxcar(void *p, double x); -double functable_window_dboxcar(void *p, double x); - -/* math lib stuff */ - -void conv_double_short_table(double *dest, short *src, int n); -void conv_double_short_unroll(double *dest, short *src, int n); -void conv_double_short_ref(double *dest, short *src, int n); -#ifdef HAVE_CPU_PPC -void conv_double_short_altivec(double *dest, short *src, int n); -#endif - -void conv_short_double_ref(short *dest, double *src, int n); -#ifdef HAVE_CPU_PPC -void conv_short_double_ppcasm(short *dest, double *src, int n); -#endif - -#ifdef HAVE_CPU_PPC -# define conv_double_short conv_double_short_table -# if 0 -/* disabled as in .c */ -# define conv_short_double conv_short_double_ppcasm -# else -# define conv_short_double conv_short_double_ref -# endif -#else -# define conv_double_short conv_double_short_ref -# define conv_short_double conv_short_double_ref -#endif - -#define conv_double_float conv_double_float_ref -#define conv_float_double conv_float_double_ref - -void conv_double_short_dstr(double *dest, short *src, int n, int dstr); -void conv_short_double_sstr(short *dest, double *src, int n, int dstr); - -void conv_double_float_ref(double *dest, float *src, int n); -void conv_float_double_ref(float *dest, double *src, int n); -void conv_double_float_dstr(double *dest, float *src, int n, int dstr); -void conv_float_double_sstr(float *dest, double *src, int n, int sstr); - -G_END_DECLS - -#endif /* __PRIVATE_H__ */ diff --git a/gst/audioscale/resample.c b/gst/audioscale/resample.c deleted file mode 100644 index 568ec14..0000000 --- a/gst/audioscale/resample.c +++ /dev/null @@ -1,929 +0,0 @@ -/* Resampling library - * Copyright (C) <2001> David A. Schleef - * - * 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 -#include -#include -#include - -#include "private.h" -#include -#include - -inline double -sinc (double x) -{ - if (x == 0) - return 1; - return sin (x) / x; -} - -inline double -window_func (double x) -{ - x = 1 - x * x; - return x * x; -} - -signed short -double_to_s16 (double x) -{ - if (x < -32768) { - printf ("clipped\n"); - return -32768; - } - if (x > 32767) { - printf ("clipped\n"); - return -32767; - } - return rint (x); -} - -signed short -double_to_s16_ppcasm (double x) -{ - if (x < -32768) { - return -32768; - } - if (x > 32767) { - return -32767; - } - return rint (x); -} - -void -gst_resample_init (gst_resample_t * r) -{ - r->i_start = 0; - if (r->filter_length & 1) { - r->o_start = 0; - } else { - r->o_start = r->o_inc * 0.5; - } - - memset (r->acc, 0, sizeof (r->acc)); - - gst_resample_reinit (r); -} - -void -gst_resample_reinit (gst_resample_t * r) -{ - /* i_inc is the number of samples that the output increments for - * each input sample. o_inc is the opposite. */ - r->i_inc = (double) r->o_rate / r->i_rate; - r->o_inc = (double) r->i_rate / r->o_rate; - - r->halftaps = (r->filter_length - 1.0) * 0.5; - - if (r->format == GST_RESAMPLE_S16) { - switch (r->method) { - default: - case GST_RESAMPLE_NEAREST: - r->scale = gst_resample_nearest_s16; - break; - case GST_RESAMPLE_BILINEAR: - r->scale = gst_resample_bilinear_s16; - break; - case GST_RESAMPLE_SINC_SLOW: - r->scale = gst_resample_sinc_s16; - break; - case GST_RESAMPLE_SINC: - r->scale = gst_resample_sinc_ft_s16; - break; - } - } else if (r->format == GST_RESAMPLE_FLOAT) { - switch (r->method) { - default: - case GST_RESAMPLE_NEAREST: - r->scale = gst_resample_nearest_float; - break; - case GST_RESAMPLE_BILINEAR: - r->scale = gst_resample_bilinear_float; - break; - case GST_RESAMPLE_SINC_SLOW: - r->scale = gst_resample_sinc_float; - break; - case GST_RESAMPLE_SINC: - r->scale = gst_resample_sinc_ft_float; - break; - } - } else { - fprintf (stderr, "gst_resample: Unexpected format \"%d\"\n", r->format); - } -} - -void -gst_resample_close (gst_resample_t * r) -{ - if (r->buffer) { - free (r->buffer); - r->buffer = NULL; - r->buffer_len = 0; - } - if (r->hack_union.s.out_tmp) { - free (r->hack_union.s.out_tmp); - r->hack_union.s.out_tmp = NULL; - r->hack_union.s.out_tmp_len = 0; - } - -} - -/* - * Prepare to be confused. - * - * We keep a "timebase" that is based on output samples. The zero - * of the timebase cooresponds to the next output sample that will - * be written. - * - * i_start is the "time" that corresponds to the first input sample - * in an incoming buffer. Since the output depends on input samples - * ahead in time, i_start will tend to be around halftaps. - * - * i_start_buf is the time of the first sample in the temporary - * buffer. - */ -void -gst_resample_scale (gst_resample_t * r, void *i_buf, unsigned int i_size) -{ - int o_size; - - r->i_buf = i_buf; - - r->i_samples = i_size / 2 / r->channels; - - r->i_start_buf = r->i_start - r->filter_length * r->i_inc; - - /* i_start is the offset (in a given output sample) that is the - * beginning of the current input buffer */ - r->i_end = r->i_start + r->i_inc * r->i_samples; - - r->o_samples = floor (r->i_end - r->halftaps * r->i_inc); - - o_size = r->o_samples * r->channels * 2; - r->o_buf = r->get_buffer (r->priv, o_size); - - if (r->verbose) { - printf ("gst_resample_scale: i_buf=%p i_size=%d\n", i_buf, i_size); - printf ("gst_resample_scale: i_samples=%d o_samples=%d i_inc=%g o_buf=%p\n", - r->i_samples, r->o_samples, r->i_inc, r->o_buf); - printf ("gst_resample_scale: i_start=%g i_end=%g o_start=%g\n", - r->i_start, r->i_end, r->o_start); - } - - if ((r->filter_length + r->i_samples) * sizeof (double) * 2 > r->buffer_len) { - int size = (r->filter_length + r->i_samples) * sizeof (double) * 2; - - if (r->verbose) { - printf ("gst_resample temp buffer size=%d\n", size); - } - if (r->buffer) - free (r->buffer); - r->buffer_len = size; - r->buffer = malloc (size); - memset (r->buffer, 0, size); - } - - if (r->format == GST_RESAMPLE_S16) { - if (r->channels == 2) { - conv_double_short (r->buffer + r->filter_length * sizeof (double) * 2, - r->i_buf, r->i_samples * 2); - } else { - conv_double_short_dstr (r->buffer + - r->filter_length * sizeof (double) * 2, r->i_buf, r->i_samples, - sizeof (double) * 2); - } - } else if (r->format == GST_RESAMPLE_FLOAT) { - if (r->channels == 2) { - conv_double_float (r->buffer + r->filter_length * sizeof (double) * 2, - r->i_buf, r->i_samples * 2); - } else { - conv_double_float_dstr (r->buffer + - r->filter_length * sizeof (double) * 2, r->i_buf, r->i_samples, - sizeof (double) * 2); - } - } - - r->scale (r); - - memcpy (r->buffer, - r->buffer + r->i_samples * sizeof (double) * 2, - r->filter_length * sizeof (double) * 2); - - /* updating times */ - r->i_start += r->i_samples * r->i_inc; - r->o_start += r->o_samples * r->o_inc - r->i_samples; - - /* adjusting timebase zero */ - r->i_start -= r->o_samples; -} - -void -gst_resample_nearest_s16 (gst_resample_t * r) -{ - signed short *i_ptr, *o_ptr; - int i_count = 0; - double a; - int i; - - i_ptr = (signed short *) r->i_buf; - o_ptr = (signed short *) r->o_buf; - - a = r->o_start; - i_count = 0; -#define SCALE_LOOP(COPY,INC) \ - for (i = 0; i < r->o_samples; i++) { \ - COPY; \ - a += r->o_inc; \ - while (a >= 1) { \ - a -= 1; \ - i_ptr+=INC; \ - i_count++; \ - } \ - o_ptr+=INC; \ - } - - switch (r->channels) { - case 1: - SCALE_LOOP (o_ptr[0] = i_ptr[0], 1); - break; - case 2: - SCALE_LOOP (o_ptr[0] = i_ptr[0]; - o_ptr[1] = i_ptr[1], 2); - break; - default: - { - int n, n_chan = r->channels; - - SCALE_LOOP (for (n = 0; n < n_chan; n++) o_ptr[n] = i_ptr[n], n_chan); - } - } - if (i_count != r->i_samples) { - printf ("handled %d in samples (expected %d)\n", i_count, r->i_samples); - } -} - -void -gst_resample_bilinear_s16 (gst_resample_t * r) -{ - signed short *i_ptr, *o_ptr; - int o_count = 0; - double b; - int i; - double acc0, acc1; - - i_ptr = (signed short *) r->i_buf; - o_ptr = (signed short *) r->o_buf; - - acc0 = r->acc[0]; - acc1 = r->acc[1]; - b = r->i_start; - for (i = 0; i < r->i_samples; i++) { - b += r->i_inc; - /*printf("in %d\n",i_ptr[0]); */ - if (b >= 2) { - printf ("not expecting b>=2\n"); - } - if (b >= 1) { - acc0 += (1.0 - (b - r->i_inc)) * i_ptr[0]; - acc1 += (1.0 - (b - r->i_inc)) * i_ptr[1]; - - o_ptr[0] = rint (acc0); - /*printf("out %d\n",o_ptr[0]); */ - o_ptr[1] = rint (acc1); - o_ptr += 2; - o_count++; - - b -= 1.0; - - acc0 = b * i_ptr[0]; - acc1 = b * i_ptr[1]; - } else { - acc0 += i_ptr[0] * r->i_inc; - acc1 += i_ptr[1] * r->i_inc; - } - i_ptr += 2; - } - r->acc[0] = acc0; - r->acc[1] = acc1; - - if (o_count != r->o_samples) { - printf ("handled %d out samples (expected %d)\n", o_count, r->o_samples); - } -} - -void -gst_resample_sinc_slow_s16 (gst_resample_t * r) -{ - signed short *i_ptr, *o_ptr; - int i, j; - double c0, c1; - double a; - int start; - double center; - double weight; - - if (!r->buffer) { - int size = r->filter_length * 2 * r->channels; - - printf ("gst_resample temp buffer\n"); - r->buffer = malloc (size); - memset (r->buffer, 0, size); - } - - i_ptr = (signed short *) r->i_buf; - o_ptr = (signed short *) r->o_buf; - - a = r->i_start; -#define GETBUF(index,chan) (((index)<0) \ - ? ((short *)(r->buffer))[((index)+r->filter_length)*2+(chan)] \ - : i_ptr[(index)*2+(chan)]) - { - double sinx, cosx, sind, cosd; - double x, d; - double t; - - for (i = 0; i < r->o_samples; i++) { - start = floor (a) - r->filter_length; - center = a - r->halftaps; - x = M_PI * (start - center) * r->o_inc; - sinx = sin (M_PI * (start - center) * r->o_inc); - cosx = cos (M_PI * (start - center) * r->o_inc); - d = M_PI * r->o_inc; - sind = sin (M_PI * r->o_inc); - cosd = cos (M_PI * r->o_inc); - c0 = 0; - c1 = 0; - for (j = 0; j < r->filter_length; j++) { - weight = (x == 0) ? 1 : (sinx / x); -/*printf("j %d sin %g cos %g\n",j,sinx,cosx); */ -/*printf("j %d sin %g x %g sinc %g\n",j,sinx,x,weight); */ - c0 += weight * GETBUF ((start + j), 0); - c1 += weight * GETBUF ((start + j), 1); - t = cosx * cosd - sinx * sind; - sinx = cosx * sind + sinx * cosd; - cosx = t; - x += d; - } - o_ptr[0] = rint (c0); - o_ptr[1] = rint (c1); - o_ptr += 2; - a += r->o_inc; - } - } -#undef GETBUF - - memcpy (r->buffer, - i_ptr + (r->i_samples - r->filter_length) * r->channels, - r->filter_length * 2 * r->channels); -} - -/* only works for channels == 2 ???? */ -void -gst_resample_sinc_s16 (gst_resample_t * r) -{ - double *ptr; - signed short *o_ptr; - int i, j; - double c0, c1; - double a; - int start; - double center; - double weight; - double x0, x, d; - double scale; - - ptr = (double *) r->buffer; - o_ptr = (signed short *) r->o_buf; - - /* scale provides a cutoff frequency for the low - * pass filter aspects of sinc(). scale=M_PI - * will cut off at the input frequency, which is - * good for up-sampling, but will cause aliasing - * for downsampling. Downsampling needs to be - * cut off at o_rate, thus scale=M_PI*r->i_inc. */ - /* actually, it needs to be M_PI*r->i_inc*r->i_inc. - * Need to research why. */ - scale = M_PI * r->i_inc; - for (i = 0; i < r->o_samples; i++) { - a = r->o_start + i * r->o_inc; - start = floor (a - r->halftaps); -/*printf("%d: a=%g start=%d end=%d\n",i,a,start,start+r->filter_length-1); */ - center = a; - /*x = M_PI * (start - center) * r->o_inc; */ - /*d = M_PI * r->o_inc; */ - /*x = (start - center) * r->o_inc; */ - x0 = (start - center) * r->o_inc; - d = r->o_inc; - c0 = 0; - c1 = 0; - for (j = 0; j < r->filter_length; j++) { - x = x0 + d * j; - weight = sinc (x * scale * r->i_inc) * scale / M_PI; - weight *= window_func (x / r->halftaps * r->i_inc); - c0 += weight * ptr[(start + j + r->filter_length) * 2 + 0]; - c1 += weight * ptr[(start + j + r->filter_length) * 2 + 1]; - } - o_ptr[0] = double_to_s16 (c0); - o_ptr[1] = double_to_s16 (c1); - o_ptr += 2; - } -} - -/* - * Resampling audio is best done using a sinc() filter. - * - * - * out[t] = Sum( in[t'] * sinc((t-t')/delta_t), all t') - * - * The immediate problem with this algorithm is that it involves a - * sum over an infinite number of input samples, both in the past - * and future. Note that even though sinc(x) is bounded by 1/x, - * and thus decays to 0 for large x, since sum(x,{x=0,1..,n}) diverges - * as log(n), we need to be careful about convergence. This is - * typically done by using a windowing function, which also makes - * the sum over a finite number of input samples. - * - * The next problem is computational: sinc(), and especially - * sinc() multiplied by a non-trivial windowing function is expensive - * to calculate, and also difficult to find SIMD optimizations. Since - * the time increment on input and output is different, it is not - * possible to use a FIR filter, because the taps would have to be - * recalculated for every t. - * - * To get around the expense of calculating sinc() for every point, - * we pre-calculate sinc() at a number of points, and then interpolate - * for the values we want in calculations. The interpolation method - * chosen is bi-cubic, which requires both the evalated function and - * its derivative at every pre-sampled point. Also, if the sampled - * points are spaced commensurate with the input delta_t, we notice - * that the interpolating weights are the same for every input point. - * This decreases the number of operations to 4 multiplies and 4 adds - * for each tap, regardless of the complexity of the filtering function. - * - * At this point, it is possible to rearrange the problem as the sum - * of 4 properly weghted FIR filters. Typical SIMD computation units - * are highly optimized for FIR filters, making long filter lengths - * reasonable. - */ - -static functable_t *ft; - -void -gst_resample_sinc_ft_s16 (gst_resample_t * r) -{ - double *ptr; - signed short *o_ptr; - int i; - - /*int j; */ - double c0, c1; - - /*double a; */ - double start_f, start_x; - int start; - double center; - - /*double weight; */ - double x, d; - double scale; - int n = 4; - double *out_tmp; - - if (r->hack_union.s.out_tmp_len < r->o_samples) { - r->hack_union.s.out_tmp = realloc (r->hack_union.s.out_tmp, - r->o_samples * 2 * sizeof (double)); - r->hack_union.s.out_tmp_len = r->o_samples; - } - out_tmp = r->hack_union.s.out_tmp; - - scale = r->i_inc; /* cutoff at 22050 */ - /*scale = 1.0; // cutoff at 24000 */ - /*scale = r->i_inc * 0.5; // cutoff at 11025 */ - - if (!ft) { - ft = malloc (sizeof (*ft)); - memset (ft, 0, sizeof (*ft)); - - ft->len = (r->filter_length + 2) * n; - ft->offset = 1.0 / n; - ft->start = -ft->len * 0.5 * ft->offset; - - ft->func_x = functable_sinc; - ft->func_dx = functable_dsinc; - ft->scale = M_PI * scale; - - ft->func2_x = functable_window_std; - ft->func2_dx = functable_window_dstd; - ft->scale2 = 1.0 / r->halftaps; - - functable_init (ft); - - /*printf("len=%d offset=%g start=%g\n",ft->len,ft->offset,ft->start); */ - } - - ptr = r->buffer; - o_ptr = (signed short *) r->o_buf; - - center = r->o_start; - while (center - r->halftaps < -1 * r->filter_length) - center += 1.0; - start_x = center - r->halftaps; - start_f = floor (start_x); - start_x -= start_f; - start = start_f; - for (i = 0; i < r->o_samples; i++) { - /*start_f = floor(center - r->halftaps); */ -/*printf("%d: a=%g start=%d end=%d\n",i,a,start,start+r->filter_length-1); */ - x = start_f - center; - d = 1; - c0 = 0; - c1 = 0; -/*#define slow */ -#ifdef slow - for (j = 0; j < r->filter_length; j++) { - weight = functable_eval (ft, x) * scale; - /*weight = sinc(M_PI * scale * x)*scale*r->i_inc; */ - /*weight *= window_func(x / r->halftaps); */ - c0 += weight * ptr[(start + j + r->filter_length) * 2 + 0]; - c1 += weight * ptr[(start + j + r->filter_length) * 2 + 1]; - x += d; - } -#else - functable_fir2 (ft, - &c0, &c1, x, n, ptr + (start + r->filter_length) * 2, r->filter_length); - c0 *= scale; - c1 *= scale; -#endif - - out_tmp[2 * i + 0] = c0; - out_tmp[2 * i + 1] = c1; - center += r->o_inc; - start_x += r->o_inc; - while (start_x >= 1.0) { - start_f++; - start_x -= 1.0; - start++; - } - } - - if (r->channels == 2) { - conv_short_double (r->o_buf, out_tmp, 2 * r->o_samples); - } else { - conv_short_double_sstr (r->o_buf, out_tmp, r->o_samples, - 2 * sizeof (double)); - } -} - -/******** - ** float code below - ********/ - - -void -gst_resample_nearest_float (gst_resample_t * r) -{ - float *i_ptr, *o_ptr; - int i_count = 0; - double a; - int i; - - i_ptr = (float *) r->i_buf; - o_ptr = (float *) r->o_buf; - - a = r->o_start; - i_count = 0; -#define SCALE_LOOP(COPY,INC) \ - for (i = 0; i < r->o_samples; i++) { \ - COPY; \ - a += r->o_inc; \ - while (a >= 1) { \ - a -= 1; \ - i_ptr+=INC; \ - i_count++; \ - } \ - o_ptr+=INC; \ - } - - switch (r->channels) { - case 1: - SCALE_LOOP (o_ptr[0] = i_ptr[0], 1); - break; - case 2: - SCALE_LOOP (o_ptr[0] = i_ptr[0]; - o_ptr[1] = i_ptr[1], 2); - break; - default: - { - int n, n_chan = r->channels; - - SCALE_LOOP (for (n = 0; n < n_chan; n++) o_ptr[n] = i_ptr[n], n_chan); - } - } - if (i_count != r->i_samples) { - printf ("handled %d in samples (expected %d)\n", i_count, r->i_samples); - } -} - -void -gst_resample_bilinear_float (gst_resample_t * r) -{ - float *i_ptr, *o_ptr; - int o_count = 0; - double b; - int i; - double acc0, acc1; - - i_ptr = (float *) r->i_buf; - o_ptr = (float *) r->o_buf; - - acc0 = r->acc[0]; - acc1 = r->acc[1]; - b = r->i_start; - for (i = 0; i < r->i_samples; i++) { - b += r->i_inc; - /*printf("in %d\n",i_ptr[0]); */ - if (b >= 2) { - printf ("not expecting b>=2\n"); - } - if (b >= 1) { - acc0 += (1.0 - (b - r->i_inc)) * i_ptr[0]; - acc1 += (1.0 - (b - r->i_inc)) * i_ptr[1]; - - o_ptr[0] = acc0; - /*printf("out %d\n",o_ptr[0]); */ - o_ptr[1] = acc1; - o_ptr += 2; - o_count++; - - b -= 1.0; - - acc0 = b * i_ptr[0]; - acc1 = b * i_ptr[1]; - } else { - acc0 += i_ptr[0] * r->i_inc; - acc1 += i_ptr[1] * r->i_inc; - } - i_ptr += 2; - } - r->acc[0] = acc0; - r->acc[1] = acc1; - - if (o_count != r->o_samples) { - printf ("handled %d out samples (expected %d)\n", o_count, r->o_samples); - } -} - -void -gst_resample_sinc_slow_float (gst_resample_t * r) -{ - float *i_ptr, *o_ptr; - int i, j; - double c0, c1; - double a; - int start; - double center; - double weight; - - if (!r->buffer) { - int size = r->filter_length * sizeof (float) * r->channels; - - printf ("gst_resample temp buffer\n"); - r->buffer = malloc (size); - memset (r->buffer, 0, size); - } - - i_ptr = (float *) r->i_buf; - o_ptr = (float *) r->o_buf; - - a = r->i_start; -#define GETBUF(index,chan) (((index)<0) \ - ? ((float *)(r->buffer))[((index)+r->filter_length)*2+(chan)] \ - : i_ptr[(index)*2+(chan)]) - { - double sinx, cosx, sind, cosd; - double x, d; - double t; - - for (i = 0; i < r->o_samples; i++) { - start = floor (a) - r->filter_length; - center = a - r->halftaps; - x = M_PI * (start - center) * r->o_inc; - sinx = sin (M_PI * (start - center) * r->o_inc); - cosx = cos (M_PI * (start - center) * r->o_inc); - d = M_PI * r->o_inc; - sind = sin (M_PI * r->o_inc); - cosd = cos (M_PI * r->o_inc); - c0 = 0; - c1 = 0; - for (j = 0; j < r->filter_length; j++) { - weight = (x == 0) ? 1 : (sinx / x); -/*printf("j %d sin %g cos %g\n",j,sinx,cosx); */ -/*printf("j %d sin %g x %g sinc %g\n",j,sinx,x,weight); */ - c0 += weight * GETBUF ((start + j), 0); - c1 += weight * GETBUF ((start + j), 1); - t = cosx * cosd - sinx * sind; - sinx = cosx * sind + sinx * cosd; - cosx = t; - x += d; - } - o_ptr[0] = c0; - o_ptr[1] = c1; - o_ptr += 2; - a += r->o_inc; - } - } -#undef GETBUF - - memcpy (r->buffer, - i_ptr + (r->i_samples - r->filter_length) * r->channels, - r->filter_length * sizeof (float) * r->channels); -} - -/* only works for channels == 2 ???? */ -void -gst_resample_sinc_float (gst_resample_t * r) -{ - double *ptr; - float *o_ptr; - int i, j; - double c0, c1; - double a; - int start; - double center; - double weight; - double x0, x, d; - double scale; - - ptr = (double *) r->buffer; - o_ptr = (float *) r->o_buf; - - /* scale provides a cutoff frequency for the low - * pass filter aspects of sinc(). scale=M_PI - * will cut off at the input frequency, which is - * good for up-sampling, but will cause aliasing - * for downsampling. Downsampling needs to be - * cut off at o_rate, thus scale=M_PI*r->i_inc. */ - /* actually, it needs to be M_PI*r->i_inc*r->i_inc. - * Need to research why. */ - scale = M_PI * r->i_inc; - for (i = 0; i < r->o_samples; i++) { - a = r->o_start + i * r->o_inc; - start = floor (a - r->halftaps); -/*printf("%d: a=%g start=%d end=%d\n",i,a,start,start+r->filter_length-1); */ - center = a; - /*x = M_PI * (start - center) * r->o_inc; */ - /*d = M_PI * r->o_inc; */ - /*x = (start - center) * r->o_inc; */ - x0 = (start - center) * r->o_inc; - d = r->o_inc; - c0 = 0; - c1 = 0; - for (j = 0; j < r->filter_length; j++) { - x = x0 + d * j; - weight = sinc (x * scale * r->i_inc) * scale / M_PI; - weight *= window_func (x / r->halftaps * r->i_inc); - c0 += weight * ptr[(start + j + r->filter_length) * 2 + 0]; - c1 += weight * ptr[(start + j + r->filter_length) * 2 + 1]; - } - o_ptr[0] = c0; - o_ptr[1] = c1; - o_ptr += 2; - } -} - -void -gst_resample_sinc_ft_float (gst_resample_t * r) -{ - double *ptr; - float *o_ptr; - int i; - - /*int j; */ - double c0, c1; - - /*double a; */ - double start_f, start_x; - int start; - double center; - - /*double weight; */ - double x, d; - double scale; - int n = 4; - double *out_tmp; - - if (r->hack_union.s.out_tmp_len < r->o_samples) { - r->hack_union.s.out_tmp = realloc (r->hack_union.s.out_tmp, - r->o_samples * 2 * sizeof (double)); - r->hack_union.s.out_tmp_len = r->o_samples; - } - out_tmp = r->hack_union.s.out_tmp; - - scale = r->i_inc; /* cutoff at 22050 */ - /*scale = 1.0; // cutoff at 24000 */ - /*scale = r->i_inc * 0.5; // cutoff at 11025 */ - - if (!ft) { - ft = malloc (sizeof (*ft)); - memset (ft, 0, sizeof (*ft)); - - ft->len = (r->filter_length + 2) * n; - ft->offset = 1.0 / n; - ft->start = -ft->len * 0.5 * ft->offset; - - ft->func_x = functable_sinc; - ft->func_dx = functable_dsinc; - ft->scale = M_PI * scale; - - ft->func2_x = functable_window_std; - ft->func2_dx = functable_window_dstd; - ft->scale2 = 1.0 / r->halftaps; - - functable_init (ft); - - /*printf("len=%d offset=%g start=%g\n",ft->len,ft->offset,ft->start); */ - } - - ptr = r->buffer; - o_ptr = (float *) r->o_buf; - - center = r->o_start; - start_x = center - r->halftaps; - start_f = floor (start_x); - start_x -= start_f; - start = start_f; - for (i = 0; i < r->o_samples; i++) { - /*start_f = floor(center - r->halftaps); */ -/*printf("%d: a=%g start=%d end=%d\n",i,a,start,start+r->filter_length-1); */ - x = start_f - center; - d = 1; - c0 = 0; - c1 = 0; -/*#define slow */ -#ifdef slow - for (j = 0; j < r->filter_length; j++) { - weight = functable_eval (ft, x) * scale; - /*weight = sinc(M_PI * scale * x)*scale*r->i_inc; */ - /*weight *= window_func(x / r->halftaps); */ - c0 += weight * ptr[(start + j + r->filter_length) * 2 + 0]; - c1 += weight * ptr[(start + j + r->filter_length) * 2 + 1]; - x += d; - } -#else - functable_fir2 (ft, - &c0, &c1, x, n, ptr + (start + r->filter_length) * 2, r->filter_length); - c0 *= scale; - c1 *= scale; -#endif - - out_tmp[2 * i + 0] = c0; - out_tmp[2 * i + 1] = c1; - center += r->o_inc; - start_x += r->o_inc; - while (start_x >= 1.0) { - start_f++; - start_x -= 1.0; - start++; - } - } - - if (r->channels == 2) { - conv_float_double (r->o_buf, out_tmp, 2 * r->o_samples); - } else { - conv_float_double_sstr (r->o_buf, out_tmp, r->o_samples, - 2 * sizeof (double)); - } -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "gstresample", - "Resampling routines for use in audio plugins", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst/audioscale/resample.h b/gst/audioscale/resample.h deleted file mode 100644 index 111c201..0000000 --- a/gst/audioscale/resample.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Resampling library - * Copyright (C) <2001> David Schleef - * - * 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. - */ - - -#ifndef __GST_RESAMPLE_H__ -#define __GST_RESAMPLE_H__ - -#include - -G_BEGIN_DECLS - -typedef enum { - GST_RESAMPLE_NEAREST = 0, - GST_RESAMPLE_BILINEAR, - GST_RESAMPLE_SINC_SLOW, - GST_RESAMPLE_SINC, -} gst_resample_method; - -typedef enum { - GST_RESAMPLE_S16 = 0, - GST_RESAMPLE_FLOAT -} gst_resample_format; - -typedef struct gst_resample_s gst_resample_t; - -struct gst_resample_s { - /* parameters */ - - gst_resample_method method; - int channels; - int verbose; - gst_resample_format format; - - int filter_length; - - double i_rate; - double o_rate; - - void *priv; - - void *(*get_buffer)(void *priv, unsigned int size); - - /* internal parameters */ - - double halftaps; - - /* filter state */ - - void *buffer; - int buffer_len; - - double i_start; - double o_start; - - double i_start_buf; - double i_end_buf; - - double i_inc; - double o_inc; - - double i_end; - double o_end; - - int i_samples; - int o_samples; - - void *i_buf, *o_buf; - - double acc[2]; - union { - struct { - double *out_tmp; - int out_tmp_len; - } s; - double padding[8]; - } hack_union; - - /* methods */ - void (*scale)(gst_resample_t *r); - - double ack; - -}; - -void gst_resample_init(gst_resample_t *r); - -void gst_resample_reinit(gst_resample_t *r); - -void gst_resample_close (gst_resample_t * r); - -void gst_resample_scale(gst_resample_t *r, void *i_buf, unsigned int size); - -G_END_DECLS - -#endif /* __GST_RESAMPLE_H__ */ diff --git a/gst/audioscale/test.c b/gst/audioscale/test.c deleted file mode 100644 index d6785ae..0000000 --- a/gst/audioscale/test.c +++ /dev/null @@ -1,375 +0,0 @@ - -#include -#include -#include -#include - -#include - -#define AMP 16000 -#define I_RATE 48000 -#define O_RATE 44100 -/*#define O_RATE 24000 */ - -/*#define test_func(x) 1 */ -/*#define test_func(x) sin(2*M_PI*(x)*10) */ -/*#define test_func(x) sin(2*M_PI*(x)*(x)*1000) */ -#define test_func(x) sin(2*M_PI*(x)*(x)*12000) - -short i_buf[I_RATE * 2 * 2]; -short o_buf[O_RATE * 2 * 2]; - -static int i_offset; -static int o_offset; - -FILE *out; - -void test_res1 (void); -void test_res2 (void); -void test_res3 (void); -void test_res4 (void); -void test_res5 (void); -void test_res6 (void); -void test_res7 (void); - -int -main (int argc, char *argv[]) -{ - out = fopen ("out", "w"); - - test_res7 (); - - return 0; -} - -void * -get_buffer (void *priv, unsigned int size) -{ - void *ret; - - ret = ((void *) o_buf) + o_offset; - o_offset += size; - return ret; -} - -struct timeval start_time; -void -start_timer (void) -{ - gettimeofday (&start_time, NULL); - /*printf("start %ld.%06ld\n",start_time.tv_sec,start_time.tv_usec); */ -} - -void -end_timer (void) -{ - struct timeval end_time; - double diff; - - gettimeofday (&end_time, NULL); - /*printf("end %ld.%06ld\n",end_time.tv_sec,end_time.tv_usec); */ - diff = (end_time.tv_sec - start_time.tv_sec) + - 1e-6 * (end_time.tv_usec - start_time.tv_usec); - - printf ("time %g\n", diff); - -} - -void -test_res1 (void) -{ - resample_t *r; - int i; - double sum10k, sum22k; - double f; - int n10k, n22k; - double x; - - for (i = 0; i < I_RATE; i++) { - i_buf[i * 2 + 0] = rint (AMP * test_func ((double) i / I_RATE)); - /*i_buf[i*2+1] = rint(AMP * test_func((double)i/I_RATE)); */ - i_buf[i * 2 + 1] = (i < 1000) ? AMP : 0; - } - - r = malloc (sizeof (resample_t)); - memset (r, 0, sizeof (resample_t)); - - r->i_rate = I_RATE; - r->o_rate = O_RATE; - /*r->method = RESAMPLE_SINC_SLOW; */ - r->method = RESAMPLE_SINC; - r->channels = 2; - /*r->verbose = 1; */ - r->filter_length = 64; - r->get_buffer = get_buffer; - - resample_init (r); - - start_timer (); -#define blocked -#ifdef blocked - for (i = 0; i + 256 < I_RATE; i += 256) { - resample_scale (r, i_buf + i * 2, 256 * 2 * 2); - } - if (I_RATE - i) { - resample_scale (r, i_buf + i * 2, (I_RATE - i) * 2 * 2); - } -#else - resample_scale (r, i_buf, I_RATE * 2 * 2); -#endif - end_timer (); - - for (i = 0; i < O_RATE; i++) { - f = AMP * test_func ((double) i / O_RATE); - /*f = rint(AMP*test_func((double)i/O_RATE)); */ - fprintf (out, "%d %d %d %g %g\n", i, - o_buf[2 * i + 0], o_buf[2 * i + 1], f, o_buf[2 * i + 0] - f); - } - - sum10k = 0; - sum22k = 0; - n10k = 0; - n22k = 0; - for (i = 0; i < O_RATE; i++) { - f = AMP * test_func ((double) i / O_RATE); - /*f = rint(AMP*test_func((double)i/O_RATE)); */ - x = o_buf[2 * i + 0] - f; - if (((0.5 * i) / O_RATE * I_RATE) < 10000) { - sum10k += x * x; - n10k++; - } - if (((0.5 * i) / O_RATE * I_RATE) < 22050) { - sum22k += x * x; - n22k++; - } - } - printf ("average error 10k=%g 22k=%g\n", - sqrt (sum10k / n10k), sqrt (sum22k / n22k)); -} - - -void -test_res2 (void) -{ - functable_t *t; - int i; - double x; - double f1, f2; - - t = malloc (sizeof (*t)); - memset (t, 0, sizeof (*t)); - - t->start = -50.0; - t->offset = 1; - t->len = 100; - - t->func_x = functable_sinc; - t->func_dx = functable_dsinc; - - functable_init (t); - - for (i = 0; i < 1000; i++) { - x = -50.0 + 0.1 * i; - f1 = functable_sinc (NULL, x); - f2 = functable_eval (t, x); - fprintf (out, "%d %g %g %g\n", i, f1, f2, f1 - f2); - } -} - -void -test_res3 (void) -{ - functable_t *t; - int i; - double x; - double f1, f2; - int n = 1; - - t = malloc (sizeof (*t)); - memset (t, 0, sizeof (*t)); - - t->start = -50.0; - t->offset = 1.0 / n; - t->len = 100 * n; - - t->func_x = functable_sinc; - t->func_dx = functable_dsinc; - - t->func2_x = functable_window_std; - t->func2_dx = functable_window_dstd; - - t->scale = 1.0; - t->scale2 = 1.0 / (M_PI * 16); - - functable_init (t); - - for (i = 0; i < 1000 * n; i++) { - x = -50.0 + 0.1 / n * i; - f1 = functable_sinc (NULL, t->scale * x) * - functable_window_std (NULL, t->scale2 * x); - f2 = functable_eval (t, x); - fprintf (out, "%d %g %g %g\n", i, f1, f2, f2 - f1); - } -} - -double -sinc_poly (double x) -{ -#define INV3FAC 1.66666666666666666e-1 -#define INV5FAC 8.33333333333333333e-3 -#define INV7FAC 1.984126984e-4 -#define INV9FAC 2.755731922e-6 -#define INV11FAC 2.505210839e-8 - double x2 = x * x; - - return 1 - x2 * INV3FAC + x2 * x2 * INV5FAC - x2 * x2 * x2 * INV7FAC; - /*+ x2 * x2 * x2 * x2 * INV9FAC */ - /*- x2 * x2 * x2 * x2 * x2 * INV11FAC; */ -} - -void -test_res4 (void) -{ - int i; - double x, f1, f2; - - for (i = 1; i < 100; i++) { - x = 0.01 * i; - f1 = 1 - sin (x) / x; - f2 = 1 - sinc_poly (x); - - fprintf (out, "%g %.20g %.20g %.20g\n", x, f1, f2, f2 - f1); - } -} - - -void -test_res5 (void) -{ - int i; - double sum; - - start_timer (); - sum = 0; - for (i = 0; i < I_RATE; i++) { - sum += i_buf[i * 2]; - } - end_timer (); - i_buf[0] = sum; -} - - -void -short_to_double (double *d, short *x) -{ - *d = *x; -} - -void -short_to_float (float *f, short *x) -{ - *f = *x; -} - -void -float_to_double (double *f, float *x) -{ - *f = *x; -} - -void -double_to_short (short *f, double *x) -{ - *f = *x; -} - -double res6_tmp[1000]; - -void -test_res6 (void) -{ - int i; - - for (i = 0; i < I_RATE; i++) { - i_buf[i] = rint (AMP * test_func ((double) i / I_RATE)); - } - - conv_double_short_ref (res6_tmp, i_buf, 1000); - for (i = 0; i < 1000; i++) { - res6_tmp[i] *= 3.0; - } - conv_short_double_ppcasm (o_buf, res6_tmp, 1000); - - for (i = 0; i < 1000; i++) { - fprintf (out, "%d %d %g %d\n", i, i_buf[i], res6_tmp[i], o_buf[i]); - } -} - -void -test_res7 (void) -{ - resample_t *r; - int i; - double sum10k, sum22k; - double f; - int n10k, n22k; - double x; - - for (i = 0; i < I_RATE; i++) { - i_buf[i] = rint (AMP * test_func ((double) i / I_RATE)); - } - - r = malloc (sizeof (resample_t)); - memset (r, 0, sizeof (resample_t)); - - r->i_rate = I_RATE; - r->o_rate = O_RATE; - /*r->method = RESAMPLE_SINC_SLOW; */ - r->method = RESAMPLE_SINC; - r->channels = 1; - /*r->verbose = 1; */ - r->filter_length = 64; - r->get_buffer = get_buffer; - - resample_init (r); - - start_timer (); -#define blocked -#ifdef blocked - for (i = 0; i + 256 < I_RATE; i += 256) { - resample_scale (r, i_buf + i, 256 * 2); - } - if (I_RATE - i) { - resample_scale (r, i_buf + i, (I_RATE - i) * 2); - } -#else - resample_scale (r, i_buf, I_RATE * 2); -#endif - end_timer (); - - for (i = 0; i < O_RATE; i++) { - f = AMP * test_func ((double) i / O_RATE); - /*f = rint(AMP*test_func((double)i/O_RATE)); */ - fprintf (out, "%d %d %d %g %g\n", i, o_buf[i], 0, f, o_buf[i] - f); - } - - sum10k = 0; - sum22k = 0; - n10k = 0; - n22k = 0; - for (i = 0; i < O_RATE; i++) { - f = AMP * test_func ((double) i / O_RATE); - /*f = rint(AMP*test_func((double)i/O_RATE)); */ - x = o_buf[i] - f; - if (((0.5 * i) / O_RATE * I_RATE) < 10000) { - sum10k += x * x; - n10k++; - } - if (((0.5 * i) / O_RATE * I_RATE) < 22050) { - sum22k += x * x; - n22k++; - } - } - printf ("average error 10k=%g 22k=%g\n", - sqrt (sum10k / n10k), sqrt (sum22k / n22k)); -} -- 2.7.4