Closed jeremygray closed 7 years ago
This is a very interesting idea! I am a little concerned that using the callback interface might use more performance than necessary. If I understand this correctly, it is sufficient to play tiny fragments of audio every few seconds, right? It might be easier/more efficient to start a Python thread that does just that.
That said, we are planning to focus our attention on PySoundCard after the next release of PySoundFile. We are thinking about some high-level classes like the one you just built. If you have more ideas like this, we would be very interested in them. Here are some ideas: https://github.com/bastibe/PySoundCard/wiki/High-Level-API
In theory, I think playing a very short snippet of silence every ~20 sec should work. I'll try it out!
I'll check out the high-level class proposal, and will let you guys know if I have anything to add.
Feel free to directly add to the Wiki page. If you think the page becomes too long, just create a new one.
Your KeepAwake
class looks much more like a work-around than a real solution.
I don't really feel comfortable adding such a thing to PySoundCard.
I think a real solution would be to create a possibility to open a long-running stream and then, during its runtime, call functions to immediately play NumPy arrays. If no array is active, only zeros would be generated, just like in your proposal. This would probably also allow to play several sounds at the same time. It might also allow to queue sounds to be played back in succession to other sounds.
There should also be an option to trade off latency against jitter.
Anyway, a proposal for such functionality should be made in the above-mentioned Wiki page.
Wouldn't this basically do what you want?
import pysoundcard as pa
def callback(in_data, out_data, time_info, status):
out_data.fill(0)
return pa.continue_flag
keep_awake = pa.Stream(input_device=False, callback=callback)
keep_awake.start()
# do something completely different here
keep_awake.stop()
Great discussion. I'll leave the pull request open or close as you prefer -- the code is not ready to be pulled in, obviously.
I like the idea of a long-running stream that is playing something actively or is playing zeroes (perhaps zeros only intermittently, every 20s or so), and you can add to that stream, schedule something to start playing at a certain time, etc. That seems useful for other reasons, and would take care of this issue as well. It is also more work than the work-around solution -- and I just saw the very latest code in the comments here, looks nice (have not tried it). It would be easier for users if they only needed one line of code instead of 6 lines to defeat the nuisance (power-saving) behavior of Mac soundcards. Or perhaps ideally it would be enabled by default, and people could instead opt to turn it off if they needed the additional performance.... ok, I'll add things to the wiki!
There is a related question on the PortAudio mailing list: http://music.columbia.edu/pipermail/portaudio/2014-November/016360.html
This may also be related: http://music.columbia.edu/pipermail/portaudio/2014-September/016323.html
Idea: Play continuous silence in a concurrent Stream in a new thread to avoid latency if only use sound intermittently. Otherwise there can be ~0.5s latency to wake-up or restart something (soundcard hardware?), esp on Mac and maybe other laptops.