[CentralOH] Async buffer generation

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


On Sun, 19 Jun 2016 12:38:38 -0400
Neil Ludban <nludban at columbus.rr.com> wrote:
> 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) +
> > MINVOL)))
> >     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
> 
> https://docs.python.org/3/library/asyncio-queue.html
> 
> 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...


Hidden on the last web page:

https://docs.python.org/3/library/asyncio-dev.html#concurrency-and-multithreading

Replace what I said earlier with run_couroutine_threadsafe and
future.result().


More information about the CentralOH mailing list