Converting push sound model to SDL

Hello,

I have a vintage computer emulator that uses SDL video and linux audio, and
nearly synchronizes the two by setting the number of sound fragments to a low
value (3) and the fragment size to 256 or 512 samples. The audio samples are
produced continuously at the rate necessary to imitate the clock frequency of
the target and a buffer is given to write(2) as soon as it gets full. Double
buffering is used to This way the write syscalls block if the host CPU gets too
far ahead, and so far it has worked beautifully.

I would like to convert the audio systel to SDL. What is the right way to go?
Is there a code that wraps the SDL audio callback API into a “push model” a la
write syscall that blocks if the buffer is full?

Thanks,
Leo

Quoth Leo Broukhis , on 2005-06-23 19:26:33 +0000:

Hello,

[paragraph reformatted]

I would like to convert the audio systel to SDL. What is the right
way to go? Is there a code that wraps the SDL audio callback API
into a “push model” a la write syscall that blocks if the buffer is
full?

Perhaps have the callback read from a circular buffer? I believe the
Simple FIFO library http://olofson.net/mixed.html might be
beneficial here.

Thanks,
Leo

—> Drake Wilson
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20050623/971fa2c4/attachment.pgp

Drake Wilson <drake libcom.com> writes:

I would like to convert the audio systel to SDL. What is the right
way to go? Is there a code that wraps the SDL audio callback API
into a “push model” a la write syscall that blocks if the buffer is
full?

Perhaps have the callback read from a circular buffer? I believe the
Simple FIFO library http://olofson.net/mixed.html might be
beneficial here.

Thanks, but unlikely (for one, it does not have locking). My attempts to use SDL
audio and mutexes resulted either in underflows or in too much lag between a
keypress and a keyclick. It seems that except the sound buffer size there is no
way to control the playback parameters (namely, the number of yet unplayed
fragments downstream from the callback).

Moreover, what are the constraints on the callback function? How long can it run
before returning to avoid underflows?
May it use SDL video calls and have the event loop inside of it?

A possible solution would be to embed all of the emulator inside of the callback
function and return from it every time an audio buffer is full, but this is too
drastic and/or will not work if the audio system only calls the callback fn when
the audio has almost drained.

Regards,
Leo

Quoth Leo Broukhis , on 2005-06-23 23:08:36 +0000:

Drake Wilson <drake libcom.com> writes:

I would like to convert the audio systel to SDL. What is the right
way to go? Is there a code that wraps the SDL audio callback API
into a “push model” a la write syscall that blocks if the buffer is
full?

Perhaps have the callback read from a circular buffer? I believe the
Simple FIFO library http://olofson.net/mixed.html might be
beneficial here.

[paragraph reformatted]

Thanks, but unlikely (for one, it does not have locking). My
attempts to use SDL audio and mutexes resulted either in underflows
or in too much lag between a keypress and a keyclick. It seems that
except the sound buffer size there is no way to control the playback
parameters (namely, the number of yet unplayed fragments downstream
from the callback).

The latter is true – only more advanced audio APIs like the ALSA PCM
API have parameter control like that.

Re the first sentence, I’m not seeing the problem. If your audio
buffer underruns, you have no choice but to supply the audio device
with something – the DAC isn’t going to wait for you. If the host
CPU can’t keep up, then you’re dead already. Why is the lockless FIFO
then a problem?

—> Drake Wilson
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20050623/35e13037/attachment.pgp

If I’m understanding you correctly, you want to move from a “push the
sound bytes down the pipe” model to a callback model? If so, I
encountered and eventually solved (with a great amount of misery) the
exact same problems with Stella, the Atari 2600 emulator.

Originally, the sound processing was done in a separate sound server,
where updates were simply done with ‘write’ and using OSS. Later, the
code was converted to use SDL.

