153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 553a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 653a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 753a5a1b3Sopenharmony_ci or (at your option) any later version. 853a5a1b3Sopenharmony_ci 953a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1053a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1153a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1253a5a1b3Sopenharmony_ci General Public License for more details. 1353a5a1b3Sopenharmony_ci 1453a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1553a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1653a5a1b3Sopenharmony_ci***/ 1753a5a1b3Sopenharmony_ci 1853a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 1953a5a1b3Sopenharmony_ci#include <config.h> 2053a5a1b3Sopenharmony_ci#endif 2153a5a1b3Sopenharmony_ci 2253a5a1b3Sopenharmony_ci#include <check.h> 2353a5a1b3Sopenharmony_ci#include <unistd.h> 2453a5a1b3Sopenharmony_ci#include <stdlib.h> 2553a5a1b3Sopenharmony_ci#include <math.h> 2653a5a1b3Sopenharmony_ci 2753a5a1b3Sopenharmony_ci#include <pulse/rtclock.h> 2853a5a1b3Sopenharmony_ci#include <pulsecore/random.h> 2953a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3053a5a1b3Sopenharmony_ci 3153a5a1b3Sopenharmony_ci#include "runtime-test-util.h" 3253a5a1b3Sopenharmony_ci 3353a5a1b3Sopenharmony_cistatic inline int32_t pa_mult_s16_volume_32(int16_t v, int32_t cv) { 3453a5a1b3Sopenharmony_ci /* Multiplying the 32 bit volume factor with the 3553a5a1b3Sopenharmony_ci * 16 bit sample might result in an 48 bit value. We 3653a5a1b3Sopenharmony_ci * want to do without 64 bit integers and hence do 3753a5a1b3Sopenharmony_ci * the multiplication independently for the HI and 3853a5a1b3Sopenharmony_ci * LO part of the volume. */ 3953a5a1b3Sopenharmony_ci int32_t hi = cv >> 16; 4053a5a1b3Sopenharmony_ci int32_t lo = cv & 0xFFFF; 4153a5a1b3Sopenharmony_ci return ((v * lo) >> 16) + (v * hi); 4253a5a1b3Sopenharmony_ci} 4353a5a1b3Sopenharmony_ci 4453a5a1b3Sopenharmony_cistatic inline int32_t pa_mult_s16_volume_64(int16_t v, int32_t cv) { 4553a5a1b3Sopenharmony_ci /* Multiply with 64 bit integers on 64 bit platforms */ 4653a5a1b3Sopenharmony_ci return (v * (int64_t) cv) >> 16; 4753a5a1b3Sopenharmony_ci} 4853a5a1b3Sopenharmony_ci 4953a5a1b3Sopenharmony_ci#define SAMPLES 1028 5053a5a1b3Sopenharmony_ci#define TIMES 10000 5153a5a1b3Sopenharmony_ci#define TIMES2 100 5253a5a1b3Sopenharmony_ci 5353a5a1b3Sopenharmony_ciSTART_TEST (mult_s16_test) { 5453a5a1b3Sopenharmony_ci int16_t samples[SAMPLES]; 5553a5a1b3Sopenharmony_ci int32_t volumes[SAMPLES]; 5653a5a1b3Sopenharmony_ci int32_t sum1 = 0, sum2 = 0; 5753a5a1b3Sopenharmony_ci int i; 5853a5a1b3Sopenharmony_ci 5953a5a1b3Sopenharmony_ci pa_random(samples, sizeof(samples)); 6053a5a1b3Sopenharmony_ci pa_random(volumes, sizeof(volumes)); 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_ci for (i = 0; i < SAMPLES; i++) { 6353a5a1b3Sopenharmony_ci int32_t a = pa_mult_s16_volume_32(samples[i], volumes[i]); 6453a5a1b3Sopenharmony_ci int32_t b = pa_mult_s16_volume_64(samples[i], volumes[i]); 6553a5a1b3Sopenharmony_ci 6653a5a1b3Sopenharmony_ci if (a != b) { 6753a5a1b3Sopenharmony_ci pa_log_debug("%d: %d != %d", i, a, b); 6853a5a1b3Sopenharmony_ci ck_abort(); 6953a5a1b3Sopenharmony_ci } 7053a5a1b3Sopenharmony_ci } 7153a5a1b3Sopenharmony_ci 7253a5a1b3Sopenharmony_ci PA_RUNTIME_TEST_RUN_START("32 bit mult", TIMES, TIMES2) { 7353a5a1b3Sopenharmony_ci for (i = 0; i < SAMPLES; i++) { 7453a5a1b3Sopenharmony_ci sum1 += pa_mult_s16_volume_32(samples[i], volumes[i]); 7553a5a1b3Sopenharmony_ci } 7653a5a1b3Sopenharmony_ci } PA_RUNTIME_TEST_RUN_STOP 7753a5a1b3Sopenharmony_ci 7853a5a1b3Sopenharmony_ci PA_RUNTIME_TEST_RUN_START("64 bit mult", TIMES, TIMES2) { 7953a5a1b3Sopenharmony_ci for (i = 0; i < SAMPLES; i++) 8053a5a1b3Sopenharmony_ci sum2 += pa_mult_s16_volume_64(samples[i], volumes[i]); 8153a5a1b3Sopenharmony_ci } PA_RUNTIME_TEST_RUN_STOP 8253a5a1b3Sopenharmony_ci 8353a5a1b3Sopenharmony_ci fail_unless(sum1 == sum2); 8453a5a1b3Sopenharmony_ci} 8553a5a1b3Sopenharmony_ciEND_TEST 8653a5a1b3Sopenharmony_ci 8753a5a1b3Sopenharmony_ciint main(int argc, char *argv[]) { 8853a5a1b3Sopenharmony_ci int failed = 0; 8953a5a1b3Sopenharmony_ci Suite *s; 9053a5a1b3Sopenharmony_ci TCase *tc; 9153a5a1b3Sopenharmony_ci SRunner *sr; 9253a5a1b3Sopenharmony_ci 9353a5a1b3Sopenharmony_ci if (!getenv("MAKE_CHECK")) 9453a5a1b3Sopenharmony_ci pa_log_set_level(PA_LOG_DEBUG); 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_ci#ifdef HAVE_FAST_64BIT_OPERATIONS 9753a5a1b3Sopenharmony_ci pa_log_debug("Detected CPU with fast 64-bit operations."); 9853a5a1b3Sopenharmony_ci#else 9953a5a1b3Sopenharmony_ci pa_log_debug("Not detected CPU with fast 64-bit operations."); 10053a5a1b3Sopenharmony_ci#endif 10153a5a1b3Sopenharmony_ci 10253a5a1b3Sopenharmony_ci s = suite_create("Mult-s16"); 10353a5a1b3Sopenharmony_ci tc = tcase_create("mult-s16"); 10453a5a1b3Sopenharmony_ci tcase_add_test(tc, mult_s16_test); 10553a5a1b3Sopenharmony_ci tcase_set_timeout(tc, 120); 10653a5a1b3Sopenharmony_ci suite_add_tcase(s, tc); 10753a5a1b3Sopenharmony_ci 10853a5a1b3Sopenharmony_ci sr = srunner_create(s); 10953a5a1b3Sopenharmony_ci srunner_run_all(sr, CK_NORMAL); 11053a5a1b3Sopenharmony_ci failed = srunner_ntests_failed(sr); 11153a5a1b3Sopenharmony_ci srunner_free(sr); 11253a5a1b3Sopenharmony_ci 11353a5a1b3Sopenharmony_ci return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 11453a5a1b3Sopenharmony_ci} 115