Path: blob/main/contrib/libsamplerate/src_linear.c
39481 views
/*1** Copyright (c) 2002-2021, 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 <assert.h>13#include <stdio.h>14#include <stdlib.h>15#include <string.h>16#include <math.h>1718#include "common.h"1920static SRC_ERROR linear_vari_process (SRC_STATE *state, SRC_DATA *data) ;21static void linear_reset (SRC_STATE *state) ;22static SRC_STATE *linear_copy (SRC_STATE *state) ;23static void linear_close (SRC_STATE *state) ;2425/*========================================================================================26*/2728#define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')2930#define SRC_DEBUG 03132typedef struct33{ int linear_magic_marker ;34bool dirty ;35long in_count, in_used ;36long out_count, out_gen ;37float *last_value ;38} LINEAR_DATA ;3940static SRC_STATE_VT linear_state_vt =41{42linear_vari_process,43linear_vari_process,44linear_reset,45linear_copy,46linear_close47} ;4849/*----------------------------------------------------------------------------------------50*/5152static SRC_ERROR53linear_vari_process (SRC_STATE *state, SRC_DATA *data)54{ LINEAR_DATA *priv ;55double src_ratio, input_index, rem ;56int ch ;5758if (data->input_frames <= 0)59return SRC_ERR_NO_ERROR ;6061if (state->private_data == NULL)62return SRC_ERR_NO_PRIVATE ;6364priv = (LINEAR_DATA*) state->private_data ;6566if (!priv->dirty)67{ /* If we have just been reset, set the last_value data. */68for (ch = 0 ; ch < state->channels ; ch++)69priv->last_value [ch] = data->data_in [ch] ;70priv->dirty = true ;71} ;7273priv->in_count = data->input_frames * state->channels ;74priv->out_count = data->output_frames * state->channels ;75priv->in_used = priv->out_gen = 0 ;7677src_ratio = state->last_ratio ;7879if (is_bad_src_ratio (src_ratio))80return SRC_ERR_BAD_INTERNAL_STATE ;8182input_index = state->last_position ;8384/* Calculate samples before first sample in input array. */85while (input_index < 1.0 && priv->out_gen < priv->out_count)86{87if (priv->in_used + state->channels * (1.0 + input_index) >= priv->in_count)88break ;8990if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)91src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;9293for (ch = 0 ; ch < state->channels ; ch++)94{ data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index *95((double) data->data_in [ch] - priv->last_value [ch])) ;96priv->out_gen ++ ;97} ;9899/* Figure out the next index. */100input_index += 1.0 / src_ratio ;101} ;102103rem = fmod_one (input_index) ;104priv->in_used += state->channels * lrint (input_index - rem) ;105input_index = rem ;106107/* Main processing loop. */108while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index < priv->in_count)109{110if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)111src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ;112113#if SRC_DEBUG114if (priv->in_used < state->channels && input_index < 1.0)115{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, state->channels, input_index) ;116exit (1) ;117} ;118#endif119120for (ch = 0 ; ch < state->channels ; ch++)121{ data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - state->channels + ch] + input_index *122((double) data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - state->channels + ch])) ;123priv->out_gen ++ ;124} ;125126/* Figure out the next index. */127input_index += 1.0 / src_ratio ;128rem = fmod_one (input_index) ;129130priv->in_used += state->channels * lrint (input_index - rem) ;131input_index = rem ;132} ;133134if (priv->in_used > priv->in_count)135{ input_index += (priv->in_used - priv->in_count) / state->channels ;136priv->in_used = priv->in_count ;137} ;138139state->last_position = input_index ;140141if (priv->in_used > 0)142for (ch = 0 ; ch < state->channels ; ch++)143priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ;144145/* Save current ratio rather then target ratio. */146state->last_ratio = src_ratio ;147148data->input_frames_used = priv->in_used / state->channels ;149data->output_frames_gen = priv->out_gen / state->channels ;150151return SRC_ERR_NO_ERROR ;152} /* linear_vari_process */153154/*------------------------------------------------------------------------------155*/156157#if 0158LIBSAMPLERATE_DLL_PRIVATE const char*159linear_get_name (int src_enum)160{161if (src_enum == SRC_LINEAR)162return "Linear Interpolator" ;163164return NULL ;165} /* linear_get_name */166167LIBSAMPLERATE_DLL_PRIVATE const char*168linear_get_description (int src_enum)169{170if (src_enum == SRC_LINEAR)171return "Linear interpolator, very fast, poor quality." ;172173return NULL ;174} /* linear_get_descrition */175#endif176177static LINEAR_DATA *178linear_data_new (int channels)179{180assert (channels > 0) ;181182LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;183if (priv)184{185priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;186priv->last_value = (float *) calloc (channels, sizeof (float)) ;187if (!priv->last_value)188{189free (priv) ;190priv = NULL ;191}192}193194return priv ;195}196197LIBSAMPLERATE_DLL_PRIVATE SRC_STATE *198linear_state_new (int channels, SRC_ERROR *error)199{200assert (channels > 0) ;201assert (error != NULL) ;202203SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;204if (!state)205{206*error = SRC_ERR_MALLOC_FAILED ;207return NULL ;208}209210state->channels = channels ;211state->mode = SRC_MODE_PROCESS ;212213state->private_data = linear_data_new (state->channels) ;214if (!state->private_data)215{216free (state) ;217*error = SRC_ERR_MALLOC_FAILED ;218return NULL ;219}220221state->vt = &linear_state_vt ;222223linear_reset (state) ;224225*error = SRC_ERR_NO_ERROR ;226227return state ;228}229230/*===================================================================================231*/232233static void234linear_reset (SRC_STATE *state)235{ LINEAR_DATA *priv = NULL ;236237priv = (LINEAR_DATA*) state->private_data ;238if (priv == NULL)239return ;240241priv->dirty = false ;242memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ;243244return ;245} /* linear_reset */246247SRC_STATE *248linear_copy (SRC_STATE *state)249{250assert (state != NULL) ;251252if (state->private_data == NULL)253return NULL ;254255SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;256if (!to)257return NULL ;258memcpy (to, state, sizeof (SRC_STATE)) ;259260LINEAR_DATA* from_priv = (LINEAR_DATA*) state->private_data ;261LINEAR_DATA *to_priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;262if (!to_priv)263{264free (to) ;265return NULL ;266}267268memcpy (to_priv, from_priv, sizeof (LINEAR_DATA)) ;269to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ;270if (!to_priv->last_value)271{272free (to) ;273free (to_priv) ;274return NULL ;275}276memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ;277278to->private_data = to_priv ;279280return to ;281} /* linear_copy */282283static void284linear_close (SRC_STATE *state)285{286if (state)287{288LINEAR_DATA *linear = (LINEAR_DATA *) state->private_data ;289if (linear)290{291if (linear->last_value)292{293free (linear->last_value) ;294linear->last_value = NULL ;295}296free (linear) ;297linear = NULL ;298}299free (state) ;300state = NULL ;301}302} /* linear_close */303304305