Effects
=======

These functions are for special effects processing. Not all effects are all that special. All effects are post processing routines that are either built-in to SDL_mixer or created by you.  Effects can be applied to individual channels, or to the final mixed stream which contains all the channels including music.

The built-in processors: Mix_SetPanning, Mix_SetPosition, Mix_SetDistance, and

Mix_SetReverseStereo, all look for an environment variable, MIX_EFFECTSMAXSPEED to be defined. If the environment variable is defined these processors may use more memory or reduce the quality of the effects, all for better speed.

Mix_RegisterEffect
------------------

     int Mix_RegisterEffect(int CHAN, Mix_EffectFunc_t F, Mix_EffectDone_t D,
                            void *ARG)

chan
     channel number to register F and D on.

     Use MIX_CHANNEL_POST to process the postmix stream.

f
     The function pointer for the effects processor.

d
     The function pointer for any cleanup routine to be called when the channel is done playing a sample.

     This may be NULL for any processors that don't need to clean up any memory or other dynamic data.

arg
     A pointer to data to pass into the F's and D's udata parameter.  It is a good place to keep the state data for the processor, especially if the processor is made to handle multiple channels at the same time.

     This may be NULL, depending on the processor.

Hook a processor function F into a channel for post processing effects.  You may just be reading the data and displaying it, or you may be altering the stream to add an echo.  Most processors also have state data that they allocate as they are in use, this would be stored in the ARG pointer data space.  When a processor is finished being used, any function passed into D will be called, which is when your processor should clean up the data in the ARG data space.

The effects are put into a linked list, and always appended to the end, meaning they always work on previously registered effects output.  Effects may be added multiple times in a row.  Effects are cumulative this way.

Returns: Zero on errors, such as a nonexisting channel.

     // make a passthru processor function that does nothing...
     void noEffect(int chan, void *stream, int len, void *udata)
     {
         // you could work with stream here...
     }
     ...
     // register noEffect as a postmix processor
     if(!Mix_RegisterEffect(MIX_CHANNEL_POST, noEffect, NULL, NULL)) {
         printf("Mix_RegisterEffect: %s\n", Mix_GetError());
     }

See Also:

Mix_UnregisterEffect, Mix_UnregisterAllEffects

Mix_UnregisterEffect
--------------------

int Mix_UnregisterEffect(int CHANNEL, Mix_EffectFunc_t F)

channel
     Channel number to remove F from as a post processor.

     Use MIX_CHANNEL_POST for the postmix stream.

f
     The function to remove from CHANNEL.

Remove the oldest (first found) registered effect function F from the effect list for CHANNEL.  This only removes the first found occurance of that function, so it may need to be called multiple times if you added the same function multiple times, just stop removing when Mix_UnregisterEffect returns an error, to remove all occurances of F from a channel.

If the channel is active the registered effect will have its Mix_EffectDone_t function called, if it was specified in Mix_RegisterEffect.

Returns: Zero on errors, such as invalid channel, or effect function not registered on channel.

     // unregister the noEffect from the postmix effects
     // this removes all occurances of noEffect registered to the postmix
     while(Mix_UnregisterEffect(MIX_CHANNEL_POST, noEffect));
     // you may print Mix_GetError() if you want to check it.
     // it should say "No such effect registered" after this loop.

See Also:

Mix_UnregisterAllEffects, Mix_RegisterEffect

Mix_UnregisterAllEffects
------------------------

int Mix_UnregisterAllEffects(int CHANNEL)

channel
     Channel to remove all effects from.

     Use MIX_CHANNEL_POST for the postmix stream.

This removes all effects registered to CHANNEL. If the channel is active all the registered effects will have their Mix_EffectDone_t functions called, if they were specified in Mix_RegisterEffect.

Returns: Zero on errors, such as CHANNEL not existing.

     // remove all effects from channel 0
     if(!Mix_UnregisterAllEffects(0)) {
         printf("Mix_UnregisterAllEffects: %s\n", Mix_GetError());
     }

