annotate src/libsamplerate-0.1.8/tests/multi_channel_test.c @ 83:ae30d91d2ffe

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