Index: trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp	(revision 88356)
@@ -64,6 +64,6 @@
 
 #ifdef DEBUG
-DECLINLINE(void)        audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc);
-DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf);
+DECLINLINE(void)        audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc);
+DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf);
 #endif
 
@@ -152,5 +152,5 @@
 /** @todo r=bird: This isn't a 'ing Peek function, it's a Read function!
  *        Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg!!!!!!!!!!!!!!!!!!! */
-int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames,
+int AudioMixBufPeekMutable(PAUDIOMIXBUF pMixBuf, uint32_t cFrames,
                            PPDMAUDIOFRAME *ppvFrames, uint32_t *pcFramesToWrite)
 {
@@ -197,5 +197,5 @@
  *
  */
-void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufClear(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturnVoid(pMixBuf);
@@ -212,5 +212,5 @@
  * @param   cFramesToClear          Number of audio frames to clear.
  */
-void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear)
+void AudioMixBufFinish(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear)
 {
     AUDMIXBUF_LOG(("cFramesToClear=%RU32\n", cFramesToClear));
@@ -221,6 +221,6 @@
 
 /** @todo r=bird: Why isn't this done when reading/releaseing ? */
-    PPDMAUDIOMIXBUF pIter;
-    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
+    PAUDIOMIXBUF pIter;
+    RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node)
     {
         AUDMIXBUF_LOG(("\t%s: cMixed=%RU32 -> %RU32\n",
@@ -271,5 +271,5 @@
  * @param   pMixBuf                 Mixing buffer to destroy.
  */
-void AudioMixBufDestroy(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufDestroy(PAUDIOMIXBUF pMixBuf)
 {
     if (!pMixBuf)
@@ -278,5 +278,5 @@
     /* Ignore calls for an uninitialized (zeroed) or already destroyed instance.  Happens a lot. */
     if (   pMixBuf->uMagic == 0
-        || pMixBuf->uMagic == ~PDMAUDIOMIXBUF_MAGIC)
+        || pMixBuf->uMagic == ~AUDIOMIXBUF_MAGIC)
     {
         Assert(!pMixBuf->pszName);
@@ -287,6 +287,6 @@
     }
 
-    Assert(pMixBuf->uMagic == PDMAUDIOMIXBUF_MAGIC);
-    pMixBuf->uMagic = ~PDMAUDIOMIXBUF_MAGIC;
+    Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
+    pMixBuf->uMagic = ~AUDIOMIXBUF_MAGIC;
 
     AudioMixBufUnlink(pMixBuf);
@@ -323,5 +323,5 @@
  * @param   pMixBuf                 Mixing buffer to return free size for.
  */
-uint32_t AudioMixBufFree(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufFree(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -356,5 +356,5 @@
  * @param   pMixBuf                 Mixing buffer to return free size for.
  */
-uint32_t AudioMixBufFreeBytes(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufFreeBytes(PAUDIOMIXBUF pMixBuf)
 {
     return AUDIOMIXBUF_F2B(pMixBuf, AudioMixBufFree(pMixBuf));
@@ -368,5 +368,5 @@
  * @param   cFrames                 Number of audio frames to allocate.
  */
-static int audioMixBufAlloc(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)
+static int audioMixBufAlloc(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
@@ -424,5 +424,5 @@
     \
     DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, \
-                                                               PCPDMAUDMIXBUFCONVOPTS pOpts) \
+                                                               PCAUDMIXBUFCONVOPTS pOpts) \
     { \
         _aType const *pSrc = (_aType const *)pvSrc; \
@@ -441,5 +441,5 @@
     \
     DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Mono(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, \
-                                                             PCPDMAUDMIXBUFCONVOPTS pOpts) \
+                                                             PCAUDMIXBUFCONVOPTS pOpts) \
     { \
         _aType const *pSrc = (_aType const *)pvSrc; \
@@ -458,5 +458,5 @@
     } \
     \
-    DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts) \
+    DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) \
     { \
         PCPDMAUDIOFRAME pSrc = paSrc; \
@@ -474,5 +474,5 @@
     } \
     \
-    DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOFRAME paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts) \
+    DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) \
     { \
         PCPDMAUDIOFRAME pSrc = paSrc; \
@@ -506,5 +506,5 @@
 #if 0
 DECLCALLBACK(uint32_t) audioMixBufConvFromS64Stereo(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc,
-                                                    PCPDMAUDMIXBUFCONVOPTS pOpts)
+                                                    PCAUDMIXBUFCONVOPTS pOpts)
 {
     _aType const *pSrc = (_aType const *)pvSrc;
@@ -523,5 +523,5 @@
 #endif
 
-DECLCALLBACK(void) audioMixBufConvToRawS64Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCPDMAUDMIXBUFCONVOPTS pOpts)
+DECLCALLBACK(void) audioMixBufConvToRawS64Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts)
 {
     AssertCompile(sizeof(paSrc[0]) == sizeof(int64_t) * 2);
@@ -535,5 +535,5 @@
     static void audioMixBufOp##_aName(PPDMAUDIOFRAME paDst, uint32_t cDstFrames, \
                                       PPDMAUDIOFRAME paSrc, uint32_t cSrcFrames, \
-                                      PPDMAUDIOSTREAMRATE pRate, \
+                                      PAUDIOSTREAMRATE pRate, \
                                       uint32_t *pcDstWritten, uint32_t *pcSrcRead) \
     { \
@@ -631,5 +631,5 @@
 /** Dummy conversion used when the source is muted. */
 static DECLCALLBACK(uint32_t)
-audioMixBufConvFromSilence(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, PCPDMAUDMIXBUFCONVOPTS pOpts)
+audioMixBufConvFromSilence(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, PCAUDMIXBUFCONVOPTS pOpts)
 {
     RT_NOREF(cbSrc, pvSrc);
@@ -647,5 +647,5 @@
  * @param   pProps  The audio format to find a "from" converter for.
  */
-static PFNPDMAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps)
+static PFNAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps)
 {
     if (PDMAudioPropsIsSigned(pProps))
@@ -710,5 +710,5 @@
  * @param   pProps  The audio format to find a "to" converter for.
  */
-static PFNPDMAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps)
+static PFNAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps)
 {
     if (PDMAudioPropsIsSigned(pProps))
@@ -773,5 +773,5 @@
  * @param   pVolSrc                 Volume to convert.
  */
-static int audioMixBufConvVol(PPDMAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc)
+static int audioMixBufConvVol(PAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc)
 {
     if (!pVolSrc->fMuted) /* Only change/convert the volume value if we're not muted. */
@@ -799,5 +799,5 @@
  * @param   cFrames                 Maximum number of audio frames the mixing buffer can hold.
  */
-int AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
+int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
@@ -806,5 +806,5 @@
     Assert(PDMAudioPropsAreValid(pProps));
 
-    pMixBuf->uMagic  = PDMAUDIOMIXBUF_MAGIC;
+    pMixBuf->uMagic  = AUDIOMIXBUF_MAGIC;
     pMixBuf->pParent = NULL;
 
@@ -862,5 +862,5 @@
  * @param   pMixBuf                 Mixing buffer to return value for.
  */
-bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf)
+bool AudioMixBufIsEmpty(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, true);
@@ -878,5 +878,5 @@
  * @param   pMixBufB            Second mixing buffer.
  */
-static int64_t audioMixBufCalcFreqRatio(PPDMAUDIOMIXBUF pMixBufA, PPDMAUDIOMIXBUF pMixBufB)
+static int64_t audioMixBufCalcFreqRatio(PAUDIOMIXBUF pMixBufA, PAUDIOMIXBUF pMixBufB)
 {
     int64_t iRatio = (int64_t)((uint64_t)PDMAudioPropsHz(&pMixBufA->Props) << 32) / PDMAudioPropsHz(&pMixBufB->Props);
@@ -906,5 +906,5 @@
  * @remark  Circular linking is not allowed.
  */
-int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent)
+int AudioMixBufLinkTo(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUF pParent)
 {
     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
@@ -969,9 +969,9 @@
         if (!pMixBuf->pRate)
         {
-            pMixBuf->pRate = (PPDMAUDIOSTREAMRATE)RTMemAllocZ(sizeof(PDMAUDIOSTREAMRATE));
+            pMixBuf->pRate = (PAUDIOSTREAMRATE)RTMemAllocZ(sizeof(AUDIOSTREAMRATE));
             AssertReturn(pMixBuf->pRate, VERR_NO_MEMORY);
         }
         else
-            RT_BZERO(pMixBuf->pRate, sizeof(PDMAUDIOSTREAMRATE));
+            RT_BZERO(pMixBuf->pRate, sizeof(AUDIOSTREAMRATE));
 
         /*
@@ -1008,5 +1008,5 @@
  * @param   pMixBuf                 Mixing buffer to return value for.
  */
-uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufLive(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -1051,5 +1051,5 @@
  * @param   pcSrcMixed              Number of source audio frames successfully mixed. Optional.
  */
-static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcFrames,
+static int audioMixBufMixTo(PAUDIOMIXBUF pDst, PAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcFrames,
                             uint32_t *pcSrcMixed)
 {
@@ -1189,5 +1189,5 @@
         Assert(cToRead <= pDst->cUsed);
 
-        PDMAUDMIXBUFCONVOPTS convOpts;
+        AUDMIXBUFCONVOPTS convOpts;
         RT_ZERO(convOpts);
         convOpts.cFrames = cToRead;
@@ -1230,5 +1230,5 @@
  * @param   pcSrcMixed              Number of source audio frames successfully mixed. Optional.
  */
-int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
+int AudioMixBufMixToParentEx(PAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
 {
     AssertMsgReturn(VALID_PTR(pMixBuf->pParent),
@@ -1247,5 +1247,5 @@
  * @param   pcSrcMixed              Number of source audio frames successfully mixed. Optional.
  */
-int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
+int AudioMixBufMixToParent(PAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed)
 {
     return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, pMixBuf->offRead, cSrcFrames, pcSrcMixed);
@@ -1263,5 +1263,5 @@
  * @param   uIdtLvl                 Indention level to use.
  */
-DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl)
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl)
 {
     Log(("%s: %*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n",
@@ -1276,5 +1276,5 @@
  * @param   pMixBuf                 Mixing buffer to validate.
  */
-DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf)
+DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf)
 {
     //const uint32_t offReadEnd  = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cFrames;
@@ -1317,9 +1317,9 @@
  * @param   pcChildren              Pointer to children counter.
  */
-DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl,
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl,
                                                        size_t *pcChildren)
 {
-    PPDMAUDIOMIXBUF pIter;
-    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
+    PAUDIOMIXBUF pIter;
+    RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node)
     {
         audioMixBufDbgPrintSingle(pIter, pszFunc, false /* ifIsParent */, uIdtLvl + 1);
@@ -1328,7 +1328,7 @@
 }
 
-DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc)
-{
-    PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc)
+{
+    PAUDIOMIXBUF pParent = pMixBuf->pParent;
     while (pParent)
     {
@@ -1359,12 +1359,12 @@
  * @param   pMixBuf                 Mixing buffer to print.
  */
-void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufDbgPrintChain(PAUDIOMIXBUF pMixBuf)
 {
     audioMixBufDbgPrintChainInternal(pMixBuf, __FUNCTION__);
 }
 
-DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc)
-{
-    PPDMAUDIOMIXBUF pParent = pMixBuf;
+DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc)
+{
+    PAUDIOMIXBUF pParent = pMixBuf;
     if (pMixBuf->pParent)
         pParent = pMixBuf->pParent;
@@ -1372,6 +1372,6 @@
     audioMixBufDbgPrintSingle(pMixBuf, pszFunc, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */);
 
-    PPDMAUDIOMIXBUF pIter;
-    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
+    PAUDIOMIXBUF pIter;
+    RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node)
     {
         if (pIter == pMixBuf)
@@ -1388,5 +1388,5 @@
  * @param   pMixBuf                 Mixing buffer to print.
  */
-void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufDbgPrint(PAUDIOMIXBUF pMixBuf)
 {
     audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
@@ -1400,5 +1400,5 @@
  * @param   pMixBuf
  */
-uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufUsed(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -1412,5 +1412,5 @@
  * @param   pMixBuf
  */
-uint32_t AudioMixBufUsedBytes(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufUsedBytes(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -1428,5 +1428,5 @@
  * @param   pcbRead                 Size (in bytes) of data read. Optional.
  */
-int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
+int AudioMixBufReadAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
 {
     return AudioMixBufReadAtEx(pMixBuf, &pMixBuf->Props, offFrames, pvBuf, cbBuf, pcbRead);
@@ -1446,5 +1446,5 @@
  * @param   pcbRead     Size (in bytes) of data read. Optional.
  */
-int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
+int AudioMixBufReadAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
                         uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
 {
@@ -1466,5 +1466,5 @@
     if (cToProcess)
     {
-        PFNPDMAUDIOMIXBUFCONVTO pfnConvTo = NULL;
+        PFNAUDIOMIXBUFCONVTO pfnConvTo = NULL;
         if (PDMAudioPropsAreEqual(&pMixBuf->Props, pDstProps))
             pfnConvTo = pMixBuf->pfnConvTo;
@@ -1473,5 +1473,5 @@
         if (pfnConvTo)
         {
-            PDMAUDMIXBUFCONVOPTS convOpts;
+            AUDMIXBUFCONVOPTS convOpts;
             RT_ZERO(convOpts);
             /* Note: No volume handling/conversion done in the conversion-to macros (yet). */
@@ -1515,5 +1515,5 @@
  *                              the block that was acquired.
  */
-int AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
+int AudioMixBufAcquireReadBlock(PAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
 {
     return AudioMixBufAcquireReadBlockEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcAcquiredFrames);
@@ -1534,5 +1534,5 @@
  *                              the block that was acquired.
  */
-int AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
+int AudioMixBufAcquireReadBlockEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
                                   void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)
 {
@@ -1563,5 +1563,5 @@
     }
 
-    PFNPDMAUDIOMIXBUFCONVTO pfnConvTo;
+    PFNAUDIOMIXBUFCONVTO pfnConvTo;
     if (PDMAudioPropsAreEqual(&pMixBuf->Props, pDstProps))
         pfnConvTo = pMixBuf->pfnConvTo;
@@ -1573,5 +1573,5 @@
     if (cFramesToRead)
     {
-        PDMAUDMIXBUFCONVOPTS convOpts;
+        AUDMIXBUFCONVOPTS convOpts;
         RT_ZERO(convOpts);
         convOpts.cFrames = cFramesToRead;
@@ -1610,5 +1610,5 @@
  *                      acquired count.)
  */
-void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)
+void AudioMixBufReleaseReadBlock(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
 {
     AssertPtrReturnVoid(pMixBuf);
@@ -1628,5 +1628,5 @@
  * @param   pMixBuf                 Mixing buffer to return position for.
  */
-uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufReadPos(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -1640,5 +1640,5 @@
  * @param   pMixBuf                 Mixing buffer to reset.
  */
-void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufReset(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturnVoid(pMixBuf);
@@ -1660,5 +1660,5 @@
  * @param   pVol                    Pointer to volume structure to set.
  */
-void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol)
+void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol)
 {
     AssertPtrReturnVoid(pMixBuf);
@@ -1677,5 +1677,5 @@
  * @param   pMixBuf                 Mixing buffer to retrieve maximum for.
  */
-uint32_t AudioMixBufSize(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -1689,5 +1689,5 @@
  * @param   pMixBuf                 Mixing buffer to retrieve maximum for.
  */
-uint32_t AudioMixBufSizeBytes(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
@@ -1701,5 +1701,5 @@
  * @param   pMixBuf                 Mixing buffer to unlink from parent.
  */
-void AudioMixBufUnlink(PPDMAUDIOMIXBUF pMixBuf)
+void AudioMixBufUnlink(PAUDIOMIXBUF pMixBuf)
 {
     if (!pMixBuf || !pMixBuf->pszName)
@@ -1725,6 +1725,6 @@
     }
 
-    PPDMAUDIOMIXBUF pChild, pChildNext;
-    RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, PDMAUDIOMIXBUF, Node)
+    PAUDIOMIXBUF pChild, pChildNext;
+    RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, AUDIOMIXBUF, Node)
     {
         AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pChild->pszName));
@@ -1767,5 +1767,5 @@
  * @param   pcWritten               Returns number of audio frames written. Optional.
  */
-int AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
+int AudioMixBufWriteAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
 {
     return AudioMixBufWriteAtEx(pMixBuf, &pMixBuf->Props, offFrames, pvBuf, cbBuf, pcWritten);
@@ -1789,5 +1789,5 @@
  * @param   pcWritten   Returns number of audio frames written. Optional.
  */
-int AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
+int AudioMixBufWriteAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
                          uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
 {
@@ -1826,5 +1826,5 @@
      * Pick the conversion function and do the conversion.
      */
-    PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
+    PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
     if (!pMixBuf->Volume.fMuted)
     {
@@ -1843,5 +1843,5 @@
     if (cToWrite)
     {
-        PDMAUDMIXBUFCONVOPTS convOpts;
+        AUDMIXBUFCONVOPTS convOpts;
 
         convOpts.cFrames            = cToWrite;
@@ -1892,5 +1892,5 @@
  * @param   pcWritten               Returns number of audio frames written. Optional.
  */
-int AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
+int AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
 {
     return AudioMixBufWriteCircEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcWritten);
@@ -1910,5 +1910,5 @@
  * @param   pcWritten   Returns number of audio frames written. Optional.
  */
-int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
+int AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
                            const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
 {
@@ -1930,5 +1930,5 @@
     AssertPtr(pMixBuf->pFrames);
 
-    PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
+    PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;
     if (!pMixBuf->Volume.fMuted)
     {
@@ -1955,5 +1955,5 @@
         Assert(cToWrite);
 
-        PDMAUDMIXBUFCONVOPTS convOpts;
+        AUDMIXBUFCONVOPTS convOpts;
         convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted;
         convOpts.From.Volume.uLeft  = pMixBuf->Volume.uLeft;
@@ -2003,5 +2003,5 @@
  * @param   pMixBuf                 Mixing buffer to return position for.
  */
-uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf)
+uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf)
 {
     AssertPtrReturn(pMixBuf, 0);
Index: trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
===================================================================
--- trunk/src/VBox/Devices/Audio/AudioMixBuffer.h	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/AudioMixBuffer.h	(revision 88356)
@@ -24,4 +24,182 @@
 #include <iprt/cdefs.h>
 #include <VBox/vmm/pdmaudioifs.h>
+
+
+/**
+ * Rate processing information of a source & destination audio stream.
+ *
+ * This is needed because both streams can differ regarding their rates and
+ * therefore need to be treated accordingly.
+ */
+typedef struct AUDIOSTREAMRATE
+{
+    /** Current (absolute) offset in the output (destination) stream.
+     * @todo r=bird: Please reveal which unit these members are given in. */
+    uint64_t        offDst;
+    /** Increment for moving offDst for the destination stream.
+     * This is needed because the source <-> destination rate might be different. */
+    uint64_t        uDstInc;
+    /** Current (absolute) offset in the input stream. */
+    uint32_t        offSrc;
+    /** Explicit alignment padding. */
+    uint32_t        u32AlignmentPadding;
+    /** Last processed frame of the input stream.
+     *  Needed for interpolation. */
+    PDMAUDIOFRAME   SrcFrameLast;
+} AUDIOSTREAMRATE;
+/** Pointer to rate processing information of a stream. */
+typedef AUDIOSTREAMRATE *PAUDIOSTREAMRATE;
+
+/**
+ * Mixing buffer volume parameters.
+ *
+ * The volume values are in fixed point style and must be converted to/from
+ * before using with e.g. PDMAUDIOVOLUME.
+ */
+typedef struct AUDMIXBUFVOL
+{
+    /** Set to @c true if this stream is muted, @c false if not. */
+    bool            fMuted;
+    /** Left volume to apply during conversion.
+     * Pass 0 to convert the original values. May not apply to all conversion functions. */
+    uint32_t        uLeft;
+    /** Right volume to apply during conversion.
+     * Pass 0 to convert the original values. May not apply to all conversion functions. */
+    uint32_t        uRight;
+} AUDMIXBUFVOL;
+/** Pointer to mixing buffer volument parameters. */
+typedef AUDMIXBUFVOL *PAUDMIXBUFVOL;
+
+/*
+ * Frame conversion parameters for the audioMixBufConvFromXXX / audioMixBufConvToXXX functions.
+ */
+typedef struct AUDMIXBUFCONVOPTS
+{
+    /** Number of audio frames to convert. */
+    uint32_t        cFrames;
+    union
+    {
+        struct
+        {
+            /** Volume to use for conversion. */
+            AUDMIXBUFVOL Volume;
+        } From;
+    } RT_UNION_NM(u);
+} AUDMIXBUFCONVOPTS;
+/** Pointer to conversion parameters for the audio mixer.   */
+typedef AUDMIXBUFCONVOPTS *PAUDMIXBUFCONVOPTS;
+/** Pointer to const conversion parameters for the audio mixer.   */
+typedef AUDMIXBUFCONVOPTS const *PCAUDMIXBUFCONVOPTS;
+
+/**
+ * @note All internal handling is done in audio frames, not in bytes!
+ * @todo r=bird: What does this note actually apply to?
+ */
+typedef uint32_t AUDIOMIXBUFFMT;
+typedef AUDIOMIXBUFFMT *PAUDIOMIXBUFFMT;
+
+/**
+ * Convertion-from function used by the audio buffer mixer.
+ *
+ * @returns Number of audio frames returned.
+ * @param   paDst           Where to return the converted frames.
+ * @param   pvSrc           The source frame bytes.
+ * @param   cbSrc           Number of bytes to convert.
+ * @param   pOpts           Conversion options.
+ * @todo r=bird: The @a paDst size is presumable given in @a pOpts->cFrames?
+ */
+typedef DECLCALLBACKTYPE(uint32_t, FNAUDIOMIXBUFCONVFROM,(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc,
+                                                          PCAUDMIXBUFCONVOPTS pOpts));
+/** Pointer to a convertion-from function used by the audio buffer mixer. */
+typedef FNAUDIOMIXBUFCONVFROM *PFNAUDIOMIXBUFCONVFROM;
+
+/**
+ * Convertion-to function used by the audio buffer mixer.
+ *
+ * @param   pvDst           Output buffer.
+ * @param   paSrc           The input frames.
+ * @param   pOpts           Conversion options.
+ * @todo r=bird: The @a paSrc size is presumable given in @a pOpts->cFrames and
+ *       this implicitly gives the pvDst size too, right?
+ */
+typedef DECLCALLBACKTYPE(void, FNAUDIOMIXBUFCONVTO,(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts));
+/** Pointer to a convertion-to function used by the audio buffer mixer. */
+typedef FNAUDIOMIXBUFCONVTO *PFNAUDIOMIXBUFCONVTO;
+
+/** Pointer to audio mixing buffer.  */
+typedef struct AUDIOMIXBUF *PAUDIOMIXBUF;
+
+/**
+ * Audio mixing buffer.
+ */
+typedef struct AUDIOMIXBUF
+{
+    /** Magic value (AUDIOMIXBUF_MAGIC). */
+    uint32_t                    uMagic;
+    uint8_t                     abPadding[4];
+    /* ???Undocumented??? */
+    RTLISTNODE                  Node;
+    /** Name of the buffer. */
+    char                       *pszName;
+    /** Frame buffer. */
+    PPDMAUDIOFRAME              pFrames;
+    /** Size of the frame buffer (in audio frames). */
+    uint32_t                    cFrames;
+    /** The current read position (in frames). */
+    uint32_t                    offRead;
+    /** The current write position (in frames). */
+    uint32_t                    offWrite;
+    /** Total frames already mixed down to the parent buffer (if any).
+     *
+     * Always starting at the parent's offRead position.
+     * @note Count always is specified in parent frames, as the sample count can
+     *       differ between parent and child.  */
+    uint32_t                    cMixed;
+    /** How much audio frames are currently being used in this buffer.
+     * @note This also is known as the distance in ring buffer terms. */
+    uint32_t                    cUsed;
+    /** Number of children mix buffers kept in lstChildren. */
+    uint32_t                    cChildren;
+    /** List of children mix buffers to keep in sync with (if being a parent buffer). */
+    RTLISTANCHOR                lstChildren;
+    /** Pointer to parent buffer (if any). */
+    PAUDIOMIXBUF                pParent;
+    /** Intermediate structure for buffer conversion tasks. */
+    PAUDIOSTREAMRATE            pRate;
+    /** Internal representation of current volume used for mixing. */
+    AUDMIXBUFVOL                Volume;
+    /** This buffer's audio format.
+     * @todo r=bird: This seems to be a value created by AUDMIXBUF_AUDIO_FMT_MAKE(),
+     *       which is not define here.  Does this structure really belong here at
+     *       all?  */
+    AUDIOMIXBUFFMT              uAudioFmt;
+    /** Audio input properties.
+     * @note There is only one set of audio properties here because we have one
+     *       mixer buffer for the guest side and a separate one for the host side.
+     * @todo r=bird: Why exactly do we need to use separate mixer buffers?
+     *       Couldn't we just have different conversion fuctions and save the
+     *       extra copying? */
+    PDMAUDIOPCMPROPS            Props;
+    /** Standard conversion-to function for set uAudioFmt. */
+    PFNAUDIOMIXBUFCONVTO        pfnConvTo;
+    /** Standard conversion-from function for set uAudioFmt. */
+    PFNAUDIOMIXBUFCONVFROM      pfnConvFrom;
+
+    /** Ratio of the associated parent stream's frequency by this stream's
+     * frequency (1<<32), represented as a signed 64 bit integer.
+     *
+     * For example, if the parent stream has a frequency of 44 khZ, and this
+     * stream has a frequency of 11 kHz, the ration then would be
+     * (44/11 * (1 << 32)).
+     *
+     * Currently this does not get changed once assigned. */
+    int64_t                     iFreqRatio;
+} AUDIOMIXBUF;
+
+/** Magic value for AUDIOMIXBUF (Antonio Lucio Vivaldi). */
+#define AUDIOMIXBUF_MAGIC           UINT32_C(0x16780304)
+/** Dead mixer buffer magic. */
+#define AUDIOMIXBUF_MAGIC_DEAD      UINT32_C(0x17410728)
+
 
 /** Constructs 32 bit value for given frequency, number of channels, bits per sample and signed bit.
@@ -54,42 +232,42 @@
 
 
-int     AudioMixBufInit(PPDMAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);
-void    AudioMixBufDestroy(PPDMAUDIOMIXBUF pMixBuf);
-void AudioMixBufClear(PPDMAUDIOMIXBUF pMixBuf);
-void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear);
-uint32_t AudioMixBufFree(PPDMAUDIOMIXBUF pMixBuf);
-uint32_t AudioMixBufFreeBytes(PPDMAUDIOMIXBUF pMixBuf);
-bool AudioMixBufIsEmpty(PPDMAUDIOMIXBUF pMixBuf);
-int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent);
-uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf);
-int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
-int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
-int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, PPDMAUDIOFRAME *ppvSamples, uint32_t *pcFramesRead);
-uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf);
-uint32_t AudioMixBufUsedBytes(PPDMAUDIOMIXBUF pMixBuf);
-int         AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
-int         AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, uint32_t offFrames,
+int     AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);
+void    AudioMixBufDestroy(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufClear(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufFinish(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear);
+uint32_t AudioMixBufFree(PAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufFreeBytes(PAUDIOMIXBUF pMixBuf);
+bool AudioMixBufIsEmpty(PAUDIOMIXBUF pMixBuf);
+int AudioMixBufLinkTo(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUF pParent);
+uint32_t AudioMixBufLive(PAUDIOMIXBUF pMixBuf);
+int AudioMixBufMixToParent(PAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
+int AudioMixBufMixToParentEx(PAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed);
+int AudioMixBufPeekMutable(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, PPDMAUDIOFRAME *ppvSamples, uint32_t *pcFramesRead);
+uint32_t AudioMixBufUsed(PAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufUsedBytes(PAUDIOMIXBUF pMixBuf);
+int         AudioMixBufReadAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
+int         AudioMixBufReadAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, uint32_t offFrames,
                                 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
-int         AudioMixBufAcquireReadBlock(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
-int         AudioMixBufAcquireReadBlockEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
+int         AudioMixBufAcquireReadBlock(PAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
+int         AudioMixBufAcquireReadBlockEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,
                                           void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);
-void AudioMixBufReleaseReadBlock(PPDMAUDIOMIXBUF pMixBuf, uint32_t cFrames);
-uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf);
-void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf);
-void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol);
-uint32_t AudioMixBufSize(PPDMAUDIOMIXBUF pMixBuf);
-uint32_t AudioMixBufSizeBytes(PPDMAUDIOMIXBUF pMixBuf);
-void AudioMixBufUnlink(PPDMAUDIOMIXBUF pMixBuf);
-int         AudioMixBufWriteAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
-int         AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, uint32_t offFrames,
+void AudioMixBufReleaseReadBlock(PAUDIOMIXBUF pMixBuf, uint32_t cFrames);
+uint32_t AudioMixBufReadPos(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufReset(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol);
+uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufUnlink(PAUDIOMIXBUF pMixBuf);
+int         AudioMixBufWriteAt(PAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
+int         AudioMixBufWriteAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, uint32_t offFrames,
                                  const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
-int         AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
-int         AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
+int         AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);
+int         AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,
                                    const void *pvBuf,uint32_t cbBuf, uint32_t *pcWritten);
-uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf);
 
 #ifdef DEBUG
-void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf);
-void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf);
+void AudioMixBufDbgPrint(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufDbgPrintChain(PAUDIOMIXBUF pMixBuf);
 #endif
 
Index: trunk/src/VBox/Devices/Audio/AudioMixer.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/AudioMixer.cpp	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/AudioMixer.cpp	(revision 88356)
@@ -651,5 +651,5 @@
                      */
                     PPDMAUDIOSTREAM pStream;
-                    rc = pConn->pfnStreamCreate(pConn, &CfgHost, pCfg, &pStream);
+                    rc = pConn->pfnStreamCreate(pConn, 0 /*fFlags*/, &CfgHost, pCfg, &pStream);
                     if (RT_SUCCESS(rc))
                     {
Index: trunk/src/VBox/Devices/Audio/AudioMixer.h
===================================================================
--- trunk/src/VBox/Devices/Audio/AudioMixer.h	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/AudioMixer.h	(revision 88356)
@@ -29,4 +29,5 @@
 
 #include <VBox/vmm/pdmaudioifs.h>
+#include "AudioMixBuffer.h"
 
 
@@ -55,4 +56,5 @@
 /** Pointer to an audio mixer instance. */
 typedef AUDIOMIXER *PAUDIOMIXER;
+
 
 /** Defines an audio mixer stream's flags. */
@@ -201,5 +203,5 @@
     /** This sink's mixing buffer, acting as
      * a parent buffer for all streams this sink owns. */
-    PDMAUDIOMIXBUF          MixBuf;
+    AUDIOMIXBUF          MixBuf;
     /** Scratch buffer for multiplexing / mixing. Might be NULL if not needed. */
     uint8_t                *pabScratchBuf;
Index: trunk/src/VBox/Devices/Audio/DevSB16.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DevSB16.cpp	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/DevSB16.cpp	(revision 88356)
@@ -1775,5 +1775,5 @@
     pCfgHost->Backend.cFramesPreBuffering = 0;
 
-    int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream);
+    int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, 0 /*fFlags*/, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream);
     if (RT_SUCCESS(rc))
     {
Index: trunk/src/VBox/Devices/Audio/DrvAudio.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 88356)
@@ -65,4 +65,134 @@
     int overriden;
 } audio_option;
+
+/**
+ * Audio stream context.
+ *
+ * Needed for separating data from the guest and host side (per stream).
+ */
+typedef struct DRVAUDIOSTREAMCTX
+{
+    /** The stream's audio configuration. */
+    PDMAUDIOSTREAMCFG   Cfg;
+    /** This stream's mixing buffer. */
+    AUDIOMIXBUF         MixBuf;
+} DRVAUDIOSTREAMCTX;
+
+/**
+ * Extended stream structure.
+ */
+typedef struct DRVAUDIOSTREAM
+{
+    /** The publicly visible bit. */
+    PDMAUDIOSTREAM      Core;
+
+    /** Just an extra magic to verify that we allocated the stream rather than some
+     * faked up stuff from the device (DRVAUDIOSTREAM_MAGIC). */
+    uintptr_t           uMagic;
+
+    /** List entry (some DrvAudio internal list). */
+    RTLISTNODE          ListEntry;
+
+    /** Data to backend-specific stream data.
+     *  This data block will be casted by the backend to access its backend-dependent data.
+     *
+     *  That way the backends do not have access to the audio connector's data. */
+    void               *pvBackend;
+
+    /** For output streams this indicates whether the stream has reached
+     *  its playback threshold, e.g. is playing audio.
+     *  For input streams this  indicates whether the stream has enough input
+     *  data to actually start reading audio. */
+    bool                fThresholdReached;
+    /** Do not use the mixing buffers (Guest::MixBuf, Host::MixBuf). */
+    bool                fNoMixBufs;
+    bool                afPadding[2];
+
+    /** Number of (re-)tries while re-initializing the stream. */
+    uint32_t            cTriesReInit;
+
+    /** The guest side of the stream. */
+    DRVAUDIOSTREAMCTX   Guest;
+    /** The host side of the stream. */
+    DRVAUDIOSTREAMCTX   Host;
+
+
+    /** Timestamp (in ns) since last trying to re-initialize.
+     *  Might be 0 if has not been tried yet. */
+    uint64_t            nsLastReInit;
+    /** Timestamp (in ns) since last iteration. */
+    uint64_t            nsLastIterated;
+    /** Timestamp (in ns) since last playback / capture. */
+    uint64_t            nsLastPlayedCaptured;
+    /** Timestamp (in ns) since last read (input streams) or
+     *  write (output streams). */
+    uint64_t            nsLastReadWritten;
+
+
+    /** Union for input/output specifics depending on enmDir. */
+    union
+    {
+        /**
+         * The specifics for an audio input stream.
+         */
+        struct
+        {
+            struct
+            {
+                /** File for writing stream reads. */
+                PPDMAUDIOFILE   pFileStreamRead;
+                /** File for writing non-interleaved captures. */
+                PPDMAUDIOFILE   pFileCaptureNonInterleaved;
+            } Dbg;
+            struct
+            {
+                STAMCOUNTER     TotalFramesCaptured;
+                STAMCOUNTER     AvgFramesCaptured;
+                STAMCOUNTER     TotalTimesCaptured;
+                STAMCOUNTER     TotalFramesRead;
+                STAMCOUNTER     AvgFramesRead;
+                STAMCOUNTER     TotalTimesRead;
+            } Stats;
+        } In;
+
+        /**
+         * The specifics for an audio output stream.
+         */
+        struct
+        {
+            struct
+            {
+                /** File for writing stream writes. */
+                PPDMAUDIOFILE   pFileStreamWrite;
+                /** File for writing stream playback. */
+                PPDMAUDIOFILE   pFilePlayNonInterleaved;
+            } Dbg;
+            struct
+            {
+                STAMCOUNTER     TotalFramesPlayed;
+                STAMCOUNTER     AvgFramesPlayed;
+                STAMCOUNTER     TotalTimesPlayed;
+                STAMCOUNTER     TotalFramesWritten;
+                STAMCOUNTER     AvgFramesWritten;
+                STAMCOUNTER     TotalTimesWritten;
+                uint32_t        cbBackendWritableBefore;
+                uint32_t        cbBackendWritableAfter;
+            } Stats;
+            /** Hack alert: Max writable amount reported by the backend.
+             * This is used to aid buffer underrun detection in DrvAudio while playing.
+             * Ideally, the backend should have a method for querying number of buffered
+             * bytes instead.  However this will do for now. */
+            uint32_t            cbBackendMaxWritable;
+        } Out;
+    } RT_UNION_NM(u);
+} DRVAUDIOSTREAM;
+/** Pointer to an extended stream structure. */
+typedef DRVAUDIOSTREAM *PDRVAUDIOSTREAM;
+
+/** Value for DRVAUDIOSTREAM::uMagic (Johann Sebastian Bach). */
+#define DRVAUDIOSTREAM_MAGIC        UINT32_C(0x16850331)
+/** Value for DRVAUDIOSTREAM::uMagic after destruction */
+#define DRVAUDIOSTREAM_MAGIC_DEAD   UINT32_C(0x17500728)
+
 
 #ifdef VBOX_WITH_STATISTICS
@@ -152,5 +282,5 @@
     /** Pointer to audio driver below us. */
     PPDMIHOSTAUDIO          pHostDrvAudio;
-    /** List of audio streams. */
+    /** List of audio streams (DRVAUDIOSTREAM). */
     RTLISTANCHOR            lstStreams;
     /** Audio configuration settings retrieved from the backend. */
@@ -202,15 +332,13 @@
 #endif
 
-static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream);
-static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
-static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
-static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
-static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
-static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream);
-static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
-static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
-static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
-static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
-static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
+static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd);
+static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd);
+static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
+static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
+static void drvAudioStreamFree(PDRVAUDIOSTREAM pStream);
+static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
+static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
+static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
+static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
 
 
@@ -456,4 +584,8 @@
     if (!pStream)
         return VINF_SUCCESS;
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
 
     int rc = RTCritSectEnter(&pThis->CritSect);
@@ -462,5 +594,5 @@
     LogFlowFunc(("[%s] enmStreamCmd=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd)));
 
-    rc = drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);
+    rc = drvAudioStreamControlInternal(pThis, pStreamEx, enmStreamCmd);
 
     RTCritSectLeave(&pThis->CritSect);
@@ -472,18 +604,18 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to control.
- * @param   enmStreamCmd        Control command.
- */
-static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
-{
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+ * @param   pThis           Pointer to driver instance.
+ * @param   pStreamEx       Stream to control.
+ * @param   enmStreamCmd    Control command.
+ */
+static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd)
+{
+    AssertPtr(pThis);
+    AssertPtr(pStreamEx);
 
 #ifdef LOG_ENABLED
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    LogFunc(("[%s] enmStreamCmd=%s fStatus=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd),
-             dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
+    LogFunc(("[%s] enmStreamCmd=%s fStatus=%s\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd),
+             dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
 
     int rc = VINF_SUCCESS;
@@ -493,15 +625,15 @@
         case PDMAUDIOSTREAMCMD_ENABLE:
         {
-            if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED))
+            if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED))
             {
                 /* Is a pending disable outstanding? Then disable first. */
-                if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
-                    rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+                if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
+                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
 
                 if (RT_SUCCESS(rc))
-                    rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_ENABLE);
+                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE);
 
                 if (RT_SUCCESS(rc))
-                    pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
+                    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
             }
             break;
@@ -510,5 +642,5 @@
         case PDMAUDIOSTREAMCMD_DISABLE:
         {
-            if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
+            if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
             {
                 /*
@@ -517,16 +649,16 @@
                  * closing the stream.
                  */
-                if (pStream->enmDir == PDMAUDIODIR_OUT)
+                if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
                 {
-                    LogFunc(("[%s] Pending disable/pause\n", pStream->szName));
-                    pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE;
+                    LogFunc(("[%s] Pending disable/pause\n", pStreamEx->Core.szName));
+                    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE;
                 }
 
                 /* Can we close the host stream as well (not in pending disable mode)? */
-                if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
+                if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
                 {
-                    rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
                     if (RT_SUCCESS(rc))
-                        drvAudioStreamResetInternal(pThis, pStream);
+                        drvAudioStreamResetInternal(pThis, pStreamEx);
                 }
             }
@@ -536,9 +668,9 @@
         case PDMAUDIOSTREAMCMD_PAUSE:
         {
-            if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
+            if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
             {
-                rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_PAUSE);
+                rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_PAUSE);
                 if (RT_SUCCESS(rc))
-                    pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
+                    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
             }
             break;
@@ -547,9 +679,9 @@
         case PDMAUDIOSTREAMCMD_RESUME:
         {
-            if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
+            if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
             {
-                rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_RESUME);
+                rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_RESUME);
                 if (RT_SUCCESS(rc))
-                    pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
+                    pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PAUSED;
             }
             break;
@@ -558,7 +690,7 @@
         case PDMAUDIOSTREAMCMD_DROP:
         {
-            rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DROP);
+            rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DROP);
             if (RT_SUCCESS(rc))
-                drvAudioStreamDropInternal(pThis, pStream);
+                drvAudioStreamDropInternal(pThis, pStreamEx);
             break;
         }
@@ -570,5 +702,5 @@
 
     if (RT_FAILURE(rc))
-        LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));
+        LogFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
 
     return rc;
@@ -577,21 +709,23 @@
 /**
  * Controls a stream's backend.
- * If the stream has no backend available, VERR_NOT_FOUND is returned.
+ *
+ * If the stream has no backend available, VERR_NOT_FOUND is returned
+ * (bird: actually the code returns VINF_SUCCESS).
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to control.
- * @param   enmStreamCmd        Control command.
- */
-static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
-{
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+ * @param   pThis           Pointer to driver instance.
+ * @param   pStreamEx       Stream to control.
+ * @param   enmStreamCmd    Control command.
+ */
+static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd)
+{
+    AssertPtr(pThis);
+    AssertPtr(pStreamEx);
 
 #ifdef LOG_ENABLED
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd),
-                 dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
+    LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd),
+                 dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
 
     if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */
@@ -613,11 +747,11 @@
      * See @bugref{9882}.
      */
-    const bool fEnabled =    (   pStream->enmDir == PDMAUDIODIR_IN
+    const bool fEnabled =    (   pStreamEx->Core.enmDir == PDMAUDIODIR_IN
                               && pThis->In.fEnabled)
-                          || (   pStream->enmDir == PDMAUDIODIR_OUT
+                          || (   pStreamEx->Core.enmDir == PDMAUDIODIR_OUT
                               && pThis->Out.fEnabled);
 
-    LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStream->szName,
-                                                              PDMAudioDirGetName(pStream->enmDir),
+    LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStreamEx->Core.szName,
+                                                              PDMAudioDirGetName(pStreamEx->Core.enmDir),
                                                               fEnabled ? "enabled" : "disabled"));
     switch (enmStreamCmd)
@@ -626,5 +760,5 @@
         {
             if (fEnabled)
-                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_ENABLE);
+                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_ENABLE);
             break;
         }
@@ -632,5 +766,5 @@
         case PDMAUDIOSTREAMCMD_DISABLE:
         {
-            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DISABLE);
+            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DISABLE);
             break;
         }
@@ -639,5 +773,5 @@
         {
             if (fEnabled) /* Needed, as resume below also is being checked for. */
-                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_PAUSE);
+                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_PAUSE);
             break;
         }
@@ -646,5 +780,5 @@
         {
             if (fEnabled)
-                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_RESUME);
+                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_RESUME);
             break;
         }
@@ -652,5 +786,5 @@
         case PDMAUDIOSTREAMCMD_DRAIN:
         {
-            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);
+            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);
             break;
         }
@@ -658,14 +792,10 @@
         case PDMAUDIOSTREAMCMD_DROP:
         {
-            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DROP);
+            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DROP);
             break;
         }
 
         default:
