Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

OpenALScene.cpp

Go to the documentation of this file.
00001 /*
00002  * OpenALScene.cpp

00003  *
00004  * The scene for sounds.

00005  *
00006  * Version: $Id: OpenALScene_cpp-source.html,v 1.1 2001/02/01 12:25:09 coockie Exp $

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 /* a trap to catch those who want to have audio when they're not allowed to. */
00026 static void sound_exit_trap()

00027 {
00028         if (sound_init_ok == 0) {
00029                 //printf("exit() called in OpenAL library. Please restart blender with -noaudio option.\n");
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;// = alcGetError();
00059                 alc_error = ALC_NO_ERROR;
00060                 // let openal generate its buffers & sources
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                                         //printf("\n\n  WARNING: OpenAL returned with an error. Continuing without audio.\n\n");
00069                                         setAudio(false);
00070                                 }
00071                         }
00072                         alGenSources(NUM_SOURCES, (unsigned int*)openalsources);
00073                 }
00074                 else {
00075                         //printf("\n\n  WARNING: OpenAL returned with an error. Continuing without audio.\n\n");
00076                         setAudio(false);
00077                 }
00078                 
00079                 // create a listener ( = the camera in audioland)
00080                 //SND_SoundListener* sndlistener = new SND_SoundListener();
00081                 //setListener(sndlistener);
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         // search for an unused buffer
00101         for (bufnum = 0; bufnum < NUM_BUFFERS; bufnum++) {
00102                 if (m_bufferList[bufnum] == false) {
00103                         m_bufferList[bufnum] = true;
00104                         
00105                         // and fill it with sample data
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         // don't add the object if no valid sample is referenced
00139         if (pSample != "") {
00140 
00141                 // check if the sample is already loaded
00142 
00143                 it = m_samples.find(pSample);
00144                 if (it != m_samples.end() ) {
00145                         buffer = (*it).second;
00146                 } 
00147                 else {
00148         
00149                         // if the sample is not loaded, make it so!
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                 // add the object to the list
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                 //      alGetSourcei(openalsources[i], AL_LOOPING, &state);
00176                 //      printf("object %d loop: %d\n", i, state);
00177                 //      alGetSourcei(openalsources[i], AL_STREAMING, &state);
00178                 //      printf("object %d streaming: %d\n", i, state);
00179                 //      alGetSourcei(openalsources[i], AL_BUFFER, &state);
00180                 //      printf("object %d buffer: %d\n", i, state);
00181                 //      alGetSourcei(openalsources[i], AL_LOOP_COUNT, &state);
00182                 //      printf("object %d loop_count: %d\n", i, state);
00183                 //      alGetSourcei(openalsources[i], AL_BUFFERS_QUEUED, &state);
00184                 //      printf("object %d buffers_queued: %d\n", i, state);
00185                 //      alGetSourcei(openalsources[i], AL_BUFFERS_USED, &state);
00186                 //      printf("object %d buffers_used: %d\n", i, state);
00187                 printf("-----------------\n");
00188         }
00189 #endif  
00190 }
00191 
00192 void OpenALScene::UpdateListener()

00193 {
00194         if (!isAudio())
00195                 return;
00196         // process the listener if modified
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                 // tell openal how we want our listener
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         // first check how many sounds want to be playing
00250         if (m_activeobjects.size() >= NUM_SOURCES) {
00251                 
00252                 // too many, so lets dump the oldest ones!
00253                 for (int i = 0; i < (m_activeobjects.size() - NUM_SOURCES + 1); i++) {
00254                         
00255                         //remove the sound with the oldest timestamp from the list
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         // update only the objects that need to be updated
00289         for (it = m_soundobjects.begin(); !(it == m_soundobjects.end()); ++it) {
00290                 int activeList = SND_DO_NOTHING;
00291                 
00292                 // lets see if the object is playing or not
00293                 int playstate = (*it).first->getPlaystate();
00294                 int id = (*it).second.id;
00295                 
00296                 switch (playstate) {
00297 
00298                         // only add sounds to the list that must play
00299                 case SND_MUST_PLAY:
00300 
00301                         activeList = SND_ADD_ACTIVE_OBJECT;
00302                         break;
00303 
00304                         // if it should be playing, check it with openal
00305                 case SND_PLAYING:
00306                         
00307                         int alstate;
00308                         alGetSourcei(openalsources[id], AL_SOURCE_STATE, &alstate);
00309         //              printf("%d, alstate: %d\n", counter, alstate);
00310         //              counter++;
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                 // if active put the object on the list
00344                 if (activeList == SND_ADD_ACTIVE_OBJECT) {
00345                         
00346                         // first check if the object is already on the list
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                         // if inactive, remove it from the list
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         // update only the objects that need to be updated
00382         for (it = m_activeobjects.begin(); !(it == m_activeobjects.end()); ++it) {
00383                 
00384                 // only update modified objects
00385                 if ((*it).first->isModified()) {
00386                         
00387                         // set and get some info
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                         //printf("x: %f, y: %f, z: %f\n", obpos[0], obpos[1], obpos[2]);
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                         // update the situation
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                         // ok, properties set. now see if it must play
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                 }       // modified check
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                 // tried to remove an object that is not in the scene
00453                 //assert(false);
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  /* USE_OPENAL */
00473  
00474 // create stubbs
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  /* USE_OPENAL */

Generated at Thu Feb 1 13:03:08 2001 for Ketsji Game Engine by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000