diff --git a/SDL2pp/Mixer.cc b/SDL2pp/Mixer.cc index e762863..7d649fc 100644 --- a/SDL2pp/Mixer.cc +++ b/SDL2pp/Mixer.cc @@ -242,4 +242,44 @@ void Mixer::SetMusicHook(MusicHook&& hook) { }, current_music_hook_.get()); } +void Mixer::SetPanning(int channel, int left, int right) { + if (Mix_SetPanning(channel, left, right) == 0) + throw Exception("Mix_SetPanning"); +} + +void Mixer::UnsetPanning(int channel) { + if (Mix_SetPanning(channel, 255, 255) == 0) + throw Exception("Mix_SetPanning"); +} + +void Mixer::SetDistance(int channel, int distance) { + if (Mix_SetDistance(channel, distance) == 0) + throw Exception("Mix_SetDistance"); +} + +void Mixer::UnsetDistance(int channel) { + if (Mix_SetDistance(channel, 0) == 0) + throw Exception("Mix_SetDistance"); +} + +void Mixer::SetPosition(int channel, int angle, int distance) { + if (Mix_SetPosition(channel, angle, distance) == 0) + throw Exception("Mix_SetPosition"); +} + +void Mixer::UnsetPosition(int channel) { + if (Mix_SetPosition(channel, 0, 0) == 0) + throw Exception("Mix_SetPosition"); +} + +void Mixer::SetReverseStereo(int channel) { + if (Mix_SetReverseStereo(channel, 1) == 0) + throw Exception("Mix_SetReverseStereo"); +} + +void Mixer::UnsetReverseStereo(int channel) { + if (Mix_SetReverseStereo(channel, 0) == 0) + throw Exception("Mix_SetReverseStereo"); +} + } diff --git a/SDL2pp/Mixer.hh b/SDL2pp/Mixer.hh index 65434f8..53d032c 100644 --- a/SDL2pp/Mixer.hh +++ b/SDL2pp/Mixer.hh @@ -652,7 +652,123 @@ public: //////////////////////////////////////////////////////////// void SetMusicHook(MusicHook&& hook); - // TODO: Effects + // TODO: custom effects + + //////////////////////////////////////////////////////////// + /// \brief Stereo panning + /// + /// \param[in] channel Channel number to register this effect on or + /// MIX_CHANNEL_POST to process the postmix stream + /// \param[in] left Volume for the left channel, range is 0 (silence) + /// to 255 (loud) + /// \param[in] right Volume for the right channel, range is 0 (silence) + /// to 255 (loud) + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC80 + /// + //////////////////////////////////////////////////////////// + void SetPanning(int channel, int left, int right); + + //////////////////////////////////////////////////////////// + /// \brief Disable stereo panning + /// + /// \param[in] channel Channel number to unregister this effect from or + /// MIX_CHANNEL_POST to unregister from the postmix stream + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC80 + /// + //////////////////////////////////////////////////////////// + void UnsetPanning(int channel); + + //////////////////////////////////////////////////////////// + /// \brief Distance attenuation (volume) + /// + /// \param[in] channel Channel number to register this effect on or + /// MIX_CHANNEL_POST to process the postmix stream + /// \param[in] distance Specify the distance from the listener, + /// from 0 (close/loud) to 255 (far/quiet) + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC81 + /// + //////////////////////////////////////////////////////////// + void SetDistance(int channel, int distance); + + //////////////////////////////////////////////////////////// + /// \brief Disable distance attenuation + /// + /// \param[in] channel Channel number to unregister this effect from or + /// MIX_CHANNEL_POST to unregister from the postmix stream + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC81 + /// + //////////////////////////////////////////////////////////// + void UnsetDistance(int channel); + + //////////////////////////////////////////////////////////// + /// \brief Panning (angular) and distance + /// + /// \param[in] channel Channel number to register this effect on or + /// MIX_CHANNEL_POST to process the postmix stream + /// \param[in] 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 + /// etc. + /// \param[in] distance Specify the distance from the listener, + /// from 0 (close/loud) to 255 (far/quiet) + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC82 + /// + //////////////////////////////////////////////////////////// + void SetPosition(int channel, int angle, int distance); + + //////////////////////////////////////////////////////////// + /// \brief Disable panning and distance + /// + /// \param[in] channel Channel number to unregister this effect from or + /// MIX_CHANNEL_POST to unregister from the postmix stream + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC82 + /// + //////////////////////////////////////////////////////////// + void UnsetPosition(int channel); + + //////////////////////////////////////////////////////////// + /// \brief Swap stereo left and right + /// + /// \param[in] channel Channel number to register this effect on or + /// MIX_CHANNEL_POST to process the postmix stream + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC83 + /// + //////////////////////////////////////////////////////////// + void SetReverseStereo(int channel); + + //////////////////////////////////////////////////////////// + /// \brief Disable stereo swapping + /// + /// \param[in] channel Channel number to unregister this effect from or + /// MIX_CHANNEL_POST to unregister from the postmix stream + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC83 + /// + //////////////////////////////////////////////////////////// + void UnsetReverseStereo(int channel); }; } diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c7e8d1f..12b1dfb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -37,4 +37,7 @@ IF(SDL2PP_WITH_MIXER) ADD_EXECUTABLE(mixer_music_sine mixer_music_sine.cc) TARGET_LINK_LIBRARIES(mixer_music_sine SDL2pp) + + ADD_EXECUTABLE(mixer_effects mixer_effects.cc) + TARGET_LINK_LIBRARIES(mixer_effects SDL2pp) ENDIF(SDL2PP_WITH_MIXER) diff --git a/examples/mixer_effects.cc b/examples/mixer_effects.cc new file mode 100644 index 0000000..191999d --- /dev/null +++ b/examples/mixer_effects.cc @@ -0,0 +1,120 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2015 Dmitry Marakasov + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include + +#include +#include + +#include +#include +#include +#include + +using namespace SDL2pp; + +int main() try { + SDL sdl(SDL_INIT_AUDIO); + SDLMixer mixerlib(MIX_INIT_OGG); + Mixer mixer(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096); + + Chunk sound(TESTDATA_DIR "/test.ogg"); + + int chan; + + // Panning + std::cerr << "Panning: left" << std::endl; + mixer.SetPanning(MIX_CHANNEL_POST, 255, 0); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + std::cerr << "Panning: right" << std::endl; + mixer.SetPanning(MIX_CHANNEL_POST, 0, 255); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + mixer.UnsetPanning(MIX_CHANNEL_POST); + + // Distance + std::cerr << "Distance: somewhat far" << std::endl; + mixer.SetDistance(MIX_CHANNEL_POST, 128); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + std::cerr << "Distance: further" << std::endl; + mixer.SetDistance(MIX_CHANNEL_POST, 192); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + std::cerr << "Distance: even further" << std::endl; + mixer.SetDistance(MIX_CHANNEL_POST, 224); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + mixer.UnsetDistance(MIX_CHANNEL_POST); + + // Position + std::cerr << "Position: closest left" << std::endl; + mixer.SetPosition(MIX_CHANNEL_POST, 270, 0); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + std::cerr << "Position: somewhat far front" << std::endl; + mixer.SetPosition(MIX_CHANNEL_POST, 0, 128); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + std::cerr << "Position: further right" << std::endl; + mixer.SetPosition(MIX_CHANNEL_POST, 90, 192); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + std::cerr << "Position: even further back" << std::endl; + mixer.SetPosition(MIX_CHANNEL_POST, 180, 224); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + mixer.UnsetPosition(MIX_CHANNEL_POST); + + // Position + std::cerr << "Reverse stereo" << std::endl; + + mixer.SetReverseStereo(MIX_CHANNEL_POST); + chan = mixer.PlayChannel(-1, sound); + SDL_Delay(2000); + mixer.HaltChannel(-1); + + mixer.UnsetReverseStereo(MIX_CHANNEL_POST); + + return 0; +} catch (std::exception& e) { + std::cerr << "Error: " << e.what() << std::endl; + return 1; +}