-        {
-            AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd));
-            rc = VERR_NOT_IMPLEMENTED;
-            break;
-        }
+            AssertMsgFailedReturn(("Command %RU32 not implemented\n", enmStreamCmd), VERR_INTERNAL_ERROR_2);
     }
 
@@ -676,8 +806,8 @@
             && rc != VERR_AUDIO_STREAM_NOT_READY)
         {
-            LogRel(("Audio: %s stream '%s' failed with %Rrc\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStream->szName, rc));
-        }
-
-        LogFunc(("[%s] %s failed with %Rrc\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd), rc));
+            LogRel(("Audio: %s stream '%s' failed with %Rrc\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStreamEx->Core.szName, rc));
+        }
+
+        LogFunc(("[%s] %s failed with %Rrc\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd), rc));
     }
 
@@ -688,18 +818,20 @@
  * Frees an audio stream and its allocated resources.
  *
- * @param   pStream             Audio stream to free.
- *                              After this call the pointer will not be valid anymore.
- */
-static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream)
-{
-    if (pStream)
-    {
-        LogFunc(("[%s]\n", pStream->szName));
-        Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC);
-
-        pStream->uMagic    = ~PDMAUDIOSTREAM_MAGIC;
-        pStream->pvBackend = NULL;
-
-        RTMemFree(pStream);
+ * @param   pStreamEx   Audio stream to free. After this call the pointer will
+ *                      not be valid anymore.
+ */
+static void drvAudioStreamFree(PDRVAUDIOSTREAM pStreamEx)
+{
+    if (pStreamEx)
+    {
+        LogFunc(("[%s]\n", pStreamEx->Core.szName));
+        Assert(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC);
+        Assert(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC);
+
+        pStreamEx->Core.uMagic    = ~PDMAUDIOSTREAM_MAGIC;
+        pStreamEx->pvBackend = NULL;
+        pStreamEx->uMagic         = DRVAUDIOSTREAM_MAGIC_DEAD;
+
+        RTMemFree(pStreamEx);
     }
 }
@@ -720,10 +852,10 @@
 
     /* Mark all host streams to re-initialize. */
-    PPDMAUDIOSTREAM pStream;
-    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
-    {
-        pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
-        pStream->cTriesReInit   = 0;
-        pStream->tsLastReInitNs = 0;
+    PDRVAUDIOSTREAM pStreamEx;
+    RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
+    {
+        pStreamEx->Core.fStatus        |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
+        pStreamEx->cTriesReInit    = 0;
+        pStreamEx->nsLastReInit         = 0;
     }
 
@@ -747,35 +879,35 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to re-initialize.
- */
-static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
-{
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-
-    LogFlowFunc(("[%s]\n", pStream->szName));
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Stream to re-initialize.
+ */
+static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
+{
+    AssertPtr(pThis);
+    AssertPtr(pStreamEx);
+
+    LogFlowFunc(("[%s]\n", pStreamEx->Core.szName));
 
     /*
      * Gather current stream status.
      */
-    const bool fIsEnabled = RT_BOOL(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */
+    const bool fIsEnabled = RT_BOOL(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */
 
     /*
      * Destroy and re-create stream on backend side.
      */
-    int rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+    int rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
     if (RT_SUCCESS(rc))
     {
-        rc = drvAudioStreamDestroyInternalBackend(pThis, pStream);
+        rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
         if (RT_SUCCESS(rc))
         {
             PDMAUDIOSTREAMCFG CfgHostAcq;
-            rc = drvAudioStreamCreateInternalBackend(pThis, pStream, &pStream->Host.Cfg, &CfgHostAcq);
-            /** @todo Validate (re-)acquired configuration with pStream->Host.Cfg? */
+            rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, &pStreamEx->Host.Cfg, &CfgHostAcq);
+            /** @todo Validate (re-)acquired configuration with pStreamEx->Core.Host.Cfg? */
             if (RT_SUCCESS(rc))
             {
 #ifdef LOG_ENABLED
-                LogFunc(("[%s] Acquired host format:\n",  pStream->szName));
+                LogFunc(("[%s] Acquired host format:\n",  pStreamEx->Core.szName));
                 PDMAudioStrmCfgLog(&CfgHostAcq);
 #endif
@@ -785,5 +917,5 @@
 
     /* Drop all old data. */
-    drvAudioStreamDropInternal(pThis, pStream);
+    drvAudioStreamDropInternal(pThis, pStreamEx);
 
     /*
@@ -791,10 +923,10 @@
      */
     if (fIsEnabled)
-        rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_ENABLE);
+        rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE);
 
     if (RT_FAILURE(rc))
-        LogRel(("Audio: Re-initializing stream '%s' failed with %Rrc\n", pStream->szName, rc));
-
-    LogFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
+        LogRel(("Audio: Re-initializing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
+
+    LogFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
     return rc;
 }
@@ -803,37 +935,36 @@
  * Drops all audio data (and associated state) of a stream.
  *
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to drop data for.
- */
-static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Stream to drop data for.
+ */
+static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
 {
     RT_NOREF(pThis);
 
-    LogFunc(("[%s]\n", pStream->szName));
-
-    AudioMixBufReset(&pStream->Guest.MixBuf);
-    AudioMixBufReset(&pStream->Host.MixBuf);
-
-    pStream->tsLastIteratedNs       = 0;
-    pStream->tsLastPlayedCapturedNs = 0;
-    pStream->tsLastReadWrittenNs    = 0;
-
-    pStream->fThresholdReached = false;
-}
-
-/**
- * Resets a given audio stream.
- *
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to reset.
- */
-static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
-{
-    drvAudioStreamDropInternal(pThis, pStream);
-
-    LogFunc(("[%s]\n", pStream->szName));
-
-    pStream->fStatus        = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
-    pStream->fWarningsShown = PDMAUDIOSTREAM_WARN_FLAGS_NONE;
+    LogFunc(("[%s]\n", pStreamEx->Core.szName));
+
+    AudioMixBufReset(&pStreamEx->Guest.MixBuf);
+    AudioMixBufReset(&pStreamEx->Host.MixBuf);
+
+    pStreamEx->fThresholdReached    = false;
+    pStreamEx->nsLastIterated       = 0;
+    pStreamEx->nsLastPlayedCaptured = 0;
+    pStreamEx->nsLastReadWritten    = 0;
+}
+
+/**
+ * Resets the given audio stream.
+ *
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Stream to reset.
+ */
+static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
+{
+    drvAudioStreamDropInternal(pThis, pStreamEx);
+
+    LogFunc(("[%s]\n", pStreamEx->Core.szName));
+
+    pStreamEx->Core.fStatus        = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
+    pStreamEx->Core.fWarningsShown = PDMAUDIOSTREAM_WARN_FLAGS_NONE;
 
 #ifdef VBOX_WITH_STATISTICS
@@ -841,17 +972,17 @@
      * Reset statistics.
      */
-    if (pStream->enmDir == PDMAUDIODIR_IN)
-    {
-        STAM_COUNTER_RESET(&pStream->In.Stats.TotalFramesCaptured);
-        STAM_COUNTER_RESET(&pStream->In.Stats.TotalFramesRead);
-        STAM_COUNTER_RESET(&pStream->In.Stats.TotalTimesCaptured);
-        STAM_COUNTER_RESET(&pStream->In.Stats.TotalTimesRead);
-    }
-    else if (pStream->enmDir == PDMAUDIODIR_OUT)
-    {
-        STAM_COUNTER_RESET(&pStream->Out.Stats.TotalFramesPlayed);
-        STAM_COUNTER_RESET(&pStream->Out.Stats.TotalFramesWritten);
-        STAM_COUNTER_RESET(&pStream->Out.Stats.TotalTimesPlayed);
-        STAM_COUNTER_RESET(&pStream->Out.Stats.TotalTimesWritten);
+    if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
+    {
+        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalFramesCaptured);
+        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalFramesRead);
+        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalTimesCaptured);
+        STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalTimesRead);
+    }
+    else if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
+    {
+        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalFramesPlayed);
+        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalFramesWritten);
+        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalTimesPlayed);
+        STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalTimesWritten);
     }
     else
@@ -868,147 +999,138 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
+
+    /*
+     * Check input and sanity.
+     */
     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
-    AssertReturn(cbBuf,         VERR_INVALID_PARAMETER);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
+    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     AssertPtrNullReturn(pcbWritten, VERR_INVALID_PARAMETER);
 
-    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT,
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
               ("Stream '%s' is not an output stream and therefore cannot be written to (direction is '%s')\n",
-               pStream->szName, PDMAudioDirGetName(pStream->enmDir)));
-
-    AssertMsg(PDMAudioPropsIsSizeAligned(&pStream->Guest.Cfg.Props, cbBuf),
-              ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStream->szName, cbBuf));
-
-    uint32_t cbWrittenTotal = 0;
+               pStreamEx->Core.szName, PDMAudioDirGetName(pStreamEx->Core.enmDir)));
+
+    AssertMsg(PDMAudioPropsIsSizeAligned(&pStreamEx->Guest.Cfg.Props, cbBuf),
+              ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStreamEx->Core.szName, cbBuf));
+
+    STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out); /* (stopped in drvAudioStreamPlayLocked) */
 
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, rc);
 