See Also:

Mix_UnregisterEffect, Mix_RegisterEffect

Mix_RegisterMusicEffect
-----------------------

     int Mix_RegisterMusicEffect(Mix_Music *MUSIC, Mix_MusicEffectFunc_t F,
                                     Mix_MusicEffectDone_t D, void *ARG)

music
     music to register F and D on.

f
     The function pointer for the music effects processor.

d
     The function pointer for any cleanup routine to be called when the music is getting closed up.

     This may be NULL for any processors that don't need to clean up any memory or other dynamic data.

arg
     A pointer to data to pass into the F's and D's udata parameter.  It is a good place to keep the state data for the processor, especially if the processor is made to handle multiple channels at the same time.

     This may be NULL, depending on the processor.

Hook a processor function F into a music for post processing effects.  You may just be reading the data and displaying it, or you may be altering the stream to add an echo.  Most processors also have state data that they allocate as they are in use, this would be stored in the ARG pointer data space. When a processor is finished being used, any function passed into D will be called, which is when your processor should clean up the data in the ARG data space.

The effects are put into a linked list, and always appended to the end, meaning they always work on previously registered effects output.  Effects may be added multiple times in a row. Effects are cumulative this way.

Returns: Zero on errors, such as a nonexisting music.

     // make a passthru processor function that does nothing...
     void noEffect(Mix_Music *music, void *stream, int len, void *udata)
     {
         // you could work with stream here...
     }
     ...

     // Mix_Music *someMusic = Mix_LoadMUS("somemusic.ogg");
     // register noEffect as a someMusic processor
     if(!Mix_RegisterMusicEffect(someMusic, noEffect, NULL, NULL)) {
         printf("Mix_RegisterMusicEffect: %s\n", Mix_GetError());
     }

See Also:

Mix_UnregisterMusicEffect, Mix_UnregisterAllMusicEffects

Mix_UnregisterMusicEffect
-------------------------

int Mix_UnregisterMusicEffect(Mix_Music MUSIC, Mix_MusicEffectFunc_t F)

music
     Music to remove F from as a post processor.

f
     The function to remove from MUSIC.

Remove the oldest (first found) registered effect function F from the effect list for CHANNEL. This only removes the first found occurance of that function, so it may need to be called multiple times if you added the same function multiple times, just stop removing when Mix_UnregisterMusicEffect returns an error, to remove all occurances of F from a channel.

If the music is active the registered effect will have its Mix_MusicEffectDone_t function called, if it was specified in Mix_RegisterMusicEffect.

Returns: Zero on errors, such as invalid music, or effect function not registered on music.

     // unregister the noEffect from the someMusic effects
     // this removes all occurances of noEffect registered to the postmix
     while(Mix_UnregisterMusicEffect(someMusic, noEffect));
     // you may print Mix_GetError() if you want to check it.
     // it should say "No such effect registered" after this loop.

See Also:

Mix_RegisterMusicEffect, Mix_UnregisterAllMusicEffects

Mix_UnregisterAllMusicEffects
-----------------------------

int Mix_UnregisterAllMusicEffects(Mix_Music *MUSIC)

music
     Music to remove all effects from.

This removes all effects registered to MUSIC. If the music is active all the registered effects will have their Mix_MusicEffectDone_t functions called, if they were specified in Mix_RegisterMusicEffect.

Returns: Zero on errors, such as MUSIC not existing.

     // remove all effects from someMusic
     if(!Mix_UnregisterAllMusicEffects(someMusic)) {
         printf("Mix_UnregisterAllMusicEffects: %s\n", Mix_GetError());
     }

See Also:

Mix_RegisterMusicEffect, Mix_UnregisterMusicEffect

