diff --git a/doc/scapy/installation.rst b/doc/scapy/installation.rst
index ac5ab68bf76f8fed5cae380346e6f12d78da1e71..df184ca496c4765b8d932deba816df357f51aeab 100644
--- a/doc/scapy/installation.rst
+++ b/doc/scapy/installation.rst
@@ -472,7 +472,6 @@ Known bugs
 
  * You may not be able to capture WLAN traffic on Windows. Reasons are explained on the Wireshark wiki and in the WinPcap FAQ. Try switching off promiscuous mode with ``conf.sniff_promisc=False``.
  * Packets sometimes cannot be sent to localhost (or local IP addresses on your own host).
- * The ``voip_play()`` functions do not work because they output the sound via ``/dev/dsp`` which is not available on Windows. 
  
 
 Build the documentation offline
diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py
index 5329cafe4a44327313d7cb89220916408438cd2a..fe5cd4350b63078686ac8ef641b81887bbbe80b0 100755
--- a/scapy/arch/windows/__init__.py
+++ b/scapy/arch/windows/__init__.py
@@ -188,9 +188,7 @@ def _where(filename, dirs=None, env="PATH"):
     for path in paths:
         for match in glob(os.path.join(path, filename)):
             if match:
-                p_match = os.path.normpath(match)
-                if os.path.isfile(p_match):
-                    return p_match
+                return os.path.normpath(match)
     raise IOError("File not found: %s" % filename)
 
 def win_find_exe(filename, installsubdir=None, env="ProgramFiles"):
@@ -251,6 +249,8 @@ class WinProgPath(ConfClass):
 conf.prog = WinProgPath()
 if conf.prog.powershell == "powershell":
     conf.prog.powershell = None
+if conf.prog.sox == "sox":
+    conf.prog.sox = None
 
 class PcapNameNotFoundError(Scapy_Exception):
     pass    
diff --git a/scapy/modules/voip.py b/scapy/modules/voip.py
index 52c7893daee017d738e8f6c076df6122ab2e8d3b..53036a7899b7782e9c1fceee47377da6b652aeed 100644
--- a/scapy/modules/voip.py
+++ b/scapy/modules/voip.py
@@ -9,138 +9,141 @@ VoIP (Voice over IP) related functions
 
 import os
 ###################
-## Testing stuff ##
+##  Listen VoIP  ##
 ###################
 
-from fcntl import fcntl
 from scapy.sendrecv import sniff
 from scapy.layers.inet import IP,UDP
 from scapy.layers.rtp import RTP
-from scapy.utils import get_temp_file
+from scapy.consts import WINDOWS
+from scapy.config import conf
 
 
-def merge(x,y,sample_size=2):
-    if len(x) > len(y):
-        y += "\x00"*(len(x)-len(y))
-    elif len(x) < len(y):
-        x += "\x00"*(len(y)-len(x))
+sox_base = "sox -t .ul %s - -t ossdsp /dev/dsp"
+
+if WINDOWS:
+    if conf.prog.sox is None:
+        raise OSError("Sox must be installed to play VoIP packets")
+    finally:
+        if p_test:
+            p_test.terminate()
+    sox_base = "\"" + conf.prog.sox + "\" -t .ul %s - -t waveaudio"
+
+def _merge_sound_bytes(x,y,sample_size=2):
+    # TODO: find a better way to merge sound bytes
+    # This will only add them one next to each other:
+    # \xff + \xff ==> \xff\xff
     m = ""
     ss=sample_size
-    for i in xrange(len(x)/ss):
+    min_ = 0
+    if len(x) >= len(y):
+        min_ = y
+    elif len(x) < len(y):
+        min_ = x
+    r_ = len(min_)
+    for i in xrange(r_/ss):
         m += x[ss*i:ss*(i+1)]+y[ss*i:ss*(i+1)]