-#ifdef VBOX_WITH_STATISTICS
-    STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out);
-#endif
-
-    /* Whether to discard the incoming data or not. */
-    bool fToBitBucket = false;
-
-    do
-    {
-        if (!PDMAudioStrmStatusIsReady(pStream->fStatus))
-        {
-            rc = VERR_AUDIO_STREAM_NOT_READY;
-            break;
-        }
-
-        /* If output is disabled on a per-driver level, send data to the bit bucket instead. See @bugref{9882}. */
-        if (!pThis->Out.fEnabled)
-        {
-            fToBitBucket = true;
-            break;
-        }
-
-        if (pThis->pHostDrvAudio)
-        {
-            /* If the backend's stream is not writable, all written data goes to /dev/null. */
-            if (!PDMAudioStrmStatusCanWrite(
-                pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend)))
+    /*
+     * First check that we can write to the stream, and if not,
+     * whether to just drop the input into the bit bucket.
+     */
+    if (PDMAudioStrmStatusIsReady(pStreamEx->Core.fStatus))
+    {
+        if (   !pThis->Out.fEnabled         /* (see @bugref{9882}) */
+            || pThis->pHostDrvAudio == NULL /* (we used to work this condition differently) */
+            || !PDMAudioStrmStatusCanWrite(pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStreamEx->pvBackend)))
+        {
+            Log3Func(("[%s] Backend stream %s, discarding the data\n", pStreamEx->Core.szName,
+                      !pThis->Out.fEnabled ? "disabled" : !pThis->pHostDrvAudio ? "not attached" : "not ready yet"));
+            *pcbWritten = cbBuf;
+        }
+        /*
+         * No-mixing buffer mode:  Write the data directly to the backend, unless
+         * we're prebuffering.  There will be no pfnStreamPlay call in this mode.
+         */
+        else if (pStreamEx->fNoMixBufs)
+        {
+            rc = VERR_NOT_IMPLEMENTED;
+        }
+        /*
+         * Legacy mode:  Here we just dump the data in the guest side mixing buffer
+         * and then mixes it into the host side buffer.  Later the device code will
+         * make a pfnStreamPlay call which  recodes the data from the host side
+         * buffer and writes it to the host backend.
+         */
+        else
+        {
+            uint32_t cbWrittenTotal = 0;
+
+            const uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf);
+            if (cbFree < cbBuf)
+                LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n",
+                         PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStreamEx->Core.szName));
+
+            uint32_t cbToWrite = RT_MIN(cbBuf, cbFree);
+            if (cbToWrite)
             {
-                fToBitBucket = true;
-                break;
-            }
-        }
-
-        const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf);
-        if (cbFree < cbBuf)
-            LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n",
-                     PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStream->szName));
-
-        uint32_t cbToWrite = RT_MIN(cbBuf, cbFree);
-        if (!cbToWrite)
-        {
-            rc = VERR_BUFFER_OVERFLOW;
-            break;
-        }
-
-        /* We use the guest side mixing buffer as an intermediate buffer to do some
-         * (first) processing (if needed), so always write the incoming data at offset 0. */
-        uint32_t cfGstWritten = 0;
-        rc = AudioMixBufWriteAt(&pStream->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten);
-        if (   RT_FAILURE(rc)
-            || !cfGstWritten)
-        {
-            AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cfWritten=%RU32, rc=%Rrc\n",
-                             pStream->szName, cbToWrite, cfGstWritten, rc));
-            break;
-        }
-
-        if (pThis->Out.Cfg.Dbg.fEnabled)
-            AudioHlpFileWrite(pStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
-
-        uint32_t cfGstMixed = 0;
-        if (cfGstWritten)
-        {
-            int rc2 = AudioMixBufMixToParentEx(&pStream->Guest.MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */,
-                                               &cfGstMixed /* pcSrcMixed */);
-            if (RT_FAILURE(rc2))
-            {
-                AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
-                                 pStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2));
+                /* We use the guest side mixing buffer as an intermediate buffer to do some
+                 * (first) processing (if needed), so always write the incoming data at offset 0. */
+                uint32_t cFramesGstWritten = 0;
+                rc = AudioMixBufWriteAt(&pStreamEx->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cFramesGstWritten);
+                if (RT_SUCCESS(rc) && cFramesGstWritten > 0)
+                {
+                    if (pThis->Out.Cfg.Dbg.fEnabled)
+                        AudioHlpFileWrite(pStreamEx->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
+
+                    uint32_t cFramesGstMixed = 0;
+                    if (cFramesGstWritten)
+                    {
+                        int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Guest.MixBuf, 0 /* cSrcOffset */,
+                                                           cFramesGstWritten /* cSrcFrames */, &cFramesGstMixed /* pcSrcMixed */);
+                        if (RT_SUCCESS(rc2))
+                        {
+                            const uint64_t tsNowNs = RTTimeNanoTS();
+
+                            Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n",
+                                      pStreamEx->Core.szName, cFramesGstWritten, PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cFramesGstWritten)));
+
+                            Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n",
+                                      pStreamEx->Core.szName, tsNowNs - pStreamEx->nsLastReadWritten,
+                                      (tsNowNs - pStreamEx->nsLastReadWritten) / RT_NS_1MS,
+                                      PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)),
+                                      AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf)));
+
+                            pStreamEx->nsLastReadWritten = tsNowNs;
+                            /* Keep going. */
+                        }
+                        else
+                        {
+                            AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
+                                             pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, cFramesGstMixed, rc2));
+                            if (RT_SUCCESS(rc))
+                                rc = rc2;
+                        }
+
+                        cbWrittenTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cFramesGstWritten);
+
+                        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten,  cFramesGstWritten);
+                        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cFramesGstMixed);
+                        Assert(cFramesGstWritten >= cFramesGstMixed);
+                        STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut,  cFramesGstWritten - cFramesGstMixed);
+                        STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten,   cbWrittenTotal);
+
+                        STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesWritten, cFramesGstWritten);
+                        STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesWritten);
+                    }
+
+                    Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cFramesGstWritten=%RU32, "
+                              "cFramesGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n",
+                              pStreamEx->Core.szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStreamEx->Host.MixBuf),
+                              AudioMixBufLive(&pStreamEx->Host.MixBuf), cFramesGstWritten, cFramesGstMixed, cbWrittenTotal, rc));
+                }
+                else
+                    AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cFramesGstWritten=%RU32, rc=%Rrc\n",
+                                     pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, rc));
             }
             else