Mix_SetPostMix
--------------

     void Mix_SetPostMix(void (*MIX_FUNC)(void *udata, Uint8 *stream, int len),
                         void *ARG)

mix_func
     The function pointer for the postmix processor.

     NULL unregisters the current postmixer.

arg
     A pointer to data to pass into the MIX_FUNC's udata parameter.  It is a good place to keep the state data for the processor, especially if the processor is made to handle multiple channels at the same time.

     This may be NULL, depending on the processor.

Hook a processor function MIX_FUNC to the postmix stream for post processing effects.  You may just be reading the data and displaying it, or you may be altering the stream to add an echo.  Most processors also have state data that they allocate as they are in use, this would be stored in the ARG pointer data space. This processor is never really finished, until the audio device is closed, or you pass NULL as the MIX_FUNC.

There can only be one postmix function used at a time through this method.  Use Mix_RegisterEffect(MIX_CHANNEL_POST, mix_func, NULL, arg) to use multiple postmix processors.

This postmix processor is run AFTER all the registered postmixers set up by Mix_RegisterEffect.

     // make a passthru processor function that does nothing...
     void noEffect(void *udata, Uint8 *stream, int len)
     {
         // you could work with stream here...
     }
     ...
     // register noEffect as a postmix processor
     Mix_SetPostMix(noEffect, NULL);

See Also:

Mix_RegisterEffect

Mix_SetPanning
--------------

int Mix_SetPanning(int CHANNEL, Uint8 LEFT, Uint8 RIGHT)

channel
     Channel number to register this effect on.

     Use MIX_CHANNEL_POST to process the postmix stream.

left
     Volume for the left channel, range is 0(silence) to 255(loud)

right
     Volume for the left channel, range is 0(silence) to 255(loud)

This effect will only work on stereo audio.  Meaning you called Mix_OpenAudio with 2 channels (MIX_DEFAULT_CHANNELS).  The easiest way to do true panning is to call Mix_SetPanning(channel, left, 254 - left); so that the total volume is correct, if you consider the maximum volume to be 127 per channel for center, or 254 max for left, this works, but about halves the effective volume.

This Function registers the effect for you, so don't try to Mix_RegisterEffect it yourself.

NOTE: Setting both LEFT and RIGHT to 255 will unregister the effect from CHANNEL.  You cannot unregister it any other way, unless you use Mix_UnregisterAllEffects on the CHANNEL.

NOTE: Using this function on a mono audio device will not register the effect, nor will it return an error status.

Returns: Zero on errors, such as bad channel, or if Mix_RegisterEffect failed.

     // pan channel 1 halfway to the left
     if(!Mix_SetPanning(1, 255, 127)) {
         printf("Mix_SetPanning: %s\n", Mix_GetError());
         // no panning, is it ok?
     }

See Also:

Mix_SetPosition, Mix_UnregisterAllEffects

Mix_SetDistance
---------------

int Mix_SetDistance(int CHANNEL, Uint8 DISTANCE)

channel
     Channel number to register this effect on.

     Use MIX_CHANNEL_POST to process the postmix stream.

distance
     Specify the distance from the listener, from 0(close/loud) to 255(far/quiet).

This effect simulates a simple attenuation of volume due to distance.  The volume never quite reaches silence, even at max distance.

NOTE: Using a DISTANCE of 0 will cause the effect to unregister itself from CHANNEL.  You cannot unregister it any other way, unless you use Mix_UnregisterAllEffects on the CHANNEL.

Returns: Zero on errors, such as an invalid channel, or if Mix_RegisterEffect failed.

     // distance channel 1 to be farthest away
     if(!Mix_SetDistance(1, 255)) {
         printf("Mix_SetDistance: %s\n", Mix_GetError());
         // no distance, is it ok?
     }

See Also:

Mix_SetPosition, Mix_UnregisterAllEffects

Mix_SetPosition
---------------

int Mix_SetPosition(int CHANNEL, Sint16 ANGLE, Uint8 DISTANCE)

