2323#define fftw_cleanup ()
2424#endif
2525
26- #define BUFFER_LEN (1 << 16 )
26+ #define BUFFER_LEN (1 << 15 )
2727
2828static void varispeed_test (int converter , double target_snr ) ;
29+ static void varispeed_bounds_test (int converter ) ;
30+ static void set_ratio_test (int converter , int channels , double initial_ratio , double second_ratio ) ;
2931
3032int
3133main (void )
3234{
33- puts ("" ) ;
34- printf (" Zero Order Hold interpolator : " ) ;
35+ puts ("\n Varispeed SNR test" ) ;
36+ printf (" Zero Order Hold interpolator : " ) ;
37+ fflush (stdout ) ;
3538 varispeed_test (SRC_ZERO_ORDER_HOLD , 10.0 ) ;
39+ puts ("ok" ) ;
3640
37- printf (" Linear interpolator : " ) ;
41+ printf (" Linear interpolator : " ) ;
42+ fflush (stdout ) ;
3843 varispeed_test (SRC_LINEAR , 10.0 ) ;
44+ puts ("ok" ) ;
3945
40- printf (" Sinc interpolator : " ) ;
46+ printf (" Sinc interpolator : " ) ;
47+ fflush (stdout ) ;
4148 varispeed_test (SRC_SINC_FASTEST , 115.0 ) ;
49+ puts ("ok" ) ;
50+
51+ puts ("\n Varispeed bounds test" ) ;
52+ printf (" Zero Order Hold interpolator : " ) ;
53+ fflush (stdout ) ;
54+ varispeed_bounds_test (SRC_ZERO_ORDER_HOLD ) ;
55+ puts ("ok" ) ;
56+
57+ printf (" Linear interpolator : " ) ;
58+ fflush (stdout ) ;
59+ varispeed_bounds_test (SRC_LINEAR ) ;
60+ puts ("ok" ) ;
61+
62+ printf (" Sinc interpolator : " ) ;
63+ fflush (stdout ) ;
64+ varispeed_bounds_test (SRC_SINC_FASTEST ) ;
65+ puts ("ok" ) ;
4266
4367 fftw_cleanup () ;
4468 puts ("" ) ;
@@ -65,7 +89,7 @@ varispeed_test (int converter, double target_snr)
6589
6690 /* Perform sample rate conversion. */
6791 if ((src_state = src_new (converter , 1 , & error )) == NULL )
68- { printf ("\n\nLine %d : src_new() failed : %s\n\n" , __LINE__ , src_strerror (error )) ;
92+ { printf ("\n\nLine %d : src_new () failed : %s\n\n" , __LINE__ , src_strerror (error )) ;
6993 exit (1 ) ;
7094 } ;
7195
@@ -144,8 +168,104 @@ varispeed_test (int converter, double target_snr)
144168 exit (1 ) ;
145169 } ;
146170
147- puts ("ok" ) ;
148-
149171 return ;
150172} /* varispeed_test */
151173
174+ static void
175+ varispeed_bounds_test (int converter )
176+ { double ratios [] = { 0.1 , 0.01 , 20 } ;
177+ int chan , r1 , r2 ;
178+
179+ for (chan = 1 ; chan <= 9 ; chan ++ )
180+ for (r1 = 0 ; r1 < ARRAY_LEN (ratios ) ; r1 ++ )
181+ for (r2 = 0 ; r2 < ARRAY_LEN (ratios ) ; r2 ++ )
182+ if (r1 != r2 )
183+ set_ratio_test (converter , chan , ratios [r1 ], ratios [r2 ]) ;
184+ } /* varispeed_bounds_test */
185+
186+ static void
187+ set_ratio_test (int converter , int channels , double initial_ratio , double second_ratio )
188+ { const int total_input_frames = BUFFER_LEN ;
189+ /* Maximum upsample ratio is 20, use a value beigger. */
190+ const int total_output_frames = 25 * BUFFER_LEN ;
191+
192+ /* Interested in array boundary conditions, so all zero data here is fine. */
193+ float * input = calloc (total_input_frames * channels , sizeof (float )) ;
194+ float * output = calloc (total_output_frames * channels , sizeof (float )) ;
195+
196+ char details [128 ] ;
197+
198+ const int max_loop_count = 100000 ;
199+ const int chunk_size = 128 ;
200+
201+ SRC_STATE * src_state ;
202+ SRC_DATA src_data ;
203+
204+ int error , k , total_frames_used , total_frames_gen ;
205+
206+ snprintf (details , sizeof (details ), "%d channels, ratio %g -> %g" , channels , initial_ratio , second_ratio ) ;
207+
208+ if ((src_state = src_new (converter , channels , & error )) == NULL )
209+ { printf ("\n\nLine %d : src_new () failed : %s\n\n" , __LINE__ , src_strerror (error )) ;
210+ exit (1 ) ;
211+ } ;
212+
213+ total_frames_used = 0 ;
214+ total_frames_gen = 0 ;
215+
216+ memset (& src_data , 0 , sizeof (src_data )) ;
217+ src_data .end_of_input = 0 ;
218+ src_data .src_ratio = initial_ratio ;
219+ src_data .data_in = input ;
220+ src_data .data_out = output ;
221+ src_data .input_frames = chunk_size ;
222+ src_data .output_frames = total_output_frames ;
223+
224+ /* Process one chunk at initial_ratio. */
225+ if ((error = src_process (src_state , & src_data )))
226+ { printf ("\n\nLine %d : %s : %s\n\n" , __LINE__ , details , src_strerror (error )) ;
227+ exit (1 ) ;
228+ } ;
229+
230+ /* Now hard switch to second_ratio ... */
231+ src_data .src_ratio = second_ratio ;
232+ if ((error = src_process (src_state , & src_data )))
233+ { printf ("\n\nLine %d : %s : %s\n\n" , __LINE__ , details , src_strerror (error )) ;
234+ exit (1 ) ;
235+ } ;
236+
237+ /* ... and process the remaining. */
238+ for (k = 0 ; k < max_loop_count ; k ++ )
239+ { if ((error = src_process (src_state , & src_data )) != 0 )
240+ { printf ("\n\nLine %d : %s : %s\n\n" , __LINE__ , details , src_strerror (error )) ;
241+ exit (1 ) ;
242+ } ;
243+
244+ if (src_data .end_of_input && src_data .output_frames_gen == 0 )
245+ break ;
246+
247+ total_frames_used += src_data .input_frames_used ;
248+ total_frames_gen += src_data .output_frames_gen ;
249+
250+ src_data .data_in += src_data .input_frames_used * channels ;
251+ src_data .data_out += src_data .output_frames_gen * channels ;
252+
253+ src_data .input_frames = total_input_frames - total_frames_used ;
254+ src_data .output_frames = total_output_frames - total_frames_gen ;
255+
256+ src_data .end_of_input = total_frames_used >= total_input_frames ? 1 : 0 ;
257+ } ;
258+
259+ ASSERT (k < max_loop_count ) ;
260+ ASSERT (total_frames_gen > 0 ) ;
261+
262+ for (k = 0 ; k < total_frames_gen * channels ; k ++ )
263+ ASSERT (! isnan (output [k ])) ;
264+
265+ src_state = src_delete (src_state ) ;
266+
267+ free (input ) ;
268+ free (output ) ;
269+
270+ return ;
271+ } /* set_ratio_test */
0 commit comments