-            {
-                const uint64_t tsNowNs = RTTimeNanoTS();
-
-                Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n",
-                          pStream->szName, cfGstWritten, PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfGstWritten)));
-
-                Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n",
-                          pStream->szName, tsNowNs - pStream->tsLastReadWrittenNs,
-                          (tsNowNs - pStream->tsLastReadWrittenNs) / RT_NS_1MS,
-                          PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)),
-                          AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf)));
-
-                pStream->tsLastReadWrittenNs = tsNowNs;
-                /* Keep going. */
-            }
-
-            if (RT_SUCCESS(rc))
-                rc = rc2;
-
-            cbWrittenTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfGstWritten);
-
-#ifdef VBOX_WITH_STATISTICS
-            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten,  cfGstWritten);
-            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cfGstMixed);
-            Assert(cfGstWritten >= cfGstMixed);
-            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut,  cfGstWritten - cfGstMixed);
-            STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten,   cbWrittenTotal);
-
-            STAM_COUNTER_ADD(&pStream->Out.Stats.TotalFramesWritten, cfGstWritten);
-            STAM_COUNTER_INC(&pStream->Out.Stats.TotalTimesWritten);
-#endif
-        }
-
-        Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cfGstWritten=%RU32, "
-                  "cfGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n",
-                  pStream->szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStream->Host.MixBuf),
-                  AudioMixBufLive(&pStream->Host.MixBuf), cfGstWritten, cfGstMixed, cbWrittenTotal, rc));
-
-    } while (0);
+                rc = VERR_BUFFER_OVERFLOW;
+            if (pcbWritten)
+                *pcbWritten = cbWrittenTotal;
+        }
+    }
+    else
+        rc = VERR_AUDIO_STREAM_NOT_READY;
 
     RTCritSectLeave(&pThis->CritSect);
-
-    if (RT_SUCCESS(rc))
-    {
-        if (fToBitBucket)
-        {
-            Log3Func(("[%s] Backend stream not ready (yet), discarding written data\n", pStream->szName));
-            cbWrittenTotal = cbBuf; /* Report all data as being written to the caller. */
-        }
-
-        if (pcbWritten)
-            *pcbWritten = cbWrittenTotal;
-    }
-
     return rc;
 }
@@ -1021,8 +1143,13 @@
    AssertPtrReturn(pInterface, UINT32_MAX);
    AssertPtrReturn(pStream,    UINT32_MAX);
-
-   NOREF(pInterface);
-
-   return ++pStream->cRefs;
+   AssertReturn(pStream->uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX);
+   AssertReturn(((PDRVAUDIOSTREAM)pStream)->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX);
+   RT_NOREF(pInterface);
+
+   uint32_t const cRefs = ASMAtomicIncU32(&pStream->cRefs);
+   Assert(cRefs > 1);
+   Assert(cRefs < _1K);
+
+   return cRefs;
 }
 
@@ -1034,11 +1161,13 @@
    AssertPtrReturn(pInterface, UINT32_MAX);
    AssertPtrReturn(pStream,    UINT32_MAX);
-
-   NOREF(pInterface);
-
-   if (pStream->cRefs > 1) /* 1 reference always is kept by this audio driver. */
-       pStream->cRefs--;
-
-   return pStream->cRefs;
+   AssertReturn(pStream->uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX);
+   AssertReturn(((PDRVAUDIOSTREAM)pStream)->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX);
+   RT_NOREF(pInterface);
+
+   uint32_t cRefs = ASMAtomicDecU32(&pStream->cRefs);
+   AssertStmt(cRefs >= 1, cRefs = ASMAtomicIncU32(&pStream->cRefs));
+   Assert(cRefs < _1K);
+
+   return cRefs;
 }
 
@@ -1050,10 +1179,13 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
-    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
 
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, rc);
 
-    rc = drvAudioStreamIterateInternal(pThis, pStream);
+    rc = drvAudioStreamIterateInternal(pThis, pStreamEx);
 
     RTCritSectLeave(&pThis->CritSect);
@@ -1070,10 +1202,10 @@
  *       needed for the host device (re-)enumeration.
  *
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to check and maybe re-initialize.
- */
-static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
-{
-    if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT)
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Stream to check and maybe re-initialize.
+ */
+static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
+{
+    if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT)
     {
         const unsigned cMaxTries = 3; /** @todo Make this configurable? */
@@ -1081,6 +1213,6 @@
 
         /* Throttle re-initializing streams on failure. */
-        if (   pStream->cTriesReInit < cMaxTries
-            && tsNowNs - pStream->tsLastReInitNs >= RT_NS_1SEC * pStream->cTriesReInit) /** @todo Ditto. */
+        if (   pStreamEx->cTriesReInit < cMaxTries
+            && tsNowNs - pStreamEx->nsLastReInit >= RT_NS_1SEC * pStreamEx->cTriesReInit) /** @todo Ditto. */
         {
 #ifdef VBOX_WITH_AUDIO_ENUM
@@ -1102,14 +1234,14 @@
 #endif /* VBOX_WITH_AUDIO_ENUM */
 
-            int rc = drvAudioStreamReInitInternal(pThis, pStream);
+            int rc = drvAudioStreamReInitInternal(pThis, pStreamEx);
             if (RT_FAILURE(rc))
             {
-                pStream->cTriesReInit++;
-                pStream->tsLastReInitNs = tsNowNs;
+                pStreamEx->cTriesReInit++;
+                pStreamEx->nsLastReInit = tsNowNs;
             }
             else
             {
                 /* Remove the pending re-init flag on success. */
-                pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
+                pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;
             }
         }
@@ -1118,11 +1250,11 @@
             /* Did we exceed our tries re-initializing the stream?
              * Then this one is dead-in-the-water, so disable it for further use. */
-            if (pStream->cTriesReInit == cMaxTries)
+            if (pStreamEx->cTriesReInit == cMaxTries)
             {
                 LogRel(("Audio: Re-initializing stream '%s' exceeded maximum retries (%u), leaving as disabled\n",
-                        pStream->szName, cMaxTries));
+                        pStreamEx->Core.szName, cMaxTries));
 
                 /* Don't try to re-initialize anymore and mark as disabled. */
-                pStream->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);
+                pStreamEx->Core.fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);
 
                 /* Note: Further writes to this stream go to / will be read from the bit bucket (/dev/null) from now on. */
@@ -1133,5 +1265,5 @@
         char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-        Log3Func(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
+        Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
     }
 }
@@ -1143,8 +1275,8 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to iterate.
- */
-static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Stream to iterate.
+ */
+static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
 {
     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
@@ -1153,18 +1285,15 @@
         return VINF_SUCCESS;
 
-    if (!pStream)
-        return VINF_SUCCESS;
-
     /* Is the stream scheduled for re-initialization? Do so now. */
-    drvAudioStreamMaybeReInit(pThis, pStream);
+    drvAudioStreamMaybeReInit(pThis, pStreamEx);
 
 #ifdef LOG_ENABLED
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    Log3Func(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
+    Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
 
     /* Not enabled or paused? Skip iteration. */
-    if (   !(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
-        ||  (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
+    if (   !(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)
+        ||  (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))
     {
         return VINF_SUCCESS;
@@ -1178,34 +1307,33 @@
     do
     {
-        rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStream->pvBackend);
+        rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStreamEx->pvBackend);
         if (RT_FAILURE(rc))
             break;
 
-        if (pStream->enmDir == PDMAUDIODIR_OUT)
+        if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
         {
             /* No audio frames to transfer from guest to host (anymore)?
              * Then try closing this stream if marked so in the next block. */
-            const uint32_t cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf);
+            const uint32_t cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
             fTryClosePending = cFramesLive == 0;
-            Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStream->szName, fTryClosePending, cFramesLive));
+            Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStreamEx->Core.szName, fTryClosePending, cFramesLive));
         }
 
         /* Has the host stream marked as pending to disable?
          * Try disabling the stream then. */
-        if (   pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE
+        if (   pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE
             && fTryClosePending)
         {
             /* Tell the backend to drain the stream, that is, play the remaining (buffered) data
              * on the backend side. */
-            rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DRAIN);
+            rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DRAIN);
             if (rc == VERR_NOT_SUPPORTED) /* Not all backends support draining. */
                 rc = VINF_SUCCESS;
-
             if (RT_SUCCESS(rc))
             {
                 if (pThis->pHostDrvAudio->pfnStreamGetPending) /* Optional to implement. */
                 {
-                    const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStream->pvBackend);
-                    Log3Func(("[%s] cxPending=%RU32\n", pStream->szName, cxPending));
+                    const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+                    Log3Func(("[%s] cxPending=%RU32\n", pStreamEx->Core.szName, cxPending));
 
                     /* Only try close pending if no audio data is pending on the backend-side anymore. */
@@ -1215,13 +1343,13 @@
                 if (fTryClosePending)
                 {
-                    LogFunc(("[%s] Closing pending stream\n", pStream->szName));
-                    rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+                    LogFunc(("[%s] Closing pending stream\n", pStreamEx->Core.szName));
+                    rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
                     if (RT_SUCCESS(rc))
                     {
-                        pStream->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE);
-                        drvAudioStreamDropInternal(pThis, pStream);
+                        pStreamEx->Core.fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE);
+                        drvAudioStreamDropInternal(pThis, pStreamEx);
                     }
                     else
-                       LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStream->szName, rc));
+                       LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStreamEx->Core.szName, rc));
                 }
             }
@@ -1231,8 +1359,8 @@
 
     /* Update timestamps. */
-    pStream->tsLastIteratedNs = RTTimeNanoTS();
+    pStreamEx->nsLastIterated = RTTimeNanoTS();
 
     if (RT_FAILURE(rc))
-        LogFunc(("[%s] Failed with %Rrc\n",  pStream->szName, rc));
+        LogFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
 
     return rc;
@@ -1244,12 +1372,12 @@
  * @returns VBox status code.
  * @param   pThis           The audio driver instance data.
- * @param   pStream         The stream to play.
+ * @param   pStreamEx       The stream to play.
  * @param   cFramesToPlay   Number of audio frames to play.  The backend is
  *                          supposed to have buffer space for this.
  * @param   pcFramesPlayed  Where to return the number of audio frames played.
  */
-static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
-{
-    Assert(pStream->enmDir == PDMAUDIODIR_OUT);
+static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)
+{
+    Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT);
 
     /*
@@ -1265,10 +1393,10 @@
         uint8_t  abChunk[_4K];
         uint32_t cFramesRead = 0;
-        rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf, abChunk,
-                                         RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesLeft)),
+        rc = AudioMixBufAcquireReadBlock(&pStreamEx->Host.MixBuf, abChunk,
+                                         RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesLeft)),
                                          &cFramesRead);
         AssertRCBreak(rc);
 
-        uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cFramesRead);
+        uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesRead);
         Assert(cbRead <= sizeof(abChunk));
 
@@ -1278,20 +1406,20 @@
         uint32_t cFramesPlayed = 0;
         uint32_t cbPlayed      = 0;
-        rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, abChunk, cbRead, &cbPlayed);
+        rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStreamEx->pvBackend, abChunk, cbRead, &cbPlayed);
         if (RT_SUCCESS(rc))
         {
             if (pThis->Out.Cfg.Dbg.fEnabled)
-                AudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
+                AudioHlpFileWrite(pStreamEx->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);
 
             if (cbRead != cbPlayed)
                 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n",
-                         pStream->szName, cbRead, cbPlayed));
-
-            cFramesPlayed  = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed);
+                         pStreamEx->Core.szName, cbRead, cbPlayed));
+
+            cFramesPlayed  = AUDIOMIXBUF_B2F(&pStreamEx->Host.MixBuf, cbPlayed);
             AssertStmt(cFramesLeft >= cFramesPlayed, cFramesPlayed = cFramesLeft);
             cFramesLeft   -= cFramesPlayed;
         }
 
-        AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cFramesPlayed);
+        AudioMixBufReleaseReadBlock(&pStreamEx->Host.MixBuf, cFramesPlayed);
 
         AssertRCBreak(rc); /* (this is here for Acquire/Release symmetry - which isn't at all necessary) */
@@ -1299,5 +1427,5 @@
     }
 
-    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
+    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStreamEx->Core.szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));
     *pcFramesPlayed = cFramesToPlay - cFramesLeft;
     return rc;
@@ -1307,5 +1435,5 @@
  * Worker for drvAudioStreamPlay.
  */
