Add 'contrib/libsamplerate/' from commit '69a539a327ef8d78260056c5394363569b5751ef'

Initial import. Needed by upcoming patches which port virtual_oss to
base.

Sponsored by:	The FreeBSD Foundation

git-subtree-dir: contrib/libsamplerate
git-subtree-mainline: e9dd9f95f8
git-subtree-split: 69a539a327
This commit is contained in:
Christos Margiolis 2025-08-01 16:01:12 +03:00
commit 1480c0b3f2
10 changed files with 368023 additions and 0 deletions

View file

@ -0,0 +1,25 @@
Copyright (c) 2012-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,185 @@
/*
** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com>
** All rights reserved.
**
** This code is released under 2-clause BSD license. Please see the
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
*/
#ifndef COMMON_H_INCLUDED
#define COMMON_H_INCLUDED
#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#ifdef HAVE_VISIBILITY
#define LIBSAMPLERATE_DLL_PRIVATE __attribute__ ((visibility ("hidden")))
#elif defined (__APPLE__)
#define LIBSAMPLERATE_DLL_PRIVATE __private_extern__
#else
#define LIBSAMPLERATE_DLL_PRIVATE
#endif
#define SRC_MAX_RATIO 256
#define SRC_MAX_RATIO_STR "256"
#define SRC_MIN_RATIO_DIFF (1e-20)
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#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))
/*
** Inspiration : http://sourcefrog.net/weblog/software/languages/C/unused.html
*/
#ifdef UNUSED
#elif defined (__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
#elif defined (__LCLINT__)
# define UNUSED(x) /*@unused@*/ x
#else
# define UNUSED(x) x
#endif
#ifdef __GNUC__
# define WARN_UNUSED __attribute__ ((warn_unused_result))
#else
# define WARN_UNUSED
#endif
#include "samplerate.h"
enum
{ SRC_FALSE = 0,
SRC_TRUE = 1,
} ;
enum SRC_MODE
{
SRC_MODE_PROCESS = 0,
SRC_MODE_CALLBACK = 1
} ;
typedef enum SRC_ERROR
{
SRC_ERR_NO_ERROR = 0,
SRC_ERR_MALLOC_FAILED,
SRC_ERR_BAD_STATE,
SRC_ERR_BAD_DATA,
SRC_ERR_BAD_DATA_PTR,
SRC_ERR_NO_PRIVATE,
SRC_ERR_BAD_SRC_RATIO,
SRC_ERR_BAD_PROC_PTR,
SRC_ERR_SHIFT_BITS,
SRC_ERR_FILTER_LEN,
SRC_ERR_BAD_CONVERTER,
SRC_ERR_BAD_CHANNEL_COUNT,
SRC_ERR_SINC_BAD_BUFFER_LEN,
SRC_ERR_SIZE_INCOMPATIBILITY,
SRC_ERR_BAD_PRIV_PTR,
SRC_ERR_BAD_SINC_STATE,
SRC_ERR_DATA_OVERLAP,
SRC_ERR_BAD_CALLBACK,
SRC_ERR_BAD_MODE,
SRC_ERR_NULL_CALLBACK,
SRC_ERR_NO_VARIABLE_RATIO,
SRC_ERR_SINC_PREPARE_DATA_BAD_LEN,
SRC_ERR_BAD_INTERNAL_STATE,
/* This must be the last error number. */
SRC_ERR_MAX_ERROR
} SRC_ERROR ;
typedef struct SRC_STATE_VT_tag
{
/* Varispeed process function. */
SRC_ERROR (*vari_process) (SRC_STATE *state, SRC_DATA *data) ;
/* Constant speed process function. */
SRC_ERROR (*const_process) (SRC_STATE *state, SRC_DATA *data) ;
/* State reset. */
void (*reset) (SRC_STATE *state) ;
/* State clone. */
SRC_STATE *(*copy) (SRC_STATE *state) ;
/* State close. */
void (*close) (SRC_STATE *state) ;
} SRC_STATE_VT ;
struct SRC_STATE_tag
{
SRC_STATE_VT *vt ;
double last_ratio, last_position ;
SRC_ERROR error ;
int channels ;
/* SRC_MODE_PROCESS or SRC_MODE_CALLBACK */
enum SRC_MODE mode ;
/* Data specific to SRC_MODE_CALLBACK. */
src_callback_t callback_func ;
void *user_callback_data ;
long saved_frames ;
const float *saved_data ;
/* Pointer to data to converter specific data. */
void *private_data ;
} ;
/* In src_sinc.c */
const char* sinc_get_name (int src_enum) ;
const char* sinc_get_description (int src_enum) ;
SRC_STATE *sinc_state_new (int converter_type, int channels, SRC_ERROR *error) ;
/* In src_linear.c */
const char* linear_get_name (int src_enum) ;
const char* linear_get_description (int src_enum) ;
SRC_STATE *linear_state_new (int channels, SRC_ERROR *error) ;
/* In src_zoh.c */
const char* zoh_get_name (int src_enum) ;
const char* zoh_get_description (int src_enum) ;
SRC_STATE *zoh_state_new (int channels, SRC_ERROR *error) ;
/*----------------------------------------------------------
** 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 */
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 */
#endif /* COMMON_H_INCLUDED */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,532 @@
/*
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
** All rights reserved.
**
** This code is released under 2-clause BSD license. Please see the
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "samplerate.h"
#include "common.h"
static SRC_STATE *psrc_set_converter (int converter_type, int channels, int *error) ;
SRC_STATE *
src_new (int converter_type, int channels, int *error)
{
return psrc_set_converter (converter_type, channels, error) ;
} /* src_new */
#if 0
SRC_STATE*
src_clone (SRC_STATE* orig, int *error)
{
if (!orig)
{
if (error)
*error = SRC_ERR_BAD_STATE ;
return NULL ;
}
if (error)
*error = SRC_ERR_NO_ERROR ;
SRC_STATE *state = orig->vt->copy (orig) ;
if (!state)
if (error)
*error = SRC_ERR_MALLOC_FAILED ;
return state ;
}
SRC_STATE*
src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data)
{ SRC_STATE *state ;
if (func == NULL)
{ if (error)
*error = SRC_ERR_BAD_CALLBACK ;
return NULL ;
} ;
if (error != NULL)
*error = 0 ;
if ((state = src_new (converter_type, channels, error)) == NULL)
return NULL ;
src_reset (state) ;
state->mode = SRC_MODE_CALLBACK ;
state->callback_func = func ;
state->user_callback_data = cb_data ;
return state ;
} /* src_callback_new */
#endif
SRC_STATE *
src_delete (SRC_STATE *state)
{
if (state)
state->vt->close (state) ;
return NULL ;
} /* src_state */
int
src_process (SRC_STATE *state, SRC_DATA *data)
{
int error ;
if (state == NULL)
return SRC_ERR_BAD_STATE ;
if (state->mode != SRC_MODE_PROCESS)
return SRC_ERR_BAD_MODE ;
/* Check for valid SRC_DATA first. */
if (data == NULL)
return SRC_ERR_BAD_DATA ;
/* And that data_in and data_out are valid. */
if ((data->data_in == NULL && data->input_frames > 0)
|| (data->data_out == NULL && data->output_frames > 0))
return SRC_ERR_BAD_DATA_PTR ;
/* Check src_ratio is in range. */
if (is_bad_src_ratio (data->src_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
if (data->input_frames < 0)
data->input_frames = 0 ;
if (data->output_frames < 0)
data->output_frames = 0 ;
if (data->data_in < data->data_out)
{ if (data->data_in + data->input_frames * state->channels > data->data_out)
{ /*-printf ("\n\ndata_in: %p data_out: %p\n",
(void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/
return SRC_ERR_DATA_OVERLAP ;
} ;
}
else if (data->data_out + data->output_frames * state->channels > data->data_in)
{ /*-printf ("\n\ndata_in : %p ouput frames: %ld data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ;
printf ("data_out: %p (%p) data_in: %p\n", (void*) data->data_out,
(void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/
return SRC_ERR_DATA_OVERLAP ;
} ;
/* Set the input and output counts to zero. */
data->input_frames_used = 0 ;
data->output_frames_gen = 0 ;
/* Special case for when last_ratio has not been set. */
if (state->last_ratio < (1.0 / SRC_MAX_RATIO))
state->last_ratio = data->src_ratio ;
/* Now process. */
if (fabs (state->last_ratio - data->src_ratio) < 1e-15)
error = state->vt->const_process (state, data) ;
else
error = state->vt->vari_process (state, data) ;
return error ;
} /* src_process */
#if 0
long
src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)
{
SRC_DATA src_data ;
long output_frames_gen ;
int error = 0 ;
if (state == NULL)
return 0 ;
if (frames <= 0)
return 0 ;
if (state->mode != SRC_MODE_CALLBACK)
{ state->error = SRC_ERR_BAD_MODE ;
return 0 ;
} ;
if (state->callback_func == NULL)
{ state->error = SRC_ERR_NULL_CALLBACK ;
return 0 ;
} ;
memset (&src_data, 0, sizeof (src_data)) ;
/* Check src_ratio is in range. */
if (is_bad_src_ratio (src_ratio))
{ state->error = SRC_ERR_BAD_SRC_RATIO ;
return 0 ;
} ;
/* Switch modes temporarily. */
src_data.src_ratio = src_ratio ;
src_data.data_out = data ;
src_data.output_frames = frames ;
src_data.data_in = state->saved_data ;
src_data.input_frames = state->saved_frames ;
output_frames_gen = 0 ;
while (output_frames_gen < frames)
{ /* Use a dummy array for the case where the callback function
** returns without setting the ptr.
*/
float dummy [1] ;
if (src_data.input_frames == 0)
{ float *ptr = dummy ;
src_data.input_frames = state->callback_func (state->user_callback_data, &ptr) ;
src_data.data_in = ptr ;
if (src_data.input_frames == 0)
src_data.end_of_input = 1 ;
} ;
/*
** Now call process function. However, we need to set the mode
** to SRC_MODE_PROCESS first and when we return set it back to
** SRC_MODE_CALLBACK.
*/
state->mode = SRC_MODE_PROCESS ;
error = src_process (state, &src_data) ;
state->mode = SRC_MODE_CALLBACK ;
if (error != 0)
break ;
src_data.data_in += src_data.input_frames_used * state->channels ;
src_data.input_frames -= src_data.input_frames_used ;
src_data.data_out += src_data.output_frames_gen * state->channels ;
src_data.output_frames -= src_data.output_frames_gen ;
output_frames_gen += src_data.output_frames_gen ;
if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0)
break ;
} ;
state->saved_data = src_data.data_in ;
state->saved_frames = src_data.input_frames ;
if (error != 0)
{ state->error = (SRC_ERROR) error ;
return 0 ;
} ;
return output_frames_gen ;
} /* src_callback_read */
/*==========================================================================
*/
int
src_set_ratio (SRC_STATE *state, double new_ratio)
{
if (state == NULL)
return SRC_ERR_BAD_STATE ;
if (is_bad_src_ratio (new_ratio))
return SRC_ERR_BAD_SRC_RATIO ;
state->last_ratio = new_ratio ;
return SRC_ERR_NO_ERROR ;
} /* src_set_ratio */
int
src_get_channels (SRC_STATE *state)
{
if (state == NULL)
return -SRC_ERR_BAD_STATE ;
return state->channels ;
} /* src_get_channels */
int
src_reset (SRC_STATE *state)
{
if (state == NULL)
return SRC_ERR_BAD_STATE ;
state->vt->reset (state) ;
state->last_position = 0.0 ;
state->last_ratio = 0.0 ;
state->saved_data = NULL ;
state->saved_frames = 0 ;
state->error = SRC_ERR_NO_ERROR ;
return SRC_ERR_NO_ERROR ;
} /* src_reset */
/*==============================================================================
** Control functions.
*/
const char *
src_get_name (int converter_type)
{ const char *desc ;
if ((desc = sinc_get_name (converter_type)) != NULL)
return desc ;
if ((desc = zoh_get_name (converter_type)) != NULL)
return desc ;
if ((desc = linear_get_name (converter_type)) != NULL)
return desc ;
return NULL ;
} /* src_get_name */
const char *
src_get_description (int converter_type)
{ const char *desc ;
if ((desc = sinc_get_description (converter_type)) != NULL)
return desc ;
if ((desc = zoh_get_description (converter_type)) != NULL)
return desc ;
if ((desc = linear_get_description (converter_type)) != NULL)
return desc ;
return NULL ;
} /* src_get_description */
const char *
src_get_version (void)
{ return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ;
} /* src_get_version */
int
src_is_valid_ratio (double ratio)
{
if (is_bad_src_ratio (ratio))
return SRC_FALSE ;
return SRC_TRUE ;
} /* src_is_valid_ratio */
/*==============================================================================
** Error reporting functions.
*/
int
src_error (SRC_STATE *state)
{ if (state)
return state->error ;
return SRC_ERR_NO_ERROR ;
} /* src_error */
const char*
src_strerror (int error)
{
switch (error)
{ case SRC_ERR_NO_ERROR :
return "No error." ;
case SRC_ERR_MALLOC_FAILED :
return "Malloc failed." ;
case SRC_ERR_BAD_STATE :
return "SRC_STATE pointer is NULL." ;
case SRC_ERR_BAD_DATA :
return "SRC_DATA pointer is NULL." ;
case SRC_ERR_BAD_DATA_PTR :
return "SRC_DATA->data_out or SRC_DATA->data_in is NULL." ;
case SRC_ERR_NO_PRIVATE :
return "Internal error. No private data." ;
case SRC_ERR_BAD_SRC_RATIO :
return "SRC ratio outside [1/" SRC_MAX_RATIO_STR ", " SRC_MAX_RATIO_STR "] range." ;
case SRC_ERR_BAD_SINC_STATE :
return "src_process() called without reset after end_of_input." ;
case SRC_ERR_BAD_PROC_PTR :
return "Internal error. No process pointer." ;
case SRC_ERR_SHIFT_BITS :
return "Internal error. SHIFT_BITS too large." ;
case SRC_ERR_FILTER_LEN :
return "Internal error. Filter length too large." ;
case SRC_ERR_BAD_CONVERTER :
return "Bad converter number." ;
case SRC_ERR_BAD_CHANNEL_COUNT :
return "Channel count must be >= 1." ;
case SRC_ERR_SINC_BAD_BUFFER_LEN :
return "Internal error. Bad buffer length. Please report this." ;
case SRC_ERR_SIZE_INCOMPATIBILITY :
return "Internal error. Input data / internal buffer size difference. Please report this." ;
case SRC_ERR_BAD_PRIV_PTR :
return "Internal error. Private pointer is NULL. Please report this." ;
case SRC_ERR_DATA_OVERLAP :
return "Input and output data arrays overlap." ;
case SRC_ERR_BAD_CALLBACK :
return "Supplied callback function pointer is NULL." ;
case SRC_ERR_BAD_MODE :
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_SINC_PREPARE_DATA_BAD_LEN :
return "Internal error : Bad length in prepare_data ()." ;
case SRC_ERR_BAD_INTERNAL_STATE :
return "Error : Someone is trampling on my internal state." ;
case SRC_ERR_MAX_ERROR :
return "Placeholder. No error defined for this error number." ;
default : break ;
}
return NULL ;
} /* src_strerror */
/*==============================================================================
** Simple interface for performing a single conversion from input buffer to
** output buffer at a fixed conversion ratio.
*/
int
src_simple (SRC_DATA *src_data, int converter, int channels)
{ SRC_STATE *src_state ;
int error ;
if ((src_state = src_new (converter, channels, &error)) == NULL)
return error ;
src_data->end_of_input = 1 ; /* Only one buffer worth of input. */
error = src_process (src_state, src_data) ;
src_delete (src_state) ;
return error ;
} /* src_simple */
void
src_short_to_float_array (const short *in, float *out, int len)
{
for (int i = 0 ; i < len ; i++)
{ out [i] = (float) (in [i] / (1.0 * 0x8000)) ;
} ;
return ;
} /* src_short_to_float_array */
void
src_float_to_short_array (const float *in, short *out, int len)
{
for (int i = 0 ; i < len ; i++)
{ float scaled_value ;
scaled_value = in [i] * 32768.f ;
if (scaled_value >= 32767.f)
out [i] = 32767 ;
else if (scaled_value <= -32768.f)
out [i] = -32768 ;
else
out [i] = (short) (lrintf (scaled_value)) ;
}
} /* src_float_to_short_array */
void
src_int_to_float_array (const int *in, float *out, int len)
{
for (int i = 0 ; i < len ; i++)
{ out [i] = (float) (in [i] / (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 ;
for (int i = 0 ; i < len ; i++)
{ scaled_value = in [i] * (8.0 * 0x10000000) ;
#if CPU_CLIPS_POSITIVE == 0
if (scaled_value >= (1.0 * 0x7FFFFFFF))
{ out [i] = 0x7fffffff ;
continue ;
} ;
#endif
#if CPU_CLIPS_NEGATIVE == 0
if (scaled_value <= (-8.0 * 0x10000000))
{ out [i] = -1 - 0x7fffffff ;
continue ;
} ;
#endif
out [i] = (int) lrint (scaled_value) ;
} ;
} /* src_float_to_int_array */
#endif
/*==============================================================================
** Private functions.
*/
static SRC_STATE *
psrc_set_converter (int converter_type, int channels, int *error)
{
SRC_ERROR temp_error;
SRC_STATE *state ;
switch (converter_type)
{
#ifdef ENABLE_SINC_BEST_CONVERTER
case SRC_SINC_BEST_QUALITY :
state = sinc_state_new (converter_type, channels, &temp_error) ;
break ;
#endif
#ifdef ENABLE_SINC_MEDIUM_CONVERTER
case SRC_SINC_MEDIUM_QUALITY :
state = sinc_state_new (converter_type, channels, &temp_error) ;
break ;
#endif
#ifdef ENABLE_SINC_FAST_CONVERTER
case SRC_SINC_FASTEST :
state = sinc_state_new (converter_type, channels, &temp_error) ;
break ;
#endif
case SRC_ZERO_ORDER_HOLD :
state = zoh_state_new (channels, &temp_error) ;
break ;
case SRC_LINEAR :
state = linear_state_new (channels, &temp_error) ;
break ;
default :
temp_error = SRC_ERR_BAD_CONVERTER ;
state = NULL ;
break ;
}
if (error)
*error = (int) temp_error ;
return state ;
} /* psrc_set_converter */

View file

@ -0,0 +1,189 @@
/*
** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
** All rights reserved.
**
** This code is released under 2-clause BSD license. Please see the
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
*/
/*
** API documentation is available here:
** http://libsndfile.github.io/libsamplerate/api.html
*/
#ifndef SAMPLERATE_H
#define SAMPLERATE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Opaque data type SRC_STATE. */
typedef struct SRC_STATE_tag SRC_STATE ;
/* SRC_DATA is used to pass data to src_simple() and src_process(). */
typedef struct
{ const float *data_in ;
float *data_out ;
long input_frames, output_frames ;
long input_frames_used, output_frames_gen ;
int end_of_input ;
double src_ratio ;
} SRC_DATA ;
/*
** User supplied callback function type for use with src_callback_new()
** and src_callback_read(). First parameter is the same pointer that was
** passed into src_callback_new(). Second parameter is pointer to a
** pointer. The user supplied callback function must modify *data to
** point to the start of the user supplied float array. The user supplied
** function must return the number of frames that **data points to.
*/
typedef long (*src_callback_t) (void *cb_data, float **data) ;
/*
** Standard initialisation function : return an anonymous pointer to the
** internal state of the converter. Choose a converter from the enums below.
** Error returned in *error.
*/
SRC_STATE* src_new (int converter_type, int channels, int *error) ;
/*
** Clone a handle : return an anonymous pointer to a new converter
** containing the same internal state as orig. Error returned in *error.
*/
SRC_STATE* src_clone (SRC_STATE* orig, int *error) ;
/*
** Initilisation for callback based API : return an anonymous pointer to the
** internal state of the converter. Choose a converter from the enums below.
** The cb_data pointer can point to any data or be set to NULL. Whatever the
** value, when processing, user supplied function "func" gets called with
** cb_data as first parameter.
*/
SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels,
int *error, void* cb_data) ;
/*
** Cleanup all internal allocations.
** Always returns NULL.
*/
SRC_STATE* src_delete (SRC_STATE *state) ;
/*
** Standard processing function.
** Returns non zero on error.
*/
int src_process (SRC_STATE *state, SRC_DATA *data) ;
/*
** Callback based processing function. Read up to frames worth of data from
** the converter int *data and return frames read or -1 on error.
*/
long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) ;
/*
** Simple interface for performing a single conversion from input buffer to
** output buffer at a fixed conversion ratio.
** Simple interface does not require initialisation as it can only operate on
** a single buffer worth of audio.
*/
int src_simple (SRC_DATA *data, int converter_type, int channels) ;
/*
** This library contains a number of different sample rate converters,
** numbered 0 through N.
**
** Return a string giving either a name or a more full description of each
** sample rate converter or NULL if no sample rate converter exists for
** the given value. The converters are sequentially numbered from 0 to N.
*/
const char *src_get_name (int converter_type) ;
const char *src_get_description (int converter_type) ;
const char *src_get_version (void) ;
/*
** Set a new SRC ratio. This allows step responses
** in the conversion ratio.
** Returns non zero on error.
*/
int src_set_ratio (SRC_STATE *state, double new_ratio) ;
/*
** Get the current channel count.
** Returns negative on error, positive channel count otherwise
*/
int src_get_channels (SRC_STATE *state) ;
/*
** Reset the internal SRC state.
** Does not modify the quality settings.
** Does not free any memory allocations.
** Returns non zero on error.
*/
int src_reset (SRC_STATE *state) ;
/*
** Return TRUE if ratio is a valid conversion ratio, FALSE
** otherwise.
*/
int src_is_valid_ratio (double ratio) ;
/*
** Return an error number.
*/
int src_error (SRC_STATE *state) ;
/*
** Convert the error number into a string.
*/
const char* src_strerror (int error) ;
/*
** The following enums can be used to set the interpolator type
** using the function src_set_converter().
*/
enum
{
SRC_SINC_BEST_QUALITY = 0,
SRC_SINC_MEDIUM_QUALITY = 1,
SRC_SINC_FASTEST = 2,
SRC_ZERO_ORDER_HOLD = 3,
SRC_LINEAR = 4,
} ;
/*
** Extra helper functions for converting from short to float and
** back again.
*/
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" */
#endif /* __cplusplus */
#endif /* SAMPLERATE_H */

View file

@ -0,0 +1,303 @@
/*
** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com>
** All rights reserved.
**
** This code is released under 2-clause BSD license. Please see the
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "common.h"
static SRC_ERROR linear_vari_process (SRC_STATE *state, SRC_DATA *data) ;
static void linear_reset (SRC_STATE *state) ;
static SRC_STATE *linear_copy (SRC_STATE *state) ;
static void linear_close (SRC_STATE *state) ;
/*========================================================================================
*/
#define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
#define SRC_DEBUG 0
typedef struct
{ int linear_magic_marker ;
bool dirty ;
long in_count, in_used ;
long out_count, out_gen ;
float *last_value ;
} LINEAR_DATA ;
static SRC_STATE_VT linear_state_vt =
{
linear_vari_process,
linear_vari_process,
linear_reset,
linear_copy,
linear_close
} ;
/*----------------------------------------------------------------------------------------
*/
static SRC_ERROR
linear_vari_process (SRC_STATE *state, SRC_DATA *data)
{ LINEAR_DATA *priv ;
double src_ratio, input_index, rem ;
int ch ;
if (data->input_frames <= 0)
return SRC_ERR_NO_ERROR ;
if (state->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
priv = (LINEAR_DATA*) state->private_data ;
if (!priv->dirty)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < state->channels ; ch++)
priv->last_value [ch] = data->data_in [ch] ;
priv->dirty = true ;
} ;
priv->in_count = data->input_frames * state->channels ;
priv->out_count = data->output_frames * state->channels ;
priv->in_used = priv->out_gen = 0 ;
src_ratio = state->last_ratio ;
if (is_bad_src_ratio (src_ratio))
return SRC_ERR_BAD_INTERNAL_STATE ;
input_index = state->last_position ;
/* Calculate samples before first sample in input array. */
while (input_index < 1.0 && priv->out_gen < priv->out_count)
{
if (priv->in_used + state->channels * (1.0 + input_index) >= priv->in_count)
break ;
if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;
for (ch = 0 ; ch < state->channels ; ch++)
{ data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index *
((double) data->data_in [ch] - priv->last_value [ch])) ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
} ;
rem = fmod_one (input_index) ;
priv->in_used += state->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index < priv->in_count)
{
if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;
#if SRC_DEBUG
if (priv->in_used < state->channels && input_index < 1.0)
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, state->channels, input_index) ;
exit (1) ;
} ;
#endif
for (ch = 0 ; ch < state->channels ; ch++)
{ data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - state->channels + ch] + input_index *
((double) data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - state->channels + ch])) ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
priv->in_used += state->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (priv->in_used > priv->in_count)
{ input_index += (priv->in_used - priv->in_count) / state->channels ;
priv->in_used = priv->in_count ;
} ;
state->last_position = input_index ;
if (priv->in_used > 0)
for (ch = 0 ; ch < state->channels ; ch++)
priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ;
/* Save current ratio rather then target ratio. */
state->last_ratio = src_ratio ;
data->input_frames_used = priv->in_used / state->channels ;
data->output_frames_gen = priv->out_gen / state->channels ;
return SRC_ERR_NO_ERROR ;
} /* linear_vari_process */
/*------------------------------------------------------------------------------
*/
#if 0
LIBSAMPLERATE_DLL_PRIVATE const char*
linear_get_name (int src_enum)
{
if (src_enum == SRC_LINEAR)
return "Linear Interpolator" ;
return NULL ;
} /* linear_get_name */
LIBSAMPLERATE_DLL_PRIVATE const char*
linear_get_description (int src_enum)
{
if (src_enum == SRC_LINEAR)
return "Linear interpolator, very fast, poor quality." ;
return NULL ;
} /* linear_get_descrition */
#endif
static LINEAR_DATA *
linear_data_new (int channels)
{
assert (channels > 0) ;
LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;
if (priv)
{
priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;
priv->last_value = (float *) calloc (channels, sizeof (float)) ;
if (!priv->last_value)
{
free (priv) ;
priv = NULL ;
}
}
return priv ;
}
LIBSAMPLERATE_DLL_PRIVATE SRC_STATE *
linear_state_new (int channels, SRC_ERROR *error)
{
assert (channels > 0) ;
assert (error != NULL) ;
SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
if (!state)
{
*error = SRC_ERR_MALLOC_FAILED ;
return NULL ;
}
state->channels = channels ;
state->mode = SRC_MODE_PROCESS ;
state->private_data = linear_data_new (state->channels) ;
if (!state->private_data)
{
free (state) ;
*error = SRC_ERR_MALLOC_FAILED ;
return NULL ;
}
state->vt = &linear_state_vt ;
linear_reset (state) ;
*error = SRC_ERR_NO_ERROR ;
return state ;
}
/*===================================================================================
*/
static void
linear_reset (SRC_STATE *state)
{ LINEAR_DATA *priv = NULL ;
priv = (LINEAR_DATA*) state->private_data ;
if (priv == NULL)
return ;
priv->dirty = false ;
memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ;
return ;
} /* linear_reset */
SRC_STATE *
linear_copy (SRC_STATE *state)
{
assert (state != NULL) ;
if (state->private_data == NULL)
return NULL ;
SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
if (!to)
return NULL ;
memcpy (to, state, sizeof (SRC_STATE)) ;
LINEAR_DATA* from_priv = (LINEAR_DATA*) state->private_data ;
LINEAR_DATA *to_priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;
if (!to_priv)
{
free (to) ;
return NULL ;
}
memcpy (to_priv, from_priv, sizeof (LINEAR_DATA)) ;
to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ;
if (!to_priv->last_value)
{
free (to) ;
free (to_priv) ;
return NULL ;
}
memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ;
to->private_data = to_priv ;
return to ;
} /* linear_copy */
static void
linear_close (SRC_STATE *state)
{
if (state)
{
LINEAR_DATA *linear = (LINEAR_DATA *) state->private_data ;
if (linear)
{
if (linear->last_value)
{
free (linear->last_value) ;
linear->last_value = NULL ;
}
free (linear) ;
linear = NULL ;
}
free (state) ;
state = NULL ;
}
} /* linear_close */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,292 @@
/*
** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com>
** All rights reserved.
**
** This code is released under 2-clause BSD license. Please see the
** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "common.h"
static SRC_ERROR zoh_vari_process (SRC_STATE *state, SRC_DATA *data) ;
static void zoh_reset (SRC_STATE *state) ;
static SRC_STATE *zoh_copy (SRC_STATE *state) ;
static void zoh_close (SRC_STATE *state) ;
/*========================================================================================
*/
#define ZOH_MAGIC_MARKER MAKE_MAGIC ('s', 'r', 'c', 'z', 'o', 'h')
typedef struct
{ int zoh_magic_marker ;
bool dirty ;
long in_count, in_used ;
long out_count, out_gen ;
float *last_value ;
} ZOH_DATA ;
static SRC_STATE_VT zoh_state_vt =
{
zoh_vari_process,
zoh_vari_process,
zoh_reset,
zoh_copy,
zoh_close
} ;
/*----------------------------------------------------------------------------------------
*/
static SRC_ERROR
zoh_vari_process (SRC_STATE *state, SRC_DATA *data)
{ ZOH_DATA *priv ;
double src_ratio, input_index, rem ;
int ch ;
if (data->input_frames <= 0)
return SRC_ERR_NO_ERROR ;
if (state->private_data == NULL)
return SRC_ERR_NO_PRIVATE ;
priv = (ZOH_DATA*) state->private_data ;
if (!priv->dirty)
{ /* If we have just been reset, set the last_value data. */
for (ch = 0 ; ch < state->channels ; ch++)
priv->last_value [ch] = data->data_in [ch] ;
priv->dirty = true ;
} ;
priv->in_count = data->input_frames * state->channels ;
priv->out_count = data->output_frames * state->channels ;
priv->in_used = priv->out_gen = 0 ;
src_ratio = state->last_ratio ;
if (is_bad_src_ratio (src_ratio))
return SRC_ERR_BAD_INTERNAL_STATE ;
input_index = state->last_position ;
/* Calculate samples before first sample in input array. */
while (input_index < 1.0 && priv->out_gen < priv->out_count)
{
if (priv->in_used + state->channels * input_index >= priv->in_count)
break ;
if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;
for (ch = 0 ; ch < state->channels ; ch++)
{ data->data_out [priv->out_gen] = priv->last_value [ch] ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
} ;
rem = fmod_one (input_index) ;
priv->in_used += state->channels * lrint (input_index - rem) ;
input_index = rem ;
/* Main processing loop. */
while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index <= priv->in_count)
{
if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;
for (ch = 0 ; ch < state->channels ; ch++)
{ data->data_out [priv->out_gen] = data->data_in [priv->in_used - state->channels + ch] ;
priv->out_gen ++ ;
} ;
/* Figure out the next index. */
input_index += 1.0 / src_ratio ;
rem = fmod_one (input_index) ;
priv->in_used += state->channels * lrint (input_index - rem) ;
input_index = rem ;
} ;
if (priv->in_used > priv->in_count)
{ input_index += (priv->in_used - priv->in_count) / state->channels ;
priv->in_used = priv->in_count ;
} ;
state->last_position = input_index ;
if (priv->in_used > 0)
for (ch = 0 ; ch < state->channels ; ch++)
priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ;
/* Save current ratio rather then target ratio. */
state->last_ratio = src_ratio ;
data->input_frames_used = priv->in_used / state->channels ;
data->output_frames_gen = priv->out_gen / state->channels ;
return SRC_ERR_NO_ERROR ;
} /* zoh_vari_process */
/*------------------------------------------------------------------------------
*/
#if 0
LIBSAMPLERATE_DLL_PRIVATE const char*
zoh_get_name (int src_enum)
{
if (src_enum == SRC_ZERO_ORDER_HOLD)
return "ZOH Interpolator" ;
return NULL ;
} /* zoh_get_name */
LIBSAMPLERATE_DLL_PRIVATE const char*
zoh_get_description (int src_enum)
{
if (src_enum == SRC_ZERO_ORDER_HOLD)
return "Zero order hold interpolator, very fast, poor quality." ;
return NULL ;
} /* zoh_get_descrition */
#endif
static ZOH_DATA *
zoh_data_new (int channels)
{
assert (channels > 0) ;
ZOH_DATA *priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ;
if (priv)
{
priv->zoh_magic_marker = ZOH_MAGIC_MARKER ;
priv->last_value = (float *) calloc (channels, sizeof (float)) ;
if (!priv->last_value)
{
free (priv) ;
priv = NULL ;
}
}
return priv ;
}
LIBSAMPLERATE_DLL_PRIVATE SRC_STATE *
zoh_state_new (int channels, SRC_ERROR *error)
{
assert (channels > 0) ;
assert (error != NULL) ;
SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
if (!state)
{
*error = SRC_ERR_MALLOC_FAILED ;
return NULL ;
}
state->channels = channels ;
state->mode = SRC_MODE_PROCESS ;
state->private_data = zoh_data_new (state->channels) ;
if (!state->private_data)
{
free (state) ;
*error = SRC_ERR_MALLOC_FAILED ;
return NULL ;
}
state->vt = &zoh_state_vt ;
zoh_reset (state) ;
*error = SRC_ERR_NO_ERROR ;
return state ;
}
/*===================================================================================
*/
static void
zoh_reset (SRC_STATE *state)
{ ZOH_DATA *priv ;
priv = (ZOH_DATA*) state->private_data ;
if (priv == NULL)
return ;
priv->dirty = false ;
memset (priv->last_value, 0, sizeof (float) * state->channels) ;
return ;
} /* zoh_reset */
static SRC_STATE *
zoh_copy (SRC_STATE *state)
{
assert (state != NULL) ;
if (state->private_data == NULL)
return NULL ;
SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
if (!to)
return NULL ;
memcpy (to, state, sizeof (SRC_STATE)) ;
ZOH_DATA* from_priv = (ZOH_DATA*) state->private_data ;
ZOH_DATA *to_priv = (ZOH_DATA *) calloc (1, sizeof (ZOH_DATA)) ;
if (!to_priv)
{
free (to) ;
return NULL ;
}
memcpy (to_priv, from_priv, sizeof (ZOH_DATA)) ;
to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ;
if (!to_priv->last_value)
{
free (to) ;
free (to_priv) ;
return NULL ;
}
memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ;
to->private_data = to_priv ;
return to ;
} /* zoh_copy */
static void
zoh_close (SRC_STATE *state)
{
if (state)
{
ZOH_DATA *zoh = (ZOH_DATA *) state->private_data ;
if (zoh)
{
if (zoh->last_value)
{
free (zoh->last_value) ;
zoh->last_value = NULL ;
}
free (zoh) ;
zoh = NULL ;
}
free (state) ;
state = NULL ;
}
} /* zoh_close */