VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp@ 57925

Last change on this file since 57925 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 KB
Line 
1/* $Id: tstAudioMixBuffer.cpp 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * Audio testcase - Mixing buffer.
4 */
5
6/*
7 * Copyright (C) 2014-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <iprt/err.h>
23#include <iprt/initterm.h>
24#include <iprt/mem.h>
25#include <iprt/rand.h>
26#include <iprt/stream.h>
27#include <iprt/string.h>
28#include <iprt/test.h>
29
30
31#include "../AudioMixBuffer.h"
32#include "../DrvAudio.h"
33
34
35/*********************************************************************************************************************************
36* Structures and Typedefs *
37*********************************************************************************************************************************/
38
39static int tstSingle(RTTEST hTest)
40{
41 RTTestSubF(hTest, "Single buffer");
42
43 PDMAUDIOSTREAMCFG config =
44 {
45 44100, /* Hz */
46 2 /* Channels */,
47 AUD_FMT_S16 /* Format */,
48 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
49 };
50 PDMPCMPROPS props;
51
52 int rc = drvAudioStreamCfgToProps(&config, &props);
53 AssertRC(rc);
54
55 uint32_t cBufSize = _1K;
56
57 /*
58 * General stuff.
59 */
60 PDMAUDIOMIXBUF mb;
61 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&mb, "Single", &props, cBufSize));
62 RTTESTI_CHECK(AudioMixBufSize(&mb) == cBufSize);
63 RTTESTI_CHECK(AUDIOMIXBUF_B2S(&mb, AudioMixBufSizeBytes(&mb)) == cBufSize);
64 RTTESTI_CHECK(AUDIOMIXBUF_S2B(&mb, AudioMixBufSize(&mb)) == AudioMixBufSizeBytes(&mb));
65 RTTESTI_CHECK(AudioMixBufFree(&mb) == cBufSize);
66 RTTESTI_CHECK(AUDIOMIXBUF_S2B(&mb, AudioMixBufFree(&mb)) == AudioMixBufFreeBytes(&mb));
67
68 /*
69 * Absolute writes.
70 */
71 uint32_t read = 0, written = 0, written_abs = 0;
72 int8_t samples8 [2] = { 0x12, 0x34 };
73 int16_t samples16[2] = { 0xAA, 0xBB };
74 int32_t samples32[2] = { 0xCC, 0xDD };
75 int64_t samples64[2] = { 0xEE, 0xFF };
76
77 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0, &samples8, sizeof(samples8), &written));
78 RTTESTI_CHECK(written == 0 /* Samples */);
79
80 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 0, &samples16, sizeof(samples16), &written));
81 RTTESTI_CHECK(written == 1 /* Samples */);
82
83 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&mb, 2, &samples32, sizeof(samples32), &written));
84 RTTESTI_CHECK(written == 2 /* Samples */);
85 written_abs = 0;
86
87 /* Beyond buffer. */
88 RTTESTI_CHECK_RC(AudioMixBufWriteAt(&mb, AudioMixBufSize(&mb) + 1, &samples16, sizeof(samples16),
89 &written), VERR_BUFFER_OVERFLOW);
90
91 /*
92 * Circular writes.
93 */
94 uint32_t cToWrite = AudioMixBufSize(&mb) - written_abs - 1; /* -1 as padding plus -2 samples for above. */
95 for (uint32_t i = 0; i < cToWrite; i++)
96 {
97 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &written));
98 RTTESTI_CHECK(written == 1);
99 }
100 RTTESTI_CHECK(!AudioMixBufIsEmpty(&mb));
101 RTTESTI_CHECK(AudioMixBufFree(&mb) == 1);
102 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 1U));
103 RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cToWrite + written_abs /* + last absolute write */);
104
105 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &written));
106 RTTESTI_CHECK(written == 1);
107 RTTESTI_CHECK(AudioMixBufFree(&mb) == 0);
108 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 0));
109 RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cBufSize);
110
111 /* Circular reads. */
112 uint32_t cToRead = AudioMixBufSize(&mb) - written_abs - 1;
113 for (uint32_t i = 0; i < cToWrite; i++)
114 {
115 RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &read));
116 RTTESTI_CHECK(read == 1);
117 AudioMixBufFinish(&mb, read);
118 }
119 RTTESTI_CHECK(!AudioMixBufIsEmpty(&mb));
120 RTTESTI_CHECK(AudioMixBufFree(&mb) == AudioMixBufSize(&mb) - written_abs - 1);
121 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs - 1));
122 RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cBufSize - cToRead + written_abs);
123
124 RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &read));
125 RTTESTI_CHECK(read == 1);
126 AudioMixBufFinish(&mb, read);
127 RTTESTI_CHECK(AudioMixBufFree(&mb) == cBufSize - written_abs);
128 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs));
129 RTTESTI_CHECK(AudioMixBufProcessed(&mb) == written_abs);
130
131 AudioMixBufDestroy(&mb);
132
133 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
134}
135
136static int tstParentChild(RTTEST hTest)
137{
138 RTTestSubF(hTest, "2 Children -> Parent");
139
140 uint32_t cBufSize = _1K;
141
142 PDMAUDIOSTREAMCFG cfg_p =
143 {
144 44100, /* Hz */
145 2 /* Channels */,
146 AUD_FMT_S16 /* Format */,
147 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
148 };
149 PDMPCMPROPS props;
150
151 int rc = drvAudioStreamCfgToProps(&cfg_p, &props);
152 AssertRC(rc);
153
154 PDMAUDIOMIXBUF parent;
155 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
156
157 PDMAUDIOSTREAMCFG cfg_c1 = /* Upmixing to parent */
158 {
159 22100, /* Hz */
160 2 /* Channels */,
161 AUD_FMT_S16 /* Format */,
162 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
163 };
164
165 rc = drvAudioStreamCfgToProps(&cfg_c1, &props);
166 AssertRC(rc);
167
168 PDMAUDIOMIXBUF child1;
169 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &props, cBufSize));
170 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent));
171
172 PDMAUDIOSTREAMCFG cfg_c2 = /* Downmixing to parent */
173 {
174 48000, /* Hz */
175 2 /* Channels */,
176 AUD_FMT_S16 /* Format */,
177 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
178 };
179
180 rc = drvAudioStreamCfgToProps(&cfg_c2, &props);
181 AssertRC(rc);
182
183 PDMAUDIOMIXBUF child2;
184 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &props, cBufSize));
185 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent));
186
187 /*
188 * Writing + mixing from child/children -> parent, sequential.
189 */
190 uint32_t cbBuf = _1K;
191 char pvBuf[_1K];
192 int16_t samples[32] = { 0xAA, 0xBB };
193 uint32_t read , written, mixed, temp;
194
195 uint32_t cChild1Free = cBufSize;
196 uint32_t cChild1Mixed = 0;
197 uint32_t cSamplesParent1 = 16;
198 uint32_t cSamplesChild1 = 16;
199
200 uint32_t cChild2Free = cBufSize;
201 uint32_t cChild2Mixed = 0;
202 uint32_t cSamplesParent2 = 16;
203 uint32_t cSamplesChild2 = 16;
204
205 uint32_t t = RTRandU32() % 64;
206
207 for (uint32_t i = 0; i < t; i++)
208 {
209 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "i=%RU32\n", i);
210 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child1, 0, &samples, sizeof(samples), &written));
211 RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild1, ("Child1: Expected %RU32 written samples, got %RU32\n", cSamplesChild1, written));
212 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, written, &mixed));
213 temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child2);
214 RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == temp, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), temp));
215
216 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &samples, sizeof(samples), &written));
217 RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild2, ("Child2: Expected %RU32 written samples, got %RU32\n", cSamplesChild2, written));
218 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, written, &mixed));
219 temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child1);
220 RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == temp, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), temp));
221 }
222
223 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2));
224
225 for (;;)
226 {
227 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, pvBuf, cbBuf, &read));
228 if (!read)
229 break;
230 AudioMixBufFinish(&parent, read);
231 }
232
233 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
234 RTTESTI_CHECK(AudioMixBufMixed(&child1) == 0);
235 RTTESTI_CHECK(AudioMixBufMixed(&child2) == 0);
236
237 AudioMixBufDestroy(&parent);
238 AudioMixBufDestroy(&child1);
239 AudioMixBufDestroy(&child2);
240
241 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
242}
243
244/* Test 8-bit sample conversion (8-bit -> internal -> 8-bit). */
245static int tstConversion8(RTTEST hTest)
246{
247 unsigned i;
248 uint32_t cBufSize = 256;
249 PDMPCMPROPS props;
250
251
252 RTTestSubF(hTest, "Sample conversion");
253
254 PDMAUDIOSTREAMCFG cfg_p =
255 {
256 44100, /* Hz */
257 1 /* Channels */,
258 AUD_FMT_U8 /* Format */,
259 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
260 };
261
262 int rc = drvAudioStreamCfgToProps(&cfg_p, &props);
263 AssertRC(rc);
264
265 PDMAUDIOMIXBUF parent;
266 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
267
268 /* Child uses half the sample rate; that ensures the mixing engine can't
269 * take shortcuts and performs conversion. Because conversion to double
270 * the sample rate effectively inserts one additional sample between every
271 * two source samples, N source samples will be converted to N * 2 - 1
272 * samples. However, the last source sample will be saved for later
273 * interpolation and not immediately output.
274 */
275 PDMAUDIOSTREAMCFG cfg_c = /* Upmixing to parent */
276 {
277 22050, /* Hz */
278 1 /* Channels */,
279 AUD_FMT_U8 /* Format */,
280 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
281 };
282
283 rc = drvAudioStreamCfgToProps(&cfg_c, &props);
284 AssertRC(rc);
285
286 PDMAUDIOMIXBUF child;
287 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize));
288 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
289
290 /* 8-bit unsigned samples. Often used with SB16 device. */
291 uint8_t samples[16] = { 0xAA, 0xBB, 0, 1, 43, 125, 126, 127,
292 128, 129, 130, 131, 132, UINT8_MAX - 1, UINT8_MAX, 0 };
293
294 /*
295 * Writing + mixing from child -> parent, sequential.
296 */
297 uint32_t cbBuf = 256;
298 char achBuf[256];
299 uint32_t read, written, mixed, temp;
300
301 uint32_t cChildFree = cBufSize;
302 uint32_t cChildMixed = 0;
303 uint32_t cSamplesChild = 16;
304 uint32_t cSamplesParent = cSamplesChild * 2 - 2;
305 uint32_t cSamplesRead = 0;
306
307 /**** 8-bit unsigned samples ****/
308 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 8-bit\n", cfg_c.uHz, cfg_c.cChannels);
309 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
310 RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
311 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
312 temp = AudioMixBufProcessed(&parent);
313 RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
314
315 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child));
316
317 for (;;)
318 {
319 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
320 if (!read)
321 break;
322 cSamplesRead += read;
323 AudioMixBufFinish(&parent, read);
324 }
325 RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
326
327 /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */
328 /* NB: This also checks that the default volume setting is 0dB attenuation. */
329 uint8_t *pSrc8 = &samples[0];
330 uint8_t *pDst8 = (uint8_t *)achBuf;
331
332 for (i = 0; i < cSamplesChild - 1; ++i)
333 {
334 RTTESTI_CHECK_MSG(*pSrc8 == *pDst8, ("index %u: Dst=%d, Src=%d\n", i, *pDst8, *pSrc8));
335 pSrc8 += 1;
336 pDst8 += 2;
337 }
338
339 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
340 RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
341
342 AudioMixBufDestroy(&parent);
343 AudioMixBufDestroy(&child);
344
345 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
346}
347
348/* Test 16-bit sample conversion (16-bit -> internal -> 16-bit). */
349static int tstConversion16(RTTEST hTest)
350{
351 unsigned i;
352 uint32_t cBufSize = 256;
353 PDMPCMPROPS props;
354
355
356 RTTestSubF(hTest, "Sample conversion 16-bit");
357
358 PDMAUDIOSTREAMCFG cfg_p =
359 {
360 44100, /* Hz */
361 1 /* Channels */,
362 AUD_FMT_S16 /* Format */,
363 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
364 };
365
366 int rc = drvAudioStreamCfgToProps(&cfg_p, &props);
367 AssertRC(rc);
368
369 PDMAUDIOMIXBUF parent;
370 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
371
372 PDMAUDIOSTREAMCFG cfg_c = /* Upmixing to parent */
373 {
374 22050, /* Hz */
375 1 /* Channels */,
376 AUD_FMT_S16 /* Format */,
377 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
378 };
379
380 rc = drvAudioStreamCfgToProps(&cfg_c, &props);
381 AssertRC(rc);
382
383 PDMAUDIOMIXBUF child;
384 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize));
385 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
386
387 /* 16-bit signed. More or less exclusively used as output, and usually as input, too. */
388 int16_t samples[16] = { 0xAA, 0xBB, INT16_MIN, INT16_MIN + 1, INT16_MIN / 2, -3, -2, -1,
389 0, 1, 2, 3, INT16_MAX / 2, INT16_MAX - 1, INT16_MAX, 0 };
390
391 /*
392 * Writing + mixing from child -> parent, sequential.
393 */
394 uint32_t cbBuf = 256;
395 char achBuf[256];
396 uint32_t read, written, mixed, temp;
397
398 uint32_t cChildFree = cBufSize;
399 uint32_t cChildMixed = 0;
400 uint32_t cSamplesChild = 16;
401 uint32_t cSamplesParent = cSamplesChild * 2 - 2;
402 uint32_t cSamplesRead = 0;
403
404 /**** 16-bit signed samples ****/
405 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 16-bit\n", cfg_c.uHz, cfg_c.cChannels);
406 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
407 RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
408 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
409 temp = AudioMixBufProcessed(&parent);
410 RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
411
412 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child));
413
414 for (;;)
415 {
416 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
417 if (!read)
418 break;
419 cSamplesRead += read;
420 AudioMixBufFinish(&parent, read);
421 }
422 RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
423
424 /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */
425 /* NB: This also checks that the default volume setting is 0dB attenuation. */
426 int16_t *pSrc16 = &samples[0];
427 int16_t *pDst16 = (int16_t *)achBuf;
428
429 for (i = 0; i < cSamplesChild - 1; ++i)
430 {
431 RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16));
432 pSrc16 += 1;
433 pDst16 += 2;
434 }
435
436 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
437 RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
438
439 AudioMixBufDestroy(&parent);
440 AudioMixBufDestroy(&child);
441
442 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
443}
444
445/* Test volume control. */
446static int tstVolume(RTTEST hTest)
447{
448 unsigned i;
449 uint32_t cBufSize = 256;
450 PDMPCMPROPS props;
451
452
453 RTTestSubF(hTest, "Volume control");
454
455 /* Same for parent/child. */
456 PDMAUDIOSTREAMCFG cfg =
457 {
458 44100, /* Hz */
459 2 /* Channels */,
460 AUD_FMT_S16 /* Format */,
461 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
462 };
463
464 int rc = drvAudioStreamCfgToProps(&cfg, &props);
465 AssertRC(rc);
466
467 PDMAUDIOVOLUME vol = { false, 0, 0 }; /* Not muted. */
468 PDMAUDIOMIXBUF parent;
469 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &props, cBufSize));
470
471 PDMAUDIOMIXBUF child;
472 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &props, cBufSize));
473 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
474
475 /* A few 16-bit signed samples. */
476 int16_t samples[16] = { INT16_MIN, INT16_MIN + 1, -128, -64, -4, -1, 0, 1,
477 2, 255, 256, INT16_MAX / 2, INT16_MAX - 2, INT16_MAX - 1, INT16_MAX, 0 };
478
479 /*
480 * Writing + mixing from child -> parent.
481 */
482 uint32_t cbBuf = 256;
483 char achBuf[256];
484 uint32_t read, written, mixed;
485
486 uint32_t cChildFree = cBufSize;
487 uint32_t cChildMixed = 0;
488 uint32_t cSamplesChild = 8;
489 uint32_t cSamplesParent = cSamplesChild;
490 uint32_t cSamplesRead;
491 int16_t *pSrc16;
492 int16_t *pDst16;
493
494 /**** Volume control test ****/
495 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Volume control test %uHz %uch \n", cfg.uHz, cfg.cChannels);
496
497 /* 1) Full volume/0dB attenuation (255). */
498 vol.uLeft = vol.uRight = 255;
499 AudioMixBufSetVolume(&child, &vol);
500
501 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
502 RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
503 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
504
505 cSamplesRead = 0;
506 for (;;)
507 {
508 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
509 if (!read)
510 break;
511 cSamplesRead += read;
512 AudioMixBufFinish(&parent, read);
513 }
514 RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
515
516 /* Check that at 0dB the samples came out unharmed. */
517 pSrc16 = &samples[0];
518 pDst16 = (int16_t *)achBuf;
519
520 for (i = 0; i < cSamplesParent * 2 /* stereo */; ++i)
521 {
522 RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16));
523 ++pSrc16;
524 ++pDst16;
525 }
526 AudioMixBufReset(&child);
527
528 /* 2) Half volume/-6dB attenuation (16 steps down). */
529 vol.uLeft = vol.uRight = 255 - 16;
530 AudioMixBufSetVolume(&child, &vol);
531
532 RTTESTI_CHECK_RC_OK(AudioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
533 RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
534 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
535
536 cSamplesRead = 0;
537 for (;;)
538 {
539 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufReadCirc(&parent, achBuf, cbBuf, &read));
540 if (!read)
541 break;
542 cSamplesRead += read;
543 AudioMixBufFinish(&parent, read);
544 }
545 RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
546
547 /* Check that at -6dB the sample values are halved. */
548 pSrc16 = &samples[0];
549 pDst16 = (int16_t *)achBuf;
550
551 for (i = 0; i < cSamplesParent * 2 /* stereo */; ++i)
552 {
553 /* Watch out! For negative values, x >> 1 is not the same as x / 2. */
554 RTTESTI_CHECK_MSG(*pSrc16 >> 1 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16));
555 ++pSrc16;
556 ++pDst16;
557 }
558
559 AudioMixBufDestroy(&parent);
560 AudioMixBufDestroy(&child);
561
562 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
563}
564
565int main(int argc, char **argv)
566{
567 RTR3InitExe(argc, &argv, 0);
568
569 /*
570 * Initialize IPRT and create the test.
571 */
572 RTTEST hTest;
573 int rc = RTTestInitAndCreate("tstAudioMixBuffer", &hTest);
574 if (rc)
575 return rc;
576 RTTestBanner(hTest);
577
578 rc = tstSingle(hTest);
579 if (RT_SUCCESS(rc))
580 rc = tstParentChild(hTest);
581 if (RT_SUCCESS(rc))
582 rc = tstConversion8(hTest);
583 if (RT_SUCCESS(rc))
584 rc = tstConversion16(hTest);
585 if (RT_SUCCESS(rc))
586 rc = tstVolume(hTest);
587
588 /*
589 * Summary
590 */
591 return RTTestSummaryAndDestroy(hTest);
592}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette