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
linear_vari_process(SRC_STATE * state,SRC_DATA * data)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 * psf_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 * psf_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 LIBSAMPLERATE_DLL_PRIVATE const char*
linear_get_name(int src_enum)159 linear_get_name (int src_enum)
160 {
161 if (src_enum == SRC_LINEAR)
162 return "Linear Interpolator" ;
163
164 return NULL ;
165 } /* linear_get_name */
166
167 LIBSAMPLERATE_DLL_PRIVATE const char*
linear_get_description(int src_enum)168 linear_get_description (int src_enum)
169 {
170 if (src_enum == SRC_LINEAR)
171 return "Linear interpolator, very fast, poor quality." ;
172
173 return NULL ;
174 } /* linear_get_descrition */
175
176 static LINEAR_DATA *
linear_data_new(int channels)177 linear_data_new (int channels)
178 {
179 assert (channels > 0) ;
180
181 LINEAR_DATA *priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;
182 if (priv)
183 {
184 priv->linear_magic_marker = LINEAR_MAGIC_MARKER ;
185 priv->last_value = (float *) calloc (channels, sizeof (float)) ;
186 if (!priv->last_value)
187 {
188 free (priv) ;
189 priv = NULL ;
190 }
191 }
192
193 return priv ;
194 }
195
196 LIBSAMPLERATE_DLL_PRIVATE SRC_STATE *
linear_state_new(int channels,SRC_ERROR * error)197 linear_state_new (int channels, SRC_ERROR *error)
198 {
199 assert (channels > 0) ;
200 assert (error != NULL) ;
201
202 SRC_STATE *state = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
203 if (!state)
204 {
205 *error = SRC_ERR_MALLOC_FAILED ;
206 return NULL ;
207 }
208
209 state->channels = channels ;
210 state->mode = SRC_MODE_PROCESS ;
211
212 state->private_data = linear_data_new (state->channels) ;
213 if (!state->private_data)
214 {
215 free (state) ;
216 *error = SRC_ERR_MALLOC_FAILED ;
217 return NULL ;
218 }
219
220 state->vt = &linear_state_vt ;
221
222 linear_reset (state) ;
223
224 *error = SRC_ERR_NO_ERROR ;
225
226 return state ;
227 }
228
229 /*===================================================================================
230 */
231
232 static void
linear_reset(SRC_STATE * state)233 linear_reset (SRC_STATE *state)
234 { LINEAR_DATA *priv = NULL ;
235
236 priv = (LINEAR_DATA*) state->private_data ;
237 if (priv == NULL)
238 return ;
239
240 priv->dirty = false ;
241 memset (priv->last_value, 0, sizeof (priv->last_value [0]) * state->channels) ;
242
243 return ;
244 } /* linear_reset */
245
246 SRC_STATE *
linear_copy(SRC_STATE * state)247 linear_copy (SRC_STATE *state)
248 {
249 assert (state != NULL) ;
250
251 if (state->private_data == NULL)
252 return NULL ;
253
254 SRC_STATE *to = (SRC_STATE *) calloc (1, sizeof (SRC_STATE)) ;
255 if (!to)
256 return NULL ;
257 memcpy (to, state, sizeof (SRC_STATE)) ;
258
259 LINEAR_DATA* from_priv = (LINEAR_DATA*) state->private_data ;
260 LINEAR_DATA *to_priv = (LINEAR_DATA *) calloc (1, sizeof (LINEAR_DATA)) ;
261 if (!to_priv)
262 {
263 free (to) ;
264 return NULL ;
265 }
266
267 memcpy (to_priv, from_priv, sizeof (LINEAR_DATA)) ;
268 to_priv->last_value = (float *) malloc (sizeof (float) * state->channels) ;
269 if (!to_priv->last_value)
270 {
271 free (to) ;
272 free (to_priv) ;
273 return NULL ;
274 }
275 memcpy (to_priv->last_value, from_priv->last_value, sizeof (float) * state->channels) ;
276
277 to->private_data = to_priv ;
278
279 return to ;
280 } /* linear_copy */
281
282 static void
linear_close(SRC_STATE * state)283 linear_close (SRC_STATE *state)
284 {
285 if (state)
286 {
287 LINEAR_DATA *linear = (LINEAR_DATA *) state->private_data ;
288 if (linear)
289 {
290 if (linear->last_value)
291 {
292 free (linear->last_value) ;
293 linear->last_value = NULL ;
294 }
295 free (linear) ;
296 linear = NULL ;
297 }
298 free (state) ;
299 state = NULL ;
300 }
301 } /* linear_close */
302