diff --git a/doomsday/libgui/include/de/Sound b/doomsday/libgui/include/de/Sound new file mode 100644 index 0000000000..4fbcb3c29e --- /dev/null +++ b/doomsday/libgui/include/de/Sound @@ -0,0 +1,2 @@ +#include "audio/sound.h" + diff --git a/doomsday/libgui/include/de/audio/sound.h b/doomsday/libgui/include/de/audio/sound.h new file mode 100644 index 0000000000..0729ed400b --- /dev/null +++ b/doomsday/libgui/include/de/audio/sound.h @@ -0,0 +1,114 @@ +/** @file sound.h Base class for playable audio waveforms. + * + * @authors Copyright (c) 2014 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBGUI_SOUND_H +#define LIBGUI_SOUND_H + +#include +#include +#include + +namespace de { + +/** + * Abstract base class for a playing sound. Provides methods for controlling how the + * sound is played, and querying the status of the sound. + * + * After creation, sounds are in a paused state, after which they can be configured with + * volume, frequency, etc. and started in either looping or non-looping mode. + * + * By default, sounds use 2D stereo positioning. 3D positioning is enabled when + * calling Sound::setPosition(). + * + * @ingroup audio + */ +class Sound +{ +public: + Sound(); + + /** + * Sounds are automatically stopped when deleted. + */ + virtual ~Sound() {} + + enum PlayingMode { + NotPlaying, + Once, ///< Play once then pause the sound. + OnceThenDelete, ///< Play once and then delete the sound. + Looping ///< Keep looping the sound. + }; + + enum Positioning { + Stereo, ///< Simple 2D stereo, not 3D. + Absolute, + HeadRelative + }; + + // Methods for controlling the sound: + + /** + * Starts playing the sound. If the sound is already playing, does nothing: + * to change the playing mode, one has to first stop the sound. + * + * @param mode Playing mode. + */ + virtual void play(PlayingMode mode = Once) = 0; + + virtual void stop() = 0; + virtual void pause() = 0; + virtual void resume() = 0; + + virtual void setVolume(dfloat volume); + virtual void setPan(dfloat pan); + virtual void setFrequency(dfloat factor); + virtual void setPosition(de::Vector3f const &position, Positioning positioning = Absolute); + virtual void setVelocity(de::Vector3f const &velocity); + + // Methods for querying the sound status: + + virtual PlayingMode mode() const = 0; + virtual bool isPaused() const = 0; + + virtual bool isPlaying() const; + virtual dfloat volume() const; + virtual dfloat pan() const; + virtual dfloat frequency() const; + virtual Positioning positioning() const; + virtual de::Vector3f position() const; + virtual de::Vector3f velocity() const; + + DENG2_AS_IS_METHODS() + + /// Audience that is notified when the sound stops. + DENG2_DEFINE_AUDIENCE2(Stop, void soundStopped(Sound &)) + + /// Audience that is notified when the sound instance is deleted. + DENG2_DEFINE_AUDIENCE2(Deletion, void soundBeingDeleted(Sound &)) + +protected: + /// Called after a property value has been changed. + virtual void update() = 0; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace de + +#endif // LIBGUI_SOUND_H diff --git a/doomsday/libgui/libgui.pro b/doomsday/libgui/libgui.pro index 8efcbb5072..280743ce8e 100644 --- a/doomsday/libgui/libgui.pro +++ b/doomsday/libgui/libgui.pro @@ -79,6 +79,7 @@ publicHeaders(root, \ include/de/NativeFont \ include/de/PersistentCanvasWindow \ include/de/RowAtlasAllocator \ + include/de/Sound \ include/de/TextureBank \ include/de/VertexBuilder \ include/de/Waveform \ @@ -96,6 +97,7 @@ publicHeaders(gui, \ ) publicHeaders(audio, \ + include/de/audio/sound.h \ include/de/audio/waveform.h \ include/de/audio/waveformbank.h \ ) @@ -143,6 +145,7 @@ publicHeaders(text, \ # Sources and private headers. SOURCES += \ + src/audio/sound.cpp \ src/audio/waveform.cpp \ src/audio/waveformbank.cpp \ src/canvas.cpp \ diff --git a/doomsday/libgui/src/audio/sound.cpp b/doomsday/libgui/src/audio/sound.cpp new file mode 100644 index 0000000000..92a6efd754 --- /dev/null +++ b/doomsday/libgui/src/audio/sound.cpp @@ -0,0 +1,115 @@ +/** @file sound.cpp Interface for playing sounds. + * + * @authors Copyright (c) 2014 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/Sound" + +namespace de { + +DENG2_PIMPL_NOREF(Sound) +{ + dfloat volume; + dfloat pan; + dfloat frequency; + Vector3f position; + Vector3f velocity; + Positioning positioning; + + Instance() + : volume(1.f) + , pan(0.f) + , frequency(1.f) + , positioning(Stereo) + {} + + DENG2_PIMPL_AUDIENCE(Stop) + DENG2_PIMPL_AUDIENCE(Deletion) +}; + +DENG2_AUDIENCE_METHOD(Sound, Stop) +DENG2_AUDIENCE_METHOD(Sound, Deletion) + +Sound::Sound() : d(new Instance) +{} + +void Sound::setVolume(dfloat volume) +{ + d->volume = volume; + update(); +} + +void Sound::setPan(dfloat pan) +{ + d->pan = pan; + update(); +} + +void Sound::setFrequency(dfloat factor) +{ + d->frequency = factor; + update(); +} + +void Sound::setPosition(Vector3f const &position, Positioning positioning) +{ + d->position = position; + d->positioning = positioning; + update(); +} + +void Sound::setVelocity(Vector3f const &velocity) +{ + d->velocity = velocity; + update(); +} + +bool Sound::isPlaying() const +{ + return mode() != NotPlaying; +} + +dfloat Sound::volume() const +{ + return d->volume; +} + +dfloat Sound::pan() const +{ + return d->pan; +} + +dfloat Sound::frequency() const +{ + return d->frequency; +} + +Vector3f Sound::position() const +{ + return d->position; +} + +Sound::Positioning Sound::positioning() const +{ + return d->positioning; +} + +Vector3f Sound::velocity() const +{ + return d->velocity; +} + +} // namespace de