SDL_mixer question

Hello all,

I’ve recently started looking at SDL_mixer stuff and I have some
questions…

The docs mention that “music is not played on a normal mixer channel”.

Q1)
Does that mean I can only have 1 “music” playing at any one time?
i.e. I can only do Mix_LoadMUS and Mix_PlayMusic for a single file…
If I need to play a different music file, I need to Mix_HaltMusic and
Mix_FreeMusic, and then start over (with load and play)

Q2)
Assuming I have my background music playing…say I need to play some SFX at
the same time…
Is this done using the Mix_LoadWAV and then the Channel family of functions
(i.e. Mix_AllocateChannels, Mix_PlayChannel, etc.)?

Q3)
I’m guessing to start off with I don’t need to worry about effects, right?
I can just use the build-in processors for now (if needed).

thx in advance,
K.

Hello Kostas,

Thursday, January 4, 2007, 4:32:56 PM, you wrote:

Hello all,

I’ve recently started looking at SDL_mixer stuff and I have some
questions…

The docs mention that “music is not played on a normal mixer channel”.

Q1)
Does that mean I can only have 1 “music” playing at any one time?
i.e. I can only do Mix_LoadMUS and Mix_PlayMusic for a single file…
If I need to play a different music file, I need to Mix_HaltMusic and
Mix_FreeMusic, and then start over (with load and play)

Yes

Q2)
Assuming I have my background music playing…say I need to play some SFX at
the same time…
Is this done using the Mix_LoadWAV and then the Channel family of functions
(i.e. Mix_AllocateChannels, Mix_PlayChannel, etc.)?

Yes

Q3)
I’m guessing to start off with I don’t need to worry about effects, right?
I can just use the build-in processors for now (if needed).

Yes :)–
Best regards,
Peter mailto:@Peter_Mulholland

Q1)
Does that mean I can only have 1 “music” playing at any one time?

Yes.

If I had a time machine, I’d go back and beg someone to call this
’channel’ something other than “music” … maybe “streamed”.

Assuming I have my background music playing…say I need to play some
SFX at the same time…
Is this done using the Mix_LoadWAV and then the Channel family of
functions (i.e. Mix_AllocateChannels, Mix_PlayChannel, etc.)?

Yes. The other channels are things that can be trivially decoded into an
uncompressed PCM waveform all at once, like a small .wav file for a
gunshot sound.

I’m guessing to start off with I don’t need to worry about effects, right?
I can just use the build-in processors for now (if needed).

Effects can be totally avoided unless you want to do something hardcore
and complex…they require you not only to operate on the waveform
directly, but handle every strange case of data format and channel count
and frequency. Avoid this API unless you have a desperate need and
really know what you’re doing at a lowlevel.

There are a few built-in effects that might be useful to you, and almost
everything else you need is just mixing some explosions with a
soundtrack as you go (which can be done with the basic SDL_mixer APIs,
completely ignoring the effects stuff).

–ryan.

Cool…thx for the replies Peter and Ryan!

I’m guessing the same principle of “don’t adjust the volume while fading is
in progress” applies to both chunk/channel stuff and music, right?

Cheers,
Kos> ----- Original Message -----

From: sdl-bounces+kos=climaxgroup.com@libsdl.org
[mailto:sdl-bounces+kos=climaxgroup.com at libsdl.org] On Behalf Of Ryan C.
Gordon
Sent: 05 January 2007 01:39
To: A list for developers using the SDL library. (includes SDL-announce)
Subject: Re: [SDL] SDL_mixer question

Q1)
Does that mean I can only have 1 “music” playing at any one time?

Yes.

If I had a time machine, I’d go back and beg someone to call this
’channel’ something other than “music” … maybe “streamed”.

Assuming I have my background music playing…say I need to play some
SFX at the same time…
Is this done using the Mix_LoadWAV and then the Channel family of
functions (i.e. Mix_AllocateChannels, Mix_PlayChannel, etc.)?

Yes. The other channels are things that can be trivially decoded into an
uncompressed PCM waveform all at once, like a small .wav file for a
gunshot sound.

I’m guessing to start off with I don’t need to worry about effects, right?
I can just use the build-in processors for now (if needed).

Effects can be totally avoided unless you want to do something hardcore
and complex…they require you not only to operate on the waveform
directly, but handle every strange case of data format and channel count
and frequency. Avoid this API unless you have a desperate need and
really know what you’re doing at a lowlevel.

There are a few built-in effects that might be useful to you, and almost
everything else you need is just mixing some explosions with a
soundtrack as you go (which can be done with the basic SDL_mixer APIs,
completely ignoring the effects stuff).

–ryan.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

LIM, if you’re around, I wouldn’t mind some input (-unfy).

I’ve got a working SDL / ffmpeg combination working just swimmingly. Single
movie with sound, or multiple silent concurrent movie playback works and all
that good jazz. RGB output or YUV, all kinds of goodness.

