]>
code.delx.au - pulseaudio/blob - src/tests/mix-special-test.c
2 This file is part of PulseAudio.
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.
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.
14 You should have received a copy of the GNU Lesser General Public License
15 along with PulseAudio; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 #include <pulse/rtclock.h>
30 #include <pulsecore/random.h>
31 #include <pulsecore/macro.h>
32 #include <pulsecore/mix.h>
33 #include <pulsecore/sample-util.h>
35 #define PA_CPU_TEST_RUN_START(l, t1, t2) \
38 int _times = (t1), _times2 = (t2); \
39 pa_usec_t _start, _stop; \
40 pa_usec_t _min = INT_MAX, _max = 0; \
41 double _s1 = 0, _s2 = 0; \
42 const char *_label = (l); \
44 for (_k = 0; _k < _times2; _k++) { \
45 _start = pa_rtclock_now(); \
46 for (_j = 0; _j < _times; _j++)
48 #define PA_CPU_TEST_RUN_STOP \
49 _stop = pa_rtclock_now(); \
51 if (_min > (_stop - _start)) _min = _stop - _start; \
52 if (_max < (_stop - _start)) _max = _stop - _start; \
53 _s1 += _stop - _start; \
54 _s2 += (_stop - _start) * (_stop - _start); \
56 pa_log_debug("%s: %llu usec (avg: %g, min = %llu, max = %llu, stddev = %g).", _label, \
57 (long long unsigned int)_s1, \
58 ((double)_s1 / _times2), \
59 (long long unsigned int)_min, \
60 (long long unsigned int)_max, \
61 sqrt(_times2 * _s2 - _s1 * _s1) / _times2); \
64 static void acquire_mix_streams(pa_mix_info streams
[], unsigned nstreams
) {
67 for (i
= 0; i
< nstreams
; i
++)
68 streams
[i
].ptr
= pa_memblock_acquire_chunk(&streams
[i
].chunk
);
71 static void release_mix_streams(pa_mix_info streams
[], unsigned nstreams
) {
74 for (i
= 0; i
< nstreams
; i
++)
75 pa_memblock_release(streams
[i
].chunk
.memblock
);
78 /* special case: mix 2 s16ne streams, 1 channel each */
79 static void pa_mix2_ch1_s16ne(pa_mix_info streams
[], int16_t *data
, unsigned length
) {
80 const int16_t *ptr0
= streams
[0].ptr
;
81 const int16_t *ptr1
= streams
[1].ptr
;
83 const int32_t cv0
= streams
[0].linear
[0].i
;
84 const int32_t cv1
= streams
[1].linear
[0].i
;
86 length
/= sizeof(int16_t);
88 for (; length
> 0; length
--) {
91 sum
= pa_mult_s16_volume(*ptr0
++, cv0
);
92 sum
+= pa_mult_s16_volume(*ptr1
++, cv1
);
94 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
99 /* special case: mix 2 s16ne streams, 2 channels each */
100 static void pa_mix2_ch2_s16ne(pa_mix_info streams
[], int16_t *data
, unsigned length
) {
101 const int16_t *ptr0
= streams
[0].ptr
;
102 const int16_t *ptr1
= streams
[1].ptr
;
104 length
/= sizeof(int16_t) * 2;
106 for (; length
> 0; length
--) {
109 sum
= pa_mult_s16_volume(*ptr0
++, streams
[0].linear
[0].i
);
110 sum
+= pa_mult_s16_volume(*ptr1
++, streams
[1].linear
[0].i
);
112 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
115 sum
= pa_mult_s16_volume(*ptr0
++, streams
[0].linear
[1].i
);
116 sum
+= pa_mult_s16_volume(*ptr1
++, streams
[1].linear
[1].i
);
118 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
123 /* special case: mix 2 s16ne streams */
124 static void pa_mix2_s16ne(pa_mix_info streams
[], unsigned channels
, int16_t *data
, unsigned length
) {
125 const int16_t *ptr0
= streams
[0].ptr
;
126 const int16_t *ptr1
= streams
[1].ptr
;
127 unsigned channel
= 0;
129 length
/= sizeof(int16_t);
131 for (; length
> 0; length
--) {
134 sum
= pa_mult_s16_volume(*ptr0
++, streams
[0].linear
[channel
].i
);
135 sum
+= pa_mult_s16_volume(*ptr1
++, streams
[1].linear
[channel
].i
);
137 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
140 if (PA_UNLIKELY(++channel
>= channels
))
145 /* special case: mix s16ne streams, 2 channels each */
146 static void pa_mix_ch2_s16ne(pa_mix_info streams
[], unsigned nstreams
, int16_t *data
, unsigned length
) {
148 length
/= sizeof(int16_t) * 2;
150 for (; length
> 0; length
--) {
151 int32_t sum0
= 0, sum1
= 0;
154 for (i
= 0; i
< nstreams
; i
++) {
155 pa_mix_info
*m
= streams
+ i
;
156 int32_t cv0
= m
->linear
[0].i
;
157 int32_t cv1
= m
->linear
[1].i
;
159 sum0
+= pa_mult_s16_volume(*((int16_t*) m
->ptr
), cv0
);
160 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
162 sum1
+= pa_mult_s16_volume(*((int16_t*) m
->ptr
), cv1
);
163 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
166 *data
++ = PA_CLAMP_UNLIKELY(sum0
, -0x8000, 0x7FFF);
167 *data
++ = PA_CLAMP_UNLIKELY(sum1
, -0x8000, 0x7FFF);
171 static void pa_mix_generic_s16ne(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, int16_t *data
, unsigned length
) {
172 unsigned channel
= 0;
174 length
/= sizeof(int16_t);
176 for (; length
> 0; length
--) {
180 for (i
= 0; i
< nstreams
; i
++) {
181 pa_mix_info
*m
= streams
+ i
;
182 int32_t cv
= m
->linear
[channel
].i
;
184 if (PA_LIKELY(cv
> 0))
185 sum
+= pa_mult_s16_volume(*((int16_t*) m
->ptr
), cv
);
186 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
189 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
192 if (PA_UNLIKELY(++channel
>= channels
))
201 START_TEST (mix_special_1ch_test
) {
202 int16_t samples0
[SAMPLES
];
203 int16_t samples1
[SAMPLES
];
204 int16_t out
[SAMPLES
];
205 int16_t out_ref
[SAMPLES
];
209 unsigned nsamples
= SAMPLES
;
211 fail_unless((pool
= pa_mempool_new(false, 0)) != NULL
, NULL
);
213 pa_random(samples0
, nsamples
* sizeof(int16_t));
214 c0
.memblock
= pa_memblock_new_fixed(pool
, samples0
, nsamples
* sizeof(int16_t), false);
215 c0
.length
= pa_memblock_get_length(c0
.memblock
);
218 pa_random(samples1
, nsamples
* sizeof(int16_t));
219 c1
.memblock
= pa_memblock_new_fixed(pool
, samples1
, nsamples
* sizeof(int16_t), false);
220 c1
.length
= pa_memblock_get_length(c1
.memblock
);
224 m
[0].volume
.channels
= 1;
225 m
[0].volume
.values
[0] = PA_VOLUME_NORM
;
226 m
[0].linear
[0].i
= 0x5555;
229 m
[1].volume
.channels
= 1;
230 m
[1].volume
.values
[0] = PA_VOLUME_NORM
;
231 m
[1].linear
[0].i
= 0x6789;
233 PA_CPU_TEST_RUN_START("mix s16 generic 1 channel", TIMES
, TIMES2
) {
234 acquire_mix_streams(m
, 2);
235 pa_mix_generic_s16ne(m
, 2, 1, out_ref
, nsamples
* sizeof(int16_t));
236 release_mix_streams(m
, 2);
237 } PA_CPU_TEST_RUN_STOP
239 PA_CPU_TEST_RUN_START("mix s16 2 streams 1 channel", TIMES
, TIMES2
) {
240 acquire_mix_streams(m
, 2);
241 pa_mix2_ch1_s16ne(m
, out
, nsamples
* sizeof(int16_t));
242 release_mix_streams(m
, 2);
243 } PA_CPU_TEST_RUN_STOP
245 fail_unless(memcmp(out
, out_ref
, nsamples
* sizeof(int16_t)) == 0);
247 pa_memblock_unref(c0
.memblock
);
248 pa_memblock_unref(c1
.memblock
);
250 pa_mempool_free(pool
);
254 START_TEST (mix_special_2ch_test
) {
255 int16_t samples0
[SAMPLES
*2];
256 int16_t samples1
[SAMPLES
*2];
257 int16_t out
[SAMPLES
*2];
258 int16_t out_ref
[SAMPLES
*2];
263 unsigned nsamples
= SAMPLES
* 2;
265 fail_unless((pool
= pa_mempool_new(false, 0)) != NULL
, NULL
);
267 pa_random(samples0
, nsamples
* sizeof(int16_t));
268 c0
.memblock
= pa_memblock_new_fixed(pool
, samples0
, nsamples
* sizeof(int16_t), false);
269 c0
.length
= pa_memblock_get_length(c0
.memblock
);
272 pa_random(samples1
, nsamples
* sizeof(int16_t));
273 c1
.memblock
= pa_memblock_new_fixed(pool
, samples1
, nsamples
* sizeof(int16_t), false);
274 c1
.length
= pa_memblock_get_length(c1
.memblock
);
278 m
[0].volume
.channels
= 2;
279 for (i
= 0; i
< m
[0].volume
.channels
; i
++) {
280 m
[0].volume
.values
[i
] = PA_VOLUME_NORM
;
281 m
[0].linear
[i
].i
= 0x5555;
285 m
[1].volume
.channels
= 2;
286 for (i
= 0; i
< m
[1].volume
.channels
; i
++) {
287 m
[1].volume
.values
[i
] = PA_VOLUME_NORM
;
288 m
[1].linear
[i
].i
= 0x6789;
291 PA_CPU_TEST_RUN_START("mix s16 generic 2 channels", TIMES
, TIMES2
) {
292 acquire_mix_streams(m
, 2);
293 pa_mix_generic_s16ne(m
, 2, 2, out_ref
, nsamples
* sizeof(int16_t));
294 release_mix_streams(m
, 2);
295 } PA_CPU_TEST_RUN_STOP
297 PA_CPU_TEST_RUN_START("mix s16 2 channels", TIMES
, TIMES2
) {
298 acquire_mix_streams(m
, 2);
299 pa_mix_ch2_s16ne(m
, 2, out
, nsamples
* sizeof(int16_t));
300 release_mix_streams(m
, 2);
301 } PA_CPU_TEST_RUN_STOP
303 fail_unless(memcmp(out
, out_ref
, nsamples
* sizeof(int16_t)) == 0);
305 PA_CPU_TEST_RUN_START("mix s16 2 streams", TIMES
, TIMES2
) {
306 acquire_mix_streams(m
, 2);
307 pa_mix2_s16ne(m
, 2, out
, nsamples
* sizeof(int16_t));
308 release_mix_streams(m
, 2);
309 } PA_CPU_TEST_RUN_STOP
311 fail_unless(memcmp(out
, out_ref
, nsamples
* sizeof(int16_t)) == 0);
313 PA_CPU_TEST_RUN_START("mix s16 2 streams 2 channels", TIMES
, TIMES2
) {
314 acquire_mix_streams(m
, 2);
315 pa_mix2_ch2_s16ne(m
, out
, nsamples
* sizeof(int16_t));
316 release_mix_streams(m
, 2);
317 } PA_CPU_TEST_RUN_STOP
319 fail_unless(memcmp(out
, out_ref
, nsamples
* sizeof(int16_t)) == 0);
321 pa_memblock_unref(c0
.memblock
);
322 pa_memblock_unref(c1
.memblock
);
324 pa_mempool_free(pool
);
328 int main(int argc
, char *argv
[]) {
334 if (!getenv("MAKE_CHECK"))
335 pa_log_set_level(PA_LOG_DEBUG
);
337 s
= suite_create("Mix-special");
338 tc
= tcase_create("mix-special 1ch");
339 tcase_add_test(tc
, mix_special_1ch_test
);
340 tcase_set_timeout(tc
, 120);
341 suite_add_tcase(s
, tc
);
342 tc
= tcase_create("mix-special 2ch");
343 tcase_add_test(tc
, mix_special_2ch_test
);
344 tcase_set_timeout(tc
, 120);
345 suite_add_tcase(s
, tc
);
347 sr
= srunner_create(s
);
348 srunner_run_all(sr
, CK_NORMAL
);
349 failed
= srunner_ntests_failed(sr
);
352 return (failed
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;