Browse Source

Positional Audio Update
- Audio Descriptions
- SceneObject Audio functions
- Scene Debug Mode "audio"

capnlove 9 years ago
parent
commit
ef7be585db

+ 2 - 0
engine/compilers/VisualStudio 2015/Torque 2D.vcxproj

@@ -296,6 +296,7 @@
     <ClCompile Include="..\..\source\assets\declaredAssets.cc" />
     <ClCompile Include="..\..\source\assets\referencedAssets.cc" />
     <ClCompile Include="..\..\source\audio\AudioAsset.cc" />
+    <ClCompile Include="..\..\source\audio\audioDescriptions.cc" />
     <ClCompile Include="..\..\source\audio\audio_ScriptBinding.cc" />
     <ClCompile Include="..\..\source\audio\vorbisStreamSource.cc" />
     <ClCompile Include="..\..\source\bitmapFont\BitmapFont.cc" />
@@ -763,6 +764,7 @@
     <ClInclude Include="..\..\source\assets\tamlAssetReferencedUpdateVisitor.h" />
     <ClInclude Include="..\..\source\assets\tamlAssetReferencedVisitor.h" />
     <ClInclude Include="..\..\source\audio\AudioAsset.h" />
+    <ClInclude Include="..\..\source\audio\audioDescriptions.h" />
     <ClInclude Include="..\..\source\audio\vorbisStreamSource.h" />
     <ClInclude Include="..\..\source\bitmapFont\BitmapFont.h" />
     <ClInclude Include="..\..\source\bitmapFont\BitmapFontCharacter.h" />

+ 6 - 0
engine/compilers/VisualStudio 2015/Torque 2D.vcxproj.filters

@@ -1440,6 +1440,9 @@
     <ClCompile Include="..\..\source\bitmapFont\BitmapFontCharacter.cc">
       <Filter>bitmapFont</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\audio\audioDescriptions.cc">
+      <Filter>audio</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -3192,6 +3195,9 @@
     <ClInclude Include="..\..\source\bitmapFont\BitmapFontLineInfo.h">
       <Filter>bitmapFont</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\audio\audioDescriptions.h">
+      <Filter>audio</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 30 - 2
engine/source/2d/gui/SceneWindow.cc

@@ -113,7 +113,8 @@ SceneWindow::SceneWindow() :    mpScene(NULL),
                                 mUseObjectInputEvents(false),
                                 mInputEventGroupMaskFilter(MASK_ALL),
                                 mInputEventLayerMaskFilter(MASK_ALL),
-                                mInputEventInvisibleFilter( true )
+                                mInputEventInvisibleFilter( true ),
+                                mProcessAudioListener(false)
 {
     // Set Vector Associations.
     VECTOR_SET_ASSOCIATION( mCameraQueue );
@@ -419,6 +420,13 @@ void SceneWindow::setCameraInterpolationMode( const CameraInterpolationMode inte
 
 //-----------------------------------------------------------------------------
 
+void SceneWindow::setProcessAudioListener(bool mval)
+{
+    mProcessAudioListener = mval;
+}
+
+//-----------------------------------------------------------------------------
+
 void SceneWindow::startCameraMove( const F32 interpolationTime )
 {
     // Are we mounted to an object and trying to move?
@@ -1462,6 +1470,8 @@ void SceneWindow::processTick( void )
     // Debug Profiling.
     PROFILE_SCOPE(SceneWindow_ProcessTick);
 
+    Point2F PreMove_CameraPos = mCameraCurrent.mSourceArea.centre();
+    F32 PreMove_CameraZoom = mCameraCurrent.mCameraZoom;
     // Are we moving the camera.
     if ( mMovingCamera )
     {
@@ -1505,7 +1515,25 @@ void SceneWindow::processTick( void )
             // No, so stop shake.
             stopCameraShake();
         }
-    }    
+    }
+    if (mProcessAudioListener)
+    {
+        F32 listenervelocity[] = { 0.f, 0.f, 0.f };
+
+        Point2F campos = mCameraCurrent.mSourceArea.centre();
+
+        if (campos != PreMove_CameraPos)
+        {
+            listenervelocity[0] = (campos.x - PreMove_CameraPos.x) * Tickable::smTickSec;
+            listenervelocity[1] = (campos.y - PreMove_CameraPos.y) * Tickable::smTickSec;
+            listenervelocity[2] = (mCameraCurrent.mCameraZoom - PreMove_CameraZoom) * Tickable::smTickSec;
+        }
+
+        F32 listenerpos[] = { campos.x, campos.y, 5.f };
+
+        alListenerfv(AL_POSITION, listenerpos);
+        alListenerfv(AL_VELOCITY, listenervelocity);
+    }
 }
 
 //-----------------------------------------------------------------------------