Have a look at the web repository on stella.sf.net. Specifically, look
for the old OSS sound code in ‘src/ui/sound/Attic/OSS.c’ and the new
code in ‘src/common/SoundSDL.cxx’. To be sure, there are some things
there that you can ignore, but it might give you some ideas on how to
proceed.

SteveOn June 23, 2005 08:38 pm, Leo Broukhis wrote:

Drake Wilson <drake libcom.com> writes:

I would like to convert the audio systel to SDL. What is the
right way to go? Is there a code that wraps the SDL audio
callback API into a “push model” a la write syscall that blocks
if the buffer is full?

Perhaps have the callback read from a circular buffer? I believe
the Simple FIFO library http://olofson.net/mixed.html might be
beneficial here.

Thanks, but unlikely (for one, it does not have locking). My attempts
to use SDL audio and mutexes resulted either in underflows or in too
much lag between a keypress and a keyclick. It seems that except the
sound buffer size there is no way to control the playback parameters
(namely, the number of yet unplayed fragments downstream from the
callback).

Moreover, what are the constraints on the callback function? How long
can it run before returning to avoid underflows?
May it use SDL video calls and have the event loop inside of it?

A possible solution would be to embed all of the emulator inside of
the callback function and return from it every time an audio buffer
is full, but this is too drastic and/or will not work if the audio
system only calls the callback fn when the audio has almost drained.

Stephen Anthony <stephena users.sourceforge.net> writes:

If I’m understanding you correctly, you want to move from a “push the
sound bytes down the pipe” model to a callback model? If so, I
encountered and eventually solved (with a great amount of misery) the
exact same problems with Stella, the Atari 2600 emulator.

Originally, the sound processing was done in a separate sound server,
where updates were simply done with ‘write’ and using OSS. Later, the
code was converted to use SDL.

Have a look at the web repository on stella.sf.net. Specifically, look
for the old OSS sound code in ‘src/ui/sound/Attic/OSS.c’ and the new
code in ‘src/common/SoundSDL.cxx’. To be sure, there are some things
there that you can ignore, but it might give you some ideas on how to
proceed.

Thanks a lot. As far as I can see from the CVS comments there are still
problems with matching the speed of the emulator to the speed of the original
Atari. In my emulator I never need to compute how much ahead I am and to call
SDL_Delay if the audio is enabled - the sound system does the speed matching for
me - this is what I’m trying to achieve in SDL. In your code you apparently
rely on some other means of slowing the emulator down.

Leo

Drake Wilson <drake libcom.com> writes:

Thanks, but unlikely (for one, it does not have locking). My
attempts to use SDL audio and mutexes resulted either in underflows
or in too much lag between a keypress and a keyclick. It seems that
except the sound buffer size there is no way to control the playback
parameters (namely, the number of yet unplayed fragments downstream
from the callback).

The latter is true – only more advanced audio APIs like the ALSA PCM
API have parameter control like that.

Re the first sentence, I’m not seeing the problem. If your audio
buffer underruns, you have no choice but to supply the audio device
with something – the DAC isn’t going to wait for you. If the host
CPU can’t keep up, then you’re dead already. Why is the lockless FIFO

The underflow problem could have been caused by thread interaction (without SDL
audio the CPU keeps up easily).

then a problem?

My goal is to have a single point where the host speed is brought down to the
target speed. Locking on the write to the audio buffer that drains with a fixed
speed in real time is, IMO, the best way to do it. Explicit calls to SDL_Delay
can be detrimental because the OSes do not guarantee real-time return.

Leo

Sorry, may be this question was here many time, but I’m newbie for SDL.
Is here anybody who link the SDL using VC++ Tollkit 2003?–
Best regards,

Andrei mail to: @Andrei_ABacus_Bondar

-====================================================-
Where a calculator on the ENIAC is equipped with
18 000 vacuum tubes and weighs 30 tons, computers of
the future may have only 1 000 vacuum tubes and
perhaps weigh 1.5 tons. – Popular Mechanics (1949)
-====================================================-

