diff --git a/SDL2pp/Mixer.cc b/SDL2pp/Mixer.cc index 32901ef..af90352 100644 --- a/SDL2pp/Mixer.cc +++ b/SDL2pp/Mixer.cc @@ -20,6 +20,7 @@ */ #include +#include #include namespace SDL2pp { @@ -48,4 +49,80 @@ Mixer& Mixer::operator=(Mixer&& other) noexcept { return *this; } +int Mixer::AllocateChannels(int numchans) { + return Mix_AllocateChannels(numchans); +} + +int Mixer::GetNumChannels() const { + return Mix_AllocateChannels(-1); +} + +int Mixer::SetVolume(int channel, int volume) { + return Mix_Volume(channel, volume); +} + +int Mixer::GetVolume(int channel) const { + return Mix_Volume(channel, -1); +} + +int Mixer::PlayChannel(int channel, const Chunk& chunk, int loops) { + int chan; + if ((chan = Mix_PlayChannel(channel, chunk.Get(), loops)) == -1) + throw Exception("Mix_PlayChannel"); + return chan; +} + +int Mixer::PlayChannel(int channel, const Chunk& chunk, int loops, int ticks) { + int chan; + if ((chan = Mix_PlayChannelTimed(channel, chunk.Get(), loops, ticks)) == -1) + throw Exception("Mix_PlayChannelTimed"); + return chan; +} + +int Mixer::FadeInChannel(int channel, const Chunk& chunk, int loops, int ms) { + int chan; + if ((chan = Mix_FadeInChannel(channel, chunk.Get(), loops, ms)) == -1) + throw Exception("Mix_FadeInChannel"); + return chan; +} + +int Mixer::FadeInChannel(int channel, const Chunk& chunk, int loops, int ms, int ticks) { + int chan; + if ((chan = Mix_FadeInChannelTimed(channel, chunk.Get(), loops, ms, ticks)) == -1) + throw Exception("Mix_FadeInChannelTimed"); + return chan; +} + +void Mixer::Pause(int channel) { + Mix_Pause(channel); +} + +void Mixer::Resume(int channel) { + Mix_Resume(channel); +} + +void Mixer::HaltChannel(int channel) { + Mix_HaltChannel(channel); +} + +int Mixer::ExpireChannel(int channel, int ticks) { + return Mix_ExpireChannel(channel, ticks); +} + +int Mixer::FadeOutChannel(int channel, int ms) { + return Mix_ExpireChannel(channel, ms); +} + +int Mixer::Playing(int channel) const { + return Mix_Playing(channel); +} + +int Mixer::Paused(int channel) const { + return Mix_Paused(channel); +} + +int Mixer::FadingChannel(int which) const { + return Mix_FadingChannel(which); +} + } diff --git a/SDL2pp/Mixer.hh b/SDL2pp/Mixer.hh index 6b52c08..af326cd 100644 --- a/SDL2pp/Mixer.hh +++ b/SDL2pp/Mixer.hh @@ -22,13 +22,11 @@ #ifndef SDL2PP_MIXER_HH #define SDL2PP_MIXER_HH -#include - #include namespace SDL2pp { -class RWops; +class Chunk; //////////////////////////////////////////////////////////// /// \brief SDL_mixer's audio mixer @@ -108,6 +106,249 @@ public: /// //////////////////////////////////////////////////////////// Mixer& operator=(const Mixer& other) = delete; + + //////////////////////////////////////////////////////////// + /// \brief Set the number of channels to mix + /// + /// \param[in] numchans Number of channels to allocate for mixing + /// + /// \returns The number of channels allocated + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC26 + /// + //////////////////////////////////////////////////////////// + int AllocateChannels(int numchans); + + //////////////////////////////////////////////////////////// + /// \brief Get the number of channels being mixed + /// + /// \returns The number of channels allocated + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC26 + /// + //////////////////////////////////////////////////////////// + int GetNumChannels() const; + + //////////////////////////////////////////////////////////// + /// \brief Set the mix volume of a channel + /// + /// \param[in] channel Channel to set mix volume for. + /// -1 will set the volume for all allocated + /// channels. + /// \param[in] volume The volume to use from 0 to MIX_MAX_VOLUME(128) + /// + /// \returns Current volume of the channel. If channel is -1, + /// the average volume is returned + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC27 + /// + //////////////////////////////////////////////////////////// + int SetVolume(int channel, int volume); + + //////////////////////////////////////////////////////////// + /// \brief Get the mix volume of a channel + /// + /// \param[in] channel Channel to set mix volume for. + /// -1 will return the average volume. + /// + /// \returns Current volume of the channel. If channel is -1, + /// the average volume is returned + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC27 + /// + //////////////////////////////////////////////////////////// + int GetVolume(int channel) const; + + //////////////////////////////////////////////////////////// + /// \brief Play loop + /// + /// \param[in] channel Channel to play on, or -1 for the first + /// free unreserved channel + /// \param[in] chunk Sample to play + /// \param[in] loops Number of loops, -1 is infinite loops. + /// Passing one here plays the sample twice (1 loop). + /// + /// \returns The channel the sample is played on + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC28 + /// + //////////////////////////////////////////////////////////// + int PlayChannel(int channel, const Chunk& chunk, int loops = 0); + + //////////////////////////////////////////////////////////// + /// \brief Play loop and limit by time + /// + /// \param[in] channel Channel to play on, or -1 for the first + /// free unreserved channel + /// \param[in] chunk Sample to play + /// \param[in] loops Number of loops, -1 is infinite loops. + /// Passing one here plays the sample twice (1 loop). + /// \param[in] ticks Millisecond limit to play sample, at most. + /// If not enough loops or the sample chunk is not + /// long enough, then the sample may stop before + /// this timeout occurs. -1 means play forever + /// + /// \returns The channel the sample is played on + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC29 + /// + //////////////////////////////////////////////////////////// + int PlayChannel(int channel, const Chunk& chunk, int loops, int ticks); + + //////////////////////////////////////////////////////////// + /// \brief Play loop with fade in + /// + /// \param[in] channel Channel to play on, or -1 for the first + /// free unreserved channel + /// \param[in] chunk Sample to play + /// \param[in] loops Number of loops, -1 is infinite loops. + /// Passing one here plays the sample twice (1 loop). + /// \param[in] ms Milliseconds of time that the fade-in effect + /// should take to go from silence to full volume + /// + /// \returns The channel the sample is played on + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC30 + /// + //////////////////////////////////////////////////////////// + int FadeInChannel(int channel, const Chunk& chunk, int loops, int ms); + + //////////////////////////////////////////////////////////// + /// \brief loop with fade in and limit by time + /// + /// \param[in] channel Channel to play on, or -1 for the first + /// free unreserved channel + /// \param[in] chunk Sample to play + /// \param[in] loops Number of loops, -1 is infinite loops. + /// Passing one here plays the sample twice (1 loop). + /// \param[in] ms Milliseconds of time that the fade-in effect + /// should take to go from silence to full volume + /// \param[in] ticks Millisecond limit to play sample, at most. + /// If not enough loops or the sample chunk is not + /// long enough, then the sample may stop before + /// this timeout occurs. -1 means play forever + /// + /// \returns The channel the sample is played on + /// + /// \throws SDL2pp::Exception + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC31 + /// + //////////////////////////////////////////////////////////// + int FadeInChannel(int channel, const Chunk& chunk, int loops, int ms, int ticks); + + //////////////////////////////////////////////////////////// + /// \brief Pause a channel + /// + /// \param[in] channel Channel to pause on, or -1 for all channels + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC32 + /// + //////////////////////////////////////////////////////////// + void Pause(int channel = -1); + + //////////////////////////////////////////////////////////// + /// \brief Resume a paused channel + /// + /// \param[in] channel Channel to resume playing, or -1 for all channels + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC33 + /// + //////////////////////////////////////////////////////////// + void Resume(int channel = -1); + + //////////////////////////////////////////////////////////// + /// \brief Stop playing on a channel + /// + /// \param[in] channel Channel to stop playing, or -1 for all channels + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC34 + /// + //////////////////////////////////////////////////////////// + void HaltChannel(int channel); + + //////////////////////////////////////////////////////////// + /// \brief Change the timed stoppage of a channel + /// + /// \param[in] channel Channel to stop playing, or -1 for all channels + /// \param[in] ticks Millisecons until channel(s) halt playback + /// + /// \returns Number of channels set to expire. Whether or not they are active + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC35 + /// + //////////////////////////////////////////////////////////// + int ExpireChannel(int channel, int ticks); + + //////////////////////////////////////////////////////////// + /// \brief Stop playing channel after timed fade out + /// + /// \param[in] channel Channel to fade out, or -1 to fade all channels out + /// \param[in] ms Milliseconds of time that the fade-out effect should + /// take to go to silence, starting now + /// + /// \returns The number of channels set to fade out + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC36 + /// + //////////////////////////////////////////////////////////// + int FadeOutChannel(int channel, int ms); + + // TODO: ChannelFinished + + //////////////////////////////////////////////////////////// + /// \brief Get the active playing status of a channel + /// + /// \param[in] channel Channel to test whether it is playing or not. + /// -1 will tell you how many channels are playing + /// + /// \returns Zero if the channel is not playing. Otherwise if you passed + /// in -1, the number of channels playing is returned. If you + /// passed in a specific channel, then 1 is returned if it is + /// playing. + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC38 + /// + //////////////////////////////////////////////////////////// + int Playing(int channel) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the pause status of a channel + /// + /// \param[in] channel Channel to test whether it is paused or not. + /// -1 will tell you how many channels are playing + /// + /// \returns Zero if the channel is not paused. Otherwise if you passed + /// in -1, the number of paused channels is returned. If you + /// passed in a specific channel, then 1 is returned if it is + /// paused. + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC39 + /// + //////////////////////////////////////////////////////////// + int Paused(int channel) const; + + //////////////////////////////////////////////////////////// + /// \brief Get the fade status of a channel + /// + /// \param[in] which Channel to get the fade activity status from + /// + /// \returns The fading status + /// + /// \see https://www.libsdl.org/projects/SDL_mixer/docs/SDL_mixer.html#SEC40 + /// + //////////////////////////////////////////////////////////// + int FadingChannel(int which) const; + + // TODO: Groups + // TODO: Music + // TODO: Effects }; } diff --git a/examples/mixer.cc b/examples/mixer.cc index 43ab0ba..c903adf 100644 --- a/examples/mixer.cc +++ b/examples/mixer.cc @@ -36,9 +36,24 @@ int main() try { SDLMixer mixerlib(MIX_INIT_OGG); Mixer mixer(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096); - // currently fails as audio device hasn't been opened Chunk chunk(TESTDATA_DIR "/test.ogg"); - chunk.Volume(128); + + int chan; + + chan = mixer.PlayChannel(-1, chunk); + std::cerr << "Playing sound on channel " << chan << "\n"; + + SDL_Delay(500); + + chan = mixer.PlayChannel(-1, chunk); + std::cerr << "Playing sound on channel " << chan << "\n"; + + SDL_Delay(1000); + + chan = mixer.PlayChannel(-1, chunk); + std::cerr << "Playing sound on channel " << chan << "\n"; + + SDL_Delay(4500); return 0; } catch (std::exception& e) {