00001
00002
00003
00004
00005
00006
00007
00008 #ifdef WIN32
00009 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
00010 #endif //WIN32
00011
00012 #include "OpenALScene.h"
00013 #include "SND_SoundObject.h"
00014 #include "SND_SoundListener.h"
00015
00016 #ifdef USE_OPENAL
00017
00018 #include <AL/al.h>
00019 #include <AL/alc.h>
00020 #include <AL/alut.h>
00021 #include <stdio.h>
00022
00023 static int sound_init_ok = 0;
00024
00025
00026 static void sound_exit_trap()
00027 {
00028 if (sound_init_ok == 0) {
00029
00030 }
00031 }
00032
00033 OpenALScene::OpenALScene()
00034 {
00035 setAudio(false);
00036
00037 #if defined(WIN32) || defined (__linux__)
00038 setAudio(true);
00039 #else
00040 setAudio(false);
00041 #endif
00042 }
00043
00044 OpenALScene::~OpenALScene()
00045 {
00046 }
00047
00048 bool OpenALScene::init()
00049 {
00050 if (isAudio()) {
00051
00052 int i;
00053 unsigned int* openalsources = getSources();
00054 unsigned int* openalbuffers = getBuffers();
00055
00056 atexit(sound_exit_trap);
00057 alutInit(NULL, NULL);
00058 ALenum alc_error;
00059 alc_error = ALC_NO_ERROR;
00060
00061 if (alc_error == ALC_NO_ERROR) {
00062
00063 alGenBuffers(NUM_BUFFERS, openalbuffers);
00064 for (i = 0; i < NUM_BUFFERS; i++) {
00065
00066 m_bufferList[i] = false;
00067 if (!alIsBuffer(openalbuffers[i])) {
00068
00069 setAudio(false);
00070 }
00071 }
00072 alGenSources(NUM_SOURCES, (unsigned int*)openalsources);
00073 }
00074 else {
00075
00076 setAudio(false);
00077 }
00078
00079
00080
00081
00082
00083 for (i = 0; i < NUM_SOURCES; i++) {
00084 m_activeList[i] = false;
00085 }
00086 }
00087 return true;
00088 }
00089
00090 int OpenALScene::loadSample(const CCString& filename )
00091 {
00092 if (!isAudio())
00093 return 0;
00094 CCString samplename = filename;
00095
00096 int bufnum;
00097 void* data;
00098 unsigned int* openalbuffers = getBuffers();
00099
00100
00101 for (bufnum = 0; bufnum < NUM_BUFFERS; bufnum++) {
00102 if (m_bufferList[bufnum] == false) {
00103 m_bufferList[bufnum] = true;
00104
00105
00106 #if defined(WIN32)
00107 unsigned int size, freq;
00108 int format;
00109
00110 alutLoadWAVFile(samplename.Ptr(), &format, &data, &size, &freq);
00111 alBufferData(openalbuffers[bufnum], format, data, size, freq);
00112 alutUnloadWAV(format, data, size, freq);
00113 #else
00114 int size, freq, bits, format;
00115
00116 alutLoadWAV(samplename.Ptr(), &data, &format, &size, &bits, &freq);
00117 alBufferData(openalbuffers[bufnum], format, data, size, freq);
00118 free(data);
00119 #endif
00120 break;
00121 }
00122 }
00123 return bufnum;
00124 }
00125
00126 void OpenALScene::addObject(SND_SoundObject* object)
00127 {
00128 if (!isAudio())
00129 return;
00130
00131 std::map<CCString, int>::iterator it;
00132
00133 Objectlistdata pairdata;
00134 CCString pSample = object->getSample();
00135 int buffer;
00136 bool loaded = false;
00137
00138
00139 if (pSample != "") {
00140
00141
00142
00143 it = m_samples.find(pSample);
00144 if (it != m_samples.end() ) {
00145 buffer = (*it).second;
00146 }
00147 else {
00148
00149
00150 buffer = loadSample(pSample);
00151 m_samples.insert(std::pair<CCString, int>(pSample, buffer));
00152
00153 }
00154
00155 pairdata.buffer = buffer;
00156 pairdata.id = -1;
00157
00158 m_soundobjects.insert(std::pair<SND_SoundObject*, Objectlistdata>(object, pairdata));
00159 }
00160 }
00161
00162 void OpenALScene::ShowPlaystate()
00163 {
00164 if (!isAudio())
00165 return;
00166 #if defined(WIN32)
00167 int state;
00168 unsigned int* openalsources = getSources();
00169
00170 printf("*******************************************\n");
00171 for (int i=0; i<NUM_SOURCES; i++) {
00172 printf("-----------------\n");
00173 alGetSourcei(openalsources[i], AL_SOURCE_STATE, &state);
00174 printf("object %d state: %d\n", i, state);
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 printf("-----------------\n");
00188 }
00189 #endif
00190 }
00191
00192 void OpenALScene::UpdateListener()
00193 {
00194 if (!isAudio())
00195 return;
00196
00197 SND_SoundListener* listener = getListener();
00198 if (listener->isModified()) {
00199 MT_Point3 position = listener->getPosition();
00200 float lispos[3];
00201 lispos[0] = position[0];
00202 lispos[1] = position[1];
00203 lispos[2] = position[2];
00204 MT_Point3 velocity = listener->getVelocity();
00205 float lisvel[3];
00206 lisvel[0] = velocity[0];
00207 lisvel[1] = velocity[1];
00208 lisvel[2] = velocity[2];
00209 MT_Matrix3x3 orientation = listener->getOrientation();
00210 float lisori[6];
00211 lisori[0] = orientation[0][0];
00212 lisori[1] = orientation[0][1];
00213 lisori[2] = orientation[0][2];
00214 lisori[3] = orientation[1][0];
00215 lisori[4] = orientation[1][1];
00216 lisori[5] = orientation[1][2];
00217
00218
00219 alListenerf (AL_GAIN, listener->getGain());
00220 alListenerfv(AL_POSITION, lispos);
00221 alListenerfv(AL_VELOCITY, lisvel);
00222 alListenerfv(AL_ORIENTATION, lisori);
00223 listener->setModified(false);
00224 }
00225 }
00226
00227 int OpenALScene::getId()
00228 { int i;
00229
00230 for (i = 0; i < NUM_SOURCES; i++) {
00231 if (m_activeList[i] == false) {
00232 m_activeList[i] = true;
00233 break;
00234 }
00235 }
00236 return i;
00237 }
00238
00239 int OpenALScene::CheckActiveList(unsigned int* openalsources)
00240 {
00241 if (!isAudio())
00242 return 0;
00243
00244 std::map<SND_SoundObject*, Activelistdata>::iterator ait;
00245 std::map<SND_SoundObject*, Activelistdata>::iterator oldest;
00246
00247 int id = -1;
00248
00249
00250 if (m_activeobjects.size() >= NUM_SOURCES) {
00251
00252
00253 for (int i = 0; i < (m_activeobjects.size() - NUM_SOURCES + 1); i++) {
00254
00255
00256 ait = m_activeobjects.begin();
00257 SND_SoundObject* oldestsound = (*ait).first;
00258 double comparetime = (*ait).second.timestamp;
00259 id = (*ait).second.id;
00260
00261 while (ait != m_activeobjects.end()) {
00262 if ((*ait).second.timestamp <= comparetime) {
00263 oldestsound = (*ait).first;
00264 id = (*ait).second.id;
00265 comparetime = (*ait).second.timestamp;
00266 oldest = ait;
00267 }
00268 ait++;
00269 }
00270 oldestsound->setPlaystate(SND_STOPPED);
00271 m_activeList[id] = false;
00272 alSourceStop(openalsources[id]);
00273 m_activeobjects.erase(oldest);
00274 }
00275 }
00276 return id;
00277 }
00278
00279 void OpenALScene::BuildActiveList(double curtime)
00280 {
00281 if (!isAudio())
00282 return;
00283
00284 unsigned int* openalsources = getSources();
00285 std::map<SND_SoundObject*, Objectlistdata>::iterator it;
00286 Activelistdata pairdata;
00287
00288
00289 for (it = m_soundobjects.begin(); !(it == m_soundobjects.end()); ++it) {
00290 int activeList = SND_DO_NOTHING;
00291
00292
00293 int playstate = (*it).first->getPlaystate();
00294 int id = (*it).second.id;
00295
00296 switch (playstate) {
00297
00298
00299 case SND_MUST_PLAY:
00300
00301 activeList = SND_ADD_ACTIVE_OBJECT;
00302 break;
00303
00304
00305 case SND_PLAYING:
00306
00307 int alstate;
00308 alGetSourcei(openalsources[id], AL_SOURCE_STATE, &alstate);
00309
00310
00311
00312
00313 if (alstate == AL_PAUSED) {
00314 (*it).first->setPlaystate(SND_PAUSED);
00315 activeList = SND_REMOVE_ACTIVE_OBJECT;
00316 }
00317 else if (alstate == AL_STOPPED) {
00318 (*it).first->setPlaystate(SND_STOPPED);
00319 activeList = SND_REMOVE_ACTIVE_OBJECT;
00320 }
00321 else
00322 activeList = SND_DO_NOTHING;
00323 break;
00324
00325 case SND_MUST_STOP:
00326
00327 alSourceStop(openalsources[id]);
00328 (*it).first->setPlaystate(SND_STOPPED);
00329 activeList = SND_REMOVE_ACTIVE_OBJECT;
00330 break;
00331
00332 case SND_MUST_PAUSE:
00333
00334 alSourcePause(openalsources[id]);
00335 (*it).first->setPlaystate(SND_PAUSED);
00336 activeList = SND_REMOVE_ACTIVE_OBJECT;
00337 break;
00338
00339 default:
00340 break;
00341 }
00342
00343
00344 if (activeList == SND_ADD_ACTIVE_OBJECT) {
00345
00346
00347 if (m_activeobjects.find((*it).first) == m_activeobjects.end()) {
00348
00349 int oldId = CheckActiveList(openalsources);
00350 if (oldId == -1)
00351 pairdata.id = getId();
00352 else
00353 pairdata.id = oldId;
00354 (*it).second.id = pairdata.id;
00355 pairdata.buffer = (*it).second.buffer;
00356 pairdata.timestamp = curtime;
00357
00358 m_activeobjects.insert(std::pair<SND_SoundObject*, Activelistdata>((*it).first, pairdata));
00359 }
00360 }
00361 else if (activeList == SND_REMOVE_ACTIVE_OBJECT) {
00362
00363
00364 if (m_activeobjects.find((*it).first) != m_activeobjects.end()) {
00365 m_activeList[(*it).second.id] = false;
00366 alSourceStop(openalsources[(*it).second.id]);
00367 m_activeobjects.erase((*it).first);
00368 }
00369 }
00370 }
00371 }
00372
00373 void OpenALScene::UpdateActiveObects()
00374 {
00375 if (!isAudio())
00376 return;
00377
00378 std::map<SND_SoundObject*, Activelistdata>::iterator it;
00379 unsigned int* openalsources = getSources();
00380
00381
00382 for (it = m_activeobjects.begin(); !(it == m_activeobjects.end()); ++it) {
00383
00384
00385 if ((*it).first->isModified()) {
00386
00387
00388 (*it).first->setModified(false);
00389 int id = (*it).second.id;
00390 int objectbuffer = (*it).second.buffer;
00391 unsigned int* openalbuffers = getBuffers();
00392 MT_Point3 position = (*it).first->getPosition();
00393 float obpos[3];
00394 obpos[0] = position[0];
00395 obpos[1] = position[1];
00396 obpos[2] = position[2];
00397
00398
00399 MT_Point3 velocity = (*it).first->getVelocity();
00400 float obvel[3];
00401 obvel[0] = velocity[0];
00402 obvel[1] = velocity[1];
00403 obvel[2] = velocity[2];
00404 MT_Matrix3x3 orientation = (*it).first->getOrientation();
00405 float obori[6];
00406 obori[0] = orientation[0][0];
00407 obori[1] = orientation[0][1];
00408 obori[2] = orientation[0][2];
00409 obori[3] = orientation[1][0];
00410 obori[4] = orientation[1][1];
00411 obori[5] = orientation[1][2];
00412
00413
00414 alSourcef (openalsources[id], AL_PITCH, (*it).first->getPitch());
00415 alSourcef (openalsources[id], AL_GAIN, (*it).first->getGain());
00416 alSourcefv(openalsources[id], AL_POSITION, obpos);
00417 alSourcefv(openalsources[id], AL_VELOCITY, obvel);
00418 alSourcefv(openalsources[id], AL_ORIENTATION, obori);
00419 #ifdef AL_LOOPING
00420
00421 if ((*it).first->isLooping())
00422 alSourcei (openalsources[id], AL_LOOPING, AL_TRUE);
00423 else
00424 alSourcei (openalsources[id], AL_LOOPING, AL_FALSE);
00425 #endif //AL_LOOPING
00426
00427 if ((*it).first->getPlaystate() == SND_MUST_PLAY) {
00428 alSourcei (openalsources[id], AL_BUFFER, m_buffer[objectbuffer]);
00429 alSourcePlay (openalsources[id]);
00430 (*it).first->setPlaystate(SND_PLAYING);
00431 }
00432 }
00433 }
00434 }
00435
00436 void OpenALScene::proceed(double curtime,double deltatime)
00437 {
00438 if (isAudio()) {
00439
00440 UpdateListener();
00441 BuildActiveList(curtime);
00442 UpdateActiveObects();
00443 }
00444 }
00445
00446 void OpenALScene::removeObject(SND_SoundObject* object)
00447 {
00448 if (m_soundobjects.find(object) != m_soundobjects.end()) {
00449 m_soundobjects.erase(object);
00450 }
00451 else {
00452
00453
00454 }
00455 }
00456
00457 void OpenALScene::exit()
00458 {
00459 unsigned int* openalsources = getSources();
00460
00461 if (isAudio()) {
00462 alSourceStopv(NUM_SOURCES, openalsources);
00463 alutExit();
00464 }
00465 }
00466
00467 void OpenALScene::SetListenerPosition(const MT_Point3& pos)
00468 {
00469 getListener()->setPosition(pos);
00470 }
00471
00472 #else
00473
00474
00475
00476 OpenALScene::OpenALScene()
00477 {
00478 setAudio(false);
00479
00480 #if defined(WIN32) || defined (__linux__)
00481 setAudio(true);
00482 #else
00483 setAudio(false);
00484 #endif
00485 }
00486
00487 OpenALScene::~OpenALScene()
00488 {
00489 }
00490
00491 bool OpenALScene::init()
00492 {
00493 return true;
00494 }
00495
00496 int OpenALScene::loadSample(const CCString& filename)
00497 {
00498 return -1;
00499 }
00500
00501 void OpenALScene::addObject(SND_SoundObject* object)
00502 {
00503 }
00504
00505 void OpenALScene::ShowPlaystate()
00506 {
00507 }
00508
00509 void OpenALScene::UpdateListener()
00510 {
00511 }
00512
00513 int OpenALScene::getId()
00514 {
00515 return 0;
00516 }
00517
00518 int OpenALScene::CheckActiveList(unsigned int* openalsources)
00519 {
00520 return 0;
00521 }
00522
00523 void OpenALScene::BuildActiveList(double curtime)
00524 {
00525 }
00526
00527 void OpenALScene::UpdateActiveObects()
00528 {
00529 }
00530
00531 void OpenALScene::proceed(double curtime,double deltatime)
00532 {
00533 }
00534
00535 void OpenALScene::removeObject(SND_SoundObject* object)
00536 {
00537 }
00538
00539 void OpenALScene::exit()
00540 {
00541 }
00542
00543 void OpenALScene::SetListenerPosition(const MT_Point3& pos)
00544 {
00545 }
00546 #endif