Sorry, may be this question was here many time, but I’m newbie for SDL.
Is here anybody who link the SDL using VC++ Tollkit 2003?

Me. And to make it more interesting, I do it from the Linux command line using WINE! So yes, works fine.

    --Gabriel

Gabriel wrote:

Sorry, may be this question was here many time, but I’m newbie for SDL.
Is here anybody who link the SDL using VC++ Tollkit 2003?

Me. And to make it more interesting, I do it from the Linux command line using WINE! So yes, works fine.
–Gabriel

And what about multi-threaded DLL linking which is lack in VC++ Toolkit?–
Best regards,

Andrei mail to: @Andrei_ABacus_Bondar

-====================================================-
Where a calculator on the ENIAC is equipped with
18 000 vacuum tubes and weighs 30 tons, computers of
the future may have only 1 000 vacuum tubes and
perhaps weigh 1.5 tons. – Popular Mechanics (1949)
-====================================================-

Yes, we sync everything to the video. So mainLoop() is called 60 times
per second, and expected to complete in less than 16.7 ms. The sound
just ‘tags along’. There’s still some video to audio lag, but if the
sound buffers are small enough it’s not really noticable.

We decided that having video and input be in sync, and audio slightly
’off’ was an acceptable solution.

I think z26 (another Atari emulator) has a ‘sync to sound’ option. But
it’s written in x86 assembly, so I don’t know how helpful it would be.

SteveOn June 23, 2005 11:24 pm, Leo Broukhis wrote:

Stephen Anthony <stephena users.sourceforge.net> writes:

If I’m understanding you correctly, you want to move from a “push
the sound bytes down the pipe” model to a callback model? If so, I
encountered and eventually solved (with a great amount of misery)
the exact same problems with Stella, the Atari 2600 emulator.
Thanks a lot. As far as I can see from the CVS comments there are
still problems with matching the speed of the emulator to the speed
of the original Atari. In my emulator I never need to compute how
much ahead I am and to call SDL_Delay if the audio is enabled - the
sound system does the speed matching for me - this is what I’m trying
to achieve in SDL. In your code you apparently rely on some other
means of slowing the emulator down.

Stephen Anthony <stephena users.sourceforge.net> writes:

Yes, we sync everything to the video. So mainLoop() is called 60 times
per second, and expected to complete in less than 16.7 ms. The sound
just ‘tags along’. There’s still some video to audio lag, but if the
sound buffers are small enough it’s not really noticable.

I see. What is specific to the computer I emulate is the bit-manipulated
speaker. Unlike the synthesizer chips that have no problem sustaining a wave
until the next command (that is, if the host CPU is too slow, the music will
play slo-o-owly as the callback will request as many filler bytes from the synth
emulator module as necessary), in my case any underrun results in a horrible
click and I have to avoid them at all costs.

I’ve finally solved my problem by introducing a semaphore which is posted by the
callback function and waited on instead of the write() syscall. In my previous
attempts I tried to follow the documentation to the letter and to avoid any SDL
calls from the callback by introducing an auxiliary thread and interlocking the
main thread and the aux thread with mutexes; it did not work well. It turned out
that calling SDL_SemPost from the callback is ok.

Thanks for the suggestions; it will be a great source of ideas,

Leo

El vie, 24-06-2005 a las 10:59 +0400, Andrei ‘ABacus’ Bondarenko
escribi?:

Sorry, may be this question was here many time, but I’m newbie for SDL.
Is here anybody who link the SDL using VC++ Tollkit 2003?

Me. And to make it more interesting, I do it from the Linux command line using WINE! So yes, works fine.

And what about multi-threaded DLL linking which is lack in VC++ Toolkit?

Apparently I’m not doing that, because everything works.

Wait. What do you mean by “anybody who link the SDL”? I thought you
meant linking TO SDL. Are you talking about compiling SDL itself? In
that case I don’t know, I never tried.

    --Gabriel