2 ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** All rights reserved.
5 ** This code is released under 2-clause BSD license. Please see the
6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
14 #include "float_cast.h"
17 static int linear_vari_process (SRC_PRIVATE
*psrc
, SRC_DATA
*data
) ;
18 static void linear_reset (SRC_PRIVATE
*psrc
) ;
20 /*========================================================================================
23 #define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
28 { int linear_magic_marker
;
31 long in_count
, in_used
;
32 long out_count
, out_gen
;
33 float last_value
[1] ;
36 /*----------------------------------------------------------------------------------------
40 linear_vari_process (SRC_PRIVATE
*psrc
, SRC_DATA
*data
)
42 double src_ratio
, input_index
, rem
;
45 if (data
->input_frames
<= 0)
46 return SRC_ERR_NO_ERROR
;
48 if (psrc
->private_data
== NULL
)
49 return SRC_ERR_NO_PRIVATE
;
51 priv
= (LINEAR_DATA
*) psrc
->private_data
;
54 { /* If we have just been reset, set the last_value data. */
55 for (ch
= 0 ; ch
< priv
->channels
; ch
++)
56 priv
->last_value
[ch
] = data
->data_in
[ch
] ;
60 priv
->in_count
= data
->input_frames
* priv
->channels
;
61 priv
->out_count
= data
->output_frames
* priv
->channels
;
62 priv
->in_used
= priv
->out_gen
= 0 ;
64 src_ratio
= psrc
->last_ratio
;
66 if (is_bad_src_ratio (src_ratio
))
67 return SRC_ERR_BAD_INTERNAL_STATE
;
69 input_index
= psrc
->last_position
;
71 /* Calculate samples before first sample in input array. */
72 while (input_index
< 1.0 && priv
->out_gen
< priv
->out_count
)
74 if (priv
->in_used
+ priv
->channels
* (1.0 + input_index
) >= priv
->in_count
)
77 if (priv
->out_count
> 0 && fabs (psrc
->last_ratio
- data
->src_ratio
) > SRC_MIN_RATIO_DIFF
)
78 src_ratio
= psrc
->last_ratio
+ priv
->out_gen
* (data
->src_ratio
- psrc
->last_ratio
) / priv
->out_count
;
80 for (ch
= 0 ; ch
< priv
->channels
; ch
++)
81 { data
->data_out
[priv
->out_gen
] = (float) (priv
->last_value
[ch
] + input_index
*
82 (data
->data_in
[ch
] - priv
->last_value
[ch
])) ;
86 /* Figure out the next index. */
87 input_index
+= 1.0 / src_ratio
;
90 rem
= fmod_one (input_index
) ;
91 priv
->in_used
+= priv
->channels
* lrint (input_index
- rem
) ;
94 /* Main processing loop. */
95 while (priv
->out_gen
< priv
->out_count
&& priv
->in_used
+ priv
->channels
* input_index
< priv
->in_count
)
97 if (priv
->out_count
> 0 && fabs (psrc
->last_ratio
- data
->src_ratio
) > SRC_MIN_RATIO_DIFF
)
98 src_ratio
= psrc
->last_ratio
+ priv
->out_gen
* (data
->src_ratio
- psrc
->last_ratio
) / priv
->out_count
;
100 if (SRC_DEBUG
&& priv
->in_used
< priv
->channels
&& input_index
< 1.0)
101 { printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", priv
->in_used
, priv
->channels
, input_index
) ;
105 for (ch
= 0 ; ch
< priv
->channels
; ch
++)
106 { data
->data_out
[priv
->out_gen
] = (float) (data
->data_in
[priv
->in_used
- priv
->channels
+ ch
] + input_index
*
107 (data
->data_in
[priv
->in_used
+ ch
] - data
->data_in
[priv
->in_used
- priv
->channels
+ ch
])) ;
111 /* Figure out the next index. */
112 input_index
+= 1.0 / src_ratio
;
113 rem
= fmod_one (input_index
) ;
115 priv
->in_used
+= priv
->channels
* lrint (input_index
- rem
) ;
119 if (priv
->in_used
> priv
->in_count
)
120 { input_index
+= (priv
->in_used
- priv
->in_count
) / priv
->channels
;
121 priv
->in_used
= priv
->in_count
;
124 psrc
->last_position
= input_index
;
126 if (priv
->in_used
> 0)
127 for (ch
= 0 ; ch
< priv
->channels
; ch
++)
128 priv
->last_value
[ch
] = data
->data_in
[priv
->in_used
- priv
->channels
+ ch
] ;
130 /* Save current ratio rather then target ratio. */
131 psrc
->last_ratio
= src_ratio
;
133 data
->input_frames_used
= priv
->in_used
/ priv
->channels
;
134 data
->output_frames_gen
= priv
->out_gen
/ priv
->channels
;
136 return SRC_ERR_NO_ERROR
;
137 } /* linear_vari_process */
139 /*------------------------------------------------------------------------------
143 linear_get_name (int src_enum
)
145 if (src_enum
== SRC_LINEAR
)
146 return "Linear Interpolator" ;
149 } /* linear_get_name */
152 linear_get_description (int src_enum
)
154 if (src_enum
== SRC_LINEAR
)
155 return "Linear interpolator, very fast, poor quality." ;
158 } /* linear_get_descrition */
161 linear_set_converter (SRC_PRIVATE
*psrc
, int src_enum
)
162 { LINEAR_DATA
*priv
= NULL
;
164 if (src_enum
!= SRC_LINEAR
)
165 return SRC_ERR_BAD_CONVERTER
;
167 if (psrc
->private_data
!= NULL
)
168 { free (psrc
->private_data
) ;
169 psrc
->private_data
= NULL
;
172 if (psrc
->private_data
== NULL
)
173 { priv
= calloc (1, sizeof (*priv
) + psrc
->channels
* sizeof (float)) ;
174 psrc
->private_data
= priv
;
178 return SRC_ERR_MALLOC_FAILED
;
180 priv
->linear_magic_marker
= LINEAR_MAGIC_MARKER
;
181 priv
->channels
= psrc
->channels
;
183 psrc
->const_process
= linear_vari_process
;
184 psrc
->vari_process
= linear_vari_process
;
185 psrc
->reset
= linear_reset
;
187 linear_reset (psrc
) ;
189 return SRC_ERR_NO_ERROR
;
190 } /* linear_set_converter */
192 /*===================================================================================
196 linear_reset (SRC_PRIVATE
*psrc
)
197 { LINEAR_DATA
*priv
= NULL
;
199 priv
= (LINEAR_DATA
*) psrc
->private_data
;
203 priv
->channels
= psrc
->channels
;
205 memset (priv
->last_value
, 0, sizeof (priv
->last_value
[0]) * priv
->channels
) ;