-    return  m
-#    return  "".join(map(str.__add__, x, y))
+    return x[r_:], y[r_:], m
 
 
-def voip_play(s1,list=None,**kargs):
-    FIFO=get_temp_file()
-    FIFO1=FIFO % 1
-    FIFO2=FIFO % 2
-    
-    os.mkfifo(FIFO1)
-    os.mkfifo(FIFO2)
-    try:
-        os.system("soxmix -t .ul %s -t .ul %s -t ossdsp /dev/dsp &" % (FIFO1,FIFO2))
-        
-        c1=open(FIFO1,"w", 4096)
-        c2=open(FIFO2,"w", 4096)
-        fcntl.fcntl(c1.fileno(),fcntl.F_SETFL, os.O_NONBLOCK)
-        fcntl.fcntl(c2.fileno(),fcntl.F_SETFL, os.O_NONBLOCK)
-    
-    #    dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp")
-        def play(pkt, last=None):
-            if last is None:
-                last = []
-            if not pkt:
-                return 
-            if not pkt.haslayer(UDP):
-                return 
-            ip=pkt.getlayer(IP)
-            if s1 in [ip.src, ip.dst]:
-                if not last:
-                    last.append(pkt)
-                    return
-                load=last.pop()
-    #            x1 = load.load[12:]
-                c1.write(load.load[12:])
-                if load.getlayer(IP).src == ip.src:
-    #                x2 = ""
-                    c2.write("\x00"*len(load.load[12:]))
-                    last.append(pkt)
-                else:
-    #                x2 = pkt.load[:12]
-                    c2.write(pkt.load[12:])
-    #            dsp.write(merge(x1,x2))
+def voip_play(s1, lst=None, **kargs):
+    """Play VoIP packets with RAW data that
+    are either sniffed either from an IP, or
+    specified as a list.
+
+    It will play only the incoming packets !
     
-        if list is None:
-            sniff(store=0, prn=play, **kargs)
-        else:
-            for p in list:
-                play(p)
-    finally:
-        os.unlink(FIFO1)
-        os.unlink(FIFO2)
+    :param s1: The IP of the src of all VoIP packets.
+    :param lst: (optional) A list of packets to load
+    :type s1: string
+    :type lst: list
+
+    :Example:
 
+    >>> voip_play("64.2.142.189")
+    while calling '411@ideasip.com'
 
+    >>> voip_play("64.2.142.189", lst)
+    with list a list of packets with VoIP data
+    in their RAW layer
 
-def voip_play1(s1,list=None,**kargs):
+    .. seealso:: voip_play2
+    to play both the outcoming and incoming packets
+    at the same time.
 
+    .. seealso:: voip_play3
+    to read RTP VoIP packets
+    """
     
-    dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp")
+    dsp, rd = os.popen2(sox_base % "")
     def play(pkt):
         if not pkt:
             return 
-        if not pkt.haslayer(UDP):
+        if not pkt.haslayer(UDP) or not pkt.haslayer(IP):
             return 
         ip=pkt.getlayer(IP)
-        if s1 in [ip.src, ip.dst]:
-            from scapy.config import conf
+        if s1 == ip.src:
             dsp.write(pkt.getlayer(conf.raw_layer).load[12:])
     try:
-        if list is None:
+        if lst is None:
             sniff(store=0, prn=play, **kargs)
         else:
-            for p in list:
+            for p in lst:
                 play(p)
     finally:
         dsp.close()
         rd.close()
 
+def voip_play1(s1, lst=None, **kargs):
+    """Same than voip_play, backward compatibility
+    """
+    return voip_play(s1, lst, **kargs)
+
 def voip_play2(s1,**kargs):
-    dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp")
-    def play(pkt, last=None):
-        if last is None:
-            last = []
+    """
+    Same than voip_play, but will play
+    both incoming and outcoming packets.
+    The sound will surely suffer distortion.
+
+    Only supports sniffing.
+
+    .. seealso:: voip_play
+    to play only incoming packets.
+    """
+    dsp,rd = os.popen2(sox_base % "-c 2")
+    global x1, x2
+    x1 = ""
+    x2 = ""
+    def play(pkt):
+        global x1, x2
         if not pkt:
             return 
-        if not pkt.haslayer(UDP):
+        if not pkt.haslayer(UDP) or not pkt.haslayer(IP):
             return 
         ip=pkt.getlayer(IP)
         if s1 in [ip.src, ip.dst]:
-            if not last:
-                last.append(pkt)
-                return
-            load=last.pop()
-            x1 = load.load[12:]
-#            c1.write(load.load[12:])
-            if load.getlayer(IP).src == ip.src:
-                x2 = ""
-#                c2.write("\x00"*len(load.load[12:]))
-                last.append(pkt)
+            if ip.dst == s1:
+                x1 += pkt.getlayer(conf.raw_layer).load[12:]
             else:
-                x2 = pkt.load[:12]
-#                c2.write(pkt.load[12:])
-            dsp.write(merge(x1,x2))
+                x2 += pkt.getlayer(conf.raw_layer).load[12:]
+            x1, x2, r = _merge_sound_bytes(x1, x2)
+            dsp.write(r)
             
     sniff(store=0, prn=play, **kargs)
 
 def voip_play3(lst=None,**kargs):
-    dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp")
+    """Same than voip_play, but made to
+    read and play VoIP RTP packets, without
+    checking IP.
+    
+    .. seealso:: voip_play
+    for basic VoIP packets
+    """
+    dsp,rd = os.popen2(sox_base % "")
+    def play(pkt, dsp=dsp):
+        if pkt and pkt.haslayer(UDP) and pkt.haslayer(RTP):
+            dsp.write(pkt.getlayer(RTP).load)
     try:
-        def play(pkt, dsp=dsp):
-            from scapy.config import conf
-            if pkt and pkt.haslayer(UDP) and pkt.haslayer(conf.raw_layer):
-                dsp.write(pkt.getlayer(RTP).load)
         if lst is None:
             sniff(store=0, prn=play, **kargs)
         else: