Index: /trunk/src/VBox/Devices/Audio/DevHDA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 75979)
+++ /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 75980)
@@ -1301,26 +1301,6 @@
     const bool fInReset  = RT_BOOL(HDA_REG_IND(pThis, iReg) & HDA_SDCTL_SRST);
 
-# ifdef LOG_ENABLED
-    if (fRun)
-    {
-        PDMAUDIOPCMPROPS Props;
-        int rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &Props);
-        AssertRC(rc2);
-        LogFunc(("[SD%RU8] %RU32Hz, %RU8bit, %RU8 channel(s)\n",
-                 uSD, Props.uHz, Props.cBytes * 8 /* Bit */, Props.cChannels));
-    }
-# endif
-
-    LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
-             uSD, fRun, fInRun, fReset, fInReset, u32Value));
-
-    if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
-    {
-        const uint8_t uStripeCtl = ((u32Value >> HDA_SDCTL_STRIPE_SHIFT) & HDA_SDCTL_STRIPE_MASK) + 1;
-        LogFunc(("[SD%RU8] Using %RU8 SDOs (stripe control)\n", uSD, uStripeCtl));
-        if (uStripeCtl > 1)
-            LogRel2(("HDA: Warning: Striping output over more than one SDO for stream #%RU8 currently is not implemented " \
-                     "(%RU8 SDOs requested)\n", uSD, uStripeCtl));
-    }
+    /*LogFunc(("[SD%RU8] fRun=%RTbool, fInRun=%RTbool, fReset=%RTbool, fInReset=%RTbool, %R[sdctl]\n",
+               uSD, fRun, fInRun, fReset, fInReset, u32Value));*/
 
     /*
@@ -1341,14 +1321,5 @@
     }
 
-    PHDATAG pTag = &pThis->aTags[uTag];
-    AssertPtr(pTag);
-
-    LogFunc(("[SD%RU8] Using stream tag=%RU8\n", uSD, uTag));
-
-    /* Assign new values. */
-    pTag->uTag    = uTag;
-    pTag->pStream = hdaGetStreamFromSD(pThis, uSD);
-
-    PHDASTREAM pStream = pTag->pStream;
+    PHDASTREAM pStream = hdaGetStreamFromSD(pThis, uSD);
     AssertPtr(pStream);
 
@@ -1410,15 +1381,44 @@
             if (fRun)
             {
+                if (hdaGetDirFromSD(uSD) == PDMAUDIODIR_OUT)
+                {
+                    const uint8_t uStripeCtl = ((u32Value >> HDA_SDCTL_STRIPE_SHIFT) & HDA_SDCTL_STRIPE_MASK) + 1;
+                    LogFunc(("[SD%RU8] Using %RU8 SDOs (stripe control)\n", uSD, uStripeCtl));
+                    if (uStripeCtl > 1)
+                        LogRel2(("HDA: Warning: Striping output over more than one SDO for stream #%RU8 currently is not implemented " \
+                                 "(%RU8 SDOs requested)\n", uSD, uStripeCtl));
+                }
+
+                PHDATAG pTag = &pThis->aTags[uTag];
+                AssertPtr(pTag);
+
+                LogFunc(("[SD%RU8] Using stream tag=%RU8\n", uSD, uTag));
+
+                /* Assign new values. */
+                pTag->uTag    = uTag;
+                pTag->pStream = hdaGetStreamFromSD(pThis, uSD);
+
+# ifdef LOG_ENABLED
+                PDMAUDIOPCMPROPS Props;
+                rc2 = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, pStream->u8SD), &Props);
+                AssertRC(rc2);
+                LogFunc(("[SD%RU8] %RU32Hz, %RU8bit, %RU8 channel(s)\n",
+                         pStream->u8SD, Props.uHz, Props.cBytes * 8 /* Bit */, Props.cChannels));
+# endif
                 /* (Re-)initialize the stream with current values. */
                 rc2 = hdaR3StreamInit(pStream, pStream->u8SD);
-                AssertRC(rc2);
-
-                /* Remove the old stream from the device setup. */
-                rc2 = hdaR3RemoveStream(pThis, &pStream->State.Cfg);
-                AssertRC(rc2);
-
-                /* Add the stream to the device setup. */
-                rc2 = hdaR3AddStream(pThis, &pStream->State.Cfg);
-                AssertRC(rc2);
+                if (   RT_SUCCESS(rc2)
+                    /* Any vital stream change occurred so that we need to (re-)add the stream to our setup?
+                     * Otherwise just skip this, as this costs a lot of performance. */
+                    && rc2 != VINF_NO_CHANGE)
+                {
+                    /* Remove the old stream from the device setup. */
+                    rc2 = hdaR3RemoveStream(pThis, &pStream->State.Cfg);
+                    AssertRC(rc2);
+
+                    /* Add the stream to the device setup. */
+                    rc2 = hdaR3AddStream(pThis, &pStream->State.Cfg);
+                    AssertRC(rc2);
+                }
             }
 