+ 9 - 0
engine/source/2d/gui/SceneWindow.h

@@ -141,6 +141,9 @@ private:
     U32                 mRenderLayerMask;
     U32                 mRenderGroupMask;
 
+    //Audio Listener
+    bool                mProcessAudioListener;
+
     char                mDebugText[256];
 
     /// Handling Input Events.
@@ -264,6 +267,9 @@ public:
     void setCameraInterpolationTime( const F32 interpolationTime );
     void setCameraInterpolationMode( const CameraInterpolationMode interpolationMode );
 
+    /// Audio Listener
+    void setProcessAudioListener(bool mval);
+
     /// Camera Movement.
     void startCameraMove( const F32 interpolationTime );
     void stopCameraMove( void );
@@ -281,6 +287,9 @@ public:
     inline bool isCameraMounted( void ) const                           { return mCameraMounted; }
     inline bool isCameraMoving( void ) const                            { return mMovingCamera; }
 
+    /// Audio Listener
+    inline bool isProcessAudioListener(void) const { return mProcessAudioListener; }
+
     /// Camera Shake.
     void startCameraShake( const F32 magnitude, const F32 time );
     void stopCameraShake( void );

+ 12 - 0
engine/source/2d/gui/SceneWindow_ScriptBinding.h

@@ -1545,4 +1545,16 @@ ConsoleMethodWithDocs(SceneWindow, getIsWindowPoint, ConsoleBool, 3, 4, (X / Y))
     return object->mBounds.pointInRect( Point2I( S32(mFloor(dstPoint.x)+object->mBounds.point.x), S32(mFloor(dstPoint.y)+object->mBounds.point.y )) );
 }
 
+/*! Sets this Scenewindow to process the AudioListener's position and velocity
+    WARNING : The code does not verify if multiple SceneWindows have this function enabled.
+              User must make sure to manage this manually. Multiple listeners may lead to crashes/bugs/unexpected behaviors.
+    @param status - Whether to enable or disable AudioListener processing (optional, default to true)
+*/
+ConsoleMethodWithDocs(SceneWindow, setAudioListener, ConsoleVoid, 2, 3, ())
+{
+    bool onoff = true;
+    if ((argc > 2) && !dAtob(argv[2])) onoff = false;
+    object->setProcessAudioListener(onoff);
+}
+
 ConsoleMethodGroupEndWithDocs(SceneWindow)

+ 1 - 0
engine/source/2d/scene/Scene.cc

@@ -5272,6 +5272,7 @@ static EnumTable::Enums DebugOptionsLookup[] =
                 { Scene::SCENE_DEBUG_CONTROLLERS,       "controllers" },
                 { Scene::SCENE_DEBUG_JOINTS,            "joints" },
                 { Scene::SCENE_DEBUG_WIREFRAME_RENDER,  "wireframe" },
+                { Scene::SCENE_DEBUG_AUDIO_SOURCES,     "audio"},
                 ///
                 { Scene::SCENE_DEBUG_AABB,              "aabb" },
                 { Scene::SCENE_DEBUG_OOBB,              "oobb" },

