1/*** 2 This file is part of PulseAudio. 3 4 PulseAudio is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as published 6 by the Free Software Foundation; either version 2.1 of the License, 7 or (at your option) any later version. 8 9 PulseAudio is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 16***/ 17 18#ifdef HAVE_CONFIG_H 19#include <config.h> 20#endif 21 22#include <check.h> 23#include <unistd.h> 24#include <stdlib.h> 25#include <math.h> 26 27#include <pulse/rtclock.h> 28#include <pulsecore/random.h> 29#include <pulsecore/macro.h> 30 31#include "runtime-test-util.h" 32 33static inline int32_t pa_mult_s16_volume_32(int16_t v, int32_t cv) { 34 /* Multiplying the 32 bit volume factor with the 35 * 16 bit sample might result in an 48 bit value. We 36 * want to do without 64 bit integers and hence do 37 * the multiplication independently for the HI and 38 * LO part of the volume. */ 39 int32_t hi = cv >> 16; 40 int32_t lo = cv & 0xFFFF; 41 return ((v * lo) >> 16) + (v * hi); 42} 43 44static inline int32_t pa_mult_s16_volume_64(int16_t v, int32_t cv) { 45 /* Multiply with 64 bit integers on 64 bit platforms */ 46 return (v * (int64_t) cv) >> 16; 47} 48 49#define SAMPLES 1028 50#define TIMES 10000 51#define TIMES2 100 52 53START_TEST (mult_s16_test) { 54 int16_t samples[SAMPLES]; 55 int32_t volumes[SAMPLES]; 56 int32_t sum1 = 0, sum2 = 0; 57 int i; 58 59 pa_random(samples, sizeof(samples)); 60 pa_random(volumes, sizeof(volumes)); 61 62 for (i = 0; i < SAMPLES; i++) { 63 int32_t a = pa_mult_s16_volume_32(samples[i], volumes[i]); 64 int32_t b = pa_mult_s16_volume_64(samples[i], volumes[i]); 65 66 if (a != b) { 67 pa_log_debug("%d: %d != %d", i, a, b); 68 ck_abort(); 69 } 70 } 71 72 PA_RUNTIME_TEST_RUN_START("32 bit mult", TIMES, TIMES2) { 73 for (i = 0; i < SAMPLES; i++) { 74 sum1 += pa_mult_s16_volume_32(samples[i], volumes[i]); 75 } 76 } PA_RUNTIME_TEST_RUN_STOP 77 78 PA_RUNTIME_TEST_RUN_START("64 bit mult", TIMES, TIMES2) { 79 for (i = 0; i < SAMPLES; i++) 80 sum2 += pa_mult_s16_volume_64(samples[i], volumes[i]); 81 } PA_RUNTIME_TEST_RUN_STOP 82 83 fail_unless(sum1 == sum2); 84} 85END_TEST 86 87int main(int argc, char *argv[]) { 88 int failed = 0; 89 Suite *s; 90 TCase *tc; 91 SRunner *sr; 92 93 if (!getenv("MAKE_CHECK")) 94 pa_log_set_level(PA_LOG_DEBUG); 95 96#ifdef HAVE_FAST_64BIT_OPERATIONS 97 pa_log_debug("Detected CPU with fast 64-bit operations."); 98#else 99 pa_log_debug("Not detected CPU with fast 64-bit operations."); 100#endif 101 102 s = suite_create("Mult-s16"); 103 tc = tcase_create("mult-s16"); 104 tcase_add_test(tc, mult_s16_test); 105 tcase_set_timeout(tc, 120); 106 suite_add_tcase(s, tc); 107 108 sr = srunner_create(s); 109 srunner_run_all(sr, CK_NORMAL); 110 failed = srunner_ntests_failed(sr); 111 srunner_free(sr); 112 113 return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 114} 115