SDL_QueueAudio()

As of tonight in Mercurial, you can now “push” audio to an SDL audio
device instead of using a callback.

Open the audio device like you normally would, but specify a NULL
callback (this would previously cause SDL_OpenAudio*() to fail
unconditionally).

Then you may call:

SDL_QueueAudio(myDeviceId, myAudioData, numberOfBytes);

Queue as much or little as you want, SDL will drain it to the audio
device as necessary. If you provide too little, SDL will feed silence to
the device until you queue more data.

To see how much is waiting to be fed to the device still:

bytesRemaining = SDL_GetQueuedAudioSize(myDeviceId);

Between these two calls, you can manage the audio device without the
control inversion inherent in the usual callback system. This new API is
built on top of the old one (internally, SDL provides its own callback
to feed from data you have queued), but might be simpler to use, and
easier to wrap one’s head around…and since it doesn’t need to operate
in a separate thread, one doesn’t have to think about locking at the
application level.

The patch (with the documentation in SDL_audio.h) is here:

 https://hg.libsdl.org/SDL/rev/aa058c87737b

–ryan.

This is great. Two nitpicks I can think of:

  • SDL_QueueAudio could go crazy with the mallocs depending on what the user
    is doing with it…an alternative I thought of is having it return the
    number of bytes that got accepted into the queue, thus letting know the app
    that it needs to hold on to the remainder for now. In this way the audio
    queue could be fixed size.
  • With this current model, SDL_QueueAudio could return the value
    for SDL_GetQueuedAudioSize providing everything’s that needed with one
    function call.

2014-07-27 1:25 GMT-03:00 Ryan C. Gordon :>

As of tonight in Mercurial, you can now “push” audio to an SDL audio
device instead of using a callback.

Open the audio device like you normally would, but specify a NULL callback
(this would previously cause SDL_OpenAudio*() to fail unconditionally).

Then you may call:

SDL_QueueAudio(myDeviceId, myAudioData, numberOfBytes);

Queue as much or little as you want, SDL will drain it to the audio device
as necessary. If you provide too little, SDL will feed silence to the
device until you queue more data.

To see how much is waiting to be fed to the device still:

bytesRemaining = SDL_GetQueuedAudioSize(myDeviceId);

Between these two calls, you can manage the audio device without the
control inversion inherent in the usual callback system. This new API is
built on top of the old one (internally, SDL provides its own callback to
feed from data you have queued), but might be simpler to use, and easier to
wrap one’s head around…and since it doesn’t need to operate in a separate
thread, one doesn’t have to think about locking at the application level.

The patch (with the documentation in SDL_audio.h) is here:

https://hg.libsdl.org/SDL/rev/aa058c87737b

–ryan.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Gabriel.

Part of the point of the API is that the user knows all of the audio is
queued and doesn’t have to do additional bookkeeping (unless it wants to),
so returning partially queued data isn’t desirable here.

Also, it’s much clearer what’s going on with QueueAudio() and
GetQueuedAudioSize() as two separate APIs.On Sun, Jul 27, 2014 at 8:06 AM, Gabriel Jacobo wrote:

This is great. Two nitpicks I can think of:

  • SDL_QueueAudio could go crazy with the mallocs depending on what the
    user is doing with it…an alternative I thought of is having it return the
    number of bytes that got accepted into the queue, thus letting know the app
    that it needs to hold on to the remainder for now. In this way the audio
    queue could be fixed size.
  • With this current model, SDL_QueueAudio could return the value
    for SDL_GetQueuedAudioSize providing everything’s that needed with one
    function call.

2014-07-27 1:25 GMT-03:00 Ryan C. Gordon :

As of tonight in Mercurial, you can now “push” audio to an SDL audio
device instead of using a callback.

Open the audio device like you normally would, but specify a NULL
callback (this would previously cause SDL_OpenAudio*() to fail
unconditionally).

Then you may call:

SDL_QueueAudio(myDeviceId, myAudioData, numberOfBytes);

Queue as much or little as you want, SDL will drain it to the audio
device as necessary. If you provide too little, SDL will feed silence to
the device until you queue more data.

To see how much is waiting to be fed to the device still:

bytesRemaining = SDL_GetQueuedAudioSize(myDeviceId);

Between these two calls, you can manage the audio device without the
control inversion inherent in the usual callback system. This new API is
built on top of the old one (internally, SDL provides its own callback to
feed from data you have queued), but might be simpler to use, and easier to
wrap one’s head around…and since it doesn’t need to operate in a separate
thread, one doesn’t have to think about locking at the application level.

The patch (with the documentation in SDL_audio.h) is here:

https://hg.libsdl.org/SDL/rev/aa058c87737b

–ryan.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Gabriel.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

  • SDL_QueueAudio could go crazy with the mallocs depending on what the user is doing with it…an alternative I thought of is having it return the number of bytes that got accepted into the queue, thus letting know the app that it needs to hold on to the remainder for now. In this way the audio queue could be fixed size.

I think most things that want to push would already be concerned with latency well before memory usage became a serious issue, but I also wanted this to work for things that just want to dump a whole wave file to the hardware in one shot. I absolutely don’t want apps to have to manage buffer size with this API in any case, as that’s just an implementation concern. I definitely don’t want them to manage half a buffer that couldn’t be queued yet.

We probably could have the allocation pool shrink if they aren’t used for awhile, but my guess is most apps don’t use much, and the ones that do will use it the whole time anyhow.

  • With this current model, SDL_QueueAudio could return the value for SDL_GetQueuedAudioSize providing everything’s that needed with one function call.

I’m not a fan of overloading functions just to reduce entry points. Conceptually, querying and queuing are two separate actions, one happening more often and being used to make decisions about the other. (And while it isn’t the case at the moment, I’d like the query to not hold a mutex.)

Notably: an app might have to decide what to generate based on how much is queued, as opposed to having data already and pushing more when it’s time. In this scenario, having these actions separated is useful.

–ryan.

I really like this idea, and I’m glad it was implemented. The current callback system requires some hackery if your audio frame size is not a power of two.