annotate src/libsamplerate-0.1.9/tests/multi_channel_test.c @ 150:0a1a4a299a5d

OSX binaries for Cap'n Proto
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 05 Jul 2017 09:46:34 +0100
parents 4a7071416412
children
rev   line source
cannam@126 1 /*
cannam@126 2 ** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com>
cannam@126 3 ** All rights reserved.
cannam@126 4 **
cannam@126 5 ** This code is released under 2-clause BSD license. Please see the
cannam@126 6 ** file at : https://github.com/erikd/libsamplerate/blob/master/COPYING
cannam@126 7 */
cannam@126 8
cannam@126 9 #include "config.h"
cannam@126 10
cannam@126 11 #include <stdio.h>
cannam@126 12 #include <stdlib.h>
cannam@126 13 #include <string.h>
cannam@126 14 #include <math.h>
cannam@126 15 #include <assert.h>
cannam@126 16
cannam@126 17 #if (HAVE_FFTW3)
cannam@126 18 #include <fftw3.h>
cannam@126 19 #else
cannam@126 20 static inline void
cannam@126 21 fftw_cleanup (void)
cannam@126 22 { return ;
cannam@126 23 }
cannam@126 24 #endif
cannam@126 25
cannam@126 26 #include <samplerate.h>
cannam@126 27
cannam@126 28 #include "util.h"
cannam@126 29 #define BUFFER_LEN 50000
cannam@126 30 #define BLOCK_LEN (12)
cannam@126 31
cannam@126 32 #define MAX_CHANNELS 10
cannam@126 33
cannam@126 34 static void simple_test (int converter, int channel_count, double target_snr) ;
cannam@126 35 static void process_test (int converter, int channel_count, double target_snr) ;
cannam@126 36 static void callback_test (int converter, int channel_count, double target_snr) ;
cannam@126 37
cannam@126 38 int
cannam@126 39 main (void)
cannam@126 40 { double target ;
cannam@126 41 int k ;
cannam@126 42
cannam@126 43 puts ("\n Zero Order Hold interpolator :") ;
cannam@126 44 target = 38.0 ;
cannam@126 45 for (k = 1 ; k <= 3 ; k++)
cannam@126 46 { simple_test (SRC_ZERO_ORDER_HOLD, k, target) ;
cannam@126 47 process_test (SRC_ZERO_ORDER_HOLD, k, target) ;
cannam@126 48 callback_test (SRC_ZERO_ORDER_HOLD, k, target) ;
cannam@126 49 } ;
cannam@126 50
cannam@126 51 puts ("\n Linear interpolator :") ;
cannam@126 52 target = 79.0 ;
cannam@126 53 for (k = 1 ; k <= 3 ; k++)
cannam@126 54 { simple_test (SRC_LINEAR, k, target) ;
cannam@126 55 process_test (SRC_LINEAR, k, target) ;
cannam@126 56 callback_test (SRC_LINEAR, k, target) ;
cannam@126 57 } ;
cannam@126 58
cannam@126 59 puts ("\n Sinc interpolator :") ;
cannam@126 60 target = 100.0 ;
cannam@126 61 for (k = 1 ; k <= MAX_CHANNELS ; k++)
cannam@126 62 { simple_test (SRC_SINC_FASTEST, k, target) ;
cannam@126 63 process_test (SRC_SINC_FASTEST, k, target) ;
cannam@126 64 callback_test (SRC_SINC_FASTEST, k, target) ;
cannam@126 65 } ;
cannam@126 66
cannam@126 67 fftw_cleanup () ;
cannam@126 68 puts ("") ;
cannam@126 69
cannam@126 70 return 0 ;
cannam@126 71 } /* main */
cannam@126 72
cannam@126 73 /*==============================================================================
cannam@126 74 */
cannam@126 75
cannam@126 76 static float input_serial [BUFFER_LEN * MAX_CHANNELS] ;
cannam@126 77 static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
cannam@126 78 static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ;
cannam@126 79 static float output_serial [BUFFER_LEN * MAX_CHANNELS] ;
cannam@126 80
cannam@126 81 static void
cannam@126 82 simple_test (int converter, int channel_count, double target_snr)
cannam@126 83 { SRC_DATA src_data ;
cannam@126 84
cannam@126 85 double freq, snr ;
cannam@126 86 int ch, error, frames ;
cannam@126 87
cannam@126 88 printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ;
cannam@126 89 fflush (stdout) ;
cannam@126 90
cannam@126 91 assert (channel_count <= MAX_CHANNELS) ;
cannam@126 92
cannam@126 93 memset (input_serial, 0, sizeof (input_serial)) ;
cannam@126 94 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
cannam@126 95 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
cannam@126 96 memset (output_serial, 0, sizeof (output_serial)) ;
cannam@126 97
cannam@126 98 frames = BUFFER_LEN ;
cannam@126 99
cannam@126 100 /* Calculate channel_count separate windowed sine waves. */
cannam@126 101 for (ch = 0 ; ch < channel_count ; ch++)
cannam@126 102 { freq = (200.0 + 33.333333333 * ch) / 44100.0 ;
cannam@126 103 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
cannam@126 104 } ;
cannam@126 105
cannam@126 106 /* Interleave the data in preparation for SRC. */
cannam@126 107 interleave_data (input_serial, input_interleaved, frames, channel_count) ;
cannam@126 108
cannam@126 109 /* Choose a converstion ratio <= 1.0. */
cannam@126 110 src_data.src_ratio = 0.95 ;
cannam@126 111
cannam@126 112 src_data.data_in = input_interleaved ;
cannam@126 113 src_data.input_frames = frames ;
cannam@126 114
cannam@126 115 src_data.data_out = output_interleaved ;
cannam@126 116 src_data.output_frames = frames ;
cannam@126 117
cannam@126 118 if ((error = src_simple (&src_data, converter, channel_count)))
cannam@126 119 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
cannam@126 120 exit (1) ;
cannam@126 121 } ;
cannam@126 122
cannam@126 123 if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2)
cannam@126 124 { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__,
cannam@126 125 src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ;
cannam@126 126 printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ;
cannam@126 127 printf ("\tinput_len : %ld\n", src_data.input_frames) ;
cannam@126 128 printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ;
cannam@126 129 exit (1) ;
cannam@126 130 } ;
cannam@126 131
cannam@126 132 /* De-interleave data so SNR can be calculated for each channel. */
cannam@126 133 deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
cannam@126 134
cannam@126 135 for (ch = 0 ; ch < channel_count ; ch++)
cannam@126 136 { snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
cannam@126 137 if (snr < target_snr)
cannam@126 138 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
cannam@126 139 save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
cannam@126 140 exit (1) ;
cannam@126 141 } ;
cannam@126 142 } ;
cannam@126 143
cannam@126 144 puts ("ok") ;
cannam@126 145
cannam@126 146 return ;
cannam@126 147 } /* simple_test */
cannam@126 148
cannam@126 149 /*==============================================================================
cannam@126 150 */
cannam@126 151
cannam@126 152 static void
cannam@126 153 process_test (int converter, int channel_count, double target_snr)
cannam@126 154 { SRC_STATE *src_state ;
cannam@126 155 SRC_DATA src_data ;
cannam@126 156
cannam@126 157 double freq, snr ;
cannam@126 158 int ch, error, frames, current_in, current_out ;
cannam@126 159
cannam@126 160 printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ;
cannam@126 161 fflush (stdout) ;
cannam@126 162
cannam@126 163 assert (channel_count <= MAX_CHANNELS) ;
cannam@126 164
cannam@126 165 memset (input_serial, 0, sizeof (input_serial)) ;
cannam@126 166 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
cannam@126 167 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
cannam@126 168 memset (output_serial, 0, sizeof (output_serial)) ;
cannam@126 169
cannam@126 170 frames = BUFFER_LEN ;
cannam@126 171
cannam@126 172 /* Calculate channel_count separate windowed sine waves. */
cannam@126 173 for (ch = 0 ; ch < channel_count ; ch++)
cannam@126 174 { freq = (400.0 + 11.333333333 * ch) / 44100.0 ;
cannam@126 175 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
cannam@126 176 } ;
cannam@126 177
cannam@126 178 /* Interleave the data in preparation for SRC. */
cannam@126 179 interleave_data (input_serial, input_interleaved, frames, channel_count) ;
cannam@126 180
cannam@126 181 /* Perform sample rate conversion. */
cannam@126 182 if ((src_state = src_new (converter, channel_count, &error)) == NULL)
cannam@126 183 { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ;
cannam@126 184 exit (1) ;
cannam@126 185 } ;
cannam@126 186
cannam@126 187 src_data.end_of_input = 0 ; /* Set this later. */
cannam@126 188
cannam@126 189 /* Choose a converstion ratio < 1.0. */
cannam@126 190 src_data.src_ratio = 0.95 ;
cannam@126 191
cannam@126 192 src_data.data_in = input_interleaved ;
cannam@126 193 src_data.data_out = output_interleaved ;
cannam@126 194
cannam@126 195 current_in = current_out = 0 ;
cannam@126 196
cannam@126 197 while (1)
cannam@126 198 { src_data.input_frames = MAX (MIN (BLOCK_LEN, frames - current_in), 0) ;
cannam@126 199 src_data.output_frames = MAX (MIN (BLOCK_LEN, frames - current_out), 0) ;
cannam@126 200
cannam@126 201 if ((error = src_process (src_state, &src_data)))
cannam@126 202 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
cannam@126 203 exit (1) ;
cannam@126 204 } ;
cannam@126 205
cannam@126 206 if (src_data.end_of_input && src_data.output_frames_gen == 0)
cannam@126 207 break ;
cannam@126 208
cannam@126 209 current_in += src_data.input_frames_used ;
cannam@126 210 current_out += src_data.output_frames_gen ;
cannam@126 211
cannam@126 212 src_data.data_in += src_data.input_frames_used * channel_count ;
cannam@126 213 src_data.data_out += src_data.output_frames_gen * channel_count ;
cannam@126 214
cannam@126 215 src_data.end_of_input = (current_in >= frames) ? 1 : 0 ;
cannam@126 216 } ;
cannam@126 217
cannam@126 218 src_state = src_delete (src_state) ;
cannam@126 219
cannam@126 220 if (fabs (current_out - src_data.src_ratio * current_in) > 2)
cannam@126 221 { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__,
cannam@126 222 current_out, (int) floor (src_data.src_ratio * current_in)) ;
cannam@126 223 printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ;
cannam@126 224 printf ("\tinput_len : %d\n", frames) ;
cannam@126 225 printf ("\toutput_len : %d\n\n", current_out) ;
cannam@126 226 exit (1) ;
cannam@126 227 } ;
cannam@126 228
cannam@126 229 /* De-interleave data so SNR can be calculated for each channel. */
cannam@126 230 deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
cannam@126 231
cannam@126 232 for (ch = 0 ; ch < channel_count ; ch++)
cannam@126 233 { snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
cannam@126 234 if (snr < target_snr)
cannam@126 235 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
cannam@126 236 save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
cannam@126 237 exit (1) ;
cannam@126 238 } ;
cannam@126 239 } ;
cannam@126 240
cannam@126 241 puts ("ok") ;
cannam@126 242
cannam@126 243 return ;
cannam@126 244 } /* process_test */
cannam@126 245
cannam@126 246 /*==============================================================================
cannam@126 247 */
cannam@126 248
cannam@126 249 typedef struct
cannam@126 250 { int channels ;
cannam@126 251 long total_frames ;
cannam@126 252 long current_frame ;
cannam@126 253 float *data ;
cannam@126 254 } TEST_CB_DATA ;
cannam@126 255
cannam@126 256 static long
cannam@126 257 test_callback_func (void *cb_data, float **data)
cannam@126 258 { TEST_CB_DATA *pcb_data ;
cannam@126 259
cannam@126 260 long frames ;
cannam@126 261
cannam@126 262 if ((pcb_data = cb_data) == NULL)
cannam@126 263 return 0 ;
cannam@126 264
cannam@126 265 if (data == NULL)
cannam@126 266 return 0 ;
cannam@126 267
cannam@126 268 *data = pcb_data->data + (pcb_data->current_frame * pcb_data->channels) ;
cannam@126 269
cannam@126 270 if (pcb_data->total_frames - pcb_data->current_frame < BLOCK_LEN)
cannam@126 271 frames = pcb_data->total_frames - pcb_data->current_frame ;
cannam@126 272 else
cannam@126 273 frames = BLOCK_LEN ;
cannam@126 274
cannam@126 275 pcb_data->current_frame += frames ;
cannam@126 276
cannam@126 277 return frames ;
cannam@126 278 } /* test_callback_func */
cannam@126 279
cannam@126 280 static void
cannam@126 281 callback_test (int converter, int channel_count, double target_snr)
cannam@126 282 { TEST_CB_DATA test_callback_data ;
cannam@126 283 SRC_STATE *src_state = NULL ;
cannam@126 284
cannam@126 285 double freq, snr, src_ratio ;
cannam@126 286 int ch, error, frames, read_total, read_count ;
cannam@126 287
cannam@126 288 printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ;
cannam@126 289 fflush (stdout) ;
cannam@126 290
cannam@126 291 assert (channel_count <= MAX_CHANNELS) ;
cannam@126 292
cannam@126 293 memset (input_serial, 0, sizeof (input_serial)) ;
cannam@126 294 memset (input_interleaved, 0, sizeof (input_interleaved)) ;
cannam@126 295 memset (output_interleaved, 0, sizeof (output_interleaved)) ;
cannam@126 296 memset (output_serial, 0, sizeof (output_serial)) ;
cannam@126 297 memset (&test_callback_data, 0, sizeof (test_callback_data)) ;
cannam@126 298
cannam@126 299 frames = BUFFER_LEN ;
cannam@126 300
cannam@126 301 /* Calculate channel_count separate windowed sine waves. */
cannam@126 302 for (ch = 0 ; ch < channel_count ; ch++)
cannam@126 303 { freq = (200.0 + 33.333333333 * ch) / 44100.0 ;
cannam@126 304 gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ;
cannam@126 305 } ;
cannam@126 306
cannam@126 307 /* Interleave the data in preparation for SRC. */
cannam@126 308 interleave_data (input_serial, input_interleaved, frames, channel_count) ;
cannam@126 309
cannam@126 310 /* Perform sample rate conversion. */
cannam@126 311 src_ratio = 0.95 ;
cannam@126 312 test_callback_data.channels = channel_count ;
cannam@126 313 test_callback_data.total_frames = frames ;
cannam@126 314 test_callback_data.current_frame = 0 ;
cannam@126 315 test_callback_data.data = input_interleaved ;
cannam@126 316
cannam@126 317 if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL)
cannam@126 318 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
cannam@126 319 exit (1) ;
cannam@126 320 } ;
cannam@126 321
cannam@126 322 read_total = 0 ;
cannam@126 323 while (read_total < frames)
cannam@126 324 { read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ;
cannam@126 325
cannam@126 326 if (read_count <= 0)
cannam@126 327 break ;
cannam@126 328
cannam@126 329 read_total += read_count ;
cannam@126 330 } ;
cannam@126 331
cannam@126 332 if ((error = src_error (src_state)) != 0)
cannam@126 333 { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ;
cannam@126 334 exit (1) ;
cannam@126 335 } ;
cannam@126 336
cannam@126 337 src_state = src_delete (src_state) ;
cannam@126 338
cannam@126 339 if (fabs (read_total - src_ratio * frames) > 2)
cannam@126 340 { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__,
cannam@126 341 read_total, (int) floor (src_ratio * frames)) ;
cannam@126 342 printf ("\tsrc_ratio : %.4f\n", src_ratio) ;
cannam@126 343 printf ("\tinput_len : %d\n", frames) ;
cannam@126 344 printf ("\toutput_len : %d\n\n", read_total) ;
cannam@126 345 exit (1) ;
cannam@126 346 } ;
cannam@126 347
cannam@126 348 /* De-interleave data so SNR can be calculated for each channel. */
cannam@126 349 deinterleave_data (output_interleaved, output_serial, frames, channel_count) ;
cannam@126 350
cannam@126 351 for (ch = 0 ; ch < channel_count ; ch++)
cannam@126 352 { snr = calculate_snr (output_serial + ch * frames, frames, 1) ;
cannam@126 353 if (snr < target_snr)
cannam@126 354 { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ;
cannam@126 355 save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ;
cannam@126 356 exit (1) ;
cannam@126 357 } ;
cannam@126 358 } ;
cannam@126 359
cannam@126 360 puts ("ok") ;
cannam@126 361
cannam@126 362 return ;
cannam@126 363 } /* callback_test */
cannam@126 364