VirtualBox

Ignore:
Timestamp:
Apr 9, 2021 12:55:19 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143685
Message:

Audio: Eliminated the DrvAudio mixing buffers for output streams on devices without their own mixer. Changed the prebuffering to not default to the whole backend buffer size, but only 2/3 of it, so that there is room for a bit of incoming data from the device once we start playing. We don't want to have that gather in the device mixer or internal DMA buffers. This code needs some more testing and work, only tested on linux against ALSA. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r88356 r88433  
    548548
    549549
     550static void tstNewPeek(RTTEST hTest, uint32_t uFromHz, uint32_t uToHz)
     551{
     552    RTTestSubF(hTest, "New peek %u to %u Hz (S16)", uFromHz, uToHz);
     553
     554    struct { int16_t l, r; }
     555        aSrcFrames[4096],
     556        aDstFrames[4096];
     557
     558    /* Mix buffer is uFromHz 2ch S16 */
     559    uint32_t const         cFrames = RTRandU32Ex(16, RT_ELEMENTS(aSrcFrames));
     560    PDMAUDIOPCMPROPS const CfgSrc  = PDMAUDIOPCMPROPS_INITIALIZER(2 /*cbSample*/, true /*fSigned*/, 2 /*ch*/, uFromHz, false /*fSwap*/);
     561    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgSrc));
     562    AUDIOMIXBUF MixBuf;
     563    RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&MixBuf, "NewPeekMixBuf", &CfgSrc, cFrames));
     564
     565    /* Peek state (destination) is uToHz 2ch S16 */
     566    PDMAUDIOPCMPROPS const CfgDst = PDMAUDIOPCMPROPS_INITIALIZER(2 /*cbSample*/, true /*fSigned*/, 2 /*ch*/, uToHz, false /*fSwap*/);
     567    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgDst));
     568    AUDIOMIXBUFPEEKSTATE PeekState;
     569    RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInitPeekState(&MixBuf, &PeekState, &CfgDst));
     570
     571    /*
     572     * Test parameters.
     573     */
     574    uint32_t const cMaxSrcFrames = RT_MIN(cFrames * uFromHz / uToHz - 1, cFrames);
     575    uint32_t const cIterations   = RTRandU32Ex(64, 1024);
     576    RTTestErrContext(hTest, "cFrames=%RU32 cMaxSrcFrames=%RU32 cIterations=%RU32", cFrames, cMaxSrcFrames, cIterations);
     577    RTTestPrintf(hTest, RTTESTLVL_DEBUG, "cFrames=%RU32 cMaxSrcFrames=%RU32 cIterations=%RU32\n",
     578                 cFrames, cMaxSrcFrames, cIterations);
     579
     580    /*
     581     * We generate a simple "A" sine wave as input.
     582     */
     583    uint32_t iSrcFrame = 0;
     584    uint32_t iDstFrame = 0;
     585    double   rdFixed = 2.0 * M_PI * 440.0 /* A */ / PDMAudioPropsHz(&CfgSrc); /* Fixed sin() input. */
     586    for (uint32_t i = 0; i < cIterations; i++)
     587    {
     588        RTTestPrintf(hTest, RTTESTLVL_DEBUG, "i=%RU32\n", i);
     589
     590        /*
     591         * Generate source frames and write them.
     592         */
     593        uint32_t const cSrcFrames = i < cIterations / 2
     594                                  ? RTRandU32Ex(2, cMaxSrcFrames) & ~(uint32_t)1
     595                                  : RTRandU32Ex(1, cMaxSrcFrames - 1) | 1;
     596        for (uint32_t j = 0; j < cSrcFrames; j++, iSrcFrame++)
     597            aSrcFrames[j].r = aSrcFrames[j].l = 32760 /*Amplitude*/ * sin(rdFixed * iSrcFrame);
     598
     599        uint32_t cSrcFramesWritten = UINT32_MAX / 2;
     600        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteCirc(&MixBuf, &aSrcFrames, cSrcFrames * sizeof(aSrcFrames[0]), &cSrcFramesWritten));
     601        RTTESTI_CHECK_MSG_BREAK(cSrcFrames == cSrcFramesWritten,
     602                                ("cSrcFrames=%RU32 vs cSrcFramesWritten=%RU32 cLiveFrames=%RU32\n",
     603                                 cSrcFrames, cSrcFramesWritten, AudioMixBufLive(&MixBuf)));
     604
     605        /*
     606         * Read out all the frames using the peek function.
     607         */
     608        uint32_t offSrcFrame = 0;
     609        while (offSrcFrame < cSrcFramesWritten)
     610        {
     611            uint32_t cSrcFramesToRead = cSrcFramesWritten - offSrcFrame;
     612            uint32_t cTmp = (uint64_t)cSrcFramesToRead * uToHz / uFromHz;
     613            if (cTmp + 32 >= RT_ELEMENTS(aDstFrames))
     614                cSrcFramesToRead = ((uint64_t)RT_ELEMENTS(aDstFrames) - 32) * uFromHz / uToHz; /* kludge */
     615
     616            uint32_t cSrcFramesPeeked = UINT32_MAX / 4;
     617            uint32_t cbDstPeeked      = UINT32_MAX / 2;
     618            RTRandBytes(aDstFrames, sizeof(aDstFrames));
     619            AudioMixBufPeek(&MixBuf, offSrcFrame, cSrcFramesToRead, &cSrcFramesPeeked,
     620                            &PeekState, aDstFrames, sizeof(aDstFrames), &cbDstPeeked);
     621            uint32_t cDstFramesPeeked = PDMAudioPropsBytesToFrames(&CfgDst, cbDstPeeked);
     622            RTTESTI_CHECK(cbDstPeeked > 0 || cSrcFramesPeeked > 0);
     623
     624            if (uFromHz == uToHz)
     625            {
     626                for (uint32_t iDst = 0; iDst < cDstFramesPeeked; iDst++)
     627                    if (memcmp(&aDstFrames[iDst], &aSrcFrames[offSrcFrame + iDst], sizeof(aSrcFrames[0])) != 0)
     628                        RTTestFailed(hTest, "Frame #%u differs: %#x / %#x, expected %#x / %#x\n", iDstFrame + iDst,
     629                                     aDstFrames[iDst].l, aDstFrames[iDst].r,
     630                                     aSrcFrames[iDst + offSrcFrame].l, aSrcFrames[iDst + offSrcFrame].r);
     631            }
     632
     633            offSrcFrame += cSrcFramesPeeked;
     634            iDstFrame   += cDstFramesPeeked;
     635        }
     636
     637        /*
     638         * Then advance.
     639         */
     640        AudioMixBufAdvance(&MixBuf, cSrcFrames);
     641        RTTESTI_CHECK(AudioMixBufLive(&MixBuf) == 0);
     642    }
     643
     644    /** @todo this is a bit lax...   */
     645    uint32_t const cDstMinExpect = ((uint64_t)iSrcFrame * uToHz - uFromHz - 1) / uFromHz;
     646    uint32_t const cDstMaxExpect = ((uint64_t)iSrcFrame * uToHz + uFromHz - 1) / uFromHz;
     647    RTTESTI_CHECK_MSG(iDstFrame >= cDstMinExpect && iDstFrame <= cDstMaxExpect,
     648                      ("iSrcFrame=%#x -> %#x..%#x; iDstFrame=%#x (delta %d)\n",
     649                       iSrcFrame, cDstMinExpect, cDstMaxExpect, iDstFrame, (cDstMinExpect + cDstMaxExpect) / 2 - iDstFrame));
     650
     651    AudioMixBufDestroy(&MixBuf);
     652}
     653
     654
    550655/* Test 8-bit sample conversion (8-bit -> internal -> 8-bit). */
    551656static int tstConversion8(RTTEST hTest)
     
    883988    tstDownsampling(hTest, 48000, 22050);
    884989    tstDownsampling(hTest, 48000, 11000);
     990    tstNewPeek(hTest, 48000, 48000);
     991    tstNewPeek(hTest, 48000, 11000);
     992    tstNewPeek(hTest, 48000, 44100);
     993    tstNewPeek(hTest, 44100, 22050);
     994    tstNewPeek(hTest, 44100, 11000);
     995    //tstNewPeek(hTest, 11000, 48000);
     996    //tstNewPeek(hTest, 22050, 44100);
    885997
    886998    /*
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