Explorar el Código

Added Channel::getTimePosition().
Simulated sound playback uses the time position to also support compressed sounds.

Lasse Öörni hace 15 años
padre
commit
925512a1f9
Se han modificado 4 ficheros con 88 adiciones y 71 borrados
  1. 69 57
      Engine/Audio/Channel.cpp
  2. 4 0
      Engine/Audio/Channel.h
  3. 14 14
      Engine/Common/HashedType.h
  4. 1 0
      Engine/Engine/RegisterTemplates.h

+ 69 - 57
Engine/Audio/Channel.cpp

@@ -30,55 +30,55 @@
 
 #include "DebugNew.h"
 
-#define INC_POS_LOOPED()        \
-    pos += intAdd;              \
-    fractPos += fractAdd;       \
-    if (fractPos > 65535)       \
-    {                           \
-        fractPos &= 65535;      \
-        ++pos;                  \
-    }                           \
-    while (pos >= end)          \
-        pos -= (end - repeat);  \
+#define INC_POS_LOOPED() \
+    pos += intAdd; \
+    fractPos += fractAdd; \
+    if (fractPos > 65535) \
+    { \
+        fractPos &= 65535; \
+        ++pos; \
+    } \
+    while (pos >= end) \
+        pos -= (end - repeat); \
 
-#define INC_POS_ONESHOT()       \
-    pos += intAdd;              \
-    fractPos += fractAdd;       \
-    if (fractPos > 65535)       \
-    {                           \
-        fractPos &= 65535;      \
-        ++pos;                  \
-    }                           \
-    if (pos >= end)             \
-    {                           \
-        pos = 0;                \
-        break;                  \
-    }                           \
+#define INC_POS_ONESHOT() \
+    pos += intAdd; \
+    fractPos += fractAdd; \
+    if (fractPos > 65535) \
+    { \
+        fractPos &= 65535; \
+        ++pos; \
+    } \
+    if (pos >= end) \
+    { \
+        pos = 0; \
+        break; \
+    } \
 
 #define INC_POS_STEREO_LOOPED() \
-    pos += (intAdd << 1);       \
-    fractPos += fractAdd;       \
-    if (fractPos > 65535)       \
-    {                           \
-        fractPos &= 65535;      \
-        pos += 2;               \
-    }                           \
-    while (pos >= end)          \
-        pos -= (end - repeat);  \
+    pos += (intAdd << 1); \
+    fractPos += fractAdd; \
+    if (fractPos > 65535) \
+    { \
+        fractPos &= 65535; \
+        pos += 2; \
+    } \
+    while (pos >= end) \
+        pos -= (end - repeat); \
 
-#define INC_POS_STEREO_ONESHOT()\
-    pos += (intAdd << 1);       \
-    fractPos += fractAdd;       \
-    if (fractPos > 65535)       \
-    {                           \
-        fractPos &= 65535;      \
-        pos += 2;               \
-    }                           \
-    if (pos >= end)             \
-    {                           \
-        pos = 0;                \
-        break;                  \
-    }                           \
+#define INC_POS_STEREO_ONESHOT() \
+    pos += (intAdd << 1); \
+    fractPos += fractAdd; \
+    if (fractPos > 65535) \
+    { \
+        fractPos &= 65535; \
+        pos += 2; \
+    } \
+    if (pos >= end) \
+    { \
+        pos = 0; \
+        break; \
+    } \
 
 #define GET_IP_SAMPLE() (((((int)pos[1] - (int)pos[0]) * fractPos) / 65536) + (int)pos[0])
 
@@ -93,6 +93,7 @@ Channel::Channel(Audio* audio) :
     mAudio(audio),
     mPos(0),
     mFractPos(0),
+    mTimePos(0.0f),
     mChannelType(CHANNEL_EFFECT),
     mFrequency(0.0f),
     mGain(1.0f),
@@ -225,6 +226,9 @@ void Channel::setPlayPosition(signed char* pos)
 
 void Channel::playLockless(Sound* sound)
 {
+    // Reset the time position in any case
+    mTimePos = 0.0f;
+    
     if (sound)
     {
         if (!sound->isCompressed())
@@ -270,6 +274,7 @@ void Channel::playLockless(Sound* sound)
 void Channel::stopLockless()
 {
     mPos = 0;
+    mTimePos = 0.0f;
 }
 
 void Channel::setPlayPositionLockless(signed char* pos)
@@ -288,6 +293,7 @@ void Channel::setPlayPositionLockless(signed char* pos)
         pos = end;
     
     mPos = pos;
+    mTimePos = (float)((int)pos - (int)mSound->getStart()) / (mSound->getSampleSize() * mSound->getFrequency());
 }
 
 void Channel::update(float timeStep)
@@ -356,7 +362,10 @@ void Channel::mix(int* dest, unsigned samples, int mixRate, bool stereo, bool in
             if (eof)
             {
                 if (mSound->isLooped())
+                {
                     mSound->rewindDecoder(mDecoder);
+                    mTimePos = 0.0f;
+                }
                 else
                     mDecodeBuffer->setOneshot(); // Stop after the current decode buffer has been played
             }
@@ -425,6 +434,12 @@ void Channel::mix(int* dest, unsigned samples, int mixRate, bool stereo, bool in
                 mixStereoToMono(sound, dest, samples, mixRate);
         }
     }
+    
+    // Update the time position
+    if (!mSound->isCompressed())
+        mTimePos = (float)((int)mPos - (int)mSound->getStart()) / (mSound->getSampleSize() * mSound->getFrequency());
+    else
+        mTimePos += ((float)samples / (float)mixRate) * mFrequency / mSound->getFrequency();
 }
 
 void Channel::mixMonoToMono(Sound* sound, int* dest, unsigned samples, int mixRate)
