[CentralOH] Async buffer generation

Neil Ludban nludban at columbus.rr.com
Sun Jun 19 12:38:38 EDT 2016

On Sun, 19 Jun 2016 11:53:49 -0400
Eric Floehr <eric at intellovations.com> wrote:
> I am using pyaudio to generate real-time audio. Pyaudio allows you to pass
> in a callback function so that it can request some amount of audio bytes to
> play.
> Here is an example of a callback function that generates random noise:
> def generate_samples(in_data, frame_count, time_info, status_flags):
>     out_data = b""
>     for _ in range(frame_count):
>         out_data += pack('h', int((round(random.random() * VOLRANGE) +
>     return out_data, pyaudio.paContinue
> The only thing I care about is "frame_count" which is the requested number
> of audio bytes to return.
> The generation/creation of those audio bytes is occurring synchronously in
> the callback however. What I'd really like to do is generate the audio
> bytes asynchronously and then just have the callback just drain however
> much of the buffer is requested.
> I've been going through Python asyncio tutorials but haven't groked this
> use-case (most of the tutorials are network/HTTP/etc. based and I know its
> the same concept but it's different enough that I haven't been able to
> latch on to how to do it in my case).
> Any thoughts on how I could do this with Python 3.5's ayncio?
> Thanks!
> Eric


The constructor accepts a maxsize argument, the put and get methods
are awaitable and block when the queue is full/empty.

I thought I once saw thread safe synchronization docs, but can't
find it now.  My best suggestion at the moment is for the audio
callback to schedule a task with call_soon_threadsafe, then sleep
on a condition.  The task pulls one item from the asyncio queue,
puts it somewhere for the callback thread, then notifies the condition.
If it's not already obvious that this a bad way to mix i/o tasks with
cpu tasks, it will be a good learning experience...

More information about the CentralOH mailing list