+ 1 - 0
engine/source/2d/scene/Scene.h

@@ -183,6 +183,7 @@ public:
         SCENE_DEBUG_CONTROLLERS        = BIT(2), 
         SCENE_DEBUG_JOINTS             = BIT(3),
         SCENE_DEBUG_WIREFRAME_RENDER   = BIT(4),
+        SCENE_DEBUG_AUDIO_SOURCES      = BIT(5),
         ///
         SCENE_DEBUG_AABB               = BIT(16),
         SCENE_DEBUG_OOBB               = BIT(17),

+ 94 - 0
engine/source/2d/sceneobject/SceneObject.cc

@@ -202,6 +202,8 @@ SceneObject::SceneObject() :
     VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs );
     VECTOR_SET_ASSOCIATION( mCollisionFixtures );
     VECTOR_SET_ASSOCIATION( mAttachedCtrls );
+    VECTOR_SET_ASSOCIATION( mAudioHandles );
+    VECTOR_SET_ASSOCIATION( mHandleDeletionList );
 
     // Assign scene-object index.
     mSerialId = ++sSceneObjectMasterSerialId;
@@ -256,6 +258,16 @@ SceneObject::~SceneObject()
         mpScene->removeFromScene( this );
     }
 
+    if (mAudioHandles.size())
+        {
+        for (typeAudioHandleVector::iterator itr = mAudioHandles.begin(); itr != mAudioHandles.end(); ++itr)
+            {
+            U32 handle = *itr;
+            alxStop(handle);
+            }
+        mAudioHandles.clear();
+        }
+
     // Decrease scene-object count.
     --sGlobalSceneObjectCount;
 }
@@ -563,6 +575,9 @@ void SceneObject::preIntegrate( const F32 totalTime, const F32 elapsedTime, Debu
 		updateSize(elapsedTime);
 	}
 
+    if (mAudioHandles.size())
+        refreshsources();
+
    // Finish if nothing is dirty.
     if ( !mSpatialDirty )
         return;
@@ -640,6 +655,17 @@ void SceneObject::integrateObject( const F32 totalTime, const F32 elapsedTime, D
 	{
 		updateBlendColor( elapsedTime );
 	}
+
+    if (mAudioHandles.size())
+    {
+        for (typeAudioHandleVector::iterator itr = mAudioHandles.begin(); itr != mAudioHandles.end(); ++itr)
+        {
+            U32 handle = *itr;
+            Point2F vel = getLinearVelocity();
+            alxSource3f(handle, AL_POSITION, position.x, position.y, 0.f);
+            alxSource3f(handle, AL_VELOCITY, vel.x, vel.y, 0.f);
+        }
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -861,6 +887,24 @@ void SceneObject::sceneRenderOverlay( const SceneRenderState* sceneRenderState )
     {
         pScene->mDebugDraw.DrawSortPoint( getRenderPosition(), getSize(), mSortPoint );
     }
+
+    if (debugMask & Scene::SCENE_DEBUG_AUDIO_SOURCES)
+        {
+            if (mAudioHandles.size())
+            {
+                for (typeAudioHandleVector::iterator itr = mAudioHandles.begin(); itr != mAudioHandles.end(); ++itr)
+                {
+                    U32 handle = *itr;
+                    ALfloat MaxDistance = 0.f;
+                    ALfloat RefDistance = 0.f;
+                    alxGetSourcef(handle, AL_MAX_DISTANCE, &MaxDistance);
+                    alxGetSourcef(handle, AL_REFERENCE_DISTANCE, &RefDistance);
+                    pScene->mDebugDraw.DrawCircle(getRenderPosition(), MaxDistance, ColorF(1.f, 0.2f, 0.2f));
+                    pScene->mDebugDraw.DrawCircle(getRenderPosition(), RefDistance, ColorF(1.f, 0.0f, 0.0f));
+                }
+            }
+        
+         }
 }
 
 //-----------------------------------------------------------------------------
@@ -4030,6 +4074,56 @@ bool SceneObject::writeField(StringTableEntry fieldname, const char* value)
    return true;
 }
 