@@ -1091,25 +1106,22 @@ void Channel::mixNull(float timeStep)
     if ((!mPos) || (!mSound))
         return;
     
-    // Can not support simulated playback of compressed sounds
-    if (mSound->isCompressed())
-        return;
-    
-    // Calculate approximate advance to sample pos
-    int advance = (int)(mFrequency * timeStep) * mSound->getSampleSize();
-    signed char* end = mSound->getEnd();
-    signed char* repeat = mSound->getRepeat();
+    // Advance only the time position
+    mTimePos += timeStep * mFrequency / mSound->getFrequency();
     
-    mPos += advance;
     if (mSound->isLooped())
     {
-        while (mPos >= end)
-            mPos -= (end - repeat);
+        // For simulated playback, simply reset the time position to zero when the sound loops
+        if (mTimePos >= mSound->getLength())
+            mTimePos -= mSound->getLength();
     }
     else
     {
-        if (mPos >= end)
+        if (mTimePos >= mSound->getLength())
+        {
             mPos = 0;
+            mTimePos = 0.0f;
+        }
     }
 }
 

+ 4 - 0
Engine/Audio/Channel.h

@@ -76,6 +76,8 @@ public:
     volatile signed char* getPlayPosition() const { return mPos; }
     //! Return channel type
     ChannelType getChannelType() const { return mChannelType; }
+    //! Return playback time position
+    float getTimePosition() const { return mTimePos; }
     //! Return frequency
     float getFrequency() const { return mFrequency; }
     //! Return gain
@@ -142,6 +144,8 @@ private:
     volatile signed char *mPos;
     //! Playback fractional position
     volatile int mFractPos;
+    //! Playback time position
+    volatile float mTimePos;
     //! Audio data decoder
     void* mDecoder;
     //! Decode buffer

+ 14 - 14
Engine/Common/HashedType.h

@@ -27,20 +27,20 @@
 #include "RefCount.h"
 #include "StringHash.h"
 
-#define DEFINE_TYPE(typeName)                                                               \
-    public:                                                                                 \
-        virtual ShortStringHash getType() const { return getTypeStatic(); }                 \
-        virtual const std::string& getTypeName() const { return getTypeNameStatic(); }      \
-        static ShortStringHash getTypeStatic()                                              \
-        {                                                                                   \
-            static const ShortStringHash type(#typeName);                                   \
-            return type;                                                                    \
-        }                                                                                   \
-        static const std::string& getTypeNameStatic()                                       \
-        {                                                                                   \
-            static const std::string name = #typeName;                                      \
-            return name;                                                                    \
-        }                                                                                   \
+#define DEFINE_TYPE(typeName) \
+    public: \
+        virtual ShortStringHash getType() const { return getTypeStatic(); } \
+        virtual const std::string& getTypeName() const { return getTypeNameStatic(); } \
+        static ShortStringHash getTypeStatic() \
+        { \
+            static const ShortStringHash type(#typeName); \
+            return type; \
+        } \
+        static const std::string& getTypeNameStatic() \
+        { \
+            static const std::string name = #typeName; \
+            return name; \
+        } \
 
 //! Base class for objects which can be searched for by type
 class HashedType : public RefCounted

+ 1 - 0
Engine/Engine/RegisterTemplates.h

@@ -249,6 +249,7 @@ template <class T> void registerChannel(asIScriptEngine* engine, const char* cla
     engine->RegisterObjectMethod(className, "void setPanning(float)", asMETHODPR(T, setPanning, (float), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Sound@+ getSound() const", asMETHODPR(T, getSound, () const, Sound*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "ChannelType getChannelType() const", asMETHODPR(T, getChannelType, () const, ChannelType), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "float getTimePosition() const", asMETHODPR(T, getTimePosition, () const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "float getFrequency() const", asMETHODPR(T, getFrequency, () const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "float getGain() const", asMETHODPR(T, getGain, () const, float), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "float getAttenuation() const", asMETHODPR(T, getAttenuation, () const, float), asCALL_THISCALL);