channel
     Channel number to register this effect on.

     Use MIX_CHANNEL_POST to process the postmix stream.

angle
     Direction in relation to forward from 0 to 360 degrees.  Larger angles will be reduced to this range using ANGLES % 360.

     0 = directly in front.

     90 = directly to the right.

     180 = directly behind.

     270 = directly to the left.

     So you can see it goes clockwise starting at directly in front.

     This ends up being similar in effect to Mix_SetPanning.

distance
     The distance from the listener, from 0(near/loud) to 255(far/quiet).

     This is the same as the Mix_SetDistance effect.

This effect emulates a simple 3D audio effect.  It's not all that realistic, but it can help improve some level of realism.  By giving it the angle and distance from the camera's point of view, the effect pans and attenuates volumes.  If you are looking for better positional audio, using OpenAL is suggested.

NOTE: Using ANGLE and DISTANCE of 0, will cause the effect to unregister itself from CHANNEL.  You cannot unregister it any other way, unless you use Mix_UnregisterAllEffects on the CHANNEL.

Returns: Zero on errors, such as an invalid channel, or if Mix_RegisterEffect failed.

     // set channel 2 to be behind and right, and 100 units away
     if(!Mix_SetPosition(2, 135, 100)) {
         printf("Mix_SetPosition: %s\n", Mix_GetError());
         // no position effect, is it ok?
     }

See Also:

Mix_SetPanning, Mix_SetDistance, Mix_UnregisterAllEffects

Mix_SetReverseStereo
--------------------

int Mix_SetReverseStereo(int CHANNEL, int FLIP)

channel
     Channel number to register this effect on.

     Use MIX_CHANNEL_POST to process the postmix stream.

flip
     Must be non-zero to work, means nothing to the effect processor itself.

     set to zero to unregister the effect from CHANNEL.

Simple reverse stereo, swaps left and right channel sound.

NOTE: Using a FLIP of 0, will cause the effect to unregister itself from CHANNEL.  You cannot unregister it any other way, unless you use Mix_UnregisterAllEffects on the CHANNEL.

Returns: Zero on errors, such as an invalid channel, or if Mix_RegisterEffect failed.

     // set the total mixer output to be reverse stereo
     if(!Mix_SetReverseStereo(MIX_CHANNEL_POST, 1)) {
         printf("Mix_SetReverseStereo: %s\n", Mix_GetError());
         // no reverse stereo, is it ok?
     }

See Also:

Mix_UnregisterAllEffects

Mix_SetMusicEffectPanning
-------------------------

int Mix_SetMusicEffectPanning(Mix_Music *MUSIC, Uint8 LEFT, Uint8 RIGHT)

music
     Music to register this effect on.

left
     Volume for the left channel, range is 0(silence) to 255(loud)

right
     Volume for the left channel, range is 0(silence) to 255(loud)

This effect will only work on stereo audio.  Meaning you called Mix_OpenAudio with 2 channels (MIX_DEFAULT_CHANNELS).  The easiest way to do true panning is to call Mix_SetMusicEffectPanning(music, left, 254 - left); so that the total volume is correct, if you consider the maximum volume to be 127 per channel for center, or 254 max for left, this works, but about halves the effective volume.

This Function registers the effect for you, so don't try to Mix_RegisterMusicEffect it yourself.

NOTE: Setting both LEFT and RIGHT to 255 will unregister the effect from MUSIC.  You cannot unregister it any other way, unless you use Mix_UnregisterAllMusicEffects on the MUSIC.

NOTE: Using this function on a mono audio device will not register the effect, nor will it return an error status.

Returns: Zero on errors, such as bad music, or if Mix_RegisterMusicEffect failed.

     // pan someMusic halfway to the left
     if(!Mix_SetMusicEffectPanning(someMusic, 255, 127)) {
         printf("Mix_SetMusicEffectPanning: %s\n", Mix_GetError());
         // no panning, is it ok?
     }

