Open joedeller opened 6 years ago
Thanks for this bug report!
It seems to affect Windows only, since psutil.Process.num_handles()
only exists in Windows.
I currently don't have access to a Windows system, so I can't test it myself.
I think you should try to reproduce the problem using sd.OutputStream
instead of sd.play()
. It probably doesn't matter if any sound is played at all. You should try what num_handles()
returns after creating an OutputStream
and after calling start()
, stop()
and close()
on it.
It may matter, however, whether you use a callback function or not. You should try both cases.
You could then directly compare the behavior with PyAudio's behavior.
Importing sounddevice
automatically does initialize PortAudio, while in PyAudio you have to explicitly initialize it with
p = pyaudio.PyAudio()
Creating a pyaudio.Stream works similarly, but the arguments are somewhat different. You can then use start_stream(), stop_stream() and close().
p.terminate()
should do the same thing as sd._terminate()
.
If the behavior of num_handles()
is the same in both, this looks like a PortAudio bug.
If PyAudio doesn't show an increase in num_handles()
, this is probably a bug in CFFI or in how sounddevice
uses CFFI.
You should also check if PyAudio and the sounddevice
module use the same version of PortAudio.
Hi Matthias, thanks for getting back to me. I've done a quick test using OutputStream without playing any sound and the handle count does increase by one each time. I will look at the other scenarios and get back to you when I have a bit more time. I do have a workaround by using subprocess to launch my sound playing code as a separate python process, which cleans up after it exits, so there isn't a steady leak. It's a bit klunky but works for now.
Thanks, Joe
def play_stream(): print ("Pre create handles {}".format( ps.Process().num_handles())) time.sleep(.5) stream =sd.OutputStream() print ("Post create, pre start handles {}".format( ps.Process().num_handles())) time.sleep(0.5) stream.start() print ("Post start handles {}".format( ps.Process().num_handles())) time.sleep(0.5) stream.stop() print ("Post stop handles {}".format( ps.Process().num_handles()))
stream.close()
The handle count does climb Start handles = 311 handles before stream init 313 Post init, pre start stream 321 Post start stream 339 Post stop stream 322 After closing stream 316 handles before stream init 316 Post init, pre start stream 322 Post start stream 340 Post stop stream 323 After closing stream 317 handles before stream init 317 Post init, pre start stream 323 Post start stream 341 Post stop stream 324 After closing stream 318 handles before stream init 318 Post init, pre start stream 324 Post start stream 342 Post stop stream 325 After closing stream 319 handles before stream init 319 Post init, pre start stream 325 Post start stream 343 Post stop stream 326 After closing stream 320
On Sat, May 26, 2018 at 10:25 AM, Matthias Geier notifications@github.com wrote:
Thanks for this bug report!
It seems to affect Windows only, since psutil.Process.num_handles() only exists in Windows.
I currently don't have access to a Windows system, so I can't test it myself.
I think you should try to reproduce the problem using sd.OutputStream instead of sd.play(). It probably doesn't matter if any sound is played at all. You should try what num_handles() returns after creating an OutputStream and after calling start(), stop() and close() on it.
It may matter, however, whether you use a callback function or not. You should try both cases.
You could then directly compare the behavior with PyAudio's behavior.
Importing sounddevice automatically does initialize PortAudio, while in PyAudio you have to explicitly initialize it with
p = pyaudio.PyAudio()
Creating a pyaudio.Stream https://people.csail.mit.edu/hubert/pyaudio/docs/#class-stream works similarly, but the arguments are somewhat different. You can then use start_stream() https://people.csail.mit.edu/hubert/pyaudio/docs/#pyaudio.Stream.start_stream, stop_stream() https://people.csail.mit.edu/hubert/pyaudio/docs/#pyaudio.Stream.stop_stream and close() https://people.csail.mit.edu/hubert/pyaudio/docs/#pyaudio.Stream.close.
p.terminate() should do the same thing as sd._terminate().
If the behavior of num_handles() is the same in both, this looks like a PortAudio bug. If PyAudio doesn't show an increase in num_handles(), this is probably a bug in CFFI or in how sounddevice uses CFFI. You should also check if PyAudio and the sounddevice module use the same version of PortAudio.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/spatialaudio/python-sounddevice/issues/140#issuecomment-392249389, or mute the thread https://github.com/notifications/unsubscribe-auth/AD-qEmOv7H2Iae5PfSLmpk7S7Mr6tjCbks5t2R-hgaJpZM4UL3qp .
I have a long running script running python 3.6 32bit on windows (7 and 10, 64bit), using sounddevice sounddevice==0.3.11 It plays sine waves from a numpy array on a regular basis. However each time it does this, it creates two additional thread handles that persist after the sound has played. Whilst these are cleaned up when the python script ultimately exits, when it is running, I've seen the handle count go >20K, with the result that at various points in time the script just hangs, sometimes in sd.wait, sometimes in other parts of the script. Different systems seem to hang at different points, but generally as the python.exe handle count is in the thousands.
I've also noticed that
do the same thing, which is even more problematic for me as I have to call them just before I play a sound to ensure that the device and buffersize are correct, so I get at least 4 additional thread handles each time I play a sound.
I've got a cut down version of my script to show the problem. I appreciate that this may well be down in portaudio or another helper library.
I've had a quick dabble with PyAudio and it doesn't seem to suffer from the same problem, but it's a far less friendly library to use :-(
Regards,
Joe