@@ -4210,15 +4210,15 @@
                              ("HDA: Saved state contains invalid DMA buffer usage (%RU32/%RU32) for stream #%RU8",
                               cbCircBufUsed, cbCircBufSize, uStreamID));
-            AssertPtr(pStream->State.pCircBuf);
 
             /* Do we need to cre-create the circular buffer do fit the data size? */
-            if (cbCircBufSize != (uint32_t)RTCircBufSize(pStream->State.pCircBuf))
+            if (   pStream->State.pCircBuf
+                && cbCircBufSize != (uint32_t)RTCircBufSize(pStream->State.pCircBuf))
             {
                 RTCircBufDestroy(pStream->State.pCircBuf);
                 pStream->State.pCircBuf = NULL;
-
-                rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBufSize);
-                AssertRC(rc);
             }
+
+            rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBufSize);
+            AssertRC(rc);
 
             if (   RT_SUCCESS(rc)
Index: /trunk/src/VBox/Devices/Audio/HDAStream.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/HDAStream.cpp	(revision 75979)
+++ /trunk/src/VBox/Devices/Audio/HDAStream.cpp	(revision 75980)
@@ -135,5 +135,5 @@
     AssertPtrReturnVoid(pStream);
 
-    LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
+    LogFlowFunc(("[SD%RU8] Destroying ...\n", pStream->u8SD));
 
     hdaR3StreamMapDestroy(&pStream->State.Mapping);
@@ -186,5 +186,6 @@
  * Initializes an HDA stream.
  *
- * @returns IPRT status code.
+ * @returns IPRT status code. VINF_NO_CHANGE if the stream does not need (re-)initialization because the stream's (hardware)
+ *          parameters did not change.
  * @param   pStream             HDA stream to initialize.
  * @param   uSD                 SD (stream descriptor) number to assign the HDA stream to.
@@ -197,14 +198,25 @@
     AssertPtr(pThis);
 
-    pStream->u8SD       = uSD;
-    pStream->u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, pStream->u8SD),
-                                      HDA_STREAM_REG(pThis, BDPU, pStream->u8SD));
-    pStream->u16LVI     = HDA_STREAM_REG(pThis, LVI, pStream->u8SD);
-    pStream->u32CBL     = HDA_STREAM_REG(pThis, CBL, pStream->u8SD);
-    pStream->u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, pStream->u8SD) + 1;
-
-    PPDMAUDIOSTREAMCFG pCfg = &pStream->State.Cfg;
-
-    int rc = hdaR3SDFMTToPCMProps(HDA_STREAM_REG(pThis, FMT, uSD), &pCfg->Props);
+    const uint64_t u64BDLBase = RT_MAKE_U64(HDA_STREAM_REG(pThis, BDPL, uSD),
+                                            HDA_STREAM_REG(pThis, BDPU, uSD));
+    const uint16_t u16LVI     = HDA_STREAM_REG(pThis, LVI, uSD);
+    const uint32_t u32CBL     = HDA_STREAM_REG(pThis, CBL, uSD);
+    const uint16_t u16FIFOS   = HDA_STREAM_REG(pThis, FIFOS, uSD) + 1;
+    const uint32_t u32FMT     = HDA_STREAM_REG(pThis, FMT, uSD);
+
+    /* Is the bare minimum set of registers configured for the stream?
+     * If not, bail out early, as there's nothing to do here for us (yet). */
+    if (   !u64BDLBase
+        || !u16LVI
+        || !u32CBL
+        || !u16FIFOS
+        || !u32FMT)
+    {
+        LogFunc(("[SD%RU8] Registers not set up yet, skipping (re-)initialization\n", uSD));
+        return VINF_SUCCESS;
+    }
+
+    PDMAUDIOPCMPROPS Props;
+    int rc = hdaR3SDFMTToPCMProps(u32FMT, &Props);
     if (RT_FAILURE(rc))
     {
@@ -213,7 +225,55 @@
     }
 
