Skip to content

Commit

Permalink
libgui: Added an abstract base class for sounds
Browse files Browse the repository at this point in the history
Once a sound is started, de::Sound allows once to control and observe
it.
  • Loading branch information
skyjake committed Mar 28, 2014
1 parent 0a089a6 commit 7a00e5a
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 0 deletions.
2 changes: 2 additions & 0 deletions doomsday/libgui/include/de/Sound
@@ -0,0 +1,2 @@
#include "audio/sound.h"

114 changes: 114 additions & 0 deletions 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 <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>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</small>
*/

#ifndef LIBGUI_SOUND_H
#define LIBGUI_SOUND_H

#include <de/Id>
#include <de/Observers>
#include <de/Vector>

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
3 changes: 3 additions & 0 deletions doomsday/libgui/libgui.pro
Expand Up @@ -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 \
Expand All @@ -96,6 +97,7 @@ publicHeaders(gui, \
)

publicHeaders(audio, \
include/de/audio/sound.h \
include/de/audio/waveform.h \
include/de/audio/waveformbank.h \
)
Expand Down Expand Up @@ -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 \
Expand Down
115 changes: 115 additions & 0 deletions doomsday/libgui/src/audio/sound.cpp
@@ -0,0 +1,115 @@
/** @file sound.cpp Interface for playing sounds.
*
* @authors Copyright (c) 2014 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>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</small>
*/

#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

0 comments on commit 7a00e5a

Please sign in to comment.