VirtualBox

Changeset 88356 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Apr 4, 2021 10:45:13 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143603
Message:

Audio: Trimmed down PDMAUDIOSTREAM a lot by moving non-essential stuff into an wrapper structure in DrvAudio. This allows for the mixing buffers and other stuff to move (back?) into AudioMixBuffer.h. Also started specifying away to skip the mixing in DrvAudio as only DevSB16 really needs this (goal is to reduce number of copies and bufferings). bugref:9890

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

Legend:

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

    r88320 r88356  
    6464
    6565#ifdef DEBUG
    66 DECLINLINE(void)        audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc);
    67 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf);
     66DECLINLINE(void)        audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc);
     67DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf);
    6868#endif
    6969
     
    152152/** @todo r=bird: This isn't a 'ing Peek function, it's a Read function!
    153153 *        Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg!!!!!!!!!!!!!!!!!!! */
    154 int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames,
     154int AudioMixBufPeekMutable(PAUDIOMIXBUF pMixBuf, uint32_t cFrames,
    155155                           PPDMAUDIOFRAME *ppvFrames, uint32_t *pcFramesToWrite)
    156156{
     
    197197 *
    198198 */
    199 void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf)
     199void AudioMixBufClear(PAUDIOMIXBUF pMixBuf)
    200200{
    201201    AssertPtrReturnVoid(pMixBuf);
     
    212212 * @param   cFramesToClear          Number of audio frames to clear.
    213213 */
    214 void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear)
     214void AudioMixBufFinish(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear)
    215215{
    216216    AUDMIXBUF_LOG(("cFramesToClear=%RU32\n", cFramesToClear));
     
    221221
    222222/** @todo r=bird: Why isn't this done when reading/releaseing ? */
    223     PPDMAUDIOMIXBUF pIter;
    224     RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
     223    PAUDIOMIXBUF pIter;
     224    RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node)
    225225    {
    226226        AUDMIXBUF_LOG(("\t%s: cMixed=%RU32 -> %RU32\n",
     
    271271 * @param   pMixBuf                 Mixing buffer to destroy.
    272272 */
    273 void AudioMixBufDestroy(PPDMAUDIOMIXBUF pMixBuf)
     273void AudioMixBufDestroy(PAUDIOMIXBUF pMixBuf)
    274274{
    275275    if (!pMixBuf)
     
    278278    /* Ignore calls for an uninitialized (zeroed) or already destroyed instance.  Happens a lot. */
    279279    if (   pMixBuf->uMagic == 0
    280         || pMixBuf->uMagic == ~PDMAUDIOMIXBUF_MAGIC)
     280        || pMixBuf->uMagic == ~AUDIOMIXBUF_MAGIC)
    281281    {
    282282        Assert(!pMixBuf->pszName);
     
    287287    }
    288288
    289     Assert(pMixBuf->uMagic == PDMAUDIOMIXBUF_MAGIC);
    290     pMixBuf->uMagic = ~PDMAUDIOMIXBUF_MAGIC;
     289    Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
     290    pMixBuf->uMagic = ~AUDIOMIXBUF_MAGIC;
    291291
    292292    AudioMixBufUnlink(pMixBuf);
     
    323323 * @param   pMixBuf                 Mixing buffer to return free size for.
    324324 */
    325 uint32_t AudioMixBufFree(PPDMAUDIOMIXBUF pMixBuf)
     325uint32_t AudioMixBufFree(PAUDIOMIXBUF pMixBuf)
    326326{
    327327    AssertPtrReturn(pMixBuf, 0);
     
    356356 * @param   pMixBuf                 Mixing buffer to return free size for.
    357357 */
    358 uint32_t AudioMixBufFreeBytes(PPDMAUDIOMIXBUF pMixBuf)
     358uint32_t AudioMixBufFreeBytes(PAUDIOMIXBUF pMixBuf)
    359359{
    360360    return AUDIOMIXBUF_F2B(pMixBuf, AudioMixBufFree(pMixBuf));
     
    368368 * @param   cFrames                 Number of audio frames to allocate.
    369369 */
    370 static int audioMixBufAlloc(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)
     370static int audioMixBufAlloc(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
    371371{
    372372    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
     
    424424    \
    425425    DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, \
    426                                                                PCPDMAUDMIXBUFCONVOPTS pOpts) \
     426                                                               PCAUDMIXBUFCONVOPTS pOpts) \
    427427    { \
    428428        _aType const *pSrc = (_aType const *)pvSrc; \
     
    441441    \
    442442    DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Mono(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, \
    443                                                              PCPDMAUDMIXBUFCONVOPTS pOpts) \
     443                                                             PCAUDMIXBUFCONVOPTS pOpts) \
    444444    { \
    445445        _aType const *pSrc = (_aType const *)pvSrc; \
     
    458458    } \
    459459    \
    460     DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts) \
     460    DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) \
    461461    { \
    462462        PCPDMAUDIOFRAME pSrc = paSrc; \
     
    474474    } \
    475475    \
    476     DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOFRAME paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts) \
     476    DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) \
    477477    { \
    478478        PCPDMAUDIOFRAME pSrc = paSrc; \
     
    506506#if 0
    507507DECLCALLBACK(uint32_t) audioMixBufConvFromS64Stereo(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc,
    508                                                     PCPDMAUDMIXBUFCONVOPTS pOpts)
     508                                                    PCAUDMIXBUFCONVOPTS pOpts)
    509509{
    510510    _aType const *pSrc = (_aType const *)pvSrc;
     
    523523#endif
    524524
    525 DECLCALLBACK(void) audioMixBufConvToRawS64Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts)
     525DECLCALLBACK(void) audioMixBufConvToRawS64Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts)
    526526{
    527527    AssertCompile(sizeof(paSrc[0]) == sizeof(int64_t) * 2);
     
    535535    static void audioMixBufOp##_aName(PPDMAUDIOFRAME paDst, uint32_t cDstFrames, \
    536536                                      PPDMAUDIOFRAME paSrc, uint32_t cSrcFrames, \
    537                                       PPDMAUDIOSTREAMRATE pRate, \
     537                                      PAUDIOSTREAMRATE pRate, \
    538538                                      uint32_t *pcDstWritten, uint32_t *pcSrcRead) \
    539539    { \
     
    631631/** Dummy conversion used when the source is muted. */
    632632static DECLCALLBACK(uint32_t)
    633 audioMixBufConvFromSilence(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, PCPDMAUDMIXBUFCONVOPTS pOpts)
     633audioMixBufConvFromSilence(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, PCAUDMIXBUFCONVOPTS pOpts)
    634634{
    635635    RT_NOREF(cbSrc, pvSrc);
     
    647647 * @param   pProps  The audio format to find a "from" converter for.
    648648 */
    649 static PFNPDMAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps)
     649static PFNAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps)
    650650{
    651651    if (PDMAudioPropsIsSigned(pProps))
     
    710710 * @param   pProps  The audio format to find a "to" converter for.
    711711 */
    712 static PFNPDMAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps)
     712static PFNAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps)
    713713{
    714714    if (PDMAudioPropsIsSigned(pProps))
     
    773773 * @param   pVolSrc                 Volume to convert.
    774774 */
    775 static int audioMixBufConvVol(PPDMAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc)
     775static int audioMixBufConvVol(PAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc)
    776776{
    777777    if (!pVolSrc->fMuted) /* Only change/convert the volume value if we're not muted. */
     
    799799 * @param   cFrames                 Maximum number of audio frames the mixing buffer can hold.
    800800 */
    801 int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
     801int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
    802802{
    803803    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
     
    806806    Assert(PDMAudioPropsAreValid(pProps));
    807807
    808     pMixBuf->uMagic  = PDMAUDIOMIXBUF_MAGIC;
     808    pMixBuf->uMagic  = AUDIOMIXBUF_MAGIC;
    809809    pMixBuf->pParent = NULL;
    810810
     
    862862 * @param   pMixBuf                 Mixing buffer to return value for.
    863863 */
    864 bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf)
     864bool AudioMixBufIsEmpty(PAUDIOMIXBUF pMixBuf)
    865865{
    866866    AssertPtrReturn(pMixBuf, true);
     
    878878 * @param   pMixBufB            Second mixing buffer.
    879879 */
    880 static int64_t audioMixBufCalcFreqRatio(PPDMAUDIOMIXBUF pMixBufA, PPDMAUDIOMIXBUF pMixBufB)
     880static int64_t audioMixBufCalcFreqRatio(PAUDIOMIXBUF pMixBufA, PAUDIOMIXBUF pMixBufB)
    881881{
    882882    int64_t iRatio = (int64_t)((uint64_t)PDMAudioPropsHz(&pMixBufA->Props) << 32) / PDMAudioPropsHz(&pMixBufB->Props);
     
    906906 * @remark  Circular linking is not allowed.
    907907 */
    908 int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent)
     908int AudioMixBufLinkTo(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUF pParent)
    909909{
    910910    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
     
    969969        if (!pMixBuf->pRate)
    970970        {
    971             pMixBuf->pRate = (PPDMAUDIOSTREAMRATE)RTMemAllocZ(sizeof(PDMAUDIOSTREAMRATE));
     971            pMixBuf->pRate = (PAUDIOSTREAMRATE)RTMemAllocZ(sizeof(AUDIOSTREAMRATE));
    972972            AssertReturn(pMixBuf->pRate, VERR_NO_MEMORY);
    973973        }
    974974        else
    975             RT_BZERO(pMixBuf->pRate, sizeof(PDMAUDIOSTREAMRATE));
     975            RT_BZERO(pMixBuf->pRate, sizeof(AUDIOSTREAMRATE));
    976976
    977977        /*
     
    10081008 * @param   pMixBuf                 Mixing buffer to return value for.
    10091009 */
    1010 uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf)
     1010uint32_t AudioMixBufLive(PAUDIOMIXBUF pMixBuf)
    10111011{
    10121012    AssertPtrReturn(pMixBuf, 0);
     
    10511051 * @param   pcSrcMixed              Number of source audio frames successfully mixed. Optional.
    10521052 */
    1053 static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcFrames,
     1053static int audioMixBufMixTo(PAUDIOMIXBUF pDst, PAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcFrames,
    10541054                            uint32_t *pcSrcMixed)
    10551055{
     
    11891189        Assert(cToRead <= pDst->cUsed);
    11901190
    1191         PDMAUDMIXBUFCONVOPTS convOpts;
     1191        AUDMIXBUFCONVOPTS convOpts;
    11921192        RT_ZERO(convOpts);
    11931193        convOpts.cFrames = cToRead;
     
    12301230 * @param   pcSrcMixed              Number of source audio frames successfully mixed. Optional.
    12311231 */
    1232 int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
     1232int AudioMixBufMixToParentEx(PAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
    12331233{
    12341234    AssertMsgReturn(VALID_PTR(pMixBuf->pParent),
     
    12471247 * @param   pcSrcMixed              Number of source audio frames successfully mixed. Optional.
    12481248 */
    1249 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
     1249int AudioMixBufMixToParent(PAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
    12501250{
    12511251    return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, pMixBuf->offRead, cSrcFrames, pcSrcMixed);
     
    12631263 * @param   uIdtLvl                 Indention level to use.
    12641264 */
    1265 DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl)
     1265DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl)
    12661266{
    12671267    Log(("%s: %*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n",
     
    12761276 * @param   pMixBuf                 Mixing buffer to validate.
    12771277 */
    1278 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf)
     1278DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf)
    12791279{
    12801280    //const uint32_t offReadEnd  = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cFrames;
     
    13171317 * @param   pcChildren              Pointer to children counter.
    13181318 */
    1319 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl,
     1319DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl,
    13201320                                                       size_t *pcChildren)
    13211321{
    1322     PPDMAUDIOMIXBUF pIter;
    1323     RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
     1322    PAUDIOMIXBUF pIter;
     1323    RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node)
    13241324    {
    13251325        audioMixBufDbgPrintSingle(pIter, pszFunc, false /* ifIsParent */, uIdtLvl + 1);
     
    13281328}
    13291329
    1330 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc)
    1331 {
    1332     PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
     1330DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc)
     1331{
     1332    PAUDIOMIXBUF pParent = pMixBuf->pParent;
    13331333    while (pParent)
    13341334    {
     
    13591359 * @param   pMixBuf                 Mixing buffer to print.
    13601360 */
    1361 void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf)
     1361void AudioMixBufDbgPrintChain(PAUDIOMIXBUF pMixBuf)
    13621362{
    13631363    audioMixBufDbgPrintChainInternal(pMixBuf, __FUNCTION__);
    13641364}
    13651365
    1366 DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc)
    1367 {
    1368     PPDMAUDIOMIXBUF pParent = pMixBuf;
     1366DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc)
     1367{
     1368    PAUDIOMIXBUF pParent = pMixBuf;
    13691369    if (pMixBuf->pParent)
    13701370        pParent = pMixBuf->pParent;
     
    13721372    audioMixBufDbgPrintSingle(pMixBuf, pszFunc, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */);
    13731373
    1374     PPDMAUDIOMIXBUF pIter;
    1375     RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
     1374    PAUDIOMIXBUF pIter;
     1375    RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node)
    13761376    {
    13771377        if (pIter == pMixBuf)
     
    13881388 * @param   pMixBuf                 Mixing buffer to print.
    13891389 */
    1390 void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf)
     1390void AudioMixBufDbgPrint(PAUDIOMIXBUF pMixBuf)
    13911391{
    13921392    audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
     
    14001400 * @param   pMixBuf
    14011401 */
    1402 uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf)
     1402uint32_t AudioMixBufUsed(PAUDIOMIXBUF pMixBuf)
    14031403{
    14041404    AssertPtrReturn(pMixBuf, 0);
     
    14121412 * @param   pMixBuf
    14131413 */
    1414 uint32_t AudioMixBufUsedBytes(PPDMAUDIOMIXBUF pMixBuf)
     1414uint32_t AudioMixBufUsedBytes(PAUDIOMIXBUF pMixBuf)
    14151415{
    14161416    AssertPtrReturn(pMixBuf, 0);
     
    14281428 * @param   pcbRead                 Size (in bytes) of data read. Optional.
    14291429 */
    1430 int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
     1430int AudioMixBufReadAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    14311431{
    14321432    return AudioMixBufReadAtEx(pMixBuf, &pMixBuf->Props, offFrames, pvBuf, cbBuf, pcbRead);
     
    14461446 * @param   pcbRead     Size (in bytes) of data read. Optional.
    14471447 */
    1448 int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
     1448int AudioMixBufReadAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
    14491449                        uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    14501450{
     
    14661466    if (cToProcess)
    14671467    {
    1468         PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL;
     1468        PFNAUDIOMIXBUFCONVTO pfnConvTo = NULL;
    14691469        if (PDMAudioPropsAreEqual(&pMixBuf->Props, pDstProps))
    14701470            pfnConvTo = pMixBuf->pfnConvTo;
     
    14731473        if (pfnConvTo)
    14741474        {
    1475             PDMAUDMIXBUFCONVOPTS convOpts;
     1475            AUDMIXBUFCONVOPTS convOpts;
    14761476            RT_ZERO(convOpts);
    14771477            /* Note: No volume handling/conversion done in the conversion-to macros (yet). */
     
    15151515 *                              the block that was acquired.
    15161516 */
    1517 int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
     1517int AudioMixBufAcquireReadBlock(PAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
    15181518{
    15191519    return AudioMixBufAcquireReadBlockEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcAcquiredFrames);
     
    15341534 *                              the block that was acquired.
    15351535 */
    1536 int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
     1536int AudioMixBufAcquireReadBlockEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
    15371537                                  void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
    15381538{
     
    15631563    }
    15641564
    1565     PFNPDMAUDIOMIXBUFCONVTO pfnConvTo;
     1565    PFNAUDIOMIXBUFCONVTO pfnConvTo;
    15661566    if (PDMAudioPropsAreEqual(&pMixBuf->Props, pDstProps))
    15671567        pfnConvTo = pMixBuf->pfnConvTo;
     
    15731573    if (cFramesToRead)
    15741574    {
    1575         PDMAUDMIXBUFCONVOPTS convOpts;
     1575        AUDMIXBUFCONVOPTS convOpts;
    15761576        RT_ZERO(convOpts);
    15771577        convOpts.cFrames = cFramesToRead;
     
    16101610 *                      acquired count.)
    16111611 */
    1612 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)
     1612void AudioMixBufReleaseReadBlock(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
    16131613{
    16141614    AssertPtrReturnVoid(pMixBuf);
     
    16281628 * @param   pMixBuf                 Mixing buffer to return position for.
    16291629 */
    1630 uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf)
     1630uint32_t AudioMixBufReadPos(PAUDIOMIXBUF pMixBuf)
    16311631{
    16321632    AssertPtrReturn(pMixBuf, 0);
     
    16401640 * @param   pMixBuf                 Mixing buffer to reset.
    16411641 */
    1642 void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf)
     1642void AudioMixBufReset(PAUDIOMIXBUF pMixBuf)
    16431643{
    16441644    AssertPtrReturnVoid(pMixBuf);
     
    16601660 * @param   pVol                    Pointer to volume structure to set.
    16611661 */
    1662 void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol)
     1662void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol)
    16631663{
    16641664    AssertPtrReturnVoid(pMixBuf);
     
    16771677 * @param   pMixBuf                 Mixing buffer to retrieve maximum for.
    16781678 */
    1679 uint32_t AudioMixBufSize(PPDMAUDIOMIXBUF pMixBuf)
     1679uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf)
    16801680{
    16811681    AssertPtrReturn(pMixBuf, 0);
     
    16891689 * @param   pMixBuf                 Mixing buffer to retrieve maximum for.
    16901690 */
    1691 uint32_t AudioMixBufSizeBytes(PPDMAUDIOMIXBUF pMixBuf)
     1691uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf)
    16921692{
    16931693    AssertPtrReturn(pMixBuf, 0);
     
    17011701 * @param   pMixBuf                 Mixing buffer to unlink from parent.
    17021702 */
    1703 void AudioMixBufUnlink(PPDMAUDIOMIXBUF pMixBuf)
     1703void AudioMixBufUnlink(PAUDIOMIXBUF pMixBuf)
    17041704{
    17051705    if (!pMixBuf || !pMixBuf->pszName)
     
    17251725    }
    17261726
    1727     PPDMAUDIOMIXBUF pChild, pChildNext;
    1728     RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, PDMAUDIOMIXBUF, Node)
     1727    PAUDIOMIXBUF pChild, pChildNext;
     1728    RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, AUDIOMIXBUF, Node)
    17291729    {
    17301730        AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pChild->pszName));
     
    17671767 * @param   pcWritten               Returns number of audio frames written. Optional.
    17681768 */
    1769 int AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
     1769int AudioMixBufWriteAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
    17701770{
    17711771    return AudioMixBufWriteAtEx(pMixBuf, &pMixBuf->Props, offFrames, pvBuf, cbBuf, pcWritten);
     
    17891789 * @param   pcWritten   Returns number of audio frames written. Optional.
    17901790 */
    1791 int AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
     1791int AudioMixBufWriteAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
    17921792                         uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
    17931793{
     
    18261826     * Pick the conversion function and do the conversion.
    18271827     */
    1828     PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
     1828    PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
    18291829    if (!pMixBuf->Volume.fMuted)
    18301830    {
     
    18431843    if (cToWrite)
    18441844    {
    1845         PDMAUDMIXBUFCONVOPTS convOpts;
     1845        AUDMIXBUFCONVOPTS convOpts;
    18461846
    18471847        convOpts.cFrames            = cToWrite;
     
    18921892 * @param   pcWritten               Returns number of audio frames written. Optional.
    18931893 */
    1894 int AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
     1894int AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
    18951895{
    18961896    return AudioMixBufWriteCircEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcWritten);
     
    19101910 * @param   pcWritten   Returns number of audio frames written. Optional.
    19111911 */
    1912 int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
     1912int AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
    19131913                           const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
    19141914{
     
    19301930    AssertPtr(pMixBuf->pFrames);
    19311931
    1932     PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
     1932    PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
    19331933    if (!pMixBuf->Volume.fMuted)
    19341934    {
     
    19551955        Assert(cToWrite);
    19561956
    1957         PDMAUDMIXBUFCONVOPTS convOpts;
     1957        AUDMIXBUFCONVOPTS convOpts;
    19581958        convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted;
    19591959        convOpts.From.Volume.uLeft  = pMixBuf->Volume.uLeft;
     
    20032003 * @param   pMixBuf                 Mixing buffer to return position for.
    20042004 */
    2005 uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf)
     2005uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf)
    20062006{
    20072007    AssertPtrReturn(pMixBuf, 0);
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.h

    r88307 r88356  
    2424#include <iprt/cdefs.h>
    2525#include <VBox/vmm/pdmaudioifs.h>
     26
     27
     28/**
     29 * Rate processing information of a source & destination audio stream.
     30 *
     31 * This is needed because both streams can differ regarding their rates and
     32 * therefore need to be treated accordingly.
     33 */
     34typedef struct AUDIOSTREAMRATE
     35{
     36    /** Current (absolute) offset in the output (destination) stream.
     37     * @todo r=bird: Please reveal which unit these members are given in. */
     38    uint64_t        offDst;
     39    /** Increment for moving offDst for the destination stream.
     40     * This is needed because the source <-> destination rate might be different. */
     41    uint64_t        uDstInc;
     42    /** Current (absolute) offset in the input stream. */
     43    uint32_t        offSrc;
     44    /** Explicit alignment padding. */
     45    uint32_t        u32AlignmentPadding;
     46    /** Last processed frame of the input stream.
     47     *  Needed for interpolation. */
     48    PDMAUDIOFRAME   SrcFrameLast;
     49} AUDIOSTREAMRATE;
     50/** Pointer to rate processing information of a stream. */
     51typedef AUDIOSTREAMRATE *PAUDIOSTREAMRATE;
     52
     53/**
     54 * Mixing buffer volume parameters.
     55 *
     56 * The volume values are in fixed point style and must be converted to/from
     57 * before using with e.g. PDMAUDIOVOLUME.
     58 */
     59typedef struct AUDMIXBUFVOL
     60{
     61    /** Set to @c true if this stream is muted, @c false if not. */
     62    bool            fMuted;
     63    /** Left volume to apply during conversion.
     64     * Pass 0 to convert the original values. May not apply to all conversion functions. */
     65    uint32_t        uLeft;
     66    /** Right volume to apply during conversion.
     67     * Pass 0 to convert the original values. May not apply to all conversion functions. */
     68    uint32_t        uRight;
     69} AUDMIXBUFVOL;
     70/** Pointer to mixing buffer volument parameters. */
     71typedef AUDMIXBUFVOL *PAUDMIXBUFVOL;
     72
     73/*
     74 * Frame conversion parameters for the audioMixBufConvFromXXX / audioMixBufConvToXXX functions.
     75 */
     76typedef struct AUDMIXBUFCONVOPTS
     77{
     78    /** Number of audio frames to convert. */
     79    uint32_t        cFrames;
     80    union
     81    {
     82        struct
     83        {
     84            /** Volume to use for conversion. */
     85            AUDMIXBUFVOL Volume;
     86        } From;
     87    } RT_UNION_NM(u);
     88} AUDMIXBUFCONVOPTS;
     89/** Pointer to conversion parameters for the audio mixer.   */
     90typedef AUDMIXBUFCONVOPTS *PAUDMIXBUFCONVOPTS;
     91/** Pointer to const conversion parameters for the audio mixer.   */
     92typedef AUDMIXBUFCONVOPTS const *PCAUDMIXBUFCONVOPTS;
     93
     94/**
     95 * @note All internal handling is done in audio frames, not in bytes!
     96 * @todo r=bird: What does this note actually apply to?
     97 */
     98typedef uint32_t AUDIOMIXBUFFMT;
     99typedef AUDIOMIXBUFFMT *PAUDIOMIXBUFFMT;
     100
     101/**
     102 * Convertion-from function used by the audio buffer mixer.
     103 *
     104 * @returns Number of audio frames returned.
     105 * @param   paDst           Where to return the converted frames.
     106 * @param   pvSrc           The source frame bytes.
     107 * @param   cbSrc           Number of bytes to convert.
     108 * @param   pOpts           Conversion options.
     109 * @todo r=bird: The @a paDst size is presumable given in @a pOpts->cFrames?
     110 */
     111typedef DECLCALLBACKTYPE(uint32_t, FNAUDIOMIXBUFCONVFROM,(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc,
     112                                                          PCAUDMIXBUFCONVOPTS pOpts));
     113/** Pointer to a convertion-from function used by the audio buffer mixer. */
     114typedef FNAUDIOMIXBUFCONVFROM *PFNAUDIOMIXBUFCONVFROM;
     115
     116/**
     117 * Convertion-to function used by the audio buffer mixer.
     118 *
     119 * @param   pvDst           Output buffer.
     120 * @param   paSrc           The input frames.
     121 * @param   pOpts           Conversion options.
     122 * @todo r=bird: The @a paSrc size is presumable given in @a pOpts->cFrames and
     123 *       this implicitly gives the pvDst size too, right?
     124 */
     125typedef DECLCALLBACKTYPE(void, FNAUDIOMIXBUFCONVTO,(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts));
     126/** Pointer to a convertion-to function used by the audio buffer mixer. */
     127typedef FNAUDIOMIXBUFCONVTO *PFNAUDIOMIXBUFCONVTO;
     128
     129/** Pointer to audio mixing buffer.  */
     130typedef struct AUDIOMIXBUF *PAUDIOMIXBUF;
     131
     132/**
     133 * Audio mixing buffer.
     134 */
     135typedef struct AUDIOMIXBUF
     136{
     137    /** Magic value (AUDIOMIXBUF_MAGIC). */
     138    uint32_t                    uMagic;
     139    uint8_t                     abPadding[4];
     140    /* ???Undocumented??? */
     141    RTLISTNODE                  Node;
     142    /** Name of the buffer. */
     143    char                       *pszName;
     144    /** Frame buffer. */
     145    PPDMAUDIOFRAME              pFrames;
     146    /** Size of the frame buffer (in audio frames). */
     147    uint32_t                    cFrames;
     148    /** The current read position (in frames). */
     149    uint32_t                    offRead;
     150    /** The current write position (in frames). */
     151    uint32_t                    offWrite;
     152    /** Total frames already mixed down to the parent buffer (if any).
     153     *
     154     * Always starting at the parent's offRead position.
     155     * @note Count always is specified in parent frames, as the sample count can
     156     *       differ between parent and child.  */
     157    uint32_t                    cMixed;
     158    /** How much audio frames are currently being used in this buffer.
     159     * @note This also is known as the distance in ring buffer terms. */
     160    uint32_t                    cUsed;
     161    /** Number of children mix buffers kept in lstChildren. */
     162    uint32_t                    cChildren;
     163    /** List of children mix buffers to keep in sync with (if being a parent buffer). */
     164    RTLISTANCHOR                lstChildren;
     165    /** Pointer to parent buffer (if any). */
     166    PAUDIOMIXBUF                pParent;
     167    /** Intermediate structure for buffer conversion tasks. */
     168    PAUDIOSTREAMRATE            pRate;
     169    /** Internal representation of current volume used for mixing. */
     170    AUDMIXBUFVOL                Volume;
     171    /** This buffer's audio format.
     172     * @todo r=bird: This seems to be a value created by AUDMIXBUF_AUDIO_FMT_MAKE(),
     173     *       which is not define here.  Does this structure really belong here at
     174     *       all?  */
     175    AUDIOMIXBUFFMT              uAudioFmt;
     176    /** Audio input properties.
     177     * @note There is only one set of audio properties here because we have one
     178     *       mixer buffer for the guest side and a separate one for the host side.
     179     * @todo r=bird: Why exactly do we need to use separate mixer buffers?
     180     *       Couldn't we just have different conversion fuctions and save the
     181     *       extra copying? */
     182    PDMAUDIOPCMPROPS            Props;
     183    /** Standard conversion-to function for set uAudioFmt. */
     184    PFNAUDIOMIXBUFCONVTO        pfnConvTo;
     185    /** Standard conversion-from function for set uAudioFmt. */
     186    PFNAUDIOMIXBUFCONVFROM      pfnConvFrom;
     187
     188    /** Ratio of the associated parent stream's frequency by this stream's
     189     * frequency (1<<32), represented as a signed 64 bit integer.
     190     *
     191     * For example, if the parent stream has a frequency of 44 khZ, and this
     192     * stream has a frequency of 11 kHz, the ration then would be
     193     * (44/11 * (1 << 32)).
     194     *
     195     * Currently this does not get changed once assigned. */
     196    int64_t                     iFreqRatio;
     197} AUDIOMIXBUF;
     198
     199/** Magic value for AUDIOMIXBUF (Antonio Lucio Vivaldi). */
     200#define AUDIOMIXBUF_MAGIC           UINT32_C(0x16780304)
     201/** Dead mixer buffer magic. */
     202#define AUDIOMIXBUF_MAGIC_DEAD      UINT32_C(0x17410728)
     203
    26204
    27205/** Constructs 32 bit value for given frequency, number of channels, bits per sample and signed bit.
     
    54232
    55233
    56 int     AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);
    57 void    AudioMixBufDestroy(PPDMAUDIOMIXBUF pMixBuf);
    58 void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf);
    59 void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear);
    60 uint32_t AudioMixBufFree(PPDMAUDIOMIXBUF pMixBuf);
    61 uint32_t AudioMixBufFreeBytes(PPDMAUDIOMIXBUF pMixBuf);
    62 bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf);
    63 int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent);
    64 uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf);
    65 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
    66 int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
    67 int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, PPDMAUDIOFRAME *ppvSamples, uint32_t *pcFramesRead);
    68 uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf);
    69 uint32_t AudioMixBufUsedBytes(PPDMAUDIOMIXBUF pMixBuf);
    70 int         AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    71 int         AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, uint32_t offFrames,
     234int     AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);
     235void    AudioMixBufDestroy(PAUDIOMIXBUF pMixBuf);
     236void AudioMixBufClear(PAUDIOMIXBUF pMixBuf);
     237void AudioMixBufFinish(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear);
     238uint32_t AudioMixBufFree(PAUDIOMIXBUF pMixBuf);
     239uint32_t AudioMixBufFreeBytes(PAUDIOMIXBUF pMixBuf);
     240bool AudioMixBufIsEmpty(PAUDIOMIXBUF pMixBuf);
     241int AudioMixBufLinkTo(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUF pParent);
     242uint32_t AudioMixBufLive(PAUDIOMIXBUF pMixBuf);
     243int AudioMixBufMixToParent(PAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
     244int AudioMixBufMixToParentEx(PAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
     245int AudioMixBufPeekMutable(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, PPDMAUDIOFRAME *ppvSamples, uint32_t *pcFramesRead);
     246uint32_t AudioMixBufUsed(PAUDIOMIXBUF pMixBuf);
     247uint32_t AudioMixBufUsedBytes(PAUDIOMIXBUF pMixBuf);
     248int         AudioMixBufReadAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
     249int         AudioMixBufReadAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, uint32_t offFrames,
    72250                                void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    73 int         AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
    74 int         AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
     251int         AudioMixBufAcquireReadBlock(PAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
     252int         AudioMixBufAcquireReadBlockEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
    75253                                          void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
    76 void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames);
    77 uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf);
    78 void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf);
    79 void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol);
    80 uint32_t AudioMixBufSize(PPDMAUDIOMIXBUF pMixBuf);
    81 uint32_t AudioMixBufSizeBytes(PPDMAUDIOMIXBUF pMixBuf);
    82 void AudioMixBufUnlink(PPDMAUDIOMIXBUF pMixBuf);
    83 int         AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
    84 int         AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, uint32_t offFrames,
     254void AudioMixBufReleaseReadBlock(PAUDIOMIXBUF pMixBuf, uint32_t cFrames);
     255uint32_t AudioMixBufReadPos(PAUDIOMIXBUF pMixBuf);
     256void AudioMixBufReset(PAUDIOMIXBUF pMixBuf);
     257void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol);
     258uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf);
     259uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf);
     260void AudioMixBufUnlink(PAUDIOMIXBUF pMixBuf);
     261int         AudioMixBufWriteAt(PAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
     262int         AudioMixBufWriteAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, uint32_t offFrames,
    85263                                 const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
    86 int         AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
    87 int         AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
     264int         AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
     265int         AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
    88266                                   const void *pvBuf,uint32_t cbBuf, uint32_t *pcWritten);
    89 uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf);
     267uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf);
    90268
    91269#ifdef DEBUG
    92 void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf);
    93 void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf);
     270void AudioMixBufDbgPrint(PAUDIOMIXBUF pMixBuf);
     271void AudioMixBufDbgPrintChain(PAUDIOMIXBUF pMixBuf);
    94272#endif
    95273
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r88320 r88356  
    651651                     */
    652652                    PPDMAUDIOSTREAM pStream;
    653                     rc = pConn->pfnStreamCreate(pConn, &CfgHost, pCfg, &pStream);
     653                    rc = pConn->pfnStreamCreate(pConn, 0 /*fFlags*/, &CfgHost, pCfg, &pStream);
    654654                    if (RT_SUCCESS(rc))
    655655                    {
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r88320 r88356  
    2929
    3030#include <VBox/vmm/pdmaudioifs.h>
     31#include "AudioMixBuffer.h"
    3132
    3233
     
    5556/** Pointer to an audio mixer instance. */
    5657typedef AUDIOMIXER *PAUDIOMIXER;
     58
    5759
    5860/** Defines an audio mixer stream's flags. */
     
    201203    /** This sink's mixing buffer, acting as
    202204     * a parent buffer for all streams this sink owns. */
    203     PDMAUDIOMIXBUF          MixBuf;
     205    AUDIOMIXBUF          MixBuf;
    204206    /** Scratch buffer for multiplexing / mixing. Might be NULL if not needed. */
    205207    uint8_t                *pabScratchBuf;
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r88300 r88356  
    17751775    pCfgHost->Backend.cFramesPreBuffering = 0;
    17761776
    1777     int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream);
     1777    int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, 0 /*fFlags*/, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream);
    17781778    if (RT_SUCCESS(rc))
    17791779    {
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88309 r88356  
    6565    int overriden;
    6666} audio_option;
     67
     68/**
     69 * Audio stream context.
     70 *
     71 * Needed for separating data from the guest and host side (per stream).
     72 */
     73typedef struct DRVAUDIOSTREAMCTX
     74{
     75    /** The stream's audio configuration. */
     76    PDMAUDIOSTREAMCFG   Cfg;
     77    /** This stream's mixing buffer. */
     78    AUDIOMIXBUF         MixBuf;
     79} DRVAUDIOSTREAMCTX;
     80
     81/**
     82 * Extended stream structure.
     83 */
     84typedef struct DRVAUDIOSTREAM
     85{
     86    /** The publicly visible bit. */
     87    PDMAUDIOSTREAM      Core;
     88
     89    /** Just an extra magic to verify that we allocated the stream rather than some
     90     * faked up stuff from the device (DRVAUDIOSTREAM_MAGIC). */
     91    uintptr_t           uMagic;
     92
     93    /** List entry (some DrvAudio internal list). */
     94    RTLISTNODE          ListEntry;
     95
     96    /** Data to backend-specific stream data.
     97     *  This data block will be casted by the backend to access its backend-dependent data.
     98     *
     99     *  That way the backends do not have access to the audio connector's data. */
     100    void               *pvBackend;
     101
     102    /** For output streams this indicates whether the stream has reached
     103     *  its playback threshold, e.g. is playing audio.
     104     *  For input streams this  indicates whether the stream has enough input
     105     *  data to actually start reading audio. */
     106    bool                fThresholdReached;
     107    /** Do not use the mixing buffers (Guest::MixBuf, Host::MixBuf). */
     108    bool                fNoMixBufs;
     109    bool                afPadding[2];
     110
     111    /** Number of (re-)tries while re-initializing the stream. */
     112    uint32_t            cTriesReInit;
     113
     114    /** The guest side of the stream. */
     115    DRVAUDIOSTREAMCTX   Guest;
     116    /** The host side of the stream. */
     117    DRVAUDIOSTREAMCTX   Host;
     118
     119
     120    /** Timestamp (in ns) since last trying to re-initialize.
     121     *  Might be 0 if has not been tried yet. */
     122    uint64_t            nsLastReInit;
     123    /** Timestamp (in ns) since last iteration. */
     124    uint64_t            nsLastIterated;
     125    /** Timestamp (in ns) since last playback / capture. */
     126    uint64_t            nsLastPlayedCaptured;
     127    /** Timestamp (in ns) since last read (input streams) or
     128     *  write (output streams). */
     129    uint64_t            nsLastReadWritten;
     130
     131
     132    /** Union for input/output specifics depending on enmDir. */
     133    union
     134    {
     135        /**
     136         * The specifics for an audio input stream.
     137         */
     138        struct
     139        {
     140            struct
     141            {
     142                /** File for writing stream reads. */
     143                PPDMAUDIOFILE   pFileStreamRead;
     144                /** File for writing non-interleaved captures. */
     145                PPDMAUDIOFILE   pFileCaptureNonInterleaved;
     146            } Dbg;
     147            struct
     148            {
     149                STAMCOUNTER     TotalFramesCaptured;
     150                STAMCOUNTER     AvgFramesCaptured;
     151                STAMCOUNTER     TotalTimesCaptured;
     152                STAMCOUNTER     TotalFramesRead;
     153                STAMCOUNTER     AvgFramesRead;
     154                STAMCOUNTER     TotalTimesRead;
     155            } Stats;
     156        } In;
     157
     158        /**
     159         * The specifics for an audio output stream.
     160         */
     161        struct
     162        {
     163            struct
     164            {
     165                /** File for writing stream writes. */
     166                PPDMAUDIOFILE   pFileStreamWrite;
     167                /** File for writing stream playback. */
     168                PPDMAUDIOFILE   pFilePlayNonInterleaved;
     169            } Dbg;
     170            struct
     171            {
     172                STAMCOUNTER     TotalFramesPlayed;
     173                STAMCOUNTER     AvgFramesPlayed;
     174                STAMCOUNTER     TotalTimesPlayed;
     175                STAMCOUNTER     TotalFramesWritten;
     176                STAMCOUNTER     AvgFramesWritten;
     177                STAMCOUNTER     TotalTimesWritten;
     178                uint32_t        cbBackendWritableBefore;
     179                uint32_t        cbBackendWritableAfter;
     180            } Stats;
     181            /** Hack alert: Max writable amount reported by the backend.
     182             * This is used to aid buffer underrun detection in DrvAudio while playing.
     183             * Ideally, the backend should have a method for querying number of buffered
     184             * bytes instead.  However this will do for now. */
     185            uint32_t            cbBackendMaxWritable;
     186        } Out;
     187    } RT_UNION_NM(u);
     188} DRVAUDIOSTREAM;
     189/** Pointer to an extended stream structure. */
     190typedef DRVAUDIOSTREAM *PDRVAUDIOSTREAM;
     191
     192/** Value for DRVAUDIOSTREAM::uMagic (Johann Sebastian Bach). */
     193#define DRVAUDIOSTREAM_MAGIC        UINT32_C(0x16850331)
     194/** Value for DRVAUDIOSTREAM::uMagic after destruction */
     195#define DRVAUDIOSTREAM_MAGIC_DEAD   UINT32_C(0x17500728)
     196
    67197
    68198#ifdef VBOX_WITH_STATISTICS
     
    152282    /** Pointer to audio driver below us. */
    153283    PPDMIHOSTAUDIO          pHostDrvAudio;
    154     /** List of audio streams. */
     284    /** List of audio streams (DRVAUDIOSTREAM). */
    155285    RTLISTANCHOR            lstStreams;
    156286    /** Audio configuration settings retrieved from the backend. */
     
    202332#endif
    203333
    204 static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream);
    205 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    206 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    207 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
    208 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    209 static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream);
    210 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    211 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    212 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    213 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    214 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
     334static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd);
     335static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd);
     336static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
     337static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
     338static void drvAudioStreamFree(PDRVAUDIOSTREAM pStream);
     339static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
     340static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
     341static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
     342static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
    215343
    216344
     
    456584    if (!pStream)
    457585        return VINF_SUCCESS;
     586    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     587    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     588    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     589    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    458590
    459591    int rc = RTCritSectEnter(&pThis->CritSect);
     
    462594    LogFlowFunc(("[%s] enmStreamCmd=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd)));
    463595
    464     rc = drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);
     596    rc = drvAudioStreamControlInternal(pThis, pStreamEx, enmStreamCmd);
    465597
    466598    RTCritSectLeave(&pThis->CritSect);
     
    472604 *
    473605 * @returns VBox status code.
    474  * @param   pThis               Pointer to driver instance.
    475  * @param   pStream             Stream to control.
    476  * @param   enmStreamCmd        Control command.
    477  */
    478 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    479 {
    480     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    481     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     606 * @param   pThis           Pointer to driver instance.
     607 * @param   pStreamEx       Stream to control.
     608 * @param   enmStreamCmd    Control command.
     609 */
     610static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd)
     611{
     612    AssertPtr(pThis);
     613    AssertPtr(pStreamEx);
    482614
    483615#ifdef LOG_ENABLED
    484616    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    485617#endif
    486     LogFunc(("[%s] enmStreamCmd=%s fStatus=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd),
    487              dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
     618    LogFunc(("[%s] enmStreamCmd=%s fStatus=%s\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd),
     619             dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
    488620
    489621    int rc = VINF_SUCCESS;
     
    493625        case PDMAUDIOSTREAMCMD_ENABLE:
    494626        {
    495             if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED))
     627            if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED))
    496628            {
    497629                /* Is a pending disable outstanding? Then disable first. */
    498                 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
    499                     rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     630                if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
     631                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    500632
    501633                if (RT_SUCCESS(rc))
    502                     rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_ENABLE);
     634                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE);
    503635
    504636                if (RT_SUCCESS(rc))
    505                     pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
     637                    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
    506638            }
    507639            break;
     
    510642        case PDMAUDIOSTREAMCMD_DISABLE:
    511643        {
    512             if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
     644            if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
    513645            {
    514646                /*
     
    517649                 * closing the stream.
    518650                 */
    519                 if (pStream->enmDir == PDMAUDIODIR_OUT)
     651                if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
    520652                {
    521                     LogFunc(("[%s] Pending disable/pause\n", pStream->szName));
    522                     pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE;
     653                    LogFunc(("[%s] Pending disable/pause\n", pStreamEx->Core.szName));
     654                    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE;
    523655                }
    524656
    525657                /* Can we close the host stream as well (not in pending disable mode)? */
    526                 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
     658                if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
    527659                {
    528                     rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     660                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    529661                    if (RT_SUCCESS(rc))
    530                         drvAudioStreamResetInternal(pThis, pStream);
     662                        drvAudioStreamResetInternal(pThis, pStreamEx);
    531663                }
    532664            }
     
    536668        case PDMAUDIOSTREAMCMD_PAUSE:
    537669        {
    538             if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
     670            if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
    539671            {
    540                 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_PAUSE);
     672                rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_PAUSE);
    541673                if (RT_SUCCESS(rc))
    542                     pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
     674                    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
    543675            }
    544676            break;
     
    547679        case PDMAUDIOSTREAMCMD_RESUME:
    548680        {
    549             if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
     681            if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
    550682            {
    551                 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_RESUME);
     683                rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_RESUME);
    552684                if (RT_SUCCESS(rc))
    553                     pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
     685                    pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
    554686            }
    555687            break;
     
    558690        case PDMAUDIOSTREAMCMD_DROP:
    559691        {
    560             rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DROP);
     692            rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DROP);
    561693            if (RT_SUCCESS(rc))
    562                 drvAudioStreamDropInternal(pThis, pStream);
     694                drvAudioStreamDropInternal(pThis, pStreamEx);
    563695            break;
    564696        }
     
    570702
    571703    if (RT_FAILURE(rc))
    572         LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));
     704        LogFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
    573705
    574706    return rc;
     
    577709/**
    578710 * Controls a stream's backend.
    579  * If the stream has no backend available, VERR_NOT_FOUND is returned.
     711 *
     712 * If the stream has no backend available, VERR_NOT_FOUND is returned
     713 * (bird: actually the code returns VINF_SUCCESS).
    580714 *
    581715 * @returns VBox status code.
    582  * @param   pThis               Pointer to driver instance.
    583  * @param   pStream             Stream to control.
    584  * @param   enmStreamCmd        Control command.
    585  */
    586 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    587 {
    588     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    589     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     716 * @param   pThis           Pointer to driver instance.
     717 * @param   pStreamEx       Stream to control.
     718 * @param   enmStreamCmd    Control command.
     719 */
     720static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd)
     721{
     722    AssertPtr(pThis);
     723    AssertPtr(pStreamEx);
    590724
    591725#ifdef LOG_ENABLED
    592726    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    593727#endif
    594     LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd),
    595                  dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
     728    LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd),
     729                 dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
    596730
    597731    if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */
     
    613747     * See @bugref{9882}.
    614748     */
    615     const bool fEnabled =    (   pStream->enmDir == PDMAUDIODIR_IN
     749    const bool fEnabled =    (   pStreamEx->Core.enmDir == PDMAUDIODIR_IN
    616750                              && pThis->In.fEnabled)
    617                           || (   pStream->enmDir == PDMAUDIODIR_OUT
     751                          || (   pStreamEx->Core.enmDir == PDMAUDIODIR_OUT
    618752                              && pThis->Out.fEnabled);
    619753
    620     LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStream->szName,
    621                                                               PDMAudioDirGetName(pStream->enmDir),
     754    LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStreamEx->Core.szName,
     755                                                              PDMAudioDirGetName(pStreamEx->Core.enmDir),
    622756                                                              fEnabled ? "enabled" : "disabled"));
    623757    switch (enmStreamCmd)
     
    626760        {
    627761            if (fEnabled)
    628                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_ENABLE);
     762                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_ENABLE);
    629763            break;
    630764        }
     
    632766        case PDMAUDIOSTREAMCMD_DISABLE:
    633767        {
    634             rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DISABLE);
     768            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DISABLE);
    635769            break;
    636770        }
     
    639773        {
    640774            if (fEnabled) /* Needed, as resume below also is being checked for. */
    641                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_PAUSE);
     775                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_PAUSE);
    642776            break;
    643777        }
     
    646780        {
    647781            if (fEnabled)
    648                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_RESUME);
     782                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_RESUME);
    649783            break;
    650784        }
     
    652786        case PDMAUDIOSTREAMCMD_DRAIN:
    653787        {
    654             rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);
     788            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);
    655789            break;
    656790        }
     
    658792        case PDMAUDIOSTREAMCMD_DROP:
    659793        {
    660             rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DROP);
     794            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DROP);
    661795            break;
    662796        }
    663797
    664798        default:
    665         {
    666             AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd));
    667             rc = VERR_NOT_IMPLEMENTED;
    668             break;
    669         }
     799            AssertMsgFailedReturn(("Command %RU32 not implemented\n", enmStreamCmd), VERR_INTERNAL_ERROR_2);
    670800    }
    671801
     
    676806            && rc != VERR_AUDIO_STREAM_NOT_READY)
    677807        {
    678             LogRel(("Audio: %s stream '%s' failed with %Rrc\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStream->szName, rc));
    679         }
    680 
    681         LogFunc(("[%s] %s failed with %Rrc\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd), rc));
     808            LogRel(("Audio: %s stream '%s' failed with %Rrc\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStreamEx->Core.szName, rc));
     809        }
     810
     811        LogFunc(("[%s] %s failed with %Rrc\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd), rc));
    682812    }
    683813
     
    688818 * Frees an audio stream and its allocated resources.
    689819 *
    690  * @param   pStream             Audio stream to free.
    691  *                              After this call the pointer will not be valid anymore.
    692  */
    693 static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream)
    694 {
    695     if (pStream)
    696     {
    697         LogFunc(("[%s]\n", pStream->szName));
    698         Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC);
    699 
    700         pStream->uMagic    = ~PDMAUDIOSTREAM_MAGIC;
    701         pStream->pvBackend = NULL;
    702 
    703         RTMemFree(pStream);
     820 * @param   pStreamEx   Audio stream to free. After this call the pointer will
     821 *                      not be valid anymore.
     822 */
     823static void drvAudioStreamFree(PDRVAUDIOSTREAM pStreamEx)
     824{
     825    if (pStreamEx)
     826    {
     827        LogFunc(("[%s]\n", pStreamEx->Core.szName));
     828        Assert(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC);
     829        Assert(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC);
     830
     831        pStreamEx->Core.uMagic    = ~PDMAUDIOSTREAM_MAGIC;
     832        pStreamEx->pvBackend = NULL;
     833        pStreamEx->uMagic         = DRVAUDIOSTREAM_MAGIC_DEAD;
     834
     835        RTMemFree(pStreamEx);
    704836    }
    705837}
     
    720852
    721853    /* Mark all host streams to re-initialize. */
    722     PPDMAUDIOSTREAM pStream;
    723     RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
    724     {
    725         pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
    726         pStream->cTriesReInit   = 0;
    727         pStream->tsLastReInitNs = 0;
     854    PDRVAUDIOSTREAM pStreamEx;
     855    RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
     856    {
     857        pStreamEx->Core.fStatus        |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
     858        pStreamEx->cTriesReInit    = 0;
     859        pStreamEx->nsLastReInit        = 0;
    728860    }
    729861
     
    747879 *
    748880 * @returns VBox status code.
    749  * @param   pThis               Pointer to driver instance.
    750  * @param   pStream             Stream to re-initialize.
    751  */
    752 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
    753 {
    754     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    755     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    756 
    757     LogFlowFunc(("[%s]\n", pStream->szName));
     881 * @param   pThis       Pointer to driver instance.
     882 * @param   pStreamEx   Stream to re-initialize.
     883 */
     884static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
     885{
     886    AssertPtr(pThis);
     887    AssertPtr(pStreamEx);
     888
     889    LogFlowFunc(("[%s]\n", pStreamEx->Core.szName));
    758890
    759891    /*
    760892     * Gather current stream status.
    761893     */
    762     const bool fIsEnabled = RT_BOOL(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */
     894    const bool fIsEnabled = RT_BOOL(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */
    763895
    764896    /*
    765897     * Destroy and re-create stream on backend side.
    766898     */
    767     int rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     899    int rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    768900    if (RT_SUCCESS(rc))
    769901    {
    770         rc = drvAudioStreamDestroyInternalBackend(pThis, pStream);
     902        rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
    771903        if (RT_SUCCESS(rc))
    772904        {
    773905            PDMAUDIOSTREAMCFG CfgHostAcq;
    774             rc = drvAudioStreamCreateInternalBackend(pThis, pStream, &pStream->Host.Cfg, &CfgHostAcq);
    775             /** @todo Validate (re-)acquired configuration with pStream->Host.Cfg? */
     906            rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, &pStreamEx->Host.Cfg, &CfgHostAcq);
     907            /** @todo Validate (re-)acquired configuration with pStreamEx->Core.Host.Cfg? */
    776908            if (RT_SUCCESS(rc))
    777909            {
    778910#ifdef LOG_ENABLED
    779                 LogFunc(("[%s] Acquired host format:\n",  pStream->szName));
     911                LogFunc(("[%s] Acquired host format:\n",  pStreamEx->Core.szName));
    780912                PDMAudioStrmCfgLog(&CfgHostAcq);
    781913#endif
     
    785917
    786918    /* Drop all old data. */
    787     drvAudioStreamDropInternal(pThis, pStream);
     919    drvAudioStreamDropInternal(pThis, pStreamEx);
    788920
    789921    /*
     
    791923     */
    792924    if (fIsEnabled)
    793         rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_ENABLE);
     925        rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE);
    794926
    795927    if (RT_FAILURE(rc))
    796         LogRel(("Audio: Re-initializing stream '%s' failed with %Rrc\n", pStream->szName, rc));
    797 
    798     LogFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
     928        LogRel(("Audio: Re-initializing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
     929
     930    LogFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
    799931    return rc;
    800932}
     
    803935 * Drops all audio data (and associated state) of a stream.
    804936 *
    805  * @param   pThis               Pointer to driver instance.
    806  * @param   pStream             Stream to drop data for.
    807  */
    808 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     937 * @param   pThis       Pointer to driver instance.
     938 * @param   pStreamEx   Stream to drop data for.
     939 */
     940static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
    809941{
    810942    RT_NOREF(pThis);
    811943
    812     LogFunc(("[%s]\n", pStream->szName));
    813 
    814     AudioMixBufReset(&pStream->Guest.MixBuf);
    815     AudioMixBufReset(&pStream->Host.MixBuf);
    816 
    817     pStream->tsLastIteratedNs       = 0;
    818     pStream->tsLastPlayedCapturedNs = 0;
    819     pStream->tsLastReadWrittenNs    = 0;
    820 
    821     pStream->fThresholdReached = false;
    822 }
    823 
    824 /**
    825  * Resets a given audio stream.
    826  *
    827  * @param   pThis               Pointer to driver instance.
    828  * @param   pStream             Stream to reset.
    829  */
    830 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
    831 {
    832     drvAudioStreamDropInternal(pThis, pStream);
    833 
    834     LogFunc(("[%s]\n", pStream->szName));
    835 
    836     pStream->fStatus        = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
    837     pStream->fWarningsShown = PDMAUDIOSTREAM_WARN_FLAGS_NONE;
     944    LogFunc(("[%s]\n", pStreamEx->Core.szName));
     945
     946    AudioMixBufReset(&pStreamEx->Guest.MixBuf);
     947    AudioMixBufReset(&pStreamEx->Host.MixBuf);
     948
     949    pStreamEx->fThresholdReached    = false;
     950    pStreamEx->nsLastIterated       = 0;
     951    pStreamEx->nsLastPlayedCaptured = 0;
     952    pStreamEx->nsLastReadWritten    = 0;
     953}
     954
     955/**
     956 * Resets the given audio stream.
     957 *
     958 * @param   pThis       Pointer to driver instance.
     959 * @param   pStreamEx   Stream to reset.
     960 */
     961static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
     962{
     963    drvAudioStreamDropInternal(pThis, pStreamEx);
     964
     965    LogFunc(("[%s]\n", pStreamEx->Core.szName));
     966
     967    pStreamEx->Core.fStatus        = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
     968    pStreamEx->Core.fWarningsShown = PDMAUDIOSTREAM_WARN_FLAGS_NONE;
    838969
    839970#ifdef VBOX_WITH_STATISTICS
     
    841972     * Reset statistics.
    842973     */
    843     if (pStream->enmDir == PDMAUDIODIR_IN)
    844     {
    845         STAM_COUNTER_RESET(&pStream->In.Stats.TotalFramesCaptured);
    846         STAM_COUNTER_RESET(&pStream->In.Stats.TotalFramesRead);
    847         STAM_COUNTER_RESET(&pStream->In.Stats.TotalTimesCaptured);
    848         STAM_COUNTER_RESET(&pStream->In.Stats.TotalTimesRead);
    849     }
    850     else if (pStream->enmDir == PDMAUDIODIR_OUT)
    851     {
    852         STAM_COUNTER_RESET(&pStream->Out.Stats.TotalFramesPlayed);
    853         STAM_COUNTER_RESET(&pStream->Out.Stats.TotalFramesWritten);
    854         STAM_COUNTER_RESET(&pStream->Out.Stats.TotalTimesPlayed);
    855         STAM_COUNTER_RESET(&pStream->Out.Stats.TotalTimesWritten);
     974    if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
     975    {
     976        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalFramesCaptured);
     977        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalFramesRead);
     978        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalTimesCaptured);
     979        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalTimesRead);
     980    }
     981    else if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
     982    {
     983        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalFramesPlayed);
     984        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalFramesWritten);
     985        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalTimesPlayed);
     986        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalTimesWritten);
    856987    }
    857988    else
     
    868999    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    8691000    AssertPtr(pThis);
     1001
     1002    /*
     1003     * Check input and sanity.
     1004     */
    8701005    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    871     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    872     AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
    873     AssertReturn(cbBuf,         VERR_INVALID_PARAMETER);
     1006    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     1007    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     1008    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1009    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
    8741010    AssertPtrNullReturn(pcbWritten, VERR_INVALID_PARAMETER);
    8751011
    876     AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT,
     1012    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1013    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1014    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
    8771015              ("Stream '%s' is not an output stream and therefore cannot be written to (direction is '%s')\n",
    878                pStream->szName, PDMAudioDirGetName(pStream->enmDir)));
    879 
    880     AssertMsg(PDMAudioPropsIsSizeAligned(&pStream->Guest.Cfg.Props, cbBuf),
    881               ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStream->szName, cbBuf));
    882 
    883     uint32_t cbWrittenTotal = 0;
     1016               pStreamEx->Core.szName, PDMAudioDirGetName(pStreamEx->Core.enmDir)));
     1017
     1018    AssertMsg(PDMAudioPropsIsSizeAligned(&pStreamEx->Guest.Cfg.Props, cbBuf),
     1019              ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStreamEx->Core.szName, cbBuf));
     1020
     1021    STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out); /* (stopped in drvAudioStreamPlayLocked) */
    8841022
    8851023    int rc = RTCritSectEnter(&pThis->CritSect);
    8861024    AssertRCReturn(rc, rc);
    8871025
    888 #ifdef VBOX_WITH_STATISTICS
    889     STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out);
    890 #endif
    891 
    892     /* Whether to discard the incoming data or not. */
    893     bool fToBitBucket = false;
    894 
    895     do
    896     {
    897         if (!PDMAudioStrmStatusIsReady(pStream->fStatus))
    898         {
    899             rc = VERR_AUDIO_STREAM_NOT_READY;
    900             break;
    901         }
    902 
    903         /* If output is disabled on a per-driver level, send data to the bit bucket instead. See @bugref{9882}. */
    904         if (!pThis->Out.fEnabled)
    905         {
    906             fToBitBucket = true;
    907             break;
    908         }
    909 
    910         if (pThis->pHostDrvAudio)
    911         {
    912             /* If the backend's stream is not writable, all written data goes to /dev/null. */
    913             if (!PDMAudioStrmStatusCanWrite(
    914                 pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend)))
     1026    /*
     1027     * First check that we can write to the stream, and if not,
     1028     * whether to just drop the input into the bit bucket.
     1029     */
     1030    if (PDMAudioStrmStatusIsReady(pStreamEx->Core.fStatus))
     1031    {
     1032        if (   !pThis->Out.fEnabled         /* (see @bugref{9882}) */
     1033            || pThis->pHostDrvAudio == NULL /* (we used to work this condition differently) */
     1034            || !PDMAudioStrmStatusCanWrite(pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStreamEx->pvBackend)))
     1035        {
     1036            Log3Func(("[%s] Backend stream %s, discarding the data\n", pStreamEx->Core.szName,
     1037                      !pThis->Out.fEnabled ? "disabled" : !pThis->pHostDrvAudio ? "not attached" : "not ready yet"));
     1038            *pcbWritten = cbBuf;
     1039        }
     1040        /*
     1041         * No-mixing buffer mode:  Write the data directly to the backend, unless
     1042         * we're prebuffering.  There will be no pfnStreamPlay call in this mode.
     1043         */
     1044        else if (pStreamEx->fNoMixBufs)
     1045        {
     1046            rc = VERR_NOT_IMPLEMENTED;
     1047        }
     1048        /*
     1049         * Legacy mode:  Here we just dump the data in the guest side mixing buffer
     1050         * and then mixes it into the host side buffer.  Later the device code will
     1051         * make a pfnStreamPlay call which  recodes the data from the host side
     1052         * buffer and writes it to the host backend.
     1053         */
     1054        else
     1055        {
     1056            uint32_t cbWrittenTotal = 0;
     1057
     1058            const uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf);
     1059            if (cbFree < cbBuf)
     1060                LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n",
     1061                         PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStreamEx->Core.szName));
     1062
     1063            uint32_t cbToWrite = RT_MIN(cbBuf, cbFree);
     1064            if (cbToWrite)
    9151065            {
    916                 fToBitBucket = true;
    917                 break;
    918             }
    919         }
    920 
    921         const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf);
    922         if (cbFree < cbBuf)
    923             LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n",
    924                      PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStream->szName));
    925 
    926         uint32_t cbToWrite = RT_MIN(cbBuf, cbFree);
    927         if (!cbToWrite)
    928         {
    929             rc = VERR_BUFFER_OVERFLOW;
    930             break;
    931         }
    932 
    933         /* We use the guest side mixing buffer as an intermediate buffer to do some
    934          * (first) processing (if needed), so always write the incoming data at offset 0. */
    935         uint32_t cfGstWritten = 0;
    936         rc = AudioMixBufWriteAt(&pStream->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten);
    937         if (   RT_FAILURE(rc)
    938             || !cfGstWritten)
    939         {
    940             AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cfWritten=%RU32, rc=%Rrc\n",
    941                              pStream->szName, cbToWrite, cfGstWritten, rc));
    942             break;
    943         }
    944 
    945         if (pThis->Out.Cfg.Dbg.fEnabled)
    946             AudioHlpFileWrite(pStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
    947 
    948         uint32_t cfGstMixed = 0;
    949         if (cfGstWritten)
    950         {
    951             int rc2 = AudioMixBufMixToParentEx(&pStream->Guest.MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */,
    952                                                &cfGstMixed /* pcSrcMixed */);
    953             if (RT_FAILURE(rc2))
    954             {
    955                 AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
    956                                  pStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2));
     1066                /* We use the guest side mixing buffer as an intermediate buffer to do some
     1067                 * (first) processing (if needed), so always write the incoming data at offset 0. */
     1068                uint32_t cFramesGstWritten = 0;
     1069                rc = AudioMixBufWriteAt(&pStreamEx->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cFramesGstWritten);
     1070                if (RT_SUCCESS(rc) && cFramesGstWritten > 0)
     1071                {
     1072                    if (pThis->Out.Cfg.Dbg.fEnabled)
     1073                        AudioHlpFileWrite(pStreamEx->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
     1074
     1075                    uint32_t cFramesGstMixed = 0;
     1076                    if (cFramesGstWritten)
     1077                    {
     1078                        int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Guest.MixBuf, 0 /* cSrcOffset */,
     1079                                                           cFramesGstWritten /* cSrcFrames */, &cFramesGstMixed /* pcSrcMixed */);
     1080                        if (RT_SUCCESS(rc2))
     1081                        {
     1082                            const uint64_t tsNowNs = RTTimeNanoTS();
     1083
     1084                            Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n",
     1085                                      pStreamEx->Core.szName, cFramesGstWritten, PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cFramesGstWritten)));
     1086
     1087                            Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n",
     1088                                      pStreamEx->Core.szName, tsNowNs - pStreamEx->nsLastReadWritten,
     1089                                      (tsNowNs - pStreamEx->nsLastReadWritten) / RT_NS_1MS,
     1090                                      PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)),
     1091                                      AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf)));
     1092
     1093                            pStreamEx->nsLastReadWritten = tsNowNs;
     1094                            /* Keep going. */
     1095                        }
     1096                        else
     1097                        {
     1098                            AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
     1099                                             pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, cFramesGstMixed, rc2));
     1100                            if (RT_SUCCESS(rc))
     1101                                rc = rc2;
     1102                        }
     1103
     1104                        cbWrittenTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cFramesGstWritten);
     1105
     1106                        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten,  cFramesGstWritten);
     1107                        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cFramesGstMixed);
     1108                        Assert(cFramesGstWritten >= cFramesGstMixed);
     1109                        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut,  cFramesGstWritten - cFramesGstMixed);
     1110                        STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten,   cbWrittenTotal);
     1111
     1112                        STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesWritten, cFramesGstWritten);
     1113                        STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesWritten);
     1114                    }
     1115
     1116                    Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cFramesGstWritten=%RU32, "
     1117                              "cFramesGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n",
     1118                              pStreamEx->Core.szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStreamEx->Host.MixBuf),
     1119                              AudioMixBufLive(&pStreamEx->Host.MixBuf), cFramesGstWritten, cFramesGstMixed, cbWrittenTotal, rc));
     1120                }
     1121                else
     1122                    AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cFramesGstWritten=%RU32, rc=%Rrc\n",
     1123                                     pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, rc));
    9571124            }
    9581125            else
    959             {
    960                 const uint64_t tsNowNs = RTTimeNanoTS();
    961 
    962                 Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n",
    963                           pStream->szName, cfGstWritten, PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfGstWritten)));
    964 
    965                 Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n",
    966                           pStream->szName, tsNowNs - pStream->tsLastReadWrittenNs,
    967                           (tsNowNs - pStream->tsLastReadWrittenNs) / RT_NS_1MS,
    968                           PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)),
    969                           AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf)));
    970 
    971                 pStream->tsLastReadWrittenNs = tsNowNs;
    972                 /* Keep going. */
    973             }
    974 
    975             if (RT_SUCCESS(rc))
    976                 rc = rc2;
    977 
    978             cbWrittenTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfGstWritten);
    979 
    980 #ifdef VBOX_WITH_STATISTICS
    981             STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten,  cfGstWritten);
    982             STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cfGstMixed);
    983             Assert(cfGstWritten >= cfGstMixed);
    984             STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut,  cfGstWritten - cfGstMixed);
    985             STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten,   cbWrittenTotal);
    986 
    987             STAM_COUNTER_ADD(&pStream->Out.Stats.TotalFramesWritten, cfGstWritten);
    988             STAM_COUNTER_INC(&pStream->Out.Stats.TotalTimesWritten);
    989 #endif
    990         }
    991 
    992         Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cfGstWritten=%RU32, "
    993                   "cfGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n",
    994                   pStream->szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStream->Host.MixBuf),
    995                   AudioMixBufLive(&pStream->Host.MixBuf), cfGstWritten, cfGstMixed, cbWrittenTotal, rc));
    996 
    997     } while (0);
     1126                rc = VERR_BUFFER_OVERFLOW;
     1127            if (pcbWritten)
     1128                *pcbWritten = cbWrittenTotal;
     1129        }
     1130    }
     1131    else
     1132        rc = VERR_AUDIO_STREAM_NOT_READY;
    9981133
    9991134    RTCritSectLeave(&pThis->CritSect);
    1000 
    1001     if (RT_SUCCESS(rc))
    1002     {
    1003         if (fToBitBucket)
    1004         {
    1005             Log3Func(("[%s] Backend stream not ready (yet), discarding written data\n", pStream->szName));
    1006             cbWrittenTotal = cbBuf; /* Report all data as being written to the caller. */
    1007         }
    1008 
    1009         if (pcbWritten)
    1010             *pcbWritten = cbWrittenTotal;
    1011     }
    1012 
    10131135    return rc;
    10141136}
     
    10211143   AssertPtrReturn(pInterface, UINT32_MAX);
    10221144   AssertPtrReturn(pStream,    UINT32_MAX);
    1023 
    1024    NOREF(pInterface);
    1025 
    1026    return ++pStream->cRefs;
     1145   AssertReturn(pStream->uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX);
     1146   AssertReturn(((PDRVAUDIOSTREAM)pStream)->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX);
     1147   RT_NOREF(pInterface);
     1148
     1149   uint32_t const cRefs = ASMAtomicIncU32(&pStream->cRefs);
     1150   Assert(cRefs > 1);
     1151   Assert(cRefs < _1K);
     1152
     1153   return cRefs;
    10271154}
    10281155
     
    10341161   AssertPtrReturn(pInterface, UINT32_MAX);
    10351162   AssertPtrReturn(pStream,    UINT32_MAX);
    1036 
    1037    NOREF(pInterface);
    1038 
    1039    if (pStream->cRefs > 1) /* 1 reference always is kept by this audio driver. */
    1040        pStream->cRefs--;
    1041 
    1042    return pStream->cRefs;
     1163   AssertReturn(pStream->uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX);
     1164   AssertReturn(((PDRVAUDIOSTREAM)pStream)->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX);
     1165   RT_NOREF(pInterface);
     1166
     1167   uint32_t cRefs = ASMAtomicDecU32(&pStream->cRefs);
     1168   AssertStmt(cRefs >= 1, cRefs = ASMAtomicIncU32(&pStream->cRefs));
     1169   Assert(cRefs < _1K);
     1170
     1171   return cRefs;
    10431172}
    10441173
     
    10501179    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    10511180    AssertPtr(pThis);
    1052     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1181    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     1182    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     1183    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1184    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    10531185
    10541186    int rc = RTCritSectEnter(&pThis->CritSect);
    10551187    AssertRCReturn(rc, rc);
    10561188
    1057     rc = drvAudioStreamIterateInternal(pThis, pStream);
     1189    rc = drvAudioStreamIterateInternal(pThis, pStreamEx);
    10581190
    10591191    RTCritSectLeave(&pThis->CritSect);
     
    10701202 *       needed for the host device (re-)enumeration.
    10711203 *
    1072  * @param   pThis               Pointer to driver instance.
    1073  * @param   pStream             Stream to check and maybe re-initialize.
    1074  */
    1075 static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
    1076 {
    1077     if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT)
     1204 * @param   pThis       Pointer to driver instance.
     1205 * @param   pStreamEx   Stream to check and maybe re-initialize.
     1206 */
     1207static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
     1208{
     1209    if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT)
    10781210    {
    10791211        const unsigned cMaxTries = 3; /** @todo Make this configurable? */
     
    10811213
    10821214        /* Throttle re-initializing streams on failure. */
    1083         if (   pStream->cTriesReInit < cMaxTries
    1084             && tsNowNs - pStream->tsLastReInitNs >= RT_NS_1SEC * pStream->cTriesReInit) /** @todo Ditto. */
     1215        if (   pStreamEx->cTriesReInit < cMaxTries
     1216            && tsNowNs - pStreamEx->nsLastReInit >= RT_NS_1SEC * pStreamEx->cTriesReInit) /** @todo Ditto. */
    10851217        {
    10861218#ifdef VBOX_WITH_AUDIO_ENUM
     
    11021234#endif /* VBOX_WITH_AUDIO_ENUM */
    11031235
    1104             int rc = drvAudioStreamReInitInternal(pThis, pStream);
     1236            int rc = drvAudioStreamReInitInternal(pThis, pStreamEx);
    11051237            if (RT_FAILURE(rc))
    11061238            {
    1107                 pStream->cTriesReInit++;
    1108                 pStream->tsLastReInitNs = tsNowNs;
     1239                pStreamEx->cTriesReInit++;
     1240                pStreamEx->nsLastReInit = tsNowNs;
    11091241            }
    11101242            else
    11111243            {
    11121244                /* Remove the pending re-init flag on success. */
    1113                 pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
     1245                pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
    11141246            }
    11151247        }
     
    11181250            /* Did we exceed our tries re-initializing the stream?
    11191251             * Then this one is dead-in-the-water, so disable it for further use. */
    1120             if (pStream->cTriesReInit == cMaxTries)
     1252            if (pStreamEx->cTriesReInit == cMaxTries)
    11211253            {
    11221254                LogRel(("Audio: Re-initializing stream '%s' exceeded maximum retries (%u), leaving as disabled\n",
    1123                         pStream->szName, cMaxTries));
     1255                        pStreamEx->Core.szName, cMaxTries));
    11241256
    11251257                /* Don't try to re-initialize anymore and mark as disabled. */
    1126                 pStream->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);
     1258                pStreamEx->Core.fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);
    11271259
    11281260                /* Note: Further writes to this stream go to / will be read from the bit bucket (/dev/null) from now on. */
     
    11331265        char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    11341266#endif
    1135         Log3Func(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
     1267        Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
    11361268    }
    11371269}
     
    11431275 *
    11441276 * @returns VBox status code.
    1145  * @param   pThis               Pointer to driver instance.
    1146  * @param   pStream             Stream to iterate.
    1147  */
    1148 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     1277 * @param   pThis       Pointer to driver instance.
     1278 * @param   pStreamEx   Stream to iterate.
     1279 */
     1280static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
    11491281{
    11501282    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     
    11531285        return VINF_SUCCESS;
    11541286
    1155     if (!pStream)
    1156         return VINF_SUCCESS;
    1157 
    11581287    /* Is the stream scheduled for re-initialization? Do so now. */
    1159     drvAudioStreamMaybeReInit(pThis, pStream);
     1288    drvAudioStreamMaybeReInit(pThis, pStreamEx);
    11601289
    11611290#ifdef LOG_ENABLED
    11621291    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    11631292#endif
    1164     Log3Func(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
     1293    Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
    11651294
    11661295    /* Not enabled or paused? Skip iteration. */
    1167     if (   !(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
    1168         ||  (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
     1296    if (   !(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
     1297        ||  (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
    11691298    {
    11701299        return VINF_SUCCESS;
     
    11781307    do
    11791308    {
    1180         rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStream->pvBackend);
     1309        rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStreamEx->pvBackend);
    11811310        if (RT_FAILURE(rc))
    11821311            break;
    11831312
    1184         if (pStream->enmDir == PDMAUDIODIR_OUT)
     1313        if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
    11851314        {
    11861315            /* No audio frames to transfer from guest to host (anymore)?
    11871316             * Then try closing this stream if marked so in the next block. */
    1188             const uint32_t cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf);
     1317            const uint32_t cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
    11891318            fTryClosePending = cFramesLive == 0;
    1190             Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStream->szName, fTryClosePending, cFramesLive));
     1319            Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStreamEx->Core.szName, fTryClosePending, cFramesLive));
    11911320        }
    11921321
    11931322        /* Has the host stream marked as pending to disable?
    11941323         * Try disabling the stream then. */
    1195         if (   pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE
     1324        if (   pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE
    11961325            && fTryClosePending)
    11971326        {
    11981327            /* Tell the backend to drain the stream, that is, play the remaining (buffered) data
    11991328             * on the backend side. */
    1200             rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DRAIN);
     1329            rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DRAIN);
    12011330            if (rc == VERR_NOT_SUPPORTED) /* Not all backends support draining. */
    12021331                rc = VINF_SUCCESS;
    1203 
    12041332            if (RT_SUCCESS(rc))
    12051333            {
    12061334                if (pThis->pHostDrvAudio->pfnStreamGetPending) /* Optional to implement. */
    12071335                {
    1208                     const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStream->pvBackend);
    1209                     Log3Func(("[%s] cxPending=%RU32\n", pStream->szName, cxPending));
     1336                    const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     1337                    Log3Func(("[%s] cxPending=%RU32\n", pStreamEx->Core.szName, cxPending));
    12101338
    12111339                    /* Only try close pending if no audio data is pending on the backend-side anymore. */
     
    12151343                if (fTryClosePending)
    12161344                {
    1217                     LogFunc(("[%s] Closing pending stream\n", pStream->szName));
    1218                     rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     1345                    LogFunc(("[%s] Closing pending stream\n", pStreamEx->Core.szName));
     1346                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    12191347                    if (RT_SUCCESS(rc))
    12201348                    {
    1221                         pStream->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE);
    1222                         drvAudioStreamDropInternal(pThis, pStream);
     1349                        pStreamEx->Core.fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE);
     1350                        drvAudioStreamDropInternal(pThis, pStreamEx);
    12231351                    }
    12241352                    else
    1225                        LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStream->szName, rc));
     1353                       LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStreamEx->Core.szName, rc));
    12261354                }
    12271355            }
     
    12311359
    12321360    /* Update timestamps. */
    1233     pStream->tsLastIteratedNs = RTTimeNanoTS();
     1361    pStreamEx->nsLastIterated = RTTimeNanoTS();
    12341362
    12351363    if (RT_FAILURE(rc))
    1236         LogFunc(("[%s] Failed with %Rrc\n",  pStream->szName, rc));
     1364        LogFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
    12371365
    12381366    return rc;
     
    12441372 * @returns VBox status code.
    12451373 * @param   pThis           The audio driver instance data.
    1246  * @param   pStream         The stream to play.
     1374 * @param   pStreamEx       The stream to play.
    12471375 * @param   cFramesToPlay   Number of audio frames to play.  The backend is
    12481376 *                          supposed to have buffer space for this.
    12491377 * @param   pcFramesPlayed  Where to return the number of audio frames played.
    12501378 */
    1251 static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
    1252 {
    1253     Assert(pStream->enmDir == PDMAUDIODIR_OUT);
     1379static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
     1380{
     1381    Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT);
    12541382
    12551383    /*
     
    12651393        uint8_t  abChunk[_4K];
    12661394        uint32_t cFramesRead = 0;
    1267         rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf, abChunk,
    1268                                          RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesLeft)),
     1395        rc = AudioMixBufAcquireReadBlock(&pStreamEx->Host.MixBuf, abChunk,
     1396                                         RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesLeft)),
    12691397                                         &cFramesRead);
    12701398        AssertRCBreak(rc);
    12711399
    1272         uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesRead);
     1400        uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesRead);
    12731401        Assert(cbRead <= sizeof(abChunk));
    12741402
     
    12781406        uint32_t cFramesPlayed = 0;
    12791407        uint32_t cbPlayed      = 0;
    1280         rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed);
     1408        rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStreamEx->pvBackend, abChunk, cbRead, &cbPlayed);
    12811409        if (RT_SUCCESS(rc))
    12821410        {
    12831411            if (pThis->Out.Cfg.Dbg.fEnabled)
    1284                 AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
     1412                AudioHlpFileWrite(pStreamEx->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
    12851413
    12861414            if (cbRead != cbPlayed)
    12871415                LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n",
    1288                          pStream->szName, cbRead, cbPlayed));
    1289 
    1290             cFramesPlayed  = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed);
     1416                         pStreamEx->Core.szName, cbRead, cbPlayed));
     1417
     1418            cFramesPlayed  = AUDIOMIXBUF_B2F(&pStreamEx->Host.MixBuf, cbPlayed);
    12911419            AssertStmt(cFramesLeft >= cFramesPlayed, cFramesPlayed = cFramesLeft);
    12921420            cFramesLeft   -= cFramesPlayed;
    12931421        }
    12941422
    1295         AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cFramesPlayed);
     1423        AudioMixBufReleaseReadBlock(&pStreamEx->Host.MixBuf, cFramesPlayed);
    12961424
    12971425        AssertRCBreak(rc); /* (this is here for Acquire/Release symmetry - which isn't at all necessary) */
     
    12991427    }
    13001428
    1301     Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
     1429    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStreamEx->Core.szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
    13021430    *pcFramesPlayed = cFramesToPlay - cFramesLeft;
    13031431    return rc;
     
    13071435 * Worker for drvAudioStreamPlay.
    13081436 */
    1309 static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed)
     1437static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcFramesPlayed)
    13101438{
    13111439    /*
     
    13141442    *pcFramesPlayed = 0;
    13151443
    1316     PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus;
     1444    PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus;
    13171445#ifdef LOG_ENABLED
    13181446    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    13191447#endif
    1320     Log3Func(("[%s] Start fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
     1448    Log3Func(("[%s] Start fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
    13211449
    13221450    /*
     
    13371465     * Get number of frames in the mix buffer and do some logging.
    13381466     */
    1339     uint32_t const cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf);
     1467    uint32_t const cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
    13401468    Log3Func(("[%s] Last played %'RI64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n",
    1341               pStream->szName, pStream->fThresholdReached ? RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs : -1, cFramesLive,
    1342               PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive),
    1343               (100 * cFramesLive) / AudioMixBufSize(&pStream->Host.MixBuf), pStream->fThresholdReached ? "" : ", pre-buffering"));
     1469              pStreamEx->Core.szName, pStreamEx->fThresholdReached ? RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured : -1, cFramesLive,
     1470              PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive),
     1471              (100 * cFramesLive) / AudioMixBufSize(&pStreamEx->Host.MixBuf), pStreamEx->fThresholdReached ? "" : ", pre-buffering"));
    13441472
    13451473    /*
    13461474     * Restart pre-buffering if we're having a buffer-underrun.
    13471475     */
    1348     if (   cFramesLive != 0                     /* no underrun */
    1349         || !pStream->fThresholdReached          /* or still pre-buffering. */)
     1476    if (   cFramesLive != 0              /* no underrun */
     1477        || !pStreamEx->fThresholdReached /* or still pre-buffering. */)
    13501478    { /* likely */ }
    13511479    else
     
    13551483           some heuristics based on number of writable bytes now compared to when
    13561484           prebuffering ended the first time around. */
    1357         uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
    1358         if (cbBuffered < pStream->Out.cbBackendMaxWritable)
    1359             cbBuffered = pStream->Out.cbBackendMaxWritable - cbBuffered;
     1485        uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     1486        if (cbBuffered < pStreamEx->Out.cbBackendMaxWritable)
     1487            cbBuffered = pStreamEx->Out.cbBackendMaxWritable - cbBuffered;
    13601488        else
    13611489            cbBuffered = 0;
    1362         uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStream->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint * 2);
     1490        uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStreamEx->Host.Cfg.Props, pStreamEx->Guest.Cfg.Device.cMsSchedulingHint * 2);
    13631491        Log3Func(("Potential underrun: cbBuffered=%#x vs cbMinBuf=%#x\n", cbBuffered, cbMinBuf));
    13641492        if (cbBuffered < cbMinBuf)
    13651493        {
    13661494            LogRel2(("Audio: Buffer underrun for stream '%s' (%RI64 ms since last call, %u buffered)\n",
    1367                      pStream->szName, RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs, cbBuffered));
     1495                     pStreamEx->Core.szName, RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured, cbBuffered));
    13681496
    13691497            /* Re-enter the pre-buffering stage again if enabled. */
    1370             if (pStream->Host.Cfg.Backend.cFramesPreBuffering > 0)
     1498            if (pStreamEx->Host.Cfg.Backend.cFramesPreBuffering > 0)
    13711499            {
    1372                 pStream->fThresholdReached = false;
     1500                pStreamEx->fThresholdReached = false;
    13731501                STAM_REL_COUNTER_INC(&pThis->Out.StatsReBuffering);
    13741502            }
     
    13831511    uint32_t cbWritable;
    13841512    bool fJustStarted = false;
    1385     if (pStream->fThresholdReached)
     1513    if (pStreamEx->fThresholdReached)
    13861514    {
    13871515        /* not-prebuffering, likely after a while at least */
    1388         cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
     1516        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
    13891517    }
    13901518    else
     
    13941522         * Can be 0 if no pre-buffering desired.
    13951523         */
    1396         if (cFramesLive >= pStream->Host.Cfg.Backend.cFramesPreBuffering)
    1397         {
    1398             LogRel2(("Audio: Stream '%s' buffering complete!\n", pStream->szName));
    1399             pStream->fThresholdReached = fJustStarted = true;
     1524        if (cFramesLive >= pStreamEx->Host.Cfg.Backend.cFramesPreBuffering)
     1525        {
     1526            LogRel2(("Audio: Stream '%s' buffering complete!\n", pStreamEx->Core.szName));
     1527            pStreamEx->fThresholdReached = fJustStarted = true;
    14001528        }
    14011529        /*
     
    14081536         */
    14091537        else if (   cFramesLive > 0
    1410                  && (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
    1411         {
    1412             LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStream->szName));
    1413             pStream->fThresholdReached = fJustStarted = true;
     1538                 && (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
     1539        {
     1540            LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStreamEx->Core.szName));
     1541            pStreamEx->fThresholdReached = fJustStarted = true;
    14141542        }
    14151543        /*
     
    14191547        {
    14201548            LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)...\n",
    1421                      pStream->szName, (100 * cFramesLive) / pStream->Host.Cfg.Backend.cFramesPreBuffering));
     1549                     pStreamEx->Core.szName, (100 * cFramesLive) / pStreamEx->Host.Cfg.Backend.cFramesPreBuffering));
    14221550            return VINF_SUCCESS;
    14231551        }
    14241552
    14251553        /* Hack alert! This is for the underrun detection.  */
    1426         cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
    1427         if (cbWritable > pStream->Out.cbBackendMaxWritable)
    1428             pStream->Out.cbBackendMaxWritable = cbWritable;
    1429     }
    1430     pStream->Out.Stats.cbBackendWritableBefore = cbWritable;
     1554        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     1555        if (cbWritable > pStreamEx->Out.cbBackendMaxWritable)
     1556            pStreamEx->Out.cbBackendMaxWritable = cbWritable;
     1557    }
     1558    pStreamEx->Out.Stats.cbBackendWritableBefore = cbWritable;
    14311559
    14321560    /*
     
    14341562     * Easy, as much as the host audio backend will allow us to.
    14351563     */
    1436     uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStream->Host.Cfg.Props, cbWritable);
     1564    uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStreamEx->Host.Cfg.Props, cbWritable);
    14371565    uint32_t cFramesToPlay   = cFramesWritable;
    14381566    if (cFramesToPlay > cFramesLive) /* Don't try to play more than available, we don't want to block. */
     
    14401568
    14411569    Log3Func(("[%s] Playing %RU32 frames (%RU64 ms), now filled with %RU64 ms -- %RU8%%\n",
    1442               pStream->szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay),
    1443               PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)),
    1444               AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf)));
     1570              pStreamEx->Core.szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay),
     1571              PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)),
     1572              AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf)));
    14451573
    14461574    /*
     
    14511579    {
    14521580        if (pThis->pHostDrvAudio->pfnStreamPlayBegin)
    1453             pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend);
    1454 
    1455         rc = drvAudioStreamPlayDoIt(pThis, pStream, cFramesToPlay, pcFramesPlayed);
     1581            pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     1582
     1583        rc = drvAudioStreamPlayDoIt(pThis, pStreamEx, cFramesToPlay, pcFramesPlayed);
    14561584
    14571585        if (pThis->pHostDrvAudio->pfnStreamPlayEnd)
    1458             pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream->pvBackend);
    1459 
    1460         pStream->tsLastPlayedCapturedNs = RTTimeNanoTS();
    1461         pStream->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio,
    1462                                                                                                pStream->pvBackend);
     1586            pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     1587
     1588        pStreamEx->nsLastPlayedCaptured = RTTimeNanoTS();
     1589        pStreamEx->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio,
     1590                                                                                                 pStreamEx->pvBackend);
    14631591    }
    14641592    else
     
    14661594
    14671595    Log3Func(("[%s] Live=%RU32 fr (%RU64 ms) Period=%RU32 fr (%RU64 ms) Writable=%RU32 fr (%RU64 ms) -> ToPlay=%RU32 fr (%RU64 ms) Played=%RU32 fr (%RU64 ms)%s\n",
    1468               pStream->szName,
    1469               cFramesLive, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive),
    1470               pStream->Host.Cfg.Backend.cFramesPeriod,
    1471               PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, pStream->Host.Cfg.Backend.cFramesPeriod),
    1472               cFramesWritable, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesWritable),
    1473               cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay),
    1474               *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, *pcFramesPlayed),
     1596              pStreamEx->Core.szName,
     1597              cFramesLive, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive),
     1598              pStreamEx->Host.Cfg.Backend.cFramesPeriod,
     1599              PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, pStreamEx->Host.Cfg.Backend.cFramesPeriod),
     1600              cFramesWritable, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesWritable),
     1601              cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay),
     1602              *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, *pcFramesPlayed),
    14751603              fJustStarted ? "just-started" : ""));
    14761604    RT_NOREF(fJustStarted);
     
    14781606    if (RT_SUCCESS(rc))
    14791607    {
    1480         AudioMixBufFinish(&pStream->Host.MixBuf, *pcFramesPlayed);
     1608        AudioMixBufFinish(&pStreamEx->Host.MixBuf, *pcFramesPlayed);
    14811609
    14821610        STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out);
    14831611        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesOut, *pcFramesPlayed);
    1484         STAM_COUNTER_ADD(&pStream->Out.Stats.TotalFramesPlayed, *pcFramesPlayed);
    1485         STAM_COUNTER_INC(&pStream->Out.Stats.TotalTimesPlayed);
     1612        STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesPlayed, *pcFramesPlayed);
     1613        STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesPlayed);
    14861614    }
    14871615    return rc;
     
    14961624    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    14971625    AssertPtr(pThis);
    1498     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1626    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     1627    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
    14991628    AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER);
    1500     AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT,
     1629    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1630    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1631    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
    15011632              ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n",
    1502                pStream->szName, pStream->enmDir));
     1633               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
     1634    AssertReturn(!pStreamEx->fNoMixBufs, VERR_INVALID_FUNCTION);
    15031635
    15041636    int rc = RTCritSectEnter(&pThis->CritSect);
     
    15061638
    15071639    uint32_t cFramesPlayed = 0;
    1508     rc = drvAudioStreamPlayLocked(pThis, pStream, &cFramesPlayed);
     1640    rc = drvAudioStreamPlayLocked(pThis, pStreamEx, &cFramesPlayed);
    15091641
    15101642    RTCritSectLeave(&pThis->CritSect);
     
    15141646
    15151647    if (RT_FAILURE(rc))
    1516         LogFlowFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));
     1648        LogFlowFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
    15171649    return rc;
    15181650}
     
    15221654 *
    15231655 * @returns VBox status code.
    1524  * @param   pThis               Driver instance.
    1525  * @param   pStream             Stream to capture from.
    1526  * @param   pcfCaptured         Number of (host) audio frames captured. Optional.
    1527  */
    1528 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
    1529 {
    1530     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1531     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1532     AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER);
    1533     Assert(pStream->enmDir == PDMAUDIODIR_IN);
    1534     Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
     1656 * @param   pThis       Driver instance.
     1657 * @param   pStreamEx   Stream to capture from.
     1658 * @param   pcfCaptured Number of (host) audio frames captured.
     1659 */
     1660static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcfCaptured)
     1661{
     1662    Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_IN);
     1663    Assert(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
    15351664
    15361665    /*
     
    15381667     */
    15391668    AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable);
    1540     uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
     1669    uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
    15411670    if (!cbReadable)
    1542         Log2Func(("[%s] No readable data available\n", pStream->szName));
    1543 
    1544     uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Guest.MixBuf); /* Parent */
     1671        Log2Func(("[%s] No readable data available\n", pStreamEx->Core.szName));
     1672
     1673    uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Guest.MixBuf); /* Parent */
    15451674    if (!cbFree)
    1546         Log2Func(("[%s] Buffer full\n", pStream->szName));
     1675        Log2Func(("[%s] Buffer full\n", pStreamEx->Core.szName));
    15471676
    15481677    if (cbReadable > cbFree) /* More data readable than we can store at the moment? Limit. */
     
    15581687        uint8_t  abChunk[_4K];
    15591688        uint32_t cbCaptured;
    1560         rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
     1689        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStreamEx->pvBackend,
    15611690                                                    abChunk, RT_MIN(cbReadable, (uint32_t)sizeof(abChunk)), &cbCaptured);
    15621691        if (RT_FAILURE(rc))
    15631692        {
    1564             int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     1693            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    15651694            AssertRC(rc2);
    15661695            break;
     
    15771706         * (first) processing (if needed), so always write the incoming data at offset 0. */
    15781707        uint32_t cfHstWritten = 0;
    1579         rc = AudioMixBufWriteAt(&pStream->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten);
     1708        rc = AudioMixBufWriteAt(&pStreamEx->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten);
    15801709        if (   RT_FAILURE(rc)
    15811710            || !cfHstWritten)
    15821711        {
    15831712            AssertMsgFailed(("[%s] Write failed: cbCaptured=%RU32, cfHstWritten=%RU32, rc=%Rrc\n",
    1584                              pStream->szName, cbCaptured, cfHstWritten, rc));
     1713                             pStreamEx->Core.szName, cbCaptured, cfHstWritten, rc));
    15851714            break;
    15861715        }
    15871716
    15881717        if (pThis->In.Cfg.Dbg.fEnabled)
    1589             AudioHlpFileWrite(pStream->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */);
     1718            AudioHlpFileWrite(pStreamEx->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */);
    15901719
    15911720        uint32_t cfHstMixed = 0;
    15921721        if (cfHstWritten)
    15931722        {
    1594             int rc2 = AudioMixBufMixToParentEx(&pStream->Host.MixBuf, 0 /* cSrcOffset */, cfHstWritten /* cSrcFrames */,
     1723            int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Host.MixBuf, 0 /* cSrcOffset */, cfHstWritten /* cSrcFrames */,
    15951724                                               &cfHstMixed /* pcSrcMixed */);
    15961725            Log3Func(("[%s] cbCaptured=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
    1597                       pStream->szName, cbCaptured, cfHstWritten, cfHstMixed, rc2));
     1726                      pStreamEx->Core.szName, cbCaptured, cfHstWritten, cfHstMixed, rc2));
    15981727            AssertRC(rc2);
    15991728        }
     
    16071736    {
    16081737        if (cfCapturedTotal)
    1609             Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
     1738            Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCapturedTotal, rc));
    16101739    }
    16111740    else
    1612         LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStream->szName, rc));
     1741        LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStreamEx->Core.szName, rc));
    16131742
    16141743    if (pcfCaptured)
     
    16261755 *
    16271756 * @returns VBox status code.
    1628  * @param   pThis               Driver instance.
    1629  * @param   pStream             Stream to capture from.
    1630  * @param   pcfCaptured         Number of (host) audio frames captured. Optional.
    1631  */
    1632 static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
    1633 {
    1634     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1635     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    1636     AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER);
    1637     Assert(pStream->enmDir == PDMAUDIODIR_IN);
    1638     Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
     1757 * @param   pThis       Driver instance.
     1758 * @param   pStreamEx   Stream to capture from.
     1759 * @param   pcfCaptured Number of (host) audio frames captured.
     1760 */
     1761static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcfCaptured)
     1762{
     1763    Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_IN);
     1764    Assert(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
    16391765    AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable);
    16401766
     
    16431769     */
    16441770    /* Note: Raw means *audio frames*, not bytes! */
    1645     uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
     1771    uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
    16461772    if (!cfReadable)
    1647         Log2Func(("[%s] No readable data available\n", pStream->szName));
    1648 
    1649     const uint32_t cfFree = AudioMixBufFree(&pStream->Guest.MixBuf); /* Parent */
     1773        Log2Func(("[%s] No readable data available\n", pStreamEx->Core.szName));
     1774
     1775    const uint32_t cfFree = AudioMixBufFree(&pStreamEx->Guest.MixBuf); /* Parent */
    16501776    if (!cfFree)
    1651         Log2Func(("[%s] Buffer full\n", pStream->szName));
     1777        Log2Func(("[%s] Buffer full\n", pStreamEx->Core.szName));
    16521778
    16531779    if (cfReadable > cfFree) /* More data readable than we can store at the moment? Limit. */
     
    16631789        PPDMAUDIOFRAME paFrames;
    16641790        uint32_t cfWritable;
    1665         rc = AudioMixBufPeekMutable(&pStream->Host.MixBuf, cfReadable, &paFrames, &cfWritable);
     1791        rc = AudioMixBufPeekMutable(&pStreamEx->Host.MixBuf, cfReadable, &paFrames, &cfWritable);
    16661792        if (   RT_FAILURE(rc)
    16671793            || !cfWritable)
     
    16691795
    16701796        uint32_t cfCaptured;
    1671         rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
     1797        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStreamEx->pvBackend,
    16721798                                                    paFrames, cfWritable, &cfCaptured);
    16731799        if (RT_FAILURE(rc))
    16741800        {
    1675             int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     1801            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    16761802            AssertRC(rc2);
    16771803            break;
     
    16891815    if (pcfCaptured)
    16901816        *pcfCaptured = cfCapturedTotal;
    1691     Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
     1817    Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCapturedTotal, rc));
    16921818    return rc;
    16931819}
     
    17011827    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    17021828    AssertPtr(pThis);
    1703     AssertPtr(pStream);
     1829    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     1830    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
    17041831    AssertPtrNull(pcFramesCaptured);
    1705     AssertMsg(pStream->enmDir == PDMAUDIODIR_IN,
     1832    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1833    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     1834    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN,
    17061835              ("Stream '%s' is not an input stream and therefore cannot be captured (direction is 0x%x)\n",
    1707                pStream->szName, pStream->enmDir));
     1836               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
    17081837    int rc = RTCritSectEnter(&pThis->CritSect);
    17091838    AssertRCReturn(rc, rc);
     
    17121841    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    17131842#endif
    1714     Log3Func(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
     1843    Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
    17151844
    17161845    /*
     
    17271856
    17281857        if (   !pThis->In.fEnabled
    1729             || !PDMAudioStrmStatusCanRead(pStream->fStatus))
     1858            || !PDMAudioStrmStatusCanRead(pStreamEx->Core.fStatus))
    17301859        {
    17311860            rc = VERR_AUDIO_STREAM_NOT_READY;
     
    17371866         */
    17381867        if (pThis->pHostDrvAudio->pfnStreamCaptureBegin)
    1739             pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStream->pvBackend);
    1740 
    1741         if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))
    1742             rc = drvAudioStreamCaptureNonInterleaved(pThis, pStream, &cfCaptured);
    1743         else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
    1744             rc = drvAudioStreamCaptureRaw(pThis, pStream, &cfCaptured);
     1868            pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     1869
     1870        if (RT_LIKELY(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))
     1871            rc = drvAudioStreamCaptureNonInterleaved(pThis, pStreamEx, &cfCaptured);
     1872        else if (pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
     1873            rc = drvAudioStreamCaptureRaw(pThis, pStreamEx, &cfCaptured);
    17451874        else
    17461875            AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    17471876
    17481877        if (pThis->pHostDrvAudio->pfnStreamCaptureEnd)
    1749             pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStream->pvBackend);
     1878            pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStreamEx->pvBackend);
    17501879
    17511880        if (RT_SUCCESS(rc))
    17521881        {
    1753             Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCaptured, rc));
    1754 
    1755 #ifdef VBOX_WITH_STATISTICS
    1756             STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn,            cfCaptured);
    1757 
    1758             STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesCaptured, cfCaptured);
    1759 #endif
     1882            Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCaptured, rc));
     1883
     1884            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn,              cfCaptured);
     1885            STAM_COUNTER_ADD(&pStreamEx->In.Stats.TotalFramesCaptured, cfCaptured);
    17601886        }
    17611887        else if (RT_UNLIKELY(RT_FAILURE(rc)))
    1762             LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream->szName, rc));
     1888            LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
    17631889    } while (0);
    17641890
     
    17731899}
    17741900
    1775 #ifdef VBOX_WITH_AUDIO_CALLBACKS
     1901#ifdef VBOX_WITH_AUDIO_CALLBACKS  /** @todo r=bird: All this is non-sense that shall be replaced by a PDMIHOSTAUDIO partner interface. */
    17761902
    17771903/**
     
    18902016 * callback. Will result in some ugly deadlocks (or at least locking
    18912017 * order violations) then.
     2018 *
     2019 * @todo r=bird: The above warning is extremely bogus. You enter the critical
     2020 *       section of the driver here, if anything, that will be the lock order
     2021 *       violation.
    18922022 */
    18932023static DECLCALLBACK(int) drvAudioBackendCallback(PPDMDRVINS pDrvIns, PDMAUDIOBACKENDCBTYPE enmType, void *pvUser, size_t cbUser)
     
    18972027    /* pvUser and cbUser are optional. */
    18982028
    1899 /** @todo r=bird: WTF *is* this?  Seriously?!? */
     2029/** @todo r=bird: WTF *is* this?  Seriously?!?
     2030 *
     2031 * DrvAudio will provide the host driver with a "callback" interface
     2032 * with methods like pfnNotifyDevicesChanged and pfnNotifyStatusChanged.
     2033 * The host drivers that implements callbacks can query the callback
     2034 * interface and make use of it.
     2035 */
    19002036
    19012037    /* Get the upper driver (PDMIAUDIOCONNECTOR). */
     
    19442080 * @param   fLog                Whether to print the enumerated device to the release log or not.
    19452081 * @param   pDevEnum            Where to store the device enumeration.
     2082 *
     2083 * @remarks This is currently ONLY used for release logging.
    19462084 */
    19472085static int drvAudioDevicesEnumerateInternal(PDRVAUDIO pThis, bool fLog, PPDMAUDIOHOSTENUM pDevEnum)
    19482086{
    1949     AssertReturn(RTCritSectIsOwned(&pThis->CritSect) == false, VERR_WRONG_ORDER);
     2087    AssertReturn(!RTCritSectIsOwner(&pThis->CritSect), VERR_WRONG_ORDER);
    19502088
    19512089    int rc;
     
    21212259    if (pThis->pHostDrvAudio)
    21222260    {
    2123         PPDMAUDIOSTREAM pStream;
    2124         RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
    2125         {
    2126             drvAudioStreamControlInternal(pThis, pStream, enmCmd);
     2261        PDRVAUDIOSTREAM pStreamEx;
     2262        RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
     2263        {
     2264            drvAudioStreamControlInternal(pThis, pStreamEx, enmCmd);
    21272265        }
    21282266    }
     
    21402278    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    21412279    AssertPtr(pThis);
    2142     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    2143     AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
    2144     AssertReturn(cbBuf,      VERR_INVALID_PARAMETER);
     2280    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     2281    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     2282    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     2283    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
    21452284    AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER);
    2146     AssertMsg(pStream->enmDir == PDMAUDIODIR_IN,
     2285    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     2286    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     2287    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN,
    21472288              ("Stream '%s' is not an input stream and therefore cannot be read from (direction is 0x%x)\n",
    2148                pStream->szName, pStream->enmDir));
     2289               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
     2290
    21492291    int rc = RTCritSectEnter(&pThis->CritSect);
    21502292    AssertRCReturn(rc, rc);
     
    21592301        uint32_t cfReadTotal = 0;
    21602302
    2161         const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf);
     2303        const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStreamEx->Guest.MixBuf, cbBuf);
    21622304
    21632305        if (pThis->In.fEnabled) /* Input for this audio driver enabled? See #9822. */
     
    21732315             * should have the audio data in the format the guest needs.
    21742316             */
    2175             uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStream->Guest.MixBuf));
     2317            uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStreamEx->Guest.MixBuf));
    21762318            while (cfToRead)
    21772319            {
    21782320                uint32_t cfRead;
    2179                 rc = AudioMixBufAcquireReadBlock(&pStream->Guest.MixBuf,
    2180                                                  (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal),
    2181                                                  AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfToRead), &cfRead);
     2321                rc = AudioMixBufAcquireReadBlock(&pStreamEx->Guest.MixBuf,
     2322                                                 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal),
     2323                                                 AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfToRead), &cfRead);
    21822324                if (RT_FAILURE(rc))
    21832325                    break;
    21842326
    21852327#ifdef VBOX_WITH_STATISTICS
    2186                 const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfRead);
    2187 
    2188                 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead,       cbRead);
    2189 
    2190                 STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesRead, cfRead);
    2191                 STAM_COUNTER_INC(&pStream->In.Stats.TotalTimesRead);
     2328                const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfRead);
     2329                STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead,    cbRead);
     2330                STAM_COUNTER_ADD(&pStreamEx->In.Stats.TotalFramesRead, cfRead);
     2331                STAM_COUNTER_INC(&pStreamEx->In.Stats.TotalTimesRead);
    21922332#endif
    21932333                Assert(cfToRead >= cfRead);
     
    21962336                cfReadTotal += cfRead;
    21972337
    2198                 AudioMixBufReleaseReadBlock(&pStream->Guest.MixBuf, cfRead);
     2338                AudioMixBufReleaseReadBlock(&pStreamEx->Guest.MixBuf, cfRead);
    21992339            }
    22002340
     
    22022342            {
    22032343                if (pThis->In.Cfg.Dbg.fEnabled)
    2204                     AudioHlpFileWrite(pStream->In.Dbg.pFileStreamRead,
    2205                                          pvBuf, AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 0 /* fFlags */);
    2206 
    2207                 AudioMixBufFinish(&pStream->Guest.MixBuf, cfReadTotal);
     2344                    AudioHlpFileWrite(pStreamEx->In.Dbg.pFileStreamRead,
     2345                                      pvBuf, AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal), 0 /* fFlags */);
     2346
     2347                AudioMixBufFinish(&pStreamEx->Guest.MixBuf, cfReadTotal);
    22082348            }
    22092349        }
     
    22162356        {
    22172357            Log3Func(("[%s] Filling in silence (%RU64ms / %RU64ms)\n", pStream->szName,
    2218                       PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfBuf - cfReadTotal),
    2219                       PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfBuf)));
    2220 
    2221             PDMAudioPropsClearBuffer(&pStream->Guest.Cfg.Props,
    2222                                      (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal),
    2223                                      AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfBuf - cfReadTotal),
     2358                      PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cfBuf - cfReadTotal),
     2359                      PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cfBuf)));
     2360
     2361            PDMAudioPropsClearBuffer(&pStreamEx->Guest.Cfg.Props,
     2362                                     (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal),
     2363                                     AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfBuf - cfReadTotal),
    22242364                                     cfBuf - cfReadTotal);
    22252365
     
    22272367        }
    22282368
    2229         cbReadTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal);
    2230 
    2231         pStream->tsLastReadWrittenNs = RTTimeNanoTS();
     2369        cbReadTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal);
     2370
     2371        pStreamEx->nsLastReadWritten = RTTimeNanoTS();
    22322372
    22332373        Log3Func(("[%s] fEnabled=%RTbool, cbReadTotal=%RU32, rc=%Rrc\n", pStream->szName, pThis->In.fEnabled, cbReadTotal, rc));
     
    22472387 *
    22482388 * @returns VBox status code.
    2249  * @param   pThis               Pointer to driver instance.
    2250  * @param   pStream             Audio stream to create the backend side for.
    2251  * @param   pCfgReq             Requested audio stream configuration to use for stream creation.
    2252  * @param   pCfgAcq             Acquired audio stream configuration returned by the backend.
     2389 * @param   pThis       Pointer to driver instance.
     2390 * @param   pStreamEx   Audio stream to create the backend side for.
     2391 * @param   pCfgReq     Requested audio stream configuration to use for
     2392 *                      stream creation.
     2393 * @param   pCfgAcq     Acquired audio stream configuration returned by
     2394 *                      the backend.
    22532395 *
    22542396 * @note    Configuration precedence for requested audio stream configuration (first has highest priority, if set):
     
    22582400 *          - default value
    22592401 */
    2260 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream,
     2402static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx,
    22612403                                               PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    22622404{
    2263     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    2264     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    2265     AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
    2266     AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
    2267 
    2268     AssertMsg((pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) == 0,
    2269               ("Stream '%s' already initialized in backend\n", pStream->szName));
     2405    AssertMsg((pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) == 0,
     2406              ("Stream '%s' already initialized in backend\n", pStreamEx->Core.szName));
    22702407
    22712408    /* Get the right configuration for the stream to be created. */
     
    22822419        PDMAudioPropsSetSampleSize(&pCfgReq->Props, PDMAudioPropsSampleSize(&pDrvCfg->Props));
    22832420        LogRel2(("Audio: Using custom sample size of %RU8 bytes for stream '%s'\n",
    2284                  PDMAudioPropsSampleSize(&pCfgReq->Props), pStream->szName));
     2421                 PDMAudioPropsSampleSize(&pCfgReq->Props), pStreamEx->Core.szName));
    22852422    }
    22862423
     
    22882425    {
    22892426        pCfgReq->Props.uHz = pDrvCfg->Props.uHz;
    2290         LogRel2(("Audio: Using custom Hz rate %RU32 for stream '%s'\n", pCfgReq->Props.uHz, pStream->szName));
     2427        LogRel2(("Audio: Using custom Hz rate %RU32 for stream '%s'\n", pCfgReq->Props.uHz, pStreamEx->Core.szName));
    22912428    }
    22922429
     
    22952432        pCfgReq->Props.fSigned = RT_BOOL(pDrvCfg->uSigned);
    22962433        LogRel2(("Audio: Using custom %s sample format for stream '%s'\n",
    2297                  pCfgReq->Props.fSigned ? "signed" : "unsigned", pStream->szName));
     2434                 pCfgReq->Props.fSigned ? "signed" : "unsigned", pStreamEx->Core.szName));
    22982435    }
    22992436
     
    23022439        pCfgReq->Props.fSwapEndian = RT_BOOL(pDrvCfg->uSwapEndian);
    23032440        LogRel2(("Audio: Using custom %s endianess for samples of stream '%s'\n",
    2304                  pCfgReq->Props.fSwapEndian ? "swapped" : "original", pStream->szName));
     2441                 pCfgReq->Props.fSwapEndian ? "swapped" : "original", pStreamEx->Core.szName));
    23052442    }
    23062443
     
    23082445    {
    23092446        PDMAudioPropsSetChannels(&pCfgReq->Props, PDMAudioPropsChannels(&pDrvCfg->Props));
    2310         LogRel2(("Audio: Using custom %RU8 channel(s) for stream '%s'\n", PDMAudioPropsChannels(&pDrvCfg->Props), pStream->szName));
     2447        LogRel2(("Audio: Using custom %RU8 channel(s) for stream '%s'\n", PDMAudioPropsChannels(&pDrvCfg->Props), pStreamEx->Core.szName));
    23112448    }
    23122449
     
    23142451    if (!AudioHlpPcmPropsAreValid(&pCfgReq->Props))
    23152452    {
    2316         LogRel(("Audio: Invalid custom PCM properties set for stream '%s', cannot create stream\n", pStream->szName));
     2453        LogRel(("Audio: Invalid custom PCM properties set for stream '%s', cannot create stream\n", pStreamEx->Core.szName));
    23172454        return VERR_INVALID_PARAMETER;
    23182455    }
     
    23362473    LogRel2(("Audio: Using %s period size %RU64 ms / %RU32 frames for stream '%s'\n",
    23372474             pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod),
    2338              pCfgReq->Backend.cFramesPeriod, pStream->szName));
     2475             pCfgReq->Backend.cFramesPeriod, pStreamEx->Core.szName));
    23392476
    23402477    /*
     
    23562493    LogRel2(("Audio: Using %s buffer size %RU64 ms / %RU32 frames for stream '%s'\n",
    23572494             pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
    2358              pCfgReq->Backend.cFramesBufferSize, pStream->szName));
     2495             pCfgReq->Backend.cFramesBufferSize, pStreamEx->Core.szName));
    23592496
    23602497    /*
     
    23792516    LogRel2(("Audio: Using %s pre-buffering size %RU64 ms / %RU32 frames for stream '%s'\n",
    23802517             pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),
    2381              pCfgReq->Backend.cFramesPreBuffering, pStream->szName));
     2518             pCfgReq->Backend.cFramesPreBuffering, pStreamEx->Core.szName));
    23822519
    23832520    /*
     
    23872524    {
    23882525        LogRel(("Audio: Error for stream '%s': Buffering size (%RU64ms) must not be smaller than the period size (%RU64ms)\n",
    2389                 pStream->szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
     2526                pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
    23902527                PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod)));
    23912528        return VERR_INVALID_PARAMETER;
     
    23982535        {
    23992536            LogRel(("Audio: Error for stream '%s': Buffering size (%RU64ms) must not be smaller than the pre-buffering size (%RU64ms)\n",
    2400                     pStream->szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),
     2537                    pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),
    24012538                    PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize)));
    24022539            return VERR_INVALID_PARAMETER;
     
    24132550    {
    24142551        LogRel(("Audio: Creating stream '%s' with an invalid backend configuration not possible, skipping\n",
    2415                 pStream->szName));
     2552                pStreamEx->Core.szName));
    24162553        return rc;
    24172554    }
     
    24222559    AssertPtr(pThis->pHostDrvAudio);
    24232560    if (pThis->pHostDrvAudio)
    2424         rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStream->pvBackend, pCfgReq, pCfgAcq);
     2561        rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStreamEx->pvBackend, pCfgReq, pCfgAcq);
    24252562    else
    24262563        rc = VERR_PDM_NO_ATTACHED_DRIVER;
     
    24282565    {
    24292566        if (rc == VERR_NOT_SUPPORTED)
    2430             LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStream->szName));
     2567            LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStreamEx->Core.szName));
    24312568        else if (rc == VERR_AUDIO_STREAM_COULD_NOT_CREATE)
    2432             LogRel2(("Audio: Stream '%s' could not be created in backend because of missing hardware / drivers\n", pStream->szName));
     2569            LogRel2(("Audio: Stream '%s' could not be created in backend because of missing hardware / drivers\n", pStreamEx->Core.szName));
    24332570        else
    2434             LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStream->szName, rc));
     2571            LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStreamEx->Core.szName, rc));
    24352572        return rc;
    24362573    }
     
    24402577    AssertLogRelMsgReturn(AudioHlpStreamCfgIsValid(pCfgAcq),
    24412578                          ("Audio: Creating stream '%s' returned an invalid backend configuration (%s), skipping\n",
    2442                            pStream->szName, PDMAudioPropsToString(&pCfgAcq->Props, szTmp, sizeof(szTmp))),
     2579                           pStreamEx->Core.szName, PDMAudioPropsToString(&pCfgAcq->Props, szTmp, sizeof(szTmp))),
    24432580                          VERR_INVALID_PARAMETER);
    24442581
     
    24462583    if (pCfgAcq->Backend.cFramesBufferSize != pCfgReq->Backend.cFramesBufferSize)
    24472584        LogRel2(("Audio: Buffer size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
    2448                  pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesBufferSize), pCfgAcq->Backend.cFramesBufferSize));
     2585                 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesBufferSize), pCfgAcq->Backend.cFramesBufferSize));
    24492586
    24502587    if (pCfgAcq->Backend.cFramesPeriod != pCfgReq->Backend.cFramesPeriod)
    24512588        LogRel2(("Audio: Period size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
    2452                  pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPeriod), pCfgAcq->Backend.cFramesPeriod));
     2589                 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPeriod), pCfgAcq->Backend.cFramesPeriod));
    24532590
    24542591    /* Was pre-buffering requested, but the acquired configuration from the backend told us something else? */
     
    24572594        if (pCfgAcq->Backend.cFramesPreBuffering != pCfgReq->Backend.cFramesPreBuffering)
    24582595            LogRel2(("Audio: Pre-buffering size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
    2459                      pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
     2596                     pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
    24602597
    24612598        if (pCfgAcq->Backend.cFramesPreBuffering > pCfgAcq->Backend.cFramesBufferSize)
     
    24632600            pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesBufferSize;
    24642601            LogRel2(("Audio: Pre-buffering size bigger than buffer size for stream '%s', adjusting to %RU64ms (%RU32 frames)\n",
    2465                      pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
     2602                     pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
    24662603        }
    24672604    }
    24682605    else if (pCfgReq->Backend.cFramesPreBuffering == 0) /* Was the pre-buffering requested as being disabeld? Tell the users. */
    24692606    {
    2470         LogRel2(("Audio: Pre-buffering is disabled for stream '%s'\n", pStream->szName));
     2607        LogRel2(("Audio: Pre-buffering is disabled for stream '%s'\n", pStreamEx->Core.szName));
    24712608        pCfgAcq->Backend.cFramesPreBuffering = 0;
    24722609    }
     
    24802617                    VERR_INVALID_PARAMETER);
    24812618
    2482     pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
     2619    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
    24832620
    24842621    return VINF_SUCCESS;
     
    24902627 *
    24912628 * @returns VBox status code.
    2492  * @param   pThis               Pointer to driver instance.
    2493  * @param   pStream             Stream to initialize.
    2494  * @param   pCfgHost            Stream configuration to use for the host side (backend).
    2495  * @param   pCfgGuest           Stream configuration to use for the guest side.
    2496  */
    2497 static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream,
     2629 * @param   pThis       Pointer to driver instance.
     2630 * @param   pStreamEx   Stream to initialize.
     2631 * @param   fFlags      PDMAUDIOSTREAM_CREATE_F_XXX.
     2632 * @param   pCfgHost    Stream configuration to use for the host side (backend).
     2633 * @param   pCfgGuest   Stream configuration to use for the guest side.
     2634 */
     2635static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t fFlags,
    24982636                                      PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest)
    24992637{
    2500     AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
    2501     AssertPtrReturn(pStream,   VERR_INVALID_POINTER);
    2502     AssertPtrReturn(pCfgHost,  VERR_INVALID_POINTER);
    2503     AssertPtrReturn(pCfgGuest, VERR_INVALID_POINTER);
    2504 
    25052638    /*
    25062639     * Init host stream.
    25072640     */
    2508     pStream->uMagic = PDMAUDIOSTREAM_MAGIC;
     2641    pStreamEx->Core.uMagic = PDMAUDIOSTREAM_MAGIC;
    25092642
    25102643    /* Set the host's default audio data layout. */
     2644/** @todo r=bird: Why, oh why? OTOH, the layout stuff is non-sense anyway. */
    25112645    pCfgHost->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
    25122646
    25132647#ifdef LOG_ENABLED
    2514     LogFunc(("[%s] Requested host format:\n", pStream->szName));
     2648    LogFunc(("[%s] Requested host format:\n", pStreamEx->Core.szName));
    25152649    PDMAudioStrmCfgLog(pCfgHost);
    25162650#endif
    25172651
    2518     LogRel2(("Audio: Creating stream '%s'\n", pStream->szName));
     2652    LogRel2(("Audio: Creating stream '%s'\n", pStreamEx->Core.szName));
    25192653    LogRel2(("Audio: Guest %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n",
    2520              pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName,
     2654             pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName,
    25212655             pCfgGuest->Props.uHz, PDMAudioPropsSampleBits(&pCfgGuest->Props), pCfgGuest->Props.fSigned ? "S" : "U",
    25222656             PDMAudioPropsChannels(&pCfgGuest->Props), PDMAudioPropsChannels(&pCfgGuest->Props) == 1 ? "" : "s"));
    25232657    LogRel2(("Audio: Requested host %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n",
    2524              pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName,
     2658             pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName,
    25252659             pCfgHost->Props.uHz, PDMAudioPropsSampleBits(&pCfgHost->Props), pCfgHost->Props.fSigned ? "S" : "U",
    25262660             PDMAudioPropsChannels(&pCfgHost->Props), PDMAudioPropsChannels(&pCfgHost->Props) == 1 ? "" : "s"));
    25272661
    25282662    PDMAUDIOSTREAMCFG CfgHostAcq;
    2529     int rc = drvAudioStreamCreateInternalBackend(pThis, pStream, pCfgHost, &CfgHostAcq);
     2663    int rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, pCfgHost, &CfgHostAcq);
    25302664    if (RT_FAILURE(rc))
    25312665        return rc;
    25322666
    2533     LogFunc(("[%s] Acquired host format:\n",  pStream->szName));
     2667    LogFunc(("[%s] Acquired host format:\n",  pStreamEx->Core.szName));
    25342668    PDMAudioStrmCfgLog(&CfgHostAcq);
    25352669    LogRel2(("Audio: Acquired host %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n",
    2536              CfgHostAcq.enmDir == PDMAUDIODIR_IN ? "recording" : "playback",  pStream->szName,
     2670             CfgHostAcq.enmDir == PDMAUDIODIR_IN ? "recording" : "playback",  pStreamEx->Core.szName,
    25372671             CfgHostAcq.Props.uHz, PDMAudioPropsSampleBits(&CfgHostAcq.Props), CfgHostAcq.Props.fSigned ? "S" : "U",
    25382672             PDMAudioPropsChannels(&CfgHostAcq.Props), PDMAudioPropsChannels(&CfgHostAcq.Props) == 1 ? "" : "s"));
     
    25652699        LogRel2(("Audio: Warning: Pre-buffering size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), "
    25662700                 "setting pre-buffering size to %RU32 frames\n",
    2567                  CfgHostAcq.Backend.cFramesPreBuffering, pStream->szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
     2701                 CfgHostAcq.Backend.cFramesPreBuffering, pStreamEx->Core.szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
    25682702        CfgHostAcq.Backend.cFramesPreBuffering = CfgHostAcq.Backend.cFramesBufferSize;
    25692703    }
     
    25722706    {
    25732707        LogRel2(("Audio: Warning: Period size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), setting to %RU32 frames\n",
    2574                  CfgHostAcq.Backend.cFramesPeriod, pStream->szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
     2708                 CfgHostAcq.Backend.cFramesPeriod, pStreamEx->Core.szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
    25752709        CfgHostAcq.Backend.cFramesPeriod = CfgHostAcq.Backend.cFramesBufferSize;
    25762710    }
     
    25782712    uint64_t msBufferSize = PDMAudioPropsFramesToMilli(&CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
    25792713    LogRel2(("Audio: Buffer size of stream '%s' is %RU64ms (%RU32 frames)\n",
    2580              pStream->szName, msBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
     2714             pStreamEx->Core.szName, msBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
    25812715
    25822716    /* If no own pre-buffer is set, let the backend choose. */
    25832717    uint64_t msPreBuf = PDMAudioPropsFramesToMilli(&CfgHostAcq.Props, CfgHostAcq.Backend.cFramesPreBuffering);
    25842718    LogRel2(("Audio: Pre-buffering size of stream '%s' is %RU64ms (%RU32 frames)\n",
    2585              pStream->szName, msPreBuf, CfgHostAcq.Backend.cFramesPreBuffering));
     2719             pStreamEx->Core.szName, msPreBuf, CfgHostAcq.Backend.cFramesPreBuffering));
    25862720
    25872721    /* Make sure the configured buffer size by the backend at least can hold the configured latency. */
     
    25892723
    25902724    LogRel2(("Audio: Period size of stream '%s' is %RU64ms (%RU32 frames)\n",
    2591              pStream->szName, msPeriod, CfgHostAcq.Backend.cFramesPeriod));
     2725             pStreamEx->Core.szName, msPeriod, CfgHostAcq.Backend.cFramesPeriod));
    25922726
    25932727    if (   pCfgGuest->Device.cMsSchedulingHint             /* Any scheduling hint set? */
     
    25952729    {
    25962730        LogRel(("Audio: Warning: Scheduling hint of stream '%s' is bigger (%RU64ms) than used period size (%RU64ms)\n",
    2597                 pStream->szName, pCfgGuest->Device.cMsSchedulingHint, msPeriod));
     2731                pStreamEx->Core.szName, pCfgGuest->Device.cMsSchedulingHint, msPeriod));
    25982732    }
    25992733
    26002734    /* Destroy any former mixing buffer. */
    2601     AudioMixBufDestroy(&pStream->Host.MixBuf);
    2602 
    2603     rc = AudioMixBufInit(&pStream->Host.MixBuf, pStream->szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
    2604     AssertRC(rc);
     2735    AudioMixBufDestroy(&pStreamEx->Host.MixBuf);
     2736
     2737    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
     2738    {
     2739        rc = AudioMixBufInit(&pStreamEx->Host.MixBuf, pStreamEx->Core.szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
     2740        AssertRCReturn(rc, rc);
     2741    }
    26052742
    26062743    /* Make a copy of the acquired host stream configuration. */
    2607     rc = PDMAudioStrmCfgCopy(&pStream->Host.Cfg, &CfgHostAcq);
     2744    rc = PDMAudioStrmCfgCopy(&pStreamEx->Host.Cfg, &CfgHostAcq);
    26082745    AssertRC(rc);
    26092746
     
    26142751    if (pCfgGuest->Device.cMsSchedulingHint)
    26152752        LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms (%RU32 bytes)\n",
    2616                  pStream->szName, pCfgGuest->Device.cMsSchedulingHint,
     2753                 pStreamEx->Core.szName, pCfgGuest->Device.cMsSchedulingHint,
    26172754                 PDMAudioPropsMilliToBytes(&pCfgGuest->Props, pCfgGuest->Device.cMsSchedulingHint)));
    26182755
    26192756    /* Destroy any former mixing buffer. */
    2620     AudioMixBufDestroy(&pStream->Guest.MixBuf);
     2757    AudioMixBufDestroy(&pStreamEx->Guest.MixBuf);
    26212758
    26222759    /* Set the guests's default audio data layout. */
    26232760    pCfgGuest->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
    26242761
    2625     rc = AudioMixBufInit(&pStream->Guest.MixBuf, pStream->szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize);
     2762    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
     2763    {
     2764        rc = AudioMixBufInit(&pStreamEx->Guest.MixBuf, pStreamEx->Core.szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize);
     2765        AssertRCReturn(rc, rc);
     2766    }
     2767
     2768    /* Make a copy of the guest stream configuration. */
     2769    rc = PDMAudioStrmCfgCopy(&pStreamEx->Guest.Cfg, pCfgGuest);
    26262770    AssertRC(rc);
    26272771
    2628     /* Make a copy of the guest stream configuration. */
    2629     rc = PDMAudioStrmCfgCopy(&pStream->Guest.Cfg, pCfgGuest);
    2630     AssertRC(rc);
    2631 
    26322772    if (RT_FAILURE(rc))
    2633         LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStream->szName, rc));
    2634 
    2635     if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    2636     {
    2637         /* Host (Parent) -> Guest (Child). */
    2638         rc = AudioMixBufLinkTo(&pStream->Host.MixBuf, &pStream->Guest.MixBuf);
    2639         AssertRC(rc);
    2640     }
    2641     else
    2642     {
    2643         /* Guest (Parent) -> Host (Child). */
    2644         rc = AudioMixBufLinkTo(&pStream->Guest.MixBuf, &pStream->Host.MixBuf);
    2645         AssertRC(rc);
     2773        LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
     2774
     2775    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
     2776    {
     2777        if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
     2778        {
     2779            /* Host (Parent) -> Guest (Child). */
     2780            rc = AudioMixBufLinkTo(&pStreamEx->Host.MixBuf, &pStreamEx->Guest.MixBuf);
     2781            AssertRC(rc);
     2782        }
     2783        else
     2784        {
     2785            /* Guest (Parent) -> Host (Child). */
     2786            rc = AudioMixBufLinkTo(&pStreamEx->Guest.MixBuf, &pStreamEx->Host.MixBuf);
     2787            AssertRC(rc);
     2788        }
    26462789    }
    26472790
     
    26512794    PPDMDRVINS const pDrvIns = pThis->pDrvIns;
    26522795    /** @todo expose config and more. */
    2653     PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.Cfg.Backend.cFramesBufferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2654                            "Host side: The size of the backend buffer (in frames)", "%s/0-HostBackendBufSize", pStream->szName);
    2655     PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2656                            "Host side: The size of the mixer buffer (in frames)",   "%s/1-HostMixBufSize", pStream->szName);
    2657     PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2658                            "Guest side: The size of the mixer buffer (in frames)",  "%s/2-GuestMixBufSize", pStream->szName);
     2796    PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.Cfg.Backend.cFramesBufferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2797                           "Host side: The size of the backend buffer (in frames)", "%s/0-HostBackendBufSize", pStreamEx->Core.szName);
     2798    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
     2799    {
     2800        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2801                               "Host side: The size of the mixer buffer (in frames)",   "%s/1-HostMixBufSize", pStreamEx->Core.szName);
     2802        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2803                               "Guest side: The size of the mixer buffer (in frames)",  "%s/2-GuestMixBufSize", pStreamEx->Core.szName);
     2804        if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
     2805        {
     2806            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2807                                   "Host side: Number of frames in the mixer buffer",   "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
     2808            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2809                                   "Guest side: Number of frames in the mixer buffer",  "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
     2810        }
     2811        else
     2812        {
     2813            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2814                                   "Host side: Number of frames in the mixer buffer",     "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
     2815            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2816                                   "Guest side: Number of frames in the mixer buffer",    "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
     2817        }
     2818    }
    26592819    if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    26602820    {
    2661         PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2662                                "Host side: Number of frames in the mixer buffer",   "%s/1-HostMixBufUsed", pStream->szName);
    2663         PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2664                                "Guest side: Number of frames in the mixer buffer",  "%s/2-GuestMixBufUsed", pStream->szName);
     2821        /** @todo later? */
    26652822    }
    26662823    else
    26672824    {
    2668         PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2669                                "Host side: Number of frames in the mixer buffer",     "%s/1-HostMixBufUsed", pStream->szName);
    2670         PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2671                                "Guest side: Number of frames in the mixer buffer",    "%s/2-GuestMixBufUsed", pStream->szName);
    2672 
    2673         PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Out.Stats.cbBackendWritableBefore, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2674                                "Host side: Free space in backend buffer before play", "%s/0-HostBackendBufFreeBefore", pStream->szName);
    2675         PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Out.Stats.cbBackendWritableAfter, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    2676                                "Host side: Free space in backend buffer after play",  "%s/0-HostBackendBufFreeAfter", pStream->szName);
     2825        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableBefore, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2826                               "Host side: Free space in backend buffer before play", "%s/0-HostBackendBufFreeBefore", pStreamEx->Core.szName);
     2827        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableAfter, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     2828                               "Host side: Free space in backend buffer after play",  "%s/0-HostBackendBufFreeAfter", pStreamEx->Core.szName);
    26772829    }
    26782830
     
    26812833    if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    26822834    {
    2683         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesCaptured", pStream->szName);
    2684         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalFramesCaptured,
     2835        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesCaptured", pStreamEx->Core.szName);
     2836        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalFramesCaptured,
    26852837                                  szStatName, STAMUNIT_COUNT, "Total frames played.");
    2686         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesCaptured", pStream->szName);
    2687         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalTimesCaptured,
     2838        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesCaptured", pStreamEx->Core.szName);
     2839        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalTimesCaptured,
    26882840                                  szStatName, STAMUNIT_COUNT, "Total number of playbacks.");
    2689         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesRead", pStream->szName);
    2690         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalFramesRead,
     2841        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesRead", pStreamEx->Core.szName);
     2842        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalFramesRead,
    26912843                                  szStatName, STAMUNIT_COUNT, "Total frames read.");
    2692         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesRead", pStream->szName);
    2693         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalTimesRead,
     2844        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesRead", pStreamEx->Core.szName);
     2845        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalTimesRead,
    26942846                                  szStatName, STAMUNIT_COUNT, "Total number of reads.");
    26952847    }
     
    26972849    {
    26982850        Assert(pCfgGuest->enmDir == PDMAUDIODIR_OUT);
    2699         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesPlayed", pStream->szName);
    2700         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalFramesPlayed,
     2851        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesPlayed", pStreamEx->Core.szName);
     2852        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalFramesPlayed,
    27012853                                  szStatName, STAMUNIT_COUNT, "Total frames played.");
    27022854
    2703         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesPlayed", pStream->szName);
    2704         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalTimesPlayed,
     2855        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesPlayed", pStreamEx->Core.szName);
     2856        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalTimesPlayed,
    27052857                                  szStatName, STAMUNIT_COUNT, "Total number of playbacks.");
    2706         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesWritten", pStream->szName);
    2707         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalFramesWritten,
     2858        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesWritten", pStreamEx->Core.szName);
     2859        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalFramesWritten,
    27082860                                  szStatName, STAMUNIT_COUNT, "Total frames written.");
    27092861
    2710         RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesWritten", pStream->szName);
    2711         PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalTimesWritten,
     2862        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesWritten", pStreamEx->Core.szName);
     2863        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalTimesWritten,
    27122864                                  szStatName, STAMUNIT_COUNT, "Total number of writes.");
    27132865    }
    27142866#endif /* VBOX_WITH_STATISTICS */
    27152867
    2716     LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
     2868    LogFlowFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
    27172869    return rc;
    27182870}
     
    27212873 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamCreate}
    27222874 */
    2723 static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost,
     2875static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, uint32_t fFlags, PPDMAUDIOSTREAMCFG pCfgHost,
    27242876                                              PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream)
    27252877{
     
    27302882     * Assert sanity.
    27312883     */
     2884    AssertReturn(!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF), VERR_INVALID_FLAGS);
    27322885    AssertPtrReturn(pCfgHost,   VERR_INVALID_POINTER);
    27332886    AssertPtrReturn(pCfgGuest,  VERR_INVALID_POINTER);
     
    27812934         * Allocate and initialize common state.
    27822935         */
    2783         PPDMAUDIOSTREAM pStream = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM) + RT_ALIGN_Z(cbHstStrm, 64));
    2784         if (pStream)
     2936        PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)RTMemAllocZ(sizeof(DRVAUDIOSTREAM) + RT_ALIGN_Z(cbHstStrm, 64));
     2937        if (pStreamEx)
    27852938        {
    27862939            /* Retrieve host driver name for easier identification. */
    27872940            AssertPtr(pThis->pHostDrvAudio);
    27882941            PPDMDRVINS pDrvAudioInst = PDMIBASE_2_PDMDRV(pThis->pDrvIns->pDownBase);
    2789             RTStrPrintf(pStream->szName, RT_ELEMENTS(pStream->szName), "[%s] %s",
     2942            RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s",
    27902943                        pDrvAudioInst && pDrvAudioInst->pReg && pDrvAudioInst->pReg->szName[0]
    27912944                        ? pDrvAudioInst->pReg->szName : "none",
    27922945                        pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<Untitled>");
    27932946
    2794             pStream->enmDir    = pCfgHost->enmDir;
    2795             pStream->cbBackend = (uint32_t)cbHstStrm;
     2947            pStreamEx->Core.enmDir    = pCfgHost->enmDir;
     2948            pStreamEx->Core.cbBackend = (uint32_t)cbHstStrm;
    27962949            if (cbHstStrm)
    2797                 pStream->pvBackend = pStream + 1;
     2950                pStreamEx->pvBackend = pStreamEx + 1;
     2951            pStreamEx->fNoMixBufs     = RT_BOOL(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF);
     2952            pStreamEx->uMagic         = DRVAUDIOSTREAM_MAGIC;
    27982953
    27992954            /*
    28002955             * Try to init the rest.
    28012956             */
    2802             rc = drvAudioStreamInitInternal(pThis, pStream, pCfgHost, pCfgGuest);
     2957            rc = drvAudioStreamInitInternal(pThis, pStreamEx, fFlags, pCfgHost, pCfgGuest);
    28032958            if (RT_SUCCESS(rc))
    28042959            {
    28052960                /* Set initial reference counts. */
    2806                 pStream->cRefs = 1;
     2961                pStreamEx->Core.cRefs = 1;
    28072962
    28082963                /* Decrement the free stream counter. */
     
    28132968                 * We're good.
    28142969                 */
    2815                 RTListAppend(&pThis->lstStreams, &pStream->ListEntry);
     2970                RTListAppend(&pThis->lstStreams, &pStreamEx->ListEntry);
    28162971                STAM_COUNTER_INC(&pThis->Stats.TotalStreamsCreated);
    2817                 *ppStream = pStream;
     2972                *ppStream = &pStreamEx->Core;
    28182973
    28192974                /*
     
    28242979                    if (pThis->In.Cfg.Dbg.fEnabled)
    28252980                    {
    2826                         AudioHlpFileCreateAndOpen(&pStream->In.Dbg.pFileCaptureNonInterleaved, pThis->In.Cfg.Dbg.szPathOut,
    2827                                                   "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
    2828                         AudioHlpFileCreateAndOpen(&pStream->In.Dbg.pFileStreamRead, pThis->In.Cfg.Dbg.szPathOut,
    2829                                                   "DrvAudioRead", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
     2981                        AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileCaptureNonInterleaved, pThis->In.Cfg.Dbg.szPathOut,
     2982                                                  "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
     2983                        AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileStreamRead, pThis->In.Cfg.Dbg.szPathOut,
     2984                                                  "DrvAudioRead", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    28302985                    }
    28312986                }
     
    28342989                    if (pThis->Out.Cfg.Dbg.fEnabled)
    28352990                    {
    2836                         AudioHlpFileCreateAndOpen(&pStream->Out.Dbg.pFilePlayNonInterleaved, pThis->Out.Cfg.Dbg.szPathOut,
    2837                                                   "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
    2838                         AudioHlpFileCreateAndOpen(&pStream->Out.Dbg.pFileStreamWrite, pThis->Out.Cfg.Dbg.szPathOut,
    2839                                                   "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
     2991                        AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFilePlayNonInterleaved, pThis->Out.Cfg.Dbg.szPathOut,
     2992                                                  "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
     2993                        AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFileStreamWrite, pThis->Out.Cfg.Dbg.szPathOut,
     2994                                                  "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    28402995                    }
    28412996                }
     
    28442999            {
    28453000                LogFunc(("drvAudioStreamInitInternal failed: %Rrc\n", rc));
    2846                 int rc2 = drvAudioStreamUninitInternal(pThis, pStream);
     3001                int rc2 = drvAudioStreamUninitInternal(pThis, pStreamEx);
    28473002                AssertRC(rc2);
    2848                 drvAudioStreamFree(pStream);
     3003                drvAudioStreamFree(pStreamEx);
    28493004            }
    28503005        }
     
    28853040        *pfEnabled = fEnable;
    28863041
    2887         PPDMAUDIOSTREAM pStream;
    2888         RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
    2889         {
    2890             if (pStream->enmDir != enmDir) /* Skip unwanted streams. */
     3042        PDRVAUDIOSTREAM pStreamEx;
     3043        RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
     3044        {
     3045            if (pStreamEx->Core.enmDir != enmDir) /* Skip unwanted streams. */
    28913046                continue;
    28923047
     
    29013056             * See @bugref{9882}.
    29023057             */
    2903             int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream,
     3058            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx,
    29043059                                                           fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
    29053060            if (RT_FAILURE(rc2))
    29063061            {
    29073062                if (rc2 == VERR_AUDIO_STREAM_NOT_READY)
    2908                 {
    2909                     LogRel(("Audio: Stream '%s' not available\n", pStream->szName));
    2910                 }
     3063                    LogRel(("Audio: Stream '%s' not available\n", pStreamEx->Core.szName));
    29113064                else
    2912                     LogRel(("Audio: Failed to %s %s stream '%s', rc=%Rrc\n",
    2913                             fEnable ? "enable" : "disable", enmDir == PDMAUDIODIR_IN ? "input" : "output", pStream->szName, rc2));
     3065                    LogRel(("Audio: Failed to %s %s stream '%s', rc=%Rrc\n", fEnable ? "enable" : "disable",
     3066                            enmDir == PDMAUDIODIR_IN ? "input" : "output", pStreamEx->Core.szName, rc2));
    29143067            }
    29153068            else
     
    29173070                /* When (re-)enabling a stream, clear the disabled warning bit again. */
    29183071                if (fEnable)
    2919                     pStream->fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
     3072                    pStreamEx->Core.fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
    29203073            }
    29213074
     
    30133166    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    30143167    AssertPtr(pThis);
    3015     AssertPtrReturn(pStream, 0);
    3016     AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
     3168    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     3169    AssertPtrReturn(pStreamEx, 0);
     3170    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, 0);
     3171    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, 0);
     3172    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
    30173173    int rc = RTCritSectEnter(&pThis->CritSect);
    30183174    AssertRCReturn(rc, 0);
     
    30273183
    30283184    if (   pThis->pHostDrvAudio
    3029         && (   PDMAudioStrmStatusCanRead(pStream->fStatus)
     3185        && (   PDMAudioStrmStatusCanRead(pStreamEx->Core.fStatus)
    30303186            || fDisabled)
    30313187       )
    30323188    {
    3033         const uint32_t cfReadable = AudioMixBufLive(&pStream->Guest.MixBuf);
    3034 
    3035         cbReadable = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable);
     3189        if (pStreamEx->fNoMixBufs)
     3190            cbReadable = pThis->pHostDrvAudio ? pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream) : 0;
     3191        else
     3192        {
     3193            const uint32_t cfReadable = AudioMixBufLive(&pStreamEx->Guest.MixBuf);
     3194            cbReadable = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadable);
     3195        }
    30363196
    30373197        if (!cbReadable)
     
    30473207            PDMAUDIOSTREAMSTS fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;
    30483208            if (pThis->pHostDrvAudio->pfnStreamGetStatus)
    3049                 fStatus = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend);
     3209                fStatus = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStreamEx->pvBackend);
    30503210            if (   !PDMAudioStrmStatusCanRead(fStatus)
    30513211                || fDisabled)
    30523212            {
    3053                 cbReadable = PDMAudioPropsNanoToBytes(&pStream->Host.Cfg.Props, RTTimeNanoTS() - pStream->tsLastReadWrittenNs);
    3054                 if (!(pStream->fWarningsShown & PDMAUDIOSTREAM_WARN_FLAGS_DISABLED))
     3213                cbReadable = PDMAudioPropsNanoToBytes(&pStreamEx->Host.Cfg.Props,
     3214                                                      RTTimeNanoTS() - pStreamEx->nsLastReadWritten);
     3215                if (!(pStreamEx->Core.fWarningsShown & PDMAUDIOSTREAM_WARN_FLAGS_DISABLED))
    30553216                {
    30563217                    if (fDisabled)
     
    30583219                    else
    30593220                        LogRel(("Audio: Warning: Input for stream '%s' of driver '%s' not ready (current input status is %#x), returning silence\n",
    3060                                 pStream->szName, pThis->szName, fStatus));
    3061 
    3062                     pStream->fWarningsShown |= PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
     3221                                pStreamEx->Core.szName, pThis->szName, fStatus));
     3222
     3223                    pStreamEx->Core.fWarningsShown |= PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
    30633224                }
    30643225            }
     
    30673228        /* Make sure to align the readable size to the guest's frame size. */
    30683229        if (cbReadable)
    3069             cbReadable = PDMAudioPropsFloorBytesToFrame(&pStream->Guest.Cfg.Props, cbReadable);
     3230            cbReadable = PDMAudioPropsFloorBytesToFrame(&pStreamEx->Guest.Cfg.Props, cbReadable);
    30703231    }
    30713232
    30723233    RTCritSectLeave(&pThis->CritSect);
    30733234    Log3Func(("[%s] cbReadable=%RU32 (%RU64ms)\n",
    3074               pStream->szName, cbReadable, PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbReadable)));
     3235              pStreamEx->Core.szName, cbReadable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbReadable)));
    30753236    return cbReadable;
    30763237}
     
    30833244    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    30843245    AssertPtr(pThis);
    3085     AssertPtrReturn(pStream,    0);
    3086     AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"));
     3246    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     3247    AssertPtrReturn(pStreamEx, 0);
     3248    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, 0);
     3249    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, 0);
     3250    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"));
    30873251    int rc = RTCritSectEnter(&pThis->CritSect);
    30883252    AssertRCReturn(rc, 0);
     
    30953259    /* Note: We don't propage the backend stream's status to the outside -- it's the job of this
    30963260     *       audio connector to make sense of it. */
    3097     if (PDMAudioStrmStatusCanWrite(pStream->fStatus))
    3098     {
    3099         cbWritable = AudioMixBufFreeBytes(&pStream->Host.MixBuf);
     3261    if (PDMAudioStrmStatusCanWrite(pStreamEx->Core.fStatus))
     3262    {
     3263        if (pStreamEx->fNoMixBufs)
     3264            cbWritable = pThis->pHostDrvAudio ? pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream) : 0;
     3265        else
     3266            cbWritable = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf);
    31003267
    31013268        /* Make sure to align the writable size to the host's frame size. */
    3102         cbWritable = PDMAudioPropsFloorBytesToFrame(&pStream->Host.Cfg.Props, cbWritable);
     3269        cbWritable = PDMAudioPropsFloorBytesToFrame(&pStreamEx->Host.Cfg.Props, cbWritable);
    31033270    }
    31043271
    31053272    RTCritSectLeave(&pThis->CritSect);
    31063273    Log3Func(("[%s] cbWritable=%RU32 (%RU64ms)\n",
    3107               pStream->szName, cbWritable, PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbWritable)));
     3274              pStreamEx->Core.szName, cbWritable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbWritable)));
    31083275    return cbWritable;
    31093276}
     
    31173284    AssertPtr(pThis);
    31183285
     3286    /** @todo r=bird: It is not documented that we ignore NULL streams...  Why is
     3287     *        this necessary? */
    31193288    if (!pStream)
    31203289        return PDMAUDIOSTREAMSTS_FLAGS_NONE;
     3290    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     3291    AssertPtrReturn(pStreamEx, PDMAUDIOSTREAMSTS_FLAGS_NONE);
     3292    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, PDMAUDIOSTREAMSTS_FLAGS_NONE);
     3293    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, PDMAUDIOSTREAMSTS_FLAGS_NONE);
    31213294
    31223295    int rc = RTCritSectEnter(&pThis->CritSect);
     
    31243297
    31253298    /* Is the stream scheduled for re-initialization? Do so now. */
    3126     drvAudioStreamMaybeReInit(pThis, pStream);
    3127 
    3128     PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus;
     3299    drvAudioStreamMaybeReInit(pThis, pStreamEx);
     3300
     3301    PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus;
    31293302
    31303303    RTCritSectLeave(&pThis->CritSect);
     
    31323305    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    31333306#endif
    3134     Log3Func(("[%s] %s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
     3307    Log3Func(("[%s] %s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
    31353308    return fStrmStatus;
    31363309}
     
    31423315{
    31433316    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    3144     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    3145     AssertPtrReturn(pVol,       VERR_INVALID_POINTER);
    3146 
    3147     LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStream->szName, pVol->uLeft, pVol->uRight, pVol->fMuted));
    3148 
    3149     AudioMixBufSetVolume(&pStream->Guest.MixBuf, pVol);
    3150     AudioMixBufSetVolume(&pStream->Host.MixBuf, pVol);
     3317    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
     3318    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     3319    AssertPtrReturn(pVol, VERR_INVALID_POINTER);
     3320    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     3321    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
     3322
     3323    LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStreamEx->Core.szName, pVol->uLeft, pVol->uRight, pVol->fMuted));
     3324    AssertReturn(!pStreamEx->fNoMixBufs, VERR_ACCESS_DENIED);
     3325
     3326    AudioMixBufSetVolume(&pStreamEx->Guest.MixBuf, pVol);
     3327    AudioMixBufSetVolume(&pStreamEx->Host.MixBuf,  pVol);
    31513328
    31523329    return VINF_SUCCESS;
     
    31603337 *
    31613338 * @returns VBox status code.
    3162  * @param   pThis               Pointer to driver instance.
    3163  * @param   pStream             Audio stream destruct backend for.
    3164  */
    3165 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
    3166 {
    3167     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    3168     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     3339 * @param   pThis       Pointer to driver instance.
     3340 * @param   pStreamEx   Audio stream destruct backend for.
     3341 */
     3342static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
     3343{
     3344    AssertPtr(pThis);
     3345    AssertPtr(pStreamEx);
    31693346
    31703347    int rc = VINF_SUCCESS;
     
    31733350    char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    31743351#endif
    3175     LogFunc(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
    3176 
    3177     if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED)
    3178     {
    3179         AssertPtr(pStream->pvBackend);
     3352    LogFunc(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
     3353
     3354    if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED)
     3355    {
     3356        AssertPtr(pStreamEx->pvBackend);
    31803357
    31813358        /* Check if the pointer to  the host audio driver is still valid.
    31823359         * It can be NULL if we were called in drvAudioDestruct, for example. */
    31833360        if (pThis->pHostDrvAudio)
    3184             rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStream->pvBackend);
    3185 
    3186         pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
    3187     }
    3188 
    3189     LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
     3361            rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     3362
     3363        pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
     3364    }
     3365
     3366    LogFlowFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
    31903367    return rc;
    31913368}
     
    31963373 *
    31973374 * @returns VBox status code.
    3198  * @param   pThis               Pointer to driver instance.
    3199  * @param   pStream             Pointer to audio stream to uninitialize.
     3375 * @param   pThis       Pointer to driver instance.
     3376 * @param   pStreamEx   Pointer to audio stream to uninitialize.
    32003377 *
    32013378 * @note    Caller owns the critical section.
    32023379 */
    3203 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     3380static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
    32043381{
    32053382    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    3206     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    3207     AssertMsgReturn(pStream->cRefs <= 1,
    3208                     ("Stream '%s' still has %RU32 references held when uninitializing\n", pStream->szName, pStream->cRefs),
     3383    AssertMsgReturn(pStreamEx->Core.cRefs <= 1,
     3384                    ("Stream '%s' still has %RU32 references held when uninitializing\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs),
    32093385                    VERR_WRONG_ORDER);
    3210     LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
     3386    LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs));
    32113387
    32123388    /*
    32133389     * ...
    32143390     */
    3215     int rc = drvAudioStreamControlInternal(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     3391    int rc = drvAudioStreamControlInternal(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    32163392    if (RT_SUCCESS(rc))
    3217         rc = drvAudioStreamDestroyInternalBackend(pThis, pStream);
     3393        rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
    32183394
    32193395    /* Destroy mixing buffers. */
    3220     AudioMixBufDestroy(&pStream->Guest.MixBuf);
    3221     AudioMixBufDestroy(&pStream->Host.MixBuf);
     3396    AudioMixBufDestroy(&pStreamEx->Guest.MixBuf);
     3397    AudioMixBufDestroy(&pStreamEx->Host.MixBuf);
    32223398
    32233399    if (RT_SUCCESS(rc))
    32243400    {
    32253401#ifdef LOG_ENABLED
    3226         if (pStream->fStatus != PDMAUDIOSTREAMSTS_FLAGS_NONE)
     3402        if (pStreamEx->Core.fStatus != PDMAUDIOSTREAMSTS_FLAGS_NONE)
    32273403        {
    32283404            char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
    32293405            LogFunc(("[%s] Warning: Still has %s set when uninitializing\n",
    3230                      pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
     3406                     pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
    32313407        }
    32323408#endif
    3233         pStream->fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;
     3409        pStreamEx->Core.fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;
    32343410    }
    32353411
    32363412    PPDMDRVINS const pDrvIns = pThis->pDrvIns;
    3237     if (pStream->enmDir == PDMAUDIODIR_IN)
     3413    if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
    32383414    {
    32393415#ifdef VBOX_WITH_STATISTICS
    3240         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalFramesCaptured);
    3241         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalTimesCaptured);
    3242         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalFramesRead);
    3243         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalTimesRead);
     3416        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalFramesCaptured);
     3417        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalTimesCaptured);
     3418        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalFramesRead);
     3419        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalTimesRead);
    32443420#endif
    32453421        if (pThis->In.Cfg.Dbg.fEnabled)
    32463422        {
    3247             AudioHlpFileDestroy(pStream->In.Dbg.pFileCaptureNonInterleaved);
    3248             pStream->In.Dbg.pFileCaptureNonInterleaved = NULL;
    3249 
    3250             AudioHlpFileDestroy(pStream->In.Dbg.pFileStreamRead);
    3251             pStream->In.Dbg.pFileStreamRead = NULL;
    3252         }
    3253         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cMixed);
    3254         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cUsed);
     3423            AudioHlpFileDestroy(pStreamEx->In.Dbg.pFileCaptureNonInterleaved);
     3424            pStreamEx->In.Dbg.pFileCaptureNonInterleaved = NULL;
     3425
     3426            AudioHlpFileDestroy(pStreamEx->In.Dbg.pFileStreamRead);
     3427            pStreamEx->In.Dbg.pFileStreamRead = NULL;
     3428        }
     3429        if (!pStreamEx->fNoMixBufs)
     3430        {
     3431            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cMixed);
     3432            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed);
     3433        }
    32553434    }
    32563435    else
    32573436    {
    3258         Assert(pStream->enmDir == PDMAUDIODIR_OUT);
     3437        Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT);
    32593438#ifdef VBOX_WITH_STATISTICS
    3260         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalFramesPlayed);
    3261         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalTimesPlayed);
    3262         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalFramesWritten);
    3263         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalTimesWritten);
     3439        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalFramesPlayed);
     3440        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalTimesPlayed);
     3441        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalFramesWritten);
     3442        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalTimesWritten);
    32643443#endif
    32653444        if (pThis->Out.Cfg.Dbg.fEnabled)
    32663445        {
    3267             AudioHlpFileDestroy(pStream->Out.Dbg.pFilePlayNonInterleaved);
    3268             pStream->Out.Dbg.pFilePlayNonInterleaved = NULL;
    3269 
    3270             AudioHlpFileDestroy(pStream->Out.Dbg.pFileStreamWrite);
    3271             pStream->Out.Dbg.pFileStreamWrite = NULL;
    3272         }
    3273         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.cbBackendWritableAfter);
    3274         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.cbBackendWritableBefore);
    3275         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cUsed);
    3276         PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cMixed);
    3277     }
    3278     PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.Cfg.Backend.cFramesBufferSize);
    3279     PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cFrames);
    3280     PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cFrames);
     3446            AudioHlpFileDestroy(pStreamEx->Out.Dbg.pFilePlayNonInterleaved);
     3447            pStreamEx->Out.Dbg.pFilePlayNonInterleaved = NULL;
     3448
     3449            AudioHlpFileDestroy(pStreamEx->Out.Dbg.pFileStreamWrite);
     3450            pStreamEx->Out.Dbg.pFileStreamWrite = NULL;
     3451        }
     3452        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableAfter);
     3453        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableBefore);
     3454        if (!pStreamEx->fNoMixBufs)
     3455        {
     3456            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cUsed);
     3457            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed);
     3458        }
     3459    }
     3460    PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.Cfg.Backend.cFramesBufferSize);
     3461    if (!pStreamEx->fNoMixBufs)
     3462    {
     3463        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cFrames);
     3464        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames);
     3465    }
    32813466
    32823467    LogFlowFunc(("Returning %Rrc\n", rc));
     
    32953480        return VINF_SUCCESS;
    32963481    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    3297     Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC);
     3482    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;   /* Note! Do not touch pStream after this! */
     3483    Assert(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC);
     3484    Assert(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC);
    32983485
    32993486    int rc = RTCritSectEnter(&pThis->CritSect);
    33003487    AssertRCReturn(rc, rc);
    33013488
    3302     LogRel2(("Audio: Destroying stream '%s'\n", pStream->szName));
    3303 
    3304     LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
    3305     AssertMsg(pStream->cRefs <= 1, ("%u %s\n", pStream->cRefs, pStream->szName));
    3306     if (pStream->cRefs <= 1)
    3307     {
    3308         rc = drvAudioStreamUninitInternal(pThis, pStream);
     3489    LogRel2(("Audio: Destroying stream '%s'\n", pStreamEx->Core.szName));
     3490
     3491    LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs));
     3492    AssertMsg(pStreamEx->Core.cRefs <= 1, ("%u %s\n", pStreamEx->Core.cRefs, pStreamEx->Core.szName));
     3493    if (pStreamEx->Core.cRefs <= 1)
     3494    {
     3495        rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
    33093496        if (RT_SUCCESS(rc))
    33103497        {
    3311             if (pStream->enmDir == PDMAUDIODIR_IN)
     3498            if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
    33123499                pThis->In.cStreamsFree++;
    33133500            else /* Out */
    33143501                pThis->Out.cStreamsFree++;
    33153502
    3316             RTListNodeRemove(&pStream->ListEntry);
    3317 
    3318             drvAudioStreamFree(pStream);
     3503            RTListNodeRemove(&pStreamEx->ListEntry);
     3504
     3505            drvAudioStreamFree(pStreamEx);
     3506            pStreamEx = NULL;
    33193507            pStream = NULL;
    33203508        }
    33213509        else
    3322             LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStream->szName, rc));
     3510            LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
    33233511    }
    33243512    else
     
    33753563         * in drvAudioDestruct().
    33763564         */
    3377         PPDMAUDIOSTREAM pStream;
    3378         RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
    3379         {
    3380             drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    3381             drvAudioStreamDestroyInternalBackend(pThis, pStream);
     3565        PDRVAUDIOSTREAM pStreamEx;
     3566        RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
     3567        {
     3568            drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
     3569            drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
    33823570        }
    33833571
     
    35343722    pThis->pHostDrvAudio = NULL;
    35353723
    3536     PPDMAUDIOSTREAM pStream, pStreamNext;
    3537     RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, ListEntry)
    3538     {
    3539         int rc = drvAudioStreamUninitInternal(pThis, pStream);
     3724    PDRVAUDIOSTREAM pStreamEx, pStreamExNext;
     3725    RTListForEachSafe(&pThis->lstStreams, pStreamEx, pStreamExNext, DRVAUDIOSTREAM, ListEntry)
     3726    {
     3727        int rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
    35403728        if (RT_SUCCESS(rc))
    35413729        {
    3542             RTListNodeRemove(&pStream->ListEntry);
    3543 
    3544             drvAudioStreamFree(pStream);
    3545             pStream = NULL;
     3730            RTListNodeRemove(&pStreamEx->ListEntry);
     3731            drvAudioStreamFree(pStreamEx);
    35463732        }
    35473733    }
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r88314 r88356  
    206206     * General stuff.
    207207     */
    208     PDMAUDIOMIXBUF mb;
     208    AUDIOMIXBUF mb;
    209209    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&mb, "Single", &config, cBufSize));
    210210    RTTESTI_CHECK(AudioMixBufSize(&mb) == cBufSize);
     
    323323    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
    324324
    325     PDMAUDIOMIXBUF parent;
     325    AUDIOMIXBUF parent;
    326326    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cParentBufSize));
    327327
     
    340340    uint32_t cChildBufSize = RTRandU32Ex(cFrames /* Min */, 64 /* Max */);
    341341
    342     PDMAUDIOMIXBUF child1;
     342    AUDIOMIXBUF child1;
    343343    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &cfg_c1, cChildBufSize));
    344344    RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent));
     
    355355    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c2));
    356356
    357     PDMAUDIOMIXBUF child2;
     357    AUDIOMIXBUF child2;
    358358    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &cfg_c2, cChildBufSize));
    359359    RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent));
     
    460460    PDMAUDIOPCMPROPS const CfgDst = PDMAUDIOPCMPROPS_INITIALIZER(2 /*cbSample*/, true /*fSigned*/, 2 /*ch*/, uToHz, false /*fSwap*/);
    461461    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgDst));
    462     PDMAUDIOMIXBUF Parent;
     462    AUDIOMIXBUF Parent;
    463463    RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&Parent, "ParentDownsampling", &CfgDst, cFramesParent));
    464464
     
    467467    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgSrc));
    468468    uint32_t const cFramesChild = RTRandU32Ex(32, RT_ELEMENTS(aSrcFrames));
    469     PDMAUDIOMIXBUF Child;
     469    AUDIOMIXBUF Child;
    470470    RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&Child, "ChildDownsampling", &CfgSrc, cFramesChild));
    471471    RTTESTI_CHECK_RC_OK_RETV(AudioMixBufLinkTo(&Child, &Parent));
     
    567567    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
    568568
    569     PDMAUDIOMIXBUF parent;
     569    AUDIOMIXBUF parent;
    570570    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
    571571
     
    589589    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));
    590590
    591     PDMAUDIOMIXBUF child;
     591    AUDIOMIXBUF child;
    592592    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
    593593    RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
     
    669669    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
    670670
    671     PDMAUDIOMIXBUF parent;
     671    AUDIOMIXBUF parent;
    672672    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
    673673
     
    683683    RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));
    684684
    685     PDMAUDIOMIXBUF child;
     685    AUDIOMIXBUF child;
    686686    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
    687687    RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
     
    763763
    764764    PDMAUDIOVOLUME vol = { false, 0, 0 };   /* Not muted. */
    765     PDMAUDIOMIXBUF parent;
     765    AUDIOMIXBUF parent;
    766766    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg, cBufSize));
    767767
    768     PDMAUDIOMIXBUF child;
     768    AUDIOMIXBUF child;
    769769    RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg, cBufSize));
    770770    RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
Note: See TracChangeset for help on using the changeset viewer.

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