Path: blob/main/contrib/libsamplerate/samplerate.c
39475 views
/*1** Copyright (c) 2002-2016, Erik de Castro Lopo <[email protected]>2** All rights reserved.3**4** This code is released under 2-clause BSD license. Please see the5** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING6*/78#ifdef HAVE_CONFIG_H9#include "config.h"10#endif1112#include <stdio.h>13#include <stdlib.h>14#include <string.h>15#include <math.h>1617#include "samplerate.h"18#include "common.h"1920static SRC_STATE *psrc_set_converter (int converter_type, int channels, int *error) ;212223SRC_STATE *24src_new (int converter_type, int channels, int *error)25{26return psrc_set_converter (converter_type, channels, error) ;27} /* src_new */2829#if 030SRC_STATE*31src_clone (SRC_STATE* orig, int *error)32{33if (!orig)34{35if (error)36*error = SRC_ERR_BAD_STATE ;37return NULL ;38}39if (error)40*error = SRC_ERR_NO_ERROR ;4142SRC_STATE *state = orig->vt->copy (orig) ;43if (!state)44if (error)45*error = SRC_ERR_MALLOC_FAILED ;4647return state ;48}4950SRC_STATE*51src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data)52{ SRC_STATE *state ;5354if (func == NULL)55{ if (error)56*error = SRC_ERR_BAD_CALLBACK ;57return NULL ;58} ;5960if (error != NULL)61*error = 0 ;6263if ((state = src_new (converter_type, channels, error)) == NULL)64return NULL ;6566src_reset (state) ;6768state->mode = SRC_MODE_CALLBACK ;69state->callback_func = func ;70state->user_callback_data = cb_data ;7172return state ;73} /* src_callback_new */74#endif7576SRC_STATE *77src_delete (SRC_STATE *state)78{79if (state)80state->vt->close (state) ;8182return NULL ;83} /* src_state */8485int86src_process (SRC_STATE *state, SRC_DATA *data)87{88int error ;8990if (state == NULL)91return SRC_ERR_BAD_STATE ;9293if (state->mode != SRC_MODE_PROCESS)94return SRC_ERR_BAD_MODE ;9596/* Check for valid SRC_DATA first. */97if (data == NULL)98return SRC_ERR_BAD_DATA ;99100/* And that data_in and data_out are valid. */101if ((data->data_in == NULL && data->input_frames > 0)102|| (data->data_out == NULL && data->output_frames > 0))103return SRC_ERR_BAD_DATA_PTR ;104105/* Check src_ratio is in range. */106if (is_bad_src_ratio (data->src_ratio))107return SRC_ERR_BAD_SRC_RATIO ;108109if (data->input_frames < 0)110data->input_frames = 0 ;111if (data->output_frames < 0)112data->output_frames = 0 ;113114if (data->data_in < data->data_out)115{ if (data->data_in + data->input_frames * state->channels > data->data_out)116{ /*-printf ("\n\ndata_in: %p data_out: %p\n",117(void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/118return SRC_ERR_DATA_OVERLAP ;119} ;120}121else if (data->data_out + data->output_frames * state->channels > data->data_in)122{ /*-printf ("\n\ndata_in : %p ouput frames: %ld data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ;123124printf ("data_out: %p (%p) data_in: %p\n", (void*) data->data_out,125(void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/126return SRC_ERR_DATA_OVERLAP ;127} ;128129/* Set the input and output counts to zero. */130data->input_frames_used = 0 ;131data->output_frames_gen = 0 ;132133/* Special case for when last_ratio has not been set. */134if (state->last_ratio < (1.0 / SRC_MAX_RATIO))135state->last_ratio = data->src_ratio ;136137/* Now process. */138if (fabs (state->last_ratio - data->src_ratio) < 1e-15)139error = state->vt->const_process (state, data) ;140else141error = state->vt->vari_process (state, data) ;142143return error ;144} /* src_process */145146#if 0147long148src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)149{150SRC_DATA src_data ;151152long output_frames_gen ;153int error = 0 ;154155if (state == NULL)156return 0 ;157158if (frames <= 0)159return 0 ;160161if (state->mode != SRC_MODE_CALLBACK)162{ state->error = SRC_ERR_BAD_MODE ;163return 0 ;164} ;165166if (state->callback_func == NULL)167{ state->error = SRC_ERR_NULL_CALLBACK ;168return 0 ;169} ;170171memset (&src_data, 0, sizeof (src_data)) ;172173/* Check src_ratio is in range. */174if (is_bad_src_ratio (src_ratio))175{ state->error = SRC_ERR_BAD_SRC_RATIO ;176return 0 ;177} ;178179/* Switch modes temporarily. */180src_data.src_ratio = src_ratio ;181src_data.data_out = data ;182src_data.output_frames = frames ;183184src_data.data_in = state->saved_data ;185src_data.input_frames = state->saved_frames ;186187output_frames_gen = 0 ;188while (output_frames_gen < frames)189{ /* Use a dummy array for the case where the callback function190** returns without setting the ptr.191*/192float dummy [1] ;193194if (src_data.input_frames == 0)195{ float *ptr = dummy ;196197src_data.input_frames = state->callback_func (state->user_callback_data, &ptr) ;198src_data.data_in = ptr ;199200if (src_data.input_frames == 0)201src_data.end_of_input = 1 ;202} ;203204/*205** Now call process function. However, we need to set the mode206** to SRC_MODE_PROCESS first and when we return set it back to207** SRC_MODE_CALLBACK.208*/209state->mode = SRC_MODE_PROCESS ;210error = src_process (state, &src_data) ;211state->mode = SRC_MODE_CALLBACK ;212213if (error != 0)214break ;215216src_data.data_in += src_data.input_frames_used * state->channels ;217src_data.input_frames -= src_data.input_frames_used ;218219src_data.data_out += src_data.output_frames_gen * state->channels ;220src_data.output_frames -= src_data.output_frames_gen ;221222output_frames_gen += src_data.output_frames_gen ;223224if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0)225break ;226} ;227228state->saved_data = src_data.data_in ;229state->saved_frames = src_data.input_frames ;230231if (error != 0)232{ state->error = (SRC_ERROR) error ;233return 0 ;234} ;235236return output_frames_gen ;237} /* src_callback_read */238239/*==========================================================================240*/241242int243src_set_ratio (SRC_STATE *state, double new_ratio)244{245if (state == NULL)246return SRC_ERR_BAD_STATE ;247248if (is_bad_src_ratio (new_ratio))249return SRC_ERR_BAD_SRC_RATIO ;250251state->last_ratio = new_ratio ;252253return SRC_ERR_NO_ERROR ;254} /* src_set_ratio */255256int257src_get_channels (SRC_STATE *state)258{259if (state == NULL)260return -SRC_ERR_BAD_STATE ;261262return state->channels ;263} /* src_get_channels */264265int266src_reset (SRC_STATE *state)267{268if (state == NULL)269return SRC_ERR_BAD_STATE ;270271state->vt->reset (state) ;272273state->last_position = 0.0 ;274state->last_ratio = 0.0 ;275276state->saved_data = NULL ;277state->saved_frames = 0 ;278279state->error = SRC_ERR_NO_ERROR ;280281return SRC_ERR_NO_ERROR ;282} /* src_reset */283284/*==============================================================================285** Control functions.286*/287288const char *289src_get_name (int converter_type)290{ const char *desc ;291292if ((desc = sinc_get_name (converter_type)) != NULL)293return desc ;294295if ((desc = zoh_get_name (converter_type)) != NULL)296return desc ;297298if ((desc = linear_get_name (converter_type)) != NULL)299return desc ;300301return NULL ;302} /* src_get_name */303304const char *305src_get_description (int converter_type)306{ const char *desc ;307308if ((desc = sinc_get_description (converter_type)) != NULL)309return desc ;310311if ((desc = zoh_get_description (converter_type)) != NULL)312return desc ;313314if ((desc = linear_get_description (converter_type)) != NULL)315return desc ;316317return NULL ;318} /* src_get_description */319320const char *321src_get_version (void)322{ return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ;323} /* src_get_version */324325int326src_is_valid_ratio (double ratio)327{328if (is_bad_src_ratio (ratio))329return SRC_FALSE ;330331return SRC_TRUE ;332} /* src_is_valid_ratio */333334/*==============================================================================335** Error reporting functions.336*/337338int339src_error (SRC_STATE *state)340{ if (state)341return state->error ;342return SRC_ERR_NO_ERROR ;343} /* src_error */344345const char*346src_strerror (int error)347{348switch (error)349{ case SRC_ERR_NO_ERROR :350return "No error." ;351case SRC_ERR_MALLOC_FAILED :352return "Malloc failed." ;353case SRC_ERR_BAD_STATE :354return "SRC_STATE pointer is NULL." ;355case SRC_ERR_BAD_DATA :356return "SRC_DATA pointer is NULL." ;357case SRC_ERR_BAD_DATA_PTR :358return "SRC_DATA->data_out or SRC_DATA->data_in is NULL." ;359case SRC_ERR_NO_PRIVATE :360return "Internal error. No private data." ;361362case SRC_ERR_BAD_SRC_RATIO :363return "SRC ratio outside [1/" SRC_MAX_RATIO_STR ", " SRC_MAX_RATIO_STR "] range." ;364365case SRC_ERR_BAD_SINC_STATE :366return "src_process() called without reset after end_of_input." ;367case SRC_ERR_BAD_PROC_PTR :368return "Internal error. No process pointer." ;369case SRC_ERR_SHIFT_BITS :370return "Internal error. SHIFT_BITS too large." ;371case SRC_ERR_FILTER_LEN :372return "Internal error. Filter length too large." ;373case SRC_ERR_BAD_CONVERTER :374return "Bad converter number." ;375case SRC_ERR_BAD_CHANNEL_COUNT :376return "Channel count must be >= 1." ;377case SRC_ERR_SINC_BAD_BUFFER_LEN :378return "Internal error. Bad buffer length. Please report this." ;379case SRC_ERR_SIZE_INCOMPATIBILITY :380return "Internal error. Input data / internal buffer size difference. Please report this." ;381case SRC_ERR_BAD_PRIV_PTR :382return "Internal error. Private pointer is NULL. Please report this." ;383case SRC_ERR_DATA_OVERLAP :384return "Input and output data arrays overlap." ;385case SRC_ERR_BAD_CALLBACK :386return "Supplied callback function pointer is NULL." ;387case SRC_ERR_BAD_MODE :388return "Calling mode differs from initialisation mode (ie process v callback)." ;389case SRC_ERR_NULL_CALLBACK :390return "Callback function pointer is NULL in src_callback_read ()." ;391case SRC_ERR_NO_VARIABLE_RATIO :392return "This converter only allows constant conversion ratios." ;393case SRC_ERR_SINC_PREPARE_DATA_BAD_LEN :394return "Internal error : Bad length in prepare_data ()." ;395case SRC_ERR_BAD_INTERNAL_STATE :396return "Error : Someone is trampling on my internal state." ;397398case SRC_ERR_MAX_ERROR :399return "Placeholder. No error defined for this error number." ;400401default : break ;402}403404return NULL ;405} /* src_strerror */406407/*==============================================================================408** Simple interface for performing a single conversion from input buffer to409** output buffer at a fixed conversion ratio.410*/411412int413src_simple (SRC_DATA *src_data, int converter, int channels)414{ SRC_STATE *src_state ;415int error ;416417if ((src_state = src_new (converter, channels, &error)) == NULL)418return error ;419420src_data->end_of_input = 1 ; /* Only one buffer worth of input. */421422error = src_process (src_state, src_data) ;423424src_delete (src_state) ;425426return error ;427} /* src_simple */428429void430src_short_to_float_array (const short *in, float *out, int len)431{432for (int i = 0 ; i < len ; i++)433{ out [i] = (float) (in [i] / (1.0 * 0x8000)) ;434} ;435436return ;437} /* src_short_to_float_array */438439void440src_float_to_short_array (const float *in, short *out, int len)441{442for (int i = 0 ; i < len ; i++)443{ float scaled_value ;444scaled_value = in [i] * 32768.f ;445if (scaled_value >= 32767.f)446out [i] = 32767 ;447else if (scaled_value <= -32768.f)448out [i] = -32768 ;449else450out [i] = (short) (lrintf (scaled_value)) ;451}452} /* src_float_to_short_array */453454void455src_int_to_float_array (const int *in, float *out, int len)456{457for (int i = 0 ; i < len ; i++)458{ out [i] = (float) (in [i] / (8.0 * 0x10000000)) ;459} ;460461return ;462} /* src_int_to_float_array */463464void465src_float_to_int_array (const float *in, int *out, int len)466{ double scaled_value ;467468for (int i = 0 ; i < len ; i++)469{ scaled_value = in [i] * (8.0 * 0x10000000) ;470#if CPU_CLIPS_POSITIVE == 0471if (scaled_value >= (1.0 * 0x7FFFFFFF))472{ out [i] = 0x7fffffff ;473continue ;474} ;475#endif476#if CPU_CLIPS_NEGATIVE == 0477if (scaled_value <= (-8.0 * 0x10000000))478{ out [i] = -1 - 0x7fffffff ;479continue ;480} ;481#endif482out [i] = (int) lrint (scaled_value) ;483} ;484485} /* src_float_to_int_array */486#endif487488/*==============================================================================489** Private functions.490*/491492static SRC_STATE *493psrc_set_converter (int converter_type, int channels, int *error)494{495SRC_ERROR temp_error;496SRC_STATE *state ;497switch (converter_type)498{499#ifdef ENABLE_SINC_BEST_CONVERTER500case SRC_SINC_BEST_QUALITY :501state = sinc_state_new (converter_type, channels, &temp_error) ;502break ;503#endif504#ifdef ENABLE_SINC_MEDIUM_CONVERTER505case SRC_SINC_MEDIUM_QUALITY :506state = sinc_state_new (converter_type, channels, &temp_error) ;507break ;508#endif509#ifdef ENABLE_SINC_FAST_CONVERTER510case SRC_SINC_FASTEST :511state = sinc_state_new (converter_type, channels, &temp_error) ;512break ;513#endif514case SRC_ZERO_ORDER_HOLD :515state = zoh_state_new (channels, &temp_error) ;516break ;517case SRC_LINEAR :518state = linear_state_new (channels, &temp_error) ;519break ;520default :521temp_error = SRC_ERR_BAD_CONVERTER ;522state = NULL ;523break ;524}525526if (error)527*error = (int) temp_error ;528529return state ;530} /* psrc_set_converter */531532533534