My application will soon need the services of a sound mixer (playing
multiple sound effects, or possibly sound effects while an ffmpeg movie is
being played). I’ve written a dozen sound mixers in the past across several
platforms (ranging from bare metal to win32, etc)… but… figured I’d give
SDL_mixer a chance first before writing yet another mixer.

My problem comes in that there doesn’t appear to be a way to hook the "IRQ"
more or less via SDL_mixer (ie: the audio call back function that’s apart of
sdl_openaudio() is missing from mix_openaudio()).

Is there a clean way to get a Mix_Chunk callback for filling in the data
stream with my own audio generator (or decoder) constantly ?

I’ve looked through the last few years of SDL mailing list that I’ve managed
to accrue and don’t appear to have seen this question before.

Poking through the documentation, it looks like the Mix_RegisterEffect()
function might accomplish what I want ? Does the ‘effect’ function get
called before the Chunk stream gets mixed into the output ?

Something along the lines of (some really ugly pseudo code):

// my audio buffer, void * for simplicity here…
void * ffmpeg_audio_buffer;

// create a chunk out of it
ffmpeg_audio_buffer = malloc(howeverbigitis);

ffmpeg_chunk = Mix_QuickLoad_RAW(ffmpeg_audio_buffer, howeverbigitis);

// i’ll leave channel 0 as my hardcoded ffmpeg decode channel

// register an ‘effect’ so that i can play with the data stream constantly
Mix_RegisterEffect(0, callback_hack, done_function, userarg);

// start playing it constantly
MixPlayChannel(0, ffmpeg_chunk, -1);

// go about the rest of my proggy as usual

… with something along the lines of:

callback_hack(chan, stream, len, userdata)
{
// overwrite stream with my ffmpeg audio data or silence as appropriate
memcpy(stream, some_ffmpeg_decoded_audio, len);

// assume at exit of this function, the data contained/obliterated in
stream gets mixed into the final output
}

Is there a clean way to get a Mix_Chunk callback for filling in the data
stream with my own audio generator (or decoder) constantly ?

You have a few options.

The effects API…

http://hg.libsdl.org/SDL_mixer/file/e60c8cff0336/SDL_mixer.h#l228

…this lets you hook in and modify the in-flight audio data right
before it’s sent to the hardware. This allows you to either modify a
specific channel right before it is mixed in with the other channels, or
to catch the final mix before it goes to the hardware.

Other options:

  • Mix_SetPostMix() will let you catch the final mix, too.
  • Mix_HookMusic() can be used if you don’t want to modify a channel so
    much as generate data for a channel on the fly, and aren’t otherwise
    using the music APIs (there’s only one “music” channel).
  • If you’re managing all the data yourself and want nothing of SDL_mixer
    but to get at the lowlevel “IRQ” in SDL_mixer, you shouldn’t be using
    SDL_mixer at all. Use SDL itself…you’re a mere call to SDL_OpenAudio()
    and SDL_PauseAudio(0) away from what you want…this is what SDL_mixer
    does under the hood, if you don’t need multiple channels and decoding of
    various file formats. I’m not sure if ffmpeg has some sort of mixer
    built in that might make more sense to wire to SDL’s audio callback.
    That’s your call.

–ryan.

Hi Ryan!

Woo! An answer from possibly the guy who would know best. Kick ass :).

Looking at my options, it looks like the effects API is indeed what I’ll be
looking for, in particular a channel specific one before the data gets
pumped into the mixing routines.

As far as I know, ffmpeg does not have it’s own internal mixer, and mixing
is indeed what I’m looking for. Concerning both static audio files as well
as dynamic audio data (output from ffmpeg). I currently have ffmpeg filling
an audio buffer and then dequeuing that buffer into the SDL_OpenAudio
callback function (or silence if appropriate). Needing to be able to
concurrently play some other wav’s or maybe even different ffmpeg audio
streams is my reasoning for looking at SDL_mixer. I’ve written my own
generic mixers, mod players, and s3m players from scratch before (as well as
a bare metal multiple-midi-on-opl3 mixer)… and was really hoping to avoid
writing another one.

I’ll give things a shot with effects API and report back.

Thanks!

-WillOn Wed, Feb 2, 2011 at 12:32 AM, Ryan C. Gordon wrote:

Is there a clean way to get a Mix_Chunk callback for filling in the data

stream with my own audio generator (or decoder) constantly ?

You have a few options.

The effects API…

http://hg.libsdl.org/SDL_mixer/file/e60c8cff0336/SDL_mixer.h#l228

…this lets you hook in and modify the in-flight audio data right before
it’s sent to the hardware. This allows you to either modify a specific
channel right before it is mixed in with the other channels, or to catch the
final mix before it goes to the hardware.