+void SceneObject::addAudioHandle(AUDIOHANDLE handle)
+{
+   mAudioHandles.push_back_unique(handle);
+   Con::printf("New Vector size : %i", mAudioHandles.size());
+}
+
+S32 SceneObject::getSoundsCount(void)
+{
+    return mAudioHandles.size();
+}
+
+U32 SceneObject::getSound(S32 index)
+{
+    if (mAudioHandles.size() - 1 < index)
+        return NULL_AUDIOHANDLE;
+    U32 handle = mAudioHandles[index];
+    return handle;
+}
+
+void SceneObject::refreshsources()
+{
+    if (mAudioHandles.size())
+    {
+        S32 index = 0;
+        for (typeAudioHandleVector::iterator itr = mAudioHandles.begin(); itr != mAudioHandles.end(); ++itr)
+        {
+            U32 handle = *itr;
+            
+            if (handle) {
+                   
+                if (!alxIsValidHandle(handle))
+                    mHandleDeletionList.push_back(index);
+
+                    index++;
+                        }
+         }
+        
+         if (mHandleDeletionList.size())
+         {
+
+            for (Vector<S32>::iterator delitr = mHandleDeletionList.begin(); delitr != mHandleDeletionList.end(); ++delitr)
+                {
+                mAudioHandles.erase(*delitr);
+                }
+            mHandleDeletionList.clear();
+         }
+    }
+}
+
+
 //------------------------------------------------------------------------------
 
 S32 QSORT_CALLBACK SceneObject::sceneObjectLayerDepthSort(const void* a, const void* b)

+ 9 - 0
engine/source/2d/sceneobject/SceneObject.h

@@ -80,6 +80,7 @@ struct tDestroyNotification
 typedef VectorPtr<b2FixtureDef*> typeCollisionFixtureDefVector;
 typedef VectorPtr<b2Fixture*> typeCollisionFixtureVector;
 typedef Vector<tDestroyNotification> typeDestroyNotificationVector;
+typedef Vector<U32> typeAudioHandleVector;
 
 //-----------------------------------------------------------------------------
 
@@ -189,6 +190,8 @@ protected:
     /// General collision shape access.
     typeCollisionFixtureDefVector mCollisionFixtureDefs;
     typeCollisionFixtureVector mCollisionFixtures;
+    typeAudioHandleVector mAudioHandles;
+    Vector<S32> mHandleDeletionList; //Used for Audio source maintenance & deletion
 
     /// Render visibility.
     bool                    mVisible;
@@ -607,6 +610,12 @@ public:
     static U32              getGlobalSceneObjectCount( void );
     inline U32              getSerialId( void ) const                   { return mSerialId; }
 
+    // Audio
+    void addAudioHandle(AUDIOHANDLE handle);
+    U32                 getSound(S32 index);
+    S32                 getSoundsCount();
+    void                refreshsources();
+
     // Read / Write fields.
     virtual bool            writeField(StringTableEntry fieldname, const char* value);
 

+ 115 - 0
engine/source/2d/sceneobject/SceneObject_ScriptBinding.h

@@ -20,6 +20,9 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#ifndef _AUDIODESCRIPTION_H_
+#include "audio/audioDescriptions.h"
+#endif
 /*! Gets the system-wide scene-object count.
     @return The system-wide scene-object count.
 */
@@ -4469,4 +4472,116 @@ ConsoleMethodWithDocs(SceneObject, safeDelete, ConsoleVoid, 2, 2, ())
     object->safeDelete();
 }
 
