Index: build/premake/premake4.lua
===================================================================
--- build/premake/premake4.lua (revision 11718)
+++ build/premake/premake4.lua (working copy)
@@ -519,7 +519,10 @@
"ps/Network",
"ps/GameSetup",
"ps/XML",
- "sound",
+ "soundmanager",
+ "soundmanager/data",
+ "soundmanager/items",
+ "soundmanager/js",
"scripting",
"maths",
"maths/scripting",
@@ -533,6 +536,8 @@
"boost",
"enet",
"libcurl",
+ "vorbis",
+ "openal"
}
setup_static_lib_project("engine", source_dirs, extern_libs, {})
@@ -553,7 +558,6 @@
end
setup_static_lib_project("graphics", source_dirs, extern_libs, {})
-
source_dirs = {
"tools/atlas/GameInterface",
"tools/atlas/GameInterface/Handlers"
Index: source/ps/GameSetup/Config.cpp
===================================================================
--- source/ps/GameSetup/Config.cpp (revision 11718)
+++ source/ps/GameSetup/Config.cpp (working copy)
@@ -23,8 +23,8 @@
#include "lib/timer.h"
#include "lib/res/sound/snd_mgr.h"
#include "Config.h"
+#include "soundmanager/CSoundManager.h"
-
// (these variables are documented in the header.)
CStrW g_CursorName = L"test";
@@ -81,9 +81,26 @@
CFG_GET_USER_VAL("particles", Bool, g_Particles);
float gain = -1.0f;
+ float musicGain = -1.0f;
+ float ambientGain = -1.0f;
+ float actionGain = -1.0f;
+ int bufferCount = 50;
+ unsigned long bufferSize = 65536;
+
CFG_GET_USER_VAL("sound.mastergain", Float, gain);
- if(gain >= 0.0f)
- WARN_IF_ERR(snd_set_master_gain(gain));
+ CFG_GET_USER_VAL("sound.musicgain", Float, musicGain);
+ CFG_GET_USER_VAL("sound.ambientgain", Float, ambientGain);
+ CFG_GET_USER_VAL("sound.actiongain", Float, actionGain);
+
+ CFG_GET_USER_VAL("sound.bufferCount", Int, bufferCount);
+ CFG_GET_USER_VAL("sound.bufferSize", UnsignedLong, bufferSize);
+
+ g_SoundManager->setMasterGain( gain );
+ g_SoundManager->setMusicGain( musicGain );
+ g_SoundManager->setAmbientGain( ambientGain );
+ g_SoundManager->setActionGain( actionGain );
+
+ g_SoundManager->setMemoryUsage( bufferSize, bufferCount);
}
Index: source/ps/GameSetup/GameSetup.cpp
===================================================================
--- source/ps/GameSetup/GameSetup.cpp (revision 11718)
+++ source/ps/GameSetup/GameSetup.cpp (working copy)
@@ -102,6 +102,7 @@
#include "tools/atlas/GameInterface/GameLoop.h"
#include "tools/atlas/GameInterface/View.h"
+#include "soundmanager/CSoundManager.h"
#if !(OS_WIN || OS_MACOSX || OS_ANDROID) // assume all other platforms use X11 for wxWidgets
#define MUST_INIT_X11 1
@@ -203,6 +204,8 @@
{
PROFILE3("render");
+ g_SoundManager->idleTask();
+
ogl_WarnIfError();
g_Profiler2.RecordGPUFrameStart();
@@ -330,7 +333,8 @@
{
// maths
JSI_Vector3D::init();
-
+
+ CSoundManager::ScriptingInit();
// graphics
CGameView::ScriptingInit();
@@ -338,7 +342,7 @@
CRenderer::ScriptingInit();
// sound
- JSI_Sound::ScriptingInit();
+// JSI_Sound::ScriptingInit();
// ps
JSI_Console::init();
@@ -476,6 +480,9 @@
g_VFS->Mount(L"", modLoosePath / modName/"", flags, priority);
g_VFS->Mount(L"", modArchivePath / modName/"", flags, priority);
}
+
+ OsPath apth = paths.RData()/"mods/public";
+ g_SoundManager = new CSoundManager( apth );
// note: don't bother with g_VFS->TextRepresentation - directories
// haven't yet been populated and are empty.
@@ -691,7 +698,7 @@
// resource
// first shut down all resource owners, and then the handle manager.
TIMER_BEGIN(L"resource modules");
- snd_shutdown();
+ delete g_SoundManager;
g_VFS.reset();
@@ -930,7 +937,7 @@
// speed up startup by disabling all sound
// (OpenAL init will be skipped).
// must be called before first snd_open.
- snd_disable(true);
+ g_SoundManager->setEnabled( false );
}
g_GUI = new CGUIManager(g_ScriptingHost.GetScriptInterface());
Index: source/ps/Game.cpp
===================================================================
--- source/ps/Game.cpp (revision 11718)
+++ source/ps/Game.cpp (working copy)
@@ -45,6 +45,7 @@
#include "simulation2/components/ICmpPlayerManager.h"
#include "gui/GUIManager.h"
+#include "soundmanager/CSoundManager.h"
extern bool g_GameRestarted;
@@ -299,6 +300,7 @@
if (doInterpolate)
{
m_TurnManager->Interpolate(deltaTime);
+ g_SoundManager->idleTask();
}
// TODO: maybe we should add a CCmpParticleInterface that passes the interpolation commands
Index: source/soundmanager/items/CSoundItem.h
===================================================================
--- source/soundmanager/items/CSoundItem.h (revision 0)
+++ source/soundmanager/items/CSoundItem.h (revision 0)
@@ -0,0 +1,48 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#ifndef SoundTester_CSoundItem_h
+#define SoundTester_CSoundItem_h
+
+#include "CSoundBase.h"
+#include "soundmanager/data/CSoundData.h"
+
+
+class CSoundItem :public CSoundBase
+{
+protected:
+
+public:
+ CSoundItem ();
+ CSoundItem (CSoundData* sndData);
+
+ virtual ~CSoundItem ();
+ void attach ( CSoundData* itemData );
+ bool idleTask ();
+
+protected:
+
+
+};
+
+
+
+
+
+
+#endif
Index: source/soundmanager/items/CBufferItem.h
===================================================================
--- source/soundmanager/items/CBufferItem.h (revision 0)
+++ source/soundmanager/items/CBufferItem.h (revision 0)
@@ -0,0 +1,40 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#ifndef SoundTester_CBufferItem_h
+#define SoundTester_CBufferItem_h
+
+#include "CSoundBase.h"
+
+class CBufferItem : public CSoundBase
+{
+public:
+ CBufferItem (CSoundData* sndData);
+ virtual ~CBufferItem ();
+
+ virtual void setLooping ( bool loops );
+ virtual bool idleTask ();
+
+protected:
+ virtual void attach ( CSoundData* itemData );
+
+
+};
+
+
+#endif
Index: source/soundmanager/items/CStreamItem.h
===================================================================
--- source/soundmanager/items/CStreamItem.h (revision 0)
+++ source/soundmanager/items/CStreamItem.h (revision 0)
@@ -0,0 +1,38 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef SoundTester_CStreamItem_h
+#define SoundTester_CStreamItem_h
+
+#include "soundmanager/data/CSoundData.h"
+#include "CSoundBase.h"
+
+class CStreamItem : public CSoundBase
+{
+public:
+ CStreamItem (CSoundData* sndData);
+ virtual ~CStreamItem ();
+
+ virtual void setLooping ( bool loops );
+ virtual bool idleTask ();
+
+protected:
+ virtual void attach ( CSoundData* itemData );
+
+};
+
+#endif
Index: source/soundmanager/items/ISoundItem.h
===================================================================
--- source/soundmanager/items/ISoundItem.h (revision 0)
+++ source/soundmanager/items/ISoundItem.h (revision 0)
@@ -0,0 +1,59 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef SoundTester_ISoundItem_h
+#define SoundTester_ISoundItem_h
+
+#include
+#include "lib/external_libraries/openal.h"
+#include "maths/Vector3D.h"
+
+
+class ISoundItem
+{
+
+public:
+ virtual ~ISoundItem(){};
+ virtual bool getLooping () = 0;
+ virtual void setLooping (bool loop) = 0;
+ virtual bool isPlaying () = 0;
+
+
+ virtual std::string getName () = 0;
+ virtual bool idleTask () = 0;
+
+ virtual void play () = 0;
+ virtual void stop () = 0;
+
+ virtual void ensurePlay () = 0;
+ virtual void playAsMusic () = 0;
+ virtual void playAsAmbient () = 0;
+
+ virtual void playAndDelete () = 0;
+ virtual void stopAndDelete () = 0;
+ virtual void fadeToIn ( ALfloat newVolume, double fadeDuration) = 0;
+ virtual void fadeAndDelete ( double fadeTime ) = 0;
+ virtual void playLoop () = 0;
+
+ virtual void setCone (ALfloat innerCone, ALfloat outerCone, ALfloat coneGain) = 0;
+ virtual void setPitch (ALfloat pitch) = 0;
+ virtual void setGain (ALfloat gain) = 0;
+ virtual void setLocation (const CVector3D& position) = 0;
+};
+
+
+#endif //SoundTester_ISoundItem_h
\ No newline at end of file
Index: source/soundmanager/items/CSoundBase.cpp
===================================================================
--- source/soundmanager/items/CSoundBase.cpp (revision 0)
+++ source/soundmanager/items/CSoundBase.cpp (revision 0)
@@ -0,0 +1,265 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "CSoundBase.h"
+#include "soundmanager/CSoundManager.h"
+#include "soundmanager/data/CSoundData.h"
+
+#include
+
+#include "lib/timer.h"
+
+
+CSoundBase::CSoundBase()
+{
+ resetVars();
+}
+
+CSoundBase::~CSoundBase()
+{
+ stop();
+ if ( mALSource != 0 ) {
+ alDeleteSources( 1, &mALSource);
+ mALSource = 0;
+ }
+ if ( mSoundData != 0 ) {
+ CSoundData::releaseSoundData( mSoundData );
+ mSoundData = 0;
+ }
+ if ( mName )
+ delete mName;
+}
+
+void CSoundBase::resetVars()
+{
+ mALSource = 0;
+ mSoundData = 0;
+ mLastPlay = false;
+ mLooping = false;
+ mStartFadeTime = 0;
+ mEndFadeTime = 0;
+ mStartVolume = 0;
+ mEndVolume = 0;
+
+ resetFade();
+ mName = new std::string( "sound name" );
+}
+
+void CSoundBase::resetFade()
+{
+ mStartFadeTime = 0;
+ mEndFadeTime = 0;
+ mStartVolume = 0;
+ mEndVolume = 0;
+ mShouldBePlaying = false;
+}
+
+void CSoundBase::setGain(ALfloat gain)
+{
+ alSourcef(mALSource, AL_GAIN, gain);
+}
+
+void CSoundBase::ensurePlay()
+{
+ if ( mShouldBePlaying && !isPlaying() )
+ play();
+}
+
+void CSoundBase::setCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain)
+{
+ alSourcef( mALSource, innerCone, AL_CONE_INNER_ANGLE);
+ alSourcef( mALSource, outerCone, AL_CONE_OUTER_ANGLE);
+ alSourcef( mALSource, coneGain, AL_CONE_OUTER_GAIN);
+}
+
+void CSoundBase::setPitch(ALfloat pitch)
+{
+ alSourcef( mALSource, AL_PITCH, pitch);
+}
+
+void CSoundBase::setDirection(const CVector3D& direction)
+{
+ alSourcefv( mALSource, AL_DIRECTION, direction.GetFloatArray() );
+}
+
+bool CSoundBase::initOpenAL()
+{
+ alGetError(); /* clear error */
+ alGenSources( 1, &mALSource);
+ long anErr = alGetError();
+ if( anErr != AL_NO_ERROR)
+ {
+ printf("- Error creating sources %ld !!\n", anErr );
+ }
+ else
+ {
+ ALfloat source0Pos[]={ -2.0, 0.0, 0.0};
+ ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
+
+ alSourcef( mALSource,AL_PITCH,1.0f);
+ alSourcef( mALSource,AL_GAIN,1.0f);
+ alSourcefv( mALSource,AL_POSITION,source0Pos);
+ alSourcefv( mALSource,AL_VELOCITY,source0Vel);
+ alSourcei( mALSource,AL_LOOPING,AL_FALSE);
+ return true;
+ }
+ return false;
+}
+
+bool CSoundBase::isPlaying()
+{
+ int proc_state;
+ alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+
+ return ( proc_state == AL_PLAYING );
+}
+
+void CSoundBase::setLastPlay( bool last )
+{
+ mLastPlay = last;
+}
+
+bool CSoundBase::idleTask()
+{
+ return true;
+}
+
+void CSoundBase::setLocation (const CVector3D& position)
+{
+ // const float* loatArr = position.GetFloatArray();
+// debug_printf(L"do upload and play at location:%f, %f, %f\n\n", loatArr[0], loatArr[1], loatArr[2] );
+
+// alSourcefv( mALSource,AL_POSITION, position.GetFloatArray() );
+}
+
+bool CSoundBase::handleFade()
+{
+ if ( mStartFadeTime != 0 ) {
+ double currTime = timer_Time();
+ double pctDone = std::min( 1.0, (currTime - mStartFadeTime) / (mEndFadeTime - mStartFadeTime) );
+ pctDone = std::max( 0.0, pctDone );
+ ALfloat curGain = ((mEndVolume - mStartVolume ) * pctDone) + mStartVolume;
+
+ if (curGain == 0 )
+ stop();
+ else if ( curGain == mEndVolume ) {
+ alSourcef( mALSource, AL_GAIN, curGain);
+ resetFade();
+ }
+ else
+ alSourcef( mALSource, AL_GAIN, curGain);
+ }
+ return true;
+}
+
+bool CSoundBase::getLooping()
+{
+ return mLooping;
+}
+void CSoundBase::setLooping( bool loops )
+{
+ mLooping = loops;
+ alSourcei( mALSource, AL_LOOPING, loops ? AL_TRUE : AL_FALSE );
+}
+
+void CSoundBase::play()
+{
+ mShouldBePlaying = true;
+ if ( mALSource != 0 )
+ alSourcePlay( mALSource );
+}
+void CSoundBase::playAndDelete()
+{
+ setLastPlay( true );
+ play();
+}
+
+void CSoundBase::fadeAndDelete( double fadeTime )
+{
+ setLastPlay( true );
+ fadeToIn( 0, fadeTime );
+}
+
+void CSoundBase::stopAndDelete()
+{
+ setLastPlay( true );
+ stop();
+}
+
+void CSoundBase::playLoop()
+{
+ if ( mALSource != 0 ) {
+ setLooping( true );
+ play();
+ }
+}
+
+void CSoundBase::fadeToIn( ALfloat newVolume, double fadeDuration)
+{
+ int proc_state;
+ alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+ if ( proc_state == AL_PLAYING ) {
+ mStartFadeTime = timer_Time();
+ mEndFadeTime = mStartFadeTime + fadeDuration;
+ alGetSourcef( mALSource, AL_GAIN, &mStartVolume);
+ mEndVolume = newVolume;
+ }
+
+}
+
+void CSoundBase::playAsMusic()
+{
+ g_SoundManager->setMusicItem( this );
+}
+
+void CSoundBase::playAsAmbient()
+{
+ g_SoundManager->setAmbientItem( this );
+}
+
+void CSoundBase::stop()
+{
+ mShouldBePlaying = false;
+ if ( mALSource != 0 ) {
+ int proc_state;
+ alSourcei( mALSource, AL_LOOPING, AL_FALSE );
+ alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+ if ( proc_state == AL_PLAYING )
+ alSourceStop( mALSource );
+ }
+}
+
+const char* CSoundBase::Name()
+{
+ return mName->c_str();
+}
+
+std::string CSoundBase::getName()
+{
+ return std::string( mName->c_str() );
+}
+
+void CSoundBase::setNameFromPath( char* fileLoc )
+{
+ std::string anst( fileLoc );
+ size_t pos = anst.find_last_of("/");
+ if(pos != std::wstring::npos)
+ mName->assign(anst.begin() + pos + 1, anst.end());
+ else
+ mName->assign(anst.begin(), anst.end());
+}
+
Index: source/soundmanager/items/CSoundItem.cpp
===================================================================
--- source/soundmanager/items/CSoundItem.cpp (revision 0)
+++ source/soundmanager/items/CSoundItem.cpp (revision 0)
@@ -0,0 +1,65 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "CSoundItem.h"
+#include "soundmanager/data/CSoundData.h"
+
+#include
+
+
+CSoundItem::CSoundItem()
+{
+ resetVars();
+}
+
+CSoundItem::CSoundItem(CSoundData* sndData)
+{
+ resetVars();
+ if ( initOpenAL() )
+ attach( sndData );
+
+ debug_printf(L"created SoundItem at: %ls\n\n", sndData->getFileName().c_str());
+}
+
+CSoundItem::~CSoundItem()
+{
+ ALuint al_buf;
+
+ stop();
+ alSourceUnqueueBuffers(mALSource, 1, &al_buf);
+}
+
+bool CSoundItem::idleTask()
+{
+ handleFade();
+
+ if ( mLastPlay )
+ {
+ int proc_state;
+ alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+ return ( proc_state != AL_STOPPED );
+ }
+ return true;
+}
+
+void CSoundItem::attach( CSoundData* itemData )
+{
+ if ( itemData != NULL ) {
+ mSoundData = itemData->incrementCount();
+ alSourcei( mALSource, AL_BUFFER, mSoundData->getBuffer() );
+ }
+}
Index: source/soundmanager/items/CBufferItem.cpp
===================================================================
--- source/soundmanager/items/CBufferItem.cpp (revision 0)
+++ source/soundmanager/items/CBufferItem.cpp (revision 0)
@@ -0,0 +1,85 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "CBufferItem.h"
+#include "soundmanager/data/CSoundData.h"
+
+#include
+
+CBufferItem::CBufferItem(CSoundData* sndData)
+{
+ resetVars();
+ if ( initOpenAL() )
+ attach( sndData );
+
+ debug_printf(L"created BufferItem at: %ls\n\n", sndData->getFileName().c_str());
+}
+
+
+CBufferItem::~CBufferItem()
+{
+ stop();
+ int num_processed;
+ alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+
+ if (num_processed > 0)
+ {
+ ALuint al_buf[num_processed];
+ alSourceUnqueueBuffers(mALSource, num_processed, al_buf);
+ }
+}
+
+
+bool CBufferItem::idleTask()
+{
+ handleFade();
+
+ if ( mLastPlay )
+ {
+ int proc_state;
+ alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+ return ( proc_state != AL_STOPPED );
+ }
+
+ if ( getLooping() ) {
+ int num_processed;
+ alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+
+ for ( int i = 0; i < num_processed; i++ )
+ {
+ ALuint al_buf;
+ alSourceUnqueueBuffers(mALSource, 1, &al_buf);
+ alSourceQueueBuffers(mALSource, 1, &al_buf);
+ }
+ }
+
+ return true;
+}
+
+void CBufferItem::attach( CSoundData* itemData )
+{
+ if ( itemData != NULL ) {
+ mSoundData = itemData->incrementCount();
+ alSourceQueueBuffers(mALSource, mSoundData->getBufferCount(),(const ALuint *) mSoundData->getBufferPtr());
+ }
+}
+
+void CBufferItem::setLooping( bool loops )
+{
+ mLooping = loops;
+}
+
Index: source/soundmanager/items/CSoundBase.h
===================================================================
--- source/soundmanager/items/CSoundBase.h (revision 0)
+++ source/soundmanager/items/CSoundBase.h (revision 0)
@@ -0,0 +1,94 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#ifndef SoundTester_CSoundBase_h
+#define SoundTester_CSoundBase_h
+
+#include
+#include "lib/external_libraries/openal.h"
+#include "soundmanager/items/ISoundItem.h"
+#include "soundmanager/data/CSoundData.h"
+
+
+class CSoundBase :public ISoundItem
+{
+protected:
+
+ ALuint mALSource;
+ CSoundData* mSoundData;
+
+ std::string* mName;
+ bool mLastPlay;
+ bool mLooping;
+ bool mShouldBePlaying;
+
+ double mStartFadeTime;
+ double mEndFadeTime;
+ ALfloat mStartVolume;
+ ALfloat mEndVolume;
+
+public:
+ CSoundBase ();
+
+ virtual ~CSoundBase ();
+
+ virtual bool initOpenAL();
+ virtual void resetVars();
+ virtual void ensurePlay();
+
+ virtual void setGain (ALfloat gain);
+ virtual void setPitch(ALfloat pitch);
+ virtual void setDirection(const CVector3D& direction);
+ virtual void setCone(ALfloat innerCone, ALfloat outerCone, ALfloat coneGain);
+ virtual void setLastPlay( bool last );
+
+ void play ();
+ void playAndDelete ();
+ bool idleTask ();
+ void playLoop ();
+ void stop ();
+ void stopAndDelete ();
+ void fadeToIn ( ALfloat newVolume, double fadeDuration);
+
+ void playAsMusic ();
+ void playAsAmbient ();
+
+ const char* Name();
+ std::string getName();
+
+ virtual bool getLooping ();
+ virtual void setLooping ( bool loops );
+ virtual bool isPlaying();
+ virtual void setLocation (const CVector3D& position);
+ virtual void fadeAndDelete ( double fadeTime );
+
+protected:
+
+ void setNameFromPath( char* fileLoc );
+ void resetFade();
+ bool handleFade();
+
+
+};
+
+
+
+
+
+
+#endif
Index: source/soundmanager/items/CStreamItem.cpp
===================================================================
--- source/soundmanager/items/CStreamItem.cpp (revision 0)
+++ source/soundmanager/items/CStreamItem.cpp (revision 0)
@@ -0,0 +1,92 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "CStreamItem.h"
+#include "soundmanager/data/COggData.h"
+
+#include
+
+CStreamItem::CStreamItem(CSoundData* sndData)
+{
+ resetVars();
+ if ( initOpenAL() )
+ attach( sndData );
+
+ debug_printf(L"created StreamItem at: %ls\n\n", sndData->getFileName().c_str());
+}
+
+CStreamItem::~CStreamItem()
+{
+ stop();
+
+ int num_processed;
+ alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+
+ if (num_processed > 0)
+ {
+ ALuint al_buf[num_processed];
+ alSourceUnqueueBuffers(mALSource, num_processed, al_buf);
+ }
+}
+
+bool CStreamItem::idleTask()
+{
+ handleFade();
+
+ int proc_state;
+ alGetSourceiv( mALSource, AL_SOURCE_STATE, &proc_state);
+
+ if ( proc_state == AL_STOPPED ) {
+ if ( mLastPlay )
+ return ( proc_state != AL_STOPPED );
+ }
+ else {
+ COggData* tmp = (COggData*)mSoundData;
+
+ if ( ! tmp->isFileFinished() ) {
+ int num_processed;
+ alGetSourcei( mALSource, AL_BUFFERS_PROCESSED, &num_processed);
+
+ if (num_processed > 0)
+ {
+ ALuint al_buf[num_processed];
+ alSourceUnqueueBuffers(mALSource, num_processed, al_buf);
+ int didWrite = tmp->fetchDataIntoBuffer( num_processed, al_buf);
+ alSourceQueueBuffers( mALSource, didWrite, al_buf);
+ }
+ }
+ else if ( getLooping() )
+ {
+ tmp->resetFile();
+ }
+ }
+ return true;
+}
+
+void CStreamItem::attach( CSoundData* itemData )
+{
+ if ( itemData != NULL ) {
+ mSoundData = itemData->incrementCount();
+ alSourceQueueBuffers(mALSource, mSoundData->getBufferCount(), (const ALuint *)mSoundData->getBufferPtr());
+ }
+}
+
+void CStreamItem::setLooping( bool loops )
+{
+ mLooping = loops;
+}
+
Index: source/soundmanager/CSoundManager.cpp
===================================================================
--- source/soundmanager/CSoundManager.cpp (revision 0)
+++ source/soundmanager/CSoundManager.cpp (revision 0)
@@ -0,0 +1,292 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#include "CSoundManager.h"
+#include "soundmanager/items/CSoundItem.h"
+#include "soundmanager/items/CBufferItem.h"
+#include "soundmanager/items/CStreamItem.h"
+#include "soundmanager/js/JAmbientSound.h"
+#include "soundmanager/js/JMusicSound.h"
+#include "soundmanager/js/JSound.h"
+#include "soundmanager/data/CSoundData.h"
+
+
+CSoundManager* g_SoundManager;
+
+void CSoundManager::ScriptingInit()
+{
+ JAmbientSound::ScriptingInit();
+ JMusicSound::ScriptingInit();
+ JSound::ScriptingInit();
+}
+
+CSoundManager::CSoundManager(OsPath& resourcePath)
+{
+ mResourcePath = resourcePath;
+
+ mItems = new ItemsList;
+ mCurrentEnvirons = 0;
+ mCurrentTune = 0;
+ mGain = 1;
+ mMusicGain = 1;
+ mAmbientGain = 1;
+ mActionGain = 1;
+ mEnabled = true;
+ mBufferCount = 50;
+ mBufferSize = 65536;
+
+ debug_printf(L"initiate manager at: %ls\n\n", resourcePath.string().c_str());
+
+ alc_init();
+}
+
+CSoundManager::~CSoundManager()
+{
+ ItemsList::iterator lstr = mItems->begin();
+ while ( lstr != mItems->end() ) {
+ (*lstr)->stop();
+ delete *lstr;
+ lstr++;
+ }
+
+ alcDestroyContext( mContext );
+ alcCloseDevice( mDevice );
+
+ delete mItems;
+ mItems = 0L;
+ mCurrentEnvirons = 0;
+ mCurrentTune = 0;
+}
+
+
+Status CSoundManager::alc_init()
+{
+ Status ret = INFO::OK;
+
+ mDevice = alcOpenDevice(NULL);
+ if(mDevice)
+ {
+ mContext = alcCreateContext(mDevice, 0); // no attrlist needed
+ if(mContext)
+ alcMakeContextCurrent(mContext);
+ }
+
+ // check if init succeeded.
+ // some OpenAL implementations don't indicate failure here correctly;
+ // we need to check if the device and context pointers are actually valid.
+ ALCenum err = alcGetError(mDevice);
+ if(err != ALC_NO_ERROR || !mDevice || !mContext)
+ {
+#if OS_UNIX
+ ret = INFO::OK;
+#else
+ ret = ERR::FAIL;
+#endif
+ }
+
+ const char* dev_name = (const char*)alcGetString(mDevice, ALC_DEVICE_SPECIFIER);
+ wchar_t buf[200];
+ swprintf(buf, ARRAY_SIZE(buf), L"SND| alc_init: success, using %hs\n", dev_name);
+
+ return ret;
+}
+void CSoundManager::setMemoryUsage( long bufferSize, int bufferCount )
+{
+ mBufferCount = bufferCount;
+ mBufferSize = bufferSize;
+}
+long CSoundManager::getBufferCount()
+{
+ return mBufferCount;
+}
+long CSoundManager::getBufferSize()
+{
+ return mBufferSize;
+}
+
+
+void CSoundManager::setMasterGain( float gain)
+{
+ mGain = gain;
+}
+void CSoundManager::setMusicGain( float gain)
+{
+ mMusicGain = gain;
+}
+void CSoundManager::setAmbientGain( float gain)
+{
+ mAmbientGain = gain;
+}
+void CSoundManager::setActionGain( float gain)
+{
+ mActionGain = gain;
+}
+
+
+ISoundItem* CSoundManager::loadItem( OsPath* itemPath )
+{
+ debug_printf(L"initiate item at: %ls\n\n", itemPath->string().c_str());
+
+ OsPath thePath = mResourcePath/ *itemPath;
+
+ CSoundData* itemData = CSoundData::soundDataFromFile( thePath );
+ ISoundItem* answer = NULL;
+
+ if ( itemData != NULL ) {
+ if ( itemData->isOneShot() ) {
+ if ( itemData->getBufferCount() == 1 )
+ answer = new CSoundItem( itemData );
+ else
+ answer = new CBufferItem( itemData );
+ }
+ else {
+ answer = new CStreamItem( itemData );
+ }
+
+ if ( answer != NULL )
+ mItems->push_back( answer );
+ }
+
+
+ return answer;
+}
+
+unsigned long CSoundManager::count()
+{
+ return mItems->size();
+}
+
+void CSoundManager::idleTask()
+{
+ if ( mItems )
+ {
+ ItemsList::iterator lstr = mItems->begin();
+ ItemsList deadItemList;
+ ItemsList* nextItemList = new ItemsList;
+
+
+ while ( lstr != mItems->end() ) {
+ if ( (*lstr)->idleTask() )
+ nextItemList->push_back( *lstr );
+ else
+ deadItemList.push_back( *lstr );
+ lstr++;
+ }
+ delete mItems;
+ mItems = nextItemList;
+
+ ItemsList::iterator deadItems = deadItemList.begin();
+ while ( deadItems != deadItemList.end() )
+ {
+ delete *deadItems;
+ deadItems++;
+ }
+ }
+ if ( mCurrentTune )
+ mCurrentTune->ensurePlay();
+ if ( mCurrentEnvirons )
+ mCurrentEnvirons->ensurePlay();
+}
+
+void CSoundManager::deleteItem( long itemNum )
+{
+ ItemsList::iterator lstr = mItems->begin();
+ lstr += itemNum;
+
+ delete *lstr;
+
+ mItems->erase( lstr );
+}
+
+ISoundItem* CSoundManager::getSoundItem( unsigned long itemRow )
+{
+ return (*mItems)[itemRow];
+}
+
+void CSoundManager::InitListener()
+{
+ ALfloat listenerPos[]={0.0,0.0,4.0};
+ ALfloat listenerVel[]={0.0,0.0,0.0};
+ ALfloat listenerOri[]={0.0,0.0,1.0, 0.0,1.0,0.0};
+
+ alListenerfv(AL_POSITION,listenerPos);
+ alListenerfv(AL_VELOCITY,listenerVel);
+ alListenerfv(AL_ORIENTATION,listenerOri);
+}
+void CSoundManager::setEnabled( bool doEnable )
+{
+ mEnabled = doEnable;
+}
+
+void CSoundManager::playActionItem( ISoundItem* anItem )
+{
+ if ( anItem )
+ {
+ if ( mEnabled && ( mActionGain > 0 ) ) {
+ anItem->setGain( mGain * mActionGain );
+ anItem->play();
+ }
+ }
+}
+void CSoundManager::playGroupItem( ISoundItem* anItem, ALfloat groupGain)
+{
+ if ( anItem )
+ {
+ if ( mEnabled && ( mActionGain > 0 ) ) {
+ anItem->setGain( mGain * groupGain );
+ anItem->play();
+ }
+ }
+}
+void CSoundManager::setMusicItem( ISoundItem* anItem )
+{
+ if ( mCurrentTune ) {
+ mCurrentTune->fadeAndDelete(3.00);
+ mCurrentTune = 0L;
+ }
+ idleTask();
+ if ( anItem )
+ {
+ if ( mEnabled && ( mMusicGain > 0 ) ) {
+ mCurrentTune = anItem;
+ mCurrentTune->setGain( 0 );
+ mCurrentTune->playLoop();
+ mCurrentTune->fadeToIn( mGain * mMusicGain, 3.00 );
+ }
+ }
+}
+
+void CSoundManager::setAmbientItem( ISoundItem* anItem )
+{
+ if ( mCurrentEnvirons ) {
+ mCurrentEnvirons->fadeAndDelete(3.00);
+ mCurrentEnvirons = 0L;
+ }
+ idleTask();
+
+ if ( anItem )
+ {
+ if ( mEnabled && ( mAmbientGain > 0 ) ) {
+ mCurrentEnvirons = anItem;
+ mCurrentEnvirons->setGain( 0 );
+ mCurrentEnvirons->playLoop();
+ mCurrentEnvirons->fadeToIn( mGain * mAmbientGain, 3.00 );
+ }
+ }
+}
+
Index: source/soundmanager/data/COggData.h
===================================================================
--- source/soundmanager/data/COggData.h (revision 0)
+++ source/soundmanager/data/COggData.h (revision 0)
@@ -0,0 +1,58 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#ifndef SoundTester_COggData_h
+#define SoundTester_COggData_h
+
+#include "CSoundData.h"
+#include "vorbis/vorbisfile.h"
+
+class COggData : public CSoundData
+{
+ ALuint mFormat;
+ long mFrequency;
+
+public:
+ COggData ();
+ virtual ~COggData ();
+
+ virtual bool InitOggFile( const wchar_t* fileLoc );
+ virtual bool isFileFinished();
+ virtual bool isOneShot();
+
+ virtual int fetchDataIntoBuffer( int count, ALuint* buffers);
+ virtual void resetFile();
+
+protected:
+ OggVorbis_File m_vf;
+ int m_current_section;
+ bool mFileFinished;
+ bool mOneShot;
+ ALuint mBuffer[100];
+ int mBuffersUsed;
+
+ bool addDataBuffer( char* data, long length);
+ void setFormatAndFreq( int form, ALsizei freq);
+ ALsizei getBufferCount();
+ ALuint getBuffer();
+ ALuint* getBufferPtr();
+};
+
+
+
+#endif
Index: source/soundmanager/data/CSoundData.cpp
===================================================================
--- source/soundmanager/data/CSoundData.cpp (revision 0)
+++ source/soundmanager/data/CSoundData.cpp (revision 0)
@@ -0,0 +1,146 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#import "CSoundData.h"
+
+
+#include
+#include "COggData.h"
+
+DataMap* CSoundData::sSoundData = NULL;
+
+CSoundData::CSoundData()
+{
+ initProperties();
+}
+
+CSoundData::~CSoundData()
+{
+ if ( mALBuffer != 0 )
+ alDeleteBuffers( 1, &mALBuffer );
+}
+
+void CSoundData::initProperties()
+{
+ mALBuffer = 0;
+ mRetentionCount = 0;
+}
+
+void CSoundData::releaseSoundData( CSoundData* theData )
+{
+ DataMap::iterator itemFind;
+
+ if ( theData->decrementCount() ) {
+ if ( ( itemFind = CSoundData::sSoundData->find( theData->getFileName() ) ) != sSoundData->end() )
+ {
+ CSoundData* dier = itemFind->second;
+ CSoundData::sSoundData->erase( itemFind );
+ delete dier;
+ }
+ }
+}
+
+CSoundData* CSoundData::soundDataFromFile( OsPath& itemPath )
+{
+ if ( CSoundData::sSoundData == NULL )
+ CSoundData::sSoundData = new DataMap;
+
+ Path fExt = itemPath.Extension();
+ DataMap::iterator itemFind;
+ CSoundData* answer;
+
+
+ debug_printf(L"creating data at: %ls\n\n", itemPath.string().c_str());
+
+ if ( ( itemFind = CSoundData::sSoundData->find( itemPath.string() ) ) != sSoundData->end() )
+ {
+ debug_printf(L"data found in cache at: %ls\n\n", itemPath.string().c_str());
+ answer = itemFind->second;
+ }
+ else
+ {
+ if ( fExt == ".ogg" )
+ answer = soundDataFromOgg( itemPath );
+// else if ( fExt == ".wav" )
+// answer = soundDataFromWAV( itemPath );
+
+ if ( answer && answer->isOneShot() )
+ (*CSoundData::sSoundData)[itemPath.string()] = answer;
+
+ }
+ return answer;
+}
+
+bool CSoundData::isOneShot()
+{
+ return true;
+}
+
+
+CSoundData* CSoundData::soundDataFromOgg(OsPath& itemPath )
+{
+ CSoundData* answer = NULL;
+ COggData* oggAnswer = new COggData();
+ if ( oggAnswer->InitOggFile( itemPath.string().c_str() ) ) {
+ answer = oggAnswer;
+ }
+
+ return answer;
+}
+
+
+ALsizei CSoundData::getBufferCount()
+{
+ return 1;
+}
+
+std::wstring CSoundData::getFileName()
+{
+ return mFileName;
+}
+
+
+
+
+
+
+
+
+
+CSoundData* CSoundData::incrementCount()
+{
+ mRetentionCount++;
+ return this;
+}
+
+bool CSoundData::decrementCount()
+{
+ mRetentionCount--;
+
+ return ( mRetentionCount <= 0 );
+}
+
+ALuint CSoundData::getBuffer()
+{
+ return mALBuffer;
+}
+ALuint* CSoundData::getBufferPtr()
+{
+ return &mALBuffer;
+}
+
Index: source/soundmanager/data/COggData.cpp
===================================================================
--- source/soundmanager/data/COggData.cpp (revision 0)
+++ source/soundmanager/data/COggData.cpp (revision 0)
@@ -0,0 +1,161 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#include "COggData.h"
+
+
+#include
+#include
+#include "soundmanager/CSoundManager.h"
+
+COggData::COggData()
+{
+ mOneShot = false;
+}
+
+COggData::~COggData()
+{
+ alDeleteBuffers( mBuffersUsed, mBuffer );
+ ov_clear(&m_vf);
+}
+
+void COggData::setFormatAndFreq( int form, ALsizei freq)
+{
+ mFormat = form;
+ mFrequency = freq;
+}
+
+bool COggData::InitOggFile( const wchar_t* fileLoc )
+{
+ int buffersToStart = g_SoundManager->getBufferCount();
+
+#ifdef _WIN32
+ _setmode( _fileno( stdin ), _O_BINARY );
+ _setmode( _fileno( stdout ), _O_BINARY );
+#endif
+
+// fprintf(stderr, "ready to open ogg file at:%ls \r\r", fileLoc);
+
+ char nameH[300];
+ sprintf( nameH, "%ls", fileLoc );
+
+ FILE* f = fopen( nameH, "rb");
+ m_current_section = 0;
+ int err = ov_open_callbacks(f, &m_vf, NULL, 0, OV_CALLBACKS_DEFAULT);
+ if ( err < 0) {
+ fprintf(stderr,"Input does not appear to be an Ogg bitstream :%d :%d.\n", err, ferror(f) );
+ return false;
+ }
+
+ mFileName = std::wstring(fileLoc);
+
+ mFileFinished = false;
+ setFormatAndFreq( (m_vf.vi->channels == 1)? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16 , (ALsizei)m_vf.vi->rate );
+
+ alGetError(); /* clear error */
+ alGenBuffers( buffersToStart, mBuffer);
+
+ if(alGetError() != AL_NO_ERROR)
+ {
+ printf("- Error creating initial buffer !!\n");
+ return false;
+ }
+ else
+ {
+ mBuffersUsed = fetchDataIntoBuffer( buffersToStart, mBuffer);
+ if ( mFileFinished ) {
+ mOneShot = true;
+ if ( mBuffersUsed < buffersToStart ) {
+ debug_printf(L"one shot gave back %d buffers\n\n", buffersToStart - mBuffersUsed );
+ alDeleteBuffers( buffersToStart - mBuffersUsed, &mBuffer[mBuffersUsed] );
+ }
+ }
+ }
+ return true;
+}
+
+ALsizei COggData::getBufferCount()
+{
+ return mBuffersUsed;
+}
+
+bool COggData::isFileFinished()
+{
+ return mFileFinished;
+}
+
+void COggData::resetFile()
+{
+ ov_time_seek( &m_vf, 0 );
+ m_current_section = 0;
+ mFileFinished = false;
+}
+
+bool COggData::isOneShot()
+{
+ return mOneShot;
+}
+
+int COggData::fetchDataIntoBuffer( int count, ALuint* buffers)
+{
+ long bufferSize = g_SoundManager->getBufferSize();
+
+ char pcmout[bufferSize + 5000];
+ int buffersWritten = 0;
+
+ for(int i = 0; ( i < count ) && !mFileFinished; i++) {
+ char* readDest = pcmout;
+ long totalRet = 0;
+ while (totalRet < bufferSize )
+ {
+ long ret=ov_read(&m_vf,readDest, 4096,0,2,1, &m_current_section);
+ if (ret == 0) {
+ mFileFinished=true;
+ break;
+ } else if (ret < 0) {
+ /* error in the stream. Not a problem, just reporting it in
+ case we (the app) cares. In this case, we don't. */
+ } else {
+ totalRet += ret;
+ readDest += ret;
+ }
+ }
+ if ( totalRet > 0 )
+ {
+ buffersWritten++;
+ alBufferData( buffers[i], mFormat, pcmout, (ALsizei)totalRet, (int)mFrequency);
+ }
+ }
+
+ return buffersWritten;
+}
+
+
+ALuint COggData::getBuffer()
+{
+ return mBuffer[0];
+}
+ALuint* COggData::getBufferPtr()
+{
+ return mBuffer;
+}
+
+
+
+
+
Index: source/soundmanager/data/CSoundData.h
===================================================================
--- source/soundmanager/data/CSoundData.h (revision 0)
+++ source/soundmanager/data/CSoundData.h (revision 0)
@@ -0,0 +1,72 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#ifndef SoundTester_CSoundData_h
+#define SoundTester_CSoundData_h
+#include "lib/os_path.h"
+
+#include "lib/external_libraries/openal.h"
+#include "string"
+#include "map"
+
+class CSoundData;
+typedef std::map DataMap;
+
+
+
+class CSoundData
+{
+public:
+ static CSoundData* soundDataFromFile( OsPath& itemPath );
+ static CSoundData* soundDataFromOgg( OsPath& itemPath );
+// static CSoundData* soundDataFromWAV( OsPath& itemPath );
+
+ static void releaseSoundData( CSoundData* theData );
+
+ CSoundData ();
+ CSoundData (ALuint dataSource);
+ virtual ~CSoundData ();
+
+ CSoundData* incrementCount();
+ bool decrementCount();
+ void initProperties();
+ virtual bool isOneShot();
+
+
+ virtual ALuint getBuffer();
+ virtual ALsizei getBufferCount();
+ std::wstring getFileName();
+ virtual ALuint* getBufferPtr();
+
+protected:
+ static DataMap* sSoundData;
+
+ ALuint mALBuffer;
+ int mRetentionCount;
+ std::wstring mFileName;
+
+
+
+};
+
+
+
+
+
+
+#endif
Index: source/soundmanager/CSoundManager.h
===================================================================
--- source/soundmanager/CSoundManager.h (revision 0)
+++ source/soundmanager/CSoundManager.h (revision 0)
@@ -0,0 +1,99 @@
+/* Copyright (C) 2012 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+
+#ifndef SoundTester_CSoundManager_h
+#define SoundTester_CSoundManager_h
+
+#include "vector"
+#include "map"
+#include "lib/external_libraries/openal.h"
+
+#include "soundmanager/items/ISoundItem.h"
+
+typedef std::vector ItemsList;
+
+
+class CSoundManager
+{
+protected:
+
+ ALuint mALEnvironment;
+ ALCcontext* mContext;
+ ALCdevice* mDevice;
+ ISoundItem* mCurrentTune;
+ ISoundItem* mCurrentEnvirons;
+ ItemsList* mItems;
+ OsPath mResourcePath;
+ float mGain;
+ float mMusicGain;
+ float mAmbientGain;
+ float mActionGain;
+ bool mEnabled;
+ long mBufferSize;
+ int mBufferCount;
+
+public:
+ CSoundManager (OsPath& resourcePath);
+ virtual ~CSoundManager ();
+
+ ISoundItem* loadItem( OsPath* itemPath );
+
+ static void ScriptingInit();
+
+
+
+ ISoundItem* itemFromWAV ( OsPath& fname);
+ ISoundItem* itemFromOgg ( OsPath& fname);
+
+ ISoundItem* getSoundItem ( unsigned long itemRow );
+ unsigned long count ();
+ void idleTask ();
+ void deleteItem ( long itemNum );
+
+ void setMemoryUsage( long bufferSize, int bufferCount );
+ long getBufferCount();
+ long getBufferSize();
+
+ void setMusicItem( ISoundItem* anItem );
+ void setAmbientItem( ISoundItem* anItem );
+ void playActionItem( ISoundItem* anItem );
+ void playGroupItem( ISoundItem* anItem, ALfloat groupGain);
+
+ void setMasterGain( float gain);
+ void setMusicGain( float gain);
+ void setAmbientGain( float gain);
+ void setActionGain( float gain);
+
+ void setEnabled( bool doEnable );
+protected:
+ void InitListener();
+ virtual Status alc_init();
+
+};
+
+
+
+extern CSoundManager* g_SoundManager;
+
+
+
+
+
+
+
+#endif
Index: source/soundmanager/js/JAmbientSound.cpp
===================================================================
--- source/soundmanager/js/JAmbientSound.cpp (revision 0)
+++ source/soundmanager/js/JAmbientSound.cpp (revision 0)
@@ -0,0 +1,99 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "JAmbientSound.h"
+#include "maths/Vector3D.h"
+
+#include "lib/utf8.h"
+#include "lib/res/sound/snd_mgr.h"
+#include "lib/res/h_mgr.h" // h_filename
+#include "ps/Filesystem.h"
+
+#include "soundmanager/CSoundManager.h"
+
+JAmbientSound::JAmbientSound(const VfsPath& pathname)
+{
+ mFileName = new OsPath( pathname.string().c_str() );
+}
+
+JAmbientSound::~JAmbientSound()
+{
+}
+
+
+// start playing the sound, all ambient sounds loop
+bool JAmbientSound::Play(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ ISoundItem* aSnd = g_SoundManager->loadItem( mFileName );
+
+ aSnd->playAsAmbient();
+
+ return true;
+}
+
+// start playing the sound, all ambient sounds loop
+bool JAmbientSound::Loop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ ISoundItem* aSnd = g_SoundManager->loadItem( mFileName );
+
+ aSnd->playAsAmbient();
+ return true;
+}
+bool JAmbientSound::Free(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ g_SoundManager->setAmbientItem( 0L );
+
+ return true;
+}
+
+// Script-bound functions
+
+
+void JAmbientSound::ScriptingInit()
+{
+ AddMethod("toString", 0);
+ AddMethod("play", 0);
+ AddMethod("loop", 0);
+ AddMethod("free", 0);
+
+ CJSObject::ScriptingInit("AmbientSound", &JAmbientSound::Construct, 1);
+}
+
+CStr JAmbientSound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ std::ostringstream stringStream;
+ stringStream << "[object AmbientSound: ";
+ stringStream << mFileName->string().c_str();
+
+ return stringStream.str();
+}
+
+JSBool JAmbientSound::Construct(JSContext* cx, uintN argc, jsval* vp)
+{
+// JSU_REQUIRE_MIN_PARAMS(1);
+
+ CStrW filename;
+ if (! ToPrimitive(cx, JS_ARGV(cx, vp)[0], filename))
+ return JS_FALSE;
+
+ JAmbientSound* newObject = new JAmbientSound(filename);
+ newObject->m_EngineOwned = false;
+
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
+
+ return JS_TRUE;
+}
Index: source/soundmanager/js/JSound.cpp
===================================================================
--- source/soundmanager/js/JSound.cpp (revision 0)
+++ source/soundmanager/js/JSound.cpp (revision 0)
@@ -0,0 +1,171 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "JSound.h"
+#include "maths/Vector3D.h"
+
+#include "lib/utf8.h"
+#include "ps/Filesystem.h"
+
+#include "soundmanager/CSoundManager.h"
+
+
+JSound::JSound(const VfsPath& pathname)
+{
+ OsPath itsPth = OsPath( pathname.string().c_str() );
+ mSndItem = g_SoundManager->loadItem( &itsPth );
+}
+
+JSound::~JSound()
+{
+ if ( mSndItem ) {
+ mSndItem->fadeAndDelete(0.2);
+ mSndItem = 0;
+ }
+}
+
+bool JSound::clearSoundItem()
+{
+ mSndItem = 0L;
+}
+
+bool JSound::SetGain(JSContext* cx, uintN UNUSED(argc), jsval* argv)
+{
+ if (! mSndItem )
+ return false;
+
+ float gain;
+ if (! ToPrimitive(cx, argv[0], gain))
+ return false;
+
+ mSndItem->setGain( gain );
+ return true;
+}
+
+bool JSound::SetPitch(JSContext* cx, uintN UNUSED(argc), jsval* argv)
+{
+ if (! mSndItem )
+ return false;
+
+ float pitch;
+ if (! ToPrimitive(cx, argv[0], pitch))
+ return false;
+
+ mSndItem->setPitch( pitch );
+ return true;
+}
+
+bool JSound::SetPosition(JSContext* cx, uintN argc, jsval* argv)
+{
+ if (! mSndItem )
+ return false;
+
+ ENSURE(argc >= 1); // FIXME
+
+ CVector3D pos;
+ // absolute world coords
+ if (!ToPrimitive(cx, argv[0], pos))
+ return false;
+
+ mSndItem->setLocation( pos );
+
+ return true;
+}
+
+
+bool JSound::Fade(JSContext* cx, uintN argc, jsval* argv)
+{
+ if (! mSndItem )
+ return false;
+
+// ENSURE(argc >= 3); // FIXME
+ float initial_gain, final_gain;
+ float length;
+ if (! (ToPrimitive(cx, argv[0], initial_gain)
+ && ToPrimitive(cx, argv[1], final_gain)
+ && ToPrimitive(cx, argv[2], length)))
+ return false;
+
+ mSndItem->setGain( initial_gain );
+ mSndItem->fadeToIn( final_gain, length );
+
+ return true;
+}
+
+bool JSound::Play(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ if (! mSndItem )
+ return false;
+
+ mSndItem->play();
+
+ return true;
+}
+
+bool JSound::Loop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ if (! mSndItem )
+ return false;
+
+ mSndItem->playLoop();
+
+ return true;
+}
+
+bool JSound::Free(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ if ( mSndItem ) {
+ mSndItem->fadeAndDelete(0.2);
+ mSndItem = 0;
+ }
+
+ return true;
+}
+
+void JSound::ScriptingInit()
+{
+ AddMethod("toString", 0);
+ AddMethod("play", 0);
+ AddMethod("loop", 0);
+ AddMethod("free", 0);
+ AddMethod("setGain", 0);
+ AddMethod("setPitch", 0);
+ AddMethod("setPosition", 0);
+ AddMethod("fade", 0);
+
+ CJSObject::ScriptingInit("Sound", &JSound::Construct, 1);
+}
+
+CStr JSound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ return "[object Sound: " + ( mSndItem ? mSndItem->getName() : "(null)" ) + "]";
+}
+
+JSBool JSound::Construct(JSContext* cx, uintN argc, jsval* vp)
+{
+// JSU_REQUIRE_MIN_PARAMS(1);
+
+ CStrW filename;
+ if (! ToPrimitive(cx, JS_ARGV(cx, vp)[0], filename))
+ return JS_FALSE;
+
+ JSound* newObject = new JSound(filename);
+ newObject->m_EngineOwned = false;
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
+
+ return JS_TRUE;
+}
Index: source/soundmanager/js/JMusicSound.cpp
===================================================================
--- source/soundmanager/js/JMusicSound.cpp (revision 0)
+++ source/soundmanager/js/JMusicSound.cpp (revision 0)
@@ -0,0 +1,85 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "JMusicSound.h"
+#include "maths/Vector3D.h"
+
+#include "lib/utf8.h"
+#include "ps/Filesystem.h"
+
+#include "soundmanager/CSoundManager.h"
+
+
+JMusicSound::JMusicSound(const VfsPath& pathname)
+{
+ mFileName = new OsPath( pathname.string().c_str() );
+}
+
+JMusicSound::~JMusicSound()
+{
+// disposing of music now handled by SoundManager
+}
+
+bool JMusicSound::Play(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ ISoundItem* aSnd = g_SoundManager->loadItem( mFileName );
+ aSnd->playAsMusic();
+
+ return true;
+}
+
+// request the sound be played until free() is called. returns immediately.
+bool JMusicSound::Loop(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ ISoundItem* aSnd = g_SoundManager->loadItem( mFileName );
+ aSnd->playAsMusic();
+
+ return true;
+}
+
+void JMusicSound::ScriptingInit()
+{
+ AddMethod("toString", 0);
+ AddMethod("play", 0);
+ AddMethod("loop", 0);
+
+ CJSObject::ScriptingInit("MusicSound", &JMusicSound::Construct, 1);
+}
+
+CStr JMusicSound::ToString(JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
+{
+ std::ostringstream stringStream;
+ stringStream << "[object MusicSound: ";
+ stringStream << mFileName->string().c_str();
+
+ return stringStream.str();
+}
+
+JSBool JMusicSound::Construct(JSContext* cx, uintN argc, jsval* vp)
+{
+// JSU_REQUIRE_MIN_PARAMS(1);
+
+ CStrW filename;
+ if (! ToPrimitive(cx, JS_ARGV(cx, vp)[0], filename))
+ return JS_FALSE;
+
+ JMusicSound* newObject = new JMusicSound(filename);
+ newObject->m_EngineOwned = false;
+ JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(newObject->GetScript()));
+
+ return JS_TRUE;
+}
Index: source/soundmanager/js/SMSoundGroup.cpp
===================================================================
--- source/soundmanager/js/SMSoundGroup.cpp (revision 0)
+++ source/soundmanager/js/SMSoundGroup.cpp (revision 0)
@@ -0,0 +1,295 @@
+/* Copyright (C) 2010 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+/**
+* =========================================================================
+* File : SoundGroup.cpp
+* Project : 0 A.D.
+* Description : Loads up a group of sound files with shared properties,
+* and provides a simple interface for playing them.
+* =========================================================================
+*/
+
+#include "precompiled.h"
+#include "soundmanager/CSoundManager.h"
+#include "SMSoundGroup.h"
+
+#include
+
+#include "lib/rand.h"
+
+#include "ps/XML/Xeromyces.h"
+#include "ps/CLogger.h"
+#include "ps/Filesystem.h"
+#include "ps/Util.h"
+
+
+static const bool DISABLE_INTENSITY = true; // disable for now since it's broken
+
+void CSMSoundGroup::SetGain(float gain)
+{
+ gain = std::min(gain, 1.0f);
+ m_Gain = gain;
+}
+
+void CSMSoundGroup::SetDefaultValues()
+{
+ m_index = 0;
+ m_Flags = 0;
+ m_Intensity = 0;
+ m_CurTime = 0.0f;
+
+ // sane defaults; will probably be replaced by the values read during LoadSoundGroup.
+ SetGain(0.7f);
+ m_Pitch = 1.0f;
+ m_Priority = 60;
+ m_PitchUpper = 1.1f;
+ m_PitchLower = 0.9f;
+ m_GainUpper = 1.0f;
+ m_GainLower = 0.8f;
+ m_ConeOuterGain = 0.0f;
+ m_ConeInnerAngle = 360.0f;
+ m_ConeOuterAngle = 360.0f;
+ m_Decay = 3.0f;
+ m_IntensityThreshold = 3;
+ // WARNING: m_TimeWindow is currently unused and uninitialized
+}
+
+CSMSoundGroup::CSMSoundGroup()
+{
+ SetDefaultValues();
+}
+
+CSMSoundGroup::CSMSoundGroup(const VfsPath& pathnameXML)
+{
+ SetDefaultValues();
+ LoadSoundGroup(pathnameXML);
+}
+
+CSMSoundGroup::~CSMSoundGroup()
+{
+ // clean up all the handles from this group.
+ ReleaseGroup();
+}
+
+static float RandFloat(float min, float max)
+{
+ return float(rand(min*100.0f, max*100.0f) / 100.0f);
+}
+
+void CSMSoundGroup::UploadPropertiesAndPlay(ISoundItem* hSound, const CVector3D& position)
+{
+ hSound->setLocation( position );
+
+ if( TestFlag(eRandPitch) )
+ hSound->setPitch( RandFloat( m_PitchLower, m_PitchUpper ) );
+ else
+ hSound->setPitch( m_Pitch );
+
+ ALfloat theGain = m_Gain;
+ if( TestFlag(eRandGain) )
+ theGain = RandFloat( m_GainLower, m_GainUpper);
+
+ hSound->setCone( m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain);
+
+
+ g_SoundManager->playGroupItem( hSound, theGain );
+}
+
+
+static void HandleError(const std::wstring& message, const VfsPath& pathname, Status err)
+{
+ if(err == ERR::AGAIN)
+ return; // open failed because sound is disabled (don't log this)
+ LOGERROR(L"%ls: pathname=%ls, error=%ls", message.c_str(), pathname.string().c_str(), ErrorString(err));
+}
+
+void CSMSoundGroup::PlayNext(const CVector3D& position)
+{
+ // if no sounds, return
+ if (filenames.size() == 0)
+ return;
+
+ m_index = (size_t)rand(0, (size_t)filenames.size());
+ UploadPropertiesAndPlay( snd_group[m_index], position);
+}
+
+void CSMSoundGroup::Reload()
+{
+ m_index = 0; // reset our index
+
+ snd_group.clear();
+
+ for(size_t i = 0; i < filenames.size(); i++)
+ {
+ OsPath thePath = OsPath( m_filepath/filenames[i] );
+ ISoundItem* temp = g_SoundManager->loadItem( &thePath );
+ snd_group.push_back(temp);
+ }
+
+ if(TestFlag(eRandOrder))
+ random_shuffle(snd_group.begin(), snd_group.end());
+}
+
+void CSMSoundGroup::ReleaseGroup()
+{
+
+ for(size_t i = 0; i < filenames.size(); i++)
+ {
+ snd_group[i]->fadeAndDelete(0.2);
+ }
+ snd_group.clear();
+}
+
+void CSMSoundGroup::Update(float TimeSinceLastFrame)
+{
+}
+
+bool CSMSoundGroup::LoadSoundGroup(const VfsPath& pathnameXML)
+{
+// LOGERROR(L"loading new sound group '%ls'", pathnameXML.string().c_str());
+
+ CXeromyces XeroFile;
+ if (XeroFile.Load(g_VFS, pathnameXML) != PSRETURN_OK)
+ return false;
+
+ // Define elements used in XML file
+ #define EL(x) int el_##x = XeroFile.GetElementID(#x)
+ #define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
+ EL(soundgroup);
+ EL(gain);
+ EL(looping);
+ EL(omnipresent);
+ EL(pitch);
+ EL(priority);
+ EL(randorder);
+ EL(randgain);
+ EL(randpitch);
+ EL(conegain);
+ EL(coneinner);
+ EL(coneouter);
+ EL(sound);
+ EL(gainupper);
+ EL(gainlower);
+ EL(pitchupper);
+ EL(pitchlower);
+ EL(path);
+ EL(threshold);
+ EL(decay);
+ EL(replacement);
+ #undef AT
+ #undef EL
+
+ XMBElement root = XeroFile.GetRoot();
+
+ if (root.GetNodeName() != el_soundgroup)
+ {
+ LOGERROR(L"Invalid SoundGroup format (unrecognised root element '%hs')", XeroFile.GetElementString(root.GetNodeName()).c_str());
+ return false;
+ }
+
+ XERO_ITER_EL(root, child)
+ {
+
+ int child_name = child.GetNodeName();
+
+ if(child_name == el_gain)
+ {
+ SetGain(child.GetText().ToFloat());
+ }
+ else if(child_name == el_looping)
+ {
+ if(child.GetText().ToInt() == 1)
+ SetFlag(eLoop);
+ }
+ else if(child_name == el_omnipresent)
+ {
+ if(child.GetText().ToInt() == 1)
+ SetFlag(eOmnipresent);
+ }
+ else if(child_name == el_pitch)
+ {
+ this->m_Pitch = child.GetText().ToFloat();
+ }
+ else if(child_name == el_priority)
+ {
+ this->m_Priority = child.GetText().ToFloat();
+ }
+ else if(child_name == el_randorder)
+ {
+ if(child.GetText().ToInt() == 1)
+ SetFlag(eRandOrder);
+ }
+ else if(child_name == el_randgain)
+ {
+ if(child.GetText().ToInt() == 1)
+ SetFlag(eRandGain);
+ }
+ else if(child_name == el_gainupper)
+ {
+ this->m_GainUpper = child.GetText().ToFloat();
+ }
+ else if(child_name == el_gainlower)
+ {
+ this->m_GainLower = child.GetText().ToFloat();
+ }
+ else if(child_name == el_randpitch)
+ {
+ if(child.GetText().ToInt() == 1)
+ SetFlag(eRandPitch);
+ }
+ else if(child_name == el_pitchupper)
+ {
+ this->m_PitchUpper = child.GetText().ToFloat();
+ }
+ else if(child_name == el_pitchlower)
+ {
+ this->m_PitchLower = child.GetText().ToFloat();
+ }
+ else if(child_name == el_conegain)
+ {
+ this->m_ConeOuterGain = child.GetText().ToFloat();
+ }
+ else if(child_name == el_coneinner)
+ {
+ this->m_ConeInnerAngle = child.GetText().ToFloat();
+ }
+ else if(child_name == el_coneouter)
+ {
+ this->m_ConeOuterAngle = child.GetText().ToFloat();
+ }
+ else if(child_name == el_sound)
+ {
+ this->filenames.push_back(child.GetText().FromUTF8());
+ }
+ else if(child_name == el_path)
+ {
+ m_filepath = child.GetText().FromUTF8();
+ }
+ else if(child_name == el_threshold)
+ {
+ m_IntensityThreshold = child.GetText().ToFloat();
+ }
+ else if(child_name == el_decay)
+ {
+ m_Decay = child.GetText().ToFloat();
+ }
+ }
+
+ Reload();
+ return true;
+}
Index: source/soundmanager/js/JAmbientSound.h
===================================================================
--- source/soundmanager/js/JAmbientSound.h (revision 0)
+++ source/soundmanager/js/JAmbientSound.h (revision 0)
@@ -0,0 +1,51 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_JAMBIENTSOUND
+#define INCLUDED_JAMBIENTSOUND
+
+#include "scripting/ScriptableObject.h"
+#include "soundmanager/items/ISoundItem.h"
+
+class JAmbientSound : public CJSObject
+{
+public:
+ JAmbientSound (const VfsPath& pathname);
+ virtual ~JAmbientSound ();
+
+
+ CStr ToString(JSContext* cx, uintN argc, jsval* argv);
+
+ bool Play(JSContext* cx, uintN argc, jsval* argv);
+
+ bool Loop(JSContext* cx, uintN argc, jsval* argv);
+ bool Free(JSContext* cx, uintN argc, jsval* argv);
+
+ bool SetGain(JSContext* cx, uintN argc, jsval* argv);
+ bool SetPitch(JSContext* cx, uintN argc, jsval* argv);
+ bool Fade(JSContext* cx, uintN argc, jsval* argv);
+
+ static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
+ void clearSoundItem();
+ static void ScriptingInit();
+protected:
+
+ OsPath* mFileName;
+
+};
+
+#endif // #ifndef INCLUDED_JAMBIENTSOUND
Index: source/soundmanager/js/JSound.h
===================================================================
--- source/soundmanager/js/JSound.h (revision 0)
+++ source/soundmanager/js/JSound.h (revision 0)
@@ -0,0 +1,67 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+// JS sound binding
+
+// interface rationale:
+// - can't just expose fire and forget playSound to script code:
+// we sometimes need to loop until a certain condition is met
+// (e.g. building is complete) => need means of access (Handle) to sound.
+//
+// - the current 64-bit Handle can't be stored as-is by JS code;
+// we could make it 32 bit, but that limits its usefulness
+// (barely enough tag bits).
+//
+// - instead, we provide a thin class wrapper (using scriptableobject.h)
+// on top of the snd API that encapsulates the Handle.
+
+#ifndef INCLUDED_JSOUND
+#define INCLUDED_JSOUND
+
+#include "scripting/ScriptableObject.h"
+#include "soundmanager/items/ISoundItem.h"
+
+class JSound : public CJSObject
+{
+public:
+
+ // note: filename is stored by handle manager; no need to keep a copy here.
+
+ JSound(const VfsPath& pathname);
+ virtual ~JSound();
+
+ CStr ToString(JSContext* cx, uintN argc, jsval* argv);
+
+ bool Play(JSContext* cx, uintN argc, jsval* argv);
+ bool Loop(JSContext* cx, uintN argc, jsval* argv);
+
+ bool Free(JSContext* cx, uintN argc, jsval* argv);
+ bool SetGain(JSContext* cx, uintN argc, jsval* argv);
+ bool SetPitch(JSContext* cx, uintN argc, jsval* argv);
+ bool SetPosition(JSContext* cx, uintN argc, jsval* argv);
+ bool clearSoundItem();
+
+ bool Fade(JSContext* cx, uintN argc, jsval* argv);
+
+ static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
+ static void ScriptingInit();
+
+protected:
+ ISoundItem* mSndItem;
+};
+
+#endif // #ifndef INCLUDED_JSOUND
Index: source/soundmanager/js/JMusicSound.h
===================================================================
--- source/soundmanager/js/JMusicSound.h (revision 0)
+++ source/soundmanager/js/JMusicSound.h (revision 0)
@@ -0,0 +1,59 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+// JS sound binding
+
+// interface rationale:
+// - can't just expose fire and forget playSound to script code:
+// we sometimes need to loop until a certain condition is met
+// (e.g. building is complete) => need means of access (Handle) to sound.
+//
+// - the current 64-bit Handle can't be stored as-is by JS code;
+// we could make it 32 bit, but that limits its usefulness
+// (barely enough tag bits).
+//
+// - instead, we provide a thin class wrapper (using scriptableobject.h)
+// on top of the snd API that encapsulates the Handle.
+
+#ifndef INCLUDED_JMUSICSOUND
+#define INCLUDED_JMUSICSOUND
+
+#include "scripting/ScriptableObject.h"
+#include "soundmanager/items/ISoundItem.h"
+
+class JMusicSound : public CJSObject
+{
+public:
+ JMusicSound(const VfsPath& pathname);
+ virtual ~JMusicSound();
+
+ // Script-bound functions
+
+ CStr ToString(JSContext* cx, uintN argc, jsval* argv);
+
+ bool Play(JSContext* cx, uintN argc, jsval* argv);
+ bool Loop(JSContext* cx, uintN argc, jsval* argv);
+
+ static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
+
+ static void ScriptingInit();
+
+protected:
+ OsPath* mFileName;
+};
+
+#endif // #ifndef INCLUDED_JMUSICSOUND
Index: source/soundmanager/js/SMSoundGroup.h
===================================================================
--- source/soundmanager/js/SMSoundGroup.h (revision 0)
+++ source/soundmanager/js/SMSoundGroup.h (revision 0)
@@ -0,0 +1,137 @@
+/* Copyright (C) 2009 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+/**
+* =========================================================================
+* File : SoundGroup.h
+* Project : 0 A.D.
+* Description : Loads up a group of sound files with shared properties,
+* and provides a simple interface for playing them.
+* =========================================================================
+*/
+
+/*
+Example usage:
+
+
+Example SoundGroup.xml
+
+
+ 1.0
+ 0
+ 1.0
+ 100
+ 0
+ 0
+ 0
+ 1.0
+ 360
+ 360
+ audio/voice/hellenes/soldier/Attack_Attackx.ogg
+ audio/voice/hellenes/soldier/Attack_Chargex.ogg
+ audio/voice/hellenes/soldier/Attack_Engagex.ogg
+ audio/voice/hellenes/soldier/Attack_ForMyFamily.ogg
+
+
+*/
+
+#ifndef INCLUDED_SMSOUNDGROUP
+#define INCLUDED_SMSOUNDGROUP
+
+#include "lib/res/handle.h"
+#include "lib/file/vfs/vfs_path.h"
+#include "ps/CStr.h"
+#include "maths/Vector3D.h"
+#include "lib/res/sound/snd_mgr.h"
+#include "soundmanager/items/ISoundItem.h"
+
+#include
+
+enum eSndGrpFlags
+{
+ eRandOrder = 0x01,
+ eRandGain = 0x02,
+ eRandPitch = 0x04,
+ eLoop = 0x08,
+ eOmnipresent = 0x10
+};
+
+
+class CSMSoundGroup
+{
+ NONCOPYABLE(CSMSoundGroup);
+public:
+ CSMSoundGroup(const VfsPath& pathnameXML);
+ CSMSoundGroup(void);
+ ~CSMSoundGroup(void);
+
+ // Play next sound in group
+ // @param position world position of the entity generating the sound
+ // (ignored if the eOmnipresent flag is set)
+ void PlayNext(const CVector3D& position);
+
+ // Load a group
+ bool LoadSoundGroup(const VfsPath& pathnameXML);
+
+ void Reload();
+
+ // Release all remaining loaded handles
+ void ReleaseGroup();
+
+ // Update SoundGroup, remove dead sounds from intensity count
+ void Update(float TimeSinceLastFrame);
+
+ // Set a flag using a value from eSndGrpFlags
+ inline void SetFlag(int flag) { m_Flags = (unsigned char)(m_Flags | flag); }
+
+ // Test flag, returns true if flag is set.
+ inline bool TestFlag(int flag) { return (m_Flags & flag) != 0; }
+
+private:
+ void SetGain(float gain);
+ void UploadPropertiesAndPlay(ISoundItem* hSound, const CVector3D& position);
+ void SetDefaultValues();
+
+ size_t m_index; // index of the next sound to play
+
+ Handle m_hReplacement;
+
+ std::vector snd_group; // we store the handles so we can load now and play later
+ std::vector filenames; // we need the filenames so we can reload when necessary.
+
+ VfsPath m_filepath; // the file path for the list of sound file resources
+
+ float m_CurTime; // Time elapsed since soundgroup was created
+ float m_TimeWindow; // The Intensity Threshold Window
+ size_t m_IntensityThreshold; // the allowable intensity before a sound switch
+ size_t m_Intensity; // our current intensity(number of sounds played since m_CurTime - m_TimeWindow)
+ float m_Decay; //
+ unsigned char m_Flags; // up to eight individual parameters, use with eSndGrpFlags.
+
+ float m_Gain;
+ float m_Pitch;
+ float m_Priority;
+ float m_ConeOuterGain;
+ float m_PitchUpper;
+ float m_PitchLower;
+ float m_GainUpper;
+ float m_GainLower;
+ float m_ConeInnerAngle;
+ float m_ConeOuterAngle;
+};
+
+#endif //#ifndef INCLUDED_SOUNDGROUP
Index: source/main.cpp
===================================================================
--- source/main.cpp (revision 11718)
+++ source/main.cpp (working copy)
@@ -383,17 +383,17 @@
// coincide in position and orientation.
float down[3] = { -up[0], -up[1], -up[2] };
- {
- PROFILE3("sound update");
- if (snd_update(pos, dir, down) < 0)
- debug_printf(L"snd_update failed\n");
- }
+// {
+// PROFILE3("sound update");
+// if (snd_update(pos, dir, down) < 0)
+// debug_printf(L"snd_update failed\n");
+// }
}
else
{
- PROFILE3("sound update (0)");
- if (snd_update(0, 0, 0) < 0)
- debug_printf(L"snd_update (pos=0 version) failed\n");
+// PROFILE3("sound update (0)");
+// if (snd_update(0, 0, 0) < 0)
+// debug_printf(L"snd_update (pos=0 version) failed\n");
}
// Immediately flush any messages produced by simulation code
@@ -477,8 +477,6 @@
// run non-visual simulation replay if requested
if (args.Has("replay"))
{
- snd_disable(true);
-
Paths paths(args);
g_VFS = CreateVfs(20 * MiB);
g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE);
Index: source/simulation2/components/CCmpSoundManager.cpp
===================================================================
--- source/simulation2/components/CCmpSoundManager.cpp (revision 11718)
+++ source/simulation2/components/CCmpSoundManager.cpp (working copy)
@@ -24,7 +24,7 @@
#include "simulation2/MessageTypes.h"
#include "simulation2/components/ICmpPosition.h"
#include "simulation2/components/ICmpRangeManager.h"
-#include "sound/SoundGroup.h"
+#include "soundmanager/js/SMSoundGroup.h"
class CCmpSoundManager : public ICmpSoundManager
{
@@ -36,7 +36,7 @@
DEFAULT_COMPONENT_ALLOCATOR(SoundManager)
- std::map m_SoundGroups;
+ std::map m_SoundGroups;
static std::string GetSchema()
{
@@ -49,7 +49,7 @@
virtual void Deinit()
{
- for (std::map::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
+ for (std::map::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
delete it->second;
m_SoundGroups.clear();
}
@@ -76,7 +76,7 @@
// or on some other timer?
const CMessageUpdate& msgData = static_cast (msg);
float t = msgData.turnLength.ToFloat();
- for (std::map::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
+ for (std::map::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
if (it->second)
it->second->Update(t);
break;
@@ -87,10 +87,10 @@
virtual void PlaySoundGroup(std::wstring name, entity_id_t source)
{
// Make sure the sound group is loaded
- CSoundGroup* group;
+ CSMSoundGroup* group;
if (m_SoundGroups.find(name) == m_SoundGroups.end())
{
- group = new CSoundGroup();
+ group = new CSMSoundGroup();
if (!group->LoadSoundGroup(L"audio/" + name))
{
LOGERROR(L"Failed to load sound group '%ls'", name.c_str());
Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js (revision 11718)
+++ binaries/data/mods/public/gui/session/session.js (working copy)
@@ -408,12 +408,11 @@
// currentAmbient = newRandomSound("ambient", "temperate_", "dayscape");
const AMBIENT = "audio/ambient/dayscape/day_temperate_gen_03.ogg";
- currentAmbient = new Sound(AMBIENT);
+ currentAmbient = new AmbientSound(AMBIENT);
if (currentAmbient)
{
currentAmbient.loop();
- currentAmbient.setGain(0.8);
}
break;
@@ -428,7 +427,7 @@
{
if (currentAmbient)
{
- currentAmbient.fade(-1, 0.0, 5.0);
+ currentAmbient.free();
currentAmbient = null;
}
}
Index: binaries/data/mods/public/gui/common/music.js
===================================================================
--- binaries/data/mods/public/gui/common/music.js (revision 11718)
+++ binaries/data/mods/public/gui/common/music.js (working copy)
@@ -72,11 +72,6 @@
switch (this.currentState)
{
case this.states.OFF:
- if (this.isPlaying())
- {
- this.currentMusic.fade(-1, 0.0, 3.0);
- this.currentMusic = null;
- }
break;
case this.states.MENU:
@@ -146,23 +141,14 @@
Music.prototype.switchMusic = function(track, fadeInPeriod, isLooping)
{
- if (this.currentMusic)
- {
- this.currentMusic.fade(-1, 0.0, 5.0);
- this.currentMusic = null;
- }
+ this.currentMusic = new MusicSound(this.RELATIVE_MUSIC_PATH + track);
- this.currentMusic = new Sound(this.RELATIVE_MUSIC_PATH + track);
-
if (this.currentMusic)
{
if (isLooping)
this.currentMusic.loop();
else
this.currentMusic.play();
-
- if (fadeInPeriod)
- this.currentMusic.fade(0.0, this.musicGain, fadeInPeriod);
}
};
Index: binaries/data/mods/public/gui/common/functions_utility_music.js
===================================================================
--- binaries/data/mods/public/gui/common/functions_utility_music.js (revision 11718)
+++ binaries/data/mods/public/gui/common/functions_utility_music.js (working copy)
@@ -66,6 +66,20 @@
//console.write("Playing " + randomSoundPath + " ...");
+ switch (soundType)
+ {
+ case "music":
+ return new MusicSound(randomSoundPath);
+ break;
+ case "ambient":
+ return new AmbientSound(randomSoundPath);
+ break;
+ case "effect":
+ console.write ("am loading effect '*"+randomSoundPath+"*'");
+ break;
+ default:
+ break;
+ }
return new Sound(randomSoundPath);
}
Index: binaries/data/mods/public/hwdetect/hwdetect.js
===================================================================
--- binaries/data/mods/public/hwdetect/hwdetect.js (revision 11718)
+++ binaries/data/mods/public/hwdetect/hwdetect.js (working copy)
@@ -213,11 +213,11 @@
}
// http://trac.wildfiregames.com/ticket/685
- if (os_macosx)
- {
- warnings.push("Audio has been disabled, due to problems with OpenAL on OS X.");
- disable_audio = true;
- }
+// if (os_macosx)
+// {
+// warnings.push("Audio has been disabled, due to problems with OpenAL on OS X.");
+// disable_audio = true;
+// }
// http://trac.wildfiregames.com/ticket/684
// https://bugs.freedesktop.org/show_bug.cgi?id=24047
Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg (revision 11718)
+++ binaries/data/config/default.cfg (working copy)
@@ -73,7 +73,12 @@
; GENERAL PREFERENCES:
-sound.mastergain = 0.5
+sound.mastergain = 0.9
+sound.musicgain = 0.1
+sound.ambientgain = 0.6
+sound.actiongain = 0.7
+sound.bufferCount = 50
+sound.bufferSize = 65536
; Camera control settings
view.scroll.speed = 120.0