integrated libsamplerate 0.1.3 source which has various improvements over 4-year-old version 0.1.2

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@895 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2008-04-07 21:37:26 +00:00
parent 4851df0cf7
commit b69c4a324e
11 changed files with 363069 additions and 22611 deletions

View File

@@ -1,5 +1,18 @@
2008-04-07 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* src/3rdparty/samplerate/common.h:
* src/3rdparty/samplerate/fastest_coeffs.h:
* src/3rdparty/samplerate/float_cast.h:
* src/3rdparty/samplerate/high_qual_coeffs.h:
* src/3rdparty/samplerate/mid_qual_coeffs.h:
* src/3rdparty/samplerate/samplerate.c:
* src/3rdparty/samplerate/samplerate.h:
* src/3rdparty/samplerate/src_linear.c:
* src/3rdparty/samplerate/src_sinc.c:
* src/3rdparty/samplerate/src_zoh.c:
integrated libsamplerate 0.1.3 source which has various improvements
over 4-year-old version 0.1.2
* src/gui/widgets/combobox.cpp:
set correct value for model when selecting an item whose strings
occurs multiple times in the combobox

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,12 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED
@@ -33,8 +39,12 @@ typedef long int32_t ;
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
#define OFFSETOF(type,member) ((int) (&((type*) 0)->member))
#define MAKE_MAGIC(a,b,c,d,e,f) ((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20))
#include "samplerate.h"
enum
@@ -67,6 +77,7 @@ enum
SRC_ERR_BAD_CALLBACK,
SRC_ERR_BAD_MODE,
SRC_ERR_NULL_CALLBACK,
SRC_ERR_NO_VARIABLE_RATIO,
/* This must be the last error number. */
SRC_ERR_MAX_ERROR
@@ -84,7 +95,13 @@ typedef struct SRC_PRIVATE_tag
/* Pointer to data to converter specific data. */
void *private_data ;
int (*process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
/* Varispeed process function. */
int (*vari_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
/* Constant speed process function. */
int (*const_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
/* State reset. */
void (*reset) (struct SRC_PRIVATE_tag *psrc) ;
/* Data specific to SRC_MODE_CALLBACK. */
@@ -112,13 +129,20 @@ const char* zoh_get_description (int src_enum) ;
int zoh_set_converter (SRC_PRIVATE *psrc, int src_enum) ;
#endif /* COMMON_H_INCLUDED */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 737d46dc-a2f8-4025-bb88-fc8915c69085
/*----------------------------------------------------------
** Common static inline functions.
*/
static inline double
fmod_one (double x)
{ double res ;
res = x - lrint (x) ;
if (res < 0.0)
return res + 1.0 ;
return res ;
} /* fmod_one */
#endif /* COMMON_H_INCLUDED */

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,11 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
/*
** f = make_filter (8, 128, 100.3) ;
@@ -26,6 +31,12 @@
** increment : 128
*/
static const struct fastest_coeffs_s
{ int increment ;
coeff_t coeffs [2464] ;
} fastest_coeffs =
{ 128,
{
8.31472372954840555082e-01,
8.31414005540308198583e-01,
8.31238918266223869580e-01,
@@ -2489,13 +2500,6 @@
-3.59691078491283933177e-07,
-2.38952398011216803052e-07,
-1.22889677382464548894e-07,
0 /* Need a final zero coefficient */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 82d149f9-28f4-4c47-b442-77a0a2d752b4
*/
0.0 /* Need a final zero coefficient */
}
} ; /* fastest_coeffs */

View File

@@ -1,23 +1,25 @@
/*
** Copyright (C) 2001-2003 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2001-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program 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 General Public License for more details.
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Version 1.3 */
/* Version 1.4 */
#ifndef FLOAT_CAST_HEADER
#define FLOAT_CAST_HEADER
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
@@ -71,10 +73,59 @@
#include <math.h>
#elif (defined (__CYGWIN__))
#include <math.h>
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
/*
** The native CYGWIN lrint and lrintf functions are buggy:
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
** and slow.
** These functions (pulled from the Public Domain MinGW math.h header)
** replace the native versions.
*/
static inline long double2int (double in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* double2int */
static inline long float2int (float in)
{ long retval ;
__asm__ __volatile__
( "fistpl %0"
: "=m" (retval)
: "t" (in)
: "st"
) ;
return retval ;
} /* float2int */
#elif (defined (WIN32) || defined (_WIN32))
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
/*
@@ -156,7 +207,7 @@
#define lrint double2int
#define lrintf float2int
inline static long int
inline static long
float2int (register float in)
{ int res [2] ;
@@ -171,7 +222,7 @@
return res [1] ;
} /* lrintf */
inline static long int
inline static long
double2int (register double in)
{ int res [2] ;
@@ -200,12 +251,5 @@
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 25418b9e-cfe8-4145-a3b3-a92388dd37c5
*/
#endif /* FLOAT_CAST_HEADER */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,12 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -23,12 +29,17 @@
#include "config.h"
#include "samplerate.h"
#include "common.h"
#include "float_cast.h"
#include "common.h"
static int psrc_set_converter (SRC_PRIVATE *psrc, int converter_type) ;
static inline int
is_bad_src_ratio (double ratio)
{ return (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) ;
} /* is_bad_src_ratio */
SRC_STATE *
src_new (int converter_type, int channels, int *error)
{ SRC_PRIVATE *psrc ;
@@ -111,7 +122,7 @@ src_process (SRC_STATE *state, SRC_DATA *data)
if (psrc == NULL)
return SRC_ERR_BAD_STATE ;
if (psrc->process == NULL)
if (psrc->vari_process == NULL || psrc->const_process == NULL)
return SRC_ERR_BAD_PROC_PTR ;
if (psrc->mode != SRC_MODE_PROCESS)
@@ -122,7 +133,7 @@ src_process (SRC_STATE *state, SRC_DATA *data)
return SRC_ERR_BAD_DATA ;
/* Check src_ratio is in range. */
if (data->src_ratio < (1.0 / SRC_MAX_RATIO) || data->src_ratio > (1.0 * SRC_MAX_RATIO))
if (is_bad_src_ratio (data->src_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
/* And that data_in and data_out are valid. */
@@ -161,7 +172,10 @@ src_process (SRC_STATE *state, SRC_DATA *data)
psrc->last_ratio = data->src_ratio ;
/* Now process. */
error = psrc->process (psrc, data) ;
if (fabs (psrc->last_ratio - data->src_ratio) < 1e-15)
error = psrc->const_process (psrc, data) ;
else
error = psrc->vari_process (psrc, data) ;
return error ;
} /* src_process */
@@ -195,7 +209,7 @@ src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)
memset (&src_data, 0, sizeof (src_data)) ;
/* Check src_ratio is in range. */
if (src_ratio < (1.0 / SRC_MAX_RATIO) || src_ratio > (1.0 * SRC_MAX_RATIO))
if (is_bad_src_ratio (src_ratio))
{ psrc->error = SRC_ERR_BAD_SRC_RATIO ;
return 0 ;
} ;
@@ -267,9 +281,12 @@ src_set_ratio (SRC_STATE *state, double new_ratio)
if (psrc == NULL)
return SRC_ERR_BAD_STATE ;
if (psrc->process == NULL)
if (psrc->vari_process == NULL || psrc->const_process == NULL)
return SRC_ERR_BAD_PROC_PTR ;
if (is_bad_src_ratio (new_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
psrc->last_ratio = new_ratio ;
return SRC_ERR_NO_ERROR ;
@@ -334,13 +351,13 @@ src_get_description (int converter_type)
const char *
src_get_version (void)
{ return PACKAGE "-" VERSION ;
{ return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ;
} /* src_get_version */
int
src_is_valid_ratio (double ratio)
{
if (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO))
if (is_bad_src_ratio (ratio))
return SRC_FALSE ;
return SRC_TRUE ;
@@ -401,6 +418,8 @@ src_strerror (int error)
return "Calling mode differs from initialisation mode (ie process v callback)." ;
case SRC_ERR_NULL_CALLBACK :
return "Callback function pointer is NULL in src_callback_read ()." ;
case SRC_ERR_NO_VARIABLE_RATIO :
return "This converter only allows constant conversion ratios." ;
case SRC_ERR_MAX_ERROR :
return "Placeholder. No error defined for this error number." ;
@@ -438,7 +457,7 @@ src_short_to_float_array (const short *in, float *out, int len)
{
while (len)
{ len -- ;
out [len] = in [len] / (1.0 * 0x8000) ;
out [len] = (float) (in [len] / (1.0 * 0x8000)) ;
} ;
return ;
@@ -446,7 +465,7 @@ src_short_to_float_array (const short *in, float *out, int len)
void
src_float_to_short_array (const float *in, short *out, int len)
{ float scaled_value ;
{ double scaled_value ;
while (len)
{ len -- ;
@@ -461,11 +480,44 @@ src_float_to_short_array (const float *in, short *out, int len)
continue ;
} ;
out [len] = (lrintf (scaled_value) >> 16) ;
out [len] = (short) (lrint (scaled_value) >> 16) ;
} ;
} /* src_float_to_short_array */
void
src_int_to_float_array (const int *in, float *out, int len)
{
while (len)
{ len -- ;
out [len] = (float) (in [len] / (8.0 * 0x10000000)) ;
} ;
return ;
} /* src_int_to_float_array */
void
src_float_to_int_array (const float *in, int *out, int len)
{ double scaled_value ;
while (len)
{ len -- ;
scaled_value = in [len] * (8.0 * 0x10000000) ;
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
{ out [len] = 0x7fffffff ;
continue ;
} ;
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
{ out [len] = -1 - 0x7fffffff ;
continue ;
} ;
out [len] = lrint (scaled_value) ;
} ;
} /* src_float_to_int_array */
/*==============================================================================
** Private functions.
*/
@@ -485,11 +537,3 @@ psrc_set_converter (SRC_PRIVATE *psrc, int converter_type)
return SRC_ERR_BAD_CONVERTER ;
} /* psrc_set_converter */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a5c5f514-a370-4210-a066-7f2035de67fb
*/

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,12 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
/*
** API documentation is available here:
** http://www.mega-nerd.com/SRC/api.html
@@ -168,7 +174,7 @@ enum
SRC_SINC_MEDIUM_QUALITY = 1,
SRC_SINC_FASTEST = 2,
SRC_ZERO_ORDER_HOLD = 3,
SRC_LINEAR = 4
SRC_LINEAR = 4,
} ;
/*
@@ -179,6 +185,9 @@ enum
void src_short_to_float_array (const short *in, float *out, int len) ;
void src_float_to_short_array (const float *in, short *out, int len) ;
void src_int_to_float_array (const int *in, float *out, int len) ;
void src_float_to_int_array (const float *in, int *out, int len) ;
#ifdef __cplusplus
} /* extern "C" */
@@ -186,11 +195,3 @@ void src_float_to_short_array (const float *in, short *out, int len) ;
#endif /* SAMPLERATE_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 5421ef3e-c898-4ec3-8671-ea03d943ee00
*/

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,12 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -24,7 +30,7 @@
#include "float_cast.h"
#include "common.h"
static int linear_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static void linear_reset (SRC_PRIVATE *psrc) ;
/*========================================================================================
@@ -37,6 +43,7 @@ static void linear_reset (SRC_PRIVATE *psrc) ;
typedef struct
{ int linear_magic_marker ;
int channels ;
int reset ;
long in_count, in_used ;
long out_count, out_gen ;
float last_value [1] ;
@@ -46,9 +53,9 @@ typedef struct
*/
static int
linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ LINEAR_DATA *linear ;
double src_ratio, input_index ;
double src_ratio, input_index, rem ;
int ch ;
if (psrc->private_data == NULL)
@@ -56,6 +63,13 @@ linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
linear = (LINEAR_DATA*) psrc->private_data ;
if (linear->reset)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < linear->channels ; ch++)
linear->last_value [ch] = data->data_in [ch] ;
linear->reset = 0 ;
} ;
linear->in_count = data->input_frames * linear->channels ;
linear->out_count = data->output_frames * linear->channels ;
linear->in_used = linear->out_gen = 0 ;
@@ -69,12 +83,12 @@ linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
if (linear->in_used + linear->channels * input_index > linear->in_count)
break ;
if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ;
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
for (ch = 0 ; ch < linear->channels ; ch++)
{ data->data_out [linear->out_gen] = linear->last_value [ch] + input_index *
(data->data_in [ch] - linear->last_value [ch]) ;
{ data->data_out [linear->out_gen] = (float) (linear->last_value [ch] + input_index *
(data->data_in [ch] - linear->last_value [ch])) ;
linear->out_gen ++ ;
} ;
@@ -82,14 +96,15 @@ linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
input_index += 1.0 / src_ratio ;
} ;
linear->in_used += linear->channels * lrint (floor (input_index)) ;
input_index -= floor (input_index) ;
rem = fmod_one (input_index) ;
linear->in_used += linear->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count)
{
if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / (linear->out_count - 1) ;
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0)
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", linear->in_used, linear->channels, input_index) ;
@@ -97,20 +112,21 @@ linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
} ;
for (ch = 0 ; ch < linear->channels ; ch++)
{ data->data_out [linear->out_gen] = data->data_in [linear->in_used - linear->channels + ch] + input_index *
(data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch]) ;
{ data->data_out [linear->out_gen] = (float) (data->data_in [linear->in_used - linear->channels + ch] + input_index *
(data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch])) ;
linear->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
linear->in_used += linear->channels * lrint (floor (input_index)) ;
input_index -= floor (input_index) ;
linear->in_used += linear->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (linear->in_used > linear->in_count)
{ input_index += linear->in_used - linear->in_count ;
{ input_index += (linear->in_used - linear->in_count) / linear->channels ;
linear->in_used = linear->in_count ;
} ;
@@ -127,7 +143,7 @@ linear_process (SRC_PRIVATE *psrc, SRC_DATA *data)
data->output_frames_gen = linear->out_gen / linear->channels ;
return SRC_ERR_NO_ERROR ;
} /* linear_process */
} /* linear_vari_process */
/*------------------------------------------------------------------------------
*/
@@ -175,7 +191,8 @@ linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
linear->linear_magic_marker = LINEAR_MAGIC_MARKER ;
linear->channels = psrc->channels ;
psrc->process = linear_process ;
psrc->const_process = linear_vari_process ;
psrc->vari_process = linear_vari_process ;
psrc->reset = linear_reset ;
linear_reset (psrc) ;
@@ -194,13 +211,9 @@ linear_reset (SRC_PRIVATE *psrc)
if (linear == NULL)
return ;
linear->channels = psrc->channels ;
linear->reset = 1 ;
memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ;
} /* linear_reset */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 7eac3103-3d84-45d3-8bbd-f409c2b2d1a9
*/

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,12 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,31 +32,14 @@
#define SINC_MAGIC_MARKER MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ')
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
/*========================================================================================
** Macros for handling the index into the array for the filter.
** Double precision floating point is not accurate enough so use a 64 bit
** fixed point value instead. SHIFT_BITS (current value of 48) is the number
** of bits to the right of the decimal point.
** The rest of the macros are for retrieving the fractional and integer parts
** and for converting floats and ints to the fixed point format or from the
** fixed point type back to integers and floats.
*/
#define MAKE_INCREMENT_T(x) ((increment_t) (x))
#define SHIFT_BITS 16
#define SHIFT_BITS 12
#define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS))
#define DOUBLE_TO_FP(x) (lrint ((x) * FP_ONE))
#define INT_TO_FP(x) (((increment_t) (x)) << SHIFT_BITS)
#define FP_FRACTION_PART(x) ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1))
#define FP_INTEGER_PART(x) ((x) & (((increment_t) -1) << SHIFT_BITS))
#define FP_TO_INT(x) (((x) >> SHIFT_BITS))
#define FP_TO_DOUBLE(x) (FP_FRACTION_PART (x) / FP_ONE)
#define INV_FP_ONE (1.0 / FP_ONE)
/*========================================================================================
*/
@@ -58,13 +47,9 @@
typedef int32_t increment_t ;
typedef float coeff_t ;
enum
{
STATE_BUFFER_START = 101,
STATE_DATA_CONTINUE = 102,
STATE_BUFFER_END = 103,
STATE_FINISHED
} ;
#include "fastest_coeffs.h"
#include "mid_qual_coeffs.h"
#include "high_qual_coeffs.h"
typedef struct
{ int sinc_magic_marker ;
@@ -74,18 +59,16 @@ typedef struct
long out_count, out_gen ;
int coeff_half_len, index_inc ;
int has_diffs ;
double src_ratio, input_index ;
int coeff_len ;
coeff_t const *coeffs ;
int b_current, b_end, b_real_end, b_len ;
float buffer [1] ;
} SINC_FILTER ;
static int sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static double calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch) ;
@@ -93,20 +76,33 @@ static void prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_c
static void sinc_reset (SRC_PRIVATE *psrc) ;
static coeff_t const high_qual_coeffs [] =
{
#include "high_qual_coeffs.h"
} ; /* high_qual_coeffs */
static inline increment_t
double_to_fp (double x)
{ if (sizeof (increment_t) == 8)
return (llrint ((x) * FP_ONE)) ;
return (lrint ((x) * FP_ONE)) ;
} /* double_to_fp */
static coeff_t const mid_qual_coeffs [] =
{
#include "mid_qual_coeffs.h"
} ; /* mid_qual_coeffs */
static inline increment_t
int_to_fp (int x)
{ return (((increment_t) (x)) << SHIFT_BITS) ;
} /* int_to_fp */
static inline int
fp_to_int (increment_t x)
{ return (((x) >> SHIFT_BITS)) ;
} /* fp_to_int */
static inline increment_t
fp_fraction_part (increment_t x)
{ return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ;
} /* fp_fraction_part */
static inline double
fp_to_double (increment_t x)
{ return fp_fraction_part (x) * INV_FP_ONE ;
} /* fp_to_double */
static coeff_t const fastest_coeffs [] =
{
#include "fastest_coeffs.h"
} ; /* fastest_coeffs */
/*----------------------------------------------------------------------------------------
*/
@@ -123,6 +119,8 @@ sinc_get_name (int src_enum)
case SRC_SINC_FASTEST :
return "Fastest Sinc Interpolator" ;
default: break ;
} ;
return NULL ;
@@ -132,14 +130,17 @@ const char*
sinc_get_description (int src_enum)
{
switch (src_enum)
{ case SRC_SINC_BEST_QUALITY :
return "Band limited sinc interpolation, best quality, 97dB SNR, 96% BW." ;
{ case SRC_SINC_FASTEST :
return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
case SRC_SINC_MEDIUM_QUALITY :
return "Band limited sinc interpolation, medium quality, 97dB SNR, 90% BW." ;
return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ;
case SRC_SINC_FASTEST :
return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
case SRC_SINC_BEST_QUALITY :
return "Band limited sinc interpolation, best quality, 145dB SNR, 96% BW." ;
default :
break ;
} ;
return NULL ;
@@ -148,7 +149,8 @@ sinc_get_description (int src_enum)
int
sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
{ SINC_FILTER *filter, temp_filter ;
int count, bits ;
increment_t count ;
int bits ;
/* Quick sanity check. */
if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
@@ -167,32 +169,27 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
temp_filter.channels = psrc->channels ;
psrc->process = sinc_process ;
psrc->const_process = sinc_vari_process ;
psrc->vari_process = sinc_vari_process ;
psrc->reset = sinc_reset ;
switch (src_enum)
{ case SRC_SINC_BEST_QUALITY :
temp_filter.coeffs = high_qual_coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (high_qual_coeffs) - 1 ;
temp_filter.index_inc = 128 ;
temp_filter.has_diffs = SRC_FALSE ;
temp_filter.coeff_len = ARRAY_LEN (high_qual_coeffs) ;
{ case SRC_SINC_FASTEST :
temp_filter.coeffs = fastest_coeffs.coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 1 ;
temp_filter.index_inc = fastest_coeffs.increment ;
break ;
case SRC_SINC_MEDIUM_QUALITY :
temp_filter.coeffs = mid_qual_coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (mid_qual_coeffs) - 1 ;
temp_filter.index_inc = 128 ;
temp_filter.has_diffs = SRC_FALSE ;
temp_filter.coeff_len = ARRAY_LEN (mid_qual_coeffs) ;
temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 1 ;
temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
break ;
case SRC_SINC_FASTEST :
temp_filter.coeffs = fastest_coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs) - 1 ;
temp_filter.index_inc = 128 ;
temp_filter.has_diffs = SRC_FALSE ;
temp_filter.coeff_len = ARRAY_LEN (fastest_coeffs) ;
case SRC_SINC_BEST_QUALITY :
temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 1 ;
temp_filter.index_inc = slow_high_qual_coeffs.increment ;
break ;
default :
@@ -204,7 +201,8 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
** a better way. Need to look at prepare_data () at the same time.
*/
temp_filter.b_len = 1000 + 2 * lrint (0.5 + temp_filter.coeff_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
temp_filter.b_len = 1000 + 2 * lrint (0.5 + 2 * temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
temp_filter.b_len = MIN (temp_filter.b_len, 4096) ;
temp_filter.b_len *= temp_filter.channels ;
if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL)
@@ -218,8 +216,8 @@ sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
sinc_reset (psrc) ;
count = filter->coeff_half_len ;
for (bits = 0 ; (1 << bits) < count ; bits++)
count |= (1 << bits) ;
for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
count |= (MAKE_INCREMENT_T (1) << bits) ;
if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
return SRC_ERR_FILTER_LEN ;
@@ -251,7 +249,7 @@ sinc_reset (SRC_PRIVATE *psrc)
*/
static int
sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data)
sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ SINC_FILTER *filter ;
double input_index, src_ratio, count, float_increment, terminate, rem ;
increment_t increment, start_filter_index ;
@@ -283,7 +281,7 @@ sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data)
input_index = psrc->last_position ;
float_increment = filter->index_inc ;
rem = fmod (input_index, 1.0) ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
@@ -309,26 +307,26 @@ sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data)
break ;
} ;
if (fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / (filter->out_count - 1) ;
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
float_increment = filter->index_inc * 1.0 ;
if (src_ratio < 1.0)
float_increment = filter->index_inc * src_ratio ;
increment = DOUBLE_TO_FP (float_increment) ;
increment = double_to_fp (float_increment) ;
start_filter_index = DOUBLE_TO_FP (input_index * float_increment) ;
start_filter_index = double_to_fp (input_index * float_increment) ;
for (ch = 0 ; ch < filter->channels ; ch++)
{ data->data_out [filter->out_gen] = (float_increment / filter->index_inc) *
calc_output (filter, increment, start_filter_index, ch) ;
{ data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
calc_output (filter, increment, start_filter_index, ch)) ;
filter->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod (input_index, 1.0) ;
rem = fmod_one (input_index) ;
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
input_index = rem ;
@@ -343,7 +341,7 @@ sinc_process (SRC_PRIVATE *psrc, SRC_DATA *data)
data->output_frames_gen = filter->out_gen / filter->channels ;
return SRC_ERR_NO_ERROR ;
} /* sinc_process */
} /* sinc_vari_process */
/*----------------------------------------------------------------------------------------
*/
@@ -423,22 +421,22 @@ calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filte
int data_index, coeff_count, indx ;
/* Convert input parameters into fixed point. */
max_filter_index = INT_TO_FP (filter->coeff_half_len) ;
max_filter_index = int_to_fp (filter->coeff_half_len) ;
/* First apply the left half of the filter. */
filter_index = start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current - filter->channels * coeff_count ;
data_index = filter->b_current - filter->channels * coeff_count + ch ;
left = 0.0 ;
do
{ fraction = FP_TO_DOUBLE (filter_index) ;
indx = FP_TO_INT (filter_index) ;
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
left += icoeff * filter->buffer [data_index + ch] ;
left += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index + filter->channels ;
@@ -449,16 +447,16 @@ calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filte
filter_index = increment - start_filter_index ;
coeff_count = (max_filter_index - filter_index) / increment ;
filter_index = filter_index + coeff_count * increment ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) ;
data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ;
right = 0.0 ;
do
{ fraction = FP_TO_DOUBLE (filter_index) ;
indx = FP_TO_INT (filter_index) ;
{ fraction = fp_to_double (filter_index) ;
indx = fp_to_int (filter_index) ;
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
right += icoeff * filter->buffer [data_index + ch] ;
right += icoeff * filter->buffer [data_index] ;
filter_index -= increment ;
data_index = data_index - filter->channels ;
@@ -468,11 +466,3 @@ calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filte
return (left + right) ;
} /* calc_output */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: db8efe06-2fbd-487e-be8f-bfc01e68c19f
*/

View File

@@ -1,5 +1,5 @@
/*
** Copyright (C) 2002-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -16,6 +16,12 @@
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
/*
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
** use license for this code is available, please see:
** http://www.mega-nerd.com/SRC/procedure.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -24,7 +30,7 @@
#include "float_cast.h"
#include "common.h"
static int zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static int zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
static void zoh_reset (SRC_PRIVATE *psrc) ;
/*========================================================================================
@@ -35,6 +41,7 @@ static void zoh_reset (SRC_PRIVATE *psrc) ;
typedef struct
{ int zoh_magic_marker ;
int channels ;
int reset ;
long in_count, in_used ;
long out_count, out_gen ;
float last_value [1] ;
@@ -44,9 +51,9 @@ typedef struct
*/
static int
zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data)
zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
{ ZOH_DATA *zoh ;
double src_ratio, input_index ;
double src_ratio, input_index, rem ;
int ch ;
if (psrc->private_data == NULL)
@@ -54,6 +61,13 @@ zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data)
zoh = (ZOH_DATA*) psrc->private_data ;
if (zoh->reset)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < zoh->channels ; ch++)
zoh->last_value [ch] = data->data_in [ch] ;
zoh->reset = 0 ;
} ;
zoh->in_count = data->input_frames * zoh->channels ;
zoh->out_count = data->output_frames * zoh->channels ;
zoh->in_used = zoh->out_gen = 0 ;
@@ -67,8 +81,8 @@ zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data)
if (zoh->in_used + zoh->channels * input_index >= zoh->in_count)
break ;
if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / (zoh->out_count - 1) ;
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
for (ch = 0 ; ch < zoh->channels ; ch++)
{ data->data_out [zoh->out_gen] = zoh->last_value [ch] ;
@@ -79,14 +93,15 @@ zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data)
input_index += 1.0 / src_ratio ;
} ;
zoh->in_used += zoh->channels * lrint (floor (input_index)) ;
input_index -= floor (input_index) ;
rem = fmod_one (input_index) ;
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (zoh->out_gen < zoh->out_count && zoh->in_used + zoh->channels * input_index <= zoh->in_count)
{
if (fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / (zoh->out_count - 1) ;
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
for (ch = 0 ; ch < zoh->channels ; ch++)
{ data->data_out [zoh->out_gen] = data->data_in [zoh->in_used - zoh->channels + ch] ;
@@ -95,13 +110,14 @@ zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data)
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
zoh->in_used += zoh->channels * lrint (floor (input_index)) ;
input_index -= floor (input_index) ;
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (zoh->in_used > zoh->in_count)
{ input_index += zoh->in_used - zoh->in_count ;
{ input_index += (zoh->in_used - zoh->in_count) / zoh->channels ;
zoh->in_used = zoh->in_count ;
} ;
@@ -118,7 +134,7 @@ zoh_process (SRC_PRIVATE *psrc, SRC_DATA *data)
data->output_frames_gen = zoh->out_gen / zoh->channels ;
return SRC_ERR_NO_ERROR ;
} /* zoh_process */
} /* zoh_vari_process */
/*------------------------------------------------------------------------------
*/
@@ -166,7 +182,8 @@ zoh_set_converter (SRC_PRIVATE *psrc, int src_enum)
zoh->zoh_magic_marker = ZOH_MAGIC_MARKER ;
zoh->channels = psrc->channels ;
psrc->process = zoh_process ;
psrc->const_process = zoh_vari_process ;
psrc->vari_process = zoh_vari_process ;
psrc->reset = zoh_reset ;
zoh_reset (psrc) ;
@@ -186,15 +203,9 @@ zoh_reset (SRC_PRIVATE *psrc)
return ;
zoh->channels = psrc->channels ;
zoh->reset = 1 ;
memset (zoh->last_value, 0, sizeof (zoh->last_value [0]) * zoh->channels) ;
return ;
} /* zoh_reset */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 808e62f8-2e4a-44a6-840f-180a3e41af01
*/