+/*! Plays a sound at the object's location
+@param AudioAsset - The Audio Asset to play
+@param AudioDescription - Sets the audio Description. If omitted,  (optional)
+@return returns the audio handle
+*/
+ConsoleMethodWithDocs(SceneObject, playSound, ConsoleInt, 3, 4, ())
+{
+    // Fetch asset Id.    
+    const char* pAssetId = argv[2];
+
+    // Acquire audio asset.
+    AudioAsset* pAudioAsset = AssetDatabase.acquireAsset<AudioAsset>(pAssetId);
+
+    // Did we get the audio asset?
+    if (pAudioAsset == NULL)
+    {
+        // No, so warn.
+        Con::warnf("alxPlay() - Could not find audio asset '%s'.", pAssetId);
+        return NULL_AUDIOHANDLE;
+    }
+    AudioDescription* AD;
+
+    if (argc > 3)
+    {
+        AD = static_cast<AudioDescription*>(Sim::findObject(argv[3]));
+    }
+    else
+    {
+        AD = new AudioDescription();
+    }
+
+    Vector2 pos = object->getPosition();
+    Vector2 vel = object->getLinearVelocity();
+    Point3F realpos;
+    Point3F velocity;
+
+    realpos.x = pos.x;
+    realpos.y = pos.y;
+    realpos.z = 0.f;
+
+    MatrixF transform(false);
+    transform.setColumn(3, realpos);
+
+    //If the source is not looping and outside of listener range, it is not created, handle = 0
+    AUDIOHANDLE handle = alxCreateSource_AD(pAudioAsset, AD, &transform);
+    if (!handle) return (0);
+    //alxplay returns the same handle as alxCreateSource
+    alxPlay(handle);
+    alxSource3f(handle, AL_POSITION, realpos.x, realpos.y, 0.f);
+
+    // Release asset.
+    AssetDatabase.releaseAsset(pAssetId);
+    object->addAudioHandle(handle);
+    return handle;
+}
+
+/*! Stops a sound attached to a SceneObject
+@param Index - The Index of the sound (obtained via getSoundatIndex)
+*/
+ConsoleMethodWithDocs(SceneObject, stopSound, ConsoleVoid, 3, 3, (S32 index))
+{
+    const S32 index = dAtoi(argv[2]);
+    
+    if (!object->getSoundsCount())
+        {
+        Con::warnf("No sounds on this object. Can't stop. WON't stop.");
+        return;
+        }    
+    
+    U32 handle = object->getSound(index);
+
+
+    if (!handle)
+    {
+        Con::warnf("Unable to find Sound Handle at index %i", index);
+        return;
+    }
+
+    alxStop(handle);
+    object->refreshsources();
+}
+
+/*! gets the amount of sounds currently attached to a SceneObject
+@return returns the Amount of sounds currently attached to the SceneObject
+*/
+ConsoleMethodWithDocs(SceneObject, getSoundsCount, ConsoleInt, 2, 2, ())
+{
+    return object->getSoundsCount();
+}
+
+/*! Gets the handle of a sound at specified index
+@param Index - The Index of the sound (obtained via getSoundatIndex)
+@return returns the handle of a sound
+*/
+ConsoleMethodWithDocs(SceneObject, getSoundatIndex, ConsoleInt, 3, 3, ())
+{
+    U32 size = object->getSoundsCount();
+    if (!size)
+    {
+        Con::printf("No sounds on this object.");
+        return 0;
+    }
+
+    U32 handle = object->getSound(dAtoi(argv[2]));
+    if (!handle)
+    {
+        Con::printf("Not a valid handle at index %i", dAtoi(argv[2]));
+        return 0;
+    }
+
+    return handle;
+}
 ConsoleMethodGroupEndWithDocs(SceneObject)

+ 39 - 0
engine/source/audio/audio.cc

@@ -22,6 +22,7 @@
 
 #include "audio/audio.h"
 #include "audio/audioDataBlock.h"
+#include "audio/audioDescriptions.h"
 #include "collection/vector.h"
 #include "console/console.h"
 #include "console/consoleTypes.h"
@@ -872,6 +873,30 @@ AUDIOHANDLE alxCreateSource(const AudioAsset *profile, const MatrixF *transform)
 }
 
 //--------------------------------------------------------------------------
