xref: /freebsd/contrib/libsamplerate/src_linear.c (revision 1480c0b3f2daa048fb3763f589302f613ff2ae54)
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