Changeset 92461 in vbox for trunk/src/VBox/ValidationKit/utils/audio
- Timestamp:
- Nov 16, 2021 3:25:10 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 148319
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp
r92452 r92461 479 479 int audioTestPlayTone(PAUDIOTESTIOOPTS pIoOpts, PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms) 480 480 { 481 uint32_t const idxTest = (uint8_t)pParms->Hdr.idxTest; 482 481 483 AUDIOTESTTONE TstTone; 482 484 AudioTestToneInit(&TstTone, &pStream->Cfg.Props, pParms->dbFreqHz); … … 486 488 pcszPathOut = pTstEnv->Set.szPathAbs; 487 489 488 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing test tone (tone frequency is %RU16Hz, %RU32ms, %RU8%% volume)\n", 489 (uint16_t)pParms->dbFreqHz, pParms->msDuration, pParms->uVolumePercent); 490 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using %RU32ms stream scheduling hint\n", pStream->Cfg.Device.cMsSchedulingHint); 490 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Playing test tone (tone frequency is %RU16Hz, %RU32ms, %RU8%% volume)\n", 491 idxTest, (uint16_t)pParms->dbFreqHz, pParms->msDuration, pParms->uVolumePercent); 492 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Using %RU32ms stream scheduling hint\n", 493 idxTest, pStream->Cfg.Device.cMsSchedulingHint); 491 494 if (pcszPathOut) 492 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, " Writing to '%s'\n", pcszPathOut);495 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Writing to '%s'\n", idxTest, pcszPathOut); 493 496 494 497 int rc; … … 519 522 && AudioTestMixStreamIsOkay(&pStream->Mix)) 520 523 { 521 uint8_t abBuf[_4K]; 522 523 uint32_t cbToPlayTotal = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, pParms->msDuration); 524 AssertStmt(cbToPlayTotal, rc = VERR_INVALID_PARAMETER); 525 uint32_t cbPlayedTotal = 0; 524 uint32_t cbToWriteTotal = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, pParms->msDuration); 525 AssertStmt(cbToWriteTotal, rc = VERR_INVALID_PARAMETER); 526 uint32_t cbWrittenTotal = 0; 526 527 527 528 /* We play a pre + post beacon before + after the actual test tone. … … 533 534 if (cbBeacon) 534 535 { 535 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing 2 x %RU32 bytes pre/post beacons\n", cbBeacon); 536 cbToPlayTotal += cbBeacon * 2 /* Pre + post beacon */; 537 } 536 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Playing 2 x %RU32 bytes pre/post beacons\n", 537 idxTest, cbBeacon); 538 539 if (g_uVerbosity >= 2) 540 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Playing %s beacon ...\n", 541 idxTest, AudioTestBeaconTypeGetName(Beacon.enmType)); 542 } 543 544 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Playing %RU32 bytes total\n", idxTest, cbToWriteTotal); 538 545 539 546 AudioTestObjAddMetadataStr(Obj, "test_id=%04RU32\n", pParms->Hdr.idxTest); … … 541 548 AudioTestObjAddMetadataStr(Obj, "beacon_pre_bytes=%RU32\n", cbBeacon); 542 549 AudioTestObjAddMetadataStr(Obj, "beacon_post_bytes=%RU32\n", cbBeacon); 543 AudioTestObjAddMetadataStr(Obj, "stream_to_ play_bytes=%RU32\n", cbToPlayTotal);550 AudioTestObjAddMetadataStr(Obj, "stream_to_write_total_bytes=%RU32\n", cbToWriteTotal); 544 551 AudioTestObjAddMetadataStr(Obj, "stream_period_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPeriod); 545 552 AudioTestObjAddMetadataStr(Obj, "stream_buffer_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesBufferSize); … … 549 556 AudioTestObjAddMetadataStr(Obj, "device_scheduling_hint_ms=%RU32\n", pStream->Cfg.Device.cMsSchedulingHint); 550 557 551 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing %RU32 bytes total\n", cbToPlayTotal);552 553 558 PAUDIOTESTDRVMIXSTREAM pMix = &pStream->Mix; 554 559 … … 562 567 uint64_t nsLastWrite = 0; 563 568 564 while (cbPlayedTotal < cbToPlayTotal) 569 AUDIOTESTSTATE enmState = AUDIOTESTSTATE_PRE; 570 uint8_t abBuf[_16K]; 571 572 for (;;) 565 573 { 566 574 uint64_t const nsNow = RTTimeNanoTS(); … … 579 587 } 580 588 581 uint32_t cb Played= 0;589 uint32_t cbWritten = 0; 582 590 uint32_t const cbCanWrite = AudioTestMixStreamGetWritable(&pStream->Mix); 583 591 if (cbCanWrite) 584 592 { 585 if (g_uVerbosity >= 3) 586 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Stream is writable with %RU64ms (%RU32 bytes)\n", 587 PDMAudioPropsBytesToMilli(pMix->pProps, cbCanWrite), cbCanWrite); 588 589 uint32_t cbToPlay; 590 591 /* Any beacon to play? */ 592 uint32_t const cbBeaconRemaining = AudioTestBeaconGetRemaining(&Beacon); 593 if (cbBeaconRemaining) 593 if (g_uVerbosity >= 4) 594 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Stream is writable with %RU64ms (%RU32 bytes)\n", 595 idxTest, PDMAudioPropsBytesToMilli(pMix->pProps, cbCanWrite), cbCanWrite); 596 597 switch (enmState) 594 598 { 595 /* Limit to exactly one beacon (pre or post). */ 596 cbToPlay = RT_MIN(sizeof(abBuf), RT_MIN(cbCanWrite, cbBeaconRemaining)); 597 rc = AudioTestBeaconWrite(&Beacon, abBuf, cbToPlay); 598 if (RT_SUCCESS(rc)) 599 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed); 600 if (RT_FAILURE(rc)) 601 break; 602 603 if (pTstEnv) 599 case AUDIOTESTSTATE_PRE: 600 RT_FALL_THROUGH(); 601 case AUDIOTESTSTATE_POST: 604 602 { 605 /* Also write the beacon data to the test object. 606 * Note: We use cbPlayed here instead of cbToPlay to know if the data actually was 607 * reported as being played by the audio stack. */ 608 rc = AudioTestObjWrite(Obj, abBuf, cbPlayed); 609 } 610 } 611 else /* Play test tone */ 612 { 613 uint32_t const cbTestToneToPlay = cbToPlayTotal - cbPlayedTotal - (cbBeacon /* Pre / post beacon */); 614 if (cbTestToneToPlay == 0) /* Done playing the test tone? */ 615 { 616 if (AudioTestBeaconGetSize(&Beacon)) /* Play the post beacon, if any. */ 603 if (g_uVerbosity >= 4) 604 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: %RU32 bytes (%RU64ms) beacon data remaining\n", 605 idxTest, AudioTestBeaconGetRemaining(&Beacon), 606 PDMAudioPropsBytesToMilli(&pStream->pStream->Cfg.Props, AudioTestBeaconGetRemaining(&Beacon))); 607 608 bool fGoToNextStage = false; 609 610 if ( AudioTestBeaconGetSize(&Beacon) 611 && !AudioTestBeaconIsComplete(&Beacon)) 617 612 { 618 AudioTestBeaconInit(&Beacon, (uint8_t)pParms->Hdr.idxTest, AUDIOTESTTONEBEACONTYPE_PLAY_POST, 619 &pStream->Cfg.Props); 620 continue; 613 bool const fStarted = AudioTestBeaconGetRemaining(&Beacon) == AudioTestBeaconGetSize(&Beacon); 614 615 uint32_t const cbBeaconRemaining = AudioTestBeaconGetRemaining(&Beacon); 616 AssertBreakStmt(cbBeaconRemaining, VERR_WRONG_ORDER); 617 618 /* Limit to exactly one beacon (pre or post). */ 619 uint32_t const cbToWrite = RT_MIN(sizeof(abBuf), RT_MIN(cbCanWrite, cbBeaconRemaining)); 620 621 rc = AudioTestBeaconWrite(&Beacon, abBuf, cbToWrite); 622 if (RT_SUCCESS(rc)) 623 { 624 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToWrite, &cbWritten); 625 if ( RT_SUCCESS(rc) 626 && pTstEnv) 627 { 628 /* Also write the beacon data to the test object. 629 * Note: We use cbPlayed here instead of cbToPlay to know if the data actually was 630 * reported as being played by the audio stack. */ 631 rc = AudioTestObjWrite(Obj, abBuf, cbWritten); 632 } 633 } 634 635 if ( fStarted 636 && g_uVerbosity >= 2) 637 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Writing %s beacon begin\n", 638 idxTest, AudioTestBeaconTypeGetName(Beacon.enmType)); 639 if (AudioTestBeaconIsComplete(&Beacon)) 640 { 641 if (g_uVerbosity >= 2) 642 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Writing %s beacon end\n", 643 idxTest, AudioTestBeaconTypeGetName(Beacon.enmType)); 644 fGoToNextStage = true; 645 } 621 646 } 622 647 else 648 fGoToNextStage = true; 649 650 if (fGoToNextStage) 651 { 652 if (enmState == AUDIOTESTSTATE_PRE) 653 enmState = AUDIOTESTSTATE_RUN; 654 else if (enmState == AUDIOTESTSTATE_POST) 655 enmState = AUDIOTESTSTATE_DONE; 656 } 623 657 break; 624 658 } 625 659 626 uint32_t const cbToGenerate = RT_MIN(RT_MIN(cbTestToneToPlay, sizeof(abBuf)), cbCanWrite); 627 rc = AudioTestToneGenerate(&TstTone, abBuf, cbToGenerate, &cbToPlay); 628 if (RT_SUCCESS(rc)) 660 case AUDIOTESTSTATE_RUN: 629 661 { 630 if (pTstEnv) 662 uint32_t cbToWrite = RT_MIN(sizeof(abBuf), cbCanWrite); 663 cbToWrite = RT_MIN(cbToWrite, cbToWriteTotal - cbWrittenTotal); 664 if (cbToWrite) 631 665 { 632 /* Write stuff to disk before trying to play it. Help analysis later. */ 633 rc = AudioTestObjWrite(Obj, abBuf, cbToPlay); 634 } 635 if (RT_SUCCESS(rc)) 636 { 637 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed); 666 rc = AudioTestToneGenerate(&TstTone, abBuf, cbToWrite, &cbToWrite); 638 667 if (RT_SUCCESS(rc)) 639 668 { 640 AssertBreakStmt(cbPlayed <= cbToPlay, rc = VERR_TOO_MUCH_DATA); 641 642 offStream += cbPlayed; 643 644 if (cbPlayed != cbToPlay) 645 RTTestFailed(g_hTest, "Only played %RU32/%RU32 bytes", cbPlayed, cbToPlay); 646 647 if (cbPlayed) 648 nsLastWrite = nsNow; 669 if (pTstEnv) 670 { 671 /* Write stuff to disk before trying to play it. Help analysis later. */ 672 rc = AudioTestObjWrite(Obj, abBuf, cbToWrite); 673 } 674 675 if (RT_SUCCESS(rc)) 676 { 677 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToWrite, &cbWritten); 678 if (RT_SUCCESS(rc)) 679 { 680 AssertBreakStmt(cbWritten <= cbToWrite, rc = VERR_TOO_MUCH_DATA); 681 682 offStream += cbWritten; 683 684 if (cbWritten != cbToWrite) 685 RTTestFailed(g_hTest, "Test #%RU32: Only played %RU32/%RU32 bytes", 686 idxTest, cbWritten, cbToWrite); 687 688 if (cbWritten) 689 nsLastWrite = nsNow; 690 691 if (g_uVerbosity >= 4) 692 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 693 "Test #%RU32: Played back %RU32 bytes\n", idxTest, cbWritten); 694 695 cbWrittenTotal += cbWritten; 696 } 697 } 649 698 } 650 699 } 700 701 const bool fComplete = cbWrittenTotal >= cbToWriteTotal; 702 if (fComplete) 703 { 704 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Playing back audio data ended\n", idxTest); 705 706 enmState = AUDIOTESTSTATE_POST; 707 708 /* Re-use the beacon object, but this time it's the post beacon. */ 709 AudioTestBeaconInit(&Beacon, (uint8_t)idxTest, AUDIOTESTTONEBEACONTYPE_PLAY_POST, 710 &pStream->Cfg.Props); 711 } 712 break; 651 713 } 714 715 case AUDIOTESTSTATE_DONE: 716 { 717 /* Handled below. */ 718 break; 719 } 720 721 default: 722 AssertFailed(); 723 break; 652 724 } 653 725 654 726 if (RT_FAILURE(rc)) 727 break; 728 729 if (enmState == AUDIOTESTSTATE_DONE) 655 730 break; 656 731 … … 665 740 || (nsNow - nsLastMsgCantWrite) > RT_NS_10SEC)) /* Don't spam the output too much. */ 666 741 { 667 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, " Waiting %RU32ms for stream to be writable again (last write %RU64ns ago) ...\n",668 msSleep, nsNow - nsLastWrite);742 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Waiting %RU32ms for stream to be writable again (last write %RU64ns ago) ...\n", 743 idxTest, msSleep, nsNow - nsLastWrite); 669 744 nsLastMsgCantWrite = nsNow; 670 745 } … … 675 750 AssertFailedBreakStmt(rc = VERR_AUDIO_STREAM_NOT_READY); 676 751 677 cbPlayedTotal += cbPlayed;678 AssertBreakStmt(cbPlayedTotal <= cbToPlayTotal, VERR_BUFFER_OVERFLOW);679 680 752 /* Fail-safe in case something screwed up while playing back. */ 681 753 uint64_t const cNsElapsed = nsNow - nsStarted; 682 754 if (cNsElapsed > nsTimeout) 683 755 { 684 RTTestFailed(g_hTest, "Playback took too long (running %RU64 vs. timeout %RU64), aborting\n", cNsElapsed, nsTimeout); 756 RTTestFailed(g_hTest, "Test #%RU32: Playback took too long (running %RU64 vs. timeout %RU64), aborting\n", 757 idxTest, cNsElapsed, nsTimeout); 685 758 rc = VERR_TIMEOUT; 686 759 } … … 688 761 if (RT_FAILURE(rc)) 689 762 break; 690 } 691 692 if (cbPlayedTotal != cbToPlayTotal) 693 RTTestFailed(g_hTest, "Playback ended unexpectedly (%RU32/%RU32 played)\n", cbPlayedTotal, cbToPlayTotal); 763 } /* for */ 764 765 if (cbWrittenTotal != cbToWriteTotal) 766 RTTestFailed(g_hTest, "Test #%RU32: Playback ended unexpectedly (%RU32/%RU32 played)\n", 767 idxTest, cbWrittenTotal, cbToWriteTotal); 694 768 695 769 if (RT_SUCCESS(rc)) 696 770 { 697 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, " Draining stream ...\n");771 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Draining stream ...\n", idxTest); 698 772 rc = AudioTestMixStreamDrain(&pStream->Mix, true /*fSync*/); 699 773 } … … 710 784 711 785 if (RT_FAILURE(rc)) 712 RTTestFailed(g_hTest, " Playing tone failed with %Rrc\n", rc);786 RTTestFailed(g_hTest, "Test #%RU32: Playing tone failed with %Rrc\n", idxTest, rc); 713 787 714 788 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.