diff options
Diffstat (limited to 'lib/libsamplerate/libsamplerate-0.2.2/tests')
21 files changed, 4661 insertions, 0 deletions
diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/CMakeLists.txt b/lib/libsamplerate/libsamplerate-0.2.2/tests/CMakeLists.txt new file mode 100755 index 00000000..eefa60b3 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/CMakeLists.txt @@ -0,0 +1,95 @@ +check_include_file(sys/times.h HAVE_SYS_TIMES_H) + +check_function_exists(alarm HAVE_ALARM) +check_function_exists(signal HAVE_SIGNAL) + +check_symbol_exists(SIGALRM signal.h HAVE_SIGALRM) + +if((NOT VCPKG_TOOLCHAIN) AND PKG_CONFIG_FOUND AND (NOT CMAKE_VERSION VERSION_LESS 3.6)) + pkg_check_modules(FFTW3 fftw3 IMPORTED_TARGET) + if(FFTW3_FOUND) + add_library(FFTW3::fftw3 INTERFACE IMPORTED) + target_link_libraries(FFTW3::fftw3 INTERFACE PkgConfig::FFTW3) + endif() +else() + find_package(FFTW3) +endif() + +set(HAVE_FFTW3 ${FFTW3_FOUND} PARENT_SCOPE) + +add_executable(misc_test misc_test.c util.c util.h) +target_link_libraries(misc_test PRIVATE samplerate) +add_test(NAME misc_test COMMAND misc_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(termination_test termination_test.c util.c util.h) +target_link_libraries(termination_test PRIVATE samplerate) +add_test(NAME termination_test COMMAND termination_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(callback_hang_test callback_hang_test.c util.c util.h) +target_link_libraries(callback_hang_test PRIVATE samplerate) +add_test(NAME callback_hang_test COMMAND callback_hang_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(downsample_test downsample_test.c util.c util.h) +target_link_libraries(downsample_test PRIVATE samplerate) +add_test(NAME downsample_test COMMAND downsample_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(simple_test simple_test.c util.c util.h) +target_link_libraries(simple_test PRIVATE samplerate) +add_test(NAME simple_test COMMAND simple_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(callback_test callback_test.c util.c util.h) +target_link_libraries(callback_test PRIVATE samplerate) +add_test(NAME callback_test COMMAND callback_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(reset_test reset_test.c util.c util.h) +target_link_libraries(reset_test PRIVATE samplerate) +add_test(NAME reset_test COMMAND reset_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(clone_test clone_test.c util.c util.h) +target_link_libraries(clone_test PRIVATE samplerate) +add_test(NAME clone_test COMMAND clone_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(nullptr_test nullptr_test.c util.c util.h) +target_link_libraries(nullptr_test PRIVATE samplerate) +add_test(NAME nullptr_test COMMAND nullptr_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(multi_channel_test multi_channel_test.c calc_snr.c util.c util.h) +target_link_libraries(multi_channel_test + PRIVATE + samplerate + $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> + ) +add_test(NAME multi_channel_test COMMAND multi_channel_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(varispeed_test varispeed_test.c calc_snr.c util.c util.h) +target_link_libraries(varispeed_test + PRIVATE samplerate + $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> + ) +add_test(NAME varispeed_test COMMAND varispeed_test util.c util.h WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(float_short_test float_short_test.c) +target_link_libraries(float_short_test PRIVATE samplerate) +add_test(NAME float_short_test COMMAND float_short_test WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(snr_bw_test snr_bw_test.c calc_snr.c util.c util.h) +target_link_libraries(snr_bw_test + PRIVATE + samplerate + $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> + ) +add_test(NAME snr_bw_test COMMAND snr_bw_test util.c util.h WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src) + +add_executable(throughput_test throughput_test.c util.c util.h) +target_link_libraries(throughput_test PRIVATE samplerate) + +add_executable(multichan_throughput_test multichan_throughput_test.c util.c util.h) +target_link_libraries(multichan_throughput_test PRIVATE samplerate) + +add_executable(src-evaluate src-evaluate.c util.c util.h calc_snr.c) +target_link_libraries(src-evaluate + PRIVATE + samplerate + $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3> + $<$<BOOL:${SndFile_FOUND}>:${SNDFILE_TARGET}> + ) diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/calc_snr.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/calc_snr.c new file mode 100755 index 00000000..35a37f77 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/calc_snr.c @@ -0,0 +1,243 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "util.h" + +#if (HAVE_FFTW3) + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <fftw3.h> + +#define MAX_SPEC_LEN (1<<18) +#define MAX_PEAKS 10 + +static void log_mag_spectrum (double *input, int len, double *magnitude) ; +static void smooth_mag_spectrum (double *magnitude, int len) ; +static double find_snr (const double *magnitude, int len, int expected_peaks) ; + +typedef struct +{ double peak ; + int index ; +} PEAK_DATA ; + +double +calculate_snr (float *data, int len, int expected_peaks) +{ static double magnitude [MAX_SPEC_LEN] ; + static double datacopy [MAX_SPEC_LEN] ; + + double snr = 200.0 ; + int k ; + + if (len > MAX_SPEC_LEN) + { printf ("%s : line %d : data length too large.\n", __FILE__, __LINE__) ; + exit (1) ; + } ; + + for (k = 0 ; k < len ; k++) + datacopy [k] = data [k] ; + + /* Pad the data just a little to speed up the FFT. */ + while ((len & 0x1F) && len < MAX_SPEC_LEN) + { datacopy [len] = 0.0 ; + len ++ ; + } ; + + log_mag_spectrum (datacopy, len, magnitude) ; + smooth_mag_spectrum (magnitude, len / 2) ; + + snr = find_snr (magnitude, len, expected_peaks) ; + + return snr ; +} /* calculate_snr */ + +/*============================================================================== +** There is a slight problem with trying to measure SNR with the method used +** here; the side lobes of the windowed FFT can look like a noise/aliasing peak. +** The solution is to smooth the magnitude spectrum by wiping out troughs +** between adjacent peaks as done here. +** This removes side lobe peaks without affecting noise/aliasing peaks. +*/ + +static void linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller) ; + +static void +smooth_mag_spectrum (double *mag, int len) +{ PEAK_DATA peaks [2] ; + + int k ; + + memset (peaks, 0, sizeof (peaks)) ; + + /* Find first peak. */ + for (k = 1 ; k < len - 1 ; k++) + { if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1]) + { peaks [0].peak = mag [k] ; + peaks [0].index = k ; + break ; + } ; + } ; + + /* Find subsequent peaks ans smooth between peaks. */ + for (k = peaks [0].index + 1 ; k < len - 1 ; k++) + { if (mag [k - 1] < mag [k] && mag [k] >= mag [k + 1]) + { peaks [1].peak = mag [k] ; + peaks [1].index = k ; + + if (peaks [1].peak > peaks [0].peak) + linear_smooth (mag, &peaks [1], &peaks [0]) ; + else + linear_smooth (mag, &peaks [0], &peaks [1]) ; + peaks [0] = peaks [1] ; + } ; + } ; + +} /* smooth_mag_spectrum */ + +static void +linear_smooth (double *mag, PEAK_DATA *larger, PEAK_DATA *smaller) +{ int k ; + + if (smaller->index < larger->index) + { for (k = smaller->index + 1 ; k < larger->index ; k++) + mag [k] = (mag [k] < mag [k - 1]) ? 0.999 * mag [k - 1] : mag [k] ; + } + else + { for (k = smaller->index - 1 ; k >= larger->index ; k--) + mag [k] = (mag [k] < mag [k + 1]) ? 0.999 * mag [k + 1] : mag [k] ; + } ; + +} /* linear_smooth */ + +/*============================================================================== +*/ + +static int +peak_compare (const void *vp1, const void *vp2) +{ const PEAK_DATA *peak1, *peak2 ; + + peak1 = (const PEAK_DATA*) vp1 ; + peak2 = (const PEAK_DATA*) vp2 ; + + return (peak1->peak < peak2->peak) ? 1 : -1 ; +} /* peak_compare */ + +static double +find_snr (const double *magnitude, int len, int expected_peaks) +{ PEAK_DATA peaks [MAX_PEAKS] ; + + int k, peak_count = 0 ; + double snr ; + + memset (peaks, 0, sizeof (peaks)) ; + + /* Find the MAX_PEAKS largest peaks. */ + for (k = 1 ; k < len - 1 ; k++) + { if (magnitude [k - 1] < magnitude [k] && magnitude [k] >= magnitude [k + 1]) + { if (peak_count < MAX_PEAKS) + { peaks [peak_count].peak = magnitude [k] ; + peaks [peak_count].index = k ; + peak_count ++ ; + qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ; + } + else if (magnitude [k] > peaks [MAX_PEAKS - 1].peak) + { peaks [MAX_PEAKS - 1].peak = magnitude [k] ; + peaks [MAX_PEAKS - 1].index = k ; + qsort (peaks, MAX_PEAKS, sizeof (PEAK_DATA), peak_compare) ; + } ; + } ; + } ; + + if (peak_count < expected_peaks) + { printf ("\n%s : line %d : bad peak_count (%d), expected %d.\n\n", __FILE__, __LINE__, peak_count, expected_peaks) ; + return -1.0 ; + } ; + + /* Sort the peaks. */ + qsort (peaks, peak_count, sizeof (PEAK_DATA), peak_compare) ; + + snr = peaks [0].peak ; + for (k = 1 ; k < peak_count ; k++) + if (fabs (snr - peaks [k].peak) > 10.0) + return fabs (peaks [k].peak) ; + + return snr ; +} /* find_snr */ + +static void +log_mag_spectrum (double *input, int len, double *magnitude) +{ fftw_plan plan = NULL ; + + double maxval ; + int k ; + + if (input == NULL || magnitude == NULL) + return ; + + plan = fftw_plan_r2r_1d (len, input, magnitude, FFTW_R2HC, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT) ; + if (plan == NULL) + { printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ; + exit (1) ; + } ; + + fftw_execute (plan) ; + + fftw_destroy_plan (plan) ; + + maxval = 0.0 ; + for (k = 1 ; k < len / 2 ; k++) + { /* + ** From : http://www.fftw.org/doc/Real_002dto_002dReal-Transform-Kinds.html#Real_002dto_002dReal-Transform-Kinds + ** + ** FFTW_R2HC computes a real-input DFT with output in “halfcomplex” format, i.e. real and imaginary parts + ** for a transform of size n stored as: + ** + ** r0, r1, r2, ..., rn/2, i(n+1)/2-1, ..., i2, i1 + */ + double re = magnitude [k] ; + double im = magnitude [len - k] ; + magnitude [k] = sqrt (re * re + im * im) ; + maxval = (maxval < magnitude [k]) ? magnitude [k] : maxval ; + } ; + + memset (magnitude + len / 2, 0, len / 2 * sizeof (magnitude [0])) ; + + /* Don't care about DC component. Make it zero. */ + magnitude [0] = 0.0 ; + + /* log magnitude. */ + for (k = 0 ; k < len ; k++) + { magnitude [k] = magnitude [k] / maxval ; + magnitude [k] = (magnitude [k] < 1e-15) ? -200.0 : 20.0 * log10 (magnitude [k]) ; + } ; + + return ; +} /* log_mag_spectrum */ + +#else /* ! (HAVE_LIBFFTW && HAVE_LIBRFFTW) */ + +double +calculate_snr (float *data, int len, int expected_peaks) +{ double snr = 200.0 ; + + data = data ; + len = len ; + expected_peaks = expected_peaks ; + + return snr ; +} /* calculate_snr */ + +#endif + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/callback_hang_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/callback_hang_test.c new file mode 100755 index 00000000..42a1bb03 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/callback_hang_test.c @@ -0,0 +1,127 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <math.h> + +#if HAVE_ALARM && HAVE_SIGNAL && HAVE_SIGALRM + +#include <signal.h> + +#include <samplerate.h> + +#include "util.h" + +#define SHORT_BUFFER_LEN 512 +#define LONG_BUFFER_LEN (1 << 14) + +typedef struct +{ double ratio ; + int count ; +} SRC_PAIR ; + +static void callback_hang_test (int converter) ; + +static void alarm_handler (int number) ; +static long input_callback (void *cb_data, float **data) ; + + +int +main (void) +{ + /* Set up SIGALRM handler. */ + signal (SIGALRM, alarm_handler) ; + + puts ("") ; + callback_hang_test (SRC_ZERO_ORDER_HOLD) ; + callback_hang_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + callback_hang_test (SRC_SINC_FASTEST) ; +#endif + puts ("") ; + + return 0 ; +} /* main */ + + +static void +callback_hang_test (int converter) +{ static float output [LONG_BUFFER_LEN] ; + static SRC_PAIR pairs [] = + { + { 1.2, 5 }, { 1.1, 1 }, { 1.0, 1 }, { 3.0, 1 }, { 2.0, 1 }, { 0.3, 1 }, + { 1.2, 0 }, { 1.1, 10 }, { 1.0, 1 } + } ; + + + SRC_STATE *src_state ; + + double src_ratio = 1.0 ; + int k, error ; + + printf ("\tcallback_hang_test (%-28s) ....... ", src_get_name (converter)) ; + fflush (stdout) ; + + /* Perform sample rate conversion. */ + src_state = src_callback_new (input_callback, converter, 1, &error, NULL) ; + if (src_state == NULL) + { printf ("\n\nLine %d : src_callback_new () failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + for (k = 0 ; k < ARRAY_LEN (pairs) ; k++) + { alarm (1) ; + src_ratio = pairs [k].ratio ; + src_callback_read (src_state, src_ratio, pairs [k].count, output) ; + } ; + + src_state = src_delete (src_state) ; + + alarm (0) ; + puts ("ok") ; + + return ; +} /* callback_hang_test */ + +static void +alarm_handler (int number) +{ + (void) number ; + printf ("\n\n Error : Hang inside src_callback_read() detected. Exiting!\n\n") ; + exit (1) ; +} /* alarm_handler */ + +static long +input_callback (void *cb_data, float **data) +{ + static float buffer [20] ; + + (void) cb_data ; + *data = buffer ; + + return ARRAY_LEN (buffer) ; +} /* input_callback */ + +#else + +int +main (void) +{ + puts ("\tCan't run this test on this platform.") ; + return 0 ; +} /* main */ + +#endif diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/callback_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/callback_test.c new file mode 100755 index 00000000..c13d2061 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/callback_test.c @@ -0,0 +1,238 @@ +/* +** Copyright (c) 2003-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN 10000 +#define CB_READ_LEN 256 + +static void callback_test (int converter, double ratio) ; +static void end_of_stream_test (int converter) ; + +int +main (void) +{ static double src_ratios [] = + { 1.0, 0.099, 0.1, 0.33333333, 0.789, 1.0001, 1.9, 3.1, 9.9 + } ; + + int k ; + + puts ("") ; + + puts (" Zero Order Hold interpolator :") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + callback_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; + + puts (" Linear interpolator :") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + callback_test (SRC_LINEAR, src_ratios [k]) ; + +#ifdef ENABLE_SINC_FAST_CONVERTER + puts (" Sinc interpolator :") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + callback_test (SRC_SINC_FASTEST, src_ratios [k]) ; +#endif + puts ("") ; + + puts (" End of stream test :") ; + end_of_stream_test (SRC_ZERO_ORDER_HOLD) ; + end_of_stream_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + end_of_stream_test (SRC_SINC_FASTEST) ; +#endif + + puts ("") ; + return 0 ; +} /* main */ + +/*===================================================================================== +*/ + +typedef struct +{ int channels ; + long count, total ; + int end_of_data ; + float data [BUFFER_LEN] ; +} TEST_CB_DATA ; + +static long +test_callback_func (void *cb_data, float **data) +{ TEST_CB_DATA *pcb_data ; + + long frames ; + + if ((pcb_data = cb_data) == NULL) + return 0 ; + + if (data == NULL) + return 0 ; + + if (pcb_data->total - pcb_data->count > CB_READ_LEN) + frames = CB_READ_LEN / pcb_data->channels ; + else + frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ; + + *data = pcb_data->data + pcb_data->count ; + pcb_data->count += frames ; + + return frames ; +} /* test_callback_func */ + + +static void +callback_test (int converter, double src_ratio) +{ static TEST_CB_DATA test_callback_data ; + static float output [BUFFER_LEN] ; + + SRC_STATE *src_state ; + + long read_count, read_total ; + int error ; + + printf ("\tcallback_test (SRC ratio = %6.4f) ........... ", src_ratio) ; + fflush (stdout) ; + + test_callback_data.channels = 2 ; + test_callback_data.count = 0 ; + test_callback_data.end_of_data = 0 ; + test_callback_data.total = ARRAY_LEN (test_callback_data.data) ; + + if ((src_state = src_callback_new (test_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + read_total = 0 ; + do + { /* We will be throwing away output data, so just grab as much as possible. */ + read_count = ARRAY_LEN (output) / test_callback_data.channels ; + read_count = src_callback_read (src_state, src_ratio, read_count, output) ; + read_total += read_count ; + } + while (read_count > 0) ; + + if ((error = src_error (src_state)) != 0) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_delete (src_state) ; + + if (fabs (read_total / src_ratio - ARRAY_LEN (test_callback_data.data)) > 2.0) + { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; + printf (" input len : %d\n", ARRAY_LEN (test_callback_data.data)) ; + printf (" output len : %ld (should be %g +/- 2)\n\n", read_total, + floor (0.5 + src_ratio * ARRAY_LEN (test_callback_data.data))) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* callback_test */ + +/*===================================================================================== +*/ + +static long +eos_callback_func (void *cb_data, float **data) +{ + TEST_CB_DATA *pcb_data ; + long frames ; + + if (data == NULL) + return 0 ; + + if ((pcb_data = cb_data) == NULL) + return 0 ; + + /* + ** Return immediately if there is no more data. + ** In this case, the output pointer 'data' will not be set and + ** valgrind should not warn about it. + */ + if (pcb_data->end_of_data) + return 0 ; + + if (pcb_data->total - pcb_data->count > CB_READ_LEN) + frames = CB_READ_LEN / pcb_data->channels ; + else + frames = (pcb_data->total - pcb_data->count) / pcb_data->channels ; + + *data = pcb_data->data + pcb_data->count ; + pcb_data->count += frames ; + + /* + ** Set end_of_data so that the next call to the callback function will + ** return zero ocunt without setting the 'data' pointer. + */ + if (pcb_data->total < 2 * pcb_data->count) + pcb_data->end_of_data = 1 ; + + return frames ; +} /* eos_callback_data */ + + +static void +end_of_stream_test (int converter) +{ static TEST_CB_DATA test_callback_data ; + static float output [BUFFER_LEN] ; + + SRC_STATE *src_state ; + + double src_ratio = 0.3 ; + long read_count ; + int error ; + + printf ("\t%-30s ........... ", src_get_name (converter)) ; + fflush (stdout) ; + + test_callback_data.channels = 2 ; + test_callback_data.count = 0 ; + test_callback_data.end_of_data = 0 ; + test_callback_data.total = ARRAY_LEN (test_callback_data.data) ; + + if ((src_state = src_callback_new (eos_callback_func, converter, test_callback_data.channels, &error, &test_callback_data)) == NULL) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + do + { /* We will be throwing away output data, so just grab as much as possible. */ + read_count = ARRAY_LEN (output) / test_callback_data.channels ; + read_count = src_callback_read (src_state, src_ratio, read_count, output) ; + } + while (read_count > 0) ; + + if ((error = src_error (src_state)) != 0) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_delete (src_state) ; + + if (test_callback_data.end_of_data == 0) + { printf ("\n\nLine %d : test_callback_data.end_of_data should not be 0." + " This is a bug in the test.\n\n", __LINE__) ; + exit (1) ; + } ; + + puts ("ok") ; + return ; +} /* end_of_stream_test */ diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/clone_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/clone_test.c new file mode 100755 index 00000000..0e420e1f --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/clone_test.c @@ -0,0 +1,134 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN (1 << 16) +#define NUM_CHANNELS 2 +#define FRAMES_PER_PASS (BUFFER_LEN >> 1) + +static void +clone_test (int converter) +{ static float input_serial [BUFFER_LEN * NUM_CHANNELS], input_interleaved [BUFFER_LEN * NUM_CHANNELS] ; + static float output [BUFFER_LEN * NUM_CHANNELS], output_cloned [BUFFER_LEN * NUM_CHANNELS] ; + double sine_freq ; + + SRC_STATE* src_state ; + SRC_STATE* src_state_cloned ; + SRC_DATA src_data, src_data_cloned ; + + int error, frame, ch, idx ; + + printf (" clone_test (%-28s) ....... ", src_get_name (converter)) ; + fflush (stdout) ; + + memset (input_serial, 0, sizeof (input_serial)) ; + memset (input_interleaved, 0, sizeof (input_interleaved)) ; + memset (output, 0, sizeof (output)) ; + memset (output_cloned, 0, sizeof (output_cloned)) ; + + /* Fill input buffer with an n-channel interleaved sine wave */ + sine_freq = 0.0111 ; + gen_windowed_sines (1, &sine_freq, 1.0, input_serial, BUFFER_LEN) ; + gen_windowed_sines (1, &sine_freq, 1.0, input_serial + BUFFER_LEN, BUFFER_LEN) ; + interleave_data (input_serial, input_interleaved, BUFFER_LEN, NUM_CHANNELS) ; + + if ((src_state = src_new (converter, NUM_CHANNELS, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Perform initial pass using first half of buffer so that src_state has non-trivial state */ + src_data.src_ratio = 1.1 ; + src_data.input_frames = FRAMES_PER_PASS ; + src_data.output_frames = FRAMES_PER_PASS ; + src_data.data_in = input_interleaved ; + src_data.data_out = output ; + src_data.output_frames_gen = 0 ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; + exit (1) ; + } ; + + /* Clone handle */ + if ((src_state_cloned = src_clone (src_state, &error)) == NULL) + { printf ("\n\nLine %d : src_clone() failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Process second half of buffer with both handles */ + src_data.data_in = input_interleaved + FRAMES_PER_PASS ; + + src_data_cloned = src_data ; + src_data_cloned.data_out = output_cloned ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; + exit (1) ; + } ; + + if ((error = src_process (src_state_cloned, &src_data_cloned))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; + exit (1) ; + } ; + + /* Check that both handles generated the same number of output frames */ + if (src_data.output_frames_gen != src_data_cloned.output_frames_gen) + { printf ("\n\nLine %d : cloned output_frames_gen (%ld) != original (%ld)\n\n", __LINE__, + src_data_cloned.output_frames_gen, src_data.output_frames_gen) ; + exit (1) ; + } ; + + for (ch = 0 ; ch < NUM_CHANNELS ; ch++) + { for (frame = 0 ; frame < src_data.output_frames_gen ; frame++) + { idx = ch * NUM_CHANNELS + ch ; + if (output[idx] != output_cloned[idx]) + { printf ("\n\nLine %d : cloned data does not equal original data at channel %d, frame %d\n\n", + __LINE__, ch, frame) ; + exit (1) ; + } ; + } ; + } ; + + src_delete (src_state) ; + src_delete (src_state_cloned) ; + + puts ("ok") ; +} /* clone_test */ + +int +main (void) +{ + puts(""); + + clone_test (SRC_ZERO_ORDER_HOLD) ; + clone_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + clone_test (SRC_SINC_FASTEST) ; +#endif + puts(""); + + return 0 ; +} /* main */ diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/downsample_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/downsample_test.c new file mode 100755 index 00000000..6a4a75e1 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/downsample_test.c @@ -0,0 +1,61 @@ +/* +** Copyright (c) 2008-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <samplerate.h> + +#include "util.h" + +static void +downsample_test (int converter) +{ static float in [1000], out [10] ; + SRC_DATA data ; + + printf (" downsample_test (%-28s) ....... ", src_get_name (converter)) ; + fflush (stdout) ; + + data.src_ratio = 1.0 / 255.0 ; + data.input_frames = ARRAY_LEN (in) ; + data.output_frames = ARRAY_LEN (out) ; + data.data_in = in ; + data.data_out = out ; + + if (src_simple (&data, converter, 1)) + { puts ("src_simple failed.") ; + exit (1) ; + } ; + + puts ("ok") ; +} /* downsample_test */ + +int +main (void) +{ + puts ("") ; + + downsample_test (SRC_ZERO_ORDER_HOLD) ; + downsample_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + downsample_test (SRC_SINC_FASTEST) ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + downsample_test (SRC_SINC_MEDIUM_QUALITY) ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + downsample_test (SRC_SINC_BEST_QUALITY) ; +#endif + + puts ("") ; + + return 0 ; +} /* main */ diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/float_short_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/float_short_test.c new file mode 100755 index 00000000..8c423e18 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/float_short_test.c @@ -0,0 +1,192 @@ +/* +** Copyright (c) 2003-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN 10000 + +static void float_to_short_test (void) ; +static void short_to_float_test (void) ; + +static void float_to_int_test (void) ; +static void int_to_float_test (void) ; + +int +main (void) +{ + puts ("") ; + + float_to_short_test () ; + short_to_float_test () ; + + float_to_int_test () ; + int_to_float_test () ; + + puts ("") ; + + return 0 ; +} /* main */ + +/*===================================================================================== +*/ + +static void +float_to_short_test (void) +{ + static float fpos [] = + { 0.95f, 0.99f, 1.0f, 1.01f, 1.1f, 2.0f, 11.1f, 111.1f, 2222.2f, 33333.3f, + // Some "almost 1" as corner cases + (float) (32767.0 / 32768.0), (float) ((32767.0 + 0.4) / 32768.0), (float) ((32767. + 0.5) / 32768.0), + (float) ((32767.0 + 0.6) / 32768.0), (float) ((32767.0 + 0.9) / 32768.0), + } ; + static float fneg [] = + { -0.95f, -0.99f, -1.0f, -1.01f, -1.1f, -2.0f, -11.1f, -111.1f, -2222.2f, -33333.3f, + // Some "almost 1" as corner cases + (float) (-32767.0 / 32768.0), (float) (-(32767.0 + 0.4) / 32768.0), (float) (-(32767.0 + 0.5) / 32768.0), + (float) (-(32767.0 + 0.6) / 32768.0), (float) (-(32767.0 + 0.9) / 32768.0), + } ; + + static short out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ; + + int k ; + + printf ("\tfloat_to_short_test ............................. ") ; + + src_float_to_short_array (fpos, out, ARRAY_LEN (fpos)) ; + + for (k = 0 ; k < ARRAY_LEN (fpos) ; k++) + if (out [k] < 30000) + { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; + exit (1) ; + } ; + + src_float_to_short_array (fneg, out, ARRAY_LEN (fneg)) ; + + for (k = 0 ; k < ARRAY_LEN (fneg) ; k++) + if (out [k] > -30000) + { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* float_to_short_test */ + +/*------------------------------------------------------------------------------------- +*/ + +static void +short_to_float_test (void) +{ + static short input [BUFFER_LEN] ; + static short output [BUFFER_LEN] ; + static float temp [BUFFER_LEN] ; + + int k ; + + printf ("\tshort_to_float_test ............................. ") ; + + for (k = 0 ; k < ARRAY_LEN (input) ; k++) + input [k] = (k * 0x8000) / ARRAY_LEN (input) ; + + src_short_to_float_array (input, temp, ARRAY_LEN (temp)) ; + src_float_to_short_array (temp, output, ARRAY_LEN (output)) ; + + for (k = 0 ; k < ARRAY_LEN (input) ; k++) + if (ABS (input [k] - output [k]) > 0) + { printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* short_to_float_test */ + +/*===================================================================================== +*/ + +static void +float_to_int_test (void) +{ + static float fpos [] = + { 0.95f, 0.99f, 1.0f, 1.01f, 1.1f, 2.0f, 11.1f, 111.1f, 2222.2f, 33333.3f + } ; + static float fneg [] = + { -0.95f, -0.99f, -1.0f, -1.01f, -1.1f, -2.0f, -11.1f, -111.1f, -2222.2f, -33333.3f + } ; + + static int out [MAX (ARRAY_LEN (fpos), ARRAY_LEN (fneg))] ; + + int k ; + + printf ("\tfloat_to_int_test ............................... ") ; + + src_float_to_int_array (fpos, out, ARRAY_LEN (fpos)) ; + + for (k = 0 ; k < ARRAY_LEN (fpos) ; k++) + if (out [k] < 30000 * 0x10000) + { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; + exit (1) ; + } ; + + src_float_to_int_array (fneg, out, ARRAY_LEN (fneg)) ; + + for (k = 0 ; k < ARRAY_LEN (fneg) ; k++) + if (out [k] > -30000 * 0x1000) + { printf ("\n\n\tLine %d : out [%d] == %d\n", __LINE__, k, out [k]) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* float_to_int_test */ + +/*------------------------------------------------------------------------------------- +*/ + +static void +int_to_float_test (void) +{ + static int input [BUFFER_LEN] ; + static int output [BUFFER_LEN] ; + static float temp [BUFFER_LEN] ; + + int k ; + + printf ("\tint_to_float_test ............................... ") ; + + for (k = 0 ; k < ARRAY_LEN (input) ; k++) + input [k] = (k * 0x80000000) / ARRAY_LEN (input) ; + + src_int_to_float_array (input, temp, ARRAY_LEN (temp)) ; + src_float_to_int_array (temp, output, ARRAY_LEN (output)) ; + + for (k = 0 ; k < ARRAY_LEN (input) ; k++) + if (ABS (input [k] - output [k]) > 0) + { printf ("\n\n\tLine %d : index %d %d -> %d\n", __LINE__, k, input [k], output [k]) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* int_to_float_test */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/misc_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/misc_test.c new file mode 100755 index 00000000..6d3c0d4e --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/misc_test.c @@ -0,0 +1,208 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <samplerate.h> + +#include "util.h" + +static void name_test (void) ; +static void error_test (void) ; +static void src_ratio_test (void) ; +static void zero_input_test (int converter) ; +static void get_channels_test (int converter); + +int +main (void) +{ + puts ("") ; + + printf (" version : %s\n\n", src_get_version ()) ; + + /* Current max converter is SRC_LINEAR. */ + name_test () ; + + error_test () ; + + src_ratio_test () ; + + zero_input_test (SRC_ZERO_ORDER_HOLD) ; + zero_input_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + zero_input_test (SRC_SINC_FASTEST) ; +#endif + get_channels_test (SRC_ZERO_ORDER_HOLD) ; + get_channels_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + get_channels_test (SRC_SINC_FASTEST) ; +#endif + puts ("") ; + return 0 ; +} /* main */ + +static void +name_test (void) +{ const char *name ; + int k = 0 ; + + puts (" name_test :") ; + + while (1) + { name = src_get_name (k) ; + if (name == NULL) + break ; + printf ("\tName %d : %s\n", k, name) ; + printf ("\tDesc %d : %s\n", k, src_get_description (k)) ; + k ++ ; + } ; + + puts ("") ; + + return ; +} /* name_test */ + +/*------------------------------------------------------------------------------ +*/ + +typedef struct +{ double ratio ; + int should_pass ; +} RATIO_TEST ; + +static RATIO_TEST ratio_test [] = +{ { 1.0 / 256.1, 0 }, + { 1.0 / 256.0, 1 }, + { 1.0, 1 }, + { 256.0, 1 }, + { 256.1, 0 }, + { -1.0, 0 } +} ; + +static void +src_ratio_test (void) +{ int k ; + + puts (" src_ratio_test (SRC ratio must be in range [1/256, 256]):" ) ; + + + for (k = 0 ; k < ARRAY_LEN (ratio_test) ; k++) + { if (ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) == 0) + { printf ("\n\nLine %d : SRC ratio %f should have passed.\n\n", __LINE__, ratio_test [k].ratio) ; + exit (1) ; + } ; + if (! ratio_test [k].should_pass && src_is_valid_ratio (ratio_test [k].ratio) != 0) + { printf ("\n\nLine %d : SRC ratio %f should not have passed.\n\n", __LINE__, ratio_test [k].ratio) ; + exit (1) ; + } ; + printf ("\t SRC ratio (%9.5f) : %s ................... ok\n", ratio_test [k].ratio, + (ratio_test [k].should_pass ? "pass" : "fail")) ; + } ; + + puts ("") ; + + return ; +} /* src_ratio_test */ + +static void +error_test (void) +{ const char *errorstr ; + int k, errors = 0 ; + + puts (" error_test :") ; + + for (k = 0 ; 1 ; k++) + { errorstr = src_strerror (k) ; + printf ("\t%-2d : %s\n", k, errorstr) ; + if (errorstr == NULL) + { errors ++ ; + continue ; + } ; + if (strstr (errorstr, "Placeholder.") == errorstr) + break ; + } ; + + if (errors != 0) + { printf ("\n\nLine %d : Missing error numbers above.\n\n", __LINE__) ; + exit (1) ; + } ; + + puts ("") ; + + return ; +} /* error_test */ + +static void +zero_input_test (int converter) +{ SRC_DATA data ; + SRC_STATE *state ; + float out [100] ; + int error ; + + printf (" %s (%-26s) ........ ", __func__, src_get_name (converter)) ; + fflush (stdout) ; + + if ((state = src_new (converter, 1, &error)) == NULL) + { printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + data.data_in = (float *) (size_t) 0xdeadbeef ; + data.input_frames = 0 ; + data.data_out = out ; + data.output_frames = ARRAY_LEN (out) ; + data.end_of_input = 0 ; + data.src_ratio = 1.0 ; + + if ((error = src_process (state, &data))) + { printf ("\n\nLine %d : src_new failed : %s.\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + state = src_delete (state) ; + + puts ("ok") ; +} /* zero_input_test */ + +static void get_channels_test(int converter) +{ + SRC_STATE *state; + int channels_in, channels_out; + const char *errorstr; + + state = NULL; + if ((channels_out = src_get_channels(state)) >= 0) + { + printf ("\n\nLine %d : Return value should be negative, was : %d.\n\n", __LINE__, channels_out) ; + exit (1) ; + } + errorstr = src_strerror(-channels_out); + if (!strstr(errorstr, "NULL")) + { + printf ("\n\nLine %d : Inverted output should be valid error code mentioning a NULL pointer, was : %s.\n\n", __LINE__, errorstr) ; + exit (1) ; + } + + for (channels_in = 1; channels_in <= 8; channels_in++) + { + int error; + state = src_new(converter, channels_in, &error); + if ((channels_out = src_get_channels(state)) != channels_in) + { + printf ("\n\nLine %d : Return value should be %d, was : %d.\n\n", __LINE__, channels_in, channels_out) ; + exit (1) ; + } + state = src_delete(state); + } +} diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/multi_channel_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/multi_channel_test.c new file mode 100755 index 00000000..0afb6398 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/multi_channel_test.c @@ -0,0 +1,368 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> + +#if (HAVE_FFTW3) +#include <fftw3.h> +#else +static inline void +fftw_cleanup (void) +{ return ; +} +#endif + +#include <samplerate.h> + +#include "util.h" +#define BUFFER_LEN 50000 +#define BLOCK_LEN (12) + +#define MAX_CHANNELS 10 + +static void simple_test (int converter, int channel_count, double target_snr) ; +static void process_test (int converter, int channel_count, double target_snr) ; +static void callback_test (int converter, int channel_count, double target_snr) ; + +int +main (void) +{ double target ; + int k ; + + puts ("\n Zero Order Hold interpolator :") ; + target = 38.0 ; + for (k = 1 ; k <= 3 ; k++) + { simple_test (SRC_ZERO_ORDER_HOLD, k, target) ; + process_test (SRC_ZERO_ORDER_HOLD, k, target) ; + callback_test (SRC_ZERO_ORDER_HOLD, k, target) ; + } ; + + puts ("\n Linear interpolator :") ; + target = 79.0 ; + for (k = 1 ; k <= 3 ; k++) + { simple_test (SRC_LINEAR, k, target) ; + process_test (SRC_LINEAR, k, target) ; + callback_test (SRC_LINEAR, k, target) ; + } ; + +#ifdef ENABLE_SINC_FAST_CONVERTER + puts ("\n Sinc interpolator :") ; + target = 100.0 ; + for (k = 1 ; k <= MAX_CHANNELS ; k++) + { simple_test (SRC_SINC_FASTEST, k, target) ; + process_test (SRC_SINC_FASTEST, k, target) ; + callback_test (SRC_SINC_FASTEST, k, target) ; + } ; +#endif + + fftw_cleanup () ; + puts ("") ; + + return 0 ; +} /* main */ + +/*============================================================================== +*/ + +static float input_serial [BUFFER_LEN * MAX_CHANNELS] ; +static float input_interleaved [BUFFER_LEN * MAX_CHANNELS] ; +static float output_interleaved [BUFFER_LEN * MAX_CHANNELS] ; +static float output_serial [BUFFER_LEN * MAX_CHANNELS] ; + +static void +simple_test (int converter, int channel_count, double target_snr) +{ SRC_DATA src_data ; + + double freq, snr ; + int ch, error, frames ; + + printf ("\t%-22s (%2d channel%c) ............ ", "simple_test", channel_count, channel_count > 1 ? 's' : ' ') ; + fflush (stdout) ; + + assert (channel_count <= MAX_CHANNELS) ; + + memset (input_serial, 0, sizeof (input_serial)) ; + memset (input_interleaved, 0, sizeof (input_interleaved)) ; + memset (output_interleaved, 0, sizeof (output_interleaved)) ; + memset (output_serial, 0, sizeof (output_serial)) ; + + frames = BUFFER_LEN ; + + /* Calculate channel_count separate windowed sine waves. */ + for (ch = 0 ; ch < channel_count ; ch++) + { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; + gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; + } ; + + /* Interleave the data in preparation for SRC. */ + interleave_data (input_serial, input_interleaved, frames, channel_count) ; + + /* Choose a converstion ratio <= 1.0. */ + src_data.src_ratio = 0.95 ; + + src_data.data_in = input_interleaved ; + src_data.input_frames = frames ; + + src_data.data_out = output_interleaved ; + src_data.output_frames = frames ; + + if ((error = src_simple (&src_data, converter, channel_count))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + if (fabs (src_data.output_frames_gen - src_data.src_ratio * src_data.input_frames) > 2) + { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, + src_data.output_frames_gen, (int) floor (src_data.src_ratio * src_data.input_frames)) ; + printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; + printf ("\tinput_len : %ld\n", src_data.input_frames) ; + printf ("\toutput_len : %ld\n\n", src_data.output_frames_gen) ; + exit (1) ; + } ; + + /* De-interleave data so SNR can be calculated for each channel. */ + deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; + + for (ch = 0 ; ch < channel_count ; ch++) + { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; + if (snr < target_snr) + { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; + save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; + exit (1) ; + } ; + } ; + + puts ("ok") ; + + return ; +} /* simple_test */ + +/*============================================================================== +*/ + +static void +process_test (int converter, int channel_count, double target_snr) +{ SRC_STATE *src_state ; + SRC_DATA src_data ; + + double freq, snr ; + int ch, error, frames, current_in, current_out ; + + printf ("\t%-22s (%2d channel%c) ............ ", "process_test", channel_count, channel_count > 1 ? 's' : ' ') ; + fflush (stdout) ; + + assert (channel_count <= MAX_CHANNELS) ; + + memset (input_serial, 0, sizeof (input_serial)) ; + memset (input_interleaved, 0, sizeof (input_interleaved)) ; + memset (output_interleaved, 0, sizeof (output_interleaved)) ; + memset (output_serial, 0, sizeof (output_serial)) ; + + frames = BUFFER_LEN ; + + /* Calculate channel_count separate windowed sine waves. */ + for (ch = 0 ; ch < channel_count ; ch++) + { freq = (400.0 + 11.333333333 * ch) / 44100.0 ; + gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; + } ; + + /* Interleave the data in preparation for SRC. */ + interleave_data (input_serial, input_interleaved, frames, channel_count) ; + + /* Perform sample rate conversion. */ + if ((src_state = src_new (converter, channel_count, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.end_of_input = 0 ; /* Set this later. */ + + /* Choose a converstion ratio < 1.0. */ + src_data.src_ratio = 0.95 ; + + src_data.data_in = input_interleaved ; + src_data.data_out = output_interleaved ; + + current_in = current_out = 0 ; + + while (1) + { src_data.input_frames = MAX (MIN (BLOCK_LEN, frames - current_in), 0) ; + src_data.output_frames = MAX (MIN (BLOCK_LEN, frames - current_out), 0) ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + if (src_data.end_of_input && src_data.output_frames_gen == 0) + break ; + + current_in += src_data.input_frames_used ; + current_out += src_data.output_frames_gen ; + + src_data.data_in += src_data.input_frames_used * channel_count ; + src_data.data_out += src_data.output_frames_gen * channel_count ; + + src_data.end_of_input = (current_in >= frames) ? 1 : 0 ; + } ; + + src_state = src_delete (src_state) ; + + if (fabs (current_out - src_data.src_ratio * current_in) > 2) + { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, + current_out, (int) floor (src_data.src_ratio * current_in)) ; + printf ("\tsrc_ratio : %.4f\n", src_data.src_ratio) ; + printf ("\tinput_len : %d\n", frames) ; + printf ("\toutput_len : %d\n\n", current_out) ; + exit (1) ; + } ; + + /* De-interleave data so SNR can be calculated for each channel. */ + deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; + + for (ch = 0 ; ch < channel_count ; ch++) + { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; + if (snr < target_snr) + { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; + save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; + exit (1) ; + } ; + } ; + + puts ("ok") ; + + return ; +} /* process_test */ + +/*============================================================================== +*/ + +typedef struct +{ int channels ; + long total_frames ; + long current_frame ; + float *data ; +} TEST_CB_DATA ; + +static long +test_callback_func (void *cb_data, float **data) +{ TEST_CB_DATA *pcb_data ; + + long frames ; + + if ((pcb_data = cb_data) == NULL) + return 0 ; + + if (data == NULL) + return 0 ; + + *data = pcb_data->data + (pcb_data->current_frame * pcb_data->channels) ; + + if (pcb_data->total_frames - pcb_data->current_frame < BLOCK_LEN) + frames = pcb_data->total_frames - pcb_data->current_frame ; + else + frames = BLOCK_LEN ; + + pcb_data->current_frame += frames ; + + return frames ; +} /* test_callback_func */ + +static void +callback_test (int converter, int channel_count, double target_snr) +{ TEST_CB_DATA test_callback_data ; + SRC_STATE *src_state = NULL ; + + double freq, snr, src_ratio ; + int ch, error, frames, read_total, read_count ; + + printf ("\t%-22s (%2d channel%c) ............ ", "callback_test", channel_count, channel_count > 1 ? 's' : ' ') ; + fflush (stdout) ; + + assert (channel_count <= MAX_CHANNELS) ; + + memset (input_serial, 0, sizeof (input_serial)) ; + memset (input_interleaved, 0, sizeof (input_interleaved)) ; + memset (output_interleaved, 0, sizeof (output_interleaved)) ; + memset (output_serial, 0, sizeof (output_serial)) ; + memset (&test_callback_data, 0, sizeof (test_callback_data)) ; + + frames = BUFFER_LEN ; + + /* Calculate channel_count separate windowed sine waves. */ + for (ch = 0 ; ch < channel_count ; ch++) + { freq = (200.0 + 33.333333333 * ch) / 44100.0 ; + gen_windowed_sines (1, &freq, 1.0, input_serial + ch * frames, frames) ; + } ; + + /* Interleave the data in preparation for SRC. */ + interleave_data (input_serial, input_interleaved, frames, channel_count) ; + + /* Perform sample rate conversion. */ + src_ratio = 0.95 ; + test_callback_data.channels = channel_count ; + test_callback_data.total_frames = frames ; + test_callback_data.current_frame = 0 ; + test_callback_data.data = input_interleaved ; + + if ((src_state = src_callback_new (test_callback_func, converter, channel_count, &error, &test_callback_data)) == NULL) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + read_total = 0 ; + while (read_total < frames) + { read_count = src_callback_read (src_state, src_ratio, frames - read_total, output_interleaved + read_total * channel_count) ; + + if (read_count <= 0) + break ; + + read_total += read_count ; + } ; + + if ((error = src_error (src_state)) != 0) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_state = src_delete (src_state) ; + + if (fabs (read_total - src_ratio * frames) > 2) + { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, + read_total, (int) floor (src_ratio * frames)) ; + printf ("\tsrc_ratio : %.4f\n", src_ratio) ; + printf ("\tinput_len : %d\n", frames) ; + printf ("\toutput_len : %d\n\n", read_total) ; + exit (1) ; + } ; + + /* De-interleave data so SNR can be calculated for each channel. */ + deinterleave_data (output_interleaved, output_serial, frames, channel_count) ; + + for (ch = 0 ; ch < channel_count ; ch++) + { snr = calculate_snr (output_serial + ch * frames, frames, 1) ; + if (snr < target_snr) + { printf ("\n\nLine %d: channel %d snr %f should be %f\n", __LINE__, ch, snr, target_snr) ; + save_oct_float ("output.dat", input_serial, channel_count * frames, output_serial, channel_count * frames) ; + exit (1) ; + } ; + } ; + + puts ("ok") ; + + return ; +} /* callback_test */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/multichan_throughput_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/multichan_throughput_test.c new file mode 100755 index 00000000..5cab44a1 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/multichan_throughput_test.c @@ -0,0 +1,261 @@ +/* +** Copyright (c) 2008-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <math.h> + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#endif + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN (1<<17) + +static float input [BUFFER_LEN] ; + +#if (defined(ENABLE_SINC_FAST_CONVERTER) || defined(ENABLE_SINC_MEDIUM_CONVERTER) || \ + defined(ENABLE_SINC_BEST_CONVERTER)) +static float output [BUFFER_LEN] ; + +static void +throughput_test (int converter, int channels, long *best_throughput) +{ SRC_DATA src_data ; + clock_t start_time, clock_time ; + double duration ; + long total_frames = 0, throughput ; + int error ; + + printf (" %-30s %2d ", src_get_name (converter), channels) ; + fflush (stdout) ; + + src_data.data_in = input ; + src_data.input_frames = ARRAY_LEN (input) / channels ; + + src_data.data_out = output ; + src_data.output_frames = ARRAY_LEN (output) / channels ; + + src_data.src_ratio = 0.99 ; + +#ifdef _WIN32 + Sleep (2000) ; +#else + sleep (2) ; +#endif + + start_time = clock () ; + + do + { + if ((error = src_simple (&src_data, converter, channels)) != 0) + { puts (src_strerror (error)) ; + exit (1) ; + } ; + + total_frames += src_data.output_frames_gen ; + + clock_time = clock () - start_time ; + duration = (1.0 * clock_time) / CLOCKS_PER_SEC ; + } + while (duration < 5.0) ; + + if (src_data.input_frames_used != src_data.input_frames) + { printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ; + exit (1) ; + } ; + + if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2) + { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; + printf (" input len : %d\n", ARRAY_LEN (input) / channels) ; + printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen, + floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ; + exit (1) ; + } ; + + throughput = lrint (floor (total_frames / duration)) ; + + if (!best_throughput) + { printf ("%5.2f %10ld\n", duration, throughput) ; + } + else + { *best_throughput = MAX (throughput, *best_throughput) ; + printf ("%5.2f %10ld %10ld\n", duration, throughput, *best_throughput) ; + } + +} /* throughput_test */ +#endif + +static void +single_run (void) +{ +#if (defined(ENABLE_SINC_FAST_CONVERTER) || defined(ENABLE_SINC_MEDIUM_CONVERTER) || \ + defined(ENABLE_SINC_BEST_CONVERTER)) + const int max_channels = 10 ; + int k ; +#endif + + printf ("\n CPU name : %s\n", get_cpu_name ()) ; + + puts ( + "\n" + " Converter Channels Duration Throughput\n" + " ---------------------------------------------------------------------" + ) ; + +#ifdef ENABLE_SINC_FAST_CONVERTER + for (k = 1 ; k <= max_channels / 2 ; k++) + throughput_test (SRC_SINC_FASTEST, k, 0) ; + + puts ("") ; +#endif + +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + for (k = 1 ; k <= max_channels / 2 ; k++) + throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ; + + puts ("") ; +#endif + +#ifdef ENABLE_SINC_BEST_CONVERTER + for (k = 1 ; k <= max_channels ; k++) + throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ; + puts ("") ; +#endif + return ; +} /* single_run */ + +static void +multi_run (int run_count) +{ int channels[] = {1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18}; + + printf ("\n CPU name : %s\n", get_cpu_name ()) ; + + puts ( + "\n" + " Converter Channels Duration Throughput Best Throughput\n" + " ----------------------------------------------------------------------------------------" + ) ; + + for (int i = 0 ; i < ARRAY_LEN(channels) ; i++) + { +#ifdef ENABLE_SINC_FAST_CONVERTER + long sinc_fastest = 0 ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + long sinc_medium = 0 ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + long sinc_best = 0 ; +#endif + int ch = channels[i]; + + for (int k = 0 ; k < run_count ; k++) + { +#ifdef ENABLE_SINC_FAST_CONVERTER + throughput_test (SRC_SINC_FASTEST, ch, &sinc_fastest) ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, &sinc_medium) ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + throughput_test (SRC_SINC_BEST_QUALITY, ch, &sinc_best) ; +#endif + + puts ("") ; + + /* Let the CPU cool down. We might be running on a laptop. */ +#ifdef _WIN32 + Sleep (10000) ; +#else + sleep (10) ; +#endif + } ; + + printf ( + "\n" + " Converter (channels: %d) Best Throughput\n" + " ------------------------------------------------\n", + ch + ) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ; +#endif + } ; + + puts ("") ; +} /* multi_run */ + +static void +usage_exit (const char * argv0) +{ const char * cptr ; + + if ((cptr = strrchr (argv0, '/')) != NULL) + argv0 = cptr ; + + printf ( + "Usage :\n" + " %s - Single run of the throughput test.\n" + " %s --best-of N - Do N runs of test a print bext result.\n" + "\n", + argv0, argv0) ; + + exit (0) ; +} /* usage_exit */ + +int +main (int argc, char ** argv) +{ double freq ; + + memset (input, 0, sizeof (input)) ; + freq = 0.01 ; + gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ; + + if (argc == 1) + single_run () ; + else if (argc == 3 && strcmp (argv [1], "--best-of") == 0) + { int run_count = atoi (argv [2]) ; + + if (run_count < 1 || run_count > 20) + { printf ("Please be sensible. Run count should be in range (1, 10].\n") ; + exit (1) ; + } ; + + multi_run (run_count) ; + } + else + usage_exit (argv [0]) ; + + puts ( + " Duration is in seconds.\n" + " Throughput is in frames/sec (more is better).\n" + ) ; + + return 0 ; +} /* main */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/nullptr_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/nullptr_test.c new file mode 100755 index 00000000..02ac00e5 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/nullptr_test.c @@ -0,0 +1,108 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN (1 << 16) +#define NUM_CHANNELS 1 + +static void +nullptr_test (int converter) +{ static float input [BUFFER_LEN * NUM_CHANNELS] ; + static float output [BUFFER_LEN * NUM_CHANNELS] ; + + SRC_STATE* src_state ; + SRC_DATA src_data, src_data2 ; + + int error ; + + printf (" nullptr_test (%-28s) ....... ", src_get_name (converter)) ; + fflush (stdout) ; + + memset (input, 0, sizeof (input)) ; + memset (output, 0, sizeof (output)) ; + + if ((src_state = src_new (converter, NUM_CHANNELS, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.src_ratio = 1.1 ; + src_data.input_frames = BUFFER_LEN ; + src_data.output_frames = BUFFER_LEN ; + src_data.data_in = input ; + src_data.data_out = output ; + src_data.output_frames_gen = 0 ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + //Input is zero-length + src_data2 = src_data; + src_data2.data_in = NULL; + src_data2.input_frames = 0; + + if ((error = src_process (src_state, &src_data2))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + //Output is zero-length + src_data2 = src_data; + src_data2.data_out = NULL; + src_data2.output_frames = 0; + + if ((error = src_process (src_state, &src_data2))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + //Input and output are zero-length + src_data2 = src_data; + src_data2.data_in = NULL; + src_data2.data_out = NULL; + src_data2.input_frames = 0; + src_data2.output_frames = 0; + + if ((error = src_process (src_state, &src_data2))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + + src_state = src_delete (src_state) ; + + puts ("ok") ; +} /* nullptr_test */ + +int +main (void) +{ + puts(""); + + nullptr_test (SRC_ZERO_ORDER_HOLD) ; + nullptr_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + nullptr_test (SRC_SINC_FASTEST) ; +#endif + puts(""); + + return 0 ; +} /* main */ diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/reset_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/reset_test.c new file mode 100755 index 00000000..736f376d --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/reset_test.c @@ -0,0 +1,236 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN 2048 +#define CB_READ_LEN 256 + +static void process_reset_test (int converter) ; +static void callback_reset_test (int converter) ; + +static float data_one [BUFFER_LEN] ; +static float data_zero [BUFFER_LEN] ; + +int +main (void) +{ + puts ("") ; + + process_reset_test (SRC_ZERO_ORDER_HOLD) ; + process_reset_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + process_reset_test (SRC_SINC_FASTEST) ; +#endif + + callback_reset_test (SRC_ZERO_ORDER_HOLD) ; + callback_reset_test (SRC_LINEAR) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + callback_reset_test (SRC_SINC_FASTEST) ; +#endif + + puts ("") ; + + return 0 ; +} /* main */ + +static void +process_reset_test (int converter) +{ static float output [BUFFER_LEN] ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + int k, error ; + + printf ("\tprocess_reset_test (%-28s) ....... ", src_get_name (converter)) ; + fflush (stdout) ; + + for (k = 0 ; k < BUFFER_LEN ; k++) + { data_one [k] = 1.0 ; + data_zero [k] = 0.0 ; + } ; + + /* Get a converter. */ + if ((src_state = src_new (converter, 1, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Process a bunch of 1.0 valued samples. */ + src_data.data_in = data_one ; + src_data.data_out = output ; + src_data.input_frames = BUFFER_LEN ; + src_data.output_frames = BUFFER_LEN ; + src_data.src_ratio = 0.9 ; + src_data.end_of_input = 1 ; + + if ((error = src_process (src_state, &src_data)) != 0) + { printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Reset the state of the converter.*/ + src_reset (src_state) ; + + /* Now process some zero data. */ + src_data.data_in = data_zero ; + src_data.data_out = output ; + src_data.input_frames = BUFFER_LEN ; + src_data.output_frames = BUFFER_LEN ; + src_data.src_ratio = 0.9 ; + src_data.end_of_input = 1 ; + + if ((error = src_process (src_state, &src_data)) != 0) + { printf ("\n\nLine %d : src_simple () returned error : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Finally make sure that the output data is zero ie reset was successful. */ + for (k = 0 ; k < BUFFER_LEN / 2 ; k++) + if (output [k] != 0.0) + { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n", __LINE__, k, output [k]) ; + exit (1) ; + } ; + + /* Make sure that this function has been exported. */ + src_set_ratio (src_state, 1.0) ; + + /* Delete converter. */ + src_state = src_delete (src_state) ; + + puts ("ok") ; +} /* process_reset_test */ + +/*============================================================================== +*/ + +typedef struct +{ int channels ; + long count, total ; + float *data ; +} TEST_CB_DATA ; + +static long +test_callback_func (void *cb_data, float **data) +{ TEST_CB_DATA *pcb_data ; + + long frames ; + + if ((pcb_data = cb_data) == NULL) + return 0 ; + + if (data == NULL) + return 0 ; + + if (pcb_data->total - pcb_data->count > 0) + frames = pcb_data->total - pcb_data->count ; + else + frames = 0 ; + + *data = pcb_data->data + pcb_data->count ; + pcb_data->count += frames ; + + return frames ; +} /* test_callback_func */ + +static void +callback_reset_test (int converter) +{ static TEST_CB_DATA test_callback_data ; + + static float output [BUFFER_LEN] ; + + SRC_STATE *src_state ; + + double src_ratio = 1.1 ; + long read_count, read_total ; + int k, error ; + + printf ("\tcallback_reset_test (%-28s) ....... ", src_get_name (converter)) ; + fflush (stdout) ; + + for (k = 0 ; k < ARRAY_LEN (data_one) ; k++) + { data_one [k] = 1.0 ; + data_zero [k] = 0.0 ; + } ; + + if ((src_state = src_callback_new (test_callback_func, converter, 1, &error, &test_callback_data)) == NULL) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Process a bunch of 1.0 valued samples. */ + test_callback_data.channels = 1 ; + test_callback_data.count = 0 ; + test_callback_data.total = ARRAY_LEN (data_one) ; + test_callback_data.data = data_one ; + + read_total = 0 ; + do + { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; + read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; + read_total += read_count ; + } + while (read_count > 0) ; + + /* Check for errors. */ + if ((error = src_error (src_state)) != 0) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Reset the state of the converter.*/ + src_reset (src_state) ; + + /* Process a bunch of 0.0 valued samples. */ + test_callback_data.channels = 1 ; + test_callback_data.count = 0 ; + test_callback_data.total = ARRAY_LEN (data_zero) ; + test_callback_data.data = data_zero ; + + /* Now process some zero data. */ + read_total = 0 ; + do + { read_count = (ARRAY_LEN (output) - read_total > CB_READ_LEN) ? CB_READ_LEN : ARRAY_LEN (output) - read_total ; + read_count = src_callback_read (src_state, src_ratio, read_count, output + read_total) ; + read_total += read_count ; + } + while (read_count > 0) ; + + /* Check for errors. */ + if ((error = src_error (src_state)) != 0) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + /* Finally make sure that the output data is zero ie reset was successful. */ + for (k = 0 ; k < BUFFER_LEN / 2 ; k++) + if (output [k] != 0.0) + { printf ("\n\nLine %d : output [%d] should be 0.0, is %f.\n\n", __LINE__, k, output [k]) ; + save_oct_float ("output.dat", data_one, ARRAY_LEN (data_one), output, ARRAY_LEN (output)) ; + exit (1) ; + } ; + + /* Make sure that this function has been exported. */ + src_set_ratio (src_state, 1.0) ; + + /* Delete converter. */ + src_state = src_delete (src_state) ; + + puts ("ok") ; +} /* callback_reset_test */ + + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/simple_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/simple_test.c new file mode 100755 index 00000000..f9014fd2 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/simple_test.c @@ -0,0 +1,168 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN 2048 + +static void simple_test (int converter, double ratio) ; +static void src_simple_produces_output (int converter, int channels, double src_ratio) ; +static void src_simple_produces_output_test (int converter, double src_ratio) ; + +int +main (void) +{ static double src_ratios [] = + { 1.0001, 0.099, 0.1, 0.33333333, 0.789, 1.9, 3.1, 9.9, 256.0, 1.0 / 256.0 + } ; + + int k ; + + puts ("") ; + + puts (" Zero Order Hold interpolator :") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + { simple_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; + src_simple_produces_output_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; + } + + puts (" Linear interpolator :") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + { simple_test (SRC_LINEAR, src_ratios [k]) ; + src_simple_produces_output_test (SRC_LINEAR, src_ratios [k]) ; + } + +#ifdef ENABLE_SINC_FAST_CONVERTER + puts (" Sinc interpolator :") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + { simple_test (SRC_SINC_FASTEST, src_ratios [k]) ; + src_simple_produces_output_test (SRC_SINC_FASTEST, src_ratios [k]) ; + } +#endif + + puts ("") ; + + return 0 ; +} /* main */ + +static void +src_simple_produces_output_test (int converter, double src_ratio) +{ + for (int channels = 1; channels <= 9; channels++) + src_simple_produces_output(converter, channels, src_ratio); +} + +static void +src_simple_produces_output (int converter, int channels, double src_ratio) +{ + // Choose a suitable number of frames. + // At least 256 so a conversion ratio of 1/256 can produce any output + const long NUM_FRAMES = 1000; + int error; + + printf ("\tproduces_output\t(SRC ratio = %6.4f, channels = %d) ... ", src_ratio, channels) ; + fflush (stdout) ; + + float *input = calloc (NUM_FRAMES * channels, sizeof (float)); + float *output = calloc (NUM_FRAMES * channels, sizeof (float)); + + SRC_DATA src_data; + memset (&src_data, 0, sizeof (src_data)) ; + src_data.data_in = input; + src_data.data_out = output; + src_data.input_frames = NUM_FRAMES; + src_data.output_frames = NUM_FRAMES; + src_data.src_ratio = src_ratio; + + if ((error = src_simple (&src_data, converter, channels))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + if (src_data.input_frames_used == 0) + { printf ("\n\nLine %d : No input frames used.\n\n", __LINE__) ; + exit (1) ; + } ; + if (src_data.output_frames_gen == 0) + { printf ("\n\nLine %d : No output frames generated.\n\n", __LINE__) ; + exit (1) ; + } ; + free(input); + free(output); + puts ("ok") ; +} + + +static void +simple_test (int converter, double src_ratio) +{ static float input [BUFFER_LEN], output [BUFFER_LEN] ; + + SRC_DATA src_data ; + + int input_len, output_len, error, terminate ; + + printf ("\tsimple_test\t(SRC ratio = %6.4f) ................. ", src_ratio) ; + fflush (stdout) ; + + /* Calculate maximun input and output lengths. */ + if (src_ratio >= 1.0) + { output_len = BUFFER_LEN ; + input_len = (int) floor (BUFFER_LEN / src_ratio) ; + } + else + { input_len = BUFFER_LEN ; + output_len = (int) floor (BUFFER_LEN * src_ratio) ; + } ; + + /* Reduce input_len by 10 so output is longer than necessary. */ + input_len -= 10 ; + + if (output_len > BUFFER_LEN) + { printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ; + exit (1) ; + } ; + + memset (&src_data, 0, sizeof (src_data)) ; + + src_data.data_in = input ; + src_data.input_frames = input_len ; + + src_data.src_ratio = src_ratio ; + + src_data.data_out = output ; + src_data.output_frames = BUFFER_LEN ; + + if ((error = src_simple (&src_data, converter, 1))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; + + if (fabs (src_data.output_frames_gen - src_ratio * input_len) > 2 * terminate) + { printf ("\n\nLine %d : bad output data length %ld should be %d.\n", __LINE__, + src_data.output_frames_gen, (int) floor (src_ratio * input_len)) ; + printf ("\tsrc_ratio : %.4f\n", src_ratio) ; + printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* simple_test */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/snr_bw_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/snr_bw_test.c new file mode 100755 index 00000000..223a637f --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/snr_bw_test.c @@ -0,0 +1,404 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <time.h> + +#if (HAVE_FFTW3) + +#include <fftw3.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN 50000 +#define MAX_FREQS 4 +#define MAX_RATIOS 6 +#define MAX_SPEC_LEN (1<<15) + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338 +#endif + +enum +{ BOOLEAN_FALSE = 0, + BOOLEAN_TRUE = 1 +} ; + +typedef struct +{ int freq_count ; + double freqs [MAX_FREQS] ; + + double src_ratio ; + int pass_band_peaks ; + + double snr ; + double peak_value ; +} SINGLE_TEST ; + +typedef struct +{ int converter ; + int tests ; + int do_bandwidth_test ; + SINGLE_TEST test_data [10] ; +} CONVERTER_TEST ; + +static double snr_test (SINGLE_TEST *snr_test_data, int number, int converter, int verbose) ; +static double find_peak (float *output, int output_len) ; +static double bandwidth_test (int converter, int verbose) ; + +int +main (int argc, char *argv []) +{ CONVERTER_TEST snr_test_data [] = + { + { SRC_ZERO_ORDER_HOLD, + 8, + BOOLEAN_FALSE, + { { 1, { 0.01111111111 }, 3.0, 1, 28.0, 1.0 }, + { 1, { 0.01111111111 }, 0.6, 1, 36.0, 1.0 }, + { 1, { 0.01111111111 }, 0.3, 1, 36.0, 1.0 }, + { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 }, + { 1, { 0.01111111111 }, 1.001, 1, 38.0, 1.0 }, + { 2, { 0.011111, 0.324 }, 1.9999, 2, 14.0, 1.0 }, + { 2, { 0.012345, 0.457 }, 0.456789, 1, 12.0, 1.0 }, + { 1, { 0.3511111111 }, 1.33, 1, 10.0, 1.0 } + } + }, + + { SRC_LINEAR, + 8, + BOOLEAN_FALSE, + { { 1, { 0.01111111111 }, 3.0, 1, 73.0, 1.0 }, + { 1, { 0.01111111111 }, 0.6, 1, 73.0, 1.0 }, + { 1, { 0.01111111111 }, 0.3, 1, 73.0, 1.0 }, + { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 }, + { 1, { 0.01111111111 }, 1.001, 1, 77.0, 1.0 }, + { 2, { 0.011111, 0.324 }, 1.9999, 2, 15.0, 0.94 }, + { 2, { 0.012345, 0.457 }, 0.456789, 1, 25.0, 0.96 }, + { 1, { 0.3511111111 }, 1.33, 1, 22.0, 0.99 } + } + }, + +#ifdef ENABLE_SINC_FAST_CONVERTER + { SRC_SINC_FASTEST, + 9, + BOOLEAN_TRUE, + { { 1, { 0.01111111111 }, 3.0, 1, 100.0, 1.0 }, + { 1, { 0.01111111111 }, 0.6, 1, 99.0, 1.0 }, + { 1, { 0.01111111111 }, 0.3, 1, 100.0, 1.0 }, + { 1, { 0.01111111111 }, 1.0, 1, 150.0, 1.0 }, + { 1, { 0.01111111111 }, 1.001, 1, 100.0, 1.0 }, + { 2, { 0.011111, 0.324 }, 1.9999, 2, 97.0, 1.0 }, + { 2, { 0.012345, 0.457 }, 0.456789, 1, 100.0, 0.5 }, + { 2, { 0.011111, 0.45 }, 0.6, 1, 97.0, 0.5 }, + { 1, { 0.3511111111 }, 1.33, 1, 97.0, 1.0 } + } + }, +#endif + +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + { SRC_SINC_MEDIUM_QUALITY, + 9, + BOOLEAN_TRUE, + { { 1, { 0.01111111111 }, 3.0, 1, 145.0, 1.0 }, + { 1, { 0.01111111111 }, 0.6, 1, 132.0, 1.0 }, + { 1, { 0.01111111111 }, 0.3, 1, 138.0, 1.0 }, + { 1, { 0.01111111111 }, 1.0, 1, 157.0, 1.0 }, + { 1, { 0.01111111111 }, 1.001, 1, 148.0, 1.0 }, + { 2, { 0.011111, 0.324 }, 1.9999, 2, 127.0, 1.0 }, + { 2, { 0.012345, 0.457 }, 0.456789, 1, 123.0, 0.5 }, + { 2, { 0.011111, 0.45 }, 0.6, 1, 126.0, 0.5 }, + { 1, { 0.43111111111 }, 1.33, 1, 121.0, 1.0 } + } + }, +#endif + +#ifdef ENABLE_SINC_BEST_CONVERTER + { SRC_SINC_BEST_QUALITY, + 9, + BOOLEAN_TRUE, + { { 1, { 0.01111111111 }, 3.0, 1, 147.0, 1.0 }, + { 1, { 0.01111111111 }, 0.6, 1, 147.0, 1.0 }, + { 1, { 0.01111111111 }, 0.3, 1, 148.0, 1.0 }, + { 1, { 0.01111111111 }, 1.0, 1, 155.0, 1.0 }, + { 1, { 0.01111111111 }, 1.001, 1, 148.0, 1.0 }, + { 2, { 0.011111, 0.324 }, 1.9999, 2, 146.0, 1.0 }, + { 2, { 0.012345, 0.457 }, 0.456789, 1, 147.0, 0.5 }, + { 2, { 0.011111, 0.45 }, 0.6, 1, 144.0, 0.5 }, + { 1, { 0.43111111111 }, 1.33, 1, 145.0, 1.0 } + } + }, +#endif + + } ; /* snr_test_data */ + + double best_snr, snr, freq3dB ; + int j, k, converter, verbose = 0 ; + + if (argc == 2 && strcmp (argv [1], "--verbose") == 0) + verbose = 1 ; + + puts ("") ; + + for (j = 0 ; j < ARRAY_LEN (snr_test_data) ; j++) + { best_snr = 5000.0 ; + + converter = snr_test_data [j].converter ; + + printf (" Converter %d : %s\n", converter, src_get_name (converter)) ; + printf (" %s\n", src_get_description (converter)) ; + + for (k = 0 ; k < snr_test_data [j].tests ; k++) + { snr = snr_test (&(snr_test_data [j].test_data [k]), k, converter, verbose) ; + if (best_snr > snr) + best_snr = snr ; + } ; + + printf (" Worst case Signal-to-Noise Ratio : %.2f dB.\n", best_snr) ; + + if (snr_test_data [j].do_bandwidth_test == BOOLEAN_FALSE) + { puts (" Bandwith test not performed on this converter.\n") ; + continue ; + } + + freq3dB = bandwidth_test (converter, verbose) ; + + printf (" Measured -3dB rolloff point : %5.2f %%.\n\n", freq3dB) ; + } ; + + fftw_cleanup () ; + + return 0 ; +} /* main */ + +/*============================================================================== +*/ + +static double +snr_test (SINGLE_TEST *test_data, int number, int converter, int verbose) +{ static float data [BUFFER_LEN + 1] ; + static float output [MAX_SPEC_LEN] ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + + double output_peak, snr ; + int k, output_len, input_len, error ; + + if (verbose != 0) + { printf ("\tSignal-to-Noise Ratio Test %d.\n" + "\t=====================================\n", number) ; + printf ("\tFrequencies : [ ") ; + for (k = 0 ; k < test_data->freq_count ; k++) + printf ("%6.4f ", test_data->freqs [k]) ; + + printf ("]\n\tSRC Ratio : %8.4f\n", test_data->src_ratio) ; + } + else + { printf ("\tSignal-to-Noise Ratio Test %d : ", number) ; + fflush (stdout) ; + } ; + + /* Set up the output array. */ + if (test_data->src_ratio >= 1.0) + { output_len = MAX_SPEC_LEN ; + input_len = (int) ceil (MAX_SPEC_LEN / test_data->src_ratio) ; + if (input_len > BUFFER_LEN) + input_len = BUFFER_LEN ; + } + else + { input_len = BUFFER_LEN ; + output_len = (int) ceil (BUFFER_LEN * test_data->src_ratio) ; + output_len &= ((~0u) << 4) ; + if (output_len > MAX_SPEC_LEN) + output_len = MAX_SPEC_LEN ; + input_len = (int) ceil (output_len / test_data->src_ratio) ; + } ; + + memset (output, 0, sizeof (output)) ; + + /* Generate input data array. */ + gen_windowed_sines (test_data->freq_count, test_data->freqs, 1.0, data, input_len) ; + + /* Perform sample rate conversion. */ + if ((src_state = src_new (converter, 1, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s.\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.end_of_input = 1 ; /* Only one buffer worth of input. */ + + src_data.data_in = data ; + src_data.input_frames = input_len ; + + src_data.src_ratio = test_data->src_ratio ; + + src_data.data_out = output ; + src_data.output_frames = output_len ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_state = src_delete (src_state) ; + + if (verbose != 0) + printf ("\tOutput Len : %ld\n", src_data.output_frames_gen) ; + + if (abs ((int) (src_data.output_frames_gen - output_len)) > 4) + { printf ("\n\nLine %d : output data length should be %d.\n\n", __LINE__, output_len) ; + exit (1) ; + } ; + + /* Check output peak. */ + output_peak = find_peak (output, src_data.output_frames_gen) ; + + if (verbose != 0) + printf ("\tOutput Peak : %6.4f\n", output_peak) ; + + if (fabs (output_peak - test_data->peak_value) > 0.01) + { printf ("\n\nLine %d : output peak (%6.4f) should be %6.4f\n\n", __LINE__, output_peak, test_data->peak_value) ; + save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, output_len) ; + exit (1) ; + } ; + + /* Calculate signal-to-noise ratio. */ + snr = calculate_snr (output, src_data.output_frames_gen, test_data->pass_band_peaks) ; + + if (snr < 0.0) + { /* An error occurred. */ + save_oct_float ("snr_test.dat", data, BUFFER_LEN, output, src_data.output_frames_gen) ; + exit (1) ; + } ; + + if (verbose != 0) + printf ("\tSNR Ratio : %.2f dB\n", snr) ; + + if (snr < test_data->snr) + { printf ("\n\nLine %d : SNR (%5.2f) should be > %6.2f dB\n\n", __LINE__, snr, test_data->snr) ; + exit (1) ; + } ; + + if (verbose != 0) + puts ("\t-------------------------------------\n\tPass\n") ; + else + puts ("Pass") ; + + return snr ; +} /* snr_test */ + +static double +find_peak (float *data, int len) +{ double peak = 0.0 ; + int k = 0 ; + + for (k = 0 ; k < len ; k++) + if (fabs (data [k]) > peak) + peak = fabs (data [k]) ; + + return peak ; +} /* find_peak */ + + +static double +find_attenuation (double freq, int converter, int verbose) +{ static float input [BUFFER_LEN] ; + static float output [2 * BUFFER_LEN] ; + + SRC_DATA src_data ; + double output_peak ; + int error ; + + gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ; + + src_data.end_of_input = 1 ; /* Only one buffer worth of input. */ + + src_data.data_in = input ; + src_data.input_frames = BUFFER_LEN ; + + src_data.src_ratio = 1.999 ; + + src_data.data_out = output ; + src_data.output_frames = ARRAY_LEN (output) ; + + if ((error = src_simple (&src_data, converter, 1))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + output_peak = find_peak (output, ARRAY_LEN (output)) ; + + if (verbose) + printf ("\tFreq : %6f InPeak : %6f OutPeak : %6f Atten : %6.2f dB\n", + freq, 1.0, output_peak, 20.0 * log10 (1.0 / output_peak)) ; + + return 20.0 * log10 (1.0 / output_peak) ; +} /* find_attenuation */ + +static double +bandwidth_test (int converter, int verbose) +{ double f1, f2, a1, a2 ; + double freq, atten ; + + f1 = 0.35 ; + a1 = find_attenuation (f1, converter, verbose) ; + + f2 = 0.495 ; + a2 = find_attenuation (f2, converter, verbose) ; + + if (a1 > 3.0 || a2 < 3.0) + { printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ; + exit (1) ; + } ; + + while (a2 - a1 > 1.0) + { freq = f1 + 0.5 * (f2 - f1) ; + atten = find_attenuation (freq, converter, verbose) ; + + if (atten < 3.0) + { f1 = freq ; + a1 = atten ; + } + else + { f2 = freq ; + a2 = atten ; + } ; + } ; + + freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ; + + return 200.0 * freq ; +} /* bandwidth_test */ + +#else /* (HAVE_FFTW3) == 0 */ + +/* Alternative main function when librfftw is not available. */ + +int +main (void) +{ puts ("\n" + "****************************************************************\n" + " This test cannot be run without FFTW (http://www.fftw.org/).\n" + " Both the real and the complex versions of the library are\n" + " required.") ; + puts ("****************************************************************\n") ; + + return 0 ; +} /* main */ + +#endif + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/src-evaluate.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/src-evaluate.c new file mode 100755 index 00000000..d55d6483 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/src-evaluate.c @@ -0,0 +1,530 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <ctype.h> + +#if defined(_WIN32) +#define popen _popen +#define pclose _pclose +#endif + +#if (HAVE_FFTW3 && HAVE_SNDFILE && HAVE_SYS_TIMES_H) + +#include <time.h> +#include <sys/times.h> + +#include <sndfile.h> +#include <math.h> +#include <sys/utsname.h> + +#include "util.h" + +#define MAX_FREQS 4 +#define BUFFER_LEN 80000 + +#define SAFE_STRNCAT(dest,src,len) \ + { int safe_strncat_count ; \ + safe_strncat_count = (len) - strlen (dest) - 1 ; \ + strncat ((dest), (src), safe_strncat_count) ; \ + (dest) [(len) - 1] = 0 ; \ + } ; + +typedef struct +{ int freq_count ; + double freqs [MAX_FREQS] ; + + int output_samplerate ; + int pass_band_peaks ; + + double peak_value ; +} SNR_TEST ; + +typedef struct +{ const char *progname ; + const char *version_cmd ; + const char *version_start ; + const char *convert_cmd ; + int format ; +} RESAMPLE_PROG ; + +static char *get_progname (char *) ; +static void usage_exit (const char *, const RESAMPLE_PROG *prog, int count) ; +static void measure_program (const RESAMPLE_PROG *prog, int verbose) ; +static void generate_source_wav (const char *filename, const double *freqs, int freq_count, int format) ; +static const char* get_machine_details (void) ; + +static char version_string [512] ; + +int +main (int argc, char *argv []) +{ static RESAMPLE_PROG resample_progs [] = + { { "sndfile-resample", + "examples/sndfile-resample --version", + "libsamplerate", + "examples/sndfile-resample --max-speed -c 0 -to %d source.wav destination.wav", + SF_FORMAT_WAV | SF_FORMAT_PCM_32 + }, + { "sox", + "sox -h 2>&1", + "sox", + "sox source.wav -r %d destination.wav resample 0.835", + SF_FORMAT_WAV | SF_FORMAT_PCM_32 + }, + { "ResampAudio", + "ResampAudio --version", + "ResampAudio", + "ResampAudio -f cutoff=0.41,atten=100,ratio=128 -s %d source.wav destination.wav", + SF_FORMAT_WAV | SF_FORMAT_PCM_32 + }, + + /*- + { /+* + ** The Shibatch converter doesn't work for all combinations of + ** source and destination sample rates. Therefore it can't be + ** included in this test. + *+/ + "shibatch", + "ssrc", + "Shibatch", + "ssrc --rate %d source.wav destination.wav", + SF_FORMAT_WAV | SF_FORMAT_PCM_32 + },-*/ + + /*- + { /+* + ** The resample program is not able to match the bandwidth and SNR + ** specs or sndfile-resample and hence will not be tested. + *+/ + "resample", + "resample -version", + "resample", + "resample -to %d source.wav destination.wav", + SF_FORMAT_WAV | SF_FORMAT_FLOAT + },-*/ + + /*- + { "mplayer", + "mplayer -v 2>&1", + "MPlayer ", + "mplayer -ao pcm -srate %d source.wav >/dev/null 2>&1 && mv audiodump.wav destination.wav", + SF_FORMAT_WAV | SF_FORMAT_PCM_32 + },-*/ + + } ; /* resample_progs */ + + char *progname ; + int prog = 0, verbose = 0 ; + + progname = get_progname (argv [0]) ; + + printf ("\n %s : evaluate a sample rate converter.\n", progname) ; + + if (argc == 3 && strcmp ("--verbose", argv [1]) == 0) + { verbose = 1 ; + prog = atoi (argv [2]) ; + } + else if (argc == 2) + { verbose = 0 ; + prog = atoi (argv [1]) ; + } + else + usage_exit (progname, resample_progs, ARRAY_LEN (resample_progs)) ; + + if (prog < 0 || prog >= ARRAY_LEN (resample_progs)) + usage_exit (progname, resample_progs, ARRAY_LEN (resample_progs)) ; + + measure_program (& (resample_progs [prog]), verbose) ; + + puts ("") ; + + return 0 ; +} /* main */ + +/*============================================================================== +*/ + +static char * +get_progname (char *progname) +{ char *cptr ; + + if ((cptr = strrchr (progname, '/')) != NULL) + progname = cptr + 1 ; + + if ((cptr = strrchr (progname, '\\')) != NULL) + progname = cptr + 1 ; + + return progname ; +} /* get_progname */ + +static void +usage_exit (const char *progname, const RESAMPLE_PROG *prog, int count) +{ int k ; + + printf ("\n Usage : %s <number>\n\n", progname) ; + + puts (" where <number> specifies the program to test:\n") ; + + for (k = 0 ; k < count ; k++) + printf (" %d : %s\n", k, prog [k].progname) ; + + puts ("\n" + " Obviously to test a given program you have to have it available on\n" + " your system. See http://libsndfile.github.io/libsamplerate/quality.html for\n" + " the download location of these programs.\n") ; + + exit (1) ; +} /* usage_exit */ + +static const char* +get_machine_details (void) +{ static char namestr [262] ; + + struct utsname name ; + + if (uname (&name) != 0) + { snprintf (namestr, sizeof (namestr), "Unknown") ; + return namestr ; + } ; + + snprintf (namestr, sizeof (namestr), "%s (%s %s %s)", name.nodename, + name.machine, name.sysname, name.release) ; + + return namestr ; +} /* get_machine_details */ + + +/*============================================================================== +*/ + +static void +get_version_string (const RESAMPLE_PROG *prog) +{ FILE *file ; + char *cptr ; + + /* Default. */ + snprintf (version_string, sizeof (version_string), "no version") ; + + if (prog->version_cmd == NULL) + return ; + + if ((file = popen (prog->version_cmd, "r")) == NULL) + return ; + + while ((cptr = fgets (version_string, sizeof (version_string), file)) != NULL) + { + if (strstr (cptr, prog->version_start) != NULL) + break ; + + version_string [0] = 0 ; + } ; + + pclose (file) ; + + /* Remove trailing newline. */ + if ((cptr = strchr (version_string, '\n')) != NULL) + cptr [0] = 0 ; + + /* Remove leading whitespace from version string. */ + cptr = version_string ; + while (cptr [0] != 0 && isspace (cptr [0])) + cptr ++ ; + + if (cptr != version_string) + { strncpy (version_string, cptr, sizeof (version_string) - 1) ; + version_string [sizeof (version_string) - 1] = 0 ; + } ; + + return ; +} /* get_version_string */ + +static void +generate_source_wav (const char *filename, const double *freqs, int freq_count, int format) +{ static float buffer [BUFFER_LEN] ; + + SNDFILE *sndfile ; + SF_INFO sfinfo ; + + sfinfo.channels = 1 ; + sfinfo.samplerate = 44100 ; + sfinfo.format = format ; + + if ((sndfile = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) + { printf ("Line %d : cound not open '%s' : %s\n", __LINE__, filename, sf_strerror (NULL)) ; + exit (1) ; + } ; + + sf_command (sndfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ; + + gen_windowed_sines (freq_count, freqs, 0.9, buffer, ARRAY_LEN (buffer)) ; + + if (sf_write_float (sndfile, buffer, ARRAY_LEN (buffer)) != ARRAY_LEN (buffer)) + { printf ("Line %d : sf_write_float short write.\n", __LINE__) ; + exit (1) ; + } ; + + sf_close (sndfile) ; +} /* generate_source_wav */ + +static double +measure_destination_wav (char *filename, int *output_samples, int expected_peaks) +{ static float buffer [250000] ; + + SNDFILE *sndfile ; + SF_INFO sfinfo ; + double snr ; + + if ((sndfile = sf_open (filename, SFM_READ, &sfinfo)) == NULL) + { printf ("Line %d : Cound not open '%s' : %s\n", __LINE__, filename, sf_strerror (NULL)) ; + exit (1) ; + } ; + + if (sfinfo.channels != 1) + { printf ("Line %d : Bad channel count (%d). Should be 1.\n", __LINE__, sfinfo.channels) ; + exit (1) ; + } ; + + if (sfinfo.frames > ARRAY_LEN (buffer)) + { printf ("Line %d : Too many frames (%ld) of data in file.\n", __LINE__, (long) sfinfo.frames) ; + exit (1) ; + } ; + + *output_samples = (int) sfinfo.frames ; + + if (sf_read_float (sndfile, buffer, sfinfo.frames) != sfinfo.frames) + { printf ("Line %d : Bad read.\n", __LINE__) ; + exit (1) ; + } ; + + sf_close (sndfile) ; + + snr = calculate_snr (buffer, sfinfo.frames, expected_peaks) ; + + return snr ; +} /* measure_desination_wav */ + +static double +measure_snr (const RESAMPLE_PROG *prog, int *output_samples, int verbose) +{ static SNR_TEST snr_test [] = + { + { 1, { 0.211111111111 }, 48000, 1, 1.0 }, + { 1, { 0.011111111111 }, 132301, 1, 1.0 }, + { 1, { 0.111111111111 }, 92301, 1, 1.0 }, + { 1, { 0.011111111111 }, 26461, 1, 1.0 }, + { 1, { 0.011111111111 }, 13231, 1, 1.0 }, + { 1, { 0.011111111111 }, 44101, 1, 1.0 }, + { 2, { 0.311111, 0.49 }, 78199, 2, 1.0 }, + { 2, { 0.011111, 0.49 }, 12345, 1, 0.5 }, + { 2, { 0.0123456, 0.4 }, 20143, 1, 0.5 }, + { 2, { 0.0111111, 0.4 }, 26461, 1, 0.5 }, + { 1, { 0.381111111111 }, 58661, 1, 1.0 } + } ; /* snr_test */ + static char command [256] ; + + double snr, worst_snr = 500.0 ; + int k , retval, sample_count ; + + *output_samples = 0 ; + + for (k = 0 ; k < ARRAY_LEN (snr_test) ; k++) + { remove ("source.wav") ; + remove ("destination.wav") ; + + if (verbose) + printf (" SNR test #%d : ", k) ; + fflush (stdout) ; + generate_source_wav ("source.wav", snr_test [k].freqs, snr_test [k].freq_count, prog->format) ; + + snprintf (command, sizeof (command), prog->convert_cmd, snr_test [k].output_samplerate) ; + SAFE_STRNCAT (command, " >/dev/null 2>&1", sizeof (command)) ; + if ((retval = system (command)) != 0) + printf ("system returned %d\n", retval) ; + + snr = measure_destination_wav ("destination.wav", &sample_count, snr_test->pass_band_peaks) ; + + *output_samples += sample_count ; + + if (fabs (snr) < fabs (worst_snr)) + worst_snr = fabs (snr) ; + + if (verbose) + printf ("%6.2f dB\n", snr) ; + } ; + + return worst_snr ; +} /* measure_snr */ + +/*------------------------------------------------------------------------------ +*/ + +static double +measure_destination_peak (const char *filename) +{ static float data [2 * BUFFER_LEN] ; + SNDFILE *sndfile ; + SF_INFO sfinfo ; + double peak = 0.0 ; + int k = 0 ; + + if ((sndfile = sf_open (filename, SFM_READ, &sfinfo)) == NULL) + { printf ("Line %d : failed to open file %s\n", __LINE__, filename) ; + exit (1) ; + } ; + + if (sfinfo.channels != 1) + { printf ("Line %d : bad channel count.\n", __LINE__) ; + exit (1) ; + } ; + + if (sfinfo.frames > ARRAY_LEN (data) + 4 || sfinfo.frames < ARRAY_LEN (data) - 100) + { printf ("Line %d : bad frame count (got %d, expected %d).\n", __LINE__, (int) sfinfo.frames, ARRAY_LEN (data)) ; + exit (1) ; + } ; + + if (sf_read_float (sndfile, data, sfinfo.frames) != sfinfo.frames) + { printf ("Line %d : bad read.\n", __LINE__) ; + exit (1) ; + } ; + + sf_close (sndfile) ; + + for (k = 0 ; k < (int) sfinfo.frames ; k++) + if (fabs (data [k]) > peak) + peak = fabs (data [k]) ; + + return peak ; +} /* measure_destination_peak */ + +static double +find_attenuation (double freq, const RESAMPLE_PROG *prog, int verbose) +{ static char command [256] ; + double output_peak ; + int retval ; + char *filename ; + + filename = "destination.wav" ; + + generate_source_wav ("source.wav", &freq, 1, prog->format) ; + + remove (filename) ; + + snprintf (command, sizeof (command), prog->convert_cmd, 88189) ; + SAFE_STRNCAT (command, " >/dev/null 2>&1", sizeof (command)) ; + if ((retval = system (command)) != 0) + printf ("system returned %d\n", retval) ; + + output_peak = measure_destination_peak (filename) ; + + if (verbose) + printf (" freq : %f peak : %f\n", freq, output_peak) ; + + return fabs (20.0 * log10 (output_peak)) ; +} /* find_attenuation */ + +static double +bandwidth_test (const RESAMPLE_PROG *prog, int verbose) +{ double f1, f2, a1, a2 ; + double freq, atten ; + + f1 = 0.35 ; + a1 = find_attenuation (f1, prog, verbose) ; + + f2 = 0.49999 ; + a2 = find_attenuation (f2, prog, verbose) ; + + + if (fabs (a1) < 1e-2 && a2 < 3.0) + return -1.0 ; + + if (a1 > 3.0 || a2 < 3.0) + { printf ("\n\nLine %d : cannot bracket 3dB point.\n\n", __LINE__) ; + exit (1) ; + } ; + + while (a2 - a1 > 1.0) + { freq = f1 + 0.5 * (f2 - f1) ; + atten = find_attenuation (freq, prog, verbose) ; + + if (atten < 3.0) + { f1 = freq ; + a1 = atten ; + } + else + { f2 = freq ; + a2 = atten ; + } ; + } ; + + freq = f1 + (3.0 - a1) * (f2 - f1) / (a2 - a1) ; + + return 200.0 * freq ; +} /* bandwidth_test */ + +static void +measure_program (const RESAMPLE_PROG *prog, int verbose) +{ double snr, bandwidth, conversion_rate ; + int output_samples ; + struct tms time_data ; + time_t time_now ; + + printf ("\n Machine : %s\n", get_machine_details ()) ; + time_now = time (NULL) ; + printf (" Date : %s", ctime (&time_now)) ; + + get_version_string (prog) ; + printf (" Program : %s\n", version_string) ; + printf (" Command : %s\n\n", prog->convert_cmd) ; + + snr = measure_snr (prog, &output_samples, verbose) ; + + printf (" Worst case SNR : %6.2f dB\n", snr) ; + + times (&time_data) ; + + conversion_rate = (1.0 * output_samples * sysconf (_SC_CLK_TCK)) / time_data.tms_cutime ; + + printf (" Conversion rate : %5.0f samples/sec\n", conversion_rate) ; + + bandwidth = bandwidth_test (prog, verbose) ; + + if (bandwidth > 0.0) + printf (" Measured bandwidth : %5.2f %%\n", bandwidth) ; + else + printf (" Could not measure bandwidth (no -3dB point found).\n") ; + + return ; +} /* measure_program */ + +/*############################################################################## +*/ + +#else + +int +main (void) +{ puts ("\n" + "****************************************************************\n" + " This program has been compiled without :\n" + " 1) FFTW (http://www.fftw.org/).\n" + " 2) libsndfile (http://www.zip.com.au/~erikd/libsndfile/).\n" + " Without these two libraries there is not much it can do.\n" + "****************************************************************\n") ; + + return 0 ; +} /* main */ + +#endif /* (HAVE_FFTW3 && HAVE_SNDFILE) */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/streaming_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/streaming_test.c new file mode 100755 index 00000000..45ad2516 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/streaming_test.c @@ -0,0 +1,149 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN (1<<15) + +#define BLOCK_LEN 100 + +static void stream_test (int converter, double ratio) ; + +int +main (void) +{ static double src_ratios [] = + { 0.3, 0.9, 1.1, 3.0 + } ; + + int k ; + + puts ("\n Zero Order Hold interpolator:") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; + + puts ("\n Linear interpolator:") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + stream_test (SRC_LINEAR, src_ratios [k]) ; + + puts ("\n Sinc interpolator:") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + stream_test (SRC_SINC_FASTEST, src_ratios [k]) ; + + puts ("") ; + + return 0 ; +} /* main */ + +static void +stream_test (int converter, double src_ratio) +{ static float input [BUFFER_LEN], output [BUFFER_LEN] ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + + int input_len, output_len, current_in, current_out ; + int error, terminate ; + + printf ("\tstreaming_test (SRC ratio = %6.4f) ........... ", src_ratio) ; + fflush (stdout) ; + + /* Calculate maximun input and output lengths. */ + if (src_ratio >= 1.0) + { output_len = BUFFER_LEN ; + input_len = (int) floor (BUFFER_LEN / src_ratio) ; + } + else + { input_len = BUFFER_LEN ; + output_len = (int) floor (BUFFER_LEN * src_ratio) ; + } ; + + /* Reduce input_len by 10 so output is longer than necessary. */ + input_len -= 10 ; + + if (output_len > BUFFER_LEN) + { printf ("\n\nLine %d : output_len > BUFFER_LEN\n\n", __LINE__) ; + exit (1) ; + } ; + + current_in = current_out = 0 ; + + /* Perform sample rate conversion. */ + if ((src_state = src_new (converter, 1, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.end_of_input = 0 ; /* Set this later. */ + + src_data.data_in = input ; + src_data.input_frames = BLOCK_LEN ; + + src_data.src_ratio = src_ratio ; + + src_data.data_out = output ; + src_data.output_frames = BLOCK_LEN ; + + while (1) + { if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + +printf ("src_data.input_frames : %ld\n", src_data.input_frames) ; +printf ("src_data.output_frames : %ld\n", src_data.output_frames) ; + + exit (1) ; + } ; + + if (src_data.end_of_input && src_data.output_frames_gen == 0) + break ; + + current_in += src_data.input_frames_used ; + current_out += src_data.output_frames_gen ; + + src_data.data_in += src_data.input_frames_used ; + src_data.data_out += src_data.output_frames_gen ; + + src_data.input_frames = MIN (BLOCK_LEN, input_len - current_in) ; + src_data.output_frames = MIN (BLOCK_LEN, output_len - current_out) ; + + src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ; + } ; + + src_state = src_delete (src_state) ; + + terminate = (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; + + if (fabs (current_out - src_ratio * input_len) > 2 * terminate) + { printf ("\n\nLine %d : bad output data length %d should be %d.\n", __LINE__, + current_out, (int) floor (src_ratio * input_len)) ; + printf ("\tsrc_ratio : %.4f\n", src_ratio) ; + printf ("\tinput_len : %d\n\toutput_len : %d\n\n", input_len, output_len) ; + exit (1) ; + } ; + + if (current_in != input_len) + { printf ("\n\nLine %d : unused input.\n", __LINE__) ; + printf ("\tinput_len : %d\n", input_len) ; + printf ("\tinput_frames_used : %d\n\n", current_in) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* stream_test */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/termination_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/termination_test.c new file mode 100755 index 00000000..0b27a217 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/termination_test.c @@ -0,0 +1,342 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include <samplerate.h> + +#include "util.h" + +#define SHORT_BUFFER_LEN 2048 +#define LONG_BUFFER_LEN ((1 << 16) - 20) + +#ifdef ENABLE_SINC_FAST_CONVERTER +static void simple_test (int converter) ; +#endif +static void stream_test (int converter, double ratio) ; +static void init_term_test (int converter, double ratio) ; + +static int next_block_length (int reset) ; + +int +main (void) +{ static double src_ratios [] = + { 0.999900, 1.000100, 0.789012, 1.200000, 0.333333, 3.100000, + 0.125000, 8.000000, 0.099900, 9.990000, 0.100000, 10.00000 + } ; + + int k ; + + puts ("\n Zero Order Hold interpolator:") ; + + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + init_term_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; + puts ("") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + stream_test (SRC_ZERO_ORDER_HOLD, src_ratios [k]) ; + + + puts ("\n Linear interpolator:") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + init_term_test (SRC_LINEAR, src_ratios [k]) ; + puts ("") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + stream_test (SRC_LINEAR, src_ratios [k]) ; + + +#ifdef ENABLE_SINC_FAST_CONVERTER + puts ("\n Sinc interpolator:") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + init_term_test (SRC_SINC_FASTEST, src_ratios [k]) ; + puts ("") ; + for (k = 0 ; k < ARRAY_LEN (src_ratios) ; k++) + stream_test (SRC_SINC_FASTEST, src_ratios [k]) ; + + puts ("") ; + + simple_test (SRC_SINC_FASTEST) ; +#endif + + return 0 ; +} /* main */ + +#ifdef ENABLE_SINC_FAST_CONVERTER +static void +simple_test (int converter) +{ + // MSVC doesn't support variable-length arrays + #define ilen 199030 + #define olen 1000 + int error ; + + { + float in [ilen] ; + float out [olen] ; + double ratio = (1.0 * olen) / ilen ; + SRC_DATA src_data = + { in, out, + ilen, olen, + 0, 0, 0, + ratio + } ; + + error = src_simple (&src_data, converter, 1) ; + if (error) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + } ; + + return ; +} /* simple_test */ +#endif + +static void +init_term_test (int converter, double src_ratio) +{ static float input [SHORT_BUFFER_LEN], output [SHORT_BUFFER_LEN] ; + + SRC_DATA src_data ; + + int k, input_len, output_len, error, terminate ; + + printf ("\tinit_term_test (SRC ratio = %7.4f) .......... ", src_ratio) ; + fflush (stdout) ; + + /* Calculate maximun input and output lengths. */ + if (src_ratio >= 1.0) + { output_len = SHORT_BUFFER_LEN ; + input_len = (int) floor (SHORT_BUFFER_LEN / src_ratio) ; + } + else + { input_len = SHORT_BUFFER_LEN ; + output_len = (int) floor (SHORT_BUFFER_LEN * src_ratio) ; + } ; + + /* Reduce input_len by 10 so output is longer than necessary. */ + input_len -= 10 ; + + for (k = 0 ; k < ARRAY_LEN (input) ; k++) + input [k] = 1.0 ; + + if (output_len > SHORT_BUFFER_LEN) + { printf ("\n\nLine %d : output_len > SHORT_BUFFER_LEN\n\n", __LINE__) ; + exit (1) ; + } ; + + src_data.data_in = input ; + src_data.input_frames = input_len ; + + src_data.src_ratio = src_ratio ; + + src_data.data_out = output ; + src_data.output_frames = SHORT_BUFFER_LEN ; + + if ((error = src_simple (&src_data, converter, 1))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + terminate = (int) ceil ((src_ratio >= 1.0) ? 1 : 1.0 / src_ratio) ; + + if (fabs (src_ratio * input_len - src_data.output_frames_gen) > terminate) + { printf ("\n\nLine %d : Bad output frame count.\n\n", __LINE__) ; + printf ("\tterminate : %d\n", terminate) ; + printf ("\tsrc_ratio : %.4f\n", src_ratio) ; + printf ("\tinput_len : %d\n" + "\tinput_len * src_ratio : %f\n", input_len, input_len * src_ratio) ; + printf ("\toutput_frames_gen : %ld\n\n", src_data.output_frames_gen) ; + exit (1) ; + } ; + + if (labs (src_data.input_frames_used - input_len) > 1) + { printf ("\n\nLine %d : input_frames_used should be %d, is %ld.\n\n", + __LINE__, input_len, src_data.input_frames_used) ; + printf ("\tsrc_ratio : %.4f\n", src_ratio) ; + printf ("\tinput_len : %d\n\tinput_used : %ld\n\n", input_len, src_data.input_frames_used) ; + exit (1) ; + } ; + + if (fabs (output [0]) < 0.1) + { printf ("\n\nLine %d : First output sample is bad.\n\n", __LINE__) ; + printf ("\toutput [0] == %f\n\n", output [0]) ; + exit (1) ; + } + + puts ("ok") ; + + return ; +} /* init_term_test */ + +static void +stream_test (int converter, double src_ratio) +{ static float input [LONG_BUFFER_LEN], output [LONG_BUFFER_LEN] ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + + int input_len, output_len, current_in, current_out ; + int k, error, terminate ; + + printf ("\tstream_test (SRC ratio = %7.4f) .......... ", src_ratio) ; + fflush (stdout) ; + +/* Erik */ +for (k = 0 ; k < LONG_BUFFER_LEN ; k++) input [k] = k * 1.0f ; + + /* Calculate maximun input and output lengths. */ + if (src_ratio >= 1.0) + { output_len = LONG_BUFFER_LEN ; + input_len = (int) floor (LONG_BUFFER_LEN / src_ratio) ; + } + else + { input_len = LONG_BUFFER_LEN ; + output_len = (int) floor (LONG_BUFFER_LEN * src_ratio) ; + } ; + + /* Reduce input_len by 10 so output is longer than necessary. */ + input_len -= 20 ; + + if (output_len > LONG_BUFFER_LEN) + { printf ("\n\nLine %d : output_len > LONG_BUFFER_LEN\n\n", __LINE__) ; + exit (1) ; + } ; + + current_in = current_out = 0 ; + + /* Perform sample rate conversion. */ + if ((src_state = src_new (converter, 1, &error)) == NULL) + { printf ("\n\nLine %d : src_new() failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.end_of_input = 0 ; /* Set this later. */ + + src_data.data_in = input ; + + src_data.src_ratio = src_ratio ; + + src_data.data_out = output ; + src_data.output_frames = ARRAY_LEN (output) / 10 ; + + terminate = 1 + (int) ceil ((src_ratio >= 1.0) ? src_ratio : 1.0 / src_ratio) ; + + while (1) + { + src_data.input_frames = next_block_length (0) ; + src_data.input_frames = MIN (src_data.input_frames, input_len - current_in) ; + + src_data.output_frames = ARRAY_LEN (output) - current_out ; + /*-Erik MIN (src_data.output_frames, output_len - current_out) ;-*/ + + src_data.end_of_input = (current_in >= input_len) ? 1 : 0 ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; + exit (1) ; + } ; + + if (src_data.end_of_input && src_data.output_frames_gen == 0) + break ; + + if (src_data.input_frames_used > src_data.input_frames) + { printf ("\n\nLine %d : input_frames_used > input_frames\n\n", __LINE__) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.input_frames_used : %ld\n", src_data.input_frames_used) ; + printf (" src_data.output_frames : %ld\n", src_data.output_frames) ; + printf (" src_data.output_frames_gen : %ld\n\n", src_data.output_frames_gen) ; + exit (1) ; + } ; + + if (src_data.input_frames_used < 0) + { printf ("\n\nLine %d : input_frames_used (%ld) < 0\n\n", __LINE__, src_data.input_frames_used) ; + exit (1) ; + } ; + + if (src_data.output_frames_gen < 0) + { printf ("\n\nLine %d : output_frames_gen (%ld) < 0\n\n", __LINE__, src_data.output_frames_gen) ; + exit (1) ; + } ; + + current_in += src_data.input_frames_used ; + current_out += src_data.output_frames_gen ; + + if (current_in > input_len + terminate) + { printf ("\n\nLine %d : current_in (%d) > input_len (%d + %d)\n\n", __LINE__, current_in, input_len, terminate) ; + exit (1) ; + } ; + + if (current_out > output_len) + { printf ("\n\nLine %d : current_out (%d) > output_len (%d)\n\n", __LINE__, current_out, output_len) ; + exit (1) ; + } ; + + if (src_data.input_frames_used > input_len) + { printf ("\n\nLine %d : input_frames_used (%ld) > %d\n\n", __LINE__, src_data.input_frames_used, input_len) ; + exit (1) ; + } ; + + if (src_data.output_frames_gen > output_len) + { printf ("\n\nLine %d : output_frames_gen (%ld) > %d\n\n", __LINE__, src_data.output_frames_gen, output_len) ; + exit (1) ; + } ; + + if (src_data.data_in == NULL && src_data.output_frames_gen == 0) + break ; + + + src_data.data_in += src_data.input_frames_used ; + src_data.data_out += src_data.output_frames_gen ; + } ; + + src_state = src_delete (src_state) ; + + if (fabs (current_out - src_ratio * input_len) > terminate) + { printf ("\n\nLine %d : bad output data length %d should be %2.1f +/- %d.\n", __LINE__, + current_out, src_ratio * input_len, terminate) ; + printf ("\tsrc_ratio : %.4f\n", src_ratio) ; + printf ("\tinput_len : %d\n\tinput_used : %d\n", input_len, current_in) ; + printf ("\toutput_len : %d\n\toutput_gen : %d\n\n", output_len, current_out) ; + exit (1) ; + } ; + + if (current_in != input_len) + { printf ("\n\nLine %d : unused input.\n", __LINE__) ; + printf ("\tinput_len : %d\n", input_len) ; + printf ("\tinput_frames_used : %d\n\n", current_in) ; + exit (1) ; + } ; + + puts ("ok") ; + + return ; +} /* stream_test */ + +static int +next_block_length (int reset) +{ static int block_lengths [] = /* Should be an odd length. */ + { /*-2, 500, 5, 400, 10, 300, 20, 200, 50, 100, 70 -*/ + 5, 400, 10, 300, 20, 200, 50, 100, 70 + } ; + static int block_len_index = 0 ; + + if (reset) + block_len_index = 0 ; + else + block_len_index = (block_len_index + 1) % ARRAY_LEN (block_lengths) ; + + return block_lengths [block_len_index] ; +} /* next_block_length */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/throughput_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/throughput_test.c new file mode 100755 index 00000000..e9974800 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/throughput_test.c @@ -0,0 +1,253 @@ +/* +** Copyright (c) 2004-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <math.h> + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#endif + +#include <samplerate.h> + +#include "util.h" + +#define BUFFER_LEN (1<<16) + +static float input [BUFFER_LEN] ; +static float output [BUFFER_LEN] ; + +static long +throughput_test (int converter, long best_throughput) +{ SRC_DATA src_data ; + clock_t start_time, clock_time ; + double duration ; + long total_frames = 0, throughput ; + int error ; + + printf (" %-30s ", src_get_name (converter)) ; + fflush (stdout) ; + + src_data.data_in = input ; + src_data.input_frames = ARRAY_LEN (input) ; + + src_data.data_out = output ; + src_data.output_frames = ARRAY_LEN (output) ; + + src_data.src_ratio = 0.99 ; + +#ifdef _WIN32 + Sleep (2000) ; +#else + sleep (2) ; +#endif + + start_time = clock () ; + + do + { + if ((error = src_simple (&src_data, converter, 1)) != 0) + { puts (src_strerror (error)) ; + exit (1) ; + } ; + + total_frames += src_data.output_frames_gen ; + + clock_time = clock () - start_time ; +#ifdef __GNU__ /* Clock resolution is 10ms on GNU/Hurd */ + duration = (10000.0 * clock_time) / CLOCKS_PER_SEC ; +#else + duration = (1.0 * clock_time) / CLOCKS_PER_SEC ; +#endif + } + while (duration < 3.0) ; + + if (src_data.input_frames_used != ARRAY_LEN (input)) + { printf ("\n\nLine %d : input frames used %ld should be %d\n", __LINE__, src_data.input_frames_used, ARRAY_LEN (input)) ; + exit (1) ; + } ; + + if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2) + { printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ; + printf (" input len : %d\n", ARRAY_LEN (input)) ; + printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen, + floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ; + exit (1) ; + } ; + + throughput = lrint (floor (total_frames / duration)) ; + + if (best_throughput == 0) + { best_throughput = MAX (throughput, best_throughput) ; + printf ("%5.2f %10ld\n", duration, throughput) ; + } + else + { best_throughput = MAX (throughput, best_throughput) ; + printf ("%5.2f %10ld %10ld\n", duration, throughput, best_throughput) ; + } + + + return best_throughput ; +} /* throughput_test */ + +static void +single_run (void) +{ + + printf ("\n CPU name : %s\n", get_cpu_name ()) ; + + puts ( + "\n" + " Converter Duration Throughput\n" + " -----------------------------------------------------------" + ) ; + + throughput_test (SRC_ZERO_ORDER_HOLD, 0) ; + throughput_test (SRC_LINEAR, 0) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + throughput_test (SRC_SINC_FASTEST, 0) ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + throughput_test (SRC_SINC_MEDIUM_QUALITY, 0) ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + throughput_test (SRC_SINC_BEST_QUALITY, 0) ; +#endif + + puts ("") ; + return ; +} /* single_run */ + +static void +multi_run (int run_count) +{ long zero_order_hold = 0, linear = 0 ; + +#ifdef ENABLE_SINC_FAST_CONVERTER + long sinc_fastest = 0 ; +#endif + +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + long sinc_medium = 0 ; +#endif + +#ifdef ENABLE_SINC_BEST_CONVERTER + long sinc_best = 0 ; +#endif + int k ; + + puts ( + "\n" + " Converter Duration Throughput Best Throughput\n" + " --------------------------------------------------------------------------------" + ) ; + + for (k = 0 ; k < run_count ; k++) + { zero_order_hold = throughput_test (SRC_ZERO_ORDER_HOLD, zero_order_hold) ; + linear = throughput_test (SRC_LINEAR, linear) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + sinc_fastest = throughput_test (SRC_SINC_FASTEST, sinc_fastest) ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + sinc_medium = throughput_test (SRC_SINC_MEDIUM_QUALITY, sinc_medium) ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + sinc_best = throughput_test (SRC_SINC_BEST_QUALITY, sinc_best) ; +#endif + puts ("") ; + + /* Let the CPU cool down. We might be running on a laptop. */ +#ifdef _WIN32 + Sleep (10000) ; +#else + sleep (10) ; +#endif + } ; + + printf ("\n CPU name : %s\n", get_cpu_name ()) ; + + puts ( + "\n" + " Converter Best Throughput\n" + " ------------------------------------------------" + ) ; + printf (" %-30s %10ld\n", src_get_name (SRC_ZERO_ORDER_HOLD), zero_order_hold) ; + printf (" %-30s %10ld\n", src_get_name (SRC_LINEAR), linear) ; +#ifdef ENABLE_SINC_FAST_CONVERTER + printf (" %-30s %10ld\n", src_get_name (SRC_SINC_FASTEST), sinc_fastest) ; +#endif +#ifdef ENABLE_SINC_MEDIUM_CONVERTER + printf (" %-30s %10ld\n", src_get_name (SRC_SINC_MEDIUM_QUALITY), sinc_medium) ; +#endif +#ifdef ENABLE_SINC_BEST_CONVERTER + printf (" %-30s %10ld\n", src_get_name (SRC_SINC_BEST_QUALITY), sinc_best) ; +#endif + + puts ("") ; +} /* multi_run */ + +static void +usage_exit (const char * argv0) +{ const char * cptr ; + + if ((cptr = strrchr (argv0, '/')) != NULL) + argv0 = cptr ; + + printf ( + "Usage :\n" + " %s - Single run of the throughput test.\n" + " %s --best-of N - Do N runs of test a print bext result.\n" + "\n", + argv0, argv0) ; + + exit (0) ; +} /* usage_exit */ + +int +main (int argc, char ** argv) +{ double freq ; + + memset (input, 0, sizeof (input)) ; + freq = 0.01 ; + gen_windowed_sines (1, &freq, 1.0, input, BUFFER_LEN) ; + + if (argc == 1) + single_run () ; + else if (argc == 3 && strcmp (argv [1], "--best-of") == 0) + { int run_count = atoi (argv [2]) ; + + if (run_count < 1 || run_count > 20) + { printf ("Please be sensible. Run count should be in range (1, 10].\n") ; + exit (1) ; + } ; + + multi_run (run_count) ; + } + else + usage_exit (argv [0]) ; + + puts ( + " Duration is in seconds.\n" + " Throughput is in samples/sec (more is better).\n" + ) ; + + return 0 ; +} /* main */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/util.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/util.c new file mode 100755 index 00000000..0e4a2337 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/util.c @@ -0,0 +1,228 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <math.h> + +#include "util.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338 +#endif + +void +gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len) +{ int k, freq ; + double amplitude, phase ; + + amplitude = max / freq_count ; + + for (k = 0 ; k < output_len ; k++) + output [k] = 0.0 ; + + for (freq = 0 ; freq < freq_count ; freq++) + { phase = 0.9 * M_PI / freq_count ; + + if (freqs [freq] <= 0.0 || freqs [freq] >= 0.5) + { printf ("\n%s : Error : freq [%d] == %g is out of range. Should be < 0.5.\n", __FILE__, freq, freqs [freq]) ; + exit (1) ; + } ; + + for (k = 0 ; k < output_len ; k++) + output [k] = (float) (output [k] + (amplitude * sin (freqs [freq] * (2 * k) * M_PI + phase))) ; + } ; + + /* Apply Hanning Window. */ + for (k = 0 ; k < output_len ; k++) + output [k] = (float) (output [k] * (0.5 - 0.5 * cos ((2 * k) * M_PI / (output_len - 1)))) ; + + /* data [k] *= 0.3635819 - 0.4891775 * cos ((2 * k) * M_PI / (output_len - 1)) + + 0.1365995 * cos ((4 * k) * M_PI / (output_len - 1)) + - 0.0106411 * cos ((6 * k) * M_PI / (output_len - 1)) ; + */ + + return ; +} /* gen_windowed_sines */ + +void +save_oct_float (char *filename, float *input, int in_len, float *output, int out_len) +{ FILE *file ; + int k ; + + printf ("Dumping input and output data to file : %s.\n\n", filename) ; + + if (! (file = fopen (filename, "w"))) + return ; + + fprintf (file, "# Not created by Octave\n") ; + + fprintf (file, "# name: input\n") ; + fprintf (file, "# type: matrix\n") ; + fprintf (file, "# rows: %d\n", in_len) ; + fprintf (file, "# columns: 1\n") ; + + for (k = 0 ; k < in_len ; k++) + fprintf (file, "% g\n", input [k]) ; + + fprintf (file, "# name: output\n") ; + fprintf (file, "# type: matrix\n") ; + fprintf (file, "# rows: %d\n", out_len) ; + fprintf (file, "# columns: 1\n") ; + + for (k = 0 ; k < out_len ; k++) + fprintf (file, "% g\n", output [k]) ; + + fclose (file) ; + return ; +} /* save_oct_float */ + +void +save_oct_double (char *filename, double *input, int in_len, double *output, int out_len) +{ FILE *file ; + int k ; + + printf ("Dumping input and output data to file : %s.\n\n", filename) ; + + if (! (file = fopen (filename, "w"))) + return ; + + fprintf (file, "# Not created by Octave\n") ; + + fprintf (file, "# name: input\n") ; + fprintf (file, "# type: matrix\n") ; + fprintf (file, "# rows: %d\n", in_len) ; + fprintf (file, "# columns: 1\n") ; + + for (k = 0 ; k < in_len ; k++) + fprintf (file, "% g\n", input [k]) ; + + fprintf (file, "# name: output\n") ; + fprintf (file, "# type: matrix\n") ; + fprintf (file, "# rows: %d\n", out_len) ; + fprintf (file, "# columns: 1\n") ; + + for (k = 0 ; k < out_len ; k++) + fprintf (file, "% g\n", output [k]) ; + + fclose (file) ; + return ; +} /* save_oct_double */ + +void +interleave_data (const float *in, float *out, int frames, int channels) +{ int fr, ch ; + + for (fr = 0 ; fr < frames ; fr++) + for (ch = 0 ; ch < channels ; ch++) + out [ch + channels * fr] = in [fr + frames * ch] ; + + return ; +} /* interleave_data */ + +void +deinterleave_data (const float *in, float *out, int frames, int channels) +{ int fr, ch ; + + for (ch = 0 ; ch < channels ; ch++) + for (fr = 0 ; fr < frames ; fr++) + out [fr + frames * ch] = in [ch + channels * fr] ; + + return ; +} /* deinterleave_data */ + +void +reverse_data (float *data, int datalen) +{ int left, right ; + float temp ; + + left = 0 ; + right = datalen - 1 ; + + while (left < right) + { temp = data [left] ; + data [left] = data [right] ; + data [right] = temp ; + left ++ ; + right -- ; + } ; + +} /* reverse_data */ + +const char * +get_cpu_name (void) +{ + const char *name = "Unknown", *search = NULL ; + static char buffer [512] ; + FILE * file = NULL ; + int is_pipe = 0 ; + +#if defined (__linux__) + file = fopen ("/proc/cpuinfo", "r") ; + search = "model name" ; +#elif defined (__APPLE__) + file = popen ("/usr/sbin/system_profiler -detailLevel full SPHardwareDataType", "r") ; + search = "Processor Name" ; + is_pipe = 1 ; +#elif defined (__FreeBSD__) + file = popen ("sysctl -a", "r") ; + search = "hw.model" ; + is_pipe = 1 ; +#else + (void) search ; + (void) buffer ; + (void) file ; + (void) is_pipe ; + + return name; +#endif + +#if defined (__linux__) || defined (__APPLE__) || defined (__FreeBSD__) + if (search == NULL) + { printf ("Error : search is NULL in function %s.\n", __func__) ; + return name ; + } ; + + while (fgets (buffer, sizeof (buffer), file) != NULL) + if (strstr (buffer, search)) + { char *src, *dest ; + + if ((src = strchr (buffer, ':')) != NULL) + { src ++ ; + while (isspace (src [0])) + src ++ ; + name = src ; + + /* Remove consecutive spaces. */ + src ++ ; + for (dest = src ; src [0] ; src ++) + { if (isspace (src [0]) && isspace (dest [-1])) + continue ; + dest [0] = src [0] ; + dest ++ ; + } ; + dest [0] = 0 ; + break ; + } ; + } ; + + if (is_pipe) + pclose (file) ; + else + fclose (file) ; + + return name ; +#endif +} /* get_cpu_name */ + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/util.h b/lib/libsamplerate/libsamplerate-0.2.2/tests/util.h new file mode 100755 index 00000000..3303a29d --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/util.h @@ -0,0 +1,41 @@ +/* +** Copyright (c) 2002-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#define ABS(a) (((a) < 0) ? - (a) : (a)) + +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) + +void gen_windowed_sines (int freq_count, const double *freqs, double max, float *output, int output_len) ; + +void save_oct_float (char *filename, float *input, int in_len, float *output, int out_len) ; +void save_oct_double (char *filename, double *input, int in_len, double *output, int out_len) ; + +void interleave_data (const float *in, float *out, int frames, int channels) ; + +void deinterleave_data (const float *in, float *out, int frames, int channels) ; + +void reverse_data (float *data, int datalen) ; + +double calculate_snr (float *data, int len, int expected_peaks) ; + +const char * get_cpu_name (void) ; + +#define ASSERT(condition) \ + if (!(condition)) \ + { printf ("Condition failed on Line %d : %s\n\n", __LINE__, #condition) ; \ + exit (1) ; \ + } ; + diff --git a/lib/libsamplerate/libsamplerate-0.2.2/tests/varispeed_test.c b/lib/libsamplerate/libsamplerate-0.2.2/tests/varispeed_test.c new file mode 100755 index 00000000..3c9531c0 --- /dev/null +++ b/lib/libsamplerate/libsamplerate-0.2.2/tests/varispeed_test.c @@ -0,0 +1,275 @@ +/* +** Copyright (c) 2006-2016, Erik de Castro Lopo <erikd@mega-nerd.com> +** All rights reserved. +** +** This code is released under 2-clause BSD license. Please see the +** file at : https://github.com/libsndfile/libsamplerate/blob/master/COPYING +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> + +#include <samplerate.h> + +#include "util.h" + +#if HAVE_FFTW3 +#include <fftw3.h> +#else +#define fftw_cleanup() +#endif + +#define BUFFER_LEN (1 << 14) + +static void varispeed_test (int converter, double target_snr) ; +static void varispeed_bounds_test (int converter) ; +static void set_ratio_test (int converter, int channels, double initial_ratio, double second_ratio) ; + +int +main (void) +{ + puts ("\n Varispeed SNR test") ; + printf (" Zero Order Hold interpolator : ") ; + fflush (stdout) ; + varispeed_test (SRC_ZERO_ORDER_HOLD, 10.0) ; + puts ("ok") ; + + printf (" Linear interpolator : ") ; + fflush (stdout) ; + varispeed_test (SRC_LINEAR, 10.0) ; + puts ("ok") ; + +#ifdef ENABLE_SINC_FAST_CONVERTER + printf (" Sinc interpolator : ") ; + fflush (stdout) ; + varispeed_test (SRC_SINC_FASTEST, 115.0) ; + puts ("ok") ; +#endif + + puts ("\n Varispeed bounds test") ; + printf (" Zero Order Hold interpolator : ") ; + fflush (stdout) ; + varispeed_bounds_test (SRC_ZERO_ORDER_HOLD) ; + puts ("ok") ; + + printf (" Linear interpolator : ") ; + fflush (stdout) ; + varispeed_bounds_test (SRC_LINEAR) ; + puts ("ok") ; + +#ifdef ENABLE_SINC_FAST_CONVERTER + printf (" Sinc interpolator : ") ; + fflush (stdout) ; + varispeed_bounds_test (SRC_SINC_FASTEST) ; + puts ("ok") ; +#endif + + fftw_cleanup () ; + puts ("") ; + + return 0 ; +} /* main */ + +static void +varispeed_test (int converter, double target_snr) +{ static float input [BUFFER_LEN], output [BUFFER_LEN] ; + double sine_freq, snr ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + + int input_len, error ; + + memset (input, 0, sizeof (input)) ; + + input_len = ARRAY_LEN (input) / 2 ; + + sine_freq = 0.0111 ; + gen_windowed_sines (1, &sine_freq, 1.0, input, input_len) ; + + /* Perform sample rate conversion. */ + if ((src_state = src_new (converter, 1, &error)) == NULL) + { printf ("\n\nLine %d : src_new () failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.end_of_input = 1 ; + + src_data.data_in = input ; + src_data.input_frames = input_len ; + + src_data.src_ratio = 3.0 ; + + src_data.data_out = output ; + src_data.output_frames = ARRAY_LEN (output) ; + + if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; + exit (1) ; + } ; + + if (src_data.input_frames_used != input_len) + { printf ("\n\nLine %d : unused input.\n", __LINE__) ; + printf ("\tinput_len : %d\n", input_len) ; + printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ; + exit (1) ; + } ; + + /* Copy the last output to the input. */ + memcpy (input, output, sizeof (input)) ; + reverse_data (input, src_data.output_frames_gen) ; + + if ((error = src_reset (src_state))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + src_data.end_of_input = 1 ; + + src_data.data_in = input ; + input_len = src_data.input_frames = src_data.output_frames_gen ; + + src_data.data_out = output ; + src_data.output_frames = ARRAY_LEN (output) ; + + if ((error = src_set_ratio (src_state, 1.0 / src_data.src_ratio))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + if ((error = src_process (src_state, &src_data))) + { printf ("\n\nLine %d : %s\n\n", __LINE__, src_strerror (error)) ; + printf (" src_data.input_frames : %ld\n", src_data.input_frames) ; + printf (" src_data.output_frames : %ld\n\n", src_data.output_frames) ; + exit (1) ; + } ; + + if (src_data.input_frames_used != input_len) + { printf ("\n\nLine %d : unused input.\n", __LINE__) ; + printf ("\tinput_len : %d\n", input_len) ; + printf ("\tinput_frames_used : %ld\n\n", src_data.input_frames_used) ; + exit (1) ; + } ; + + src_state = src_delete (src_state) ; + + snr = calculate_snr (output, src_data.output_frames_gen, 1) ; + + if (target_snr > snr) + { printf ("\n\nLine %d : snr (%3.1f) does not meet target (%3.1f)\n\n", __LINE__, snr, target_snr) ; + save_oct_float ("varispeed.mat", input, src_data.input_frames, output, src_data.output_frames_gen) ; + exit (1) ; + } ; + + return ; +} /* varispeed_test */ + +static void +varispeed_bounds_test (int converter) +{ double ratios [] = { 0.1, 0.01, 20 } ; + int chan, r1, r2 ; + + for (chan = 1 ; chan <= 9 ; chan ++) + for (r1 = 0 ; r1 < ARRAY_LEN (ratios) ; r1++) + for (r2 = 0 ; r2 < ARRAY_LEN (ratios) ; r2 ++) + if (r1 != r2) + set_ratio_test (converter, chan, ratios [r1], ratios [r2]) ; +} /* varispeed_bounds_test */ + +static void +set_ratio_test (int converter, int channels, double initial_ratio, double second_ratio) +{ const int total_input_frames = BUFFER_LEN ; + /* Maximum upsample ratio is 20, use a value beigger. */ + const int total_output_frames = 25 * BUFFER_LEN ; + + /* Interested in array boundary conditions, so all zero data here is fine. */ + float *input = calloc (total_input_frames * channels, sizeof (float)) ; + float *output = calloc (total_output_frames * channels, sizeof (float)) ; + + char details [128] ; + + const int max_loop_count = 100000 ; + const int chunk_size = 128 ; + + SRC_STATE *src_state ; + SRC_DATA src_data ; + + int error, k, total_frames_used, total_frames_gen ; + + snprintf (details, sizeof (details), "%d channels, ratio %g -> %g", channels, initial_ratio, second_ratio) ; + + if ((src_state = src_new (converter, channels, &error)) == NULL) + { printf ("\n\nLine %d : src_new () failed : %s\n\n", __LINE__, src_strerror (error)) ; + exit (1) ; + } ; + + total_frames_used = 0 ; + total_frames_gen = 0 ; + + memset (&src_data, 0, sizeof (src_data)) ; + src_data.end_of_input = 0 ; + src_data.src_ratio = initial_ratio ; + src_data.data_in = input ; + src_data.data_out = output ; + src_data.input_frames = chunk_size ; + src_data.output_frames = total_output_frames ; + + /* Use a max_loop_count here to enable the detection of infinite loops + ** (due to end of input not being detected. + */ + for (k = 0 ; k < max_loop_count ; k ++) + { if (k == 1) + { /* Hard switch to second_ratio after processing one chunk. */ + src_data.src_ratio = second_ratio ; + if ((error = src_set_ratio (src_state, second_ratio))) + { printf ("\n\nLine %d : %s : %s\n\n", __LINE__, details, src_strerror (error)) ; + exit (1) ; + } ; + } ; + + if ((error = src_process (src_state, &src_data)) != 0) + { printf ("\n\nLine %d : %s : %s\n\n", __LINE__, details, src_strerror (error)) ; + exit (1) ; + } ; + + if (src_data.end_of_input && src_data.output_frames_gen == 0) + break ; + + total_frames_used += src_data.input_frames_used ; + total_frames_gen += src_data.output_frames_gen ; + + src_data.data_in += src_data.input_frames_used * channels ; + src_data.data_out += src_data.output_frames_gen * channels ; + + src_data.input_frames = total_input_frames - total_frames_used ; + src_data.output_frames = total_output_frames - total_frames_gen ; + + src_data.end_of_input = total_frames_used >= total_input_frames ? 1 : 0 ; + } ; + + ASSERT (k < max_loop_count) ; + ASSERT (total_frames_gen > 0) ; + + for (k = 0 ; k < total_frames_gen * channels ; k ++) + ASSERT (! isnan (output [k])) ; + + src_state = src_delete (src_state) ; + + free (input) ; + free (output) ; + + return ; +} /* set_ratio_test */ |
