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
26 #include <samplerate.h>
29 #define BUFFER_LEN 50000
30 #define BLOCK_LEN (12)
32 #define MAX_CHANNELS 10
34 static void simple_test (int converter
, int channel_count
, double target_snr
) ;
35 static void process_test (int converter
, int channel_count
, double target_snr
) ;
36 static void callback_test (int converter
, int channel_count
, double target_snr
) ;
43 puts ("\n Zero Order Hold interpolator :") ;
45 for (k
= 1 ; k
<= 3 ; k
++)
46 { simple_test (SRC_ZERO_ORDER_HOLD
, k
, target
) ;
47 process_test (SRC_ZERO_ORDER_HOLD
, k
, target
) ;
48 callback_test (SRC_ZERO_ORDER_HOLD
, k
, target
) ;
51 puts ("\n Linear interpolator :") ;
53 for (k
= 1 ; k
<= 3 ; k
++)
54 { simple_test (SRC_LINEAR
, k
, target
) ;
55 process_test (SRC_LINEAR
, k
, target
) ;
56 callback_test (SRC_LINEAR
, k
, target
) ;
59 puts ("\n Sinc interpolator :") ;
61 for (k
= 1 ; k
<= MAX_CHANNELS
; k
++)
62 { simple_test (SRC_SINC_FASTEST
, k
, target
) ;
63 process_test (SRC_SINC_FASTEST
, k
, target
) ;
64 callback_test (SRC_SINC_FASTEST
, k
, target
) ;
73 /*==============================================================================
76 static float input_serial
[BUFFER_LEN
* MAX_CHANNELS
] ;
77 static float input_interleaved
[BUFFER_LEN
* MAX_CHANNELS
] ;
78 static float output_interleaved
[BUFFER_LEN
* MAX_CHANNELS
] ;
79 static float output_serial
[BUFFER_LEN
* MAX_CHANNELS
] ;
82 simple_test (int converter
, int channel_count
, double target_snr
)
86 int ch
, error
, frames
;
88 printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count
, channel_count
> 1 ? 's' : ' ') ;
91 assert (channel_count
<= MAX_CHANNELS
) ;
93 memset (input_serial
, 0, sizeof (input_serial
)) ;
94 memset (input_interleaved
, 0, sizeof (input_interleaved
)) ;
95 memset (output_interleaved
, 0, sizeof (output_interleaved
)) ;
96 memset (output_serial
, 0, sizeof (output_serial
)) ;
100 /* Calculate channel_count separate windowed sine waves. */
101 for (ch
= 0 ; ch
< channel_count
; ch
++)
102 { freq
= (200.0 + 33.333333333 * ch
) / 44100.0 ;
103 gen_windowed_sines (1, &freq
, 1.0, input_serial
+ ch
* frames
, frames
) ;
106 /* Interleave the data in preparation for SRC. */
107 interleave_data (input_serial
, input_interleaved
, frames
, channel_count
) ;
109 /* Choose a converstion ratio <= 1.0. */
110 src_data
.src_ratio
= 0.95 ;
112 src_data
.data_in
= input_interleaved
;
113 src_data
.input_frames
= frames
;
115 src_data
.data_out
= output_interleaved
;
116 src_data
.output_frames
= frames
;
118 if ((error
= src_simple (&src_data
, converter
, channel_count
)))
119 { printf ("\n\nLine %d : %s\n\n", __LINE__
, src_strerror (error
)) ;
123 if (fabs (src_data
.output_frames_gen
- src_data
.src_ratio
* src_data
.input_frames
) > 2)
124 { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__
,
125 src_data
.output_frames_gen
, (int) floor (src_data
.src_ratio
* src_data
.input_frames
)) ;
126 printf ("\tsrc_ratio : %.4f\n", src_data
.src_ratio
) ;
127 printf ("\tinput_len : %ld\n", src_data
.input_frames
) ;
128 printf ("\toutput_len : %ld\n\n", src_data
.output_frames_gen
) ;
132 /* De-interleave data so SNR can be calculated for each channel. */
133 deinterleave_data (output_interleaved
, output_serial
, frames
, channel_count
) ;
135 for (ch
= 0 ; ch
< channel_count
; ch
++)
136 { snr
= calculate_snr (output_serial
+ ch
* frames
, frames
, 1) ;
137 if (snr
< target_snr
)
138 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__
, ch
, snr
, target_snr
) ;
139 save_oct_float ("output.dat", input_serial
, channel_count
* frames
, output_serial
, channel_count
* frames
) ;
149 /*==============================================================================
153 process_test (int converter
, int channel_count
, double target_snr
)
154 { SRC_STATE
*src_state
;
158 int ch
, error
, frames
, current_in
, current_out
;
160 printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count
, channel_count
> 1 ? 's' : ' ') ;
163 assert (channel_count
<= MAX_CHANNELS
) ;
165 memset (input_serial
, 0, sizeof (input_serial
)) ;
166 memset (input_interleaved
, 0, sizeof (input_interleaved
)) ;
167 memset (output_interleaved
, 0, sizeof (output_interleaved
)) ;
168 memset (output_serial
, 0, sizeof (output_serial
)) ;
170 frames
= BUFFER_LEN
;
172 /* Calculate channel_count separate windowed sine waves. */
173 for (ch
= 0 ; ch
< channel_count
; ch
++)
174 { freq
= (400.0 + 11.333333333 * ch
) / 44100.0 ;
175 gen_windowed_sines (1, &freq
, 1.0, input_serial
+ ch
* frames
, frames
) ;
178 /* Interleave the data in preparation for SRC. */
179 interleave_data (input_serial
, input_interleaved
, frames
, channel_count
) ;
181 /* Perform sample rate conversion. */
182 if ((src_state
= src_new (converter
, channel_count
, &error
)) == NULL
)
183 { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__
, src_strerror (error
)) ;
187 src_data
.end_of_input
= 0 ; /* Set this later. */
189 /* Choose a converstion ratio < 1.0. */
190 src_data
.src_ratio
= 0.95 ;
192 src_data
.data_in
= input_interleaved
;
193 src_data
.data_out
= output_interleaved
;
195 current_in
= current_out
= 0 ;
198 { src_data
.input_frames
= MAX (MIN (BLOCK_LEN
, frames
- current_in
), 0) ;
199 src_data
.output_frames
= MAX (MIN (BLOCK_LEN
, frames
- current_out
), 0) ;
201 if ((error
= src_process (src_state
, &src_data
)))
202 { printf ("\n\nLine %d : %s\n\n", __LINE__
, src_strerror (error
)) ;
206 if (src_data
.end_of_input
&& src_data
.output_frames_gen
== 0)
209 current_in
+= src_data
.input_frames_used
;
210 current_out
+= src_data
.output_frames_gen
;
212 src_data
.data_in
+= src_data
.input_frames_used
* channel_count
;
213 src_data
.data_out
+= src_data
.output_frames_gen
* channel_count
;
215 src_data
.end_of_input
= (current_in
>= frames
) ? 1 : 0 ;
218 src_state
= src_delete (src_state
) ;
220 if (fabs (current_out
- src_data
.src_ratio
* current_in
) > 2)
221 { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__
,
222 current_out
, (int) floor (src_data
.src_ratio
* current_in
)) ;
223 printf ("\tsrc_ratio : %.4f\n", src_data
.src_ratio
) ;
224 printf ("\tinput_len : %d\n", frames
) ;
225 printf ("\toutput_len : %d\n\n", current_out
) ;
229 /* De-interleave data so SNR can be calculated for each channel. */
230 deinterleave_data (output_interleaved
, output_serial
, frames
, channel_count
) ;
232 for (ch
= 0 ; ch
< channel_count
; ch
++)
233 { snr
= calculate_snr (output_serial
+ ch
* frames
, frames
, 1) ;
234 if (snr
< target_snr
)
235 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__
, ch
, snr
, target_snr
) ;
236 save_oct_float ("output.dat", input_serial
, channel_count
* frames
, output_serial
, channel_count
* frames
) ;
246 /*==============================================================================
257 test_callback_func (void *cb_data
, float **data
)
258 { TEST_CB_DATA
*pcb_data
;
262 if ((pcb_data
= cb_data
) == NULL
)
268 *data
= pcb_data
->data
+ (pcb_data
->current_frame
* pcb_data
->channels
) ;
270 if (pcb_data
->total_frames
- pcb_data
->current_frame
< BLOCK_LEN
)
271 frames
= pcb_data
->total_frames
- pcb_data
->current_frame
;
275 pcb_data
->current_frame
+= frames
;
278 } /* test_callback_func */
281 callback_test (int converter
, int channel_count
, double target_snr
)
282 { TEST_CB_DATA test_callback_data
;
283 SRC_STATE
*src_state
= NULL
;
285 double freq
, snr
, src_ratio
;
286 int ch
, error
, frames
, read_total
, read_count
;
288 printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count
, channel_count
> 1 ? 's' : ' ') ;
291 assert (channel_count
<= MAX_CHANNELS
) ;
293 memset (input_serial
, 0, sizeof (input_serial
)) ;
294 memset (input_interleaved
, 0, sizeof (input_interleaved
)) ;
295 memset (output_interleaved
, 0, sizeof (output_interleaved
)) ;
296 memset (output_serial
, 0, sizeof (output_serial
)) ;
297 memset (&test_callback_data
, 0, sizeof (test_callback_data
)) ;
299 frames
= BUFFER_LEN
;
301 /* Calculate channel_count separate windowed sine waves. */
302 for (ch
= 0 ; ch
< channel_count
; ch
++)
303 { freq
= (200.0 + 33.333333333 * ch
) / 44100.0 ;
304 gen_windowed_sines (1, &freq
, 1.0, input_serial
+ ch
* frames
, frames
) ;
307 /* Interleave the data in preparation for SRC. */
308 interleave_data (input_serial
, input_interleaved
, frames
, channel_count
) ;
310 /* Perform sample rate conversion. */
312 test_callback_data
.channels
= channel_count
;
313 test_callback_data
.total_frames
= frames
;
314 test_callback_data
.current_frame
= 0 ;
315 test_callback_data
.data
= input_interleaved
;
317 if ((src_state
= src_callback_new (test_callback_func
, converter
, channel_count
, &error
, &test_callback_data
)) == NULL
)
318 { printf ("\n\nLine %d : %s\n\n", __LINE__
, src_strerror (error
)) ;
323 while (read_total
< frames
)
324 { read_count
= src_callback_read (src_state
, src_ratio
, frames
- read_total
, output_interleaved
+ read_total
* channel_count
) ;
329 read_total
+= read_count
;
332 if ((error
= src_error (src_state
)) != 0)
333 { printf ("\n\nLine %d : %s\n\n", __LINE__
, src_strerror (error
)) ;
337 src_state
= src_delete (src_state
) ;
339 if (fabs (read_total
- src_ratio
* frames
) > 2)
340 { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__
,
341 read_total
, (int) floor (src_ratio
* frames
)) ;
342 printf ("\tsrc_ratio : %.4f\n", src_ratio
) ;
343 printf ("\tinput_len : %d\n", frames
) ;
344 printf ("\toutput_len : %d\n\n", read_total
) ;
348 /* De-interleave data so SNR can be calculated for each channel. */
349 deinterleave_data (output_interleaved
, output_serial
, frames
, channel_count
) ;
351 for (ch
= 0 ; ch
< channel_count
; ch
++)
352 { snr
= calculate_snr (output_serial
+ ch
* frames
, frames
, 1) ;
353 if (snr
< target_snr
)
354 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__
, ch
, snr
, target_snr
) ;
355 save_oct_float ("output.dat", input_serial
, channel_count
* frames
, output_serial
, channel_count
* frames
) ;
363 } /* callback_test */