-    /* Set scheduling hint (if available). */
-    if (pThis->uTimerHz)
-        pCfg->Device.uSchedulingHintMs = 1000 /* ms */ / pThis->uTimerHz;
+    /* Reset (any former) stream map. */
+    hdaR3StreamMapReset(&pStream->State.Mapping);
+
+    /*
+     * Initialize the stream mapping in any case, regardless if
+     * we support surround audio or not. This is needed to handle
+     * the supported channels within a single audio stream, e.g. mono/stereo.
+     *
+     * In other words, the stream mapping *always* knows the real
+     * number of channels in a single audio stream.
+     */
+    rc = hdaR3StreamMapInit(&pStream->State.Mapping, &Props);
+    AssertRCReturn(rc, rc);
+
+#ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
+    if (Props.cChannels > 2)
+    {
+        /*
+         * When not running with surround support enabled, override the audio channel count
+         * with stereo (2) channels so that we at least can properly work with those.
+         *
+         * Note: This also involves dealing with surround setups the guest might has set up for us.
+         */
+        LogRel2(("HDA: More than stereo (2) channels are not supported (%RU8 requested), "
+                 "falling back to stereo channels for stream #%RU8\n", Props.cChannels, uSD));
+        Props.cChannels = 2;
+    }
+#endif
+
+    /* Did some of the vital / critical parameters change?
+     * If not, we can skip a lot of the (re-)initialization and just (re-)use the existing stuff.
+     * Also, tell the caller so that further actions can be taken. */
+    if (   uSD        == pStream->u8SD
+        && u64BDLBase == pStream->u64BDLBase
+        && u16LVI     == pStream->u16LVI
+        && u32CBL     == pStream->u32CBL
+        && u16FIFOS   == pStream->u16FIFOS
+        && DrvAudioHlpPCMPropsAreEqual(&Props, &pStream->State.Cfg.Props))
+    {
+        LogFunc(("[SD%RU8] No format change, skipping (re-)initialization\n", uSD));
+        return VINF_NO_CHANGE;
+    }
+
+    pStream->u8SD       = uSD;
+    pStream->u64BDLBase = u64BDLBase;
+    pStream->u16LVI     = u16LVI;
+    pStream->u32CBL     = u32CBL;
+    pStream->u16FIFOS   = u16FIFOS;
+
+    PPDMAUDIOSTREAMCFG pCfg = &pStream->State.Cfg;
+    pCfg->Props = Props;
 
     /* (Re-)Allocate the stream's internal DMA buffer, based on the PCM  properties we just got above. */
@@ -225,5 +285,6 @@
 
     /* By default we allocate an internal buffer of 100ms. */
-    rc = RTCircBufCreate(&pStream->State.pCircBuf, DrvAudioHlpMilliToBytes(100 /* ms */, &pCfg->Props)); /** @todo Make this configurable. */
+    rc = RTCircBufCreate(&pStream->State.pCircBuf,
+                         DrvAudioHlpMilliToBytes(100 /* ms */, &pCfg->Props)); /** @todo Make this configurable. */
     AssertRCReturn(rc, rc);
 
@@ -254,36 +315,6 @@
     }
 
-    if (   !pStream->u32CBL
-        || !pStream->u16LVI
-        || !pStream->u64BDLBase
-        || !pStream->u16FIFOS)
-    {
-        return VINF_SUCCESS;
-    }
-
-    /*
-     * Initialize the stream mapping in any case, regardless if
-     * we support surround audio or not. This is needed to handle
-     * the supported channels within a single audio stream, e.g. mono/stereo.
-     *
-     * In other words, the stream mapping *always* knows the real
-     * number of channels in a single audio stream.
-     */
-    rc = hdaR3StreamMapInit(&pStream->State.Mapping, &pCfg->Props);
-    AssertRCReturn(rc, rc);
-
-#ifndef VBOX_WITH_AUDIO_HDA_51_SURROUND
-    /*
-     * When not running with surround support enabled, override the channel count
-     * with stereo (2) channels so that we at least can properly work with those.
-     *
-     * Note: This also involves dealing with surround setups the guest might has set up for us.
-     */
-    pCfg->Props.cChannels = 2;
-#endif
-
-    LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16, Hz=%RU32, rc=%Rrc\n",
-             pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS,
-             pStream->State.Cfg.Props.uHz, rc));
+    LogFunc(("[SD%RU8] DMA @ 0x%x (%RU32 bytes), LVI=%RU16, FIFOS=%RU16\n",
+             pStream->u8SD, pStream->u64BDLBase, pStream->u32CBL, pStream->u16LVI, pStream->u16FIFOS));
 
     /* Make sure that mandatory parameters are set up correctly. */
@@ -397,8 +428,4 @@
             pStream->State.cbTransferChunk = pStream->State.cbTransferSize;
 
