VirtualBox

Changeset 55462 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 27, 2015 8:01:05 PM (10 years ago)
Author:
vboxsync
Message:

Audio: Fixed minor format conversion errors, added a testcase (16-bit signed test only so far).

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

Legend:

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

    r55447 r55462  
    7474 *
    7575 * For actual volume calculation, 33.31 fixed point is used. Maximum (or
    76  * unattenuated) volume is represented as 0x80000000; conveniently, this
     76 * unattenuated) volume is represented as 0x40000000; conveniently, this
    7777 * value fits into a uint32_t.
     78 *
     79 * To enable fast processing, the maximum volume must be a power of two
     80 * and must not have a sign when converted to int32_t. While 0x80000000
     81 * violates these constraints, 0x40000000 does not.
    7882 */
    7983
     
    115119};
    116120
     121/* Bit shift for fixed point conversion. */
     122#define VOL_SHIFT       30
     123
     124/* Internal representation of 0dB volume (1.0 in fixed point). */
     125#define VOL_0DB         (1 << VOL_SHIFT)
     126
     127AssertCompile(VOL_0DB <= 0x40000000);   /* Must always hold. */
     128AssertCompile(VOL_0DB == 0x40000000);   /* For now -- when only attenuation is used. */
     129
    117130/**
    118131 * Structure for holding sample conversion parameters for
     
    343356    AUDMIXBUF_MACRO_FN _aType audioMixBufClipTo##_aName(int64_t iVal) \
    344357    { \
    345         if (iVal >= 0x7f000000) \
     358        if (iVal >= 0x7fffffff) \
    346359            return _aMax; \
    347         else if (iVal < -2147483648LL) \
     360        else if (iVal < -INT64_C(0x80000000)) \
    348361            return _aMin; \
    349362        \
     
    363376        { \
    364377            AUDMIXBUF_MACRO_LOG(("%p: l=%RI16, r=%RI16\n", paDst, *pSrc, *(pSrc + 1))); \
    365             paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft ) >> 31; \
    366             paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uRight) >> 31; \
     378            paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft ) >> VOL_SHIFT; \
     379            paDst->i64RSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uRight) >> VOL_SHIFT; \
    367380            AUDMIXBUF_MACRO_LOG(("\t-> l=%RI64, r=%RI64\n", paDst->i64LSample, paDst->i64RSample)); \
    368381            paDst++; \
     
    382395        { \
    383396            AUDMIXBUF_MACRO_LOG(("%p: s=%RI16\n", paDst, *pSrc)); \
    384             paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft) >> 31; \
     397            paDst->i64LSample = ASMMult2xS32RetS64((int32_t)audioMixBufClipFrom##_aName(*pSrc++), pOpts->Volume.uLeft) >> VOL_SHIFT; \
    385398            paDst->i64RSample = paDst->i64LSample; \
    386399            AUDMIXBUF_MACRO_LOG(("\t-> l=%RI64, r=%RI64\n", paDst->i64LSample, paDst->i64RSample)); \
     
    418431        while (cSamples--) \
    419432        { \
    420             *pDst++ = audioMixBufClipTo##_aName(pSrc->i64LSample + pSrc->i64RSample); \
     433            *pDst++ = audioMixBufClipTo##_aName((pSrc->i64LSample + pSrc->i64RSample) / 2); \
    421434            pSrc++; \
    422435        } \
     
    506519            int64_t iDstOffInt = pRate->dstOffset & UINT32_MAX; \
    507520            \
    508             samOut.i64LSample = (samLast.i64LSample * ((int64_t) UINT32_MAX - iDstOffInt) + samCur.i64LSample * iDstOffInt) >> 32; \
    509             samOut.i64RSample = (samLast.i64RSample * ((int64_t) UINT32_MAX - iDstOffInt) + samCur.i64RSample * iDstOffInt) >> 32; \
     521            samOut.i64LSample = (samLast.i64LSample * ((int64_t) (INT64_C(1) << 32) - iDstOffInt) + samCur.i64LSample * iDstOffInt) >> 32; \
     522            samOut.i64RSample = (samLast.i64RSample * ((int64_t) (INT64_C(1) << 32) - iDstOffInt) + samCur.i64RSample * iDstOffInt) >> 32; \
    510523            \
    511524            paDst->i64LSample _aOp samOut.i64LSample; \
     
    709722    /* Set initial volume to max. */
    710723    pMixBuf->Volume.fMuted = false;
    711     pMixBuf->Volume.uLeft  = 0x7FFFFFFF;
    712     pMixBuf->Volume.uRight = 0x7FFFFFFF;
     724    pMixBuf->Volume.uLeft  = VOL_0DB;
     725    pMixBuf->Volume.uRight = VOL_0DB;
    713726
    714727    /* Prevent division by zero.
     
    11961209
    11971210    pMixBuf->Volume.fMuted = pVol->fMuted;
    1198     pMixBuf->Volume.uLeft  = (UINT64_C(0x80000000) * pVol->uLeft) / 255;
    1199     pMixBuf->Volume.uRight = (UINT64_C(0x80000000) * pVol->uRight) / 255;
    12001211    //@todo: Ensure that the input is in the correct range/initialized!
    1201     pMixBuf->Volume.uLeft  = aVolumeConv[pVol->uLeft  & 0xFF] * UINT64_C(0x8000);
    1202     pMixBuf->Volume.uRight = aVolumeConv[pVol->uRight & 0xFF] * UINT64_C(0x8000);
     1212    pMixBuf->Volume.uLeft  = aVolumeConv[pVol->uLeft  & 0xFF] * UINT32_C(VOL_0DB >> 16);
     1213    pMixBuf->Volume.uRight = aVolumeConv[pVol->uRight & 0xFF] * UINT32_C(VOL_0DB >> 16);
    12031214
    12041215    LogFlowFunc(("\t-> lVol=%#RX32, rVol=%#RX32\n", pMixBuf->Volume.uLeft, pMixBuf->Volume.uRight));
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r55449 r55462  
    236236}
    237237
     238static int tstConversion(RTTEST hTest)
     239{
     240    unsigned        i;
     241    uint32_t        cBufSize = 256;
     242    PDMPCMPROPS     props;
     243
     244
     245    RTTestSubF(hTest, "Sample conversion");
     246
     247    PDMAUDIOSTREAMCFG cfg_p =
     248    {
     249        44100,                   /* Hz */
     250        1                        /* Channels */,
     251        AUD_FMT_S16              /* Format */,
     252        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
     253    };
     254
     255    int rc = drvAudioStreamCfgToProps(&cfg_p, &props);
     256    AssertRC(rc);
     257
     258    PDMAUDIOMIXBUF parent;
     259    RTTESTI_CHECK_RC_OK(audioMixBufInit(&parent, "Parent", &props, cBufSize));
     260
     261    /* Child uses half the sample rate; that ensures the mixing engine can't
     262     * take shortcuts and performs conversion. Because conversion to double
     263     * the sample rate effectively inserts one additional sample between every
     264     * two source samples, N source samples will be converted to N * 2 - 1
     265     * samples. However, the last source sample will be saved for later
     266     * interpolation and not immediately output.
     267     */
     268    PDMAUDIOSTREAMCFG cfg_c =   /* Upmixing to parent */
     269    {
     270        22050,                   /* Hz */
     271        1                        /* Channels */,
     272        AUD_FMT_S16              /* Format */,
     273        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
     274    };
     275
     276    rc = drvAudioStreamCfgToProps(&cfg_c, &props);
     277    AssertRC(rc);
     278
     279    PDMAUDIOMIXBUF child;
     280    RTTESTI_CHECK_RC_OK(audioMixBufInit(&child, "Child", &props, cBufSize));
     281    RTTESTI_CHECK_RC_OK(audioMixBufLinkTo(&child, &parent));
     282
     283    /*
     284     * Writing + mixing from child -> parent, sequential.
     285     */
     286    uint32_t cbBuf = 256;
     287    char pvBuf[256];
     288    int16_t samples[16] = { 0xAA, 0xBB, INT16_MIN, INT16_MIN + 1, INT16_MIN / 2, -3, -2, -1,
     289                            0, 1, 2, 3, INT16_MAX / 2, INT16_MAX - 1, INT16_MAX, 0 };
     290    uint32_t read, written, mixed, temp;
     291
     292    uint32_t cChildFree     = cBufSize;
     293    uint32_t cChildMixed    = 0;
     294    uint32_t cSamplesChild  = 16;
     295    uint32_t cSamplesParent = cSamplesChild * 2 - 2;
     296    uint32_t cSamplesRead   = 0;
     297
     298    RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Conversion test %uHz %uch\n", cfg_c.uHz, cfg_c.cChannels);
     299    RTTESTI_CHECK_RC_OK(audioMixBufWriteAt(&child, 0, &samples, sizeof(samples), &written));
     300    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
     301    RTTESTI_CHECK_RC_OK(audioMixBufMixToParent(&child, written, &mixed));
     302    temp = audioMixBufProcessed(&parent);
     303    RTTESTI_CHECK_MSG(audioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", audioMixBufMixed(&child), temp));
     304
     305    RTTESTI_CHECK(audioMixBufProcessed(&parent) == audioMixBufMixed(&child));
     306
     307    for (;;)
     308    {
     309        RTTESTI_CHECK_RC_OK_BREAK(audioMixBufReadCirc(&parent, pvBuf, cbBuf, &read));
     310        if (!read)
     311            break;
     312        cSamplesRead += read;
     313        audioMixBufFinish(&parent, read);
     314    }
     315    RTTESTI_CHECK_MSG(cSamplesRead == cSamplesParent, ("Parent: Expected %RU32 mixed samples, got %RU32\n", cSamplesParent, cSamplesRead));
     316
     317    /* Check that the samples came out unharmed. Every other sample is interpolated and we ignore it. */
     318    int16_t *pSrc16 = &samples[0];
     319    int16_t *pDst16 = (int16_t *)pvBuf;
     320
     321    for (i = 0; i < cSamplesChild; ++i)
     322    {
     323        RTTESTI_CHECK_MSG(*pSrc16 == *pDst16, ("index %u: Dst=%d, Src=%d\n", i, *pDst16, *pSrc16));
     324        pSrc16 += 1;
     325        pDst16 += 2;
     326    }
     327
     328    RTTESTI_CHECK(audioMixBufProcessed(&parent) == 0);
     329    RTTESTI_CHECK(audioMixBufMixed(&child) == 0);
     330
     331    return RTTestSubErrorCount(hTest) ? VERR_GENERAL_FAILURE : VINF_SUCCESS;
     332}
     333
    238334int main(int argc, char **argv)
    239335{
     
    252348    if (RT_SUCCESS(rc))
    253349        rc = tstParentChild(hTest);
     350    if (RT_SUCCESS(rc))
     351        rc = tstConversion(hTest);
    254352
    255353    /*
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