-static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed)
+static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcFramesPlayed)
 {
     /*
@@ -1314,9 +1442,9 @@
     *pcFramesPlayed = 0;
 
-    PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus;
+    PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus;
 #ifdef LOG_ENABLED
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    Log3Func(("[%s] Start fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
+    Log3Func(("[%s] Start fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
 
     /*
@@ -1337,15 +1465,15 @@
      * Get number of frames in the mix buffer and do some logging.
      */
-    uint32_t const cFramesLive = AudioMixBufLive(&pStream->Host.MixBuf);
+    uint32_t const cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf);
     Log3Func(("[%s] Last played %'RI64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n",
-              pStream->szName, pStream->fThresholdReached ? RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs : -1, cFramesLive,
-              PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive),
-              (100 * cFramesLive) / AudioMixBufSize(&pStream->Host.MixBuf), pStream->fThresholdReached ? "" : ", pre-buffering"));
+              pStreamEx->Core.szName, pStreamEx->fThresholdReached ? RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured : -1, cFramesLive,
+              PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive),
+              (100 * cFramesLive) / AudioMixBufSize(&pStreamEx->Host.MixBuf), pStreamEx->fThresholdReached ? "" : ", pre-buffering"));
 
     /*
      * Restart pre-buffering if we're having a buffer-underrun.
      */
-    if (   cFramesLive != 0                     /* no underrun */
-        || !pStream->fThresholdReached          /* or still pre-buffering. */)
+    if (   cFramesLive != 0              /* no underrun */
+        || !pStreamEx->fThresholdReached /* or still pre-buffering. */)
     { /* likely */ }
     else
@@ -1355,20 +1483,20 @@
            some heuristics based on number of writable bytes now compared to when
            prebuffering ended the first time around. */
-        uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
-        if (cbBuffered < pStream->Out.cbBackendMaxWritable)
-            cbBuffered = pStream->Out.cbBackendMaxWritable - cbBuffered;
+        uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+        if (cbBuffered < pStreamEx->Out.cbBackendMaxWritable)
+            cbBuffered = pStreamEx->Out.cbBackendMaxWritable - cbBuffered;
         else
             cbBuffered = 0;
-        uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStream->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint * 2);
+        uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStreamEx->Host.Cfg.Props, pStreamEx->Guest.Cfg.Device.cMsSchedulingHint * 2);
         Log3Func(("Potential underrun: cbBuffered=%#x vs cbMinBuf=%#x\n", cbBuffered, cbMinBuf));
         if (cbBuffered < cbMinBuf)
         {
             LogRel2(("Audio: Buffer underrun for stream '%s' (%RI64 ms since last call, %u buffered)\n",
-                     pStream->szName, RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs, cbBuffered));
+                     pStreamEx->Core.szName, RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured, cbBuffered));
 
             /* Re-enter the pre-buffering stage again if enabled. */
-            if (pStream->Host.Cfg.Backend.cFramesPreBuffering > 0)
+            if (pStreamEx->Host.Cfg.Backend.cFramesPreBuffering > 0)
             {
-                pStream->fThresholdReached = false;
+                pStreamEx->fThresholdReached = false;
                 STAM_REL_COUNTER_INC(&pThis->Out.StatsReBuffering);
             }
@@ -1383,8 +1511,8 @@
     uint32_t cbWritable;
     bool fJustStarted = false;
-    if (pStream->fThresholdReached)
+    if (pStreamEx->fThresholdReached)
     {
         /* not-prebuffering, likely after a while at least */
-        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
+        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     }
     else
@@ -1394,8 +1522,8 @@
          * Can be 0 if no pre-buffering desired.
          */
-        if (cFramesLive >= pStream->Host.Cfg.Backend.cFramesPreBuffering)
-        {
-            LogRel2(("Audio: Stream '%s' buffering complete!\n", pStream->szName));
-            pStream->fThresholdReached = fJustStarted = true;
+        if (cFramesLive >= pStreamEx->Host.Cfg.Backend.cFramesPreBuffering)
+        {
+            LogRel2(("Audio: Stream '%s' buffering complete!\n", pStreamEx->Core.szName));
+            pStreamEx->fThresholdReached = fJustStarted = true;
         }
         /*
@@ -1408,8 +1536,8 @@
          */
         else if (   cFramesLive > 0
-                 && (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
-        {
-            LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStream->szName));
-            pStream->fThresholdReached = fJustStarted = true;
+                 && (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))
+        {
+            LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStreamEx->Core.szName));
+            pStreamEx->fThresholdReached = fJustStarted = true;
         }
         /*
@@ -1419,14 +1547,14 @@
         {
             LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)...\n",
-                     pStream->szName, (100 * cFramesLive) / pStream->Host.Cfg.Backend.cFramesPreBuffering));
+                     pStreamEx->Core.szName, (100 * cFramesLive) / pStreamEx->Host.Cfg.Backend.cFramesPreBuffering));
             return VINF_SUCCESS;
         }
 
         /* Hack alert! This is for the underrun detection.  */
-        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
-        if (cbWritable > pStream->Out.cbBackendMaxWritable)
-            pStream->Out.cbBackendMaxWritable = cbWritable;
-    }
-    pStream->Out.Stats.cbBackendWritableBefore = cbWritable;
+        cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+        if (cbWritable > pStreamEx->Out.cbBackendMaxWritable)
+            pStreamEx->Out.cbBackendMaxWritable = cbWritable;
+    }
+    pStreamEx->Out.Stats.cbBackendWritableBefore = cbWritable;
 
     /*
@@ -1434,5 +1562,5 @@
      * Easy, as much as the host audio backend will allow us to.
      */
-    uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStream->Host.Cfg.Props, cbWritable);
+    uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStreamEx->Host.Cfg.Props, cbWritable);
     uint32_t cFramesToPlay   = cFramesWritable;
     if (cFramesToPlay > cFramesLive) /* Don't try to play more than available, we don't want to block. */
@@ -1440,7 +1568,7 @@
 
     Log3Func(("[%s] Playing %RU32 frames (%RU64 ms), now filled with %RU64 ms -- %RU8%%\n",
-              pStream->szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay),
-              PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)),
-              AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf)));
+              pStreamEx->Core.szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay),
+              PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)),
+              AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf)));
 
     /*
@@ -1451,14 +1579,14 @@
     {
         if (pThis->pHostDrvAudio->pfnStreamPlayBegin)
-            pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend);
-
-        rc = drvAudioStreamPlayDoIt(pThis, pStream, cFramesToPlay, pcFramesPlayed);
+            pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+
+        rc = drvAudioStreamPlayDoIt(pThis, pStreamEx, cFramesToPlay, pcFramesPlayed);
 
         if (pThis->pHostDrvAudio->pfnStreamPlayEnd)
-            pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream->pvBackend);
-
-        pStream->tsLastPlayedCapturedNs = RTTimeNanoTS();
-        pStream->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio,
-                                                                                               pStream->pvBackend);
+            pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+
+        pStreamEx->nsLastPlayedCaptured = RTTimeNanoTS();
+        pStreamEx->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio,
+                                                                                                 pStreamEx->pvBackend);
     }
     else
@@ -1466,11 +1594,11 @@
 
     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",
-              pStream->szName,
-              cFramesLive, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesLive),
-              pStream->Host.Cfg.Backend.cFramesPeriod,
-              PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, pStream->Host.Cfg.Backend.cFramesPeriod),
-              cFramesWritable, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesWritable),
-              cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay),
-              *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, *pcFramesPlayed),
+              pStreamEx->Core.szName,
+              cFramesLive, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive),
+              pStreamEx->Host.Cfg.Backend.cFramesPeriod,
+              PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, pStreamEx->Host.Cfg.Backend.cFramesPeriod),
+              cFramesWritable, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesWritable),
+              cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay),
+              *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, *pcFramesPlayed),
               fJustStarted ? "just-started" : ""));
     RT_NOREF(fJustStarted);
@@ -1478,10 +1606,10 @@
     if (RT_SUCCESS(rc))
     {
-        AudioMixBufFinish(&pStream->Host.MixBuf, *pcFramesPlayed);
+        AudioMixBufFinish(&pStreamEx->Host.MixBuf, *pcFramesPlayed);
 
         STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out);
         STAM_COUNTER_ADD(&pThis->Stats.TotalFramesOut, *pcFramesPlayed);
-        STAM_COUNTER_ADD(&pStream->Out.Stats.TotalFramesPlayed, *pcFramesPlayed);
-        STAM_COUNTER_INC(&pStream->Out.Stats.TotalTimesPlayed);
+        STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesPlayed, *pcFramesPlayed);
+        STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesPlayed);
     }
     return rc;
@@ -1496,9 +1624,13 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER);
-    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT,
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT,
               ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n",
-               pStream->szName, pStream->enmDir));
+               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
+    AssertReturn(!pStreamEx->fNoMixBufs, VERR_INVALID_FUNCTION);
 
     int rc = RTCritSectEnter(&pThis->CritSect);
@@ -1506,5 +1638,5 @@
 
     uint32_t cFramesPlayed = 0;
-    rc = drvAudioStreamPlayLocked(pThis, pStream, &cFramesPlayed);
+    rc = drvAudioStreamPlayLocked(pThis, pStreamEx, &cFramesPlayed);
 
     RTCritSectLeave(&pThis->CritSect);
@@ -1514,5 +1646,5 @@
 
     if (RT_FAILURE(rc))
-        LogFlowFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));
+        LogFlowFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc));
     return rc;
 }
@@ -1522,15 +1654,12 @@
  *
  * @returns VBox status code.
- * @param   pThis               Driver instance.
- * @param   pStream             Stream to capture from.
- * @param   pcfCaptured         Number of (host) audio frames captured. Optional.
- */
-static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
-{
-    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER);
-    Assert(pStream->enmDir == PDMAUDIODIR_IN);
-    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
+ * @param   pThis       Driver instance.
+ * @param   pStreamEx   Stream to capture from.
+ * @param   pcfCaptured Number of (host) audio frames captured.
+ */
+static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcfCaptured)
+{
+    Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_IN);
+    Assert(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
 
     /*
@@ -1538,11 +1667,11 @@
      */
     AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable);
-    uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
+    uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     if (!cbReadable)
-        Log2Func(("[%s] No readable data available\n", pStream->szName));
-
-    uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Guest.MixBuf); /* Parent */
+        Log2Func(("[%s] No readable data available\n", pStreamEx->Core.szName));
+
+    uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Guest.MixBuf); /* Parent */
     if (!cbFree)
-        Log2Func(("[%s] Buffer full\n", pStream->szName));
+        Log2Func(("[%s] Buffer full\n", pStreamEx->Core.szName));
 
     if (cbReadable > cbFree) /* More data readable than we can store at the moment? Limit. */
@@ -1558,9 +1687,9 @@
         uint8_t  abChunk[_4K];
         uint32_t cbCaptured;
-        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
+        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStreamEx->pvBackend,
                                                     abChunk, RT_MIN(cbReadable, (uint32_t)sizeof(abChunk)), &cbCaptured);
         if (RT_FAILURE(rc))
         {
-            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
             AssertRC(rc2);
             break;
@@ -1577,23 +1706,23 @@
          * (first) processing (if needed), so always write the incoming data at offset 0. */
         uint32_t cfHstWritten = 0;
-        rc = AudioMixBufWriteAt(&pStream->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten);
+        rc = AudioMixBufWriteAt(&pStreamEx->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten);
         if (   RT_FAILURE(rc)
             || !cfHstWritten)
         {
             AssertMsgFailed(("[%s] Write failed: cbCaptured=%RU32, cfHstWritten=%RU32, rc=%Rrc\n",
-                             pStream->szName, cbCaptured, cfHstWritten, rc));
+                             pStreamEx->Core.szName, cbCaptured, cfHstWritten, rc));
             break;
         }
 
         if (pThis->In.Cfg.Dbg.fEnabled)
-            AudioHlpFileWrite(pStream->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */);
+            AudioHlpFileWrite(pStreamEx->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */);
 
         uint32_t cfHstMixed = 0;
         if (cfHstWritten)
         {
-            int rc2 = AudioMixBufMixToParentEx(&pStream->Host.MixBuf, 0 /* cSrcOffset */, cfHstWritten /* cSrcFrames */,
+            int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Host.MixBuf, 0 /* cSrcOffset */, cfHstWritten /* cSrcFrames */,
                                                &cfHstMixed /* pcSrcMixed */);
             Log3Func(("[%s] cbCaptured=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
-                      pStream->szName, cbCaptured, cfHstWritten, cfHstMixed, rc2));
+                      pStreamEx->Core.szName, cbCaptured, cfHstWritten, cfHstMixed, rc2));
             AssertRC(rc2);
         }
@@ -1607,8 +1736,8 @@
     {
         if (cfCapturedTotal)
-            Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
+            Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCapturedTotal, rc));
     }
     else
-        LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStream->szName, rc));
+        LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStreamEx->Core.szName, rc));
 
     if (pcfCaptured)
@@ -1626,15 +1755,12 @@
  *
  * @returns VBox status code.
- * @param   pThis               Driver instance.
- * @param   pStream             Stream to capture from.
- * @param   pcfCaptured         Number of (host) audio frames captured. Optional.
- */
-static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
-{
-    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER);
-    Assert(pStream->enmDir == PDMAUDIODIR_IN);
-    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
+ * @param   pThis       Driver instance.
+ * @param   pStreamEx   Stream to capture from.
+ * @param   pcfCaptured Number of (host) audio frames captured.
+ */
+static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcfCaptured)
+{
+    Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_IN);
+    Assert(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
     AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable);
 
@@ -1643,11 +1769,11 @@
      */
     /* Note: Raw means *audio frames*, not bytes! */
-    uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
+    uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStreamEx->pvBackend);
     if (!cfReadable)
-        Log2Func(("[%s] No readable data available\n", pStream->szName));
-
-    const uint32_t cfFree = AudioMixBufFree(&pStream->Guest.MixBuf); /* Parent */
+        Log2Func(("[%s] No readable data available\n", pStreamEx->Core.szName));
+
+    const uint32_t cfFree = AudioMixBufFree(&pStreamEx->Guest.MixBuf); /* Parent */
     if (!cfFree)
-        Log2Func(("[%s] Buffer full\n", pStream->szName));
+        Log2Func(("[%s] Buffer full\n", pStreamEx->Core.szName));
 
     if (cfReadable > cfFree) /* More data readable than we can store at the moment? Limit. */
@@ -1663,5 +1789,5 @@
         PPDMAUDIOFRAME paFrames;
         uint32_t cfWritable;
-        rc = AudioMixBufPeekMutable(&pStream->Host.MixBuf, cfReadable, &paFrames, &cfWritable);
+        rc = AudioMixBufPeekMutable(&pStreamEx->Host.MixBuf, cfReadable, &paFrames, &cfWritable);
         if (   RT_FAILURE(rc)
             || !cfWritable)
@@ -1669,9 +1795,9 @@
 
         uint32_t cfCaptured;
-        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
+        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStreamEx->pvBackend,
                                                     paFrames, cfWritable, &cfCaptured);
         if (RT_FAILURE(rc))
         {
-            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
             AssertRC(rc2);
             break;
@@ -1689,5 +1815,5 @@
     if (pcfCaptured)
         *pcfCaptured = cfCapturedTotal;
-    Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
+    Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCapturedTotal, rc));
     return rc;
 }
@@ -1701,9 +1827,12 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
-    AssertPtr(pStream);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
     AssertPtrNull(pcFramesCaptured);
-    AssertMsg(pStream->enmDir == PDMAUDIODIR_IN,
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN,
               ("Stream '%s' is not an input stream and therefore cannot be captured (direction is 0x%x)\n",
-               pStream->szName, pStream->enmDir));
+               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, rc);
@@ -1712,5 +1841,5 @@
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    Log3Func(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
+    Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
 
     /*
@@ -1727,5 +1856,5 @@
 
         if (   !pThis->In.fEnabled
-            || !PDMAudioStrmStatusCanRead(pStream->fStatus))
+            || !PDMAudioStrmStatusCanRead(pStreamEx->Core.fStatus))
         {
             rc = VERR_AUDIO_STREAM_NOT_READY;
@@ -1737,28 +1866,25 @@
          */
         if (pThis->pHostDrvAudio->pfnStreamCaptureBegin)
-            pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStream->pvBackend);
-
-        if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))
-            rc = drvAudioStreamCaptureNonInterleaved(pThis, pStream, &cfCaptured);
-        else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
-            rc = drvAudioStreamCaptureRaw(pThis, pStream, &cfCaptured);
+            pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+
+        if (RT_LIKELY(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))
+            rc = drvAudioStreamCaptureNonInterleaved(pThis, pStreamEx, &cfCaptured);
+        else if (pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
+            rc = drvAudioStreamCaptureRaw(pThis, pStreamEx, &cfCaptured);
         else
             AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
 
         if (pThis->pHostDrvAudio->pfnStreamCaptureEnd)
-            pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStream->pvBackend);
+            pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStreamEx->pvBackend);
 
         if (RT_SUCCESS(rc))
         {
-            Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCaptured, rc));
-
-#ifdef VBOX_WITH_STATISTICS
-            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn,            cfCaptured);
-
-            STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesCaptured, cfCaptured);
-#endif
+            Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCaptured, rc));
+
+            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn,              cfCaptured);
+            STAM_COUNTER_ADD(&pStreamEx->In.Stats.TotalFramesCaptured, cfCaptured);
         }
         else if (RT_UNLIKELY(RT_FAILURE(rc)))
-            LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream->szName, rc));
+            LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
     } while (0);
 
@@ -1773,5 +1899,5 @@
 }
 
-#ifdef VBOX_WITH_AUDIO_CALLBACKS
+#ifdef VBOX_WITH_AUDIO_CALLBACKS  /** @todo r=bird: All this is non-sense that shall be replaced by a PDMIHOSTAUDIO partner interface. */
 
 /**
@@ -1890,4 +2016,8 @@
  * callback. Will result in some ugly deadlocks (or at least locking
  * order violations) then.
+ *
+ * @todo r=bird: The above warning is extremely bogus. You enter the critical
+ *       section of the driver here, if anything, that will be the lock order
+ *       violation.
  */
 static DECLCALLBACK(int) drvAudioBackendCallback(PPDMDRVINS pDrvIns, PDMAUDIOBACKENDCBTYPE enmType, void *pvUser, size_t cbUser)
@@ -1897,5 +2027,11 @@
     /* pvUser and cbUser are optional. */
 