-        pStream->State.cbTransferProcessed        = 0;
-        pStream->State.cTransferPendingInterrupts = 0;
-        pStream->State.tsLastUpdateNs             = 0;
-
         const uint64_t cTicksPerHz = TMTimerGetFreq(pStream->pTimer) / pThis->uTimerHz;
 
@@ -410,8 +437,4 @@
         pStream->State.cTransferTicks     = pStream->State.cbTransferChunk * pStream->State.cTicksPerByte;
         Assert(pStream->State.cTransferTicks);
-
-        /* Initialize the transfer timestamps. */
-        pStream->State.tsTransferLast     = 0;
-        pStream->State.tsTransferNext     = 0;
 
         LogFunc(("[SD%RU8] Timer %uHz (%RU64 ticks per Hz), cTicksPerByte=%RU64, cbTransferChunk=%RU32, cTransferTicks=%RU64, " \
@@ -451,5 +474,5 @@
 # endif
 
-    LogFunc(("[SD%RU8]: Reset\n", uSD));
+    LogFunc(("[SD%RU8] Reset\n", uSD));
 
     /*
@@ -482,9 +505,15 @@
 
     /* Assign the default mixer sink to the stream. */
-    pStream->pMixSink             = hdaR3GetDefaultSink(pThis, uSD);
-
+    pStream->pMixSink = hdaR3GetDefaultSink(pThis, uSD);
+
+    /* Reset transfer stuff. */
+    pStream->State.cbTransferProcessed        = 0;
+    pStream->State.cTransferPendingInterrupts = 0;
     pStream->State.tsTransferLast = 0;
     pStream->State.tsTransferNext = 0;
 
+    /* Initialize other timestamps. */
+    pStream->State.tsLastUpdateNs = 0;
+
     RT_ZERO(pStream->State.BDLE);
     pStream->State.uCurBDLE = 0;
@@ -492,11 +521,4 @@
     if (pStream->State.pCircBuf)
         RTCircBufReset(pStream->State.pCircBuf);
-
-    /* Reset stream map. */
-    hdaR3StreamMapReset(&pStream->State.Mapping);
-
-    /* (Re-)initialize the stream with current values. */
-    int rc2 = hdaR3StreamInit(pStream, uSD);
-    AssertRC(rc2);
 
     /* Reset the stream's period. */
@@ -534,5 +556,5 @@
     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
 
-    LogFunc(("[SD%RU8]: fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
+    LogFunc(("[SD%RU8] fEnable=%RTbool, pMixSink=%p\n", pStream->u8SD, fEnable, pStream->pMixSink));
 
     int rc = VINF_SUCCESS;
@@ -781,5 +803,5 @@
     if (!pSink)
     {
-        AssertMsgFailed(("[SD%RU8]: Can't read from a stream with no sink attached\n", pStream->u8SD));
+        AssertMsgFailed(("[SD%RU8] Can't read from a stream with no sink attached\n", pStream->u8SD));
 
         if (pcbRead)
@@ -814,5 +836,5 @@
 
             Assert(cbSrc >= cbWritten);
-            Log2Func(("[SD%RU8]: %RU32/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
+            Log2Func(("[SD%RU8] %RU32/%zu bytes read\n", pStream->u8SD, cbWritten, cbSrc));
         }
 
@@ -1565,5 +1587,5 @@
     u32LPIB = RT_MIN(u32LPIB, pStream->u32CBL);
 
-    LogFlowFunc(("[SD%RU8]: LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
+    LogFlowFunc(("[SD%RU8] LPIB=%RU32 (DMA Position Buffer Enabled: %RTbool)\n",
                  pStream->u8SD, u32LPIB, pThis->fDMAPosition));
 
@@ -1777,5 +1799,5 @@
     RTThreadUserSignal(hThreadSelf);
 
-    LogFunc(("[SD%RU8]: Started\n", pStream->u8SD));
+    LogFunc(("[SD%RU8] Started\n", pStream->u8SD));
 
     for (;;)
@@ -1806,5 +1828,5 @@
     }
 
-    LogFunc(("[SD%RU8]: Ended\n", pStream->u8SD));
+    LogFunc(("[SD%RU8] Ended\n", pStream->u8SD));
 
     ASMAtomicXchgBool(&pAIO->fStarted, false);
@@ -1851,5 +1873,5 @@
         rc = VINF_SUCCESS;
 
-    LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
+    LogFunc(("[SD%RU8] Returning %Rrc\n", pStream->u8SD, rc));
     return rc;
 }
@@ -1890,5 +1912,5 @@
     }
 
-    LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
+    LogFunc(("[SD%RU8] Returning %Rrc\n", pStream->u8SD, rc));
     return rc;
 }
