VirtualBox

Changeset 88112 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 12, 2021 8:41:05 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143255
Message:

Audio,DevHDA: Made PDMAUDIOPCMPROPS_F2B and PDMAUDIOPCMPROPS_B2F work for 5.1 and other frame sizes that aren't a power of two. Rewrote hdaR3StreamDoDmaOutput. Mapping is now done using converter functions rather than the complexity in hdaR3StreamTransfer. Probably fixes some recent goofs in the DMA period heuristics for non-stereo guest streams, I've renamed the members to make it clear what's what. bugref:9890

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

Legend:

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

    r88094 r88112  
    52005200                               "The stream frequency.",                     "Stream%u/Cfg/Hz", idxStream);
    52015201        PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.Cfg.Props.cChannels, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_BYTES,
    5202                                "The number of channels.",                   "Stream%u/Cfg/Channels", idxStream);
     5202                               "The number of channels.",                   "Stream%u/Cfg/Channels-Host", idxStream);
     5203        PDMDevHlpSTAMRegisterF(pDevIns, &pThisCC->aStreams[idxStream].State.Mapping.GuestProps.cChannels, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_BYTES,
     5204                               "The number of channels.",                   "Stream%u/Cfg/Channels-Guest", idxStream);
    52035205        PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aStreams[idxStream].State.Cfg.Props.cbSample, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_BYTES,
    52045206                               "The size of a sample (per channel).",       "Stream%u/Cfg/cbSample", idxStream);
  • trunk/src/VBox/Devices/Audio/HDAStream.cpp

    r88097 r88112  
    265265    }
    266266
    267     PDMAUDIOPCMPROPS Props;
    268     int rc = hdaR3SDFMTToPCMProps(u16FMT, &Props);
     267    PDMAUDIOPCMPROPS HostProps;
     268    int rc = hdaR3SDFMTToPCMProps(u16FMT, &HostProps);
    269269    if (RT_FAILURE(rc))
    270270    {
     
    272272        return rc;
    273273    }
    274 
    275     /* Reset (any former) stream map. */
    276     hdaR3StreamMapReset(&pStreamR3->State.Mapping);
    277274
    278275    /*
     
    284281     * number of channels in a single audio stream.
    285282     */
    286     rc = hdaR3StreamMapInit(&pStreamR3->State.Mapping, &Props);
     283    /** @todo r=bird: this is not done at the wrong time.  We don't have the host
     284     * output side set up yet, so we cannot really do proper mapping setup.
     285     * However, we really need this further down when we configure the internal DMA
     286     * buffer size.  For now we just assume it's all stereo on the host side.
     287     * This is not compatible with microphone support. */
     288# ifdef VBOX_WITH_AUDIO_HDA_MIC_IN
     289#  error "Implement me!"
     290# endif
     291    rc = hdaR3StreamMapInit(&pStreamR3->State.Mapping, 2 /*cHostChannels*/, &HostProps);
    287292    AssertRCReturn(rc, rc);
    288293
    289     ASSERT_GUEST_LOGREL_MSG_RETURN(   pStreamR3->State.Mapping.cbFrameSize > 0
    290                                    && u32CBL % pStreamR3->State.Mapping.cbFrameSize == 0,
     294    ASSERT_GUEST_LOGREL_MSG_RETURN(   pStreamR3->State.Mapping.cbGuestFrame > 0
     295                                   && u32CBL % pStreamR3->State.Mapping.cbGuestFrame == 0,
    291296                                   ("CBL for stream #%RU8 does not align to frame size (u32CBL=%u cbFrameSize=%u)\n",
    292                                     uSD, u32CBL, pStreamR3->State.Mapping.cbFrameSize),
     297                                    uSD, u32CBL, pStreamR3->State.Mapping.cbGuestFrame),
    293298                                   VERR_INVALID_PARAMETER);
    294 
    295 #ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
    296     if (Props.cChannels > 2)
    297     {
    298         /*
    299          * When not running with surround support enabled, override the audio channel count
    300          * with stereo (2) channels so that we at least can properly work with those.
    301          *
    302          * Note: This also involves dealing with surround setups the guest might has set up for us.
    303          */
    304         LogRelMax(32, ("HDA: Warning: More than stereo (2) channels are not supported (%RU8 requested), falling back to stereo channels for stream #%RU8\n",
    305                        Props.cChannels, uSD));
    306         Props.cChannels = 2;
    307         Props.cShift    = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(Props.cbSample, Props.cChannels);
    308     }
    309 #endif
    310299
    311300    /* Make sure the guest behaves regarding the stream's FIFO. */
     
    325314
    326315    PPDMAUDIOSTREAMCFG pCfg = &pStreamShared->State.Cfg;
    327     pCfg->Props = Props;
     316    pCfg->Props = HostProps;
    328317
    329318    /* Set the stream's direction. */
     
    344333
    345334        case PDMAUDIODIR_OUT:
    346             /* Destination(s) will be set in hdaAddStreamOut(),
     335            /* Destination(s) will be set in hdaR3AddStreamOut(),
    347336             * based on the channels / stream layout. */
    348337            break;
     
    355344    LogRel2(("HDA: Stream #%RU8 DMA @ 0x%x (%RU32 bytes = %RU64ms total)\n",
    356345             uSD, pStreamShared->u64BDLBase, pStreamShared->u32CBL,
    357              PDMAudioPropsBytesToMilli(&pStreamR3->State.Mapping.PCMProps, pStreamShared->u32CBL)));
     346             PDMAudioPropsBytesToMilli(&pStreamR3->State.Mapping.GuestProps, pStreamShared->u32CBL)));
    358347
    359348    /* Figure out how many transfer fragments we're going to use for this stream. */
     
    396385#ifdef VBOX_WITH_INTEL_HDA
    397386            /* Intel ICH / PCH: 1 frame. */
    398             if (BDLE.Desc.u32BufSize == (uint32_t)(1 * pStreamR3->State.Mapping.cbFrameSize))
     387            if (BDLE.Desc.u32BufSize == (uint32_t)(1 * pStreamR3->State.Mapping.cbGuestFrame))
    399388            {
    400389                cfPosAdjust = 1;
    401390            }
    402391            /* Intel Baytrail / Braswell: 32 frames. */
    403             else if (BDLE.Desc.u32BufSize == (uint32_t)(32 * pStreamR3->State.Mapping.cbFrameSize))
     392            else if (BDLE.Desc.u32BufSize == (uint32_t)(32 * pStreamR3->State.Mapping.cbGuestFrame))
    404393            {
    405394                cfPosAdjust = 32;
     
    422411             * position adjustment.
    423412             */
    424             if ((cfPosAdjust * pStreamR3->State.Mapping.cbFrameSize) == BDLE.Desc.u32BufSize)
     413            if ((cfPosAdjust * pStreamR3->State.Mapping.cbGuestFrame) == BDLE.Desc.u32BufSize)
    425414                cTransferFragments--;
    426415
     
    457446
    458447    /* Audio data per second the stream needs. */
    459     const uint32_t cbDataPerSec = PDMAudioPropsMilliToBytes(&pStreamR3->State.Mapping.PCMProps, RT_MS_1SEC);
     448    const uint32_t cbDataPerSec = PDMAudioPropsMilliToBytes(&pStreamR3->State.Mapping.GuestProps, RT_MS_1SEC);
    460449
    461450    /* This is used to indicate whether we're done or should the uTimerIoHz as fallback. */
     
    469458    unsigned uTransferHz = pStreamShared->State.uTimerIoHz;
    470459
    471     LogRel2(("HDA: Stream #%RU8 needs %RU32 bytes/s audio data\n", uSD, cbDataPerSec));
     460    LogRel2(("HDA: Stream #%RU8 needs %RU32 bytes/s audio data (from the guest).\n", uSD, cbDataPerSec));
    472461
    473462    if (pThis->fTransferHeuristicsEnabled) /* Are data transfer heuristics enabled? */
    474463    {
    475464        /* Don't take frames (as bytes) into account which are part of the position adjustment. */
    476         uint32_t cbTransferHeuristicsPosAdjust = pStreamShared->State.cfPosAdjustDefault * pStreamR3->State.Mapping.cbFrameSize;
     465        uint32_t cbTransferHeuristicsPosAdjust = pStreamShared->State.cfPosAdjustDefault * pStreamR3->State.Mapping.cbGuestFrame;
    477466        uint32_t cbTransferHeuristics          = 0;
    478467        uint32_t cbTransferHeuristicsCur       = 0;
     
    533522        if (cbTransferHeuristics >= 8)
    534523        {
    535             ASSERT_GUEST_LOGREL_MSG(PDMAudioPropsIsSizeAligned(&pStreamR3->State.Mapping.PCMProps, cbTransferHeuristics),
     524            ASSERT_GUEST_LOGREL_MSG(PDMAudioPropsIsSizeAligned(&pStreamR3->State.Mapping.GuestProps, cbTransferHeuristics),
    536525                                    ("We arrived at a misaligned transfer size for stream #%RU8: %#x (%u)\n",
    537526                                     uSD, cbTransferHeuristics, cbTransferHeuristics));
    538527
    539528            uint64_t const cTimerTicksPerSec = PDMDevHlpTimerGetFreq(pDevIns, pStreamShared->hTimer);
    540             uint64_t const cbTransferPerSec  = RT_MAX(pStreamR3->State.Mapping.PCMProps.uHz * pStreamR3->State.Mapping.cbFrameSize,
     529
     530            /* Convert the heuristics value to host side bytes and that's what we're calculating. */
     531            cbTransferHeuristics = PDMAudioPropsBytesToFrames(&pStreamR3->State.Mapping.GuestProps, cbTransferHeuristics);
     532            cbTransferHeuristics = PDMAudioPropsFramesToBytes(&pCfg->Props, cbTransferHeuristics);
     533
     534            uint64_t const cbTransferPerSec  = RT_MAX(PDMAudioPropsFramesToBytes(&pCfg->Props, pCfg->Props.uHz),
    541535                                                      4096 /* zero div prevention: min is 6kHz, picked 4k in case I'm mistaken */);
    542536
     
    545539               halve the buffer till we get there. */
    546540            while (cbTransferHeuristics > 1024 && cbTransferHeuristics > cbTransferPerSec / 4)
    547                 cbTransferHeuristics = PDMAudioPropsFloorBytesToFrame(&pStreamR3->State.Mapping.PCMProps, cbTransferHeuristics / 2);
     541                cbTransferHeuristics = PDMAudioPropsFloorBytesToFrame(&pCfg->Props, cbTransferHeuristics / 2);
    548542
    549543            /* Set the transfer size per timer callout. (No chunking, so same.) */
    550544            pStreamShared->State.cbTransferSize  = cbTransferHeuristics;
    551545            pStreamShared->State.cbTransferChunk = cbTransferHeuristics;
    552             ASSERT_GUEST_LOGREL_MSG(PDMAudioPropsIsSizeAligned(&pStreamR3->State.Mapping.PCMProps, cbTransferHeuristics),
     546            ASSERT_GUEST_LOGREL_MSG(PDMAudioPropsIsSizeAligned(&pCfg->Props, cbTransferHeuristics),
    553547                                    ("We arrived at a misaligned transfer size for stream #%RU8: %#x (%u)\n",
    554548                                     uSD, cbTransferHeuristics, cbTransferHeuristics));
     
    594588                                     uTransferHz = HDA_TIMER_HZ_DEFAULT);
    595589
    596         pStreamShared->State.cbTransferSize = (pStreamR3->State.Mapping.PCMProps.uHz * pStreamR3->State.Mapping.cbFrameSize)
     590        pStreamShared->State.cbTransferSize = (pStreamR3->State.Mapping.GuestProps.uHz * pStreamR3->State.Mapping.cbGuestFrame)
    597591                                            / uTransferHz;
    598592        ASSERT_GUEST_LOGREL_MSG_STMT(pStreamShared->State.cbTransferSize,
     
    641635
    642636                LogRel2(("HDA: Stream #%RU8 is using %uHz I/O timer (%RU64 virtual ticks / Hz), stream Hz=%RU32, cTicksPerByte=%RU64, cTransferTicks=%RU64 -> cbTransferChunk=%RU32 (%RU64ms), cbTransferSize=%RU32 (%RU64ms)\n",
    643                          uSD, pStreamShared->State.uTimerIoHz, (uint64_t)cTicksPerHz, pStreamR3->State.Mapping.PCMProps.uHz,
     637                         uSD, pStreamShared->State.uTimerIoHz, (uint64_t)cTicksPerHz, pStreamR3->State.Mapping.GuestProps.uHz,
    644638                         pStreamShared->State.cTicksPerByte, pStreamShared->State.cTransferTicks,
    645                          pStreamShared->State.cbTransferChunk, PDMAudioPropsBytesToMilli(&pStreamR3->State.Mapping.PCMProps, pStreamShared->State.cbTransferChunk),
    646                          pStreamShared->State.cbTransferSize,  PDMAudioPropsBytesToMilli(&pStreamR3->State.Mapping.PCMProps, pStreamShared->State.cbTransferSize)));
     639                         pStreamShared->State.cbTransferChunk, PDMAudioPropsBytesToMilli(&pStreamR3->State.Mapping.GuestProps, pStreamShared->State.cbTransferChunk),
     640                         pStreamShared->State.cbTransferSize,  PDMAudioPropsBytesToMilli(&pStreamR3->State.Mapping.GuestProps, pStreamShared->State.cbTransferSize)));
    647641            }
    648642        }
     
    979973 * @param   pDevIns             The device instance.
    980974 * @param   pThis               The shared HDA device state.
    981  * @param   uToAdd              Position (in bytes) to add to the current read / write position.
    982  */
    983 void hdaR3StreamSetPositionAdd(PHDASTREAM pStreamShared, PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t uToAdd)
    984 {
    985     if (!uToAdd) /* No need to update anything if 0. */
    986         return;
    987 
    988     hdaR3StreamSetPositionAbs(pStreamShared, pDevIns, pThis,
    989                               (HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD) + uToAdd) % pStreamShared->u32CBL);
     975 * @param   cbToAdd             Position (in bytes) to add to the current read / write position.
     976 */
     977void hdaR3StreamSetPositionAdd(PHDASTREAM pStreamShared, PPDMDEVINS pDevIns, PHDASTATE pThis, uint32_t cbToAdd)
     978{
     979    if (cbToAdd) /* No need to update anything if 0. */
     980    {
     981        uint32_t const uCBL = pStreamShared->u32CBL;
     982        if (uCBL) /* paranoia */
     983            hdaR3StreamSetPositionAbs(pStreamShared, pDevIns, pThis,
     984                                      (HDA_STREAM_REG(pThis, LPIB, pStreamShared->u8SD) + cbToAdd) % uCBL);
     985    }
    990986}
    991987
     
    12961292         * make sure that we process them first as a whole. */
    12971293        if (pStreamShared->State.cfPosAdjustLeft)
    1298             cbChunk = RT_MIN(cbChunk, (uint32_t)pStreamShared->State.cfPosAdjustLeft * pStreamR3->State.Mapping.cbFrameSize);
     1294            cbChunk = RT_MIN(cbChunk, (uint32_t)pStreamShared->State.cfPosAdjustLeft * pStreamR3->State.Mapping.cbGuestFrame);
    12991295
    13001296        if (!cbChunk)
     
    13681364                 * Only macOS guests need the frame extraction branch below at the moment AFAIK.
    13691365                 */
    1370                 if (pStreamR3->State.Mapping.cbFrameSize == HDA_FRAME_SIZE_DEFAULT)
     1366                if (pStreamR3->State.Mapping.cbGuestFrame == HDA_FRAME_SIZE_DEFAULT)
    13711367                {
    13721368                    uint32_t cbDMARead = 0;
     
    14101406                    for (unsigned m = 0; m < pStreamR3->State.Mapping.cMappings; m++)
    14111407                    {
    1412                         const uint32_t cbFrame  = pStreamR3->State.Mapping.cbFrameSize;
     1408                        const uint32_t cbFrame  = pStreamR3->State.Mapping.cbGuestFrame;
    14131409
    14141410                        Assert(cbFree >= cbDMA);
     
    15461542                           + hdaR3StreamPeriodFramesToWalClk(pPeriod,
    15471543                                                               pBDLE->Desc.u32BufSize
    1548                                                              / pStreamR3->State.Mapping.cbFrameSize),
     1544                                                             / pStreamR3->State.Mapping.cbGuestFrame),
    15491545                           false /* fForce */);
    15501546
     
    16191615        /* Do the position adjustment accounting. */
    16201616        pStreamShared->State.cfPosAdjustLeft -=
    1621             RT_MIN(pStreamShared->State.cfPosAdjustLeft, cbDMA / pStreamR3->State.Mapping.cbFrameSize);
     1617            RT_MIN(pStreamShared->State.cfPosAdjustLeft, cbDMA / pStreamR3->State.Mapping.cbGuestFrame);
    16221618
    16231619        if (RT_FAILURE(rc))
     
    16361632    if (pStreamShared->State.cfPosAdjustLeft == 0)
    16371633    {
    1638         hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStreamR3->State.Mapping.cbFrameSize,
     1634        hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStreamR3->State.Mapping.cbGuestFrame,
    16391635                                             hdaR3StreamPeriodGetRemainingFrames(pPeriod)));
    16401636    }
     
    16591655                                                      + hdaR3StreamPeriodFramesToWalClk(pPeriod,
    16601656                                                                                          cbProcessed
    1661                                                                                         / pStreamR3->State.Mapping.cbFrameSize),
     1657                                                                                        / pStreamR3->State.Mapping.cbGuestFrame),
    16621658                                                      hdaR3WalClkGetMax(pThis, pThisCC)),
    16631659                                               false /* fForce */);
     
    17001696 * @param   pStreamShared       HDA stream to update (shared).
    17011697 * @param   pStreamR3           HDA stream to update (ring-3).
    1702  * @param   cbToProcessMax      How much data (in bytes) to process as maximum.
    1703  *                              Caller should already have made sure this is at
    1704  *                              least one
     1698 * @param   cbToProduce         The max amount of data to produce (i.e. put into
     1699 *                              the circular buffer).  (Caller should already
     1700 *                              have made sure this is at least the size of one
     1701 *                              DMA timer period, so this function doesn't need
     1702 *                              to do any extra underflow handling.)
     1703 * @param   tsNowNs             The current RTTimeNano() value.
     1704 *
    17051705 * @remarks Caller owns the stream lock.
    17061706 */
    17071707static int hdaR3StreamDoDmaOutput(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamShared,
    1708                                   PHDASTREAMR3 pStreamR3, uint32_t cbToProcessMax, uint64_t tsNowNs)
     1708                                  PHDASTREAMR3 pStreamR3, uint32_t cbToProduce, uint64_t tsNowNs)
    17091709{
    17101710    PHDASTREAMPERIOD const  pPeriod = &pStreamShared->State.Period;
    17111711    uint8_t const           uSD     = pStreamShared->u8SD;
    1712     LogFlowFunc(("ENTER - #%u cbToProcessMax=%#x\n", uSD, cbToProcessMax));
     1712    LogFlowFunc(("ENTER - #%u cbToProduce=%#x\n", uSD, cbToProduce));
    17131713
    17141714
     
    17781778     * of buffer available.   We will not transfer more than that.
    17791779     */
     1780    uint8_t cSuppressIocs = 0;
    17801781    Assert(pStreamShared->State.cbTransferChunk == pStreamShared->State.cbTransferSize);
    1781     Assert(cbToProcessMax >= pStreamShared->State.cbTransferSize);
    1782     if (cbToProcessMax > pStreamShared->State.cbTransferSize)
    1783         cbToProcessMax = pStreamShared->State.cbTransferSize;
    1784     uint32_t cbLeft = cbToProcessMax;
     1782    if (!pStreamShared->State.cfPosAdjustLeft)
     1783    {
     1784        Assert(cbToProduce >= pStreamShared->State.cbTransferSize);
     1785        if (cbToProduce > pStreamShared->State.cbTransferSize)
     1786            cbToProduce = pStreamShared->State.cbTransferSize;
     1787    }
     1788    else
     1789    {
     1790        /* We currently process the position adjustment BLDE0 and the whole BLDE1
     1791           in one DMA timer callout, ignoring BLDE0.IOC. */
     1792        /** @todo Process the tiny BLDE0 seperatly. */
     1793        uint32_t const cbPosAdjust = PDMAudioPropsFramesToBytes(&pStreamShared->State.Cfg.Props,
     1794                                                                pStreamShared->State.cfPosAdjustLeft);
     1795        Assert(cbToProduce >= pStreamShared->State.cbTransferSize + cbPosAdjust);
     1796        if (cbToProduce >= pStreamShared->State.cbTransferSize + cbPosAdjust)
     1797        {
     1798            cbToProduce = pStreamShared->State.cbTransferSize + cbPosAdjust;
     1799            pStreamShared->State.cfPosAdjustLeft = 0;
     1800            cSuppressIocs = pBDLE->Desc.fFlags & HDA_BDLE_F_IOC ? 1 : 0;
     1801        }
     1802        else
     1803            pStreamShared->State.cfPosAdjustLeft -= PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props, cbToProduce);
     1804    }
     1805    uint32_t cbLeft = cbToProduce;
     1806    Assert(PDMAudioPropsIsSizeAligned(&pStreamShared->State.Cfg.Props, cbLeft));
    17851807
    17861808    /*
     
    17961818     *        Unless the buffers are really small, this is stuff that won't happen
    17971819     *        on real hardware.  */
    1798     /** @todo Disallow non-heuristics approach!  It only complicates the code. */
     1820    /** @todo Disallow non-heuristics approach!  It only complicates the code
     1821     *        and messes with the guest if we cover more than one IOC! */
    17991822    bool fInterruptSent = false;
    18001823
     
    18071830    HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_FIFORDY;
    18081831
    1809     while (cbLeft)
    1810     {
    1811         /* Limit the chunk to the stream's FIFO size and what's left to process. */
    1812         uint32_t cbChunk = RT_MIN(cbLeft, pStreamShared->u8FIFOS);
    1813 
    1814         /* Limit the chunk to the remaining data of the current BDLE. */
    1815         cbChunk = RT_MIN(cbChunk, pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff);
    1816 
    1817         /* If there are position adjustment frames left to be processed,
    1818          * make sure that we process them first as a whole. */
    1819         if (pStreamShared->State.cfPosAdjustLeft)
    1820             cbChunk = RT_MIN(cbChunk, (uint32_t)pStreamShared->State.cfPosAdjustLeft * pStreamR3->State.Mapping.cbFrameSize);
    1821 
    1822         /** @todo wtf is this for? Move on to the next BDLE! */
    1823         if (!cbChunk)
    1824             break;
    1825 
    1826         uint32_t   cbDMA    = 0;
    1827         PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf;
    1828         uint8_t   *pabFIFO  = pStreamShared->abFIFO;
    1829 
     1832    /*
     1833     *
     1834     * The DMA copy loop.
     1835     *
     1836     */
     1837    uint8_t    abBounce[4096 + 128];    /* Most guest does at most 4KB BDLE. So, 4KB + space for a partial frame to reduce loops. */
     1838    uint32_t   cbBounce = 0;            /* in case of incomplete frames between buffer segments */
     1839    PRTCIRCBUF pCircBuf = pStreamR3->State.pCircBuf;
     1840    while (cbLeft > 0)
     1841    {
    18301842        STAM_PROFILE_START(&pThis->StatOut, a);
    18311843
    1832         rc = hdaR3DMARead(pDevIns, pThis, pStreamShared, pStreamR3, pabFIFO, cbChunk, &cbDMA /* pcbRead */);
    1833         if (RT_SUCCESS(rc))
     1844        /*
     1845         * Figure out how much we can read & write in this iteration.
     1846         */
     1847        uint32_t cbChunk = pBDLE->Desc.u32BufSize - pBDLE->State.u32BufOff;
     1848        AssertStmt(cbChunk <= pBDLE->Desc.u32BufSize, cbChunk = 0);
     1849
     1850        /* Need to diverge if the frame format differs.  */
     1851        if (   !pStreamR3->State.Mapping.fMappingNeeded
     1852            /** @todo && pStreamShared->State.fFrameAlignedBuffers */)
    18341853        {
    1835             /** @todo wtf? Caller passed us the RTCircBufFree value via cbToProcessMax.   */
    1836             const uint32_t cbFree = (uint32_t)RTCircBufFree(pCircBuf);
     1854            if (cbChunk <= cbLeft)
     1855            { /* very likely */ }
     1856            else
     1857                cbChunk = cbLeft;
    18371858
    18381859            /*
    1839              * Most guests don't use different stream frame sizes than
    1840              * the default one, so save a bit of CPU time and don't go into
    1841              * the frame extraction code below.
    1842              *
    1843              * Only macOS guests need the frame extraction branch below at the moment AFAIK.
     1860             * Read the guest data directly into the internal DMA buffer.
    18441861             */
    1845             if (pStreamR3->State.Mapping.cbFrameSize == HDA_FRAME_SIZE_DEFAULT)
     1862            RTGCPHYS GCPhys = pBDLE->Desc.u64BufAddr + pBDLE->State.u32BufOff;
     1863            while (cbChunk > 0)
    18461864            {
    1847                 uint32_t cbDMARead = 0;
    1848                 uint32_t cbDMALeft = RT_MIN(cbDMA, cbFree);
    1849 
    1850                 while (cbDMALeft)
    1851                 {
    1852                     void *pvBuf; size_t cbBuf;
    1853                     RTCircBufAcquireWriteBlock(pCircBuf, cbDMALeft, &pvBuf, &cbBuf);
    1854 
    1855                     if (cbBuf)
    1856                     {
    1857                         memcpy(pvBuf, pabFIFO + cbDMARead, cbBuf);
    1858                         cbDMARead += (uint32_t)cbBuf;
    1859                         cbDMALeft -= (uint32_t)cbBuf;
    1860 #ifdef VBOX_WITH_DTRACE
    1861                         VBOXDD_HDA_STREAM_DMA_OUT((uint32_t)uSD, (uint32_t)cbBuf, pStreamR3->State.offWrite);
    1862 #endif
    1863                         pStreamR3->State.offWrite += cbBuf;
    1864                     }
    1865 
    1866                     RTCircBufReleaseWriteBlock(pCircBuf, cbBuf);
    1867                 }
    1868             }
    1869             else
    1870             {
    1871                 /*
    1872                  * The following code extracts the required audio stream (channel) data
    1873                  * of non-interleaved *and* interleaved audio streams.
    1874                  *
    1875                  * We by default only support 2 channels with 16-bit samples (HDA_FRAME_SIZE),
    1876                  * but an HDA audio stream can have interleaved audio data of multiple audio
    1877                  * channels in such a single stream ("AA,AA,AA vs. AA,BB,AA,BB").
    1878                  *
    1879                  * So take this into account by just handling the first channel in such a stream ("A")
    1880                  * and just discard the other channel's data.
    1881                  *
    1882                  * I know, the following code is horribly slow, but seems to work for now.
    1883                  */
    1884                 /** @todo Optimize channel data extraction! Use some SSE(3) / intrinsics? */
    1885                 for (unsigned m = 0; m < pStreamR3->State.Mapping.cMappings; m++)
    1886                 {
    1887                     const uint32_t cbFrame  = pStreamR3->State.Mapping.cbFrameSize;
    1888 
    1889                     Assert(cbFree >= cbDMA);
    1890 
    1891                     PPDMAUDIOSTREAMMAP pMap = &pStreamR3->State.Mapping.paMappings[m];
    1892                     AssertPtr(pMap);
    1893 
    1894                     Log3Func(("Mapping #%u: Start (cbDMA=%RU32, cbFrame=%RU32, offNext=%RU32)\n",
    1895                               m, cbDMA, cbFrame, pMap->offNext));
    1896 
    1897 
    1898                     /* Skip the current DMA chunk if the chunk is smaller than what the current stream mapping needs to read
    1899                      * the next associated frame (pointed to at pMap->cbOff).
    1900                      *
    1901                      * This can happen if the guest did not come up with enough data within a certain time period, especially
    1902                      * when using multi-channel speaker (> 2 channels [stereo]) setups. */
    1903                     if (pMap->offNext > cbChunk)
    1904                     {
    1905                         Log2Func(("Mapping #%u: Skipped (cbChunk=%RU32, cbMapOff=%RU32)\n", m, cbChunk, pMap->offNext));
    1906                         continue;
    1907                     }
    1908 
    1909                     uint8_t *pbSrcBuf = pabFIFO;
    1910                     size_t cbSrcOff   = pMap->offNext;
    1911 
    1912                     for (unsigned i = 0; i < cbDMA / cbFrame; i++)
    1913                     {
    1914                         void *pvDstBuf; size_t cbDstBuf;
    1915                         RTCircBufAcquireWriteBlock(pCircBuf, pMap->cbStep, &pvDstBuf, &cbDstBuf);
    1916 
    1917                         Assert(cbDstBuf >= pMap->cbStep);
    1918 
    1919                         if (cbDstBuf)
    1920                         {
    1921                             Log3Func(("Mapping #%u: Frame #%02u:    cbStep=%u, offFirst=%u, offNext=%u, cbDstBuf=%u, cbSrcOff=%u\n",
    1922                                       m, i, pMap->cbStep, pMap->offFirst, pMap->offNext, cbDstBuf, cbSrcOff));
    1923 
    1924                             memcpy(pvDstBuf, pbSrcBuf + cbSrcOff, cbDstBuf);
    1925 
    1926 #if 0 /* Too slow, even for release builds, so disabled it. */
    1927                             if (pStreamR3->Dbg.Runtime.fEnabled)
    1928                                 DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileDMAMapped, pvDstBuf, cbDstBuf,
    1929                                                      0 /* fFlags */);
    1930 #endif
    1931                             Assert(cbSrcOff <= cbDMA);
    1932                             if (cbSrcOff + cbFrame + pMap->offFirst<= cbDMA)
    1933                                 cbSrcOff += cbFrame + pMap->offFirst;
    1934 
    1935 #ifdef VBOX_WITH_DTRACE
    1936                             VBOXDD_HDA_STREAM_DMA_OUT((uint32_t)uSD, (uint32_t)cbDstBuf, pStreamR3->State.offWrite);
    1937 #endif
    1938                             Log3Func(("Mapping #%u: Frame #%02u:    -> cbSrcOff=%zu\n", m, i, cbSrcOff));
    1939                             pStreamR3->State.offWrite += cbDstBuf;
    1940                         }
    1941 
    1942                         RTCircBufReleaseWriteBlock(pCircBuf, cbDstBuf);
    1943                     }
    1944 
    1945                     Log3Func(("Mapping #%u: End cbSize=%u, cbDMA=%RU32, cbSrcOff=%zu\n",
    1946                               m, pMap->cbStep, cbDMA, cbSrcOff));
    1947 
    1948                     Assert(cbSrcOff <= cbDMA);
    1949 
    1950                     const uint32_t cbSrcLeft = cbDMA - (uint32_t)cbSrcOff;
    1951                     if (cbSrcLeft)
    1952                     {
    1953                         Log3Func(("Mapping #%u: cbSrcLeft=%RU32\n", m, cbSrcLeft));
    1954 
    1955                         if (cbSrcLeft >= pMap->cbStep)
    1956                         {
    1957                             void *pvDstBuf; size_t cbDstBuf;
    1958                             RTCircBufAcquireWriteBlock(pCircBuf, pMap->cbStep, &pvDstBuf, &cbDstBuf);
    1959 
    1960                             Assert(cbDstBuf >= pMap->cbStep);
    1961 
    1962                             if (cbDstBuf)
    1963                             {
    1964                                 memcpy(pvDstBuf, pbSrcBuf + cbSrcOff, cbDstBuf);
    1965 #ifdef VBOX_WITH_DTRACE
    1966                                 VBOXDD_HDA_STREAM_DMA_OUT((uint32_t)uSD, (uint32_t)cbDstBuf, pStreamR3->State.offWrite);
    1967 #endif
    1968                                 pStreamR3->State.offWrite += cbDstBuf;
    1969                             }
    1970 
    1971                             RTCircBufReleaseWriteBlock(pCircBuf, cbDstBuf);
    1972                         }
    1973 
    1974                         Assert(pMap->cbFrame >= cbSrcLeft);
    1975                         pMap->offNext = pMap->cbFrame - cbSrcLeft;
    1976                     }
    1977                     else
    1978                         pMap->offNext = 0;
    1979 
    1980                     Log3Func(("Mapping #%u finish (cbSrcOff=%zu, offNext=%zu)\n", m, cbSrcOff, pMap->offNext));
    1981                 }
     1865                /* Grab internal DMA buffer space and read into it. */
     1866                void  *pvBufDst;
     1867                size_t cbBufDst;
     1868                RTCircBufAcquireWriteBlock(pCircBuf, cbChunk, &pvBufDst, &cbBufDst);
     1869                AssertBreakStmt(cbBufDst, RTCircBufReleaseWriteBlock(pCircBuf, 0));
     1870
     1871                int rc2 = PDMDevHlpPhysRead(pDevIns, GCPhys, pvBufDst, cbBufDst);
     1872                AssertRC(rc2);
     1873
     1874# ifdef HDA_DEBUG_SILENCE
     1875                fix me if relevant;
     1876# endif
     1877                if (RT_LIKELY(!pStreamR3->Dbg.Runtime.fEnabled))
     1878                { /* likely */ }
     1879                else
     1880                    DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileDMARaw, pvBufDst, cbBufDst, 0 /* fFlags */);
     1881
     1882                pStreamR3->State.offWrite += cbBufDst;
     1883                RTCircBufReleaseWriteBlock(pCircBuf, cbBufDst);
     1884                STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBufDst);
     1885
     1886                /* advance */
     1887                cbChunk                -= cbBufDst;
     1888                GCPhys                 += cbBufDst;
     1889                cbLeft                 -= cbBufDst;
     1890                pBDLE->State.u32BufOff += cbBufDst;
     1891                Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
    19821892            }
    19831893        }
     1894        /*
     1895         * Need to map the frame content, so we need to read the guest data
     1896         * into a temporary buffer, though the output can be directly written
     1897         * into the internal buffer as it is assumed to be frame aligned.
     1898         *
     1899         * Note! cbLeft is relative to the output frame size.
     1900         *       cbChunk OTOH is relative to input size.
     1901         */
    19841902        else
    1985             LogRel(("HDA: Reading from stream #%RU8 DMA failed with %Rrc\n", uSD, rc));
     1903        {
     1904            Assert(PDMAudioPropsIsSizeAligned(&pStreamShared->State.Cfg.Props, cbLeft));
     1905            uint32_t const cbLeftInput = PDMAudioPropsFramesToBytes(&pStreamR3->State.Mapping.GuestProps,
     1906                                                                    PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props,
     1907                                                                                               cbLeft));
     1908            if (cbChunk <= cbLeftInput)
     1909            { /* very likely */ }
     1910            else
     1911                cbChunk = cbLeftInput;
     1912
     1913            /*
     1914             * Loop till we've covered the chunk.
     1915             */
     1916            RTGCPHYS GCPhys = pBDLE->Desc.u64BufAddr + pBDLE->State.u32BufOff;
     1917            Log5Func(("loop0:  GCPhys=%RGp cbChunk=%#x + cbBounce=%#x\n", GCPhys, cbChunk, cbBounce));
     1918            while (cbChunk > 0)
     1919            {
     1920                /* Read into the bounce buffer. */
     1921                uint32_t const cbToRead = RT_MIN(cbChunk, sizeof(abBounce) - cbBounce);
     1922                int rc2 = PDMDevHlpPhysRead(pDevIns, GCPhys, &abBounce[cbBounce], cbToRead);
     1923                AssertRC(rc2);
     1924                cbBounce += cbToRead;
     1925
     1926                /* Convert the size to whole frames and a remainder. */
     1927                uint32_t cFrames = PDMAudioPropsBytesToFrames(&pStreamR3->State.Mapping.GuestProps, cbBounce);
     1928                uint32_t const cbRemainder = cbBounce - PDMAudioPropsFramesToBytes(&pStreamR3->State.Mapping.GuestProps, cFrames);
     1929                Log5Func((" loop1: GCPhys=%RGp cbToRead=%#x cbBounce=%#x cFrames=%#x\n", GCPhys, cbToRead, cbBounce, cFrames));
     1930
     1931                /*
     1932                 * Convert from the bounce buffer and into the internal DMA buffer.
     1933                 */
     1934                uint32_t offBounce = 0;
     1935                while (cFrames > 0)
     1936                {
     1937                    void  *pvBufDst;
     1938                    size_t cbBufDst;
     1939                    RTCircBufAcquireWriteBlock(pCircBuf, PDMAudioPropsFramesToBytes(&pStreamShared->State.Cfg.Props, cFrames),
     1940                                               &pvBufDst, &cbBufDst);
     1941
     1942                    uint32_t const cFramesToConvert = PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props, cbBufDst);
     1943                    Assert(PDMAudioPropsFramesToBytes(&pStreamShared->State.Cfg.Props, cFramesToConvert) == cbBufDst);
     1944                    Assert(cFramesToConvert > 0);
     1945                    Assert(cFramesToConvert <= cFrames);
     1946
     1947                    pStreamR3->State.Mapping.pfnGuestToHost(pvBufDst, &abBounce[offBounce], cFramesToConvert,
     1948                                                            &pStreamR3->State.Mapping);
     1949                    Log5Func(("  loop2: offBounce=%#05x cFramesToConvert=%#05x cbBufDst=%#x%s\n",
     1950                              offBounce, cFramesToConvert, cbBufDst, ASMMemIsZero(pvBufDst, cbBufDst) ? " all zero" : ""));
     1951
     1952# ifdef HDA_DEBUG_SILENCE
     1953                    fix me if relevant;
     1954# endif
     1955                    if (RT_LIKELY(!pStreamR3->Dbg.Runtime.fEnabled))
     1956                    { /* likely */ }
     1957                    else
     1958                        DrvAudioHlpFileWrite(pStreamR3->Dbg.Runtime.pFileDMARaw, pvBufDst, cbBufDst, 0 /* fFlags */);
     1959
     1960                    pStreamR3->State.offWrite += cbBufDst;
     1961                    RTCircBufReleaseWriteBlock(pCircBuf, cbBufDst);
     1962                    STAM_COUNTER_ADD(&pThis->StatBytesRead, cbBufDst);
     1963
     1964                    /* advance */
     1965                    cbLeft    -= cbBufDst;
     1966                    cFrames   -= cFramesToConvert;
     1967                    offBounce += PDMAudioPropsFramesToBytes(&pStreamR3->State.Mapping.GuestProps, cFramesToConvert);
     1968                }
     1969
     1970                /* advance */
     1971                cbChunk                -= cbToRead;
     1972                GCPhys                 += cbToRead;
     1973                pBDLE->State.u32BufOff += cbToRead;
     1974                Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
     1975                if (cbRemainder)
     1976                    memmove(&abBounce[0], &abBounce[cbBounce - cbRemainder], cbRemainder);
     1977                cbBounce = cbRemainder;
     1978            }
     1979            Log5Func(("loop0: GCPhys=%RGp cbBounce=%#x cbLeft=%#x\n", GCPhys, cbBounce, cbLeft));
     1980        }
    19861981
    19871982        STAM_PROFILE_STOP(&pThis->StatOut, a);
    1988 
    1989         if (cbDMA)
    1990         {
    1991             /* We always increment the position of DMA buffer counter because we're always reading
    1992              * into an intermediate DMA buffer. */
    1993             pBDLE->State.u32BufOff += (uint32_t)cbDMA;
    1994             Assert(pBDLE->State.u32BufOff <= pBDLE->Desc.u32BufSize);
    1995 
    1996             /* Are we done doing the position adjustment?
    1997              * Only then do the transfer accounting .*/
    1998             if (pStreamShared->State.cfPosAdjustLeft == 0)
    1999             {
    2000                 Assert(cbLeft >= cbDMA);
    2001                 cbLeft        -= cbDMA;
    2002             }
    2003 
    2004             Log3Func(("[SD%RU8] cbDMA=%RU32 -> %R[bdle]\n", uSD, cbDMA, pBDLE));
    2005         }
    20061983
    20071984        /*
     
    20141991            /* Make sure to also update the wall clock when a BDLE is complete.
    20151992             * Needed for Windows 10 guests. */
     1993            /** @todo there is a rounding error here.   */
    20161994            hdaR3WalClkSet(pThis, pThisCC,
    20171995                             hdaWalClkGetCurrent(pThis)
    20181996                           + hdaR3StreamPeriodFramesToWalClk(pPeriod,
    20191997                                                               pBDLE->Desc.u32BufSize
    2020                                                              / pStreamR3->State.Mapping.cbFrameSize),
     1998                                                             / pStreamR3->State.Mapping.cbGuestFrame),
    20211999                           false /* fForce */);
    20222000
     
    20332011
    20342012            /* Does the current BDLE require an interrupt to be sent? */
    2035             if (   hdaR3BDLENeedsInterrupt(pBDLE)
    2036                 /* Are we done doing the position adjustment?
    2037                  * It can happen that a BDLE which is handled while doing the
    2038                  * position adjustment requires an interrupt on completion (IOC) being set.
    2039                  *
    2040                  * In such a case we need to skip such an interrupt and just move on. */
    2041                 && pStreamShared->State.cfPosAdjustLeft == 0)
     2013            if (hdaR3BDLENeedsInterrupt(pBDLE))
    20422014            {
    2043                 /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL register is set
    2044                  * we need to generate an interrupt.
    2045                  */
    2046                 if (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_IOCE)
     2015                if (cSuppressIocs == 0)
    20472016                {
    2048                     /* Assert the interrupt before actually fetching the next BDLE below. */
    2049                     if (!fInterruptSent)
     2017                    /* If the IOCE ("Interrupt On Completion Enable") bit of the SDCTL
     2018                       register is set we need to generate an interrupt. */
     2019                    if (HDA_STREAM_REG(pThis, CTL, uSD) & HDA_SDCTL_IOCE)
    20502020                    {
    2051 #if 1
    2052                         pStreamShared->State.cTransferPendingInterrupts = 1;
    2053                         Log3Func(("[SD%RU8] Scheduling interrupt\n", uSD));
    2054 #else
    2055                         /* ??*/
    2056                         AssertMsg(pStreamShared->State.cTransferPendingInterrupts <= 32, ("Too many pending interrupts (%RU8) for stream #%RU8\n", pStreamShared->State.cTransferPendingInterrupts, uSD));
    2057                         Log3Func(("[SD%RU8] Scheduling interrupt (now %RU8 total)\n", uSD, pStreamShared->State.cTransferPendingInterrupts));
    2058 #endif
    2059 
    2060                         /*
    2061                          * Set the stream's BCIS bit.
    2062                          *
    2063                          * Note: This only must be done if the whole period is complete, and not if only
    2064                          * one specific BDL entry is complete (if it has the IOC bit set).
    2065                          *
    2066                          * This will otherwise confuses the guest when it 1) deasserts the interrupt,
    2067                          * 2) reads SDSTS (with BCIS set) and then 3) too early reads a (wrong) WALCLK value.
    2068                          *
    2069                          * snd_hda_intel on Linux will tell.
    2070                          */
    2071                         /** @todo r=bird: The above comment does not match what we're doing.  This is
    2072                          *        just a flag indicating that the IOC is why the driver got an IRQ. */
    2073                         HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_BCIS;
    2074 
    2075                         /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with
    2076                          * ending / beginning a period. */
    2077                         HDA_PROCESS_INTERRUPT(pDevIns, pThis);
    2078 
    2079                         fInterruptSent = true;
     2021                        /* Assert the interrupt before actually fetching the next BDLE below. */
     2022                        if (!fInterruptSent)
     2023                        {
     2024                            pStreamShared->State.cTransferPendingInterrupts = 1;
     2025                            Log3Func(("[SD%RU8] Scheduling interrupt\n", uSD));
     2026
     2027                            /* Trigger an interrupt first and let hdaRegWriteSDSTS() deal with
     2028                             * ending / beginning of a period. */
     2029                            /** @todo r=bird: What does the above comment mean? */
     2030                            HDA_STREAM_REG(pThis, STS, uSD) |= HDA_SDSTS_BCIS;
     2031                            HDA_PROCESS_INTERRUPT(pDevIns, pThis);
     2032                            fInterruptSent = true;
     2033                        }
    20802034                    }
    20812035                }
     2036                else
     2037                    cSuppressIocs--;
    20822038            }
    20832039
    20842040            /*
    2085              * Advance.
     2041             * Advance to the next BDLE.
    20862042             */
    20872043            if (pStreamShared->State.uCurBDLE >= pStreamShared->u16LVI)
     
    20892045            else
    20902046                pStreamShared->State.uCurBDLE++;
    2091 
    2092             /* Fetch the next BDLE entry. */
    20932047            hdaR3BDLEFetch(pDevIns, pBDLE, pStreamShared->u64BDLBase, pStreamShared->State.uCurBDLE);
    20942048        }
    2095 
    2096         /* Do the position adjustment accounting. */
    2097         pStreamShared->State.cfPosAdjustLeft -= RT_MIN(pStreamShared->State.cfPosAdjustLeft, cbDMA / pStreamR3->State.Mapping.cbFrameSize);
    2098 
    2099         if (RT_FAILURE(rc))
    2100             break;
    2101     }
    2102 
    2103     /* Remove the FIFORDY bit again. */
     2049        else
     2050            Log3Func(("[SD%RU8] Not complete %R[bdle]\n", uSD, pBDLE));
     2051    }
     2052
     2053    Assert(cbLeft == 0); /* There shall be no break statements in the above loop, so cbLeft is always zero here! */
     2054    AssertMsg(cbBounce == 0, ("%#x\n", cbBounce));
     2055
     2056    /*
     2057     * Clear the (pointless) FIFORDY bit again.
     2058     */
    21042059    HDA_STREAM_REG(pThis, STS, uSD) &= ~HDA_SDSTS_FIFORDY;
    21052060
    2106     /* Sanity. */
    2107     Assert(cbLeft == 0);
    2108     uint32_t const cbProcessed = cbToProcessMax - cbLeft;
    2109 
    2110     /* Only do the data accounting if we don't have to do any position
    2111      * adjustment anymore. */
    2112     if (pStreamShared->State.cfPosAdjustLeft == 0)
    2113     {
    2114         hdaR3StreamPeriodInc(pPeriod, RT_MIN(cbProcessed / pStreamR3->State.Mapping.cbFrameSize,
    2115                                              hdaR3StreamPeriodGetRemainingFrames(pPeriod)));
    2116     }
    2117 
    2118     const bool fTransferComplete = cbLeft == 0;
    2119     if (fTransferComplete)
    2120     {
    2121         /*
    2122          * Try updating the wall clock.
    2123          *
    2124          * Note 1) Only certain guests (like Linux' snd_hda_intel) rely on the WALCLK register
    2125          *         in order to determine the correct timing of the sound device. Other guests
    2126          *         like Windows 7 + 10 (or even more exotic ones like Haiku) will completely
    2127          *         ignore this.
    2128          *
    2129          * Note 2) When updating the WALCLK register too often / early (or even in a non-monotonic
    2130          *         fashion) this *will* upset guest device drivers and will completely fuck up the
    2131          *         sound output. Running VLC on the guest will tell!
    2132          */
    2133         const bool fWalClkSet = hdaR3WalClkSet(pThis, pThisCC,
    2134                                                RT_MIN(  hdaWalClkGetCurrent(pThis)
    2135                                                       + hdaR3StreamPeriodFramesToWalClk(pPeriod,
    2136                                                                                           cbProcessed
    2137                                                                                         / pStreamR3->State.Mapping.cbFrameSize),
    2138                                                       hdaR3WalClkGetMax(pThis, pThisCC)),
    2139                                                false /* fForce */);
    2140         RT_NOREF(fWalClkSet);
    2141     }
    2142 
    2143     Log3Func(("[SD%RU8] %R[bdle] -- %#RX32/%#RX32 @ %#RX64 - fTransferComplete=%d (%d) cTransferPendingInterrupts=%RU8\n",
    2144               uSD, pBDLE, cbProcessed, pStreamShared->State.cbTransferSize, pStreamR3->State.offWrite - cbProcessed,
    2145               fTransferComplete, cbLeft, pStreamShared->State.cTransferPendingInterrupts));
     2061    /*
     2062     * Try updating the wall clock.
     2063     *
     2064     * Note 1) Only certain guests (like Linux' snd_hda_intel) rely on the WALCLK register
     2065     *         in order to determine the correct timing of the sound device. Other guests
     2066     *         like Windows 7 + 10 (or even more exotic ones like Haiku) will completely
     2067     *         ignore this.
     2068     *
     2069     * Note 2) When updating the WALCLK register too often / early (or even in a non-monotonic
     2070     *         fashion) this *will* upset guest device drivers and will completely fuck up the
     2071     *         sound output. Running VLC on the guest will tell!
     2072     */
     2073    uint32_t const cFramesProcessed = PDMAudioPropsBytesToFrames(&pStreamShared->State.Cfg.Props, cbToProduce);
     2074    /** @todo this needs to go, but we need it for hdaR3WalClkGetMax below. */
     2075    hdaR3StreamPeriodInc(&pStreamShared->State.Period,
     2076                         RT_MIN(cFramesProcessed, hdaR3StreamPeriodGetRemainingFrames(&pStreamShared->State.Period)));
     2077
     2078    uint64_t const cWallTicks = hdaR3StreamPeriodFramesToWalClk(pPeriod, cFramesProcessed);
     2079    uint64_t const uWallNew   = hdaWalClkGetCurrent(pThis) + cWallTicks;
     2080    uint64_t const uWallMax   = hdaR3WalClkGetMax(pThis, pThisCC);
     2081    bool const     fWalClkSet = hdaR3WalClkSet(pThis, pThisCC, RT_MIN(uWallNew, uWallMax), false /* fForce */);
     2082    RT_NOREF(fWalClkSet);
     2083
     2084    /*
     2085     * Log and leave.
     2086     */
     2087    Log3Func(("[SD%RU8] %R[bdle] -- %#RX32/%#RX32 @ %#RX64 - cTransferPendingInterrupts=%RU8\n",
     2088              uSD, pBDLE, cbToProduce, pStreamShared->State.cbTransferSize, pStreamR3->State.offWrite - cbToProduce,
     2089              pStreamShared->State.cTransferPendingInterrupts));
    21462090
    21472091    LogFlowFuncLeave();
     
    21642108    uint32_t       cbToReadFromStream = RT_MIN(cbStreamReadable, cbSinkWritable);
    21652109    /* Make sure that we always align the number of bytes when reading to the stream's PCM properties. */
    2166     cbToReadFromStream = PDMAudioPropsFloorBytesToFrame(&pStreamR3->State.Mapping.PCMProps, cbToReadFromStream);
     2110    cbToReadFromStream = PDMAudioPropsFloorBytesToFrame(&pStreamShared->State.Cfg.Props, cbToReadFromStream);
    21672111
    21682112    Assert(nsNow >= pStreamShared->State.tsLastReadNs);
     
    22052149
    22062150    /* Re-arm the timer if the sink is still active: */
    2207     if (   pStreamR3->pMixSink
     2151    if (   pStreamShared->State.fRunning
     2152        && pStreamR3->pMixSink
    22082153        && AudioMixerSinkIsActive(pStreamR3->pMixSink->pMixSink))
    22092154    {
  • trunk/src/VBox/Devices/Audio/HDAStream.h

    r88094 r88112  
    132132     *  Can be 0 if no next transfer is scheduled. */
    133133    uint64_t                tsTransferNext;
    134     /** Total transfer size (in bytes) of a transfer period. */
     134    /** Total transfer size (in bytes) of a transfer period.
     135     * @note This is in host side frames, in case we're doing any mapping. */
    135136    uint32_t                cbTransferSize;
    136     /** Transfer chunk size (in bytes) of a transfer period. */
     137    /** Unused, same as cbTransferSize. */
    137138    uint32_t                cbTransferChunk;
    138139    /** How many interrupts are pending due to
     
    157158    /** The stream's period. Need for timing. */
    158159    HDASTREAMPERIOD         Period;
    159     /** The stream's current configuration.
    160      *  Should match SDFMT. */
     160    /** The stream's current host side configuration.
     161     * This should match the SDnFMT in all respects but maybe the channel count as
     162     * we may need to expand mono or into/from into stereo.  The unmodified SDnFMT
     163     * properties can be found in HDASTREAMR3::Mapping::PCMProps. */
    161164    PDMAUDIOSTREAMCFG       Cfg;
    162165    /** Timestamp (real time, in ns) of last DMA transfer. */
  • trunk/src/VBox/Devices/Audio/HDAStreamMap.cpp

    r88028 r88112  
    2323#include <VBox/log.h>
    2424
    25 #include <iprt/mem.h>
    26 
    2725#include <VBox/vmm/pdmdev.h>
    2826#include <VBox/vmm/pdmaudioifs.h>
    2927#include <VBox/vmm/pdmaudioinline.h>
    3028
     29#include <iprt/mem.h>
     30#include <iprt/string.h>
     31
    3132#include "DrvAudio.h"
    3233
     
    3435#include "HDAStreamMap.h"
    3536
    36 #ifdef IN_RING3
    37 
    38 static int hdaR3StreamMapSetup(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps);
    39 
    40 /**
    41  * Initializes a stream mapping structure according to the given PCM properties.
    42  *
    43  * @return  IPRT status code.
    44  * @param   pMap                Pointer to mapping to initialize.
    45  * @param   pProps              Pointer to PCM properties to use for initialization.
    46  */
    47 int hdaR3StreamMapInit(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps)
    48 {
    49     AssertPtrReturn(pMap, VERR_INVALID_POINTER);
    50     AssertPtrReturn(pProps,   VERR_INVALID_POINTER);
    51 
    52     if (!DrvAudioHlpPcmPropsAreValid(pProps))
    53         return VERR_INVALID_PARAMETER;
    54 
    55     hdaR3StreamMapReset(pMap);
    56 
    57     int rc = hdaR3StreamMapSetup(pMap, pProps);
    58     if (RT_FAILURE(rc))
    59         return rc;
    60 
    61 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    62     if (   RT_SUCCESS(rc)
    63         /* Create circular buffer if not created yet. */
    64         && !pMap->pCircBuf)
    65     {
    66         rc = RTCircBufCreate(&pMap->pCircBuf, _4K); /** @todo Make size configurable? */
    67     }
    68 #endif
    69 
    70     if (RT_SUCCESS(rc))
    71     {
    72         pMap->cbFrameSize = pProps->cChannels * pProps->cbSample;
    73 
    74         LogFunc(("cChannels=%RU8, cBytes=%RU8 -> cbFrameSize=%RU32\n",
    75                  pProps->cChannels, pProps->cbSample, pMap->cbFrameSize));
    76 
    77         Assert(pMap->cbFrameSize); /* Frame size must not be 0. */
    78 
    79         pMap->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED;
    80     }
    81 
    82     return rc;
    83 }
    84 
    85 
    86 /**
    87  * Destroys a given stream mapping.
    88  *
    89  * @param   pMap            Pointer to mapping to destroy.
    90  */
    91 void hdaR3StreamMapDestroy(PHDASTREAMMAP pMap)
    92 {
    93     hdaR3StreamMapReset(pMap);
    94 
    95 #ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
    96     if (pMap->pCircBuf)
    97     {
    98         RTCircBufDestroy(pMap->pCircBuf);
    99         pMap->pCircBuf = NULL;
    100     }
    101 #endif
    102 }
    103 
    104 
    105 /**
    106  * Resets a given stream mapping.
    107  *
    108  * @param   pMap            Pointer to mapping to reset.
    109  */
    110 void hdaR3StreamMapReset(PHDASTREAMMAP pMap)
    111 {
    112     AssertPtrReturnVoid(pMap);
    113 
    114     pMap->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN;
    115 
    116     if (pMap->paMappings)
    117     {
    118         for (uint8_t i = 0; i < pMap->cMappings; i++)
    119             hdaR3StreamChannelDataDestroy(&pMap->paMappings[i].Data);
    120 
    121         RTMemFree(pMap->paMappings);
    122         pMap->paMappings = NULL;
    123 
    124         pMap->cMappings = 0;
    125     }
    126 
    127     RT_ZERO(pMap->PCMProps);
     37
     38
     39/** Convert host stereo to mono guest, signed 16-bit edition. */
     40static DECLCALLBACK(void)
     41hdaR3StreamMap_H2G_GenericS16_Stereo2Mono(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     42{
     43    /** @todo this doesn't merge the two, it just picks the first one. */
     44    uint16_t       *pu16Dst    = (uint16_t *)pvDst;
     45    uint16_t const *pu16Src    = (uint16_t const *)pvSrc;
     46    size_t const    cbDstFrame = pMap->cbGuestFrame;
     47
     48    if (cbDstFrame != sizeof(*pu16Dst))
     49        RT_BZERO(pvDst, cbDstFrame * cFrames);
     50
     51    while (cFrames-- > 0)
     52    {
     53        *pu16Dst = *pu16Src;
     54        pu16Src += 2;
     55        pu16Dst  = (uint16_t *)((uintptr_t)pu16Dst + cbDstFrame);
     56    }
     57}
     58
     59
     60/** Convert mono guest channel to host stereo, signed 16-bit edition. */
     61static DECLCALLBACK(void)
     62hdaR3StreamMap_G2H_GenericS16_Mono2Stereo(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     63{
     64    uint32_t       *pu32Dst    = (uint32_t *)pvDst;
     65    uint16_t const *pu16Src    = (uint16_t const *)pvSrc;
     66    size_t const    cbSrcFrame = pMap->cbGuestFrame;
     67
     68    while (cFrames-- > 0)
     69    {
     70        uint16_t uSample = *pu16Src;
     71        *pu32Dst++ = RT_MAKE_U32(uSample, uSample);
     72        pu16Src = (uint16_t const *)((uintptr_t)pu16Src + cbSrcFrame);
     73    }
     74}
     75
     76
     77/** Convert host stereo to mono guest, signed 32-bit edition. */
     78static DECLCALLBACK(void)
     79hdaR3StreamMap_H2G_GenericS32_Stereo2Mono(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     80{
     81    /** @todo this doesn't merge the two, it just picks the first one. */
     82    uint32_t       *pu32Dst    = (uint32_t *)pvDst;
     83    uint32_t const *pu32Src    = (uint32_t const *)pvSrc;
     84    size_t const    cbDstFrame = pMap->cbGuestFrame;
     85
     86    if (cbDstFrame != sizeof(*pu32Dst))
     87        RT_BZERO(pvDst, cbDstFrame * cFrames);
     88
     89    while (cFrames-- > 0)
     90    {
     91        *pu32Dst = *pu32Src;
     92        pu32Src += 2;
     93        pu32Dst  = (uint32_t *)((uintptr_t)pu32Dst + cbDstFrame);
     94    }
     95}
     96
     97
     98/** Convert mono guest channel to host stereo, signed 32-bit edition. */
     99static DECLCALLBACK(void)
     100hdaR3StreamMap_G2H_GenericS32_Mono2Stereo(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     101{
     102    uint64_t       *pu64Dst    = (uint64_t *)pvDst;
     103    uint32_t const *pu32Src    = (uint32_t const *)pvSrc;
     104    size_t const    cbSrcFrame = pMap->cbGuestFrame;
     105
     106    while (cFrames-- > 0)
     107    {
     108        uint32_t uSample = *pu32Src;
     109        *pu64Dst++ = RT_MAKE_U64(uSample, uSample);
     110        pu32Src = (uint32_t const *)((uintptr_t)pu32Src + cbSrcFrame);
     111    }
     112}
     113
     114
     115/** Convert stereo host to 2 or more guest channels, signed 16-bit edition. */
     116static DECLCALLBACK(void)
     117hdaR3StreamMap_H2G_GenericS16_Stereo2NonMono(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     118{
     119    uint32_t       *pu32Dst    = (uint32_t *)pvDst;
     120    uint32_t const *pu32Src    = (uint32_t const *)pvSrc; /** @todo could be misaligned */
     121    size_t const    cbDstFrame = pMap->cbGuestFrame;
     122
     123    RT_BZERO(pvDst, cbDstFrame * cFrames);
     124
     125    while (cFrames-- > 0)
     126    {
     127        *pu32Dst = *pu32Src++;
     128        pu32Dst = (uint32_t *)((uintptr_t)pu32Dst + cbDstFrame);
     129    }
     130}
     131
     132
     133/** Convert 2 or more guest channels to host stereo, signed 16-bit edition. */
     134static DECLCALLBACK(void)
     135hdaR3StreamMap_G2H_GenericS16_NonMono2Stereo(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     136{
     137    uint32_t       *pu32Dst    = (uint32_t *)pvDst;
     138    uint32_t const *pu32Src    = (uint32_t const *)pvSrc; /** @todo could be misaligned */
     139    size_t const    cbSrcFrame = pMap->cbGuestFrame;
     140
     141    while (cFrames-- > 0)
     142    {
     143        *pu32Dst++ = *pu32Src;
     144        pu32Src = (uint32_t const *)((uintptr_t)pu32Src + cbSrcFrame);
     145    }
     146}
     147
     148
     149/** Convert stereo host to 2 or more guest channels, signed 32-bit edition. */
     150static DECLCALLBACK(void)
     151hdaR3StreamMap_H2G_GenericS32_Stereo2NonMono(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     152{
     153    uint64_t       *pu64Dst    = (uint64_t *)pvDst;         /** @todo could be misaligned. */
     154    uint64_t const *pu64Src    = (uint64_t const *)pvSrc;
     155    size_t const    cbDstFrame = pMap->cbGuestFrame;
     156
     157    RT_BZERO(pvDst, cbDstFrame * cFrames);
     158
     159    while (cFrames-- > 0)
     160    {
     161        *pu64Dst = *pu64Src++;
     162        pu64Dst = (uint64_t *)((uintptr_t)pu64Dst + cbDstFrame);
     163    }
     164}
     165
     166
     167/** Convert 2 or more guest channels to host stereo, signed 32-bit edition. */
     168static DECLCALLBACK(void)
     169hdaR3StreamMap_G2H_GenericS32_NonMono2Stereo(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     170{
     171    uint64_t       *pu64Dst    = (uint64_t *)pvDst;
     172    uint64_t const *pu64Src    = (uint64_t const *)pvSrc; /** @todo could be misaligned */
     173    size_t const    cbSrcFrame = pMap->cbGuestFrame;
     174
     175    while (cFrames-- > 0)
     176    {
     177        *pu64Dst++ = *pu64Src;
     178        pu64Src = (uint64_t const *)((uintptr_t)pu64Src + cbSrcFrame);
     179    }
     180}
     181
     182
     183/** No conversion needed, just copy the data. */
     184static DECLCALLBACK(void)
     185hdaR3StreamMap_GenericCopy(void *pvDst, void const *pvSrc, uint32_t cFrames, HDASTREAMMAP const *pMap)
     186{
     187    memcpy(pvDst, pvSrc, cFrames * pMap->cbGuestFrame);
    128188}
    129189
     
    132192 * Sets up a stream mapping according to the given properties / configuration.
    133193 *
    134  * @return VBox status code, or VERR_NOT_SUPPORTED if the channel setup is not supported (yet).
    135  * @param  pMap                 Pointer to mapping to set up.
    136  * @param  pProps               PCM audio properties to use for lookup.
    137  */
    138 static int hdaR3StreamMapSetup(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps)
     194 * @return  VBox status code.
     195 * @retval  VERR_NOT_SUPPORTED if the channel setup is not supported.
     196 *
     197 * @param   pMap            Pointer to mapping to set up.
     198 * @param   pProps          Input: The stream PCM properties from the guest.
     199 *                          Output: Properties for the host stream.
     200 * @param   cHostChannels   The number of host channels to map to.
     201 */
     202static int hdaR3StreamMapSetup(PHDASTREAMMAP pMap, PPDMAUDIOPCMPROPS pProps, uint8_t cHostChannels)
    139203{
    140204    int rc;
     
    150214         || pProps->cChannels == 6) /* Surround (5.1) */
    151215    {
     216        /*
     217         * Copy the guest stream properties and see if we need to change the host properties.
     218         */
     219        memcpy(&pMap->GuestProps, pProps, sizeof(PDMAUDIOPCMPROPS));
     220        if (pProps->cChannels != cHostChannels)
     221        {
     222            if (pProps->cChannels == 1)
     223                LogRelMax(32, ("HDA: Warning: Guest mono, host stereo.\n"));
     224            else if (cHostChannels == 1 && pProps->cChannels == 2)
     225                LogRelMax(32, ("HDA: Warning: Host mono, guest stereo.\n"));
     226            else
     227#ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
     228                LogRelMax(32, ("HDA: Warning: Guest configured %u channels, host only supports %u. Ignoring additional channels.\n",
     229                               pProps->cChannels, cHostChannels));
     230#else
     231# error reconsider the above logic
     232#endif
     233            pProps->cChannels = cHostChannels;
     234            pProps->cShift    = PDMAUDIOPCMPROPS_MAKE_SHIFT(pProps);
     235        }
     236
     237        /*
     238         * Pick conversion functions.
     239         */
     240        Assert(pMap->GuestProps.cbSample == pProps->cbSample);
     241
     242        /* If the channel count matches, we can use the memcpy converters: */
     243        if (pProps->cChannels == pMap->GuestProps.cChannels)
     244        {
     245            pMap->pfnGuestToHost = hdaR3StreamMap_GenericCopy;
     246            pMap->pfnHostToGuest = hdaR3StreamMap_GenericCopy;
     247            pMap->fMappingNeeded = false;
     248        }
     249        else
     250        {
     251            /* For multi-speaker guest configs, we currently just pick the
     252               first two channels and map this onto the host stereo ones. */
     253            AssertReturn(cHostChannels == 2, VERR_NOT_SUPPORTED);
     254            switch (pMap->GuestProps.cbSample)
     255            {
     256                case 2:
     257                    if (pMap->GuestProps.cChannels > 1)
     258                    {
     259                        pMap->pfnGuestToHost = hdaR3StreamMap_G2H_GenericS16_NonMono2Stereo;
     260                        pMap->pfnHostToGuest = hdaR3StreamMap_H2G_GenericS16_Stereo2NonMono;
     261                    }
     262                    else
     263                    {
     264                        pMap->pfnGuestToHost = hdaR3StreamMap_G2H_GenericS16_Mono2Stereo;
     265                        pMap->pfnHostToGuest = hdaR3StreamMap_H2G_GenericS16_Stereo2Mono;
     266                    }
     267                    break;
     268
     269                case 4:
     270                    if (pMap->GuestProps.cChannels > 1)
     271                    {
     272                        pMap->pfnGuestToHost = hdaR3StreamMap_G2H_GenericS32_NonMono2Stereo;
     273                        pMap->pfnHostToGuest = hdaR3StreamMap_H2G_GenericS32_Stereo2NonMono;
     274                    }
     275                    else
     276                    {
     277                        pMap->pfnGuestToHost = hdaR3StreamMap_G2H_GenericS32_Mono2Stereo;
     278                        pMap->pfnHostToGuest = hdaR3StreamMap_H2G_GenericS32_Stereo2Mono;
     279                    }
     280                    break;
     281
     282                default:
     283                    AssertMsgFailedReturn(("cbSample=%u\n", pMap->GuestProps.cbSample), VERR_NOT_SUPPORTED);
     284            }
     285            pMap->fMappingNeeded = true;
     286        }
     287
     288        /** @todo bird: Not sure if this is really needed any more. */
     289
    152290        /* For now we don't have anything other as mono / stereo channels being covered by the backends.
    153291         * So just set up one channel covering those and skipping the rest (like configured rear or center/LFE outputs). */
    154292        pMap->cMappings  = 1;
    155293        pMap->paMappings = (PPDMAUDIOSTREAMMAP)RTMemAlloc(sizeof(PDMAUDIOSTREAMMAP) * pMap->cMappings);
    156         if (!pMap->paMappings)
    157             return VERR_NO_MEMORY;
    158 
    159         PPDMAUDIOSTREAMMAP pMapLR = &pMap->paMappings[0];
    160 
    161         pMapLR->aenmIDs[0]  = PDMAUDIOSTREAMCHANNELID_FRONT_LEFT;
    162         pMapLR->aenmIDs[1]  = PDMAUDIOSTREAMCHANNELID_FRONT_RIGHT;
    163         pMapLR->cbFrame     = pProps->cbSample * pProps->cChannels;
    164         pMapLR->cbStep      = pProps->cbSample * 2 /* Front left + Front right channels */;
    165         pMapLR->offFirst    = 0;
    166         pMapLR->offNext     = pMapLR->offFirst;
    167 
    168         rc = hdaR3StreamChannelDataInit(&pMapLR->Data, PDMAUDIOSTREAMCHANNELDATA_FLAGS_NONE);
    169         AssertRC(rc);
    170 
    171         memcpy(&pMap->PCMProps, pProps, sizeof(PDMAUDIOPCMPROPS));
     294        if (pMap->paMappings)
     295        {
     296            PPDMAUDIOSTREAMMAP pMapLR = &pMap->paMappings[0];
     297            pMapLR->aenmIDs[0]  = PDMAUDIOSTREAMCHANNELID_FRONT_LEFT;
     298            pMapLR->aenmIDs[1]  = PDMAUDIOSTREAMCHANNELID_FRONT_RIGHT;
     299            pMapLR->cbFrame     = pProps->cbSample * pProps->cChannels;
     300            pMapLR->cbStep      = pProps->cbSample * 2 /* Front left + Front right channels */;
     301            pMapLR->offFirst    = 0;
     302            pMapLR->offNext     = pMapLR->offFirst;
     303
     304            rc = hdaR3StreamChannelDataInit(&pMapLR->Data, PDMAUDIOSTREAMCHANNELDATA_FLAGS_NONE);
     305            AssertRC(rc);
     306        }
     307        else
     308            rc = VERR_NO_MEMORY;
    172309    }
    173310    else
     
    176313    return rc;
    177314}
    178 #endif /* IN_RING3 */
    179 
     315
     316
     317/**
     318 * Initializes a stream mapping structure according to the given PCM properties.
     319 *
     320 * @return  IPRT status code.
     321 * @param   pMap            Pointer to mapping to initialize.
     322 * @param   cHostChannels   The number of host channels to map to.
     323 * @param   pProps          Input: The stream PCM properties from the guest.
     324 *                          Output: Properties for the host side.
     325 */
     326int hdaR3StreamMapInit(PHDASTREAMMAP pMap, uint8_t cHostChannels, PPDMAUDIOPCMPROPS pProps)
     327{
     328    AssertPtrReturn(pMap, VERR_INVALID_POINTER);
     329    AssertPtrReturn(pProps, VERR_INVALID_POINTER);
     330
     331    if (!DrvAudioHlpPcmPropsAreValid(pProps))
     332        return VERR_INVALID_PARAMETER;
     333
     334    hdaR3StreamMapReset(pMap);
     335
     336    pMap->cbGuestFrame = pProps->cChannels * pProps->cbSample;
     337    int rc = hdaR3StreamMapSetup(pMap, pProps, cHostChannels);
     338    if (RT_SUCCESS(rc))
     339    {
     340#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     341        /* Create the circular buffer if not created yet. */
     342        if (!pMap->pCircBuf)
     343            rc = RTCircBufCreate(&pMap->pCircBuf, _4K); /** @todo Make size configurable? */
     344        if (RT_SUCCESS(rc))
     345#endif
     346        {
     347            LogFunc(("cChannels=%RU8, cBytes=%RU8 -> cbGuestFrame=%RU32\n",
     348                     pProps->cChannels, pProps->cbSample, pMap->cbGuestFrame));
     349
     350            Assert(pMap->cbGuestFrame); /* Frame size must not be 0. */
     351            pMap->enmLayout = PDMAUDIOSTREAMLAYOUT_INTERLEAVED;
     352            return VINF_SUCCESS;
     353        }
     354    }
     355
     356    return rc;
     357}
     358
     359
     360/**
     361 * Destroys a given stream mapping.
     362 *
     363 * @param   pMap            Pointer to mapping to destroy.
     364 */
     365void hdaR3StreamMapDestroy(PHDASTREAMMAP pMap)
     366{
     367    hdaR3StreamMapReset(pMap);
     368
     369#ifdef VBOX_WITH_AUDIO_HDA_51_SURROUND
     370    if (pMap->pCircBuf)
     371    {
     372        RTCircBufDestroy(pMap->pCircBuf);
     373        pMap->pCircBuf = NULL;
     374    }
     375#endif
     376}
     377
     378
     379/**
     380 * Resets a given stream mapping.
     381 *
     382 * @param   pMap            Pointer to mapping to reset.
     383 */
     384void hdaR3StreamMapReset(PHDASTREAMMAP pMap)
     385{
     386    AssertPtrReturnVoid(pMap);
     387
     388    pMap->enmLayout = PDMAUDIOSTREAMLAYOUT_UNKNOWN;
     389
     390    if (pMap->paMappings)
     391    {
     392        for (uint8_t i = 0; i < pMap->cMappings; i++)
     393            hdaR3StreamChannelDataDestroy(&pMap->paMappings[i].Data);
     394
     395        RTMemFree(pMap->paMappings);
     396        pMap->paMappings = NULL;
     397
     398        pMap->cMappings = 0;
     399    }
     400
     401    pMap->fMappingNeeded = false;
     402    pMap->pfnGuestToHost = hdaR3StreamMap_GenericCopy;
     403    pMap->pfnHostToGuest = hdaR3StreamMap_GenericCopy;
     404    RT_ZERO(pMap->GuestProps);
     405}
     406
  • trunk/src/VBox/Devices/Audio/HDAStreamMap.h

    r87942 r88112  
    2727typedef struct HDASTREAMMAP
    2828{
    29     /** The PCM properties which have been used. */
    30     PDMAUDIOPCMPROPS                PCMProps;
     29    /** The guest stream properties that is being mapped from/to.
     30     * The host properties are found in HDASTREAMSTATE::Cfg::Props.  */
     31    PDMAUDIOPCMPROPS                GuestProps;
    3132    /** The stream's layout. */
    3233    PDMAUDIOSTREAMLAYOUT            enmLayout;
    33     /** The mapping's overall audio frame size (in bytes).
    34      *  This includes all mappings in \a paMappings. */
    35     uint8_t                         cbFrameSize;
     34    /** The guest side frame size in bytes. */
     35    uint8_t                         cbGuestFrame;
     36    /** Set if mapping is needed. */
     37    bool                            fMappingNeeded;
    3638    /** Number of mappings in paMappings. */
    3739    uint8_t                         cMappings;
    38     uint8_t                         aPadding[2];
     40    uint8_t                         aPadding[1];
    3941    /** Array of stream mappings.
    4042     *  Note: The mappings *must* be layed out in an increasing order, e.g.
     
    4850    R3PTRTYPE(PRTCIRCBUF)           pCircBuf;
    4951#endif
     52    /**
     53     * Converts guest data to host data.
     54     *
     55     * @param   pvDst       The destination (host) buffer.
     56     * @param   pvSrc       The source (guest) data.  Does not overlap @a pvDst.
     57     * @param   cFrames     Number of frames to convert.
     58     * @param   pMapping    Pointer to this structure.
     59     */
     60    DECLCALLBACKMEMBER(void, pfnGuestToHost,(void *pvDst, void const *pvSrc, uint32_t cFrames,
     61                                             struct HDASTREAMMAP const *pMapping));
     62    /**
     63     * Converts host data to guest data.
     64     *
     65     * @param   pvDst       The destination (guest) buffer.
     66     * @param   pvSrc       The source (host) data.  Does not overlap @a pvDst.
     67     * @param   cFrames     Number of frames to convert.
     68     * @param   pMapping    Pointer to this structure.
     69     */
     70    DECLCALLBACKMEMBER(void, pfnHostToGuest,(void *pvDst, void const *pvSrc, uint32_t cFrames,
     71                                             struct HDASTREAMMAP const *pMapping));
    5072} HDASTREAMMAP;
    5173AssertCompileSizeAlignment(HDASTREAMMAP, 8);
     
    5779 */
    5880#ifdef IN_RING3
    59 int  hdaR3StreamMapInit(PHDASTREAMMAP pMapping, PPDMAUDIOPCMPROPS pProps);
     81int  hdaR3StreamMapInit(PHDASTREAMMAP pMapping, uint8_t cHostChannels, PPDMAUDIOPCMPROPS pProps);
    6082void hdaR3StreamMapDestroy(PHDASTREAMMAP pMapping);
    6183void hdaR3StreamMapReset(PHDASTREAMMAP pMapping);
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r88028 r88112  
    3838    RTTestSub(hTest, "Basics");
    3939
    40     static const PDMAUDIOPCMPROPS s_Cfg441StereoS16 = PDMAUDIOPCMPROPS_INITIALIZOR(
     40    const PDMAUDIOPCMPROPS Cfg441StereoS16 = PDMAUDIOPCMPROPS_INITIALIZOR(
    4141        /* a_cb: */             2,
    4242        /* a_fSigned: */        true,
     
    4646        /* a_fSwapEndian: */    false
    4747    );
    48     static const PDMAUDIOPCMPROPS s_Cfg441StereoU16 = PDMAUDIOPCMPROPS_INITIALIZOR(
     48    const PDMAUDIOPCMPROPS Cfg441StereoU16 = PDMAUDIOPCMPROPS_INITIALIZOR(
    4949        /* a_cb: */             2,
    5050        /* a_fSigned: */        false,
     
    5454        /* a_fSwapEndian: */    false
    5555    );
    56     static const PDMAUDIOPCMPROPS s_Cfg441StereoU32 = PDMAUDIOPCMPROPS_INITIALIZOR(
     56    const PDMAUDIOPCMPROPS Cfg441StereoU32 = PDMAUDIOPCMPROPS_INITIALIZOR(
    5757        /* a_cb: */             4,
    5858        /* a_fSigned: */        false,
     
    6363    );
    6464
    65     RTTESTI_CHECK(PDMAudioPropsGetBitrate(&s_Cfg441StereoS16) == 44100*4*8);
    66     RTTESTI_CHECK(PDMAudioPropsGetBitrate(&s_Cfg441StereoU16) == 44100*4*8);
    67     RTTESTI_CHECK(PDMAudioPropsGetBitrate(&s_Cfg441StereoU32) == 44100*8*8);
    68 
    69     RTTESTI_CHECK(DrvAudioHlpPcmPropsAreValid(&s_Cfg441StereoS16));
    70     RTTESTI_CHECK(DrvAudioHlpPcmPropsAreValid(&s_Cfg441StereoU16) == false); /* go figure */
    71     RTTESTI_CHECK(DrvAudioHlpPcmPropsAreValid(&s_Cfg441StereoU32) == false); /* go figure */
    72 
    73 
    74     RTTESTI_CHECK_MSG(PDMAUDIOPCMPROPS_F2B(&s_Cfg441StereoS16, 1) == 4,
    75                       ("got %x, expected 4\n", PDMAUDIOPCMPROPS_F2B(&s_Cfg441StereoS16, 1)));
    76     RTTESTI_CHECK_MSG(PDMAUDIOPCMPROPS_F2B(&s_Cfg441StereoU16, 1) == 4,
    77                       ("got %x, expected 4\n", PDMAUDIOPCMPROPS_F2B(&s_Cfg441StereoU16, 1)));
    78     RTTESTI_CHECK_MSG(PDMAUDIOPCMPROPS_F2B(&s_Cfg441StereoU32, 1) == 8,
    79                       ("got %x, expected 4\n", PDMAUDIOPCMPROPS_F2B(&s_Cfg441StereoU32, 1)));
    80 
    81     RTTESTI_CHECK_MSG(PDMAudioPropsBytesPerFrame(&s_Cfg441StereoS16) == 4,
    82                       ("got %x, expected 4\n", PDMAudioPropsBytesPerFrame(&s_Cfg441StereoS16)));
    83     RTTESTI_CHECK_MSG(PDMAudioPropsBytesPerFrame(&s_Cfg441StereoU16) == 4,
    84                       ("got %x, expected 4\n", PDMAudioPropsBytesPerFrame(&s_Cfg441StereoU16)));
    85     RTTESTI_CHECK_MSG(PDMAudioPropsBytesPerFrame(&s_Cfg441StereoU32) == 8,
    86                       ("got %x, expected 4\n", PDMAudioPropsBytesPerFrame(&s_Cfg441StereoU32)));
     65    RTTESTI_CHECK(PDMAudioPropsGetBitrate(&Cfg441StereoS16) == 44100*4*8);
     66    RTTESTI_CHECK(PDMAudioPropsGetBitrate(&Cfg441StereoU16) == 44100*4*8);
     67    RTTESTI_CHECK(PDMAudioPropsGetBitrate(&Cfg441StereoU32) == 44100*8*8);
     68
     69    RTTESTI_CHECK(DrvAudioHlpPcmPropsAreValid(&Cfg441StereoS16));
     70    RTTESTI_CHECK(DrvAudioHlpPcmPropsAreValid(&Cfg441StereoU16) == false); /* go figure */
     71    RTTESTI_CHECK(DrvAudioHlpPcmPropsAreValid(&Cfg441StereoU32) == false); /* go figure */
     72
     73
     74    RTTESTI_CHECK_MSG(PDMAUDIOPCMPROPS_F2B(&Cfg441StereoS16, 1) == 4,
     75                      ("got %x, expected 4\n", PDMAUDIOPCMPROPS_F2B(&Cfg441StereoS16, 1)));
     76    RTTESTI_CHECK_MSG(PDMAUDIOPCMPROPS_F2B(&Cfg441StereoU16, 1) == 4,
     77                      ("got %x, expected 4\n", PDMAUDIOPCMPROPS_F2B(&Cfg441StereoU16, 1)));
     78    RTTESTI_CHECK_MSG(PDMAUDIOPCMPROPS_F2B(&Cfg441StereoU32, 1) == 8,
     79                      ("got %x, expected 4\n", PDMAUDIOPCMPROPS_F2B(&Cfg441StereoU32, 1)));
     80
     81    RTTESTI_CHECK_MSG(PDMAudioPropsBytesPerFrame(&Cfg441StereoS16) == 4,
     82                      ("got %x, expected 4\n", PDMAudioPropsBytesPerFrame(&Cfg441StereoS16)));
     83    RTTESTI_CHECK_MSG(PDMAudioPropsBytesPerFrame(&Cfg441StereoU16) == 4,
     84                      ("got %x, expected 4\n", PDMAudioPropsBytesPerFrame(&Cfg441StereoU16)));
     85    RTTESTI_CHECK_MSG(PDMAudioPropsBytesPerFrame(&Cfg441StereoU32) == 8,
     86                      ("got %x, expected 4\n", PDMAudioPropsBytesPerFrame(&Cfg441StereoU32)));
    8787
    8888    uint32_t u32;
    8989    for (uint32_t i = 0; i < 256; i += 8)
    9090    {
    91         RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&s_Cfg441StereoU32, i) == true);
     91        RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&Cfg441StereoU32, i) == true);
    9292        for (uint32_t j = 1; j < 8; j++)
    93             RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&s_Cfg441StereoU32, i + j) == false);
     93            RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&Cfg441StereoU32, i + j) == false);
    9494        for (uint32_t j = 0; j < 8; j++)
    95             RTTESTI_CHECK(PDMAudioPropsFloorBytesToFrame(&s_Cfg441StereoU32, i + j) == i);
     95            RTTESTI_CHECK(PDMAudioPropsFloorBytesToFrame(&Cfg441StereoU32, i + j) == i);
    9696    }
    9797    for (uint32_t i = 0; i < 4096; i += 4)
    9898    {
    99         RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&s_Cfg441StereoS16, i) == true);
     99        RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&Cfg441StereoS16, i) == true);
    100100        for (uint32_t j = 1; j < 4; j++)
    101             RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&s_Cfg441StereoS16, i + j) == false);
     101            RTTESTI_CHECK(PDMAudioPropsIsSizeAligned(&Cfg441StereoS16, i + j) == false);
    102102        for (uint32_t j = 0; j < 4; j++)
    103             RTTESTI_CHECK(PDMAudioPropsFloorBytesToFrame(&s_Cfg441StereoS16, i + j) == i);
    104     }
    105 
    106     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&s_Cfg441StereoS16, 44100)) == 44100 * 2 * 2,
     103            RTTESTI_CHECK(PDMAudioPropsFloorBytesToFrame(&Cfg441StereoS16, i + j) == i);
     104    }
     105
     106    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&Cfg441StereoS16, 44100)) == 44100 * 2 * 2,
    107107                      ("cb=%RU32\n", u32));
    108     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&s_Cfg441StereoS16, 2)) == 2 * 2 * 2,
     108    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&Cfg441StereoS16, 2)) == 2 * 2 * 2,
    109109                      ("cb=%RU32\n", u32));
    110     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&s_Cfg441StereoS16, 1)) == 4,
     110    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&Cfg441StereoS16, 1)) == 4,
    111111                      ("cb=%RU32\n", u32));
    112     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&s_Cfg441StereoU16, 1)) == 4,
     112    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&Cfg441StereoU16, 1)) == 4,
    113113                      ("cb=%RU32\n", u32));
    114     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&s_Cfg441StereoU32, 1)) == 8,
     114    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsFramesToBytes(&Cfg441StereoU32, 1)) == 8,
    115115                      ("cb=%RU32\n", u32));
    116116
    117     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsBytesToFrames(&s_Cfg441StereoS16, 4)) == 1, ("cb=%RU32\n", u32));
    118     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsBytesToFrames(&s_Cfg441StereoU16, 4)) == 1, ("cb=%RU32\n", u32));
    119     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsBytesToFrames(&s_Cfg441StereoU32, 8)) == 1, ("cb=%RU32\n", u32));
     117    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsBytesToFrames(&Cfg441StereoS16, 4)) == 1, ("cb=%RU32\n", u32));
     118    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsBytesToFrames(&Cfg441StereoU16, 4)) == 1, ("cb=%RU32\n", u32));
     119    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsBytesToFrames(&Cfg441StereoU32, 8)) == 1, ("cb=%RU32\n", u32));
    120120
    121121    uint64_t u64;
    122     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsBytesToNano(&s_Cfg441StereoS16, 44100 * 2 * 2)) == RT_NS_1SEC,
     122    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsBytesToNano(&Cfg441StereoS16, 44100 * 2 * 2)) == RT_NS_1SEC,
    123123                      ("ns=%RU64\n", u64));
    124     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsBytesToMicro(&s_Cfg441StereoS16, 44100 * 2 * 2)) == RT_US_1SEC,
     124    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsBytesToMicro(&Cfg441StereoS16, 44100 * 2 * 2)) == RT_US_1SEC,
    125125                      ("us=%RU64\n", u64));
    126     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsBytesToMilli(&s_Cfg441StereoS16, 44100 * 2 * 2)) == RT_MS_1SEC,
     126    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsBytesToMilli(&Cfg441StereoS16, 44100 * 2 * 2)) == RT_MS_1SEC,
    127127                      ("ms=%RU64\n", u64));
    128128
    129     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&s_Cfg441StereoS16, 44100)) == RT_NS_1SEC, ("ns=%RU64\n", u64));
    130     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&s_Cfg441StereoS16,     1)) == 22675,      ("ns=%RU64\n", u64));
    131     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&s_Cfg441StereoS16,    31)) == 702947,     ("ns=%RU64\n", u64));
    132     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&s_Cfg441StereoS16,   255)) == 5782312,    ("ns=%RU64\n", u64));
    133     //RTTESTI_CHECK_MSG((u64 = DrvAudioHlpFramesToMicro(&s_Cfg441StereoS16, 44100)) == RT_US_1SEC,
     129    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&Cfg441StereoS16, 44100)) == RT_NS_1SEC, ("ns=%RU64\n", u64));
     130    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&Cfg441StereoS16,     1)) == 22675,      ("ns=%RU64\n", u64));
     131    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&Cfg441StereoS16,    31)) == 702947,     ("ns=%RU64\n", u64));
     132    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToNano(&Cfg441StereoS16,   255)) == 5782312,    ("ns=%RU64\n", u64));
     133    //RTTESTI_CHECK_MSG((u64 = DrvAudioHlpFramesToMicro(&Cfg441StereoS16, 44100)) == RT_US_1SEC,
    134134    //                  ("us=%RU64\n", u64));
    135     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToMilli(&s_Cfg441StereoS16, 44100)) == RT_MS_1SEC, ("ms=%RU64\n", u64));
    136     RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToMilli(&s_Cfg441StereoS16,   255)) == 5,          ("ms=%RU64\n", u64));
    137 
    138     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToFrames(&s_Cfg441StereoS16,  RT_NS_1SEC)) == 44100, ("cb=%RU32\n", u32));
    139     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToFrames(&s_Cfg441StereoS16,      215876)) == 10,    ("cb=%RU32\n", u32));
    140     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToFrames(&s_Cfg441StereoS16, RT_MS_1SEC)) == 44100, ("cb=%RU32\n", u32));
    141     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToFrames(&s_Cfg441StereoU32,          6)) == 265,   ("cb=%RU32\n", u32));
    142 
    143     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToBytes(&s_Cfg441StereoS16,  RT_NS_1SEC)) == 44100*2*2, ("cb=%RU32\n", u32));
    144     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToBytes(&s_Cfg441StereoS16,      702947)) == 31*2*2,    ("cb=%RU32\n", u32));
    145     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToBytes(&s_Cfg441StereoS16, RT_MS_1SEC)) == 44100*2*2, ("cb=%RU32\n", u32));
    146     RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToBytes(&s_Cfg441StereoS16,          5)) == 884,       ("cb=%RU32\n", u32));
     135    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToMilli(&Cfg441StereoS16, 44100)) == RT_MS_1SEC, ("ms=%RU64\n", u64));
     136    RTTESTI_CHECK_MSG((u64 = PDMAudioPropsFramesToMilli(&Cfg441StereoS16,   255)) == 5,          ("ms=%RU64\n", u64));
     137
     138    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToFrames(&Cfg441StereoS16,  RT_NS_1SEC)) == 44100, ("cb=%RU32\n", u32));
     139    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToFrames(&Cfg441StereoS16,      215876)) == 10,    ("cb=%RU32\n", u32));
     140    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToFrames(&Cfg441StereoS16, RT_MS_1SEC)) == 44100, ("cb=%RU32\n", u32));
     141    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToFrames(&Cfg441StereoU32,          6)) == 265,   ("cb=%RU32\n", u32));
     142
     143    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToBytes(&Cfg441StereoS16,  RT_NS_1SEC)) == 44100*2*2, ("cb=%RU32\n", u32));
     144    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsNanoToBytes(&Cfg441StereoS16,      702947)) == 31*2*2,    ("cb=%RU32\n", u32));
     145    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToBytes(&Cfg441StereoS16, RT_MS_1SEC)) == 44100*2*2, ("cb=%RU32\n", u32));
     146    RTTESTI_CHECK_MSG((u32 = PDMAudioPropsMilliToBytes(&Cfg441StereoS16,          5)) == 884,       ("cb=%RU32\n", u32));
    147147
    148148    /* DrvAudioHlpClearBuf: */
     
    152152
    153153    memset(pbPage, 0x42, PAGE_SIZE);
    154     PDMAudioPropsClearBuffer(&s_Cfg441StereoS16, pbPage, PAGE_SIZE, PAGE_SIZE / 4);
     154    PDMAudioPropsClearBuffer(&Cfg441StereoS16, pbPage, PAGE_SIZE, PAGE_SIZE / 4);
    155155    RTTESTI_CHECK(ASMMemIsZero(pbPage, PAGE_SIZE));
    156156
    157157    memset(pbPage, 0x42, PAGE_SIZE);
    158     PDMAudioPropsClearBuffer(&s_Cfg441StereoU16, pbPage, PAGE_SIZE, PAGE_SIZE / 4);
     158    PDMAudioPropsClearBuffer(&Cfg441StereoU16, pbPage, PAGE_SIZE, PAGE_SIZE / 4);
    159159    for (uint32_t off = 0; off < PAGE_SIZE; off += 2)
    160160        RTTESTI_CHECK_MSG(pbPage[off] == 0x80 && pbPage[off + 1] == 0, ("off=%#x: %#x %x\n", off, pbPage[off], pbPage[off + 1]));
    161161
    162162    memset(pbPage, 0x42, PAGE_SIZE);
    163     PDMAudioPropsClearBuffer(&s_Cfg441StereoU32, pbPage, PAGE_SIZE, PAGE_SIZE / 8);
     163    PDMAudioPropsClearBuffer(&Cfg441StereoU32, pbPage, PAGE_SIZE, PAGE_SIZE / 8);
    164164    for (uint32_t off = 0; off < PAGE_SIZE; off += 4)
    165165        RTTESTI_CHECK(pbPage[off] == 0x80 && pbPage[off + 1] == 0 && pbPage[off + 2] == 0 && pbPage[off + 3] == 0);
     
    168168    RTTestDisableAssertions(hTest);
    169169    memset(pbPage, 0x42, PAGE_SIZE);
    170     PDMAudioPropsClearBuffer(&s_Cfg441StereoS16, pbPage, PAGE_SIZE, PAGE_SIZE); /* should adjust down the frame count. */
     170    PDMAudioPropsClearBuffer(&Cfg441StereoS16, pbPage, PAGE_SIZE, PAGE_SIZE); /* should adjust down the frame count. */
    171171    RTTESTI_CHECK(ASMMemIsZero(pbPage, PAGE_SIZE));
    172172
    173173    memset(pbPage, 0x42, PAGE_SIZE);
    174     PDMAudioPropsClearBuffer(&s_Cfg441StereoU16, pbPage, PAGE_SIZE, PAGE_SIZE); /* should adjust down the frame count. */
     174    PDMAudioPropsClearBuffer(&Cfg441StereoU16, pbPage, PAGE_SIZE, PAGE_SIZE); /* should adjust down the frame count. */
    175175    for (uint32_t off = 0; off < PAGE_SIZE; off += 2)
    176176        RTTESTI_CHECK_MSG(pbPage[off] == 0x80 && pbPage[off + 1] == 0, ("off=%#x: %#x %x\n", off, pbPage[off], pbPage[off + 1]));
    177177
    178178    memset(pbPage, 0x42, PAGE_SIZE);
    179     PDMAudioPropsClearBuffer(&s_Cfg441StereoU32, pbPage, PAGE_SIZE, PAGE_SIZE); /* should adjust down the frame count. */
     179    PDMAudioPropsClearBuffer(&Cfg441StereoU32, pbPage, PAGE_SIZE, PAGE_SIZE); /* should adjust down the frame count. */
    180180    for (uint32_t off = 0; off < PAGE_SIZE; off += 4)
    181181        RTTESTI_CHECK(pbPage[off] == 0x80 && pbPage[off + 1] == 0 && pbPage[off + 2] == 0 && pbPage[off + 3] == 0);
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