Problem with mp3 playback using SDL_mixer and SMPeg.dll

Hi,

I had similar problems with MP3 playback using SDL_mixer and SMPeg.dll

I wrote about this using this SDL mailing list, and other more experienced
SDL users told me that playing MP3s using SLD_mixer and SMPeg.dll is broken and
should not be used.

My recommendation to you is to convert the MP3s to OGG files and play these
music files using SDL_mixer only.

Again, MP3 playback with SMPeg.dll is broken.

Jesse
SLNTHERO at AOL.com (mailto:SLNTHERO at AOL.com)
http://www.SilentHeroProductions.com (http://www.SilentHeroProductions.com)

Sorry, misunderstood your request!

Happy Holidays!

Would say Merry Chistmas, but you might sue me :slight_smile:

Jesse
SLNTHERO at AOL.com (mailto:SLNTHERO at AOL.com)
http://www.SilentHeroProductions.com (http://www.SilentHeroProductions.com)

In a message dated 12/26/2006 6:07:25 P.M. Eastern Standard Time,
karx11erx at hotmail.com writes:

SIntHero,

you’re reply is uncalled for. I was asking for advice where
to look for the problem._______________________________________________
SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

I’d rather sue you for not saying Merry Christmas … :wink:

Merry Christmas and a happy new year to you, too. :slight_smile:

Btw, I think I have found the reason for the bug. SDL_mixer first starts the
music, then sets the playback position to the start. For mp3, this means that a
few threads are created, deleted and recreated very quickly. SDL or Windows do
not seem to like that.

Implausible. More likely is that the threads are not being taken down properly.

After I had temporarily disabled the positioning call, the problem was gone.

Excellent proof of absence! And good call getting rid of that
ornamental positioning call!

Another flaw was located in [smpeg]MPEGaudio.cpp, where
MPEGaudio::StopDecoding() calls SDL_WaitThread(). SDL_KillThread() is safer.

Right, it’s opposites day. Here we call it Boxing Day, anyone know why?

RF> From: karx11erx

Btw, I think I have found the reason for the bug. SDL_mixer first starts the
music, then sets the playback position to the start. For mp3, this means that a
few threads are created, deleted and recreated very quickly. SDL or Windows do
not seem to like that. After I had temporarily disabled the positioning call,
the problem was gone.

I’ll take a look at these changes soon and see about getting them into
smpeg.

Thanks!

–ryan.

Fistman,

Him? Never listen to that guy. He’s a jerk.

However he does worry when folks assert that killing a thread
is safer than convincing it to exit of natural causes. Poor fellow
had a difficult childhood - they used to whip him with threads.

[…]

Btw, another problem were Windows project settings. The library should be set to
’multithreaded DLL’, not just ‘multithreaded’. Inconsistencies in this setting
through a project (i.e. smpeg settings this way, main program settings that way)
are likely to result in smpeg not functioning properly.

This is true. The dll part means, at the very least, that you
get a single allocator and the ability to allocate mem in one component
and free it in another. (Heady stuff!) Anyway, that’s what using the debug
version of “multithreaded/non dll” lead me to believe, with its handy asserts.

[…]

Actually, the entire SDL and SDL_mixer sound handling is crap. You have one
global setting for frequency etc. - no chance to mix sounds and music if they
are sampled with different frequencies unless you resample one of them (which I
had to implement in my case :-/). Why the heck global variables instead of
encapsuled sound objects operating separately from each other?

Beats me. I did my own mixer for SDL and it’s crap too. One of the reasons that
it’s crap is that it queues up sounds by modifying a pointer without
any synchronisation (ha! storing a pointer is “atomic”, what could go wrong!?),
which of course won’t work on the increasingly common non-uniprocessor machines.
Can I use the SDL thread synchronisation functions in the sound callback?
Or is the sound callback not always a thread?

RF> From: karx11erx

Fistman,

Him? Never listen to that guy. He’s a jerk.

However he does worry when folks assert that killing a thread
is safer than convincing it to exit of natural causes. Poor fellow
had a difficult childhood - they used to whip him with threads.

Well, whether or not this guy is a jerk, I have to agree on this
point: Killing a thread is really a last resort thing, if all else
fails.

If you’re worried about getting out of sync, ending up waiting for
ever, tell the thread to finish it’s work, and then wait with a
timeout. If it times out instead of finishing, kill it, and hope for
the best. (And don’t forget to do the cleaning up that the thread was
supposed to do…!)

[…]

Beats me. I did my own mixer for SDL and it’s crap too. One of the
reasons that it’s crap is that it queues up sounds by modifying a
pointer without any synchronisation (ha! storing a pointer
is “atomic”, what could go wrong!?), which of course won’t work on
the increasingly common non-uniprocessor machines.

You can’t even count on a 32 bit integer access being atomic in a 32
bit system, in some extreme cases…