See Also:

Mix_SetMusicEffectPosition, Mix_UnregisterAllMusicEffects

Mix_SetMusicEffectDistance
--------------------------

int Mix_SetMusicEffectDistance(Mix_Music *MUSIC, Uint8 DISTANCE)

music
     Music to register this effect on.

distance
     Specify the distance from the listener, from 0(close/loud) to 255(far/quiet).

This effect simulates a simple attenuation of volume due to distance. The volume never quite reaches silence, even at max distance.

NOTE: Using a DISTANCE of 0 will cause the effect to unregister itself from CHANNEL. You cannot unregister it any other way, unless you use Mix_UnregisterAllMusicEffects on the MUSIC.

Returns: Zero on errors, such as an invalid music, or if Mix_RegisterMusicEffect failed.

     // distance someMusic to be farthest away
     if(!Mix_SetMusicEffectDistance(someMusic, 255)) {
         printf("Mix_SetMusicEffectDistance: %s\n", Mix_GetError());
         // no distance, is it ok?
     }

See Also:

Mix_SetMusicEffectPosition, Mix_UnregisterAllMusicEffects

Mix_SetMusicEffectPosition
--------------------------

int Mix_SetMusicEffectPosition(Mix_Music *MUSIC, Sint16 ANGLE, Uint8 DISTANCE)

music
     Music to register this effect on.

angle
     Direction in relation to forward from 0 to 360 degrees.  Larger angles will be reduced to this range using ANGLES % 360.

     0 = directly in front.

     90 = directly to the right.

     180 = directly behind.

     270 = directly to the left.

     So you can see it goes clockwise starting at directly in front.

     This ends up being similar in effect to Mix_SetMusicEffectPanning.

distance
     The distance from the listener, from 0(near/loud) to 255(far/quiet).

     This is the same as the Mix_SetMusicEffectDistance effect.

This effect emulates a simple 3D audio effect. It's not all that realistic, but it can help improve some level of realism. By giving it the angle and distance from the camera's point of view, the effect pans and attenuates volumes. If you are looking for better positional audio, using OpenAL is suggested.

NOTE: Using ANGLE and DISTANCE of 0, will cause the effect to unregister itself from MUSIC. You cannot unregister it any other way, unless you use Mix_UnregisterAllMusicEffects on the MUSIC.

Returns: Zero on errors, such as an invalid music, or if Mix_RegisterMusicEffect failed.

     // set someMusic to be behind and right, and 100 units away
     if(!Mix_SetMusicEffectPosition(someMusic, 135, 100)) {
         printf("Mix_SetMusicEffectPosition: %s\n", Mix_GetError());
         // no position effect, is it ok?
     }

See Also:

Mix_SetMusicEffectPanning, Mix_SetMusicEffectDistance, Mix_UnregisterAllMusicEffects

Mix_SetMusicEffectReverseStereo
-------------------------------

int Mix_SetMusicEffectReverseStereo(Mix_Music *MUSIC, int FLIP)

music
     Music to register this effect on.

flip
     Must be non-zero to work, means nothing to the effect processor itself.

     set to zero to unregister the effect from MUSIC.

Simple reverse stereo, swaps left and right channel sound.

NOTE: Using a FLIP of 0, will cause the effect to unregister itself from MUSIC. You cannot unregister it any other way, unless you use Mix_UnregisterAllMusicEffects on the MUSIC.

Returns: Zero on errors, such as an invalid music, or if Mix_RegisterMusicEffect failed.

     // set the someMusic to be reverse stereo
     if(!Mix_SetMusicEffectReverseStereo(someMusic, 1)) {
         printf("Mix_SetMusicEffectReverseStereo: %s\n", Mix_GetError());
         // no reverse stereo, is it ok?
     }

See Also:

Mix_UnregisterAllMusicEffects