VirtualBox

Ignore:
Timestamp:
Nov 16, 2021 3:25:10 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
148319
Message:

Audio/Validation Kit: Use the same audio test states in audioTestPlayTone() as we do in the Validation Kit audio driver in drvHostValKitAudioHA_StreamPlay(). bugref:10008

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp

    r92452 r92461  
    479479int audioTestPlayTone(PAUDIOTESTIOOPTS pIoOpts, PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)
    480480{
     481    uint32_t const idxTest = (uint8_t)pParms->Hdr.idxTest;
     482
    481483    AUDIOTESTTONE TstTone;
    482484    AudioTestToneInit(&TstTone, &pStream->Cfg.Props, pParms->dbFreqHz);
     
    486488        pcszPathOut = pTstEnv->Set.szPathAbs;
    487489
    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);
    491494    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);
    493496
    494497    int rc;
     
    519522        && AudioTestMixStreamIsOkay(&pStream->Mix))
    520523    {
    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;
    526527
    527528        /* We play a pre + post beacon before + after the actual test tone.
     
    533534        if (cbBeacon)
    534535        {
    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);
    538545
    539546        AudioTestObjAddMetadataStr(Obj, "test_id=%04RU32\n", pParms->Hdr.idxTest);
     
    541548        AudioTestObjAddMetadataStr(Obj, "beacon_pre_bytes=%RU32\n", cbBeacon);
    542549        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);
    544551        AudioTestObjAddMetadataStr(Obj, "stream_period_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPeriod);
    545552        AudioTestObjAddMetadataStr(Obj, "stream_buffer_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesBufferSize);
     
    549556        AudioTestObjAddMetadataStr(Obj, "device_scheduling_hint_ms=%RU32\n", pStream->Cfg.Device.cMsSchedulingHint);
    550557
    551         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing %RU32 bytes total\n", cbToPlayTotal);
    552 
    553558        PAUDIOTESTDRVMIXSTREAM pMix = &pStream->Mix;
    554559
     
    562567        uint64_t        nsLastWrite        = 0;
    563568
    564         while (cbPlayedTotal < cbToPlayTotal)
     569        AUDIOTESTSTATE  enmState           = AUDIOTESTSTATE_PRE;
     570        uint8_t         abBuf[_16K];
     571
     572        for (;;)
    565573        {
    566574            uint64_t const nsNow = RTTimeNanoTS();
     
    579587            }
    580588
    581             uint32_t       cbPlayed   = 0;
     589            uint32_t       cbWritten  = 0;
    582590            uint32_t const cbCanWrite = AudioTestMixStreamGetWritable(&pStream->Mix);
    583591            if (cbCanWrite)
    584592            {
    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)
    594598                {
    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:
    604602                    {
    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))
    617612                        {
    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                            }
    621646                        }
    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                        }
    623657                        break;
    624658                    }
    625659
    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:
    629661                    {
    630                         if (pTstEnv)
     662                        uint32_t cbToWrite = RT_MIN(sizeof(abBuf), cbCanWrite);
     663                                 cbToWrite = RT_MIN(cbToWrite, cbToWriteTotal - cbWrittenTotal);
     664                        if (cbToWrite)
    631665                        {
    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);
    638667                            if (RT_SUCCESS(rc))
    639668                            {
    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                                }
    649698                            }
    650699                        }
     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;
    651713                    }
     714
     715                    case AUDIOTESTSTATE_DONE:
     716                    {
     717                        /* Handled below. */
     718                        break;
     719                    }
     720
     721                    default:
     722                        AssertFailed();
     723                        break;
    652724                }
    653725
    654726                if (RT_FAILURE(rc))
     727                    break;
     728
     729                if (enmState == AUDIOTESTSTATE_DONE)
    655730                    break;
    656731
     
    665740                        || (nsNow - nsLastMsgCantWrite) > RT_NS_10SEC)) /* Don't spam the output too much. */
    666741                {
    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);
    669744                    nsLastMsgCantWrite = nsNow;
    670745                }
     
    675750                AssertFailedBreakStmt(rc = VERR_AUDIO_STREAM_NOT_READY);
    676751
    677             cbPlayedTotal += cbPlayed;
    678             AssertBreakStmt(cbPlayedTotal <= cbToPlayTotal, VERR_BUFFER_OVERFLOW);
    679 
    680752            /* Fail-safe in case something screwed up while playing back. */
    681753            uint64_t const cNsElapsed = nsNow - nsStarted;
    682754            if (cNsElapsed > nsTimeout)
    683755            {
    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);
    685758                rc = VERR_TIMEOUT;
    686759            }
     
    688761            if (RT_FAILURE(rc))
    689762                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);
    694768
    695769        if (RT_SUCCESS(rc))
    696770        {
    697             RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Draining stream ...\n");
     771            RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%RU32: Draining stream ...\n", idxTest);
    698772            rc = AudioTestMixStreamDrain(&pStream->Mix, true /*fSync*/);
    699773        }
     
    710784
    711785    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);
    713787
    714788    return rc;
Note: See TracChangeset for help on using the changeset viewer.

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