Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve usage of the sounddevice module #9

Open
mgeier opened this issue Sep 14, 2018 · 1 comment
Open

Improve usage of the sounddevice module #9

mgeier opened this issue Sep 14, 2018 · 1 comment
Assignees

Comments

@mgeier
Copy link

mgeier commented Sep 14, 2018

Sorry for spamming here, I wanted to comment on https://www.swharden.com/wp/2016-07-19-realtime-audio-visualization-in-python/ but I couldn't manage to comment over there ...

You are showing this code snippet:

import sounddevice #pip install sounddevice

for i in range(30): #30 updates in 1 second
    rec = sounddevice.rec(44100/30)
    sounddevice.wait()
    print(rec.shape)

The function sounddevice.rec() is really not meant to be used repeatedly in quick succession.
It's really just a high-level wrapper for the case where you want to record one piece of audio and you know the duration beforehand. It's no wonder that it creates glitches if you use it like in your example, because for each call a new "stream" object is created, audio processing is started, then the (very short) recording is done, audio processing is stopped and the "stream" object is destroyed. Just to create a new "stream" object an instance later ...

Since you are using stream.read() from PyAudio, you could as well use stream.read() from the sounddevice module: https://python-sounddevice.readthedocs.io/en/latest/api.html#sounddevice.Stream.read.
This uses the exact same underlying PortAudio function call, it just does the conversion to a NumPy array internally without you having to worry about it.

This should take about the same amount of resources than PyAudio (only a bit more for the very little overhead of CFFI calls in Python code, probably not really measurable).
And it should definitely not produce any glitches (given that the same block size and latency settings are used as in PyAudio).

As a (not necessarily better) alternative to using stream.read() you can also implement your own callback function (as you could also do in PyAudio, but again the NumPy array conversion is done for you). I've provided an example program for recordings where the duration is not known in advance: https://github.com/spatialaudio/python-sounddevice/blob/master/examples/rec_unlimited.py.

BTW, I'm the author of the sounddevice module, in case you didn't know.

@swharden
Copy link
Owner

@mgeier, thank you for your insightful suggestions! I've been wanting to come back and re-vamp this repository for some time, and this ticket has motivated me to get started sooner than later.

I will study the topics you raised over the next few days. Unfortunately (due to my tendency to copy/paste code) I know the poor method of opening/closing the sound stream is in numerous code examples on my website. I'll produce minimal-case examples demonstrating a few of the ways to continuously capture data from the sound card using methods you mentioned here, and will search through my website and add links to the new examples wherever the inferior method was used.

I'll leave this ticket open until these examples are ready and the QT audio monitor uses one of these improved methods.

Thanks for the ticket, and thanks for sounddevice!

@swharden swharden changed the title Usage of the sounddevice module Improve usage of the sounddevice module Sep 29, 2018
@swharden swharden self-assigned this Sep 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants