From 7d36b599d0a991857b1d5952f9831b0828fad013 Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Wed, 30 Dec 2009 16:15:46 +0100 Subject: [PATCH] Added Sound.clone(), implemented with OpenAL. --- sound/output.h | 40 ++++++++++++++++++++++++++---------- sound/outputs/openal_out.cpp | 38 +++++++++++++++++++++++++++++++--- sound/outputs/openal_out.h | 24 ++++++++++------------ 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/sound/output.h b/sound/output.h index 4cdac7bed5..0829e4789c 100644 --- a/sound/output.h +++ b/sound/output.h @@ -17,6 +17,11 @@ namespace Sound { may be connected to a SampleSource or read directly from a file, and they may support 3d sounds, looping and other features depending on the capabilities of the backend system. + + To create multiple instances of one sound, it is recommended to + 'clone' an existing instance instead of reloading it from + file. Cloned sounds will often (depending on the back-end) use + less memory due to shared buffers. */ class Sound { @@ -31,14 +36,33 @@ class Sound virtual void pause() = 0; /// Check if the sound is still playing - virtual bool isPlaying() = 0; + virtual bool isPlaying() = 0 const; /// Set the volume. The parameter must be between 0.0 and 1.0. virtual void setVolume(float) = 0; - /// Set the position. May not have any effect on 2D sounds. + /// Set left/right pan. -1.0 is left, 0.0 is center and 1.0 is right. + virtual void setPan(float) = 0; + + /// Set the position. May not work with all backends. virtual void setPos(float x, float y, float z) = 0; + /// Set loop mode + virtual void setRepeat(bool) = 0; + + /// Set streaming mode. + /** This may be used by implementations to optimize for very large + files. If streaming mode is off (default), most implementations + will load the entire file into memory before starting playback. + */ + virtual void setStreaming(bool) = 0; + + /// Create a new instance of this sound. + /** Playback status is not cloned, only the sound data + itself. Back-ends can use this as a means of sharing data and + saving memory. */ + virtual Sound* clone() const = 0; + /// Virtual destructor virtual ~Sound() {} }; @@ -71,12 +95,6 @@ class SoundFactory */ bool has3D; - /** @brief true if 'repeat' and 'stream' can be used simultaneously. - If false, repeating a streamed sound will give undefined - behavior. - */ - bool canRepeatStream; - /// true if we can load sounds directly from file (containing encoded data) bool canLoadFile; @@ -99,7 +117,7 @@ class SoundFactory large files, but they are not required to. @return a new Sound object */ - virtual Sound *load(SampleSource *input, bool stream=false) = 0; + virtual Sound *load(SampleSource *input) = 0; /** @brief Load a sound file from stream. Only valid if canLoadStream @@ -109,7 +127,7 @@ class SoundFactory @param stream true if the file should be streamed @see load(InputSource*,bool) */ - virtual Sound *load(Stream::Stream *input, bool stream=false) = 0; + virtual Sound *load(Stream::Stream *input) = 0; /** @brief Load a sound directly from file. Only valid if canLoadFile @@ -119,7 +137,7 @@ class SoundFactory @param stream true if the file should be streamed @see load(InputSource*,bool) */ - virtual Sound *load(const std::string &file, bool stream=false) = 0; + virtual Sound *load(const std::string &file) = 0; /// Call this every frame if needsUpdate is true /** diff --git a/sound/outputs/openal_out.cpp b/sound/outputs/openal_out.cpp index b5ec9c171e..649a56aef3 100644 --- a/sound/outputs/openal_out.cpp +++ b/sound/outputs/openal_out.cpp @@ -103,6 +103,28 @@ void OpenAL_Sound::setPos(float x, float y, float z) checkALError("setting position"); } +void OpenAL_Sound::setRepeat(bool rep) +{ + alSourcei(Source, AL_LOOPING, rep?AL_TRUE:AL_FALSE); +} + +void OpenAL_Sound::setup() +{ +} + +// Constructor used for cloned sounds +OpenAL_Sound::OpenAL_Sound(ALuint buf, int *ref) + : refCnt(ref), bufferID(buf) +{ + // Increase the reference count + assert(ref != NULL); + *refCnt++; + + // Create a source + alGenSources(1, &inst); + alSourcei(inst, AL_BUFFER, bufferID); +} + OpenAL_Sound::OpenAL_Sound(SampleSource *input) { // Get the format @@ -120,7 +142,11 @@ OpenAL_Sound::OpenAL_Sound(SampleSource *input) // Create a source alGenSources(1, &inst); - alSourcei(inst, AL_BUFFER, buf); + alSourcei(inst, AL_BUFFER, bufferID); + + // Create a cheap reference counter for the buffer + refCnt = new int; + *refCnt = 1; } OpenAL_Sound::~OpenAL_Sound() @@ -131,6 +157,12 @@ OpenAL_Sound::~OpenAL_Sound() // Return sound alDeleteSources(1, &inst); - // Delete buffer - alDeleteBuffers(1, &bufferID); + // Decrease the reference + if(--(*refCnt)) + { + // We're the last owner. Delete the buffer and the counter + // itself. + alDeleteBuffers(1, &bufferID); + delete refCnt; + } } diff --git a/sound/outputs/openal_out.h b/sound/outputs/openal_out.h index 1cce21607f..a0b8ed4129 100644 --- a/sound/outputs/openal_out.h +++ b/sound/outputs/openal_out.h @@ -18,27 +18,26 @@ class OpenAL_Sound : public Sound ALuint inst; ALuint bufferID; + // Poor mans reference counting. Might improve this later. + int *refCnt; + public: OpenAL_Sound(SampleSource *input); + OpenAL_Sound(ALuint buf, int *ref); // Used for cloning ~OpenAL_Sound(); - /// Play or resume the sound void play(); - - /// Stop the sound void stop(); - - /// Pause the sound, may be resumed later void pause(); - - /// Check if the sound is still playing - bool isPlaying(); - - /// Set the volume. The parameter must be between 0.0 and 1.0. + bool isPlaying() const; void setVolume(float); - - /// Set the 3D position. void setPos(float x, float y, float z); + void setRepeat(bool); + void setStreaming(bool) {} // Not implemented yet + Sound* clone() const; + + /// Not implemented + void setPan(float) {} }; class OpenAL_Factory : public SoundFactory @@ -56,7 +55,6 @@ class OpenAL_Factory : public SoundFactory { needsUpdate = false; has3D = true; - canRepeatStream = false; canLoadFile = false; canLoadStream = false; canLoadSource = true;