Other options:

  • Mix_SetPostMix() will let you catch the final mix, too.
  • Mix_HookMusic() can be used if you don’t want to modify a channel so much
    as generate data for a channel on the fly, and aren’t otherwise using the
    music APIs (there’s only one “music” channel).
  • If you’re managing all the data yourself and want nothing of SDL_mixer
    but to get at the lowlevel “IRQ” in SDL_mixer, you shouldn’t be using
    SDL_mixer at all. Use SDL itself…you’re a mere call to SDL_OpenAudio() and
    SDL_PauseAudio(0) away from what you want…this is what SDL_mixer does
    under the hood, if you don’t need multiple channels and decoding of various
    file formats. I’m not sure if ffmpeg has some sort of mixer built in that
    might make more sense to wire to SDL’s audio callback. That’s your call.

–ryan.


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

Success!

Just to report back (for archival purposes and kudos / thank you’s):

This was for converting an app that had an ffmpeg centric audio routine
using vanilla SDL audio routines into using SDL_mixer.

Steps:

  • removing the SDL_OpenAudio() call

  • Using the SDL_AudioSpec struct params into the Mix_OpenAudio() call params

  • Setting aside an array for holding the Mix_Chunk audio buffer (whereas
    before, just worked from array passed by the SDL_OpenAudio() callback)

  • Mix_QuickLoad_RAW()

  • Mix_PlayChannel() on the quickload returned chunk with infinite loops

  • Mix_RegisterEffect() to setup the signal / callback for filling in data
    dynamically

  • the effect callback / API function just calls the old SDL_OpenAudio audio
    callback (discarding the channel param for now)

  • make regular Mix_LoadWAV() and Mix_PlayChannel() calls for regular sound
    effects playback

So a basic synopsis of code:

Uint8 chunk_buffer[1024];
void * is_audio;

init_psuedo_code()
{
int mix_movie_channel;
Mix_Chunk * chunk_movie;

SDL_Init(SDL_INIT_AUDIO);

Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 1024));

memset(chunk_buffer, 0, sizeof(chunk_buffer));

chunk_movie = Mix_QuickLoad_RAW(chunk_buffer, 1024);

mix_movie_channel = Mix_PlayChannel(-1, chunk_movie, -1);

Mix_RegisterEffect(mix_movie_channel, mixer_effect_ffmpeg_cb,
mixer_effectdone_ffmpeg_cb, &is_audio);
}

void mixer_effect_ffmpeg_cb(int chan, void * stream, int len, void * udata)
{
old_sdl_audio_callback_that_used_ffmpeg_data(udata, stream, len);
}

void mixer_effectdone_ffmpeg_cb(int chan, void * udata)
{
// dont care
}On Wed, Feb 2, 2011 at 8:02 PM, Will Langford <@William_Langford> wrote:

Hi Ryan!

Woo! An answer from possibly the guy who would know best. Kick ass :).

Looking at my options, it looks like the effects API is indeed what I’ll be
looking for, in particular a channel specific one before the data gets
pumped into the mixing routines.

As far as I know, ffmpeg does not have it’s own internal mixer, and mixing
is indeed what I’m looking for. Concerning both static audio files as well
as dynamic audio data (output from ffmpeg). I currently have ffmpeg filling
an audio buffer and then dequeuing that buffer into the SDL_OpenAudio
callback function (or silence if appropriate). Needing to be able to
concurrently play some other wav’s or maybe even different ffmpeg audio
streams is my reasoning for looking at SDL_mixer. I’ve written my own
generic mixers, mod players, and s3m players from scratch before (as well as
a bare metal multiple-midi-on-opl3 mixer)… and was really hoping to avoid
writing another one.

I’ll give things a shot with effects API and report back.

Thanks!

-Will

On Wed, Feb 2, 2011 at 12:32 AM, Ryan C. Gordon wrote:

Is there a clean way to get a Mix_Chunk callback for filling in the data

stream with my own audio generator (or decoder) constantly ?

You have a few options.

The effects API…

http://hg.libsdl.org/SDL_mixer/file/e60c8cff0336/SDL_mixer.h#l228

…this lets you hook in and modify the in-flight audio data right before
it’s sent to the hardware. This allows you to either modify a specific
channel right before it is mixed in with the other channels, or to catch the
final mix before it goes to the hardware.

Other options:

  • Mix_SetPostMix() will let you catch the final mix, too.
  • Mix_HookMusic() can be used if you don’t want to modify a channel so
    much as generate data for a channel on the fly, and aren’t otherwise using
    the music APIs (there’s only one “music” channel).
  • If you’re managing all the data yourself and want nothing of SDL_mixer
    but to get at the lowlevel “IRQ” in SDL_mixer, you shouldn’t be using
    SDL_mixer at all. Use SDL itself…you’re a mere call to SDL_OpenAudio() and
    SDL_PauseAudio(0) away from what you want…this is what SDL_mixer does
    under the hood, if you don’t need multiple channels and decoding of various
    file formats. I’m not sure if ffmpeg has some sort of mixer built in that
    might make more sense to wire to SDL’s audio callback. That’s your call.

–ryan.


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