Can I use the SDL thread synchronisation functions in the sound
callback?
Or is the sound callback not always a thread?

On Mac OS Classic and maybe some other platform, the callback runs in
some kind of interrupt context. The sync functions might still
work, though; not sure about that…

However, if you just want the simplest possible locking/unlocking, to
safely mess around with the sound engine data from the main thread,
you can use the SDL_LockAudio() and SDL_UnlockAudio() calls.

Another approach is to use a lock-free FIFO or similar construct to
pass commands from the main thread to the audio callback. This may be
a better idea if you send lots of “sound commands” from all over the
place. (Not sure if abusing the SDL_(Un)LockAudio() calls that way is
a good idea, though it’s probably not a problem for “normal use”.)

A hybrid approach would be to enqueue sound commands in a linked list
or other simple, non thread safe structure, and then execute them all
once per game logic cycle or something, with the audio callback
locked.

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Friday 29 December 2006 23:05, Rhythmic Fistman wrote:

From: karx11erx

Message: 6

On Mac OS Classic and maybe some other platform, the callback runs in
some kind of interrupt context. The sync functions might still
work, though; not sure about that…

Only if they’re nops. It’s kinda hard to deschedule an interrupt.

However, if you just want the simplest possible locking/unlocking, to
safely mess around with the sound engine data from the main thread,
you can use the SDL_LockAudio() and SDL_UnlockAudio() calls.

Thank you, that’s exactly what I’m looking for.

Another approach is to use a lock-free FIFO or similar construct to
pass commands from the main thread to the audio callback. This may be
a better idea if you send lots of “sound commands” from all over the
place. (Not sure if abusing the SDL_(Un)LockAudio() calls that way is
a good idea, though it’s probably not a problem for “normal use”.)

Normal use here, main thread enqueues and sound callback dequeues.> From: David Olofson

Message: 6

On Mac OS Classic and maybe some other platform, the callback runs
in
some kind of interrupt context. The sync functions might still
work, though; not sure about that…

Only if they’re nops. It’s kinda hard to deschedule an interrupt.

Yeah, you’ve got a point there… :smiley:

So, the answer has to be no. The best you can do is check whether or
not a lock is held, and act accordingly - but that’s a different
design entirely.

However, if you just want the simplest possible locking/unlocking,
to safely mess around with the sound engine data from the main
thread,
you can use the SDL_LockAudio() and SDL_UnlockAudio() calls.

Thank you, that’s exactly what I’m looking for.

…and BTW, it should do what you expect on Mac OS Classic as well.
(If SDL audio is locked when the Sound Manager callback fires, the
mixing is done by SDL_UnlockAudio() instead.)

[…]

Normal use here, main thread enqueues and sound callback dequeues.

I’m just thinking number of lock/unlock cycles per second… (One per
command, unless it’s somehow centralized in the main thread.)

Can’t see why these calls would be incredibly expensive on any
platform, though.

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Saturday 30 December 2006 23:47, Rhythmic Fistman wrote:

From: David Olofson <@David_Olofson>

However he does worry when folks assert that killing a thread
is safer than convincing it to exit of natural causes. Poor fellow
had a difficult childhood - they used to whip him with threads.

Child abuse aside, forcefully killing a thread is a bad idea. It’s not
portable, it’s inelegant, and it leaves many systems in undefined
states. If you have to kill a thread, your program is probably trying to
recover from a deadlock bug. Better to just crash at this point and fix
the bug. :slight_smile:

Also, SDL_KillThread() will be a no-op in 1.3:
http://bugzilla.libsdl.org/show_bug.cgi?id=205

Can I use the SDL thread synchronisation functions in the sound callback?
Or is the sound callback not always a thread?

It’s not always a thread (it’s a hardware interrupt on Mac OS 9 and
other legacy/embedded systems), or it might not be a thread we
explicitly created (depending on the backend API). This is why there is
an SDL_LockAudio() call that is separate from the regular thread
primitives, and it works even on systems that don’t offer threads like
Mac OS 9.

You can assume you already hold the SDL_LockAudio() lock when your
callback starts running, and your callback won’t run while something
else holds the lock.

–ryan.

Only if they’re nops. It’s kinda hard to deschedule an interrupt.

Yeah, you’ve got a point there… :smiley:

So, the answer has to be no. The best you can do is check whether or
not a lock is held, and act accordingly - but that’s a different
design entirely.

On Mac OS 9, SDL returns immediately from the hardware interrupt if
audio lock is held, and will fill two buffers on the next interrupt
instead of one…as long as you don’t hold the audio lock for a really
long time, this actually works fine on this platform. If you hold it too
long, you’ll get an audio skip, but that’s true on any platform.

Like any other lock, don’t hold it for longer than you have to…just
twiddle some pointers and get out of there, having done the heavy
lifting before calling LockAudio.

–ryan.