浏览代码

[Added] C++ Implementation of dynamic audio sound types which maintains backward compatibility

Alex Parlett 11 年之前
父节点
当前提交
8123624ee1

+ 39 - 4
Source/Engine/Audio/Audio.cpp

@@ -54,7 +54,7 @@ Audio::Audio(Context* context) :
     playing_(false)
 {
     for (unsigned i = 0; i < MAX_SOUND_TYPES; ++i)
-        masterGain_[i] = 1.0f;
+        masterGain_[soundTypeHashes[i]] = 1.0f;
     
     // Register Audio library object factories
     RegisterAudioLibrary(context_);
@@ -153,7 +153,12 @@ void Audio::SetMasterGain(SoundType type, float gain)
 {
     if (type >= MAX_SOUND_TYPES)
         return;
-    
+
+    SetMasterGain(soundTypeHashes[type], gain);
+}
+
+void Audio::SetMasterGain(const StringHash& type, float gain)
+{
     masterGain_[type] = Clamp(gain, 0.0f, 1.0f);
 }
 
@@ -171,12 +176,23 @@ void Audio::StopSound(Sound* soundClip)
     }
 }
 
+
 float Audio::GetMasterGain(SoundType type) const
 {
     if (type >= MAX_SOUND_TYPES)
         return 0.0f;
-    
-    return masterGain_[type];
+
+    return GetMasterGain(soundTypeHashes[type]);
+}
+
+
+float Audio::GetMasterGain(const StringHash& type) const
+{
+    VariantMap::ConstIterator findIt = masterGain_.Find(type);
+    if (findIt == masterGain_.End())
+        return 0.0f;
+
+    return findIt->second_.GetFloat();
 }
 
 SoundListener* Audio::GetListener() const
@@ -200,6 +216,25 @@ void Audio::RemoveSoundSource(SoundSource* channel)
     }
 }
 
+float Audio::GetSoundSourceMasterGain(SoundType type) const
+{
+    if (type >= MAX_SOUND_TYPES)
+        return 0.0f;
+    
+    return GetSoundSourceMasterGain(soundTypeHashes[type]);
+}
+
+float Audio::GetSoundSourceMasterGain(const StringHash& type) const
+{
+    VariantMap::ConstIterator masterIt = masterGain_.Find(soundTypeHashes[SOUND_MASTER]);
+    VariantMap::ConstIterator typeIt = masterGain_.Find(type);
+
+    if (typeIt == masterGain_.End())
+        return 0.0f;
+
+    return masterIt->second_.GetFloat() * typeIt->second_.GetFloat();
+}
+
 void SDLAudioCallback(void *userdata, Uint8* stream, int len)
 {
     Audio* audio = static_cast<Audio*>(userdata);

+ 13 - 5
Source/Engine/Audio/Audio.h

@@ -54,8 +54,10 @@ public:
     bool Play();
     /// Suspend sound output.
     void Stop();
-    /// Set master gain on a specific sound type such as sound effects, music or voice.
+    /// Set master gain on a specific sound type such as sound effecs, music or voice using the enum for backwards compatibility.
     void SetMasterGain(SoundType type, float gain);
+    /// Set master gain on a specific sound type such as sound effects, music or voice.
+    void SetMasterGain(const StringHash& type, float gain);
     /// Set active sound listener for 3D sounds.
     void SetListener(SoundListener* listener);
     /// Stop any sound source playing a certain sound clip.
@@ -73,13 +75,18 @@ public:
     bool IsPlaying() const { return playing_; }
     /// Return whether an audio stream has been reserved.
     bool IsInitialized() const { return deviceID_ != 0; }
-    /// Return master gain for a specific sound source type.
+    /// Return master gain for a specific sound source type by enum.
     float GetMasterGain(SoundType type) const;
+    /// Return master gain for a specific sound source type.
+    float GetMasterGain(const StringHash& type) const;
     /// Return active sound listener.
     SoundListener* GetListener() const;
     /// Return all sound sources.
     const PODVector<SoundSource*>& GetSoundSources() const { return soundSources_; }
 
+    /// Return whether the specified master gain has been defined.
+    bool IsMasterGain(const StringHash& type) const { return masterGain_.Contains(type); }
+
     /// Add a sound source to keep track of. Called by SoundSource.
     void AddSoundSource(SoundSource* soundSource);
     /// Remove a sound source. Called by SoundSource.
@@ -87,7 +94,9 @@ public:
     /// Return audio thread mutex.
     Mutex& GetMutex() { return audioMutex_; }
     /// Return sound type specific gain multiplied by master gain.
-    float GetSoundSourceMasterGain(SoundType type) const { return masterGain_[SOUND_MASTER] * masterGain_[type]; }
+    float GetSoundSourceMasterGain(SoundType type) const;
+    /// Return sound type specific gain multiplied by master gain.
+    float GetSoundSourceMasterGain(const StringHash& type) const;
 
     /// Mix sound sources into the buffer.
     void MixOutput(void *dest, unsigned samples);
@@ -97,7 +106,6 @@ private:
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     /// Stop sound output and release the sound buffer.
     void Release();
-
     /// Clipping buffer for mixing.
     SharedArrayPtr<int> clipBuffer_;
     /// Audio thread mutex.
@@ -117,7 +125,7 @@ private:
     /// Playing flag.
     bool playing_;
     /// Master gain by sound source type.
-    float masterGain_[MAX_SOUND_TYPES];
+    VariantMap masterGain_;
     /// Sound sources.
     PODVector<SoundSource*> soundSources_;
     /// Sound listener.

+ 12 - 0
Source/Engine/Audio/AudioDefs.h

@@ -22,6 +22,8 @@
 
 #pragma once
 
+#include "StringHash.h"
+
 namespace Urho3D
 {
 
@@ -36,4 +38,14 @@ enum SoundType
     MAX_SOUND_TYPES
 };
 
+static const StringHash soundTypeHashes[MAX_SOUND_TYPES] =
+{
+    "Effect",
+    "Ambient",
+    "Voice",
+    "Music",
+    "Master"
+};
+
+
 }

+ 47 - 10
Source/Engine/Audio/SoundSource.cpp

@@ -91,7 +91,13 @@ namespace Urho3D
 
 #define GET_IP_SAMPLE_RIGHT() (((((int)pos[3] - (int)pos[1]) * fractPos) / 65536) + (int)pos[1])
 
-static const char* typeNames[] =
+static const float AUTOREMOVE_DELAY = 0.25f;
+
+static const int STREAM_SAFETY_SAMPLES = 4;
+
+extern const char* AUDIO_CATEGORY;
+
+static const char* typeNames[MAX_SOUND_TYPES] =
 {
     "Effect",
     "Ambient",
@@ -100,15 +106,14 @@ static const char* typeNames[] =
     0
 };
 
-static const float AUTOREMOVE_DELAY = 0.25f;
-
-static const int STREAM_SAFETY_SAMPLES = 4;
-
-extern const char* AUDIO_CATEGORY;
+template<> SoundType Variant::Get<SoundType>() const
+{
+    return static_cast<SoundType>(GetInt());
+}
 
 SoundSource::SoundSource(Context* context) :
     Component(context),
-    soundType_(SOUND_EFFECT),
+    soundType_(soundTypeHashes[SOUND_EFFECT]),
     frequency_(0.0f),
     gain_(1.0f),
     attenuation_(1.0f),
@@ -138,14 +143,15 @@ void SoundSource::RegisterObject(Context* context)
 
     ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
     MIXED_ACCESSOR_ATTRIBUTE("Sound", GetSoundAttr, SetSoundAttr, ResourceRef, ResourceRef(Sound::GetTypeStatic()), AM_DEFAULT);
-    ENUM_ATTRIBUTE("Sound Type", soundType_, typeNames, SOUND_EFFECT, AM_DEFAULT);
+    ENUM_ACCESSOR_ATTRIBUTE("Sound Type", GetSoundTypeAttr, SetSoundTypeAttr, SoundType, typeNames, SOUND_MASTER, AM_EDIT | AM_READ);
+    ATTRIBUTE("Type", StringHash, soundType_, soundTypeHashes[SOUND_EFFECT], AM_DEFAULT);
     ATTRIBUTE("Frequency", float, frequency_, 0.0f, AM_DEFAULT);
     ATTRIBUTE("Gain", float, gain_, 1.0f, AM_DEFAULT);
     ATTRIBUTE("Attenuation", float, attenuation_, 1.0f, AM_DEFAULT);
     ATTRIBUTE("Panning", float, panning_, 0.0f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE("Is Playing", IsPlaying, SetPlayingAttr, bool, false, AM_DEFAULT);
     ATTRIBUTE("Autoremove on Stop", bool, autoRemove_, false, AM_FILE);
-    ACCESSOR_ATTRIBUTE("Play Position", GetPositionAttr, SetPositionAttr, int, 0, AM_FILE);
+    ACCESSOR_ATTRIBUTE("Play Position", GetPositionAttr, SetPositionAttr, int, 0, AM_FILE);
 }
 
 void SoundSource::Play(Sound* sound)
@@ -240,6 +246,18 @@ void SoundSource::SetSoundType(SoundType type)
     if (type == SOUND_MASTER || type >= MAX_SOUND_TYPES)
         return;
 
+    soundType_ = soundTypeHashes[type];
+    MarkNetworkUpdate();
+}
+
+void SoundSource::SetSoundType(const StringHash& type)
+{
+    if (type == soundTypeHashes[SOUND_MASTER])
+        return;
+
+    if (!audio_->IsMasterGain(type))
+        audio_->SetMasterGain(type, 1.0f);
+
     soundType_ = type;
     MarkNetworkUpdate();
 }
