Index: trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
===================================================================
--- trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp	(revision 61090)
+++ trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp	(revision 61091)
@@ -131,18 +131,4 @@
 AssertCompile(AUDIOMIXBUF_VOL_0DB == 0x40000000);   /* For now -- when only attenuation is used. */
 
-/**
- * Structure for holding sample conversion parameters for
- * the audioMixBufConvFromXXX / audioMixBufConvToXXX macros.
- */
-typedef struct AUDMIXBUF_CONVOPTS
-{
-    /** Number of audio samples to convert. */
-    uint32_t       cSamples;
-    /** Volume to apply during conversion. Pass 0
-     *  to convert the original values. May not apply to
-     *  all conversion functions. */
-    PDMAUDIOVOLUME Volume;
-} AUDMIXBUF_CONVOPTS, *PAUDMIXBUF_CONVOPTS;
-
 /*
  * When running the audio testcases we want to verfiy
@@ -160,10 +146,4 @@
 static inline void audioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf);
 #endif
-
-typedef uint32_t (AUDMIXBUF_FN_CONVFROM) (PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, const PAUDMIXBUF_CONVOPTS pOpts);
-typedef AUDMIXBUF_FN_CONVFROM *PAUDMIXBUF_FN_CONVFROM;
-
-typedef void (AUDMIXBUF_FN_CONVTO) (void *pvDst, const PPDMAUDIOSAMPLE paSrc, const PAUDMIXBUF_CONVOPTS pOpts);
-typedef AUDMIXBUF_FN_CONVTO *PAUDMIXBUF_FN_CONVTO;
 
 /* Can return VINF_TRY_AGAIN for getting next pointer at beginning (circular) */
@@ -649,11 +629,7 @@
  * @return  PAUDMIXBUF_FN_CONVFROM  Function pointer to conversion macro if found, NULL if not supported.
  * @param   enmFmt                  Audio format to lookup conversion macro for.
- * @param   fMuted                  Flag determining whether the source is muted.
- */
-static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt, bool fMuted)
-{
-    if (fMuted)
-        return audioMixBufConvFromSilence;
-
+ */
+static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt)
+{
     if (AUDMIXBUF_FMT_SIGNED(enmFmt))
     {
@@ -807,4 +783,8 @@
                                                  pProps->cBits,
                                                  pProps->fSigned);
+
+    pMixBuf->pConvFrom = audioMixBufConvFromLookup(pMixBuf->AudioFmt);
+    pMixBuf->pConvTo   = audioMixBufConvToLookup(pMixBuf->AudioFmt);
+
     pMixBuf->cShift = pProps->cShift;
     pMixBuf->pszName = RTStrDup(pszName);
@@ -1321,18 +1301,24 @@
     if (cToProcess)
     {
-        PAUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt);
+        PAUDMIXBUF_FN_CONVTO pConv;
+        if (pMixBuf->AudioFmt != enmFmt)
+            pConv = audioMixBufConvToLookup(enmFmt);
+        else
+            pConv = pMixBuf->pConvTo;
+
         if (pConv)
         {
             AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
+
+            AssertPtr(pConv);
             pConv(pvBuf, pMixBuf->pSamples + offSamples, &convOpts);
 
+#ifdef DEBUG
+            AudioMixBufDbgPrint(pMixBuf);
+#endif
             rc = VINF_SUCCESS;
         }
         else
-            rc = VERR_INVALID_PARAMETER;
-
-#ifdef DEBUG
-        AudioMixBufDbgPrint(pMixBuf);
-#endif
+            rc = VERR_NOT_SUPPORTED;
     }
     else
@@ -1651,5 +1637,13 @@
         return VERR_BUFFER_OVERFLOW;
 
-    PAUDMIXBUF_FN_CONVFROM pConv = audioMixBufConvFromLookup(enmFmt, pMixBuf->Volume.fMuted);
+    PAUDMIXBUF_FN_CONVFROM pConv;
+    if (pMixBuf->AudioFmt != enmFmt)
+        pConv = audioMixBufConvFromLookup(enmFmt);
+    else
+    {
+        pConv = pMixBuf->Volume.fMuted
+              ? &audioMixBufConvFromSilence : pMixBuf->pConvFrom;
+    }
+
     if (!pConv)
         return VERR_NOT_SUPPORTED;
@@ -1754,5 +1748,13 @@
     }
 
-    PAUDMIXBUF_FN_CONVFROM pConv = audioMixBufConvFromLookup(enmFmt, pMixBuf->Volume.fMuted);
+    PAUDMIXBUF_FN_CONVFROM pConv;
+    if (pMixBuf->AudioFmt != enmFmt)
+        pConv = audioMixBufConvFromLookup(enmFmt);
+    else
+    {
+        pConv = pMixBuf->Volume.fMuted
+              ? &audioMixBufConvFromSilence : pMixBuf->pConvFrom;
+    }
+
     if (!pConv)
         return VERR_NOT_SUPPORTED;