-/** @todo r=bird: WTF *is* this?  Seriously?!? */
+/** @todo r=bird: WTF *is* this?  Seriously?!?
+ *
+ * DrvAudio will provide the host driver with a "callback" interface
+ * with methods like pfnNotifyDevicesChanged and pfnNotifyStatusChanged.
+ * The host drivers that implements callbacks can query the callback
+ * interface and make use of it.
+ */
 
     /* Get the upper driver (PDMIAUDIOCONNECTOR). */
@@ -1944,8 +2080,10 @@
  * @param   fLog                Whether to print the enumerated device to the release log or not.
  * @param   pDevEnum            Where to store the device enumeration.
+ *
+ * @remarks This is currently ONLY used for release logging.
  */
 static int drvAudioDevicesEnumerateInternal(PDRVAUDIO pThis, bool fLog, PPDMAUDIOHOSTENUM pDevEnum)
 {
-    AssertReturn(RTCritSectIsOwned(&pThis->CritSect) == false, VERR_WRONG_ORDER);
+    AssertReturn(!RTCritSectIsOwner(&pThis->CritSect), VERR_WRONG_ORDER);
 
     int rc;
@@ -2121,8 +2259,8 @@
     if (pThis->pHostDrvAudio)
     {
-        PPDMAUDIOSTREAM pStream;
-        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
-        {
-            drvAudioStreamControlInternal(pThis, pStream, enmCmd);
+        PDRVAUDIOSTREAM pStreamEx;
+        RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
+        {
+            drvAudioStreamControlInternal(pThis, pStreamEx, enmCmd);
         }
     }
@@ -2140,11 +2278,15 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
-    AssertReturn(cbBuf,      VERR_INVALID_PARAMETER);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
+    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER);
-    AssertMsg(pStream->enmDir == PDMAUDIODIR_IN,
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN,
               ("Stream '%s' is not an input stream and therefore cannot be read from (direction is 0x%x)\n",
-               pStream->szName, pStream->enmDir));
+               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
+
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, rc);
@@ -2159,5 +2301,5 @@
         uint32_t cfReadTotal = 0;
 
-        const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf);
+        const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStreamEx->Guest.MixBuf, cbBuf);
 
         if (pThis->In.fEnabled) /* Input for this audio driver enabled? See #9822. */
@@ -2173,21 +2315,19 @@
              * should have the audio data in the format the guest needs.
              */
-            uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStream->Guest.MixBuf));
+            uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStreamEx->Guest.MixBuf));
             while (cfToRead)
             {
                 uint32_t cfRead;
-                rc = AudioMixBufAcquireReadBlock(&pStream->Guest.MixBuf,
-                                                 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal),
-                                                 AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfToRead), &cfRead);
+                rc = AudioMixBufAcquireReadBlock(&pStreamEx->Guest.MixBuf,
+                                                 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal),
+                                                 AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfToRead), &cfRead);
                 if (RT_FAILURE(rc))
                     break;
 
 #ifdef VBOX_WITH_STATISTICS
-                const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfRead);
-
-                STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead,       cbRead);
-
-                STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesRead, cfRead);
-                STAM_COUNTER_INC(&pStream->In.Stats.TotalTimesRead);
+                const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfRead);
+                STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead,    cbRead);
+                STAM_COUNTER_ADD(&pStreamEx->In.Stats.TotalFramesRead, cfRead);
+                STAM_COUNTER_INC(&pStreamEx->In.Stats.TotalTimesRead);
 #endif
                 Assert(cfToRead >= cfRead);
@@ -2196,5 +2336,5 @@
                 cfReadTotal += cfRead;
 
-                AudioMixBufReleaseReadBlock(&pStream->Guest.MixBuf, cfRead);
+                AudioMixBufReleaseReadBlock(&pStreamEx->Guest.MixBuf, cfRead);
             }
 
@@ -2202,8 +2342,8 @@
             {
                 if (pThis->In.Cfg.Dbg.fEnabled)
-                    AudioHlpFileWrite(pStream->In.Dbg.pFileStreamRead,
-                                         pvBuf, AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 0 /* fFlags */);
-
-                AudioMixBufFinish(&pStream->Guest.MixBuf, cfReadTotal);
+                    AudioHlpFileWrite(pStreamEx->In.Dbg.pFileStreamRead,
+                                      pvBuf, AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal), 0 /* fFlags */);
+
+                AudioMixBufFinish(&pStreamEx->Guest.MixBuf, cfReadTotal);
             }
         }
@@ -2216,10 +2356,10 @@
         {
             Log3Func(("[%s] Filling in silence (%RU64ms / %RU64ms)\n", pStream->szName,
-                      PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfBuf - cfReadTotal),
-                      PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfBuf)));
-
-            PDMAudioPropsClearBuffer(&pStream->Guest.Cfg.Props,
-                                     (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal),
-                                     AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfBuf - cfReadTotal),
+                      PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cfBuf - cfReadTotal),
+                      PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cfBuf)));
+
+            PDMAudioPropsClearBuffer(&pStreamEx->Guest.Cfg.Props,
+                                     (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal),
+                                     AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfBuf - cfReadTotal),
                                      cfBuf - cfReadTotal);
 
@@ -2227,7 +2367,7 @@
         }
 
-        cbReadTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal);
-
-        pStream->tsLastReadWrittenNs = RTTimeNanoTS();
+        cbReadTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal);
+
+        pStreamEx->nsLastReadWritten = RTTimeNanoTS();
 
         Log3Func(("[%s] fEnabled=%RTbool, cbReadTotal=%RU32, rc=%Rrc\n", pStream->szName, pThis->In.fEnabled, cbReadTotal, rc));
@@ -2247,8 +2387,10 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Audio stream to create the backend side for.
- * @param   pCfgReq             Requested audio stream configuration to use for stream creation.
- * @param   pCfgAcq             Acquired audio stream configuration returned by the backend.
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Audio stream to create the backend side for.
+ * @param   pCfgReq     Requested audio stream configuration to use for
+ *                      stream creation.
+ * @param   pCfgAcq     Acquired audio stream configuration returned by
+ *                      the backend.
  *
  * @note    Configuration precedence for requested audio stream configuration (first has highest priority, if set):
@@ -2258,14 +2400,9 @@
  *          - default value
  */
-static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream,
+static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx,
                                                PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
 {
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
-
-    AssertMsg((pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) == 0,
-              ("Stream '%s' already initialized in backend\n", pStream->szName));
+    AssertMsg((pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) == 0,
+              ("Stream '%s' already initialized in backend\n", pStreamEx->Core.szName));
 
     /* Get the right configuration for the stream to be created. */
@@ -2282,5 +2419,5 @@
         PDMAudioPropsSetSampleSize(&pCfgReq->Props, PDMAudioPropsSampleSize(&pDrvCfg->Props));
         LogRel2(("Audio: Using custom sample size of %RU8 bytes for stream '%s'\n",
-                 PDMAudioPropsSampleSize(&pCfgReq->Props), pStream->szName));
+                 PDMAudioPropsSampleSize(&pCfgReq->Props), pStreamEx->Core.szName));
     }
 
@@ -2288,5 +2425,5 @@
     {
         pCfgReq->Props.uHz = pDrvCfg->Props.uHz;
-        LogRel2(("Audio: Using custom Hz rate %RU32 for stream '%s'\n", pCfgReq->Props.uHz, pStream->szName));
+        LogRel2(("Audio: Using custom Hz rate %RU32 for stream '%s'\n", pCfgReq->Props.uHz, pStreamEx->Core.szName));
     }
 
@@ -2295,5 +2432,5 @@
         pCfgReq->Props.fSigned = RT_BOOL(pDrvCfg->uSigned);
         LogRel2(("Audio: Using custom %s sample format for stream '%s'\n",
-                 pCfgReq->Props.fSigned ? "signed" : "unsigned", pStream->szName));
+                 pCfgReq->Props.fSigned ? "signed" : "unsigned", pStreamEx->Core.szName));
     }
 
@@ -2302,5 +2439,5 @@
         pCfgReq->Props.fSwapEndian = RT_BOOL(pDrvCfg->uSwapEndian);
         LogRel2(("Audio: Using custom %s endianess for samples of stream '%s'\n",
-                 pCfgReq->Props.fSwapEndian ? "swapped" : "original", pStream->szName));
+                 pCfgReq->Props.fSwapEndian ? "swapped" : "original", pStreamEx->Core.szName));
     }
 
@@ -2308,5 +2445,5 @@
     {
         PDMAudioPropsSetChannels(&pCfgReq->Props, PDMAudioPropsChannels(&pDrvCfg->Props));
-        LogRel2(("Audio: Using custom %RU8 channel(s) for stream '%s'\n", PDMAudioPropsChannels(&pDrvCfg->Props), pStream->szName));
+        LogRel2(("Audio: Using custom %RU8 channel(s) for stream '%s'\n", PDMAudioPropsChannels(&pDrvCfg->Props), pStreamEx->Core.szName));
     }
 
@@ -2314,5 +2451,5 @@
     if (!AudioHlpPcmPropsAreValid(&pCfgReq->Props))
     {
-        LogRel(("Audio: Invalid custom PCM properties set for stream '%s', cannot create stream\n", pStream->szName));
+        LogRel(("Audio: Invalid custom PCM properties set for stream '%s', cannot create stream\n", pStreamEx->Core.szName));
         return VERR_INVALID_PARAMETER;
     }
@@ -2336,5 +2473,5 @@
     LogRel2(("Audio: Using %s period size %RU64 ms / %RU32 frames for stream '%s'\n",
              pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod),
-             pCfgReq->Backend.cFramesPeriod, pStream->szName));
+             pCfgReq->Backend.cFramesPeriod, pStreamEx->Core.szName));
 
     /*
@@ -2356,5 +2493,5 @@
     LogRel2(("Audio: Using %s buffer size %RU64 ms / %RU32 frames for stream '%s'\n",
              pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
-             pCfgReq->Backend.cFramesBufferSize, pStream->szName));
+             pCfgReq->Backend.cFramesBufferSize, pStreamEx->Core.szName));
 
     /*
@@ -2379,5 +2516,5 @@
     LogRel2(("Audio: Using %s pre-buffering size %RU64 ms / %RU32 frames for stream '%s'\n",
              pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),
-             pCfgReq->Backend.cFramesPreBuffering, pStream->szName));
+             pCfgReq->Backend.cFramesPreBuffering, pStreamEx->Core.szName));
 
     /*
@@ -2387,5 +2524,5 @@
     {
         LogRel(("Audio: Error for stream '%s': Buffering size (%RU64ms) must not be smaller than the period size (%RU64ms)\n",
-                pStream->szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
+                pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),
                 PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod)));
         return VERR_INVALID_PARAMETER;
@@ -2398,5 +2535,5 @@
         {
             LogRel(("Audio: Error for stream '%s': Buffering size (%RU64ms) must not be smaller than the pre-buffering size (%RU64ms)\n",
-                    pStream->szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),
+                    pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),
                     PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize)));
             return VERR_INVALID_PARAMETER;
@@ -2413,5 +2550,5 @@
     {
         LogRel(("Audio: Creating stream '%s' with an invalid backend configuration not possible, skipping\n",
-                pStream->szName));
+                pStreamEx->Core.szName));
         return rc;
     }
@@ -2422,5 +2559,5 @@
     AssertPtr(pThis->pHostDrvAudio);
     if (pThis->pHostDrvAudio)
-        rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStream->pvBackend, pCfgReq, pCfgAcq);
+        rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStreamEx->pvBackend, pCfgReq, pCfgAcq);
     else
         rc = VERR_PDM_NO_ATTACHED_DRIVER;
@@ -2428,9 +2565,9 @@
     {
         if (rc == VERR_NOT_SUPPORTED)
-            LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStream->szName));
+            LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStreamEx->Core.szName));
         else if (rc == VERR_AUDIO_STREAM_COULD_NOT_CREATE)
-            LogRel2(("Audio: Stream '%s' could not be created in backend because of missing hardware / drivers\n", pStream->szName));
+            LogRel2(("Audio: Stream '%s' could not be created in backend because of missing hardware / drivers\n", pStreamEx->Core.szName));
         else
-            LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStream->szName, rc));
+            LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStreamEx->Core.szName, rc));
         return rc;
     }
@@ -2440,5 +2577,5 @@
     AssertLogRelMsgReturn(AudioHlpStreamCfgIsValid(pCfgAcq),
                           ("Audio: Creating stream '%s' returned an invalid backend configuration (%s), skipping\n",
-                           pStream->szName, PDMAudioPropsToString(&pCfgAcq->Props, szTmp, sizeof(szTmp))),
+                           pStreamEx->Core.szName, PDMAudioPropsToString(&pCfgAcq->Props, szTmp, sizeof(szTmp))),
                           VERR_INVALID_PARAMETER);
 
@@ -2446,9 +2583,9 @@
     if (pCfgAcq->Backend.cFramesBufferSize != pCfgReq->Backend.cFramesBufferSize)
         LogRel2(("Audio: Buffer size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
-                 pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesBufferSize), pCfgAcq->Backend.cFramesBufferSize));
+                 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesBufferSize), pCfgAcq->Backend.cFramesBufferSize));
 
     if (pCfgAcq->Backend.cFramesPeriod != pCfgReq->Backend.cFramesPeriod)
         LogRel2(("Audio: Period size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
-                 pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPeriod), pCfgAcq->Backend.cFramesPeriod));
+                 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPeriod), pCfgAcq->Backend.cFramesPeriod));
 
     /* Was pre-buffering requested, but the acquired configuration from the backend told us something else? */
@@ -2457,5 +2594,5 @@
         if (pCfgAcq->Backend.cFramesPreBuffering != pCfgReq->Backend.cFramesPreBuffering)
             LogRel2(("Audio: Pre-buffering size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
-                     pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
+                     pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
 
         if (pCfgAcq->Backend.cFramesPreBuffering > pCfgAcq->Backend.cFramesBufferSize)
@@ -2463,10 +2600,10 @@
             pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesBufferSize;
             LogRel2(("Audio: Pre-buffering size bigger than buffer size for stream '%s', adjusting to %RU64ms (%RU32 frames)\n",
-                     pStream->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
+                     pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));
         }
     }
     else if (pCfgReq->Backend.cFramesPreBuffering == 0) /* Was the pre-buffering requested as being disabeld? Tell the users. */
     {
-        LogRel2(("Audio: Pre-buffering is disabled for stream '%s'\n", pStream->szName));
+        LogRel2(("Audio: Pre-buffering is disabled for stream '%s'\n", pStreamEx->Core.szName));
         pCfgAcq->Backend.cFramesPreBuffering = 0;
     }
@@ -2480,5 +2617,5 @@
                     VERR_INVALID_PARAMETER);
 
-    pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
+    pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
 
     return VINF_SUCCESS;
@@ -2490,49 +2627,46 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Stream to initialize.
- * @param   pCfgHost            Stream configuration to use for the host side (backend).
- * @param   pCfgGuest           Stream configuration to use for the guest side.
- */
-static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream,
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Stream to initialize.
+ * @param   fFlags      PDMAUDIOSTREAM_CREATE_F_XXX.
+ * @param   pCfgHost    Stream configuration to use for the host side (backend).
+ * @param   pCfgGuest   Stream configuration to use for the guest side.
+ */
+static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t fFlags,
                                       PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest)
 {
-    AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfgHost,  VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfgGuest, VERR_INVALID_POINTER);
-
     /*
      * Init host stream.
      */
-    pStream->uMagic = PDMAUDIOSTREAM_MAGIC;
+    pStreamEx->Core.uMagic = PDMAUDIOSTREAM_MAGIC;
 
     /* Set the host's default audio data layout. */
+/** @todo r=bird: Why, oh why? OTOH, the layout stuff is non-sense anyway. */
     pCfgHost->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
 
 #ifdef LOG_ENABLED
-    LogFunc(("[%s] Requested host format:\n", pStream->szName));
+    LogFunc(("[%s] Requested host format:\n", pStreamEx->Core.szName));
     PDMAudioStrmCfgLog(pCfgHost);
 #endif
 
-    LogRel2(("Audio: Creating stream '%s'\n", pStream->szName));
+    LogRel2(("Audio: Creating stream '%s'\n", pStreamEx->Core.szName));
     LogRel2(("Audio: Guest %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n",
-             pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName,
+             pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName,
              pCfgGuest->Props.uHz, PDMAudioPropsSampleBits(&pCfgGuest->Props), pCfgGuest->Props.fSigned ? "S" : "U",
              PDMAudioPropsChannels(&pCfgGuest->Props), PDMAudioPropsChannels(&pCfgGuest->Props) == 1 ? "" : "s"));
     LogRel2(("Audio: Requested host %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n",
-             pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName,
+             pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName,
              pCfgHost->Props.uHz, PDMAudioPropsSampleBits(&pCfgHost->Props), pCfgHost->Props.fSigned ? "S" : "U",
              PDMAudioPropsChannels(&pCfgHost->Props), PDMAudioPropsChannels(&pCfgHost->Props) == 1 ? "" : "s"));
 
     PDMAUDIOSTREAMCFG CfgHostAcq;
-    int rc = drvAudioStreamCreateInternalBackend(pThis, pStream, pCfgHost, &CfgHostAcq);
+    int rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, pCfgHost, &CfgHostAcq);
     if (RT_FAILURE(rc))
         return rc;
 
-    LogFunc(("[%s] Acquired host format:\n",  pStream->szName));
+    LogFunc(("[%s] Acquired host format:\n",  pStreamEx->Core.szName));
     PDMAudioStrmCfgLog(&CfgHostAcq);
     LogRel2(("Audio: Acquired host %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n",
-             CfgHostAcq.enmDir == PDMAUDIODIR_IN ? "recording" : "playback",  pStream->szName,
+             CfgHostAcq.enmDir == PDMAUDIODIR_IN ? "recording" : "playback",  pStreamEx->Core.szName,
              CfgHostAcq.Props.uHz, PDMAudioPropsSampleBits(&CfgHostAcq.Props), CfgHostAcq.Props.fSigned ? "S" : "U",
              PDMAudioPropsChannels(&CfgHostAcq.Props), PDMAudioPropsChannels(&CfgHostAcq.Props) == 1 ? "" : "s"));
