• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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