+AUDIOHANDLE alxCreateSource_AD(const AudioAsset *profile, const AudioDescription* description, const MatrixF *transform)
+{
+        //Since we don't want to modify AudioAssets all the time
+            //here is a version which accepts a script-defined AudioDescription
+        if (profile == NULL)
+        return NULL_AUDIOHANDLE;
+    
+        Audio::Description newAD;
+    newAD.mVolume = description->mVolume;
+    newAD.mVolumeChannel = description->mVolumeChannel;
+    newAD.mConeInsideAngle = description->mConeInsideAngle;
+    newAD.mConeOutsideAngle = description->mConeOutsideAngle;
+    newAD.mConeOutsideVolume = description->mConeOutsideVolume;
+    newAD.mConeVector = description->mConeVector;
+    newAD.mEnvironmentLevel = description->mEnvironmentLevel;
+    newAD.mIs3D = description->mIs3D;
+    newAD.mIsLooping = description->mIsLooping;
+    newAD.mIsStreaming = description->mIsStreaming;
+    newAD.mMaxDistance = description->mMaxDistance;
+    newAD.mReferenceDistance = description->mReferenceDistance;
+    
+        return alxCreateSource(newAD, profile->getAudioFile(), transform, NULL);
+    }
+//--------------------------------------------------------------------------
 
 extern void threadPlay(AudioBuffer * buffer, AUDIOHANDLE handle);
 
@@ -2541,8 +2566,22 @@ bool OpenALInit()
    // Similiar to DSound Model w/o min distance clamping
    alEnable(AL_DISTANCE_MODEL);
    alDistanceModel(AL_INVERSE_DISTANCE);
+   alDopplerFactor(1.f);
    alListenerf(AL_GAIN_LINEAR, 1.f);
 
+   //The audio listener is initialized at position 0,0
+   //Listener orientation
+   //The first three values represent an "at" vector which points towards the screen.
+   //The second set of three values represent the "up" vector (Y+)
+
+   F32 listenerPos[] = { 0.f, 0.f, 0.f };
+   F32 listenerVel[] = { 0.f, 0.f, 0.f };
+   F32 listenerOrientation[] = { 0.f, 0.f, -1.0f, 0.f, 1.f, 0.f };
+
+   alListenerfv(AL_POSITION, listenerPos);
+   alListenerfv(AL_VELOCITY, listenerVel);
+   alListenerfv(AL_ORIENTATION, listenerOrientation);
+
    return true;
 }
 

+ 57 - 0
engine/source/audio/audioDescriptions.cc

