Changeset 89373 in vbox for trunk/src/VBox
- Timestamp:
- May 29, 2021 3:35:17 AM (4 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r89371 r89373 169 169 static void audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl) 170 170 { 171 Log(("%s: %*s %s: offRead=%RU32, offWrite=%RU32 , cMixed=%RU32-> %RU32/%RU32\n",171 Log(("%s: %*s %s: offRead=%RU32, offWrite=%RU32 -> %RU32/%RU32\n", 172 172 pszFunc, uIdtLvl * 4, "", 173 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->c Mixed, pMixBuf->cUsed, pMixBuf->cFrames));173 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cUsed, pMixBuf->cFrames)); 174 174 } 175 175 … … 231 231 { 232 232 int64_t const i64Dst = *pi64Dst; 233 if (! pi64Dst)233 if (!i64Dst) 234 234 *pi64Dst = i64Src; 235 235 else … … 273 273 while (cFrames-- > 0) 274 274 { 275 int64_t const i64DstL = pi64Dst[0]; 276 int64_t const i64SrcL = pi64Src[0]; 277 if (!i64DstL) 278 pi64Dst[0] = i64SrcL; 279 else if (!i64SrcL) 280 pi64Dst[0] = (i64DstL + i64SrcL) / 2; 281 282 int64_t const i64DstR = pi64Dst[1]; 283 int64_t const i64SrcR = pi64Src[1]; 284 if (!i64DstR) 285 pi64Dst[1] = i64SrcR; 286 else if (!i64SrcR) 287 pi64Dst[1] = (i64DstR + i64SrcR) / 2; 288 275 audioMixBufBlendSample(&pi64Dst[0], pi64Dst[0]); 276 audioMixBufBlendSample(&pi64Dst[1], pi64Dst[1]); 289 277 pi64Dst += 2; 290 278 pi64Src += 2; … … 298 286 while (cFrames-- > 0) 299 287 { 300 int64_t const i64Dst = *pi64Dst; 301 int64_t const i64Src = *pi64Src; 302 if (!i64Dst) 303 *pi64Dst = i64Src; 304 else if (!i64Src) 305 *pi64Dst = (i64Dst + i64Src) / 2; 288 audioMixBufBlendSample(pi64Dst, pi64Dst[0]); 306 289 pi64Dst++; 307 290 pi64Src++; … … 890 873 pMixBuf->offRead = 0; 891 874 pMixBuf->offWrite = 0; 892 pMixBuf->cMixed = 0;893 875 pMixBuf->cUsed = 0; 894 876 … … 986 968 pMixBuf->offRead = 0; 987 969 pMixBuf->offWrite = 0; 988 pMixBuf->cMixed = 0;989 970 pMixBuf->cUsed = 0; 990 971 } … … 1580 1561 AssertPtr(pState); 1581 1562 AssertPtr(pState->pfnDecode); 1563 AssertPtr(pState->pfnDecodeBlend); 1582 1564 Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props)); 1583 1565 Assert(cMaxDstFrames > 0); … … 1727 1709 * write position. 1728 1710 * @param cFrames Number of frames of silence. 1729 * @sa AudioMixBuf Silence1711 * @sa AudioMixBufWrite 1730 1712 * 1731 1713 * @note Does not advance the write position, please call AudioMixBufCommit() … … 1741 1723 AssertPtr(pState); 1742 1724 AssertPtr(pState->pfnDecode); 1725 AssertPtr(pState->pfnDecodeBlend); 1743 1726 Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props)); 1744 1727 Assert(cFrames > 0); 1745 Assert(cFrames <= pMixBuf->cFrames); 1746 Assert(offFrame <= pMixBuf->cFrames); 1747 Assert(offFrame + cFrames <= pMixBuf->cUsed); 1728 #ifdef VBOX_STRICT 1729 uint32_t const cMixBufFree = pMixBuf->cFrames - pMixBuf->cUsed; 1730 #endif 1731 Assert(cFrames <= cMixBufFree); 1732 Assert(offFrame < cMixBufFree); 1733 Assert(offFrame + cFrames <= cMixBufFree); 1748 1734 1749 1735 /* -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r89371 r89373 151 151 /** The current write position (in frames). */ 152 152 uint32_t offWrite; 153 /** Total frames already mixed down to the parent buffer (if any).154 *155 * Always starting at the parent's offRead position.156 * @note Count always is specified in parent frames, as the sample count can157 * differ between parent and child. */158 uint32_t cMixed;159 153 /** How much audio frames are currently being used in this buffer. 160 154 * @note This also is known as the distance in ring buffer terms. */ -
trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
r89371 r89373 36 36 #define _USE_MATH_DEFINES 37 37 #include <math.h> /* sin, M_PI */ 38 39 40 /********************************************************************************************************************************* 41 * Global Variables * 42 *********************************************************************************************************************************/ 43 #ifdef RT_LITTLE_ENDIAN 44 bool const g_fLittleEndian = true; 45 #else 46 bool const g_fLittleEndian = false; 47 #endif 38 48 39 49 … … 321 331 } 322 332 323 #if 0 /* obsolete */ 324 static int tstParentChild(RTTEST hTest) 333 /** @name Eight test samples represented in all basic formats. 334 * @{ */ 335 static uint8_t const g_au8TestSamples[8] = { 0x1, 0x11, 0x32, 0x7f, 0x80, 0x81, 0xbe, 0xff }; 336 static int8_t const g_ai8TestSamples[8] = { -127, -111, -78, -1, 0, 1, 62, 127 }; 337 static uint16_t const g_au16TestSamples[8] = { 0x100, 0x1100, 0x3200, 0x7f00, 0x8000, 0x8100, 0xbe00, 0xff00 }; 338 static int16_t const g_ai16TestSamples[8] = { -32512, -28416, -19968, -256, 0, 256, 15872, 32512 }; 339 static uint32_t const g_au32TestSamples[8] = { 0x1000000, 0x11000000, 0x32000000, 0x7f000000, 0x80000000, 0x81000000, 0xbe000000, 0xff000000 }; 340 static int32_t const g_ai32TestSamples[8] = { -2130706432, -1862270976, -1308622848, -16777216, 0, 16777216, 1040187392, 2130706432 }; 341 static int64_t const g_ai64TestSamples[8] = { -2130706432, -1862270976, -1308622848, -16777216, 0, 16777216, 1040187392, 2130706432 }; 342 static struct { void const *apv[2]; uint32_t cb; } g_aTestSamples[] = 325 343 { 326 RTTestSub(hTest, "2 Children -> Parent (AudioMixBufWriteAt)"); 327 328 uint32_t cParentBufSize = RTRandU32Ex(_1K /* Min */, _16K /* Max */); /* Enough room for random sizes */ 329 330 /* 44100Hz, 2 Channels, S16 */ 331 PDMAUDIOPCMPROPS cfg_p = PDMAUDIOPCMPROPS_INITIALIZER( 332 2, /* Bytes */ 333 true, /* Signed */ 334 2, /* Channels */ 335 44100, /* Hz */ 336 false /* Swap Endian */ 337 ); 338 339 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p)); 340 341 AUDIOMIXBUF parent; 342 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cParentBufSize)); 343 344 /* 22050Hz, 2 Channels, S16 */ 345 PDMAUDIOPCMPROPS cfg_c1 = PDMAUDIOPCMPROPS_INITIALIZER(/* Upmixing to parent */ 346 2, /* Bytes */ 347 true, /* Signed */ 348 2, /* Channels */ 349 22050, /* Hz */ 350 false /* Swap Endian */ 351 ); 352 353 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c1)); 354 355 uint32_t cFrames = 16; 356 uint32_t cChildBufSize = RTRandU32Ex(cFrames /* Min */, 64 /* Max */); 357 358 AUDIOMIXBUF child1; 359 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &cfg_c1, cChildBufSize)); 360 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent)); 361 362 /* 48000Hz, 2 Channels, S16 */ 363 PDMAUDIOPCMPROPS cfg_c2 = PDMAUDIOPCMPROPS_INITIALIZER(/* Downmixing to parent */ 364 2, /* Bytes */ 365 true, /* Signed */ 366 2, /* Channels */ 367 48000, /* Hz */ 368 false /* Swap Endian */ 369 ); 370 371 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c2)); 372 373 AUDIOMIXBUF child2; 374 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &cfg_c2, cChildBufSize)); 375 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent)); 376 377 /* 378 * Writing + mixing from child/children -> parent, sequential. 379 */ 380 uint32_t cbBuf = _1K; 381 char pvBuf[_1K]; 382 int16_t aFrames16[32] = { 0xAA, 0xBB }; 383 uint32_t cFramesRead, cFramesWritten, cFramesMixed; 384 385 uint32_t cFramesChild1 = cFrames; 386 uint32_t cFramesChild2 = cFrames; 387 388 uint32_t t = RTRandU32() % 32; 389 390 RTTestPrintf(hTest, RTTESTLVL_DEBUG, 391 "cParentBufSize=%RU32, cChildBufSize=%RU32, %RU32 frames -> %RU32 iterations total\n", 392 cParentBufSize, cChildBufSize, cFrames, t); 393 394 /* 395 * Using AudioMixBufWriteAt for writing to children. 396 */ 397 uint32_t cChildrenSamplesMixedTotal = 0; 398 399 for (uint32_t i = 0; i < t; i++) 400 { 401 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "i=%RU32\n", i); 402 403 uint32_t cChild1Writes = RTRandU32() % 8; 404 405 for (uint32_t c1 = 0; c1 < cChild1Writes; c1++) 344 /* 0/0: */ { { NULL, NULL }, 0 }, 345 /* 1/8: */ { { g_au8TestSamples, g_ai8TestSamples }, sizeof( g_au8TestSamples) }, 346 /* 2/16: */ { { g_au16TestSamples, g_ai16TestSamples }, sizeof(g_au16TestSamples) }, 347 /* 3/24: */ { { NULL, NULL }, 0 }, 348 /* 4/32: */ { { g_au32TestSamples, g_ai32TestSamples }, sizeof(g_au32TestSamples) }, 349 /* 5: */ { { NULL, NULL }, 0 }, 350 /* 6: */ { { NULL, NULL }, 0 }, 351 /* 7: */ { { NULL, NULL }, 0 }, 352 /* 8:64 */ { { NULL, g_ai64TestSamples }, sizeof(g_ai64TestSamples) }, /* raw */ 353 }; 354 /** @} */ 355 356 /** Fills a buffer with samples from an g_aTestSamples entry. */ 357 static uint32_t tstFillBuf(PCPDMAUDIOPCMPROPS pCfg, void const *pvTestSamples, uint32_t iTestSample, 358 uint8_t *pbBuf, uint32_t cFrames) 359 { 360 uint8_t const cTestSamples = RT_ELEMENTS(g_au8TestSamples); 361 362 cFrames *= PDMAudioPropsChannels(pCfg); 363 switch (PDMAudioPropsSampleSize(pCfg)) 364 { 365 case 1: 406 366 { 407 /* Child 1. */ 408 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child1, 0, &aFrames16, sizeof(aFrames16), &cFramesWritten)); 409 RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesChild1, ("Child1: Expected %RU32 written frames, got %RU32\n", cFramesChild1, cFramesWritten)); 410 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, cFramesWritten, &cFramesMixed)); 411 412 cChildrenSamplesMixedTotal += cFramesMixed; 413 414 RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesMixed, ("Child1: Expected %RU32 mixed frames, got %RU32\n", cFramesWritten, cFramesMixed)); 415 RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == 0, ("Child1: Expected %RU32 used frames, got %RU32\n", 0, AudioMixBufUsed(&child1))); 367 uint8_t const * const pau8TestSamples = (uint8_t const *)pvTestSamples; 368 uint8_t *pu8Dst = (uint8_t *)pbBuf; 369 while (cFrames-- > 0) 370 { 371 *pu8Dst++ = pau8TestSamples[iTestSample]; 372 iTestSample = (iTestSample + 1) % cTestSamples; 373 } 374 break; 416 375 } 417 376 418 uint32_t cChild2Writes = RTRandU32() % 8; 419 420 for (uint32_t c2 = 0; c2 < cChild2Writes; c2++) 377 case 2: 421 378 { 422 /* Child 2. */ 423 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &aFrames16, sizeof(aFrames16), &cFramesWritten)); 424 RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesChild2, ("Child2: Expected %RU32 written frames, got %RU32\n", cFramesChild2, cFramesWritten)); 425 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, cFramesWritten, &cFramesMixed)); 426 427 cChildrenSamplesMixedTotal += cFramesMixed; 428 429 RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesMixed, ("Child2: Expected %RU32 mixed frames, got %RU32\n", cFramesWritten, cFramesMixed)); 430 RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == 0, ("Child2: Expected %RU32 used frames, got %RU32\n", 0, AudioMixBufUsed(&child2))); 379 uint16_t const * const pau16TestSamples = (uint16_t const *)pvTestSamples; 380 uint16_t *pu16Dst = (uint16_t *)pbBuf; 381 while (cFrames-- > 0) 382 { 383 *pu16Dst++ = pau16TestSamples[iTestSample]; 384 iTestSample = (iTestSample + 1) % cTestSamples; 385 } 386 break; 431 387 } 432 388 433 /* 434 * Read out all frames from the parent buffer and also mark the just-read frames as finished 435 * so that both connected children buffers can keep track of their stuff. 436 */ 437 uint32_t cParentSamples = AudioMixBufUsed(&parent); 438 while (cParentSamples) 389 case 4: 439 390 { 440 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufAcquireReadBlock(&parent, pvBuf, cbBuf, &cFramesRead)); 441 if (!cFramesRead) 442 break; 443 444 AudioMixBufReleaseReadBlock(&parent, cFramesRead); 445 AudioMixBufFinish(&parent, cFramesRead); 446 447 RTTESTI_CHECK(cParentSamples >= cFramesRead); 448 cParentSamples -= cFramesRead; 391 uint32_t const * const pau32TestSamples = (uint32_t const *)pvTestSamples; 392 uint32_t *pu32Dst = (uint32_t *)pbBuf; 393 while (cFrames-- > 0) 394 { 395 *pu32Dst++ = pau32TestSamples[iTestSample]; 396 iTestSample = (iTestSample + 1) % cTestSamples; 397 } 398 break; 449 399 } 450 400 451 RTTESTI_CHECK(cParentSamples == 0); 452 } 453 454 RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0); 455 RTTESTI_CHECK(AudioMixBufLive(&child1) == 0); 456 RTTESTI_CHECK(AudioMixBufLive(&child2) == 0); 457 458 AudioMixBufDestroy(&parent); 459 AudioMixBufDestroy(&child1); 460 AudioMixBufDestroy(&child2); 461 462 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS; 401 case 8: 402 { 403 uint64_t const * const pau64TestSamples = (uint64_t const *)pvTestSamples; 404 uint64_t *pu64Dst = (uint64_t *)pbBuf; 405 while (cFrames-- > 0) 406 { 407 *pu64Dst++ = pau64TestSamples[iTestSample]; 408 iTestSample = (iTestSample + 1) % cTestSamples; 409 } 410 break; 411 } 412 413 default: 414 AssertFailedBreak(); 415 } 416 return iTestSample; 463 417 } 418 419 420 static void tstConversion(RTTEST hTest, uint8_t cSrcBits, bool fSrcSigned, uint8_t cSrcChs, 421 uint8_t cDstBits, bool fDstSigned, uint8_t cDstChs) 422 { 423 RTTestSubF(hTest, "Conv %uch %c%u to %uch %c%u", cSrcChs, fSrcSigned ? 'S' : 'U', cSrcBits, 424 cDstChs, fDstSigned ? 'S' : 'U', cDstBits); 425 426 PDMAUDIOPCMPROPS CfgSrc, CfgDst; 427 PDMAudioPropsInitEx(&CfgSrc, cSrcBits / 8, fSrcSigned, cSrcChs, 44100, g_fLittleEndian, cSrcBits == 64 /*fRaw*/); 428 PDMAudioPropsInitEx(&CfgDst, cDstBits / 8, fDstSigned, cDstChs, 44100, g_fLittleEndian, cDstBits == 64 /*fRaw*/); 429 430 void const * const pvSrcTestSamples = g_aTestSamples[cSrcBits / 8].apv[fSrcSigned]; 431 void const * const pvDstTestSamples = g_aTestSamples[cDstBits / 8].apv[fDstSigned]; 432 uint32_t const cMixBufFrames = RTRandU32Ex(128, 16384); 433 uint32_t const cIterations = RTRandU32Ex(256, 1536); 434 uint32_t const cbSrcBuf = PDMAudioPropsFramesToBytes(&CfgSrc, cMixBufFrames + 64); 435 uint8_t * const pbSrcBuf = (uint8_t *)RTMemAllocZ(cbSrcBuf); 436 uint32_t const cbDstBuf = PDMAudioPropsFramesToBytes(&CfgDst, cMixBufFrames + 64); 437 uint8_t * const pbDstBuf = (uint8_t *)RTMemAllocZ(cbDstBuf); 438 uint8_t * const pbDstExpect = (uint8_t *)RTMemAllocZ(cbDstBuf); 439 RTTESTI_CHECK_RETV(pbSrcBuf); 440 RTTESTI_CHECK_RETV(pbDstBuf); 441 RTTESTI_CHECK_RETV(pbDstExpect); 442 443 AUDIOMIXBUF MixBuf; 444 RTTESTI_CHECK_RC_RETV(AudioMixBufInit(&MixBuf, "FormatOutputConversion", &CfgSrc, cMixBufFrames), VINF_SUCCESS); 445 AUDIOMIXBUFWRITESTATE WriteState; 446 RTTESTI_CHECK_RC_RETV(AudioMixBufInitWriteState(&MixBuf, &WriteState, &CfgSrc), VINF_SUCCESS); 447 AUDIOMIXBUFWRITESTATE WriteStateIgnZero = WriteState; 448 AUDIOMIXBUFPEEKSTATE PeekState; 449 RTTESTI_CHECK_RC_RETV(AudioMixBufInitPeekState(&MixBuf, &PeekState, &CfgDst), VINF_SUCCESS); 450 451 uint32_t iSrcTestSample = 0; 452 uint32_t iDstTestSample = 0; 453 //RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "cIterations=%u\n", cIterations); 454 for (uint32_t iIteration = 0; iIteration < cIterations; iIteration++) 455 { 456 /* Write some frames to the buffer. */ 457 uint32_t const cSrcFramesToWrite = iIteration < 16 ? iIteration + 1 458 : AudioMixBufFree(&MixBuf) ? RTRandU32Ex(1, AudioMixBufFree(&MixBuf)) : 0; 459 if (cSrcFramesToWrite > 0) 460 { 461 uint32_t const cbSrcToWrite = PDMAudioPropsFramesToBytes(&CfgSrc, cSrcFramesToWrite); 462 uint32_t cFrames = RTRandU32(); 463 switch (RTRandU32Ex(0, 3)) 464 { 465 default: 466 iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite); 467 AudioMixBufWrite(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames); 468 RTTESTI_CHECK(cFrames == cSrcFramesToWrite); 469 break; 470 471 #if 0 /** @todo doesn't work for some U64 variations */ 472 case 1: /* zero & blend */ 473 AudioMixBufSilence(&MixBuf, &WriteStateIgnZero, 0 /*offFrame*/, cSrcFramesToWrite); 474 iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite); 475 AudioMixBufBlend(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames); 476 RTTESTI_CHECK(cFrames == cSrcFramesToWrite); 477 break; 464 478 #endif 479 480 case 2: /* blend same equal data twice */ 481 { 482 AUDIOMIXBUFWRITESTATE WriteStateSame = WriteState; 483 iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite); 484 AudioMixBufWrite(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames); 485 RTTESTI_CHECK(cFrames == cSrcFramesToWrite); 486 AudioMixBufBlend(&MixBuf, &WriteStateSame, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames); 487 RTTESTI_CHECK(cFrames == cSrcFramesToWrite); 488 break; 489 } 490 case 3: /* write & blend with zero */ 491 { 492 AUDIOMIXBUFWRITESTATE WriteStateSame = WriteState; 493 iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite); 494 AudioMixBufWrite(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames); 495 RTTESTI_CHECK(cFrames == cSrcFramesToWrite); 496 PDMAudioPropsClearBuffer(&CfgSrc, pbSrcBuf, cbSrcToWrite, cSrcFramesToWrite); 497 AudioMixBufBlend(&MixBuf, &WriteStateSame, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames); 498 RTTESTI_CHECK(cFrames == cSrcFramesToWrite); 499 break; 500 } 501 } 502 AudioMixBufCommit(&MixBuf, cSrcFramesToWrite); 503 } 504 505 /* Read some frames back. */ 506 uint32_t const cUsed = AudioMixBufUsed(&MixBuf); 507 uint32_t const cDstFramesToRead = iIteration < 16 ? iIteration + 1 : iIteration + 5 >= cIterations ? cUsed 508 : cUsed ? RTRandU32Ex(1, cUsed) : 0; 509 if (cDstFramesToRead > 0) 510 { 511 uint32_t const cbDstToRead = PDMAudioPropsFramesToBytes(&CfgDst, cDstFramesToRead); 512 uint32_t cbRead = RTRandU32(); 513 uint32_t cFrames = RTRandU32(); 514 RTRandBytes(pbDstBuf, cbDstToRead); 515 AudioMixBufPeek(&MixBuf, 0 /*offSrcFrame*/, (iIteration & 3) != 2 ? cDstFramesToRead : cUsed, &cFrames, 516 &PeekState, pbDstBuf, (iIteration & 3) != 3 ? cbDstToRead : cbDstBuf, &cbRead); 517 RTTESTI_CHECK(cFrames == cDstFramesToRead); 518 RTTESTI_CHECK(cbRead == cbDstToRead); 519 AudioMixBufAdvance(&MixBuf, cFrames); 520 521 /* Verify if we can. */ 522 if (PDMAudioPropsChannels(&CfgSrc) == PDMAudioPropsChannels(&CfgDst)) 523 { 524 iDstTestSample = tstFillBuf(&CfgDst, pvDstTestSamples, iDstTestSample, pbDstExpect, cFrames); 525 if (memcmp(pbDstExpect, pbDstBuf, cbRead) == 0) 526 { /* likely */ } 527 else 528 { 529 RTTestFailed(hTest, 530 "mismatch: %.*Rhxs\n" 531 "expected: %.*Rhxs\n" 532 "iIteration=%u cDstFramesToRead=%u cbRead=%#x\n", 533 RT_MIN(cbRead, 48), pbDstBuf, 534 RT_MIN(cbRead, 48), pbDstExpect, 535 iIteration, cDstFramesToRead, cbRead); 536 break; 537 } 538 } 539 } 540 } 541 542 AudioMixBufTerm(&MixBuf); 543 RTMemFree(pbSrcBuf); 544 RTMemFree(pbDstBuf); 545 RTMemFree(pbDstExpect); 546 } 465 547 466 548 … … 677 759 } 678 760 679 680 #if 0 /** @todo rewrite to non-parent/child setup */681 /* Test 8-bit sample conversion (8-bit -> internal -> 8-bit). */682 static int tstConversion8(RTTEST hTest)683 {684 RTTestSub(hTest, "Convert 22kHz/U8 to 44.1kHz/S16 (mono)");685 unsigned i;686 uint32_t cBufSize = 256;687 688 689 /* 44100Hz, 1 Channel, U8 */690 PDMAUDIOPCMPROPS cfg_p = PDMAUDIOPCMPROPS_INITIALIZER(691 1, /* Bytes */692 false, /* Signed */693 1, /* Channels */694 44100, /* Hz */695 false /* Swap Endian */696 );697 698 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));699 700 AUDIOMIXBUF parent;701 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));702 703 /* Child uses half the sample rate; that ensures the mixing engine can't704 * take shortcuts and performs conversion. Because conversion to double705 * the sample rate effectively inserts one additional sample between every706 * two source frames, N source frames will be converted to N * 2 - 1707 * frames. However, the last source sample will be saved for later708 * interpolation and not immediately output.709 */710 711 /* 22050Hz, 1 Channel, U8 */712 PDMAUDIOPCMPROPS cfg_c = PDMAUDIOPCMPROPS_INITIALIZER( /* Upmixing to parent */713 1, /* Bytes */714 false, /* Signed */715 1, /* Channels */716 22050, /* Hz */717 false /* Swap Endian */718 );719 720 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));721 722 AUDIOMIXBUF child;723 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));724 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));725 726 /* 8-bit unsigned frames. Often used with SB16 device. */727 uint8_t aFrames8U[16] = { 0xAA, 0xBB, 0, 1, 43, 125, 126, 127,728 128, 129, 130, 131, 132, UINT8_MAX - 1, UINT8_MAX, 0 };729 730 /*731 * Writing + mixing from child -> parent, sequential.732 */733 uint32_t cbBuf = 256;734 char achBuf[256];735 uint32_t cFramesRead, cFramesWritten, cFramesMixed;736 737 uint32_t cFramesChild = 16;738 uint32_t cFramesParent = cFramesChild * 2 - 2;739 uint32_t cFramesTotalRead = 0;740 741 /**** 8-bit unsigned samples ****/742 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 8-bit\n", cfg_c.uHz, PDMAudioPropsChannels(&cfg_c));743 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &aFrames8U, sizeof(aFrames8U), &cFramesWritten));744 RTTESTI_CHECK_MSG(cFramesWritten == cFramesChild, ("Child: Expected %RU32 written frames, got %RU32\n", cFramesChild, cFramesWritten));745 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cFramesWritten, &cFramesMixed));746 uint32_t cFrames = AudioMixBufUsed(&parent);747 RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == cFrames, ("Child: Expected %RU32 mixed frames, got %RU32\n", AudioMixBufLive(&child), cFrames));748 749 RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));750 751 for (;;)752 {753 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufAcquireReadBlock(&parent, achBuf, cbBuf, &cFramesRead));754 if (!cFramesRead)755 break;756 cFramesTotalRead += cFramesRead;757 AudioMixBufReleaseReadBlock(&parent, cFramesRead);758 AudioMixBufFinish(&parent, cFramesRead);759 }760 761 RTTESTI_CHECK_MSG(cFramesTotalRead == cFramesParent, ("Parent: Expected %RU32 mixed frames, got %RU32\n", cFramesParent, cFramesTotalRead));762 763 /* Check that the frames came out unharmed. Every other sample is interpolated and we ignore it. */764 /* NB: This also checks that the default volume setting is 0dB attenuation. */765 uint8_t *pSrc8 = &aFrames8U[0];766 uint8_t *pDst8 = (uint8_t *)achBuf;767 768 for (i = 0; i < cFramesChild - 1; ++i)769 {770 RTTESTI_CHECK_MSG(*pSrc8 == *pDst8, ("index %u: Dst=%d, Src=%d\n", i, *pDst8, *pSrc8));771 pSrc8 += 1;772 pDst8 += 2;773 }774 775 RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);776 RTTESTI_CHECK(AudioMixBufLive(&child) == 0);777 778 AudioMixBufDestroy(&parent);779 AudioMixBufDestroy(&child);780 781 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;782 }783 #endif784 785 #if 0 /** @todo rewrite to non-parent/child setup */786 /* Test 16-bit sample conversion (16-bit -> internal -> 16-bit). */787 static int tstConversion16(RTTEST hTest)788 {789 RTTestSub(hTest, "Convert 22kHz/S16 to 44.1kHz/S16 (mono)");790 unsigned i;791 uint32_t cBufSize = 256;792 793 /* 44100Hz, 1 Channel, S16 */794 PDMAUDIOPCMPROPS cfg_p = PDMAUDIOPCMPROPS_INITIALIZER(795 2, /* Bytes */796 true, /* Signed */797 1, /* Channels */798 44100, /* Hz */799 false /* Swap Endian */800 );801 802 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));803 804 AUDIOMIXBUF parent;805 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));806 807 /* 22050Hz, 1 Channel, S16 */808 PDMAUDIOPCMPROPS cfg_c = PDMAUDIOPCMPROPS_INITIALIZER( /* Upmixing to parent */809 2, /* Bytes */810 true, /* Signed */811 1, /* Channels */812 22050, /* Hz */813 false /* Swap Endian */814 );815 816 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));817 818 AUDIOMIXBUF child;819 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));820 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));821 822 /* 16-bit signed. More or less exclusively used as output, and usually as input, too. */823 int16_t aFrames16S[16] = { 0xAA, 0xBB, INT16_MIN, INT16_MIN + 1, INT16_MIN / 2, -3, -2, -1,824 0, 1, 2, 3, INT16_MAX / 2, INT16_MAX - 1, INT16_MAX, 0 };825 826 /*827 * Writing + mixing from child -> parent, sequential.828 */829 uint32_t cbBuf = 256;830 char achBuf[256];831 uint32_t cFramesRead, cFramesWritten, cFramesMixed;832 833 uint32_t cFramesChild = 16;834 uint32_t cFramesParent = cFramesChild * 2 - 2;835 uint32_t cFramesTotalRead = 0;836 837 /**** 16-bit signed samples ****/838 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 16-bit\n", cfg_c.uHz, PDMAudioPropsChannels(&cfg_c));839 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &aFrames16S, sizeof(aFrames16S), &cFramesWritten));840 RTTESTI_CHECK_MSG(cFramesWritten == cFramesChild, ("Child: Expected %RU32 written frames, got %RU32\n", cFramesChild, cFramesWritten));841 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cFramesWritten, &cFramesMixed));842 uint32_t cFrames = AudioMixBufUsed(&parent);843 RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == cFrames, ("Child: Expected %RU32 mixed frames, got %RU32\n", AudioMixBufLive(&child), cFrames));844 845 RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));846 847 for (;;)848 {849 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufAcquireReadBlock(&parent, achBuf, cbBuf, &cFramesRead));850 if (!cFramesRead)851 break;852 cFramesTotalRead += cFramesRead;853 AudioMixBufReleaseReadBlock(&parent, cFramesRead);854 AudioMixBufFinish(&parent, cFramesRead);855 }856 RTTESTI_CHECK_MSG(cFramesTotalRead == cFramesParent, ("Parent: Expected %RU32 mixed frames, got %RU32\n", cFramesParent, cFramesTotalRead));857 858 /* Check that the frames came out unharmed. Every other sample is interpolated and we ignore it. */859 /* NB: This also checks that the default volume setting is 0dB attenuation. */860 int16_t *pSrc16 = &aFrames16S[0];861 int16_t *pDst16 = (int16_t *)achBuf;862 863 for (i = 0; i < cFramesChild - 1; ++i)864 {865 RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16));866 pSrc16 += 1;867 pDst16 += 2;868 }869 870 RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);871 RTTESTI_CHECK(AudioMixBufLive(&child) == 0);872 873 AudioMixBufDestroy(&parent);874 AudioMixBufDestroy(&child);875 876 return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;877 }878 #endif879 880 761 #if 0 /** @todo rewrite to non-parent/child setup */ 881 762 /* Test volume control. */ … … 1011 892 tstBasics(hTest); 1012 893 tstSimple(hTest); 1013 //tstParentChild(hTest); 1014 //tstConversion8(hTest); 1015 //tstConversion16(hTest); 1016 //tstVolume(hTest); 894 895 /* Run tstConversion for all combinations we have test data. */ 896 for (unsigned iSrc = 0; iSrc < RT_ELEMENTS(g_aTestSamples); iSrc++) 897 { 898 for (unsigned iSrcSigned = 0; iSrcSigned < RT_ELEMENTS(g_aTestSamples[0].apv); iSrcSigned++) 899 if (g_aTestSamples[iSrc].apv[iSrcSigned]) 900 for (unsigned cSrcChs = 1; cSrcChs <= 2; cSrcChs++) 901 for (unsigned iDst = 0; iDst < RT_ELEMENTS(g_aTestSamples); iDst++) 902 for (unsigned iDstSigned = 0; iDstSigned < RT_ELEMENTS(g_aTestSamples[0].apv); iDstSigned++) 903 if (g_aTestSamples[iDst].apv[iDstSigned]) 904 for (unsigned cDstChs = 1; cDstChs <= 2; cDstChs++) 905 tstConversion(hTest, iSrc * 8, iSrcSigned == 1, cSrcChs, 906 /*->*/ iDst * 8, iDstSigned == 1, cDstChs); 907 } 908 1017 909 #if 0 /** @todo rewrite to non-parent/child setup */ 1018 910 tstDownsampling(hTest, 44100, 22050); … … 1029 921 //tstNewPeek(hTest, 22050, 44100); 1030 922 923 //tstVolume(hTest); 924 1031 925 /* 1032 926 * Summary
Note:
See TracChangeset
for help on using the changeset viewer.