Index: sipXmediaLib/include/mp/dmaTask.h
===================================================================
--- sipXmediaLib/include/mp/dmaTask.h    (revision 9895)
+++ sipXmediaLib/include/mp/dmaTask.h    (working copy)
@@ -33,8 +33,17 @@
 #  define N_IN_BUFFERS        N_BUFFERS
 #  define N_OUT_BUFFERS       N_BUFFERS
 
+// N_OUT_PRIME was previously set to 8. however, we found that on windows 
+// vista this would cause a bad stutter. this is because after calling
+// 8 waveOpenOut we got a batch of 8 WOM_DONE and then called another
+// 8 waveOpenOut. hence there was a gap. by using 16 buffers we find
+// that vista sends 5 WOM_DONE at a time. windows xp and windows 2000
+// send WOM_DONE one at a time at regular intervals. this is surely
+// a bug in windows vista! that said we can't fix vista and there
+// doesn't appear to be any harm with setting N_OUT_PRIME to 16.
+
 #  define N_IN_PRIME          32 // must not be more than N_IN_BUFFERS:
-#  define N_OUT_PRIME         8 // must not be more than N_OUT_BUFFERS:
+#  define N_OUT_PRIME         16 // must not be more than N_OUT_BUFFERS:
 
 #  define N_SAMPLES           80
 
Index: sipXmediaLib/src/mp/SpeakerThreadWnt.cpp
===================================================================
--- sipXmediaLib/src/mp/SpeakerThreadWnt.cpp    (revision 9895)
+++ sipXmediaLib/src/mp/SpeakerThreadWnt.cpp    (working copy)
@@ -414,7 +414,40 @@
     return 0 ;
 }
 
+void waitResetCompleteSpeakerDevices()
+{
+    int i ;
+    bool bStillResetting;
+    int iterations = 0;
 
+    // wait until all the buffers have been reset. previously the code 
+    // waited exactly 100ms, however this wasn't always enough. now
+    // it will wait until there are no buffers in the queue.
+    // in order to avoid an infinite loop (although this should only happen
+    // if waveOutReset was not called) we give up after 100 iterations
+    // (equals 1 second). if this happens then we could be left with some 
+    // active data in the buffers.
+
+    do
+    {
+        bStillResetting = false;
+
+        for (i=0; i<N_OUT_BUFFERS; i++) 
+        {
+            if (NULL != hOutHdr[i] && (pOutHdr[i]->dwFlags & WHDR_INQUEUE) != 0 ) 
+            {
+                bStillResetting = true;
+            }
+        }
+
+        if ( bStillResetting )
+        {
+            Sleep(10);
+        }
+    }
+    while ( bStillResetting && ++iterations<100 );
+}
+
 void closeSpeakerDevices()
 {
     MMRESULT ret;
@@ -427,11 +460,14 @@
     if (audioOutH)
     {
         ret = waveOutReset(audioOutH);
-        Sleep(100) ;
         if (ret != MMSYSERR_NOERROR)
         {
             showWaveError("waveOutReset", ret, -1, __LINE__);
         }
+        else
+        {
+            waitResetCompleteSpeakerDevices();
+        }
 
         for (i=0; i<N_OUT_BUFFERS; i++) 
         {
@@ -463,11 +499,14 @@
     if (audioOutCallH)
     {
         ret = waveOutReset(audioOutCallH);
-        Sleep(100) ;
         if (ret != MMSYSERR_NOERROR)
         {
             showWaveError("waveOutReset", ret, -1, __LINE__);
         }
+        else
+        {
+            waitResetCompleteSpeakerDevices();
+        }
 
         for (i=0; i<N_OUT_BUFFERS; i++) 
         {
@@ -567,12 +606,21 @@
         {
             if (audioOutH)
             {
-                waveOutReset(audioOutH);
+                ret = waveOutReset(audioOutH);
             }
             if (audioOutCallH)
             {
-                waveOutReset(audioOutCallH);
+                ret = waveOutReset(audioOutCallH);
             }
+
+            if (ret != MMSYSERR_NOERROR)
+            {
+                showWaveError("waveOutReset", ret, -1, __LINE__);
+            }
+            else
+            {
+                waitResetCompleteSpeakerDevices();
+            }
         }
 
         if (bGotMsg) 
@@ -619,12 +667,22 @@
                     closeSpeakerDevices() ;
                     if (audioOutH)
                     {
-                        waveOutReset(audioOutH);
+                        ret = waveOutReset(audioOutH);
                     }
                     if (audioOutCallH)
                     {
-                        waveOutReset(audioOutCallH);
+                        ret = waveOutReset(audioOutCallH);
                     }
+
+                    if (ret != MMSYSERR_NOERROR)
+                    {
+                        showWaveError("waveOutReset", ret, -1, __LINE__);
+                    }
+                    else
+                    {
+                        waitResetCompleteSpeakerDevices();
+                    }
+
                     //Sleep(100);
                     // Kill the hearbeat timer if it exists
                     if (timerId>0)
