1 /* 2 ** Copyright (c) 2002-2021, Erik de Castro Lopo <erikd@mega-nerd.com> 3 ** All rights reserved. 4 ** 5 ** This code is released under 2-clause BSD license. Please see the 6 ** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING 7 */ 8 9 #ifdef HAVE_CONFIG_H 10 #include "config.h" 11 #endif 12 13 #include <assert.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <math.h> 18 19 #include "common.h" 20 21 static SRC_ERROR linear_vari_process (SRC_STATE *state, SRC_DATA *data) ; 22 static void linear_reset (SRC_STATE *state) ; 23 static SRC_STATE *linear_copy (SRC_STATE *state) ; 24 static void linear_close (SRC_STATE *state) ; 25 26 /*======================================================================================== 27 */ 28 29 #define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r') 30 31 #define SRC_DEBUG 0 32 33 typedef struct 34 { int linear_magic_marker ; 35 bool dirty ; 36 long in_count, in_used ; 37 long out_count, out_gen ; 38 float *last_value ; 39 } LINEAR_DATA ; 40 41 static SRC_STATE_VT linear_state_vt = 42 { 43 linear_vari_process, 44 linear_vari_process, 45 linear_reset, 46 linear_copy, 47 linear_close 48 } ; 49 50 /*---------------------------------------------------------------------------------------- 51 */ 52 53 static SRC_ERROR 54 linear_vari_process (SRC_STATE *state, SRC_DATA *data) 55 { LINEAR_DATA *priv ; 56 double src_ratio, input_index, rem ; 57 int ch ; 58 59 if (data->input_frames <= 0) 60 return SRC_ERR_NO_ERROR ; 61 62 if (state->private_data == NULL) 63 return SRC_ERR_NO_PRIVATE ; 64 65 priv = (LINEAR_DATA*) state->private_data ; 66 67 if (!priv->dirty) 68 { /* If we have just been reset, set the last_value data. */ 69 for (ch = 0 ; ch < state->channels ; ch++) 70 priv->last_value [ch] = data->data_in [ch] ; 71 priv->dirty = true ; 72 } ; 73 74 priv->in_count = data->input_frames * state->channels ; 75 priv->out_count = data->output_frames * state->channels ; 76 priv->in_used = priv->out_gen = 0 ; 77 78 src_ratio = state->last_ratio ; 79 80 if (is_bad_src_ratio (src_ratio)) 81 return SRC_ERR_BAD_INTERNAL_STATE ; 82 83 input_index = state->last_position ; 84 85 /* Calculate samples before first sample in input array. */ 86 while (input_index < 1.0 && priv->out_gen < priv->out_count) 87 { 88 if (priv->in_used + state->channels * (1.0 + input_index) >= priv->in_count) 89 break ; 90 91 if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) 92 src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; 93 94 for (ch = 0 ; ch < state->channels ; ch++) 95 { data->data_out [priv->out_gen] = (float) (priv->last_value [ch] + input_index * 96 ((double) data->data_in [ch] - priv->last_value [ch])) ; 97 priv->out_gen ++ ; 98 } ; 99 100 /* Figure out the next index. */ 101 input_index += 1.0 / src_ratio ; 102 } ; 103 104 rem = fmod_one (input_index) ; 105 priv->in_used += state->channels * lrint (input_index - rem) ; 106 input_index = rem ; 107 108 /* Main processing loop. */ 109 while (priv->out_gen < priv->out_count && priv->in_used + state->channels * input_index < priv->in_count) 110 { 111 if (priv->out_count > 0 && fabs (state->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF) 112 src_ratio = state->last_ratio + priv->out_gen * (data->src_ratio - state->last_ratio) / priv->out_count ; 113 114 #if SRC_DEBUG 115 if (priv->in_used < state->channels && input_index < 1.0) 116 { printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv->in_used, state->channels, input_index) ; 117 exit (1) ; 118 } ; 119 #endif 120 121 for (ch = 0 ; ch < state->channels ; ch++) 122 { data->data_out [priv->out_gen] = (float) (data->data_in [priv->in_used - state->channels + ch] + input_index * 123 ((double) data->data_in [priv->in_used + ch] - data->data_in [priv->in_used - state->channels + ch])) ; 124 priv->out_gen ++ ; 125 } ; 126 127 /* Figure out the next index. */ 128 input_index += 1.0 / src_ratio ; 129 rem = fmod_one (input_index) ; 130 131 priv->in_used += state->channels * lrint (input_index - rem) ; 132 input_index = rem ; 133 } ; 134 135 if (priv->in_used > priv->in_count) 136 { input_index += (priv->in_used - priv->in_count) / state->channels ; 137 priv->in_used = priv->in_count ; 138 } ; 139 140 state->last_position = input_index ; 141 142 if (priv->in_used > 0) 143 for (ch = 0 ; ch < state->channels ; ch++) 144 priv->last_value [ch] = data->data_in [priv->in_used - state->channels + ch] ; 145 146 /* Save current ratio rather then target ratio. */ 147 state->last_ratio = src_ratio ; 148 149 data->input_frames_used = priv->in_used / state->channels ; 150 data->output_frames_gen = priv->out_gen / state->channels ; 151 152 return SRC_ERR_NO_ERROR ; 153 } /* linear_vari_process */ 154 155 /*------------------------------------------------------------------------------ 156 */ 157 158 #if 0 159 LIBSAMPLERATE_DLL_PRIVATE const char* 160 linear_get_name (int src_enum) 161 { 162 if (src_enum == SRC_LINEAR) 163 return "Linear Interpolator" ; 164 165 return NULL ; 166 } /* linear_get_name */ 167 168 LIBSAMPLERATE_DLL_PRIVATE const char* 169 linear_get_description (int src_enum) 170 { 171 if (src_enum == SRC_LINEAR) 172 return "Linear interpolator, very fast, poor quality." ; 173 174 return NULL ; 175 } /* linear_get_descrition */ 176 #endif 177 178 static LINEAR_DATA * 179 linear_data_new (int channels) 180 { 181 assert (channels > 0) ; 182 183 LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ; 184 if (priv) 185 { 186 priv->linear_magic_marker = LINEAR_MAGIC_MARKER ; 187 priv->last_value = (float *) calloc (channels, sizeof (float)) ; 188 if (!priv->last_value) 189 { 190 free (priv) ; 191 priv = NULL ; 192 } 193 } 194 195 return priv ; 196 } 197 198 LIBSAMPLERATE_DLL_PRIVATE SRC_STATE * 199 linear_state_new (int channels, SRC_ERROR *error) 200 { 201 assert (channels > 0) ; 202 assert (error != NULL) ; 203 204 SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 205 if (!state) 206 { 207 *error = SRC_ERR_MALLOC_FAILED ; 208 return NULL ; 209 } 210 211 state->channels = channels ; 212 state->mode = SRC_MODE_PROCESS ; 213 214 state->private_data = linear_data_new (state->channels) ; 215 if (!state->private_data) 216 { 217 free (state) ; 218 *error = SRC_ERR_MALLOC_FAILED ; 219 return NULL ; 220 } 221 222 state->vt = &linear_state_vt ; 223 224 linear_reset (state) ; 225 226 *error = SRC_ERR_NO_ERROR ; 227 228 return state ; 229 } 230 231 /*=================================================================================== 232 */ 233 234 static void 235 linear_reset (SRC_STATE *state) 236 { LINEAR_DATA *priv = NULL ; 237 238 priv = (LINEAR_DATA*) state->private_data ; 239 if (priv == NULL) 240 return ; 241 242 priv->dirty = false ; 243 memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ; 244 245 return ; 246 } /* linear_reset */ 247 248 SRC_STATE * 249 linear_copy (SRC_STATE *state) 250 { 251 assert (state != NULL) ; 252 253 if (state->private_data == NULL) 254 return NULL ; 255 256 SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ; 257 if (!to) 258 return NULL ; 259 memcpy (to, state, sizeof (SRC_STATE)) ; 260 261 LINEAR_DATA* from_priv = (LINEAR_DATA*) state->private_data ; 262 LINEAR_DATA *to_priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ; 263 if (!to_priv) 264 { 265 free (to) ; 266 return NULL ; 267 } 268 269 memcpy (to_priv, from_priv, sizeof (LINEAR_DATA)) ; 270 to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ; 271 if (!to_priv->last_value) 272 { 273 free (to) ; 274 free (to_priv) ; 275 return NULL ; 276 } 277 memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ; 278 279 to->private_data = to_priv ; 280 281 return to ; 282 } /* linear_copy */ 283 284 static void 285 linear_close (SRC_STATE *state) 286 { 287 if (state) 288 { 289 LINEAR_DATA *linear = (LINEAR_DATA *) state->private_data ; 290 if (linear) 291 { 292 if (linear->last_value) 293 { 294 free (linear->last_value) ; 295 linear->last_value = NULL ; 296 } 297 free (linear) ; 298 linear = NULL ; 299 } 300 free (state) ; 301 state = NULL ; 302 } 303 } /* linear_close */ 304