mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
add float support to resampling lib clean up header file
Original commit message from CVS: * add float support to resampling lib * clean up header file
This commit is contained in:
parent
86a025734a
commit
a8cd8e0c7f
6 changed files with 567 additions and 113 deletions
|
@ -12,12 +12,15 @@ ARCHCFLAGS =
|
|||
endif
|
||||
endif
|
||||
|
||||
libgstresample_la_SOURCES = dtos.c functable.c resample.c resample.h
|
||||
libgstresample_la_SOURCES = dtos.c dtof.c functable.c resample.c resample.h
|
||||
libgstresample_la_LIBADD =
|
||||
libgstresample_la_CFLAGS = $(GST_CFLAGS) -ffast-math $(ARCHCFLAGS)
|
||||
libgstresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
noinst_HEADERS = resample.h
|
||||
libgstresampleincludedir = $(includedir)/gst/resample
|
||||
libgstresampleinclude_HEADERS = resample.h
|
||||
|
||||
noinst_HEADERS = private.h
|
||||
|
||||
#check_PROGRAMS = test
|
||||
#test_SOURCES = test.c
|
||||
|
|
65
gst-libs/gst/resample/dtof.c
Normal file
65
gst-libs/gst/resample/dtof.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*#include <ml.h> */
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <resample.h>
|
||||
#include "private.h"
|
||||
|
||||
|
||||
|
||||
|
|
110
gst-libs/gst/resample/private.h
Normal file
110
gst-libs/gst/resample/private.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/* Resampling library
|
||||
* Copyright (C) <2001> David 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __PRIVATE_H__
|
||||
#define __PRIVATE_H__
|
||||
|
||||
#include "resample.h"
|
||||
#include "config.h"
|
||||
|
||||
void resample_nearest_s16(resample_t *r);
|
||||
void resample_bilinear_s16(resample_t *r);
|
||||
void resample_sinc_s16(resample_t *r);
|
||||
void resample_sinc_slow_s16(resample_t *r);
|
||||
void resample_sinc_ft_s16(resample_t * r);
|
||||
|
||||
void resample_nearest_float(resample_t *r);
|
||||
void resample_bilinear_float(resample_t *r);
|
||||
void resample_sinc_float(resample_t *r);
|
||||
void resample_sinc_slow_float(resample_t *r);
|
||||
void resample_sinc_ft_float(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
|
||||
#define conv_short_double conv_short_double_ppcasm
|
||||
#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);
|
||||
|
||||
#endif /* __PRIVATE_H__ */
|
|
@ -23,7 +23,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <resample.h>
|
||||
#include "private.h"
|
||||
#include <gst/gstplugin.h>
|
||||
#include <gst/gstversion.h>
|
||||
|
||||
|
@ -63,8 +63,6 @@ signed short double_to_s16_ppcasm(double x)
|
|||
return rint(x);
|
||||
}
|
||||
|
||||
static void resample_sinc_ft(resample_t * r);
|
||||
|
||||
void resample_init(resample_t * r)
|
||||
{
|
||||
r->i_start = 0;
|
||||
|
@ -88,20 +86,40 @@ void resample_reinit(resample_t * r)
|
|||
|
||||
r->halftaps = (r->filter_length - 1.0) * 0.5;
|
||||
|
||||
switch (r->method) {
|
||||
default:
|
||||
case RESAMPLE_NEAREST:
|
||||
r->scale = resample_nearest;
|
||||
break;
|
||||
case RESAMPLE_BILINEAR:
|
||||
r->scale = resample_bilinear;
|
||||
break;
|
||||
case RESAMPLE_SINC_SLOW:
|
||||
r->scale = resample_sinc;
|
||||
break;
|
||||
case RESAMPLE_SINC:
|
||||
r->scale = resample_sinc_ft;
|
||||
break;
|
||||
if (r->format == RESAMPLE_S16) {
|
||||
switch (r->method) {
|
||||
default:
|
||||
case RESAMPLE_NEAREST:
|
||||
r->scale = resample_nearest_s16;
|
||||
break;
|
||||
case RESAMPLE_BILINEAR:
|
||||
r->scale = resample_bilinear_s16;
|
||||
break;
|
||||
case RESAMPLE_SINC_SLOW:
|
||||
r->scale = resample_sinc_s16;
|
||||
break;
|
||||
case RESAMPLE_SINC:
|
||||
r->scale = resample_sinc_ft_s16;
|
||||
break;
|
||||
}
|
||||
} else if (r->format == RESAMPLE_FLOAT) {
|
||||
switch (r->method) {
|
||||
default:
|
||||
case RESAMPLE_NEAREST:
|
||||
r->scale = resample_nearest_float;
|
||||
break;
|
||||
case RESAMPLE_BILINEAR:
|
||||
r->scale = resample_bilinear_float;
|
||||
break;
|
||||
case RESAMPLE_SINC_SLOW:
|
||||
r->scale = resample_sinc_float;
|
||||
break;
|
||||
case RESAMPLE_SINC:
|
||||
r->scale = resample_sinc_ft_float;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf (stderr, "resample: Unexpected format \"%d\"\n", r->format);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,14 +177,26 @@ void resample_scale(resample_t * r, void *i_buf, unsigned int i_size)
|
|||
memset(r->buffer, 0, size);
|
||||
}
|
||||
|
||||
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);
|
||||
if (r->format==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==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);
|
||||
|
@ -183,7 +213,7 @@ void resample_scale(resample_t * r, void *i_buf, unsigned int i_size)
|
|||
r->i_start -= r->o_samples;
|
||||
}
|
||||
|
||||
void resample_nearest(resample_t * r)
|
||||
void resample_nearest_s16(resample_t * r)
|
||||
{
|
||||
signed short *i_ptr, *o_ptr;
|
||||
int i_count = 0;
|
||||
|
@ -229,7 +259,7 @@ void resample_nearest(resample_t * r)
|
|||
}
|
||||
}
|
||||
|
||||
void resample_bilinear(resample_t * r)
|
||||
void resample_bilinear_s16(resample_t * r)
|
||||
{
|
||||
signed short *i_ptr, *o_ptr;
|
||||
int o_count = 0;
|
||||
|
@ -278,7 +308,7 @@ void resample_bilinear(resample_t * r)
|
|||
}
|
||||
}
|
||||
|
||||
void resample_sinc_slow(resample_t * r)
|
||||
void resample_sinc_slow_s16(resample_t * r)
|
||||
{
|
||||
signed short *i_ptr, *o_ptr;
|
||||
int i, j;
|
||||
|
@ -336,13 +366,15 @@ void resample_sinc_slow(resample_t * r)
|
|||
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);
|
||||
}
|
||||
|
||||
void resample_sinc(resample_t * r)
|
||||
/* only works for channels == 2 ???? */
|
||||
void resample_sinc_s16(resample_t * r)
|
||||
{
|
||||
double *ptr;
|
||||
signed short *o_ptr;
|
||||
|
@ -392,9 +424,6 @@ void resample_sinc(resample_t * r)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Resampling audio is best done using a sinc() filter.
|
||||
*
|
||||
|
@ -436,7 +465,7 @@ static functable_t *ft;
|
|||
|
||||
double out_tmp[10000];
|
||||
|
||||
static void resample_sinc_ft(resample_t * r)
|
||||
void resample_sinc_ft_s16(resample_t * r)
|
||||
{
|
||||
double *ptr;
|
||||
signed short *o_ptr;
|
||||
|
@ -530,6 +559,316 @@ static void resample_sinc_ft(resample_t * r)
|
|||
}
|
||||
}
|
||||
|
||||
/********
|
||||
** float code below
|
||||
********/
|
||||
|
||||
|
||||
void resample_nearest_float(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 resample_bilinear_float(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 resample_sinc_slow_float(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("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 resample_sinc_float(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 resample_sinc_ft_float(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;
|
||||
|
||||
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 (GModule *module, GstPlugin *plugin)
|
||||
{
|
||||
|
|
|
@ -21,16 +21,27 @@
|
|||
#ifndef __RESAMPLE_H__
|
||||
#define __RESAMPLE_H__
|
||||
|
||||
#include <config.h>
|
||||
typedef enum {
|
||||
RESAMPLE_NEAREST = 0,
|
||||
RESAMPLE_BILINEAR,
|
||||
RESAMPLE_SINC_SLOW,
|
||||
RESAMPLE_SINC,
|
||||
} resample_method;
|
||||
|
||||
typedef enum {
|
||||
RESAMPLE_S16 = 0,
|
||||
RESAMPLE_FLOAT
|
||||
} resample_format;
|
||||
|
||||
typedef struct resample_s resample_t;
|
||||
|
||||
struct resample_s {
|
||||
/* parameters */
|
||||
|
||||
int method;
|
||||
resample_method method;
|
||||
int channels;
|
||||
int verbose;
|
||||
resample_format format;
|
||||
|
||||
int filter_length;
|
||||
|
||||
|
@ -75,85 +86,11 @@ struct resample_s {
|
|||
double ack;
|
||||
};
|
||||
|
||||
enum{
|
||||
RESAMPLE_NEAREST = 0,
|
||||
RESAMPLE_BILINEAR,
|
||||
RESAMPLE_SINC_SLOW,
|
||||
RESAMPLE_SINC,
|
||||
};
|
||||
|
||||
void resample_init(resample_t *r);
|
||||
|
||||
void resample_reinit(resample_t *r);
|
||||
|
||||
void resample_scale(resample_t *r, void *i_buf, unsigned int size);
|
||||
|
||||
void resample_nearest(resample_t *r);
|
||||
void resample_bilinear(resample_t *r);
|
||||
void resample_sinc(resample_t *r);
|
||||
void resample_sinc_slow(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
|
||||
#define conv_short_double conv_short_double_ppcasm
|
||||
#else
|
||||
#define conv_double_short conv_double_short_ref
|
||||
#define conv_short_double conv_short_double_ref
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#endif /* __RESAMPLE_H__ */
|
||||
|
||||
|
|
Loading…
Reference in a new issue