@@ -2565,5 +2699,5 @@
         LogRel2(("Audio: Warning: Pre-buffering size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), "
                  "setting pre-buffering size to %RU32 frames\n",
-                 CfgHostAcq.Backend.cFramesPreBuffering, pStream->szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
+                 CfgHostAcq.Backend.cFramesPreBuffering, pStreamEx->Core.szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
         CfgHostAcq.Backend.cFramesPreBuffering = CfgHostAcq.Backend.cFramesBufferSize;
     }
@@ -2572,5 +2706,5 @@
     {
         LogRel2(("Audio: Warning: Period size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), setting to %RU32 frames\n",
-                 CfgHostAcq.Backend.cFramesPeriod, pStream->szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
+                 CfgHostAcq.Backend.cFramesPeriod, pStreamEx->Core.szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
         CfgHostAcq.Backend.cFramesPeriod = CfgHostAcq.Backend.cFramesBufferSize;
     }
@@ -2578,10 +2712,10 @@
     uint64_t msBufferSize = PDMAudioPropsFramesToMilli(&CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
     LogRel2(("Audio: Buffer size of stream '%s' is %RU64ms (%RU32 frames)\n",
-             pStream->szName, msBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
+             pStreamEx->Core.szName, msBufferSize, CfgHostAcq.Backend.cFramesBufferSize));
 
     /* If no own pre-buffer is set, let the backend choose. */
     uint64_t msPreBuf = PDMAudioPropsFramesToMilli(&CfgHostAcq.Props, CfgHostAcq.Backend.cFramesPreBuffering);
     LogRel2(("Audio: Pre-buffering size of stream '%s' is %RU64ms (%RU32 frames)\n",
-             pStream->szName, msPreBuf, CfgHostAcq.Backend.cFramesPreBuffering));
+             pStreamEx->Core.szName, msPreBuf, CfgHostAcq.Backend.cFramesPreBuffering));
 
     /* Make sure the configured buffer size by the backend at least can hold the configured latency. */
@@ -2589,5 +2723,5 @@
 
     LogRel2(("Audio: Period size of stream '%s' is %RU64ms (%RU32 frames)\n",
-             pStream->szName, msPeriod, CfgHostAcq.Backend.cFramesPeriod));
+             pStreamEx->Core.szName, msPeriod, CfgHostAcq.Backend.cFramesPeriod));
 
     if (   pCfgGuest->Device.cMsSchedulingHint             /* Any scheduling hint set? */
@@ -2595,15 +2729,18 @@
     {
         LogRel(("Audio: Warning: Scheduling hint of stream '%s' is bigger (%RU64ms) than used period size (%RU64ms)\n",
-                pStream->szName, pCfgGuest->Device.cMsSchedulingHint, msPeriod));
+                pStreamEx->Core.szName, pCfgGuest->Device.cMsSchedulingHint, msPeriod));
     }
 
     /* Destroy any former mixing buffer. */
-    AudioMixBufDestroy(&pStream->Host.MixBuf);
-
-    rc = AudioMixBufInit(&pStream->Host.MixBuf, pStream->szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
-    AssertRC(rc);
+    AudioMixBufDestroy(&pStreamEx->Host.MixBuf);
+
+    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
+    {
+        rc = AudioMixBufInit(&pStreamEx->Host.MixBuf, pStreamEx->Core.szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize);
+        AssertRCReturn(rc, rc);
+    }
 
     /* Make a copy of the acquired host stream configuration. */
-    rc = PDMAudioStrmCfgCopy(&pStream->Host.Cfg, &CfgHostAcq);
+    rc = PDMAudioStrmCfgCopy(&pStreamEx->Host.Cfg, &CfgHostAcq);
     AssertRC(rc);
 
@@ -2614,34 +2751,40 @@
     if (pCfgGuest->Device.cMsSchedulingHint)
         LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms (%RU32 bytes)\n",
-                 pStream->szName, pCfgGuest->Device.cMsSchedulingHint,
+                 pStreamEx->Core.szName, pCfgGuest->Device.cMsSchedulingHint,
                  PDMAudioPropsMilliToBytes(&pCfgGuest->Props, pCfgGuest->Device.cMsSchedulingHint)));
 
     /* Destroy any former mixing buffer. */
-    AudioMixBufDestroy(&pStream->Guest.MixBuf);
+    AudioMixBufDestroy(&pStreamEx->Guest.MixBuf);
 
     /* Set the guests's default audio data layout. */
     pCfgGuest->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
 
-    rc = AudioMixBufInit(&pStream->Guest.MixBuf, pStream->szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize);
+    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
+    {
+        rc = AudioMixBufInit(&pStreamEx->Guest.MixBuf, pStreamEx->Core.szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize);
+        AssertRCReturn(rc, rc);
+    }
+
+    /* Make a copy of the guest stream configuration. */
+    rc = PDMAudioStrmCfgCopy(&pStreamEx->Guest.Cfg, pCfgGuest);
     AssertRC(rc);
 
-    /* Make a copy of the guest stream configuration. */
-    rc = PDMAudioStrmCfgCopy(&pStream->Guest.Cfg, pCfgGuest);
-    AssertRC(rc);
-
     if (RT_FAILURE(rc))
-        LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStream->szName, rc));
-
-    if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
-    {
-        /* Host (Parent) -> Guest (Child). */
-        rc = AudioMixBufLinkTo(&pStream->Host.MixBuf, &pStream->Guest.MixBuf);
-        AssertRC(rc);
-    }
-    else
-    {
-        /* Guest (Parent) -> Host (Child). */
-        rc = AudioMixBufLinkTo(&pStream->Guest.MixBuf, &pStream->Host.MixBuf);
-        AssertRC(rc);
+        LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
+
+    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
+    {
+        if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
+        {
+            /* Host (Parent) -> Guest (Child). */
+            rc = AudioMixBufLinkTo(&pStreamEx->Host.MixBuf, &pStreamEx->Guest.MixBuf);
+            AssertRC(rc);
+        }
+        else
+        {
+            /* Guest (Parent) -> Host (Child). */
+            rc = AudioMixBufLinkTo(&pStreamEx->Guest.MixBuf, &pStreamEx->Host.MixBuf);
+            AssertRC(rc);
+        }
     }
 
@@ -2651,28 +2794,37 @@
     PPDMDRVINS const pDrvIns = pThis->pDrvIns;
     /** @todo expose config and more. */
-    PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.Cfg.Backend.cFramesBufferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                           "Host side: The size of the backend buffer (in frames)", "%s/0-HostBackendBufSize", pStream->szName);
-    PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                           "Host side: The size of the mixer buffer (in frames)",   "%s/1-HostMixBufSize", pStream->szName);
-    PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                           "Guest side: The size of the mixer buffer (in frames)",  "%s/2-GuestMixBufSize", pStream->szName);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.Cfg.Backend.cFramesBufferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                           "Host side: The size of the backend buffer (in frames)", "%s/0-HostBackendBufSize", pStreamEx->Core.szName);
+    if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF))
+    {
+        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                               "Host side: The size of the mixer buffer (in frames)",   "%s/1-HostMixBufSize", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                               "Guest side: The size of the mixer buffer (in frames)",  "%s/2-GuestMixBufSize", pStreamEx->Core.szName);
+        if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
+        {
+            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                                   "Host side: Number of frames in the mixer buffer",   "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
+            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                                   "Guest side: Number of frames in the mixer buffer",  "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
+        }
+        else
+        {
+            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                                   "Host side: Number of frames in the mixer buffer",     "%s/1-HostMixBufUsed", pStreamEx->Core.szName);
+            PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                                   "Guest side: Number of frames in the mixer buffer",    "%s/2-GuestMixBufUsed", pStreamEx->Core.szName);
+        }
+    }
     if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
     {
-        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                               "Host side: Number of frames in the mixer buffer",   "%s/1-HostMixBufUsed", pStream->szName);
-        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                               "Guest side: Number of frames in the mixer buffer",  "%s/2-GuestMixBufUsed", pStream->szName);
+        /** @todo later? */
     }
     else
     {
-        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                               "Host side: Number of frames in the mixer buffer",     "%s/1-HostMixBufUsed", pStream->szName);
-        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                               "Guest side: Number of frames in the mixer buffer",    "%s/2-GuestMixBufUsed", pStream->szName);
-
-        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Out.Stats.cbBackendWritableBefore, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                               "Host side: Free space in backend buffer before play", "%s/0-HostBackendBufFreeBefore", pStream->szName);
-        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Out.Stats.cbBackendWritableAfter, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
-                               "Host side: Free space in backend buffer after play",  "%s/0-HostBackendBufFreeAfter", pStream->szName);
+        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableBefore, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                               "Host side: Free space in backend buffer before play", "%s/0-HostBackendBufFreeBefore", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableAfter, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
+                               "Host side: Free space in backend buffer after play",  "%s/0-HostBackendBufFreeAfter", pStreamEx->Core.szName);
     }
 
@@ -2681,15 +2833,15 @@
     if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
     {
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesCaptured", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalFramesCaptured,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesCaptured", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalFramesCaptured,
                                   szStatName, STAMUNIT_COUNT, "Total frames played.");
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesCaptured", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalTimesCaptured,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesCaptured", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalTimesCaptured,
                                   szStatName, STAMUNIT_COUNT, "Total number of playbacks.");
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesRead", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalFramesRead,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesRead", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalFramesRead,
                                   szStatName, STAMUNIT_COUNT, "Total frames read.");
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesRead", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->In.Stats.TotalTimesRead,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesRead", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalTimesRead,
                                   szStatName, STAMUNIT_COUNT, "Total number of reads.");
     }
@@ -2697,22 +2849,22 @@
     {
         Assert(pCfgGuest->enmDir == PDMAUDIODIR_OUT);
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesPlayed", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalFramesPlayed,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesPlayed", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalFramesPlayed,
                                   szStatName, STAMUNIT_COUNT, "Total frames played.");
 
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesPlayed", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalTimesPlayed,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesPlayed", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalTimesPlayed,
                                   szStatName, STAMUNIT_COUNT, "Total number of playbacks.");
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesWritten", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalFramesWritten,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesWritten", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalFramesWritten,
                                   szStatName, STAMUNIT_COUNT, "Total frames written.");
 
-        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesWritten", pStream->szName);
-        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream->Out.Stats.TotalTimesWritten,
+        RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesWritten", pStreamEx->Core.szName);
+        PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalTimesWritten,
                                   szStatName, STAMUNIT_COUNT, "Total number of writes.");
     }
 #endif /* VBOX_WITH_STATISTICS */
 
-    LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
+    LogFlowFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
     return rc;
 }
@@ -2721,5 +2873,5 @@
  * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamCreate}
  */
-static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost,
+static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, uint32_t fFlags, PPDMAUDIOSTREAMCFG pCfgHost,
                                               PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream)
 {
@@ -2730,4 +2882,5 @@
      * Assert sanity.
      */
+    AssertReturn(!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF), VERR_INVALID_FLAGS);
     AssertPtrReturn(pCfgHost,   VERR_INVALID_POINTER);
     AssertPtrReturn(pCfgGuest,  VERR_INVALID_POINTER);
@@ -2781,28 +2934,30 @@
          * Allocate and initialize common state.
          */
-        PPDMAUDIOSTREAM pStream = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM) + RT_ALIGN_Z(cbHstStrm, 64));
-        if (pStream)
+        PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)RTMemAllocZ(sizeof(DRVAUDIOSTREAM) + RT_ALIGN_Z(cbHstStrm, 64));
+        if (pStreamEx)
         {
             /* Retrieve host driver name for easier identification. */
             AssertPtr(pThis->pHostDrvAudio);
             PPDMDRVINS pDrvAudioInst = PDMIBASE_2_PDMDRV(pThis->pDrvIns->pDownBase);
-            RTStrPrintf(pStream->szName, RT_ELEMENTS(pStream->szName), "[%s] %s",
+            RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s",
                         pDrvAudioInst && pDrvAudioInst->pReg && pDrvAudioInst->pReg->szName[0]
                         ? pDrvAudioInst->pReg->szName : "none",
                         pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<Untitled>");
 
-            pStream->enmDir    = pCfgHost->enmDir;
-            pStream->cbBackend = (uint32_t)cbHstStrm;
+            pStreamEx->Core.enmDir    = pCfgHost->enmDir;
+            pStreamEx->Core.cbBackend = (uint32_t)cbHstStrm;
             if (cbHstStrm)
-                pStream->pvBackend = pStream + 1;
+                pStreamEx->pvBackend = pStreamEx + 1;
+            pStreamEx->fNoMixBufs     = RT_BOOL(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF);
+            pStreamEx->uMagic         = DRVAUDIOSTREAM_MAGIC;
 
             /*
              * Try to init the rest.
              */
-            rc = drvAudioStreamInitInternal(pThis, pStream, pCfgHost, pCfgGuest);
+            rc = drvAudioStreamInitInternal(pThis, pStreamEx, fFlags, pCfgHost, pCfgGuest);
             if (RT_SUCCESS(rc))
             {
                 /* Set initial reference counts. */
-                pStream->cRefs = 1;
+                pStreamEx->Core.cRefs = 1;
 
                 /* Decrement the free stream counter. */
@@ -2813,7 +2968,7 @@
                  * We're good.
                  */
-                RTListAppend(&pThis->lstStreams, &pStream->ListEntry);
+                RTListAppend(&pThis->lstStreams, &pStreamEx->ListEntry);
                 STAM_COUNTER_INC(&pThis->Stats.TotalStreamsCreated);
-                *ppStream = pStream;
+                *ppStream = &pStreamEx->Core;
 
                 /*
@@ -2824,8 +2979,8 @@
                     if (pThis->In.Cfg.Dbg.fEnabled)
                     {
-                        AudioHlpFileCreateAndOpen(&pStream->In.Dbg.pFileCaptureNonInterleaved, pThis->In.Cfg.Dbg.szPathOut,
-                                                  "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
-                        AudioHlpFileCreateAndOpen(&pStream->In.Dbg.pFileStreamRead, pThis->In.Cfg.Dbg.szPathOut,
-                                                  "DrvAudioRead", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
+                        AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileCaptureNonInterleaved, pThis->In.Cfg.Dbg.szPathOut,
+                                                  "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
+                        AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileStreamRead, pThis->In.Cfg.Dbg.szPathOut,
+                                                  "DrvAudioRead", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
                     }
                 }
@@ -2834,8 +2989,8 @@
                     if (pThis->Out.Cfg.Dbg.fEnabled)
                     {
-                        AudioHlpFileCreateAndOpen(&pStream->Out.Dbg.pFilePlayNonInterleaved, pThis->Out.Cfg.Dbg.szPathOut,
-                                                  "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
-                        AudioHlpFileCreateAndOpen(&pStream->Out.Dbg.pFileStreamWrite, pThis->Out.Cfg.Dbg.szPathOut,
-                                                  "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStream->Host.Cfg.Props);
+                        AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFilePlayNonInterleaved, pThis->Out.Cfg.Dbg.szPathOut,
+                                                  "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
+                        AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFileStreamWrite, pThis->Out.Cfg.Dbg.szPathOut,
+                                                  "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
                     }
                 }
@@ -2844,7 +2999,7 @@
             {
                 LogFunc(("drvAudioStreamInitInternal failed: %Rrc\n", rc));
-                int rc2 = drvAudioStreamUninitInternal(pThis, pStream);
+                int rc2 = drvAudioStreamUninitInternal(pThis, pStreamEx);
                 AssertRC(rc2);
-                drvAudioStreamFree(pStream);
+                drvAudioStreamFree(pStreamEx);
             }
         }
@@ -2885,8 +3040,8 @@
         *pfEnabled = fEnable;
 
-        PPDMAUDIOSTREAM pStream;
-        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
-        {
-            if (pStream->enmDir != enmDir) /* Skip unwanted streams. */
+        PDRVAUDIOSTREAM pStreamEx;
+        RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
+        {
+            if (pStreamEx->Core.enmDir != enmDir) /* Skip unwanted streams. */
                 continue;
 
@@ -2901,15 +3056,13 @@
              * See @bugref{9882}.
              */
-            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream,
+            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx,
                                                            fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
             if (RT_FAILURE(rc2))
             {
                 if (rc2 == VERR_AUDIO_STREAM_NOT_READY)
-                {
-                    LogRel(("Audio: Stream '%s' not available\n", pStream->szName));
-                }
+                    LogRel(("Audio: Stream '%s' not available\n", pStreamEx->Core.szName));
                 else
-                    LogRel(("Audio: Failed to %s %s stream '%s', rc=%Rrc\n",
-                            fEnable ? "enable" : "disable", enmDir == PDMAUDIODIR_IN ? "input" : "output", pStream->szName, rc2));
+                    LogRel(("Audio: Failed to %s %s stream '%s', rc=%Rrc\n", fEnable ? "enable" : "disable",
+                            enmDir == PDMAUDIODIR_IN ? "input" : "output", pStreamEx->Core.szName, rc2));
             }
             else
@@ -2917,5 +3070,5 @@
                 /* When (re-)enabling a stream, clear the disabled warning bit again. */
                 if (fEnable)
-                    pStream->fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
+                    pStreamEx->Core.fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
             }
 
@@ -3013,6 +3166,9 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
-    AssertPtrReturn(pStream, 0);
-    AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, 0);
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, 0);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, 0);
+    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, 0);
@@ -3027,11 +3183,15 @@
 
     if (   pThis->pHostDrvAudio
-        && (   PDMAudioStrmStatusCanRead(pStream->fStatus)
+        && (   PDMAudioStrmStatusCanRead(pStreamEx->Core.fStatus)
             || fDisabled)
        )
     {
-        const uint32_t cfReadable = AudioMixBufLive(&pStream->Guest.MixBuf);
-
-        cbReadable = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable);
+        if (pStreamEx->fNoMixBufs)
+            cbReadable = pThis->pHostDrvAudio ? pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream) : 0;
+        else
+        {
+            const uint32_t cfReadable = AudioMixBufLive(&pStreamEx->Guest.MixBuf);
+            cbReadable = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadable);
+        }
 
         if (!cbReadable)
