00001 #ifdef USE_FMOD
00002 #include "lugre_sound.h"
00003
00004
00005
00006 #include <fmod.h>
00007 #include <fmod_errors.h>
00008
00009 namespace Lugre {
00010
00011
00012
00013 FMOD_RESULT result;
00014
00015 void ERRCHECK(FMOD_RESULT result){
00016 if (result != FMOD_OK){
00017 printf("FMOD error! (%d) %s\n", (int)result, FMOD_ErrorString(result));
00018 }
00019 }
00020
00021
00022 class cSoundSourceFmod;
00023
00024 class cSoundSystemFmod : public cSoundSystem {
00025 friend class Lugre::cSoundSourceFmod;
00026 public:
00027 cSoundSystemFmod(const int frequency, const int maxchannels);
00028 virtual ~cSoundSystemFmod();
00029 virtual void SetListenerPosition(const float x, const float y, const float z);
00030 virtual void SetListenerVelocity(const float x, const float y, const float z);
00031 virtual void GetListenerPosition(float &x, float &y, float &z);
00032 virtual void GetListenerVelocity(float &x, float &y, float &z);
00033 virtual void SetVolume(const float volume);
00034 virtual const float GetVolume();
00035 virtual void SetDistanceFactor(const float s);
00036 virtual const float GetDistanceFactor();
00037 virtual cSoundSource *CreateSoundSource(const char *filename);
00038 virtual cSoundSource *CreateSoundSource(const char *buffer, const int size, const int channels, const int bitrate, const int frequency);
00039 virtual cSoundSource *CreateSoundSource3D(const float x, const float y, const float z, const char *filename);
00040 virtual cSoundSource *CreateSoundSource3D(const float x, const float y, const float z, const char *buffer, const int size, const int channels, const int bitrate, const int frequency);
00041 virtual void Step();
00042
00043 private:
00045 void UpdatePositionAndVelocity();
00046
00048 int miMaxChannels;
00050 float mfDistanceFactor;
00052 FMOD_VECTOR mlPos;
00053 FMOD_VECTOR mlVel;
00054
00056 FMOD_SYSTEM *mpSystem;
00057 };
00058
00060 class cSoundSourceFmod : public cSoundSource {
00061 public:
00062 cSoundSourceFmod(cSoundSystemFmod *soundsystem, const char *filename) : mSoundSystem(soundsystem), mpChannel(0), mb3D(false), mpSound(0), mfMinDistance(100.0f), mfMaxDistance(100000.0f) {
00063 if(mSoundSystem && mSoundSystem->mpSystem){
00064 result = FMOD_System_CreateStream(mSoundSystem->mpSystem,filename, (FMOD_MODE)(FMOD_SOFTWARE | FMOD_2D), 0, &mpSound);
00065 ERRCHECK(result);
00066
00067 SetPosition(0.0f,0.0f,0.0f);
00068 SetVelocity(0.0f,0.0f,0.0f);
00069 }
00070 }
00071 cSoundSourceFmod(cSoundSystemFmod *soundsystem, const char *buffer, const int size, const int channels, const int bitrate, const int frequency) : mSoundSystem(soundsystem), mpChannel(0), mb3D(false), mpSound(0), mfMinDistance(100.0f), mfMaxDistance(100000.0f) {
00072 if(mSoundSystem && mSoundSystem->mpSystem){
00073 FMOD_CREATESOUNDEXINFO exinfo;
00074
00075 memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
00076 exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
00077 exinfo.length = size;
00078 exinfo.numchannels = channels;
00079 exinfo.defaultfrequency = frequency;
00080
00081 switch(bitrate){
00082 case 8:exinfo.format = FMOD_SOUND_FORMAT_PCM8;break;
00083 case 16:exinfo.format = FMOD_SOUND_FORMAT_PCM16;break;
00084 case 24:exinfo.format = FMOD_SOUND_FORMAT_PCM24;break;
00085 case 32:exinfo.format = FMOD_SOUND_FORMAT_PCM32;break;
00086 }
00087
00088 result = FMOD_System_CreateStream(mSoundSystem->mpSystem, buffer, (FMOD_MODE)(FMOD_OPENRAW | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_2D), &exinfo, &mpSound);
00089 ERRCHECK(result);
00090 }
00091
00092 SetPosition(0.0f,0.0f,0.0f);
00093 SetVelocity(0.0f,0.0f,0.0f);
00094 }
00095
00096 cSoundSourceFmod(cSoundSystemFmod *soundsystem, const float x, const float y, const float z, const char *filename) : mSoundSystem(soundsystem), mpChannel(0), mb3D(true), mpSound(0), mfMinDistance(100.0f), mfMaxDistance(100000.0f) {
00097 if(mSoundSystem && mSoundSystem->mpSystem){
00098 result = FMOD_System_CreateStream(mSoundSystem->mpSystem, filename, (FMOD_MODE)(FMOD_SOFTWARE | FMOD_3D), 0, &mpSound);
00099 ERRCHECK(result);
00100
00101 SetPosition(x,y,z);
00102 SetVelocity(0,0,0);
00103 }
00104 }
00105
00106 cSoundSourceFmod(cSoundSystemFmod *soundsystem, const float x, const float y, const float z, const char *buffer, const int size, const int channels, const int bitrate, const int frequency) : mSoundSystem(soundsystem), mpChannel(0), mb3D(true), mpSound(0), mfMinDistance(100.0f), mfMaxDistance(100000.0f) {
00107 if(mSoundSystem && mSoundSystem->mpSystem){
00108 FMOD_CREATESOUNDEXINFO exinfo;
00109
00110 memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
00111 exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
00112 exinfo.length = size;
00113 exinfo.numchannels = channels;
00114 exinfo.defaultfrequency = frequency;
00115
00116 switch(bitrate){
00117 case 8:exinfo.format = FMOD_SOUND_FORMAT_PCM8;break;
00118 case 16:exinfo.format = FMOD_SOUND_FORMAT_PCM16;break;
00119 case 24:exinfo.format = FMOD_SOUND_FORMAT_PCM24;break;
00120 case 32:exinfo.format = FMOD_SOUND_FORMAT_PCM32;break;
00121 }
00122
00123 result = FMOD_System_CreateStream(mSoundSystem->mpSystem, buffer, (FMOD_MODE)(FMOD_OPENRAW | FMOD_OPENMEMORY | FMOD_SOFTWARE | FMOD_3D), &exinfo, &mpSound);
00124 ERRCHECK(result);
00125 }
00126
00127 SetPosition(x,y,z);
00128 SetVelocity(0.0f,0.0f,0.0f);
00129 }
00130
00131 virtual ~cSoundSourceFmod(){
00132 if(mpSound){
00133
00134 FMOD_Sound_Release(mpSound);
00135 mpSound = 0;
00136 }
00137 }
00138
00140 virtual const bool Play(){
00141 if(IsPlaying())return true;
00142 if(IsPaused()){
00143
00144 if(mpChannel){
00145 result = FMOD_Channel_SetPaused(mpChannel,false);
00146 ERRCHECK(result);
00147 }
00148 } else {
00149
00150 mpChannel = 0;
00151
00152 if(mpSound && mSoundSystem && mSoundSystem->mpSystem){
00153 result = FMOD_System_PlaySound(mSoundSystem->mpSystem, FMOD_CHANNEL_FREE, mpSound, true, &mpChannel);
00154 ERRCHECK(result);
00155 }
00156
00157
00158 if(mpChannel){
00159
00160 if(mb3D){
00161
00162 result = FMOD_Channel_Set3DAttributes(mpChannel, &mlPos, &mlVel);
00163 ERRCHECK(result);
00164
00165 SetMinMaxDistance(mfMinDistance,mfMaxDistance);
00166 }
00167
00168 result = FMOD_Channel_SetPaused(mpChannel,false);
00169 ERRCHECK(result);
00170
00171 return true;
00172 } else return false;
00173 }
00174 return false;
00175 }
00176
00178 virtual const bool IsPlaying(){
00179 FMOD_BOOL b;
00180 if(mpChannel == 0)return false;
00181 else {
00182 FMOD_Channel_IsPlaying(mpChannel,&b);
00183 if(b)return true;
00184 else return false;
00185 }
00186 }
00188 virtual const bool IsPaused(){
00189 FMOD_BOOL b;
00190 if(mpChannel == 0)return false;
00191 else {
00192 FMOD_Channel_GetPaused(mpChannel,&b);
00193 if(b)return true;
00194 else return false;
00195 }
00196 }
00197
00199 virtual void Stop(){
00200 if(mpChannel == 0)return;
00201
00202 result = FMOD_Channel_Stop(mpChannel);
00203 ERRCHECK(result);
00204 }
00205
00207 virtual void Pause(){
00208 if(mpChannel == 0)return;
00209
00210 result = FMOD_Channel_SetPaused(mpChannel, true);
00211 ERRCHECK(result);
00212 }
00213
00215 virtual void SetVolume(const float volume){
00216 if(mpChannel == 0)return;
00217
00218 result = FMOD_Channel_SetVolume(mpChannel, volume);
00219 ERRCHECK(result);
00220 }
00221
00222 virtual const float GetVolume(){
00223 float b;
00224 if(mpChannel == 0)return 0.0f;
00225 else {
00226 FMOD_Channel_GetVolume(mpChannel, &b);
00227 return b;
00228 }
00229 }
00230
00232 virtual void SetMinMaxDistance(const float min, const float max){
00233 mfMinDistance = min;
00234 mfMaxDistance = max;
00235
00236 if(mpChannel == 0 || !Is3D())return;
00237
00238 result = FMOD_Channel_Set3DMinMaxDistance(mpChannel, min * mSoundSystem->mfDistanceFactor,max * mSoundSystem->mfDistanceFactor);
00239 ERRCHECK(result);
00240 }
00241
00242 virtual void GetMinMaxDistance(float &min, float &max){
00243 if(mpChannel == 0 || !Is3D())return;
00244
00245
00246
00247 min = mfMinDistance;
00248 max = mfMaxDistance;
00249
00250
00251
00252 }
00253
00254
00256
00258 virtual bool Is3D(){return mb3D;}
00259
00261 virtual void SetPosition(const float x, const float y, const float z){
00262 if(!Is3D())return;
00263 mlPos.x = x * mSoundSystem->mfDistanceFactor;
00264 mlPos.y = y * mSoundSystem->mfDistanceFactor;
00265 mlPos.z = z * mSoundSystem->mfDistanceFactor;
00266 if(mpChannel == 0)return;
00267
00268 result = FMOD_Channel_Set3DAttributes(mpChannel, &mlPos, &mlVel);
00269 ERRCHECK(result);
00270 }
00271
00273 virtual void SetVelocity(const float x, const float y, const float z){
00274 if(!Is3D())return;
00275 mlVel.x = x * mSoundSystem->mfDistanceFactor;
00276 mlVel.y = y * mSoundSystem->mfDistanceFactor;
00277 mlVel.z = z * mSoundSystem->mfDistanceFactor;
00278 if(mpChannel == 0)return;
00279
00280 result = FMOD_Channel_Set3DAttributes(mpChannel, &mlPos, &mlVel);
00281 ERRCHECK(result);
00282 }
00283
00285 virtual void GetPosition(float &x, float &y, float &z){
00286 if(!Is3D())return;
00287 x = mlPos.x / mSoundSystem->mfDistanceFactor;
00288 y = mlPos.y / mSoundSystem->mfDistanceFactor;
00289 z = mlPos.z / mSoundSystem->mfDistanceFactor;
00290 }
00291
00293 virtual void GetVelocity(float &x, float &y, float &z){
00294 if(!Is3D())return;
00295 x = mlVel.x / mSoundSystem->mfDistanceFactor;
00296 y = mlVel.y / mSoundSystem->mfDistanceFactor;
00297 z = mlVel.z / mSoundSystem->mfDistanceFactor;
00298 }
00299
00300 private:
00301 FMOD_SOUND *mpSound;
00302 FMOD_CHANNEL *mpChannel;
00303
00305 cSoundSystemFmod *mSoundSystem;
00307 bool mb3D;
00308
00310 float mfMinDistance,mfMaxDistance;
00311
00313 FMOD_VECTOR mlPos;
00314 FMOD_VECTOR mlVel;
00315 };
00316
00317
00318
00319
00320 cSoundSystemFmod::cSoundSystemFmod(const int frequency, const int maxchannels) : mpSystem(0), miMaxChannels(maxchannels), mfDistanceFactor(1.0f) {
00321 result = FMOD_System_Create(&mpSystem);
00322 ERRCHECK(result);
00323
00324 if(mpSystem){
00325 unsigned int version;
00326 result = FMOD_System_GetVersion(mpSystem, &version);
00327 ERRCHECK(result);
00328
00329 if (version < FMOD_VERSION){
00330 printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION);
00331 }
00332
00333 result = FMOD_System_Init(mpSystem, miMaxChannels, FMOD_INIT_NORMAL, 0);
00334 ERRCHECK(result);
00335 }
00336
00337 SetListenerPosition(0.0f,0.0f,0.0f);
00338 SetListenerVelocity(0.0f,0.0f,0.0f);
00339 }
00340
00341 cSoundSystemFmod::~cSoundSystemFmod(){
00342 if(mpSystem){
00343 result = FMOD_System_Close(mpSystem);
00344 ERRCHECK(result);
00345 result = FMOD_System_Release(mpSystem);
00346 ERRCHECK(result);
00347 }
00348 }
00349
00350
00351 void cSoundSystemFmod::UpdatePositionAndVelocity(){
00352 if(mpSystem){
00353 result = FMOD_System_Set3DListenerAttributes(mpSystem, 0, &mlPos, &mlVel, 0, 0);
00354 ERRCHECK(result);
00355 }
00356 }
00357
00358
00360 void cSoundSystemFmod::SetListenerPosition(const float x, const float y, const float z){
00361 mlPos.x = x * mfDistanceFactor;
00362 mlPos.y = y * mfDistanceFactor;
00363 mlPos.z = z * mfDistanceFactor;
00364
00365 UpdatePositionAndVelocity();
00366 }
00367
00369 void cSoundSystemFmod::SetListenerVelocity(const float x, const float y, const float z){
00370 mlVel.x = x * mfDistanceFactor;
00371 mlVel.y = y * mfDistanceFactor;
00372 mlVel.z = z * mfDistanceFactor;
00373
00374 UpdatePositionAndVelocity();
00375 }
00376
00378 void cSoundSystemFmod::GetListenerPosition(float &x, float &y, float &z){
00379
00380 x = mlPos.x / mfDistanceFactor;
00381 y = mlPos.y / mfDistanceFactor;
00382 z = mlPos.z / mfDistanceFactor;
00383 }
00384
00386 void cSoundSystemFmod::GetListenerVelocity(float &x, float &y, float &z){
00387
00388 x = mlVel.x / mfDistanceFactor;
00389 y = mlVel.y / mfDistanceFactor;
00390 z = mlVel.z / mfDistanceFactor;
00391 }
00392
00394 void cSoundSystemFmod::SetVolume(const float volume){}
00395 const float cSoundSystemFmod::GetVolume(){return 1.0f;}
00396
00399 void cSoundSystemFmod::SetDistanceFactor(const float s){
00400
00401 for(int i = 0;i < 3;++i){
00402 mlPos.x = mlPos.x / mfDistanceFactor * s;
00403 mlPos.y = mlPos.y / mfDistanceFactor * s;
00404 mlPos.z = mlPos.z / mfDistanceFactor * s;
00405 mlVel.x = mlVel.x / mfDistanceFactor * s;
00406 mlVel.y = mlVel.y / mfDistanceFactor * s;
00407 mlVel.z = mlVel.z / mfDistanceFactor * s;
00408 }
00409
00410 mfDistanceFactor = s;
00411 }
00412 const float cSoundSystemFmod::GetDistanceFactor(){return mfDistanceFactor;}
00413
00415 cSoundSource *cSoundSystemFmod::CreateSoundSource(const char *filename){
00416 return new cSoundSourceFmod(this,filename);
00417 }
00419 cSoundSource *cSoundSystemFmod::CreateSoundSource(const char *buffer, const int size, const int channels, const int bitrate, const int frequency){
00420 return new cSoundSourceFmod(this,buffer,size,channels,bitrate,frequency);
00421 }
00422
00424 cSoundSource *cSoundSystemFmod::CreateSoundSource3D(const float x, const float y, const float z, const char *filename){
00425 return new cSoundSourceFmod(this,x,y,z,filename);
00426 }
00428 cSoundSource *cSoundSystemFmod::CreateSoundSource3D(const float x, const float y, const float z, const char *buffer, const int size, const int channels, const int bitrate, const int frequency){
00429 return new cSoundSourceFmod(this,x,y,z,buffer,size,channels,bitrate,frequency);
00430 }
00431
00433 void cSoundSystemFmod::Step(){if(mpSystem)FMOD_System_Update(mpSystem);}
00434
00435
00436
00437
00438 cSoundSystem *CreateSoundSystemFmod(const int frequency){
00439
00440 int channels = 64;
00441 return new cSoundSystemFmod(frequency,channels);
00442 }
00443
00444 };
00445 #endif