@@ -0,0 +1,57 @@
+#ifndef _AUDIODESCRIPTION_H_
+#include "audio\audioDescriptions.h"
+#endif
+
+#include "audio/audio.h"
+
+#include "console/consoleTypes.h"
+#include "platform/platformAL.h"
+
+IMPLEMENT_CO_DATABLOCK_V1(AudioDescription);
+
+AudioDescription::AudioDescription()
+{
+    mVolume = 1.f;  // 0-1    1=loudest volume
+    mVolumeChannel = 1;
+    mIsLooping = false;
+    mIsStreaming = false;
+
+    mIs3D = true; //The default class is used with SceneObject.Playsound
+
+    mReferenceDistance = 25.f;
+    mRollOffFactor = 5.0f;
+    mMaxDistance = 50.f;
+
+    mConeInsideAngle = 360;
+    mConeOutsideAngle = 360;
+    mConeOutsideVolume = 1.0f;
+    mConeVector = { 0.f, 0.f, 1.f };
+
+    // environment info
+    mEnvironmentLevel = 0.f;
+}
+
+void AudioDescription::initPersistFields()
+{
+    Parent::initPersistFields();
+
+    addField("Volume", TypeF32, Offset(mVolume, AudioDescription));
+    addField("VolumeChannel", TypeS32, Offset(mVolumeChannel, AudioDescription));
+    addField("isLooping", TypeBool, Offset(mIsLooping, AudioDescription));
+    addField("isStreaming", TypeBool, Offset(mIsStreaming, AudioDescription));
+
+    addField("is3D", TypeBool, Offset(mIs3D, AudioDescription));
+    addField("ReferenceDistance", TypeF32, Offset(mReferenceDistance, AudioDescription));
+    addField("RolloffFactor", TypeF32, Offset(mRollOffFactor, AudioDescription));
+    addField("MaxDistance", TypeF32, Offset(mMaxDistance, AudioDescription));
+    addField("ConeInsideAngle", TypeS32, Offset(mConeInsideAngle, AudioDescription));
+    addField("ConeOutsideAngle", TypeS32, Offset(mConeOutsideAngle, AudioDescription));
+    addField("ConeOutsideVolume", TypeF32, Offset(mConeOutsideVolume, AudioDescription));
+    addField("ConeVector", TypeF32Vector, Offset(mConeVector, AudioDescription));
+    addField("EnvironmentLevel", TypeF32, Offset(mEnvironmentLevel, AudioDescription));
+}
+
+//--------------------------------------------------------------------------
+IMPLEMENT_CONSOLETYPE(AudioDescription)
+IMPLEMENT_GETDATATYPE(AudioDescription)
+IMPLEMENT_SETDATATYPE(AudioDescription)

+ 72 - 0
engine/source/audio/audioDescriptions.h

@@ -0,0 +1,72 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _AUDIODESCRIPTION_H_
+#define _AUDIODESCRIPTION_H_
+
+#ifndef _PLATFORMAUDIO_H_
+#include "platform/platformAudio.h"
+#endif
+#ifndef _AUDIOBUFFER_H_
+#include "audio/audioBuffer.h"
+#endif
+#ifndef _BITSTREAM_H_
+#include "io/bitStream.h"
+#endif
+#ifndef _SIMBASE_H_
+#include "sim/simBase.h"
+#endif
+
+//--------------------------------------------------------------------------
+
+class AudioDescription : public SimDataBlock
+{
+    typedef SimDataBlock Parent;
+
+public:
+
+    F32  mVolume;    // 0-1    1=loudest volume
+    S32  mVolumeChannel;
+    bool mIsLooping;
+    bool mIsStreaming;
+
+    bool mIs3D;
+    F32  mReferenceDistance;
+    F32  mRollOffFactor;
+    F32  mMaxDistance;
+    S32  mConeInsideAngle;
+    S32  mConeOutsideAngle;
+    F32  mConeOutsideVolume;
+    Point3F mConeVector;
+
+    // environment info
+    F32 mEnvironmentLevel;
+
+    AudioDescription();
+
+    static void initPersistFields();
+
+    DECLARE_CONOBJECT(AudioDescription);
+};
+DECLARE_CONSOLETYPE(AudioDescription)
+
+#endif  // _H_AUDIODATABLOCK_

+ 1 - 0
engine/source/platform/platformAudio.h

@@ -86,6 +86,7 @@ class AudioStreamSource;
 AUDIOHANDLE alxCreateSource(const Audio::Description *desc, const char *filename, const MatrixF *transform=NULL, AudioSampleEnvironment * sampleEnvironment = 0);
 AUDIOHANDLE alxCreateSource(AudioDescription *descObject, const char *filename, const MatrixF *transform=NULL, AudioSampleEnvironment * sampleEnvironment = 0);
 AUDIOHANDLE alxCreateSource(const AudioAsset *profile, const MatrixF *transform=NULL);
+AUDIOHANDLE alxCreateSource_AD(const AudioAsset *profile, const AudioDescription* description, const MatrixF *transform);
 AudioStreamSource* alxFindAudioStreamSource(AUDIOHANDLE handle);
 
 AUDIOHANDLE alxPlay(AUDIOHANDLE handle);