tests: Factor out ARM svolume test into cpu-test
[platform/upstream/pulseaudio.git] / src / tests / cpu-test.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4
5 #include <check.h>
6 #include <unistd.h>
7 #include <math.h>
8
9 #include <pulse/rtclock.h>
10 #include <pulsecore/cpu-x86.h>
11 #include <pulsecore/cpu-orc.h>
12 #include <pulsecore/random.h>
13 #include <pulsecore/macro.h>
14 #include <pulsecore/endianmacros.h>
15 #include <pulsecore/sconv.h>
16 #include <pulsecore/sample-util.h>
17
18 /* Common defines for svolume tests */
19 #define CHANNELS 2
20 #define SAMPLES 1022
21 #define TIMES 1000
22 #define TIMES2 100
23 #define PADDING 16
24
25 static void run_volume_test(pa_do_volume_func_t func, pa_do_volume_func_t orig_func) {
26     int16_t samples[SAMPLES];
27     int16_t samples_ref[SAMPLES];
28     int16_t samples_orig[SAMPLES];
29     int32_t volumes[CHANNELS + PADDING];
30     int i, j, padding;
31     pa_usec_t start, stop;
32     int k;
33     pa_usec_t min = INT_MAX, max = 0;
34     double s1 = 0, s2 = 0;
35
36
37     pa_random(samples, sizeof(samples));
38     memcpy(samples_ref, samples, sizeof(samples));
39     memcpy(samples_orig, samples, sizeof(samples));
40
41     for (i = 0; i < CHANNELS; i++)
42         volumes[i] = PA_CLAMP_VOLUME((pa_volume_t)(rand() >> 15));
43     for (padding = 0; padding < PADDING; padding++, i++)
44         volumes[i] = volumes[padding];
45
46     orig_func(samples_ref, volumes, CHANNELS, sizeof(samples));
47     func(samples, volumes, CHANNELS, sizeof(samples));
48     for (i = 0; i < SAMPLES; i++) {
49         if (samples[i] != samples_ref[i]) {
50             printf("%d: %04x != %04x (%04x * %08x)\n", i, samples[i], samples_ref[i],
51                   samples_orig[i], volumes[i % CHANNELS]);
52             fail();
53         }
54     }
55
56     for (k = 0; k < TIMES2; k++) {
57         start = pa_rtclock_now();
58         for (j = 0; j < TIMES; j++) {
59             memcpy(samples, samples_orig, sizeof(samples));
60             func(samples, volumes, CHANNELS, sizeof(samples));
61         }
62         stop = pa_rtclock_now();
63
64         if (min > (stop - start)) min = stop - start;
65         if (max < (stop - start)) max = stop - start;
66         s1 += stop - start;
67         s2 += (stop - start) * (stop - start);
68     }
69     pa_log_debug("func: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
70             (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
71
72     min = INT_MAX; max = 0;
73     s1 = s2 = 0;
74     for (k = 0; k < TIMES2; k++) {
75         start = pa_rtclock_now();
76         for (j = 0; j < TIMES; j++) {
77             memcpy(samples_ref, samples_orig, sizeof(samples));
78             orig_func(samples_ref, volumes, CHANNELS, sizeof(samples));
79         }
80         stop = pa_rtclock_now();
81
82         if (min > (stop - start)) min = stop - start;
83         if (max < (stop - start)) max = stop - start;
84         s1 += stop - start;
85         s2 += (stop - start) * (stop - start);
86     }
87     pa_log_debug("orig: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
88             (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
89
90     fail_unless(memcmp(samples_ref, samples, sizeof(samples)) == 0);
91 }
92
93 #if defined (__i386__) || defined (__amd64__)
94 START_TEST (svolume_mmx_test) {
95     pa_do_volume_func_t orig_func, mmx_func;
96     pa_cpu_x86_flag_t flags = 0;
97
98     pa_cpu_get_x86_flags(&flags);
99
100     if (!((flags & PA_CPU_X86_MMX) && (flags & PA_CPU_X86_CMOV))) {
101         pa_log_info("MMX/CMOV not supported. Skipping");
102         return;
103     }
104
105     orig_func = pa_get_volume_func(PA_SAMPLE_S16NE);
106     pa_volume_func_init_mmx(flags);
107     mmx_func = pa_get_volume_func(PA_SAMPLE_S16NE);
108
109     pa_log_debug("Checking MMX svolume");
110     run_volume_test(mmx_func, orig_func);
111 }
112 END_TEST
113
114 START_TEST (svolume_sse_test) {
115     pa_do_volume_func_t orig_func, sse_func;
116     pa_cpu_x86_flag_t flags = 0;
117
118     pa_cpu_get_x86_flags(&flags);
119
120     if (!(flags & PA_CPU_X86_SSE2)) {
121         pa_log_info("SSE2 not supported. Skipping");
122         return;
123     }
124
125     orig_func = pa_get_volume_func(PA_SAMPLE_S16NE);
126     pa_volume_func_init_sse(flags);
127     sse_func = pa_get_volume_func(PA_SAMPLE_S16NE);
128
129     pa_log_debug("Checking SSE2 svolume");
130     run_volume_test(sse_func, orig_func);
131 }
132 END_TEST
133 #endif /* defined (__i386__) || defined (__amd64__) */
134
135 #if defined (__arm__) && defined (__linux__)
136 START_TEST (svolume_arm_test) {
137     pa_do_volume_func_t orig_func, arm_func;
138     pa_cpu_arm_flag_t flags = 0;
139
140     pa_cpu_get_arm_flags(&flags);
141
142     if (!(flags & PA_CPU_ARM_V6)) {
143         pa_log_info("ARMv6 instructions not supported. Skipping");
144         return;
145     }
146
147     orig_func = pa_get_volume_func(PA_SAMPLE_S16NE);
148     pa_volume_func_init_arm(flags);
149     arm_func = pa_get_volume_func(PA_SAMPLE_S16NE);
150
151     pa_log_debug("Checking ARM svolume");
152     run_volume_test(arm_func, orig_func);
153 }
154 END_TEST
155 #endif /* defined (__arm__) && defined (__linux__) */
156
157 START_TEST (svolume_orc_test) {
158     pa_do_volume_func_t orig_func, orc_func;
159     pa_cpu_info cpu_info;
160
161 #if defined (__i386__) || defined (__amd64__)
162     pa_zero(cpu_info);
163     cpu_info.cpu_type = PA_CPU_X86;
164     pa_cpu_get_x86_flags(&cpu_info.flags.x86);
165 #endif
166
167     orig_func = pa_get_volume_func(PA_SAMPLE_S16NE);
168
169     if (!pa_cpu_init_orc(cpu_info)) {
170         pa_log_info("Orc not supported. Skipping");
171         return;
172     }
173
174     orc_func = pa_get_volume_func(PA_SAMPLE_S16NE);
175
176     pa_log_debug("Checking Orc svolume");
177     run_volume_test(orc_func, orig_func);
178 }
179 END_TEST
180
181 #undef CHANNELS
182 #undef SAMPLES
183 #undef TIMES
184 #undef TIMES2
185 #undef PADDING
186 /* End svolume tests */
187
188 /* Start conversion tests */
189 #if defined (__i386__) || defined (__amd64__)
190 START_TEST (sconv_sse_test) {
191 #define SAMPLES 1019
192 #define TIMES 1000
193
194     int16_t samples[SAMPLES];
195     int16_t samples_ref[SAMPLES];
196     float floats[SAMPLES];
197     int i;
198     pa_usec_t start, stop;
199     pa_convert_func_t orig_func, sse_func;
200     pa_cpu_x86_flag_t flags = 0;
201
202     pa_cpu_get_x86_flags(&flags);
203
204     if (!(flags & PA_CPU_X86_SSE2)) {
205         pa_log_info("SSE2 not supported. Skipping");
206         return;
207     }
208
209     pa_log_debug("Checking SSE sconv (%zd)\n", sizeof(samples));
210
211     memset(samples_ref, 0, sizeof(samples_ref));
212     memset(samples, 0, sizeof(samples));
213
214     for (i = 0; i < SAMPLES; i++) {
215         floats[i] = 2.1f * (rand()/(float) RAND_MAX - 0.5f);
216     }
217
218     orig_func = pa_get_convert_from_float32ne_function(PA_SAMPLE_S16LE);
219     pa_convert_func_init_sse(flags);
220     sse_func = pa_get_convert_from_float32ne_function(PA_SAMPLE_S16LE);
221
222     orig_func(SAMPLES, floats, samples_ref);
223     sse_func(SAMPLES, floats, samples);
224
225     for (i = 0; i < SAMPLES; i++) {
226         if (samples[i] != samples_ref[i]) {
227             printf ("%d: %04x != %04x (%f)\n", i, samples[i], samples_ref[i],
228                       floats[i]);
229             fail();
230         }
231     }
232
233     start = pa_rtclock_now();
234     for (i = 0; i < TIMES; i++) {
235         sse_func(SAMPLES, floats, samples);
236     }
237     stop = pa_rtclock_now();
238     pa_log_debug("SSE: %llu usec.", (long long unsigned int)(stop - start));
239
240     start = pa_rtclock_now();
241     for (i = 0; i < TIMES; i++) {
242         orig_func(SAMPLES, floats, samples_ref);
243     }
244     stop = pa_rtclock_now();
245     pa_log_debug("ref: %llu usec.", (long long unsigned int)(stop - start));
246
247 #undef SAMPLES
248 #undef TIMES
249 }
250 END_TEST
251 #endif /* defined (__i386__) || defined (__amd64__) */
252 /* End conversion tests */
253
254 int main(int argc, char *argv[]) {
255     int failed = 0;
256     Suite *s;
257     TCase *tc;
258     SRunner *sr;
259
260     if (!getenv("MAKE_CHECK"))
261         pa_log_set_level(PA_LOG_DEBUG);
262
263     s = suite_create("CPU");
264     tc = tcase_create("x86");
265
266     /* Volume tests */
267 #if defined (__i386__) || defined (__amd64__)
268     tcase_add_test(tc, svolume_mmx_test);
269     tcase_add_test(tc, svolume_sse_test);
270 #endif
271 #if defined (__arm__) && defined (__linux__)
272     tcase_add_test(tc, svolume_arm_test);
273 #endif
274     tcase_add_test(tc, svolume_orc_test);
275
276     /* Converstion tests */
277 #if defined (__i386__) || defined (__amd64__)
278     tcase_add_test(tc, sconv_sse_test);
279 #endif
280     suite_add_tcase(s, tc);
281
282     sr = srunner_create(s);
283     srunner_run_all(sr, CK_NORMAL);
284     failed = srunner_ntests_failed(sr);
285     srunner_free(sr);
286
287     return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
288 }