VirtualBox

Changeset 89890 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
Jun 24, 2021 3:56:05 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145348
Message:

Audio/ValKit: More code for audio verification. bugref:10008

Location:
trunk/src/VBox/ValidationKit/utils/audio
Files:
4 edited

Legend:

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

    r89850 r89890  
    6161*   Internal Functions                                                                                                           *
    6262*********************************************************************************************************************************/
    63 static int audioTestCombineParms(PAUDIOTESTPARMS pBaseParms, PAUDIOTESTPARMS pOverrideParms);
    6463static int audioVerifyOne(const char *pszPathSetA, const char *pszPathSetB);
    6564
     
    230229
    231230
    232 /**
    233  * Overrides audio test base parameters with another set.
    234  *
    235  * @returns VBox status code.
    236  * @param   pBaseParms          Base parameters to override.
    237  * @param   pOverrideParms      Override parameters to use for overriding the base parameters.
    238  *
    239  * @note    Overriding a parameter depends on its type / default values.
    240  */
    241 static int audioTestCombineParms(PAUDIOTESTPARMS pBaseParms, PAUDIOTESTPARMS pOverrideParms)
    242 {
    243     RT_NOREF(pBaseParms, pOverrideParms);
    244 
    245     /** @todo Implement parameter overriding. */
    246     return VERR_NOT_IMPLEMENTED;
    247 }
    248 
    249 
    250231/*********************************************************************************************************************************
    251232*   Test callbacks                                                                                                               *
     
    257238static DECLCALLBACK(int) audioTestPlayToneSetup(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx)
    258239{
    259     RT_NOREF(pTstEnv, pTstDesc, ppvCtx);
     240    RT_NOREF(pTstDesc, ppvCtx);
     241
     242    int rc;
     243
     244    if (strlen(pTstEnv->szDev))
     245    {
     246        rc = audioTestDriverStackSetDevice(&pTstEnv->DrvStack, PDMAUDIODIR_OUT, pTstEnv->szDev);
     247        if (RT_FAILURE(rc))
     248            return rc;
     249    }
    260250
    261251    pTstParmsAcq->enmType     = AUDIOTESTTYPE_TESTTONE_PLAY;
    262 
    263     PDMAudioPropsInit(&pTstParmsAcq->Props, 16 /* bit */ / 8, true /* fSigned */, 2 /* Channels */, 44100 /* Hz */);
    264 
     252    pTstParmsAcq->Props       = pTstEnv->Props;
    265253    pTstParmsAcq->enmDir      = PDMAUDIODIR_OUT;
    266254#ifdef DEBUG
    267     pTstParmsAcq->cIterations = 2;
     255    pTstParmsAcq->cIterations = 1;
    268256#else
    269257    pTstParmsAcq->cIterations = RTRandU32Ex(1, 10);
     
    271259    pTstParmsAcq->idxCurrent  = 0;
    272260
    273     return VINF_SUCCESS;
     261    PAUDIOTESTTONEPARMS pToneParms = &pTstParmsAcq->TestTone;
     262
     263    pToneParms->Props          = pTstParmsAcq->Props;
     264    pToneParms->dbFreqHz       = AudioTestToneGetRandomFreq();
     265    pToneParms->msPrequel      = 0; /** @todo Implement analyzing this first! */
     266#ifdef DEBUG_andy
     267    pToneParms->msDuration     = 2000;
     268#else
     269    pToneParms->msDuration     = RTRandU32Ex(0, RT_MS_10SEC); /** @todo Probably a bit too long, but let's see. */
     270#endif
     271    pToneParms->msSequel       = 0;   /** @todo Implement analyzing this first! */
     272    pToneParms->uVolumePercent = 100; /** @todo Implement analyzing this first! */
     273
     274    return rc;
    274275}
    275276
     
    285286    for (uint32_t i = 0; i < pTstParms->cIterations; i++)
    286287    {
    287         AudioTestToneParamsInitRandom(&pTstParms->TestTone, &pTstParms->Props);
    288 
     288        /*
     289         * 1. Arm the (host) ValKit ATS with the recording parameters.
     290         */
    289291        PAUDIOTESTTONEPARMS const pToneParms = &pTstParms->TestTone;
    290292        rc = AudioTestSvcClientToneRecord(&pTstEnv->u.Host.AtsClValKit, pToneParms);
    291293        if (RT_SUCCESS(rc))
     294        {
     295            /*
     296             * 2. Tell the guest ATS to start playback.
     297             */
    292298            rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.AtsClGuest, pToneParms);
     299        }
    293300
    294301        if (RT_FAILURE(rc))
     
    314321static DECLCALLBACK(int) audioTestRecordToneSetup(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx)
    315322{
    316     RT_NOREF(pTstEnv, pTstDesc, ppvCtx);
     323    RT_NOREF(pTstDesc, ppvCtx);
     324
     325    int rc;
     326
     327    if (strlen(pTstEnv->szDev))
     328    {
     329        rc = audioTestDriverStackSetDevice(&pTstEnv->DrvStack, PDMAUDIODIR_IN, pTstEnv->szDev);
     330        if (RT_FAILURE(rc))
     331            return rc;
     332    }
    317333
    318334    pTstParmsAcq->enmType     = AUDIOTESTTYPE_TESTTONE_RECORD;
    319 
    320     PDMAudioPropsInit(&pTstParmsAcq->Props, 16 /* bit */ / 8, true /* fSigned */, 2 /* Channels */, 44100 /* Hz */);
    321 
     335    pTstParmsAcq->Props       = pTstEnv->Props;
    322336    pTstParmsAcq->enmDir      = PDMAUDIODIR_IN;
    323337#ifdef DEBUG
    324     pTstParmsAcq->cIterations = 2;
     338    pTstParmsAcq->cIterations = 1;
    325339#else
    326340    pTstParmsAcq->cIterations = RTRandU32Ex(1, 10);
     
    328342    pTstParmsAcq->idxCurrent  = 0;
    329343
    330     return VINF_SUCCESS;
     344    return rc;
    331345}
    332346
     
    349363#endif
    350364        /*
    351          * 1. Arm the ValKit ATS with the recording parameters.
     365         * 1. Arm the (host) ValKit ATS with the playback parameters.
    352366         */
    353367        rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.AtsClValKit, &pTstParms->TestTone);
     
    399413 * @param   pTstDesc            Test to run.
    400414 * @param   uSeq                Test sequence # in case there are more tests.
    401  * @param   pOverrideParms      Test parameters for overriding the actual test parameters. Optional.
    402  */
    403 static int audioTestOne(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc,
    404                         unsigned uSeq, PAUDIOTESTPARMS pOverrideParms)
     415 */
     416static int audioTestOne(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, unsigned uSeq)
    405417{
    406418    RT_NOREF(uSeq);
     
    431443    }
    432444
    433     audioTestCombineParms(&TstParms, pOverrideParms);
    434 
    435445    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test #%u: %RU32 iterations\n", uSeq, TstParms.cIterations);
    436 
    437     if (TstParms.Dev.pszName && strlen(TstParms.Dev.pszName)) /** @todo Refine this check. Use pszId for starters! */
    438         rc = audioTestDeviceOpen(&TstParms.Dev);
    439446
    440447    AssertPtr(pTstDesc->pfnExec);
     
    455462    }
    456463
    457     rc = audioTestDeviceClose(&TstParms.Dev);
    458 
    459464    audioTestParmsDestroy(&TstParms);
    460465
     
    467472 * @returns VBox status code.
    468473 * @param   pTstEnv             Test environment to use for running all tests.
    469  * @param   pOverrideParms      Test parameters for (some / all) specific test parameters. Optional.
    470  */
    471 int audioTestWorker(PAUDIOTESTENV pTstEnv, PAUDIOTESTPARMS pOverrideParms)
     474 */
     475int audioTestWorker(PAUDIOTESTENV pTstEnv)
    472476{
    473477    int rc = VINF_SUCCESS;
     
    501505            for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
    502506            {
    503                 int rc2 = audioTestOne(pTstEnv, &g_aTests[i], uSeq, pOverrideParms);
     507                int rc2 = audioTestOne(pTstEnv, &g_aTests[i], uSeq);
    504508                if (RT_SUCCESS(rc))
    505509                    rc = rc2;
     
    631635    RT_ZERO(TstEnv);
    632636
    633     AUDIOTESTPARMS TstCust;
    634     audioTestParmsInit(&TstCust);
    635 
    636637    const char *pszDevice     = NULL; /* Custom device to use. Can be NULL if not being used. */
    637638    const char *pszTag        = NULL; /* Custom tag to use. Can be NULL if not being used. */
     
    750751
    751752            case VKAT_TEST_OPT_VOL:
    752                 TstCust.TestTone.uVolumePercent = ValueUnion.u8;
     753                TstEnv.uVolumePercent = ValueUnion.u8;
    753754                break;
    754755
     
    766767
    767768    /* Initialize the custom test parameters with sensible defaults if nothing else is given. */
    768     PDMAudioPropsInit(&TstCust.TestTone.Props,
     769    PDMAudioPropsInit(&TstEnv.Props,
    769770                      cPcmSampleBit ? cPcmSampleBit / 8 : 2 /* 16-bit */, fPcmSigned, cPcmChannels ? cPcmChannels : 2,
    770771                      uPcmHz ? uPcmHz : 44100);
     
    784785                          pszGuestTcpAddr, uGuestTcpPort);
    785786    if (RT_SUCCESS(rc))
    786     {
    787         audioTestWorker(&TstEnv, &TstCust);
    788         audioTestEnvDestroy(&TstEnv);
    789     }
    790 
    791     audioTestParmsDestroy(&TstCust);
     787        rc = audioTestWorker(&TstEnv);
     788
     789    audioTestEnvDestroy(&TstEnv);
    792790
    793791    if (RT_FAILURE(rc)) /* Let us know that something went wrong in case we forgot to mention it. */
  • trunk/src/VBox/ValidationKit/utils/audio/vkatCmdSelfTest.cpp

    r89834 r89890  
    5656    PSELFTESTCTX pCtx = (PSELFTESTCTX)pvUser;
    5757
    58     AUDIOTESTPARMS TstCust;
    59     audioTestParmsInit(&TstCust);
    60 
    61     PAUDIOTESTENV pTstEnv = &pCtx->Guest.TstEnv;
     58    PAUDIOTESTENV pTstEnvGst = &pCtx->Guest.TstEnv;
    6259
    6360    /* Flag the environment for self test mode. */
    64     pTstEnv->fSelftest = true;
     61    pTstEnvGst->fSelftest = true;
    6562
    6663    /* Generate tag for guest side. */
    67     int rc = RTStrCopy(pTstEnv->szTag, sizeof(pTstEnv->szTag), pCtx->szTag);
     64    int rc = RTStrCopy(pTstEnvGst->szTag, sizeof(pTstEnvGst->szTag), pCtx->szTag);
    6865    AssertRCReturn(rc, rc);
    6966
    70     rc = AudioTestPathCreateTemp(pTstEnv->szPathTemp, sizeof(pTstEnv->szPathTemp), "selftest-guest");
     67    rc = AudioTestPathCreateTemp(pTstEnvGst->szPathTemp, sizeof(pTstEnvGst->szPathTemp), "selftest-guest");
    7168    AssertRCReturn(rc, rc);
    7269
    73     rc = AudioTestPathCreateTemp(pTstEnv->szPathOut, sizeof(pTstEnv->szPathOut), "selftest-out");
     70    rc = AudioTestPathCreateTemp(pTstEnvGst->szPathOut, sizeof(pTstEnvGst->szPathOut), "selftest-out");
    7471    AssertRCReturn(rc, rc);
    7572
    76     pTstEnv->enmMode = AUDIOTESTMODE_GUEST;
     73    pTstEnvGst->enmMode = AUDIOTESTMODE_GUEST;
    7774
    7875    /** @todo Make this customizable. */
    79     PDMAudioPropsInit(&TstCust.TestTone.Props,
     76    PDMAudioPropsInit(&pTstEnvGst->Props,
    8077                      2 /* 16-bit */, true  /* fSigned */, 2 /* cChannels */, 44100 /* uHz */);
    8178
    82     rc = audioTestEnvInit(pTstEnv, pTstEnv->DrvStack.pDrvReg, pCtx->fWithDrvAudio,
     79    rc = audioTestEnvInit(pTstEnvGst, pTstEnvGst->DrvStack.pDrvReg, pCtx->fWithDrvAudio,
    8380                          pCtx->Host.szValKitAtsAddr, pCtx->Host.uValKitAtsPort,
    8481                          pCtx->Guest.szAtsAddr, pCtx->Guest.uAtsPort);
     
    8784        RTThreadUserSignal(hThread);
    8885
    89         audioTestWorker(pTstEnv, &TstCust);
    90         audioTestEnvDestroy(pTstEnv);
    91     }
    92 
    93     audioTestParmsDestroy(&TstCust);
     86        audioTestWorker(pTstEnvGst);
     87        audioTestEnvDestroy(pTstEnvGst);
     88    }
    9489
    9590    return rc;
     
    118113     */
    119114
    120     AUDIOTESTPARMS TstCust;
    121     audioTestParmsInit(&TstCust);
    122 
    123115    /* Generate a common tag for guest and host side. */
    124116    int rc = AudioTestGenTag(pCtx->szTag, sizeof(pCtx->szTag));
    125117    AssertRCReturn(rc, RTEXITCODE_FAILURE);
    126118
    127     PAUDIOTESTENV pTstEnv = &pCtx->Host.TstEnv;
     119    PAUDIOTESTENV pTstEnvHst = &pCtx->Host.TstEnv;
    128120
    129121    /* Flag the environment for self test mode. */
    130     pTstEnv->fSelftest = true;
     122    pTstEnvHst->fSelftest = true;
    131123
    132124    /* Generate tag for host side. */
    133     rc = RTStrCopy(pTstEnv->szTag, sizeof(pTstEnv->szTag), pCtx->szTag);
     125    rc = RTStrCopy(pTstEnvHst->szTag, sizeof(pTstEnvHst->szTag), pCtx->szTag);
    134126    AssertRCReturn(rc, RTEXITCODE_FAILURE);
    135127
    136     rc = AudioTestPathCreateTemp(pTstEnv->szPathTemp, sizeof(pTstEnv->szPathTemp), "selftest-tmp");
     128    rc = AudioTestPathCreateTemp(pTstEnvHst->szPathTemp, sizeof(pTstEnvHst->szPathTemp), "selftest-tmp");
    137129    AssertRCReturn(rc, RTEXITCODE_FAILURE);
    138130
    139     rc = AudioTestPathCreateTemp(pTstEnv->szPathOut, sizeof(pTstEnv->szPathOut), "selftest-out");
     131    rc = AudioTestPathCreateTemp(pTstEnvHst->szPathOut, sizeof(pTstEnvHst->szPathOut), "selftest-out");
    140132    AssertRCReturn(rc, RTEXITCODE_FAILURE);
     133
     134    /* Initialize the PCM properties to some sane values. */
     135    PDMAudioPropsInit(&pTstEnvHst->Props,
     136                      2 /* 16-bit */, true /* fPcmSigned */, 2 /* cPcmChannels */, 44100 /* uPcmHz */);
    141137
    142138    /*
     
    161157         * Steps 2 + 3.
    162158         */
    163         pTstEnv->enmMode = AUDIOTESTMODE_HOST;
    164 
    165         rc = audioTestEnvInit(pTstEnv, &g_DrvHostValidationKitAudio, true /* fWithDrvAudio */,
     159        pTstEnvHst->enmMode = AUDIOTESTMODE_HOST;
     160
     161        rc = audioTestEnvInit(pTstEnvHst, &g_DrvHostValidationKitAudio, true /* fWithDrvAudio */,
    166162                              pCtx->Host.szValKitAtsAddr, pCtx->Host.uValKitAtsPort,
    167163                              pCtx->Host.szGuestAtsAddr, pCtx->Host.uGuestAtsPort);
    168164        if (RT_SUCCESS(rc))
    169165        {
    170             rc = audioTestWorker(pTstEnv, &TstCust);
     166            rc = audioTestWorker(pTstEnvHst);
    171167            if (RT_SUCCESS(rc))
    172168            {
     
    174170            }
    175171
    176             audioTestEnvDestroy(pTstEnv);
     172            audioTestEnvDestroy(pTstEnvHst);
    177173        }
    178174    }
    179 
    180     audioTestParmsDestroy(&TstCust);
    181175
    182176    /*
  • trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp

    r89837 r89890  
    6868*   Internal Functions                                                                                                           *
    6969*********************************************************************************************************************************/
    70 static int audioTestCreateStreamDefaultIn(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PPDMAUDIOPCMPROPS pProps);
    71 static int audioTestCreateStreamDefaultOut(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PPDMAUDIOPCMPROPS pProps);
     70static int audioTestStreamInit(PAUDIOTESTDRVSTACK pDrvStack, PAUDIOTESTSTREAM pStream, PDMAUDIODIR enmDir, PCPDMAUDIOPCMPROPS pProps, bool fWithMixer, uint32_t cMsBufferSize, uint32_t cMsPreBuffer, uint32_t cMsSchedulingHint);
    7271static int audioTestStreamDestroy(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream);
    7372static int audioTestDevicesEnumerateAndCheck(PAUDIOTESTENV pTstEnv, const char *pszDev, PPDMAUDIOHOSTDEV *ppDev);
     
    144143}
    145144
    146 /**
    147  * Opens an audio device.
    148  *
    149  * @returns VBox status code.
    150  * @param   pDev                Audio device to open.
    151  */
    152 int audioTestDeviceOpen(PPDMAUDIOHOSTDEV pDev)
    153 {
    154     int rc = VINF_SUCCESS;
    155 
    156     RTTestSubF(g_hTest, "Opening audio device '%s' ...", pDev->pszName);
    157 
    158     /** @todo Detect + open device here. */
    159 
    160     RTTestSubDone(g_hTest);
    161 
    162     return rc;
    163 }
    164 
    165 /**
    166  * Closes an audio device.
    167  *
    168  * @returns VBox status code.
    169  * @param   pDev                Audio device to close.
    170  */
    171 int audioTestDeviceClose(PPDMAUDIOHOSTDEV pDev)
    172 {
    173     int rc = VINF_SUCCESS;
    174 
    175     RTTestSubF(g_hTest, "Closing audio device '%s' ...", pDev->pszName);
    176 
    177     /** @todo Close device here. */
    178 
    179     RTTestSubDone(g_hTest);
     145static int audioTestStreamInit(PAUDIOTESTDRVSTACK pDrvStack, PAUDIOTESTSTREAM pStream,
     146                               PDMAUDIODIR enmDir, PCPDMAUDIOPCMPROPS pProps, bool fWithMixer,
     147                               uint32_t cMsBufferSize, uint32_t cMsPreBuffer, uint32_t cMsSchedulingHint)
     148{
     149    int rc;
     150
     151    if (enmDir == PDMAUDIODIR_IN)
     152        rc = audioTestDriverStackStreamCreateInput(pDrvStack, pProps, cMsBufferSize,
     153                                                   cMsPreBuffer, cMsSchedulingHint, &pStream->pStream, &pStream->Cfg);
     154    else if (enmDir == PDMAUDIODIR_OUT)
     155        rc = audioTestDriverStackStreamCreateOutput(pDrvStack, pProps, cMsBufferSize,
     156                                                    cMsPreBuffer, cMsSchedulingHint, &pStream->pStream, &pStream->Cfg);
     157    else
     158        rc = VERR_NOT_SUPPORTED;
     159
     160    if (RT_SUCCESS(rc))
     161    {
     162        if (!pDrvStack->pIAudioConnector)
     163        {
     164            pStream->pBackend = &((PAUDIOTESTDRVSTACKSTREAM)pStream->pStream)->Backend;
     165        }
     166        else
     167            pStream->pBackend = NULL;
     168
     169        /*
     170         * Automatically enable the mixer if the PCM properties don't match.
     171         */
     172        if (   !fWithMixer
     173            && !PDMAudioPropsAreEqual(pProps, &pStream->Cfg.Props))
     174        {
     175            RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS,  "Enabling stream mixer\n");
     176            fWithMixer = true;
     177        }
     178
     179        rc = AudioTestMixStreamInit(&pStream->Mix, pDrvStack, pStream->pStream,
     180                                    fWithMixer ? pProps : NULL, 100 /* ms */); /** @todo Configure mixer buffer? */
     181    }
     182
     183    if (RT_FAILURE(rc))
     184        RTTestFailed(g_hTest, "Initializing %s stream failed with %Rrc", enmDir == PDMAUDIODIR_IN ? "input" : "output", rc);
    180185
    181186    return rc;
     
    201206    }
    202207
    203     return rc;
    204 }
    205 
    206 /**
    207  * Creates an audio default input (recording) test stream.
    208  * Convenience function.
    209  *
    210  * @returns VBox status code.
    211  * @param   pTstEnv             Test environment to use for creating the stream.
    212  * @param   pStream             Audio stream to create.
    213  * @param   pProps              PCM properties to use for creation.
    214  */
    215 static int audioTestCreateStreamDefaultIn(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PPDMAUDIOPCMPROPS pProps)
    216 {
    217     pStream->pBackend = NULL;
    218     int rc = audioTestDriverStackStreamCreateInput(&pTstEnv->DrvStack, pProps, pTstEnv->cMsBufferSize, pTstEnv->cMsPreBuffer,
    219                                                    pTstEnv->cMsSchedulingHint, &pStream->pStream, &pStream->Cfg);
    220     if (RT_SUCCESS(rc) && !pTstEnv->DrvStack.pIAudioConnector)
    221         pStream->pBackend = &((PAUDIOTESTDRVSTACKSTREAM)pStream->pStream)->Backend;
    222     return rc;
    223 }
    224 
    225 /**
    226  * Creates an audio default output (playback) test stream.
    227  * Convenience function.
    228  *
    229  * @returns VBox status code.
    230  * @param   pTstEnv             Test environment to use for creating the stream.
    231  * @param   pStream             Audio stream to create.
    232  * @param   pProps              PCM properties to use for creation.
    233  */
    234 static int audioTestCreateStreamDefaultOut(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PPDMAUDIOPCMPROPS pProps)
    235 {
    236     pStream->pBackend = NULL;
    237     int rc = audioTestDriverStackStreamCreateOutput(&pTstEnv->DrvStack, pProps, pTstEnv->cMsBufferSize, pTstEnv->cMsPreBuffer,
    238                                                     pTstEnv->cMsSchedulingHint, &pStream->pStream, &pStream->Cfg);
    239     if (RT_SUCCESS(rc) && !pTstEnv->DrvStack.pIAudioConnector)
    240         pStream->pBackend = &((PAUDIOTESTDRVSTACKSTREAM)pStream->pStream)->Backend;
     208    AudioTestMixStreamTerm(&pStream->Mix);
     209
    241210    return rc;
    242211}
     
    246215*   Test Primitives                                                                                                              *
    247216*********************************************************************************************************************************/
     217
     218/**
     219 * Returns a random scheduling hint (in ms).
     220 */
     221DECLINLINE(uint32_t) audioTestEnvGetRandomSchedulingHint(void)
     222{
     223    static const unsigned s_aSchedulingHintsMs[] =
     224    {
     225        10,
     226        25,
     227        50,
     228        100,
     229        200,
     230        250
     231    };
     232
     233    return s_aSchedulingHintsMs[RTRandU32Ex(0, RT_ELEMENTS(s_aSchedulingHintsMs) - 1)];
     234}
    248235
    249236/**
     
    260247{
    261248    AUDIOTESTTONE TstTone;
    262     AudioTestToneInit(&TstTone, &pParms->Props, pParms->dbFreqHz);
     249    AudioTestToneInit(&TstTone, &pStream->Cfg.Props, pParms->dbFreqHz);
    263250
    264251    const char *pcszPathOut = pTstEnv->Set.szPathAbs;
    265252
    266253    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing test tone (tone frequency is %RU16Hz, %RU32ms)\n", (uint16_t)pParms->dbFreqHz, pParms->msDuration);
    267     RTTestPrintf(g_hTest, RTTESTLVL_DEBUG,  "Writing to '%s'\n", pcszPathOut);
     254    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using %RU32ms stream scheduling hint\n", pStream->Cfg.Device.cMsSchedulingHint);
     255    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Writing to '%s'\n", pcszPathOut);
    268256
    269257    /** @todo Use .WAV here? */
     
    272260    AssertRCReturn(rc, rc);
    273261
     262    rc = AudioTestMixStreamEnable(&pStream->Mix);
     263    if (   RT_SUCCESS(rc)
     264        && AudioTestMixStreamIsOkay(&pStream->Mix))
     265    {
     266        uint8_t  abBuf[_4K];
     267
     268        uint32_t cbToPlayTotal  = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, pParms->msDuration);
     269        AssertStmt(cbToPlayTotal, rc = VERR_INVALID_PARAMETER);
     270
     271        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Playing %RU32 bytes total\n", cbToPlayTotal);
     272
     273        AudioTestSetObjAddMetadataStr(pObj, "stream_to_play_bytes=%RU32\n",      cbToPlayTotal);
     274        AudioTestSetObjAddMetadataStr(pObj, "stream_period_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPeriod);
     275        AudioTestSetObjAddMetadataStr(pObj, "stream_buffer_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesBufferSize);
     276        AudioTestSetObjAddMetadataStr(pObj, "stream_prebuf_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPreBuffering);
     277        /* Note: This mostly is provided by backend (e.g. PulseAudio / ALSA / ++) and
     278         *       has nothing to do with the device emulation scheduling hint. */
     279        AudioTestSetObjAddMetadataStr(pObj, "device_scheduling_hint_ms=%RU32\n", pStream->Cfg.Device.cMsSchedulingHint);
     280
     281        while (cbToPlayTotal)
     282        {
     283            uint32_t       cbPlayed   = 0;
     284            uint32_t const cbCanWrite = AudioTestMixStreamGetWritable(&pStream->Mix);
     285            if (cbCanWrite)
     286            {
     287                uint32_t const cbToGenerate = RT_MIN(RT_MIN(cbToPlayTotal, sizeof(abBuf)), cbCanWrite);
     288                uint32_t       cbToPlay;
     289                rc = AudioTestToneGenerate(&TstTone, abBuf, cbToGenerate, &cbToPlay);
     290                if (RT_SUCCESS(rc))
     291                {
     292                    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Playing %RU32 bytes ...\n", cbToPlay);
     293
     294                    /* Write stuff to disk before trying to play it. Help analysis later. */
     295                    rc = AudioTestSetObjWrite(pObj, abBuf, cbToPlay);
     296                    if (RT_SUCCESS(rc))
     297                        rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed);
     298                }
     299
     300                if (RT_FAILURE(rc))
     301                    break;
     302            }
     303            else if (AudioTestMixStreamIsOkay(&pStream->Mix))
     304                RTThreadSleep(RT_MIN(RT_MAX(1, pStream->Cfg.Device.cMsSchedulingHint), 256));
     305            else
     306                AssertFailedBreakStmt(rc = VERR_AUDIO_STREAM_NOT_READY);
     307
     308            Assert(cbToPlayTotal >= cbPlayed);
     309            cbToPlayTotal -= cbPlayed;
     310        }
     311
     312        if (cbToPlayTotal != 0)
     313            RTTestFailed(g_hTest, "Playback ended unexpectedly (%RU32 bytes left)\n", cbToPlayTotal);
     314    }
     315    else
     316        rc = VERR_AUDIO_STREAM_NOT_READY;
     317
     318    int rc2 = AudioTestSetObjClose(pObj);
     319    if (RT_SUCCESS(rc))
     320        rc = rc2;
     321
     322    if (RT_FAILURE(rc))
     323        RTTestFailed(g_hTest, "Playing tone failed with %Rrc\n", rc);
     324
     325    return rc;
     326}
     327
     328/**
     329 * Records a test tone from a specific audio test stream.
     330 *
     331 * @returns VBox status code.
     332 * @param   pTstEnv             Test environment to use for running the test.
     333 * @param   pStream             Stream to use for recording the tone.
     334 * @param   pParms              Tone parameters to use.
     335 *
     336 * @note    Blocking function.
     337 */
     338static int audioTestRecordTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)
     339{
     340    const char *pcszPathOut = pTstEnv->Set.szPathAbs;
     341
     342    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Recording test tone (for %RU32ms)\n", pParms->msDuration);
     343    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG,  "Writing to '%s'\n", pcszPathOut);
     344
     345    /** @todo Use .WAV here? */
     346    PAUDIOTESTOBJ pObj;
     347    int rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "guest-tone-rec.pcm", &pObj);
     348    AssertRCReturn(rc, rc);
     349
    274350    if (audioTestDriverStackStreamIsOkay(&pTstEnv->DrvStack, pStream->pStream))
    275351    {
    276         uint32_t cbBuf;
    277         uint8_t  abBuf[_4K];
    278 
    279352        const uint32_t cbPerSched = PDMAudioPropsMilliToBytes(&pParms->Props, pTstEnv->cMsSchedulingHint);
    280353        AssertStmt(cbPerSched, rc = VERR_INVALID_PARAMETER);
    281               uint32_t cbToWrite  = PDMAudioPropsMilliToBytes(&pParms->Props, pParms->msDuration);
    282         AssertStmt(cbToWrite,  rc = VERR_INVALID_PARAMETER);
     354              uint32_t cbToRead   = PDMAudioPropsMilliToBytes(&pParms->Props, pParms->msDuration);
     355        AssertStmt(cbToRead,   rc = VERR_INVALID_PARAMETER);
    283356
    284357        if (RT_SUCCESS(rc))
     
    288361            AudioTestSetObjAddMetadataStr(pObj, "scheduling_hint_ms=%RU32\n", pTstEnv->cMsSchedulingHint);
    289362
    290             while (cbToWrite)
    291             {
    292                 uint32_t cbWritten    = 0;
    293                 uint32_t cbToGenerate = RT_MIN(cbToWrite, RT_MIN(cbPerSched, sizeof(abBuf)));
    294                 Assert(cbToGenerate);
    295 
    296                 rc = AudioTestToneGenerate(&TstTone, abBuf, cbToGenerate, &cbBuf);
    297                 if (RT_SUCCESS(rc))
    298                 {
    299                     /* Write stuff to disk before trying to play it. Help analysis later. */
    300                     rc = AudioTestSetObjWrite(pObj, abBuf, cbBuf);
    301                     if (RT_SUCCESS(rc))
    302                         rc = audioTestDriverStackStreamPlay(&pTstEnv->DrvStack, pStream->pStream,
    303                                                             abBuf, cbBuf, &cbWritten);
    304                 }
    305 
    306                 if (RT_FAILURE(rc))
    307                     break;
    308 
    309                 RTThreadSleep(pTstEnv->cMsSchedulingHint);
    310 
    311                 Assert(cbToWrite >= cbWritten);
    312                 cbToWrite -= cbWritten;
    313             }
    314         }
    315     }
    316     else
    317         rc = VERR_AUDIO_STREAM_NOT_READY;
    318 
    319     int rc2 = AudioTestSetObjClose(pObj);
    320     if (RT_SUCCESS(rc))
    321         rc = rc2;
    322 
    323     if (RT_FAILURE(rc))
    324         RTTestFailed(g_hTest, "Playing tone done failed with %Rrc\n", rc);
    325 
    326     return rc;
    327 }
    328 
    329 /**
    330  * Records a test tone from a specific audio test stream.
    331  *
    332  * @returns VBox status code.
    333  * @param   pTstEnv             Test environment to use for running the test.
    334  * @param   pStream             Stream to use for recording the tone.
    335  * @param   pParms              Tone parameters to use.
    336  *
    337  * @note    Blocking function.
    338  */
    339 static int audioTestRecordTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)
    340 {
    341     const char *pcszPathOut = pTstEnv->Set.szPathAbs;
    342 
    343     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Recording test tone (for %RU32ms)\n", pParms->msDuration);
    344     RTTestPrintf(g_hTest, RTTESTLVL_DEBUG,  "Writing to '%s'\n", pcszPathOut);
    345 
    346     /** @todo Use .WAV here? */
    347     PAUDIOTESTOBJ pObj;
    348     int rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "guest-tone-rec.pcm", &pObj);
    349     AssertRCReturn(rc, rc);
    350 
    351     if (audioTestDriverStackStreamIsOkay(&pTstEnv->DrvStack, pStream->pStream))
    352     {
    353         const uint32_t cbPerSched = PDMAudioPropsMilliToBytes(&pParms->Props, pTstEnv->cMsSchedulingHint);
    354         AssertStmt(cbPerSched, rc = VERR_INVALID_PARAMETER);
    355               uint32_t cbToRead   = PDMAudioPropsMilliToBytes(&pParms->Props, pParms->msDuration);
    356         AssertStmt(cbToRead,   rc = VERR_INVALID_PARAMETER);
    357 
    358         if (RT_SUCCESS(rc))
    359         {
    360             AudioTestSetObjAddMetadataStr(pObj, "buffer_size_ms=%RU32\n", pTstEnv->cMsBufferSize);
    361             AudioTestSetObjAddMetadataStr(pObj, "prebuf_size_ms=%RU32\n", pTstEnv->cMsPreBuffer);
    362             AudioTestSetObjAddMetadataStr(pObj, "scheduling_hint_ms=%RU32\n", pTstEnv->cMsSchedulingHint);
    363 
    364363            uint8_t abBuf[_4K];
    365364
     
    444443    const PAUDIOTESTSTREAM pTstStream = &pTstEnv->aStreams[0]; /** @todo Make this dynamic. */
    445444
    446     int rc = audioTestCreateStreamDefaultOut(pTstEnv, pTstStream, &pToneParms->Props);
     445    int rc = audioTestStreamInit(&pTstEnv->DrvStack, pTstStream, PDMAUDIODIR_OUT, &pTstEnv->Props, false /* fWithMixer */,
     446                                 pTstEnv->cMsBufferSize, pTstEnv->cMsPreBuffer, pTstEnv->cMsSchedulingHint);
    447447    if (RT_SUCCESS(rc))
    448448    {
     
    484484    const PAUDIOTESTSTREAM pTstStream = &pTstEnv->aStreams[0]; /** @todo Make this dynamic. */
    485485
    486     int rc = audioTestCreateStreamDefaultIn(pTstEnv, pTstStream, &pToneParms->Props);
     486    int rc = audioTestStreamInit(&pTstEnv->DrvStack, pTstStream, PDMAUDIODIR_IN, &pTstEnv->Props, false /* fWithMixer */,
     487                                 pTstEnv->cMsBufferSize, pTstEnv->cMsPreBuffer, pTstEnv->cMsSchedulingHint);
    487488    if (RT_SUCCESS(rc))
    488489    {
     
    666667    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Temp directory is '%s'\n", pTstEnv->szPathTemp);
    667668
     669    if (!pTstEnv->cMsBufferSize)
     670        pTstEnv->cMsBufferSize     = UINT32_MAX;
     671    if (!pTstEnv->cMsPreBuffer)
     672        pTstEnv->cMsPreBuffer      = UINT32_MAX;
     673    if (!pTstEnv->cMsSchedulingHint)
     674        pTstEnv->cMsSchedulingHint = UINT32_MAX;
     675
    668676    PDMAudioHostEnumInit(&pTstEnv->DevEnum);
    669 
    670     pTstEnv->cMsBufferSize     = 300; /* ms */ /** @todo Randomize this also? */
    671     pTstEnv->cMsPreBuffer      = 150; /* ms */ /** @todo Ditto. */
    672     pTstEnv->cMsSchedulingHint = RTRandU32Ex(10, 80); /* Choose a random scheduling (in ms). */
    673677
    674678    bool fUseDriverStack = false; /* Whether to init + use the audio driver stack or not. */
     
    691695
    692696        PPDMAUDIOHOSTDEV pDev;
    693         rc = audioTestDevicesEnumerateAndCheck(pTstEnv, NULL /* pszDevice */, &pDev); /** @todo Implement device checking. */
     697        rc = audioTestDevicesEnumerateAndCheck(pTstEnv, pTstEnv->szDev, &pDev);
    694698        if (RT_FAILURE(rc))
    695699            return rc;
  • trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h

    r89837 r89890  
    165165    /** The stream config. */
    166166    PDMAUDIOSTREAMCFG       Cfg;
     167    /** Associated mixing stream. Optional. */
     168    AUDIOTESTDRVMIXSTREAM   Mix;
    167169} AUDIOTESTSTREAM;
    168170/** Pointer to audio test stream. */
     
    184186    /** Whether skip the actual verification or not. */
    185187    bool                    fSkipVerify;
     188    /** The PCM properties to use. */
     189    PDMAUDIOPCMPROPS        Props;
     190    /** Name of the audio device to use.
     191     *  If empty the default audio device will be used. */
     192    char                    szDev[128];
     193    /** Audio volume to use (in percent).
     194     *  Might not be available on all systems. */
     195    uint8_t                 uVolumePercent;
    186196    /** Output path for storing the test environment's final test files. */
    187197    char                    szTag[AUDIOTEST_TAG_MAX];
     
    427437/** @}  */
    428438
    429 int         audioTestWorker(PAUDIOTESTENV pTstEnv, PAUDIOTESTPARMS pOverrideParms);
     439int         audioTestWorker(PAUDIOTESTENV pTstEnv);
    430440
    431441/** @name Command handlers
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