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 * 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 *
linear_data_new(int channels)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 *
linear_state_new(int channels,SRC_ERROR * error)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
linear_reset(SRC_STATE * state)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 *
linear_copy(SRC_STATE * 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
linear_close(SRC_STATE * state)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