@@ -3047,10 +3207,11 @@
             PDMAUDIOSTREAMSTS fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;
             if (pThis->pHostDrvAudio->pfnStreamGetStatus)
-                fStatus = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend);
+                fStatus = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStreamEx->pvBackend);
             if (   !PDMAudioStrmStatusCanRead(fStatus)
                 || fDisabled)
             {
-                cbReadable = PDMAudioPropsNanoToBytes(&pStream->Host.Cfg.Props, RTTimeNanoTS() - pStream->tsLastReadWrittenNs);
-                if (!(pStream->fWarningsShown & PDMAUDIOSTREAM_WARN_FLAGS_DISABLED))
+                cbReadable = PDMAudioPropsNanoToBytes(&pStreamEx->Host.Cfg.Props,
+                                                      RTTimeNanoTS() - pStreamEx->nsLastReadWritten);
+                if (!(pStreamEx->Core.fWarningsShown & PDMAUDIOSTREAM_WARN_FLAGS_DISABLED))
                 {
                     if (fDisabled)
@@ -3058,7 +3219,7 @@
                     else
                         LogRel(("Audio: Warning: Input for stream '%s' of driver '%s' not ready (current input status is %#x), returning silence\n",
-                                pStream->szName, pThis->szName, fStatus));
-
-                    pStream->fWarningsShown |= PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
+                                pStreamEx->Core.szName, pThis->szName, fStatus));
+
+                    pStreamEx->Core.fWarningsShown |= PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;
                 }
             }
@@ -3067,10 +3228,10 @@
         /* Make sure to align the readable size to the guest's frame size. */
         if (cbReadable)
-            cbReadable = PDMAudioPropsFloorBytesToFrame(&pStream->Guest.Cfg.Props, cbReadable);
+            cbReadable = PDMAudioPropsFloorBytesToFrame(&pStreamEx->Guest.Cfg.Props, cbReadable);
     }
 
     RTCritSectLeave(&pThis->CritSect);
     Log3Func(("[%s] cbReadable=%RU32 (%RU64ms)\n",
-              pStream->szName, cbReadable, PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbReadable)));
+              pStreamEx->Core.szName, cbReadable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbReadable)));
     return cbReadable;
 }
@@ -3083,6 +3244,9 @@
     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     AssertPtr(pThis);
-    AssertPtrReturn(pStream,    0);
-    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"));
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, 0);
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, 0);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, 0);
+    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"));
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, 0);
@@ -3095,15 +3259,18 @@
     /* Note: We don't propage the backend stream's status to the outside -- it's the job of this
      *       audio connector to make sense of it. */
-    if (PDMAudioStrmStatusCanWrite(pStream->fStatus))
-    {
-        cbWritable = AudioMixBufFreeBytes(&pStream->Host.MixBuf);
+    if (PDMAudioStrmStatusCanWrite(pStreamEx->Core.fStatus))
+    {
+        if (pStreamEx->fNoMixBufs)
+            cbWritable = pThis->pHostDrvAudio ? pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream) : 0;
+        else
+            cbWritable = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf);
 
         /* Make sure to align the writable size to the host's frame size. */
-        cbWritable = PDMAudioPropsFloorBytesToFrame(&pStream->Host.Cfg.Props, cbWritable);
+        cbWritable = PDMAudioPropsFloorBytesToFrame(&pStreamEx->Host.Cfg.Props, cbWritable);
     }
 
     RTCritSectLeave(&pThis->CritSect);
     Log3Func(("[%s] cbWritable=%RU32 (%RU64ms)\n",
-              pStream->szName, cbWritable, PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbWritable)));
+              pStreamEx->Core.szName, cbWritable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbWritable)));
     return cbWritable;
 }
@@ -3117,6 +3284,12 @@
     AssertPtr(pThis);
 
+    /** @todo r=bird: It is not documented that we ignore NULL streams...  Why is
+     *        this necessary? */
     if (!pStream)
         return PDMAUDIOSTREAMSTS_FLAGS_NONE;
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, PDMAUDIOSTREAMSTS_FLAGS_NONE);
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, PDMAUDIOSTREAMSTS_FLAGS_NONE);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, PDMAUDIOSTREAMSTS_FLAGS_NONE);
 
     int rc = RTCritSectEnter(&pThis->CritSect);
@@ -3124,7 +3297,7 @@
 
     /* Is the stream scheduled for re-initialization? Do so now. */
-    drvAudioStreamMaybeReInit(pThis, pStream);
-
-    PDMAUDIOSTREAMSTS fStrmStatus = pStream->fStatus;
+    drvAudioStreamMaybeReInit(pThis, pStreamEx);
+
+    PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus;
 
     RTCritSectLeave(&pThis->CritSect);
@@ -3132,5 +3305,5 @@
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    Log3Func(("[%s] %s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
+    Log3Func(("[%s] %s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));
     return fStrmStatus;
 }
@@ -3142,11 +3315,15 @@
 {
     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
-    AssertPtrReturn(pVol,       VERR_INVALID_POINTER);
-
-    LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStream->szName, pVol->uLeft, pVol->uRight, pVol->fMuted));
-
-    AudioMixBufSetVolume(&pStream->Guest.MixBuf, pVol);
-    AudioMixBufSetVolume(&pStream->Host.MixBuf, pVol);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;
+    AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
+    AssertPtrReturn(pVol, VERR_INVALID_POINTER);
+    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
+
+    LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStreamEx->Core.szName, pVol->uLeft, pVol->uRight, pVol->fMuted));
+    AssertReturn(!pStreamEx->fNoMixBufs, VERR_ACCESS_DENIED);
+
+    AudioMixBufSetVolume(&pStreamEx->Guest.MixBuf, pVol);
+    AudioMixBufSetVolume(&pStreamEx->Host.MixBuf,  pVol);
 
     return VINF_SUCCESS;
@@ -3160,11 +3337,11 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Audio stream destruct backend for.
- */
-static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
-{
-    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Audio stream destruct backend for.
+ */
+static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
+{
+    AssertPtr(pThis);
+    AssertPtr(pStreamEx);
 
     int rc = VINF_SUCCESS;
@@ -3173,19 +3350,19 @@
     char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
 #endif
-    LogFunc(("[%s] fStatus=%s\n", pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
-
-    if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED)
-    {
-        AssertPtr(pStream->pvBackend);
+    LogFunc(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
+
+    if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED)
+    {
+        AssertPtr(pStreamEx->pvBackend);
 
         /* Check if the pointer to  the host audio driver is still valid.
          * It can be NULL if we were called in drvAudioDestruct, for example. */
         if (pThis->pHostDrvAudio)
-            rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStream->pvBackend);
-
-        pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
-    }
-
-    LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
+            rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStreamEx->pvBackend);
+
+        pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
+    }
+
+    LogFlowFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
     return rc;
 }
@@ -3196,87 +3373,95 @@
  *
  * @returns VBox status code.
- * @param   pThis               Pointer to driver instance.
- * @param   pStream             Pointer to audio stream to uninitialize.
+ * @param   pThis       Pointer to driver instance.
+ * @param   pStreamEx   Pointer to audio stream to uninitialize.
  *
  * @note    Caller owns the critical section.
  */
-static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
+static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
 {
     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    AssertMsgReturn(pStream->cRefs <= 1,
-                    ("Stream '%s' still has %RU32 references held when uninitializing\n", pStream->szName, pStream->cRefs),
+    AssertMsgReturn(pStreamEx->Core.cRefs <= 1,
+                    ("Stream '%s' still has %RU32 references held when uninitializing\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs),
                     VERR_WRONG_ORDER);
-    LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
+    LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs));
 
     /*
      * ...
      */
-    int rc = drvAudioStreamControlInternal(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
+    int rc = drvAudioStreamControlInternal(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
     if (RT_SUCCESS(rc))
-        rc = drvAudioStreamDestroyInternalBackend(pThis, pStream);
+        rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
 
     /* Destroy mixing buffers. */
-    AudioMixBufDestroy(&pStream->Guest.MixBuf);
-    AudioMixBufDestroy(&pStream->Host.MixBuf);
+    AudioMixBufDestroy(&pStreamEx->Guest.MixBuf);
+    AudioMixBufDestroy(&pStreamEx->Host.MixBuf);
 
     if (RT_SUCCESS(rc))
     {
 #ifdef LOG_ENABLED
-        if (pStream->fStatus != PDMAUDIOSTREAMSTS_FLAGS_NONE)
+        if (pStreamEx->Core.fStatus != PDMAUDIOSTREAMSTS_FLAGS_NONE)
         {
             char szStreamSts[DRVAUDIO_STATUS_STR_MAX];
             LogFunc(("[%s] Warning: Still has %s set when uninitializing\n",
-                     pStream->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));
+                     pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus)));
         }
 #endif
-        pStream->fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;
+        pStreamEx->Core.fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;
     }
 
     PPDMDRVINS const pDrvIns = pThis->pDrvIns;
-    if (pStream->enmDir == PDMAUDIODIR_IN)
+    if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
     {
 #ifdef VBOX_WITH_STATISTICS
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalFramesCaptured);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalTimesCaptured);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalFramesRead);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->In.Stats.TotalTimesRead);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalFramesCaptured);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalTimesCaptured);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalFramesRead);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalTimesRead);
 #endif
         if (pThis->In.Cfg.Dbg.fEnabled)
         {
-            AudioHlpFileDestroy(pStream->In.Dbg.pFileCaptureNonInterleaved);
-            pStream->In.Dbg.pFileCaptureNonInterleaved = NULL;
-
-            AudioHlpFileDestroy(pStream->In.Dbg.pFileStreamRead);
-            pStream->In.Dbg.pFileStreamRead = NULL;
-        }
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cMixed);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cUsed);
+            AudioHlpFileDestroy(pStreamEx->In.Dbg.pFileCaptureNonInterleaved);
+            pStreamEx->In.Dbg.pFileCaptureNonInterleaved = NULL;
+
+            AudioHlpFileDestroy(pStreamEx->In.Dbg.pFileStreamRead);
+            pStreamEx->In.Dbg.pFileStreamRead = NULL;
+        }
+        if (!pStreamEx->fNoMixBufs)
+        {
+            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cMixed);
+            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed);
+        }
     }
     else
     {
-        Assert(pStream->enmDir == PDMAUDIODIR_OUT);
+        Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT);
 #ifdef VBOX_WITH_STATISTICS
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalFramesPlayed);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalTimesPlayed);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalFramesWritten);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.TotalTimesWritten);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalFramesPlayed);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalTimesPlayed);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalFramesWritten);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalTimesWritten);
 #endif
         if (pThis->Out.Cfg.Dbg.fEnabled)
         {
-            AudioHlpFileDestroy(pStream->Out.Dbg.pFilePlayNonInterleaved);
-            pStream->Out.Dbg.pFilePlayNonInterleaved = NULL;
-
-            AudioHlpFileDestroy(pStream->Out.Dbg.pFileStreamWrite);
-            pStream->Out.Dbg.pFileStreamWrite = NULL;
-        }
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.cbBackendWritableAfter);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.cbBackendWritableBefore);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cUsed);
-        PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cMixed);
-    }
-    PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.Cfg.Backend.cFramesBufferSize);
-    PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cFrames);
-    PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cFrames);
+            AudioHlpFileDestroy(pStreamEx->Out.Dbg.pFilePlayNonInterleaved);
+            pStreamEx->Out.Dbg.pFilePlayNonInterleaved = NULL;
+
+            AudioHlpFileDestroy(pStreamEx->Out.Dbg.pFileStreamWrite);
+            pStreamEx->Out.Dbg.pFileStreamWrite = NULL;
+        }
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableAfter);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableBefore);
+        if (!pStreamEx->fNoMixBufs)
+        {
+            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cUsed);
+            PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed);
+        }
+    }
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.Cfg.Backend.cFramesBufferSize);
+    if (!pStreamEx->fNoMixBufs)
+    {
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cFrames);
+        PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames);
+    }
 
     LogFlowFunc(("Returning %Rrc\n", rc));
@@ -3295,30 +3480,33 @@
         return VINF_SUCCESS;
     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
-    Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC);
+    PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream;   /* Note! Do not touch pStream after this! */
+    Assert(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC);
+    Assert(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC);
 
     int rc = RTCritSectEnter(&pThis->CritSect);
     AssertRCReturn(rc, rc);
 
-    LogRel2(("Audio: Destroying stream '%s'\n", pStream->szName));
-
-    LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
-    AssertMsg(pStream->cRefs <= 1, ("%u %s\n", pStream->cRefs, pStream->szName));
-    if (pStream->cRefs <= 1)
-    {
-        rc = drvAudioStreamUninitInternal(pThis, pStream);
+    LogRel2(("Audio: Destroying stream '%s'\n", pStreamEx->Core.szName));
+
+    LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs));
+    AssertMsg(pStreamEx->Core.cRefs <= 1, ("%u %s\n", pStreamEx->Core.cRefs, pStreamEx->Core.szName));
+    if (pStreamEx->Core.cRefs <= 1)
+    {
+        rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
         if (RT_SUCCESS(rc))
         {
-            if (pStream->enmDir == PDMAUDIODIR_IN)
+            if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
                 pThis->In.cStreamsFree++;
             else /* Out */
                 pThis->Out.cStreamsFree++;
 
-            RTListNodeRemove(&pStream->ListEntry);
-
-            drvAudioStreamFree(pStream);
+            RTListNodeRemove(&pStreamEx->ListEntry);
+
+            drvAudioStreamFree(pStreamEx);
+            pStreamEx = NULL;
             pStream = NULL;
         }
         else
-            LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStream->szName, rc));
+            LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc));
     }
     else
@@ -3375,9 +3563,9 @@
          * in drvAudioDestruct().
          */
-        PPDMAUDIOSTREAM pStream;
-        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
-        {
-            drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
-            drvAudioStreamDestroyInternalBackend(pThis, pStream);
+        PDRVAUDIOSTREAM pStreamEx;
+        RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
+        {
+            drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
+            drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
         }
 
@@ -3534,14 +3722,12 @@
     pThis->pHostDrvAudio = NULL;
 
-    PPDMAUDIOSTREAM pStream, pStreamNext;
-    RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, ListEntry)
-    {
-        int rc = drvAudioStreamUninitInternal(pThis, pStream);
+    PDRVAUDIOSTREAM pStreamEx, pStreamExNext;
+    RTListForEachSafe(&pThis->lstStreams, pStreamEx, pStreamExNext, DRVAUDIOSTREAM, ListEntry)
+    {
+        int rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
         if (RT_SUCCESS(rc))
         {
-            RTListNodeRemove(&pStream->ListEntry);
-
-            drvAudioStreamFree(pStream);
-            pStream = NULL;
+            RTListNodeRemove(&pStreamEx->ListEntry);
+            drvAudioStreamFree(pStreamEx);
         }
     }
Index: trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp	(revision 88320)
+++ trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp	(revision 88356)
@@ -206,5 +206,5 @@
      * General stuff.
      */
-    PDMAUDIOMIXBUF mb;
+    AUDIOMIXBUF mb;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&mb, "Single", &config, cBufSize));
     RTTESTI_CHECK(AudioMixBufSize(&mb) == cBufSize);
@@ -323,5 +323,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
 
-    PDMAUDIOMIXBUF parent;
+    AUDIOMIXBUF parent;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cParentBufSize));
 
@@ -340,5 +340,5 @@
     uint32_t cChildBufSize = RTRandU32Ex(cFrames /* Min */, 64 /* Max */);
 
-    PDMAUDIOMIXBUF child1;
+    AUDIOMIXBUF child1;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &cfg_c1, cChildBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent));
@@ -355,5 +355,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c2));
 
-    PDMAUDIOMIXBUF child2;
+    AUDIOMIXBUF child2;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &cfg_c2, cChildBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent));
@@ -460,5 +460,5 @@
     PDMAUDIOPCMPROPS const CfgDst = PDMAUDIOPCMPROPS_INITIALIZER(2 /*cbSample*/, true /*fSigned*/, 2 /*ch*/, uToHz, false /*fSwap*/);
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgDst));
-    PDMAUDIOMIXBUF Parent;
+    AUDIOMIXBUF Parent;
     RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&Parent, "ParentDownsampling", &CfgDst, cFramesParent));
 
@@ -467,5 +467,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgSrc));
     uint32_t const cFramesChild = RTRandU32Ex(32, RT_ELEMENTS(aSrcFrames));
-    PDMAUDIOMIXBUF Child;
+    AUDIOMIXBUF Child;
     RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&Child, "ChildDownsampling", &CfgSrc, cFramesChild));
     RTTESTI_CHECK_RC_OK_RETV(AudioMixBufLinkTo(&Child, &Parent));
@@ -567,5 +567,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
 
-    PDMAUDIOMIXBUF parent;
+    AUDIOMIXBUF parent;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
 
@@ -589,5 +589,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));
 
-    PDMAUDIOMIXBUF child;
+    AUDIOMIXBUF child;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
@@ -669,5 +669,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p));
 
-    PDMAUDIOMIXBUF parent;
+    AUDIOMIXBUF parent;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize));
 
@@ -683,5 +683,5 @@
     RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c));
 
-    PDMAUDIOMIXBUF child;
+    AUDIOMIXBUF child;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
@@ -763,8 +763,8 @@
 
     PDMAUDIOVOLUME vol = { false, 0, 0 };   /* Not muted. */
-    PDMAUDIOMIXBUF parent;
+    AUDIOMIXBUF parent;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg, cBufSize));
 
-    PDMAUDIOMIXBUF child;
+    AUDIOMIXBUF child;
     RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg, cBufSize));
     RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
