VirtualBox

Changeset 89373 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 29, 2021 3:35:17 AM (4 years ago)
Author:
vboxsync
Message:

AudioMixBuffer,tstAudioMixBuffer: Added more conversion tests and fixed a couple of blending bugs. Also fixed AudioMixBufSilence assertion issue and removed unused member AUDIOMIXBUF::cMixed. bugref:9890

Location:
trunk/src/VBox/Devices/Audio
Files:
3 edited

Legend:

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

    r89371 r89373  
    169169static void audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl)
    170170{
    171     Log(("%s: %*s %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n",
     171    Log(("%s: %*s %s: offRead=%RU32, offWrite=%RU32 -> %RU32/%RU32\n",
    172172         pszFunc, uIdtLvl * 4, "",
    173          pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cMixed, pMixBuf->cUsed, pMixBuf->cFrames));
     173         pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cUsed, pMixBuf->cFrames));
    174174}
    175175
     
    231231    {
    232232        int64_t const i64Dst = *pi64Dst;
    233         if (!pi64Dst)
     233        if (!i64Dst)
    234234            *pi64Dst = i64Src;
    235235        else
     
    273273            while (cFrames-- > 0)
    274274            {
    275                 int64_t const i64DstL = pi64Dst[0];
    276                 int64_t const i64SrcL = pi64Src[0];
    277                 if (!i64DstL)
    278                     pi64Dst[0] = i64SrcL;
    279                 else if (!i64SrcL)
    280                     pi64Dst[0] = (i64DstL + i64SrcL) / 2;
    281 
    282                 int64_t const i64DstR = pi64Dst[1];
    283                 int64_t const i64SrcR = pi64Src[1];
    284                 if (!i64DstR)
    285                     pi64Dst[1] = i64SrcR;
    286                 else if (!i64SrcR)
    287                     pi64Dst[1] = (i64DstR + i64SrcR) / 2;
    288 
     275                audioMixBufBlendSample(&pi64Dst[0], pi64Dst[0]);
     276                audioMixBufBlendSample(&pi64Dst[1], pi64Dst[1]);
    289277                pi64Dst += 2;
    290278                pi64Src += 2;
     
    298286            while (cFrames-- > 0)
    299287            {
    300                 int64_t const i64Dst = *pi64Dst;
    301                 int64_t const i64Src = *pi64Src;
    302                 if (!i64Dst)
    303                     *pi64Dst = i64Src;
    304                 else if (!i64Src)
    305                     *pi64Dst = (i64Dst + i64Src) / 2;
     288                audioMixBufBlendSample(pi64Dst, pi64Dst[0]);
    306289                pi64Dst++;
    307290                pi64Src++;
     
    890873    pMixBuf->offRead  = 0;
    891874    pMixBuf->offWrite = 0;
    892     pMixBuf->cMixed   = 0;
    893875    pMixBuf->cUsed    = 0;
    894876
     
    986968    pMixBuf->offRead  = 0;
    987969    pMixBuf->offWrite = 0;
    988     pMixBuf->cMixed   = 0;
    989970    pMixBuf->cUsed    = 0;
    990971}
     
    15801561    AssertPtr(pState);
    15811562    AssertPtr(pState->pfnDecode);
     1563    AssertPtr(pState->pfnDecodeBlend);
    15821564    Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
    15831565    Assert(cMaxDstFrames > 0);
     
    17271709 *                      write position.
    17281710 * @param   cFrames     Number of frames of silence.
    1729  * @sa      AudioMixBufSilence
     1711 * @sa      AudioMixBufWrite
    17301712 *
    17311713 * @note    Does not advance the write position, please call AudioMixBufCommit()
     
    17411723    AssertPtr(pState);
    17421724    AssertPtr(pState->pfnDecode);
     1725    AssertPtr(pState->pfnDecodeBlend);
    17431726    Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
    17441727    Assert(cFrames > 0);
    1745     Assert(cFrames <= pMixBuf->cFrames);
    1746     Assert(offFrame <= pMixBuf->cFrames);
    1747     Assert(offFrame + cFrames <= pMixBuf->cUsed);
     1728#ifdef VBOX_STRICT
     1729    uint32_t const cMixBufFree = pMixBuf->cFrames - pMixBuf->cUsed;
     1730#endif
     1731    Assert(cFrames <= cMixBufFree);
     1732    Assert(offFrame < cMixBufFree);
     1733    Assert(offFrame + cFrames <= cMixBufFree);
    17481734
    17491735    /*
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.h

    r89371 r89373  
    151151    /** The current write position (in frames). */
    152152    uint32_t                    offWrite;
    153     /** Total frames already mixed down to the parent buffer (if any).
    154      *
    155      * Always starting at the parent's offRead position.
    156      * @note Count always is specified in parent frames, as the sample count can
    157      *       differ between parent and child.  */
    158     uint32_t                    cMixed;
    159153    /** How much audio frames are currently being used in this buffer.
    160154     * @note This also is known as the distance in ring buffer terms. */
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r89371 r89373  
    3636#define _USE_MATH_DEFINES
    3737#include <math.h> /* sin, M_PI */
     38
     39
     40/*********************************************************************************************************************************
     41*   Global Variables                                                                                                             *
     42*********************************************************************************************************************************/
     43#ifdef RT_LITTLE_ENDIAN
     44bool const g_fLittleEndian = true;
     45#else
     46bool const g_fLittleEndian = false;
     47#endif
    3848
    3949
     
    321331}
    322332
    323 #if 0 /* obsolete */
    324 static int tstParentChild(RTTEST hTest)
     333/** @name Eight test samples represented in all basic formats.
     334 * @{ */
     335static uint8_t const  g_au8TestSamples[8]  = {         0x1,        0x11,        0x32,       0x7f,        0x80,       0x81,       0xbe,       0xff };
     336static int8_t  const  g_ai8TestSamples[8]  = {        -127,        -111,         -78,         -1,           0,          1,         62,        127 };
     337static uint16_t const g_au16TestSamples[8] = {       0x100,      0x1100,      0x3200,     0x7f00,      0x8000,     0x8100,     0xbe00,     0xff00 };
     338static int16_t  const g_ai16TestSamples[8] = {      -32512,      -28416,      -19968,       -256,           0,        256,      15872,      32512 };
     339static uint32_t const g_au32TestSamples[8] = {   0x1000000,  0x11000000,  0x32000000, 0x7f000000,  0x80000000, 0x81000000, 0xbe000000, 0xff000000 };
     340static int32_t  const g_ai32TestSamples[8] = { -2130706432, -1862270976, -1308622848,  -16777216,           0,   16777216, 1040187392, 2130706432 };
     341static int64_t  const g_ai64TestSamples[8] = { -2130706432, -1862270976, -1308622848,  -16777216,           0,   16777216, 1040187392, 2130706432 };
     342static struct { void const *apv[2]; uint32_t cb; } g_aTestSamples[] =
    325343{
    326     RTTestSub(hTest, "2 Children -> Parent (AudioMixBufWriteAt)");
    327 
    328     uint32_t cParentBufSize = RTRandU32Ex(_1K /* Min */, _16K /* Max */); /* Enough room for random sizes */
    329 
    330     /* 44100Hz, 2 Channels, S16 */
    331     PDMAUDIOPCMPROPS cfg_p = PDMAUDIOPCMPROPS_INITIALIZER(
    332         2,                                                                  /* Bytes */
    333         true,                                                               /* Signed */
    334         2,                                                                  /* Channels */
    335         44100,                                                              /* Hz */
    336         false                                                               /* Swap Endian */
    337     );
    338 
    339     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
    340 
    341     AUDIOMIXBUF parent;
    342     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cParentBufSize));
    343 
    344     /* 22050Hz, 2 Channels, S16 */
    345     PDMAUDIOPCMPROPS cfg_c1 = PDMAUDIOPCMPROPS_INITIALIZER(/* Upmixing to parent */
    346         2,                                                                  /* Bytes */
    347         true,                                                               /* Signed */
    348         2,                                                                  /* Channels */
    349         22050,                                                              /* Hz */
    350         false                                                               /* Swap Endian */
    351     );
    352 
    353     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c1));
    354 
    355     uint32_t cFrames      = 16;
    356     uint32_t cChildBufSize = RTRandU32Ex(cFrames /* Min */, 64 /* Max */);
    357 
    358     AUDIOMIXBUF child1;
    359     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &cfg_c1, cChildBufSize));
    360     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent));
    361 
    362     /* 48000Hz, 2 Channels, S16 */
    363     PDMAUDIOPCMPROPS cfg_c2 = PDMAUDIOPCMPROPS_INITIALIZER(/* Downmixing to parent */
    364         2,                                                                  /* Bytes */
    365         true,                                                               /* Signed */
    366         2,                                                                  /* Channels */
    367         48000,                                                              /* Hz */
    368         false                                                               /* Swap Endian */
    369     );
    370 
    371     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c2));
    372 
    373     AUDIOMIXBUF child2;
    374     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &cfg_c2, cChildBufSize));
    375     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent));
    376 
    377     /*
    378      * Writing + mixing from child/children -> parent, sequential.
    379      */
    380     uint32_t cbBuf = _1K;
    381     char pvBuf[_1K];
    382     int16_t aFrames16[32] = { 0xAA, 0xBB };
    383     uint32_t cFramesRead, cFramesWritten, cFramesMixed;
    384 
    385     uint32_t cFramesChild1  = cFrames;
    386     uint32_t cFramesChild2  = cFrames;
    387 
    388     uint32_t t = RTRandU32() % 32;
    389 
    390     RTTestPrintf(hTest, RTTESTLVL_DEBUG,
    391                  "cParentBufSize=%RU32, cChildBufSize=%RU32, %RU32 frames -> %RU32 iterations total\n",
    392                  cParentBufSize, cChildBufSize, cFrames, t);
    393 
    394     /*
    395      * Using AudioMixBufWriteAt for writing to children.
    396      */
    397     uint32_t cChildrenSamplesMixedTotal = 0;
    398 
    399     for (uint32_t i = 0; i < t; i++)
    400     {
    401         RTTestPrintf(hTest, RTTESTLVL_DEBUG, "i=%RU32\n", i);
    402 
    403         uint32_t cChild1Writes = RTRandU32() % 8;
    404 
    405         for (uint32_t c1 = 0; c1 < cChild1Writes; c1++)
     344    /* 0/0:  */ { { NULL, NULL }, 0 },
     345    /* 1/8:  */ { {  g_au8TestSamples,  g_ai8TestSamples }, sizeof( g_au8TestSamples) },
     346    /* 2/16: */ { { g_au16TestSamples, g_ai16TestSamples }, sizeof(g_au16TestSamples) },
     347    /* 3/24: */ { { NULL, NULL }, 0 },
     348    /* 4/32: */ { { g_au32TestSamples, g_ai32TestSamples }, sizeof(g_au32TestSamples) },
     349    /* 5: */    { { NULL, NULL }, 0 },
     350    /* 6: */    { { NULL, NULL }, 0 },
     351    /* 7: */    { { NULL, NULL }, 0 },
     352    /* 8:64 */  { {              NULL, g_ai64TestSamples }, sizeof(g_ai64TestSamples) }, /* raw */
     353};
     354/** @} */
     355
     356/** Fills a buffer with samples from an g_aTestSamples entry. */
     357static uint32_t tstFillBuf(PCPDMAUDIOPCMPROPS pCfg, void const *pvTestSamples, uint32_t iTestSample,
     358                           uint8_t *pbBuf, uint32_t cFrames)
     359{
     360    uint8_t const cTestSamples = RT_ELEMENTS(g_au8TestSamples);
     361
     362    cFrames *= PDMAudioPropsChannels(pCfg);
     363    switch (PDMAudioPropsSampleSize(pCfg))
     364    {
     365        case 1:
    406366        {
    407             /* Child 1. */
    408             RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child1, 0, &aFrames16, sizeof(aFrames16), &cFramesWritten));
    409             RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesChild1, ("Child1: Expected %RU32 written frames, got %RU32\n", cFramesChild1, cFramesWritten));
    410             RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, cFramesWritten, &cFramesMixed));
    411 
    412             cChildrenSamplesMixedTotal += cFramesMixed;
    413 
    414             RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesMixed, ("Child1: Expected %RU32 mixed frames, got %RU32\n", cFramesWritten, cFramesMixed));
    415             RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == 0, ("Child1: Expected %RU32 used frames, got %RU32\n", 0, AudioMixBufUsed(&child1)));
     367            uint8_t const * const pau8TestSamples = (uint8_t const *)pvTestSamples;
     368            uint8_t              *pu8Dst          = (uint8_t *)pbBuf;
     369            while (cFrames-- > 0)
     370            {
     371                *pu8Dst++ = pau8TestSamples[iTestSample];
     372                iTestSample = (iTestSample + 1) % cTestSamples;
     373            }
     374            break;
    416375        }
    417376
    418         uint32_t cChild2Writes = RTRandU32() % 8;
    419 
    420         for (uint32_t c2 = 0; c2 < cChild2Writes; c2++)
     377        case 2:
    421378        {
    422             /* Child 2. */
    423             RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &aFrames16, sizeof(aFrames16), &cFramesWritten));
    424             RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesChild2, ("Child2: Expected %RU32 written frames, got %RU32\n", cFramesChild2, cFramesWritten));
    425             RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, cFramesWritten, &cFramesMixed));
    426 
    427             cChildrenSamplesMixedTotal += cFramesMixed;
    428 
    429             RTTESTI_CHECK_MSG_BREAK(cFramesWritten == cFramesMixed, ("Child2: Expected %RU32 mixed frames, got %RU32\n", cFramesWritten, cFramesMixed));
    430             RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == 0, ("Child2: Expected %RU32 used frames, got %RU32\n", 0, AudioMixBufUsed(&child2)));
     379            uint16_t const * const pau16TestSamples = (uint16_t const *)pvTestSamples;
     380            uint16_t              *pu16Dst          = (uint16_t *)pbBuf;
     381            while (cFrames-- > 0)
     382            {
     383                *pu16Dst++ = pau16TestSamples[iTestSample];
     384                iTestSample = (iTestSample + 1) % cTestSamples;
     385            }
     386            break;
    431387        }
    432388
    433         /*
    434          * Read out all frames from the parent buffer and also mark the just-read frames as finished
    435          * so that both connected children buffers can keep track of their stuff.
    436          */
    437         uint32_t cParentSamples = AudioMixBufUsed(&parent);
    438         while (cParentSamples)
     389        case 4:
    439390        {
    440             RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufAcquireReadBlock(&parent, pvBuf, cbBuf, &cFramesRead));
    441             if (!cFramesRead)
    442                 break;
    443 
    444             AudioMixBufReleaseReadBlock(&parent, cFramesRead);
    445             AudioMixBufFinish(&parent, cFramesRead);
    446 
    447             RTTESTI_CHECK(cParentSamples >= cFramesRead);
    448             cParentSamples -= cFramesRead;
     391            uint32_t const * const pau32TestSamples = (uint32_t const *)pvTestSamples;
     392            uint32_t              *pu32Dst          = (uint32_t *)pbBuf;
     393            while (cFrames-- > 0)
     394            {
     395                *pu32Dst++ = pau32TestSamples[iTestSample];
     396                iTestSample = (iTestSample + 1) % cTestSamples;
     397            }
     398            break;
    449399        }
    450400
    451         RTTESTI_CHECK(cParentSamples == 0);
    452     }
    453 
    454     RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    455     RTTESTI_CHECK(AudioMixBufLive(&child1) == 0);
    456     RTTESTI_CHECK(AudioMixBufLive(&child2) == 0);
    457 
    458     AudioMixBufDestroy(&parent);
    459     AudioMixBufDestroy(&child1);
    460     AudioMixBufDestroy(&child2);
    461 
    462     return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
     401        case 8:
     402        {
     403            uint64_t const * const pau64TestSamples = (uint64_t const *)pvTestSamples;
     404            uint64_t              *pu64Dst          = (uint64_t *)pbBuf;
     405            while (cFrames-- > 0)
     406            {
     407                *pu64Dst++ = pau64TestSamples[iTestSample];
     408                iTestSample = (iTestSample + 1) % cTestSamples;
     409            }
     410            break;
     411        }
     412
     413        default:
     414            AssertFailedBreak();
     415    }
     416    return iTestSample;
    463417}
     418
     419
     420static void tstConversion(RTTEST hTest, uint8_t cSrcBits, bool fSrcSigned, uint8_t cSrcChs,
     421                          uint8_t cDstBits, bool fDstSigned, uint8_t cDstChs)
     422{
     423    RTTestSubF(hTest, "Conv %uch %c%u to %uch %c%u", cSrcChs, fSrcSigned ? 'S' : 'U', cSrcBits,
     424               cDstChs, fDstSigned ? 'S' : 'U', cDstBits);
     425
     426    PDMAUDIOPCMPROPS       CfgSrc, CfgDst;
     427    PDMAudioPropsInitEx(&CfgSrc, cSrcBits / 8, fSrcSigned, cSrcChs, 44100, g_fLittleEndian, cSrcBits == 64 /*fRaw*/);
     428    PDMAudioPropsInitEx(&CfgDst, cDstBits / 8, fDstSigned, cDstChs, 44100, g_fLittleEndian, cDstBits == 64 /*fRaw*/);
     429
     430    void const * const     pvSrcTestSamples = g_aTestSamples[cSrcBits / 8].apv[fSrcSigned];
     431    void const * const     pvDstTestSamples = g_aTestSamples[cDstBits / 8].apv[fDstSigned];
     432    uint32_t const         cMixBufFrames = RTRandU32Ex(128, 16384);
     433    uint32_t const         cIterations   = RTRandU32Ex(256, 1536);
     434    uint32_t const         cbSrcBuf      = PDMAudioPropsFramesToBytes(&CfgSrc, cMixBufFrames + 64);
     435    uint8_t * const        pbSrcBuf      = (uint8_t *)RTMemAllocZ(cbSrcBuf);
     436    uint32_t const         cbDstBuf      = PDMAudioPropsFramesToBytes(&CfgDst, cMixBufFrames + 64);
     437    uint8_t * const        pbDstBuf      = (uint8_t *)RTMemAllocZ(cbDstBuf);
     438    uint8_t * const        pbDstExpect   = (uint8_t *)RTMemAllocZ(cbDstBuf);
     439    RTTESTI_CHECK_RETV(pbSrcBuf);
     440    RTTESTI_CHECK_RETV(pbDstBuf);
     441    RTTESTI_CHECK_RETV(pbDstExpect);
     442
     443    AUDIOMIXBUF             MixBuf;
     444    RTTESTI_CHECK_RC_RETV(AudioMixBufInit(&MixBuf, "FormatOutputConversion", &CfgSrc, cMixBufFrames), VINF_SUCCESS);
     445    AUDIOMIXBUFWRITESTATE   WriteState;
     446    RTTESTI_CHECK_RC_RETV(AudioMixBufInitWriteState(&MixBuf, &WriteState, &CfgSrc), VINF_SUCCESS);
     447    AUDIOMIXBUFWRITESTATE   WriteStateIgnZero = WriteState;
     448    AUDIOMIXBUFPEEKSTATE    PeekState;
     449    RTTESTI_CHECK_RC_RETV(AudioMixBufInitPeekState(&MixBuf, &PeekState, &CfgDst), VINF_SUCCESS);
     450
     451    uint32_t iSrcTestSample = 0;
     452    uint32_t iDstTestSample = 0;
     453    //RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "cIterations=%u\n", cIterations);
     454    for (uint32_t iIteration = 0; iIteration < cIterations; iIteration++)
     455    {
     456        /* Write some frames to the buffer. */
     457        uint32_t const cSrcFramesToWrite = iIteration < 16 ? iIteration + 1
     458                                         : AudioMixBufFree(&MixBuf) ? RTRandU32Ex(1, AudioMixBufFree(&MixBuf)) : 0;
     459        if (cSrcFramesToWrite > 0)
     460        {
     461            uint32_t const cbSrcToWrite = PDMAudioPropsFramesToBytes(&CfgSrc, cSrcFramesToWrite);
     462            uint32_t cFrames = RTRandU32();
     463            switch (RTRandU32Ex(0, 3))
     464            {
     465                default:
     466                    iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite);
     467                    AudioMixBufWrite(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames);
     468                    RTTESTI_CHECK(cFrames == cSrcFramesToWrite);
     469                    break;
     470
     471#if 0 /** @todo doesn't work for some U64 variations */
     472                case 1: /* zero & blend */
     473                    AudioMixBufSilence(&MixBuf, &WriteStateIgnZero, 0 /*offFrame*/, cSrcFramesToWrite);
     474                    iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite);
     475                    AudioMixBufBlend(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames);
     476                    RTTESTI_CHECK(cFrames == cSrcFramesToWrite);
     477                    break;
    464478#endif
     479
     480                case 2: /* blend same equal data twice */
     481                {
     482                    AUDIOMIXBUFWRITESTATE WriteStateSame = WriteState;
     483                    iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite);
     484                    AudioMixBufWrite(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames);
     485                    RTTESTI_CHECK(cFrames == cSrcFramesToWrite);
     486                    AudioMixBufBlend(&MixBuf, &WriteStateSame, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames);
     487                    RTTESTI_CHECK(cFrames == cSrcFramesToWrite);
     488                    break;
     489                }
     490                case 3: /* write & blend with zero */
     491                {
     492                    AUDIOMIXBUFWRITESTATE WriteStateSame = WriteState;
     493                    iSrcTestSample = tstFillBuf(&CfgSrc, pvSrcTestSamples, iSrcTestSample, pbSrcBuf, cSrcFramesToWrite);
     494                    AudioMixBufWrite(&MixBuf, &WriteState, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames);
     495                    RTTESTI_CHECK(cFrames == cSrcFramesToWrite);
     496                    PDMAudioPropsClearBuffer(&CfgSrc, pbSrcBuf, cbSrcToWrite, cSrcFramesToWrite);
     497                    AudioMixBufBlend(&MixBuf, &WriteStateSame, pbSrcBuf, cbSrcToWrite, 0 /*offDstFrame*/, cSrcFramesToWrite, &cFrames);
     498                    RTTESTI_CHECK(cFrames == cSrcFramesToWrite);
     499                    break;
     500                }
     501            }
     502            AudioMixBufCommit(&MixBuf, cSrcFramesToWrite);
     503        }
     504
     505        /* Read some frames back. */
     506        uint32_t const cUsed            = AudioMixBufUsed(&MixBuf);
     507        uint32_t const cDstFramesToRead = iIteration < 16 ? iIteration + 1 : iIteration + 5 >= cIterations ? cUsed
     508                                        : cUsed ? RTRandU32Ex(1, cUsed) : 0;
     509        if (cDstFramesToRead > 0)
     510        {
     511            uint32_t const cbDstToRead = PDMAudioPropsFramesToBytes(&CfgDst, cDstFramesToRead);
     512            uint32_t       cbRead      = RTRandU32();
     513            uint32_t       cFrames     = RTRandU32();
     514            RTRandBytes(pbDstBuf, cbDstToRead);
     515            AudioMixBufPeek(&MixBuf, 0 /*offSrcFrame*/, (iIteration & 3) != 2 ? cDstFramesToRead : cUsed, &cFrames,
     516                            &PeekState, pbDstBuf,       (iIteration & 3) != 3 ? cbDstToRead      : cbDstBuf, &cbRead);
     517            RTTESTI_CHECK(cFrames == cDstFramesToRead);
     518            RTTESTI_CHECK(cbRead  == cbDstToRead);
     519            AudioMixBufAdvance(&MixBuf, cFrames);
     520
     521            /* Verify if we can. */
     522            if (PDMAudioPropsChannels(&CfgSrc) == PDMAudioPropsChannels(&CfgDst))
     523            {
     524                iDstTestSample = tstFillBuf(&CfgDst, pvDstTestSamples, iDstTestSample, pbDstExpect, cFrames);
     525                if (memcmp(pbDstExpect, pbDstBuf, cbRead) == 0)
     526                { /* likely */ }
     527                else
     528                {
     529                    RTTestFailed(hTest,
     530                                 "mismatch: %.*Rhxs\n"
     531                                 "expected: %.*Rhxs\n"
     532                                 "iIteration=%u cDstFramesToRead=%u cbRead=%#x\n",
     533                                 RT_MIN(cbRead, 48), pbDstBuf,
     534                                 RT_MIN(cbRead, 48), pbDstExpect,
     535                                 iIteration, cDstFramesToRead, cbRead);
     536                    break;
     537                }
     538            }
     539        }
     540    }
     541
     542    AudioMixBufTerm(&MixBuf);
     543    RTMemFree(pbSrcBuf);
     544    RTMemFree(pbDstBuf);
     545    RTMemFree(pbDstExpect);
     546}
    465547
    466548
     
    677759}
    678760
    679 
    680 #if 0 /** @todo rewrite to non-parent/child setup */
    681 /* Test 8-bit sample conversion (8-bit -> internal -> 8-bit). */
    682 static int tstConversion8(RTTEST hTest)
    683 {
    684     RTTestSub(hTest, "Convert 22kHz/U8 to 44.1kHz/S16 (mono)");
    685     unsigned         i;
    686     uint32_t         cBufSize = 256;
    687 
    688 
    689     /* 44100Hz, 1 Channel, U8 */
    690     PDMAUDIOPCMPROPS cfg_p = PDMAUDIOPCMPROPS_INITIALIZER(
    691         1,                                                                  /* Bytes */
    692         false,                                                              /* Signed */
    693         1,                                                                  /* Channels */
    694         44100,                                                              /* Hz */
    695         false                                                               /* Swap Endian */
    696     );
    697 
    698     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
    699 
    700     AUDIOMIXBUF parent;
    701     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
    702 
    703     /* Child uses half the sample rate; that ensures the mixing engine can't
    704      * take shortcuts and performs conversion. Because conversion to double
    705      * the sample rate effectively inserts one additional sample between every
    706      * two source frames, N source frames will be converted to N * 2 - 1
    707      * frames. However, the last source sample will be saved for later
    708      * interpolation and not immediately output.
    709      */
    710 
    711     /* 22050Hz, 1 Channel, U8 */
    712     PDMAUDIOPCMPROPS cfg_c = PDMAUDIOPCMPROPS_INITIALIZER( /* Upmixing to parent */
    713         1,                                                                  /* Bytes */
    714         false,                                                              /* Signed */
    715         1,                                                                  /* Channels */
    716         22050,                                                              /* Hz */
    717         false                                                               /* Swap Endian */
    718     );
    719 
    720     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));
    721 
    722     AUDIOMIXBUF child;
    723     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
    724     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
    725 
    726     /* 8-bit unsigned frames. Often used with SB16 device. */
    727     uint8_t aFrames8U[16]  = { 0xAA, 0xBB, 0, 1, 43, 125, 126, 127,
    728                                128, 129, 130, 131, 132, UINT8_MAX - 1, UINT8_MAX, 0 };
    729 
    730     /*
    731      * Writing + mixing from child -> parent, sequential.
    732      */
    733     uint32_t    cbBuf = 256;
    734     char        achBuf[256];
    735     uint32_t    cFramesRead, cFramesWritten, cFramesMixed;
    736 
    737     uint32_t cFramesChild  = 16;
    738     uint32_t cFramesParent = cFramesChild * 2 - 2;
    739     uint32_t cFramesTotalRead   = 0;
    740 
    741     /**** 8-bit unsigned samples ****/
    742     RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 8-bit\n", cfg_c.uHz, PDMAudioPropsChannels(&cfg_c));
    743     RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &aFrames8U, sizeof(aFrames8U), &cFramesWritten));
    744     RTTESTI_CHECK_MSG(cFramesWritten == cFramesChild, ("Child: Expected %RU32 written frames, got %RU32\n", cFramesChild, cFramesWritten));
    745     RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cFramesWritten, &cFramesMixed));
    746     uint32_t cFrames = AudioMixBufUsed(&parent);
    747     RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == cFrames, ("Child: Expected %RU32 mixed frames, got %RU32\n", AudioMixBufLive(&child), cFrames));
    748 
    749     RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));
    750 
    751     for (;;)
    752     {
    753         RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufAcquireReadBlock(&parent, achBuf, cbBuf, &cFramesRead));
    754         if (!cFramesRead)
    755             break;
    756         cFramesTotalRead += cFramesRead;
    757         AudioMixBufReleaseReadBlock(&parent, cFramesRead);
    758         AudioMixBufFinish(&parent, cFramesRead);
    759     }
    760 
    761     RTTESTI_CHECK_MSG(cFramesTotalRead == cFramesParent, ("Parent: Expected %RU32 mixed frames, got %RU32\n", cFramesParent, cFramesTotalRead));
    762 
    763     /* Check that the frames came out unharmed. Every other sample is interpolated and we ignore it. */
    764     /* NB: This also checks that the default volume setting is 0dB attenuation. */
    765     uint8_t *pSrc8 = &aFrames8U[0];
    766     uint8_t *pDst8 = (uint8_t *)achBuf;
    767 
    768     for (i = 0; i < cFramesChild - 1; ++i)
    769     {
    770         RTTESTI_CHECK_MSG(*pSrc8 == *pDst8, ("index %u: Dst=%d, Src=%d\n", i, *pDst8, *pSrc8));
    771         pSrc8 += 1;
    772         pDst8 += 2;
    773     }
    774 
    775     RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    776     RTTESTI_CHECK(AudioMixBufLive(&child)  == 0);
    777 
    778     AudioMixBufDestroy(&parent);
    779     AudioMixBufDestroy(&child);
    780 
    781     return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
    782 }
    783 #endif
    784 
    785 #if 0 /** @todo rewrite to non-parent/child setup */
    786 /* Test 16-bit sample conversion (16-bit -> internal -> 16-bit). */
    787 static int tstConversion16(RTTEST hTest)
    788 {
    789     RTTestSub(hTest, "Convert 22kHz/S16 to 44.1kHz/S16 (mono)");
    790     unsigned         i;
    791     uint32_t         cBufSize = 256;
    792 
    793     /* 44100Hz, 1 Channel, S16 */
    794     PDMAUDIOPCMPROPS cfg_p = PDMAUDIOPCMPROPS_INITIALIZER(
    795         2,                                                                  /* Bytes */
    796         true,                                                               /* Signed */
    797         1,                                                                  /* Channels */
    798         44100,                                                              /* Hz */
    799         false                                                               /* Swap Endian */
    800     );
    801 
    802     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
    803 
    804     AUDIOMIXBUF parent;
    805     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
    806 
    807     /* 22050Hz, 1 Channel, S16 */
    808     PDMAUDIOPCMPROPS cfg_c = PDMAUDIOPCMPROPS_INITIALIZER( /* Upmixing to parent */
    809         2,                                                                  /* Bytes */
    810         true,                                                               /* Signed */
    811         1,                                                                  /* Channels */
    812         22050,                                                              /* Hz */
    813         false                                                               /* Swap Endian */
    814     );
    815 
    816     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));
    817 
    818     AUDIOMIXBUF child;
    819     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
    820     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
    821 
    822     /* 16-bit signed. More or less exclusively used as output, and usually as input, too. */
    823     int16_t     aFrames16S[16] = { 0xAA, 0xBB, INT16_MIN, INT16_MIN + 1, INT16_MIN / 2, -3, -2, -1,
    824                                    0, 1, 2, 3, INT16_MAX / 2, INT16_MAX - 1, INT16_MAX, 0 };
    825 
    826     /*
    827      * Writing + mixing from child -> parent, sequential.
    828      */
    829     uint32_t    cbBuf = 256;
    830     char        achBuf[256];
    831     uint32_t    cFramesRead, cFramesWritten, cFramesMixed;
    832 
    833     uint32_t cFramesChild  = 16;
    834     uint32_t cFramesParent = cFramesChild * 2 - 2;
    835     uint32_t cFramesTotalRead   = 0;
    836 
    837     /**** 16-bit signed samples ****/
    838     RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch 16-bit\n", cfg_c.uHz, PDMAudioPropsChannels(&cfg_c));
    839     RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&child, &aFrames16S, sizeof(aFrames16S), &cFramesWritten));
    840     RTTESTI_CHECK_MSG(cFramesWritten == cFramesChild, ("Child: Expected %RU32 written frames, got %RU32\n", cFramesChild, cFramesWritten));
    841     RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, cFramesWritten, &cFramesMixed));
    842     uint32_t cFrames = AudioMixBufUsed(&parent);
    843     RTTESTI_CHECK_MSG(AudioMixBufLive(&child) == cFrames, ("Child: Expected %RU32 mixed frames, got %RU32\n", AudioMixBufLive(&child), cFrames));
    844 
    845     RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufLive(&child));
    846 
    847     for (;;)
    848     {
    849         RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufAcquireReadBlock(&parent, achBuf, cbBuf, &cFramesRead));
    850         if (!cFramesRead)
    851             break;
    852         cFramesTotalRead += cFramesRead;
    853         AudioMixBufReleaseReadBlock(&parent, cFramesRead);
    854         AudioMixBufFinish(&parent, cFramesRead);
    855     }
    856     RTTESTI_CHECK_MSG(cFramesTotalRead == cFramesParent, ("Parent: Expected %RU32 mixed frames, got %RU32\n", cFramesParent, cFramesTotalRead));
    857 
    858     /* Check that the frames came out unharmed. Every other sample is interpolated and we ignore it. */
    859     /* NB: This also checks that the default volume setting is 0dB attenuation. */
    860     int16_t *pSrc16 = &aFrames16S[0];
    861     int16_t *pDst16 = (int16_t *)achBuf;
    862 
    863     for (i = 0; i < cFramesChild - 1; ++i)
    864     {
    865         RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16));
    866         pSrc16 += 1;
    867         pDst16 += 2;
    868     }
    869 
    870     RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    871     RTTESTI_CHECK(AudioMixBufLive(&child)  == 0);
    872 
    873     AudioMixBufDestroy(&parent);
    874     AudioMixBufDestroy(&child);
    875 
    876     return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
    877 }
    878 #endif
    879 
    880761#if 0 /** @todo rewrite to non-parent/child setup */
    881762/* Test volume control. */
     
    1011892    tstBasics(hTest);
    1012893    tstSimple(hTest);
    1013     //tstParentChild(hTest);
    1014     //tstConversion8(hTest);
    1015     //tstConversion16(hTest);
    1016     //tstVolume(hTest);
     894
     895    /* Run tstConversion for all combinations we have test data. */
     896    for (unsigned iSrc = 0; iSrc < RT_ELEMENTS(g_aTestSamples); iSrc++)
     897    {
     898        for (unsigned iSrcSigned = 0; iSrcSigned < RT_ELEMENTS(g_aTestSamples[0].apv); iSrcSigned++)
     899            if (g_aTestSamples[iSrc].apv[iSrcSigned])
     900                for (unsigned cSrcChs = 1; cSrcChs <= 2; cSrcChs++)
     901                    for (unsigned iDst = 0; iDst < RT_ELEMENTS(g_aTestSamples); iDst++)
     902                        for (unsigned iDstSigned = 0; iDstSigned < RT_ELEMENTS(g_aTestSamples[0].apv); iDstSigned++)
     903                            if (g_aTestSamples[iDst].apv[iDstSigned])
     904                                for (unsigned cDstChs = 1; cDstChs <= 2; cDstChs++)
     905                                    tstConversion(hTest, iSrc * 8, iSrcSigned == 1, cSrcChs,
     906                                                  /*->*/ iDst * 8, iDstSigned == 1, cDstChs);
     907    }
     908
    1017909#if 0 /** @todo rewrite to non-parent/child setup */
    1018910    tstDownsampling(hTest, 44100, 22050);
     
    1029921    //tstNewPeek(hTest, 22050, 44100);
    1030922
     923    //tstVolume(hTest);
     924
    1031925    /*
    1032926     * Summary
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