VirtualBox

Changeset 89140 in vbox


Ignore:
Timestamp:
May 18, 2021 2:04:24 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144481
Message:

Audio/ValKit: Initial implementation of testing recording audio via VKAT / AudioTest. bugref:10008

File:
1 edited

Legend:

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

    r89139 r89140  
    14661466
    14671467/**
    1468  * Creates an audio default output test stream.
     1468 * Creates an audio default input (recording) test stream.
     1469 * Convenience function.
     1470 *
     1471 * @returns VBox status code.
     1472 * @param   pTstEnv             Test environment to use for creating the stream.
     1473 * @param   pStream             Audio stream to create.
     1474 * @param   pProps              PCM properties to use for creation.
     1475 */
     1476static int audioTestCreateStreamDefaultIn(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PPDMAUDIOPCMPROPS pProps)
     1477{
     1478    PDMAUDIOSTREAMCFG Cfg;
     1479    int rc = PDMAudioStrmCfgInitWithProps(&Cfg, pProps);
     1480    AssertRC(rc); /* Cannot fail. */
     1481
     1482    Cfg.enmDir      = PDMAUDIODIR_IN;
     1483    Cfg.u.enmSrc    = PDMAUDIORECSRC_LINE; /* Note: HDA does not have a separate Mic-In enabled yet, so got for Line-In here. */
     1484    Cfg.enmLayout   = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
     1485
     1486    Cfg.Backend.cFramesBufferSize   = PDMAudioPropsMilliToFrames(pProps, 300);
     1487    Cfg.Backend.cFramesPreBuffering = PDMAudioPropsMilliToFrames(pProps, 200);
     1488    Cfg.Backend.cFramesPeriod       = PDMAudioPropsMilliToFrames(pProps, 10);
     1489    Cfg.Device.cMsSchedulingHint    = 10;
     1490
     1491    return audioTestStreamCreate(pTstEnv, pStream, &Cfg);
     1492}
     1493
     1494/**
     1495 * Records a test tone from a specific audio test stream.
     1496 *
     1497 * @returns VBox status code.
     1498 * @param   pTstEnv             Test environment to use for running the test.
     1499 * @param   pStream             Stream to use for recording the tone.
     1500 * @param   pParms              Tone parameters to use.
     1501 *
     1502 * @note    Blocking function.
     1503 */
     1504static int audioTestRecordTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)
     1505{
     1506    const char *pcszPathOut = pTstEnv->Set.szPathAbs;
     1507
     1508    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Recording test tone (for %RU32ms)\n", pParms->msDuration);
     1509    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG,  "Writing to '%s'\n", pcszPathOut);
     1510
     1511    /** @todo Use .WAV here? */
     1512    PAUDIOTESTOBJ pObj;
     1513    int rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "tone.pcm", &pObj);
     1514    AssertRCReturn(rc, rc);
     1515
     1516    PDMHOSTAUDIOSTREAMSTATE enmState = pTstEnv->DrvStack.pIHostAudio->pfnStreamGetState(pTstEnv->DrvStack.pIHostAudio, &pStream->Backend);
     1517    if (enmState == PDMHOSTAUDIOSTREAMSTATE_OKAY)
     1518    {
     1519        uint8_t  abBuf[_4K];
     1520
     1521        const uint64_t tsStartMs     = RTTimeMilliTS();
     1522        const uint16_t cSchedulingMs = RTRandU32Ex(10, 80); /* Chose a random scheduling (in ms). */
     1523
     1524        do
     1525        {
     1526            uint32_t cbRead = 0;
     1527            rc = pTstEnv->DrvStack.pIHostAudio->pfnStreamCapture(pTstEnv->DrvStack.pIHostAudio, &pStream->Backend, abBuf, sizeof(abBuf), &cbRead);
     1528            if (RT_SUCCESS(rc))
     1529                rc = AudioTestSetObjWrite(pObj, abBuf, cbRead);
     1530
     1531            if (RT_FAILURE(rc))
     1532                break;
     1533
     1534            if (RTTimeMilliTS() - tsStartMs >= pParms->msDuration)
     1535                break;
     1536
     1537            RTThreadSleep(cSchedulingMs);
     1538
     1539        } while (RT_SUCCESS(rc));
     1540    }
     1541    else
     1542        rc = VERR_AUDIO_STREAM_NOT_READY;
     1543
     1544    int rc2 = AudioTestSetObjClose(pObj);
     1545    if (RT_SUCCESS(rc))
     1546        rc = rc2;
     1547
     1548    return rc;
     1549}
     1550
     1551/**
     1552 * Creates an audio default output (playback) test stream.
    14691553 * Convenience function.
    14701554 *
     
    16571741}
    16581742
     1743/**
     1744 * @copydoc FNAUDIOTESTSETUP
     1745 */
     1746static DECLCALLBACK(int) audioTestRecordToneSetup(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx)
     1747{
     1748    RT_NOREF(pTstEnv, pTstDesc, ppvCtx);
     1749
     1750    pTstParmsAcq->enmType     = AUDIOTESTTYPE_TESTTONE;
     1751
     1752    PDMAudioPropsInit(&pTstParmsAcq->TestTone.Props, 16 /* bit */ / 8, true /* fSigned */, 2 /* Channels */, 44100 /* Hz */);
     1753
     1754    pTstParmsAcq->enmDir      = PDMAUDIODIR_IN;
     1755    pTstParmsAcq->cIterations = RTRandU32Ex(1, 10);
     1756    pTstParmsAcq->idxCurrent  = 0;
     1757
     1758    return VINF_SUCCESS;
     1759}
     1760
     1761/**
     1762 * @copydoc FNAUDIOTESTEXEC
     1763 */
     1764static DECLCALLBACK(int) audioTestRecordToneExec(PAUDIOTESTENV pTstEnv, void *pvCtx, PAUDIOTESTPARMS pTstParms)
     1765{
     1766    RT_NOREF(pvCtx);
     1767
     1768    int rc = VINF_SUCCESS;
     1769
     1770    PAUDIOTESTSTREAM pStream = &pTstEnv->aStreams[0];
     1771
     1772    for (uint32_t i = 0; i < pTstParms->cIterations; i++)
     1773    {
     1774        PAUDIOTESTENTRY pTst;
     1775        rc = AudioTestSetTestBegin(&pTstEnv->Set, "Recording test tone", pTstParms, &pTst);
     1776        if (RT_SUCCESS(rc))
     1777        {
     1778            /** @todo  For now we're (re-)creating the recording stream for each iteration. Change that to be random. */
     1779            rc = audioTestCreateStreamDefaultIn(pTstEnv, pStream, &pTstParms->TestTone.Props);
     1780            if (RT_SUCCESS(rc))
     1781            {
     1782                pTstParms->TestTone.msDuration = RTRandU32Ex(50 /* ms */, RT_MS_10SEC); /** @todo Record even longer? */
     1783
     1784                rc = audioTestRecordTone(pTstEnv, pStream, &pTstParms->TestTone);
     1785            }
     1786
     1787            int rc2 = audioTestStreamDestroy(pTstEnv, pStream);
     1788            if (RT_SUCCESS(rc))
     1789                rc = rc2;
     1790
     1791            if (RT_SUCCESS(rc))
     1792            {
     1793               AudioTestSetTestDone(pTst);
     1794            }
     1795            else
     1796                AudioTestSetTestFailed(pTst, rc, "Recording test tone failed");
     1797        }
     1798
     1799        if (RT_FAILURE(rc))
     1800            RTTestFailed(g_hTest, "Recording tone failed\n");
     1801    }
     1802
     1803    return rc;
     1804}
     1805
     1806/**
     1807 * @copydoc FNAUDIOTESTDESTROY
     1808 */
     1809static DECLCALLBACK(int) audioTestRecordToneDestroy(PAUDIOTESTENV pTstEnv, void *pvCtx)
     1810{
     1811    RT_NOREF(pTstEnv, pvCtx);
     1812
     1813    return VINF_SUCCESS;
     1814}
    16591815
    16601816/*********************************************************************************************************************************
     
    16651821{
    16661822    /* pszTest      fExcluded      pfnSetup */
    1667     { "PlayTone",   false,         audioTestPlayToneSetup,       audioTestPlayToneExec,      audioTestPlayToneDestroy }
     1823    { "PlayTone",   false,         audioTestPlayToneSetup,       audioTestPlayToneExec,      audioTestPlayToneDestroy },
     1824    { "RecordTone", false,         audioTestRecordToneSetup,     audioTestRecordToneExec,    audioTestRecordToneDestroy }
    16681825};
    16691826
Note: See TracChangeset for help on using the changeset viewer.

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