@@ -458,6 +476,26 @@ int SoundSource::GetPositionAttr() const
         return 0;
 }
 
+SoundType SoundSource::GetSoundTypeAttr() const
+{
+    for (int i; i < MAX_SOUND_TYPES; i++)
+    {
+        if (soundType_ == soundTypeHashes[i])
+            return static_cast<SoundType>(i);
+    }
+
+    // Valid as this defaults to 0 in type names.
+    return SOUND_MASTER;
+}
+
+void SoundSource::SetSoundTypeAttr(SoundType type)
+{
+    // Ensure that we don't set twice via normal attribute and backwards compatibility attribute.
+    if (soundType_ == StringHash::ZERO)
+        SetSoundType(type);
+}
+
+
 void SoundSource::PlayLockless(Sound* sound)
 {
     // Reset the time position in any case
@@ -619,7 +657,6 @@ void SoundSource::MixMonoToMono(Sound* sound, int* dest, unsigned samples, int m
             position_ = pos;
         }
     }
-
     fractPosition_ = fractPos;
 }
 

+ 17 - 11
Source/Engine/Audio/SoundSource.h

@@ -39,7 +39,7 @@ static const int STREAM_BUFFER_LENGTH = 100;
 class URHO3D_API SoundSource : public Component
 {
     OBJECT(SoundSource);
-
+    
 public:
     /// Construct.
     SoundSource(Context* context);
@@ -47,7 +47,7 @@ public:
     virtual ~SoundSource();
     /// Register object factory.
     static void RegisterObject(Context* context);
-
+    
     /// Play a sound.
     void Play(Sound* sound);
     /// Play a sound with specified frequency.
@@ -60,8 +60,10 @@ public:
     void Play(SoundStream* stream);
     /// Stop playback.
     void Stop();
+    /// Set sound type, determines the master gain group by enum.
+    void SetSoundType(SoundType type);   
     /// Set sound type, determines the master gain group.
-    void SetSoundType(SoundType type);
+    void SetSoundType(const StringHash& type);
     /// Set frequency.
     void SetFrequency(float frequency);
     /// Set gain. 0.0 is silence, 1.0 is full volume.
@@ -74,13 +76,13 @@ public:
     void SetAutoRemove(bool enable);
     /// Set new playback position.
     void SetPlayPosition(signed char* pos);
-
+    
     /// Return sound.
     Sound* GetSound() const { return sound_; }
     /// Return playback position.
     volatile signed char* GetPlayPosition() const { return position_; }
     /// Return sound type, determines the master gain group.
-    SoundType GetSoundType() const { return soundType_; }
+    StringHash GetSoundType() const { return soundType_; }
     /// Return playback time position.
     float GetTimePosition() const { return timePosition_; }
     /// Return frequency.
@@ -95,12 +97,12 @@ public:
     bool GetAutoRemove() const { return autoRemove_; }
     /// Return whether is playing.
     bool IsPlaying() const;
-
+    
     /// Update the sound source. Perform subclass specific operations. Called by Audio.
     virtual void Update(float timeStep);
     /// Mix sound source output to a 32-bit clipping buffer. Called by Audio.
     void Mix(int* dest, unsigned samples, int mixRate, bool stereo, bool interpolation);
-
+    
     /// Set sound attribute.
     void SetSoundAttr(const ResourceRef& value);
     /// Set sound position attribute.
@@ -111,12 +113,16 @@ public:
     void SetPlayingAttr(bool value);
     /// Return sound position attribute.
     int GetPositionAttr() const;
-
+    /// Set sound type attribute for backwards compatibility.
+    void SetSoundTypeAttr(SoundType type);
+    /// Return sound type attribute for backwards compatibility.
+    SoundType GetSoundTypeAttr() const;
+    
 protected:
     /// Audio subsystem.
     WeakPtr<Audio> audio_;
     /// SoundSource type, determines the master gain group.
-    SoundType soundType_;
+    StringHash soundType_;
     /// Frequency.
     float frequency_;
     /// Gain.
@@ -129,7 +135,7 @@ protected:
     float autoRemoveTimer_;
     /// Autoremove flag.
     bool autoRemove_;
-
+    
 private:
     /// Play a sound without locking the audio mutex. Called internally.
     void PlayLockless(Sound* sound);
@@ -159,7 +165,7 @@ private:
     void MixZeroVolume(Sound* sound, unsigned samples, int mixRate);
     /// Advance playback pointer to simulate audio playback in headless mode.
     void MixNull(float timeStep);
-
+    
     /// Sound that is being played.
     SharedPtr<Sound> sound_;
     /// Sound stream that is being played.