Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 7460 in orxonox.OLD for trunk/src/lib


Ignore:
Timestamp:
May 1, 2006, 12:30:34 AM (19 years ago)
Author:
bensch
Message:

orxonox/trunk: Namespaces for sound

Location:
trunk/src/lib
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/sound/ogg_player.cc

    r7314 r7460  
    3232#include "debug.h"
    3333
    34 /**
    35  * initializes an Ogg-player from a file
    36  * @param fileName the file to load
    37  */
    38 OggPlayer::OggPlayer(const std::string& fileName)
     34namespace OrxSound
    3935{
    40   this->setClassID(CL_SOUND_OGG_PLAYER, "OggPlayer");
    41 
    42   this->state = OggPlayer::None;
    43 
    44   this->source = 0;
    45   this->buffers[0] = 0;
    46   this->buffers[1] = 0;
    47   this->musicThreadID = NULL;
    48   this->musicMutex = SDL_CreateMutex();
    49 
    50   if (!fileName.empty())
    51   {
    52     if (this->open(fileName))
    53       this->setName(fileName);
    54   }
    55 
    56 }
    57 
    58 /**
    59  * @brief deletes the OggPlayer
    60  */
    61 OggPlayer::~OggPlayer()
    62 {
    63   this->release();
    64   SDL_DestroyMutex(this->musicMutex);
    65 }
    66 
    67 ///////////////
    68 // INTERFACE //
    69 ///////////////
    70 /**
    71  * @brief opens a file for playback
    72  * @param fileName the file to open
    73  */
    74 bool OggPlayer::open(const std::string& fileName)
    75 {
    76   MutexLock(this->musicMutex);
    77   // release old Ogg-File (if loaded)
    78   if (this->state & OggPlayer::FileOpened)
    79     this->release();
    80 
    81   // allocating Buffers
    82   if (this->buffers[0] == 0)
    83     alGenBuffers(2, this->buffers);
    84   SoundEngine::checkError("Allocating Buffers", __LINE__);
    85   if (this->buffers[0] != 0 && this->buffers[1] != 0)
    86     state |= OggPlayer::BuffersAllocated;
    87   else
    88   {
    89     PRINTF(2)("Unable to allocate al-Buffers\n");
    90     this->release();
    91     return false;
    92   }
    93   // allocating source
    94   if (this->source == 0)
    95     SoundEngine::getInstance()->popALSource(this->source);
    96   if (this->source != 0)
    97     state |= OggPlayer::SourceAllocated;
    98   else
    99   {
    100     PRINTF(2)("No more Sources Availiable (maybe you should consider raising the source-count.)\n");
    101     this->release();
    102     return false;
    103   }
    104 
    105   // opening the FILE;
    106   int result;
    107   if(!(oggFile = fopen(fileName.c_str(), "rb")))
    108   {
    109     PRINTF(2)("Could not open Ogg file.");
    110     this->release();
    111     return false;
    112   }
    113   // reading the Stream.
    114   if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
    115   {
    116     PRINTF(2)("Could not open Ogg stream. %s", getVorbisError(result));
    117     fclose(oggFile);
    118     this->release();
    119     return false;
    120   }
    121   this->state |= OggPlayer::FileOpened;
    122 
    123   // acquiring the vorbis-properties.
    124   vorbisInfo = ov_info(&oggStream, -1);
    125   vorbisComment = ov_comment(&oggStream, -1);
    126 
    127   if(vorbisInfo->channels == 1)
    128     format = AL_FORMAT_MONO16;
    129   else
    130     format = AL_FORMAT_STEREO16;
    131 
    132   // setting the Source Properties.
    133   alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
    134   alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
    135   alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
    136   alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
    137   alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
    138   alSourcef (source, AL_GAIN,            SoundEngine::getInstance()->getMusicVolume());
    139   SoundEngine::checkError("OggPlayer::open()::SetSourceProperties", __LINE__);
    140 
    141   // Set to State Stopped
    142   this->state |= OggPlayer::Stopped;
    143   return true;
    144 }
    145 
    146 
    147 /**
    148  * @brief start Playing Music.
    149  * @returns true on success false otherwise.
    150  */
    151 bool OggPlayer::play()
    152 {
    153   if (!(this->state & OggPlayer::FileOpened))
    154     return false;
    155 
    156   this->state &= ~(OggPlayer::Stopped | OggPlayer::Paused);
    157 
    158   if (!this->playback())
    159     return false;
    160 
    161   if (this->musicThreadID == NULL)
    162     return ((this->musicThreadID = SDL_CreateThread(OggPlayer::musicThread, (void*)this)) != NULL);
    163   return true;
    164 }
    165 
    166 /**
    167  * @brief stop the OggPlayer from Playing.
    168  */
    169 void OggPlayer::stop()
    170 {
    171   this->state &= ~(OggPlayer::Playing | OggPlayer::Paused);
    172   this->state |= OggPlayer::Stopped;
    173 
    174   this->suspend();
    175   this->rewind();
    176 }
    177 
    178 /**
    179  * @brief Pause the Playing.
    180  */
    181 void OggPlayer::pause()
    182 {
    183   this->state &= ~OggPlayer::Playing;
    184 
    185   if (!(this->state & OggPlayer::Stopped))
    186     this->state |= OggPlayer::Paused;
    187 
    188   this->suspend();
    189 }
    190 
    191 /**
    192  * @brief rewind to the beginning, and play (if already playing)
    193  */
    194 void OggPlayer::rewind()
    195 {
    196   this->jumpTo(0.0f);
    197 }
    198 
    199 /**
    200  * @brief jump to Second timeCode in the MusicFile
    201  * @param timeCode where to jump to.
    202  */
    203 void OggPlayer::jumpTo(float timeCode)
    204 {
    205 
    206   if (this->state & OggPlayer::FileOpened)
    207   {
    208     SDL_mutexP(this->musicMutex);
    209     ov_time_seek(&this->oggStream, timeCode);
    210     SDL_mutexV(this->musicMutex);
    211   }
    212 }
    213 
    214 /**
    215  * @returns the Length of the Music in Seconds
    216  */
    217 float OggPlayer::length()
    218 {
    219   if (this->state & OggPlayer::FileOpened)
    220     return ov_time_total(&this->oggStream, -1);
    221   else
    222     return 0.0f;
    223 }
    224 
    225 
    226 /**
    227  * @returns true if the file is playing
    228  */
    229 bool OggPlayer::isPlaying()
    230 {
    231   if (!(this->state & OggPlayer::FileOpened))
    232     return false;
    233   ALenum state;
    234 
    235   alGetSourcei(this->source, AL_SOURCE_STATE, &state);
    236 
    237   return (state == AL_PLAYING);
    238 }
    239 
    240 
    241 
    242 ////////////////////////
    243 // INTERNAL FUNCTIONS //
    244 ////////////////////////
    245 /**
    246  * @brief creates a Thread for Playing back the music even if the rest of the Engine is slow
    247  * @param oggPlayer the OggPlayer to play back
    248  * @returns -1 on error.
    249  */
    250 int OggPlayer::musicThread(void* oggPlayer)
    251 {
    252   if (oggPlayer == NULL)
    253     return -1;
    254   OggPlayer* ogg = (OggPlayer*)oggPlayer;
    255 
    256   PRINTF(4)("STARTIG AUDIO THREAD\n");
    257   while (ogg->state & OggPlayer::Playing)
    258   {
    259     SDL_mutexP(ogg->musicMutex);
    260     ogg->update();
    261     SDL_mutexV(ogg->musicMutex);
    262     SDL_Delay(1);
    263   }
    264   PRINTF(4)("End the AudioThread\n");
    265 }
    266 
    267 
    268 /**
    269  * @brief plays back the sound
    270  * @return true if running, false otherwise
    271  */
    272 bool OggPlayer::playback()
    273 {
    274   if (!(this->state & OggPlayer::FileOpened))
    275     return false;
    276 
    277   if(this->state & OggPlayer::Playing)
    278     return true;
    279   this->state |= OggPlayer::Playing;
    280 
    281   SDL_mutexP(this->musicMutex);
    282   if(!this->stream(this->buffers[0]) || !this->stream(this->buffers[1]))
    283   {
    284     SDL_mutexV(this->musicMutex);
    285     this->state &= ~OggPlayer::Playing;
    286     return false;
    287   }
    288 
    289   alSourceQueueBuffers(this->source, 2, this->buffers);
    290   if (DEBUG >= 3)
    291     SoundEngine::checkError("OggPlayer::playback()::alSourceQueueBuffers", __LINE__);
    292 
    293   alSourcePlay(this->source);
    294   if (DEBUG >= 3)
    295     SoundEngine::checkError("OggPlayer::playback()::alSourcePlay", __LINE__);
    296   SDL_mutexV(this->musicMutex);
    297   return true;
    298 }
    299 
    300 
    301 /**
    302  * @brief waits for the AudioThread to be finished.
    303  */
    304 void OggPlayer::suspend()
    305 {
    306   if (this->musicThreadID != NULL)
    307   {
    308     assert (!(this->state & Playing));
    309     SDL_WaitThread(this->musicThreadID, NULL);
    310     this->musicThreadID = NULL;
    311   }
    312   if (this->state & OggPlayer::SourceAllocated)
    313   {
    314     alSourceStop(this->source);
    315     alSourcei(this->source, AL_BUFFER, 0);
    316   }
    317 }
    318 
    319 /**
    320  * @brief updates the stream, this has to be done every few parts of a second, for sound-consistency
    321  * @returns true, if the Sound is playing flawlessly
    322  */
    323 bool OggPlayer::update()
    324 {
    325   int processed = 0;
    326   bool active = true;
    327 
    328   alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
    329   if (DEBUG >= 3)
    330     SoundEngine::checkError("OggPlayer::update()::alGetSourceI", __LINE__);
    331 
    332   while(processed--)
    333   {
    334     ALuint buffer;
    335 
    336     alSourceUnqueueBuffers(source, 1, &buffer);
    337     if (DEBUG >= 3)
    338       SoundEngine::checkError("OggPlayer::update()::unqueue", __LINE__);
    339 
    340     active = stream(buffer);
    341 
    342     alSourceQueueBuffers(source, 1, &buffer);
    343     if (DEBUG >= 3)
    344       SoundEngine::checkError("OggPlayer::update()::queue", __LINE__);
    345   }
    346 
    347   return active;
    348 }
    349 
    350 /**
    351  * @brief gets a new Stream from buffer
    352  * @param buffer the buffer to get the stream from
    353  * @return true, if everything worked as planed
    354  */
    355 bool OggPlayer::stream(ALuint buffer)
    356 {
    357   if (unlikely(!(this->state & Playing)))
    358     return false;
    359   char pcm[OGG_PLAYER_BUFFER_SIZE];
    360   int  size = 0;
    361   int  section;
    362   int  result;
    363 
    364   while(size < OGG_PLAYER_BUFFER_SIZE)
    365   {
    366     result = ov_read(&this->oggStream, pcm + size, OGG_PLAYER_BUFFER_SIZE - size, 0, 2, 1, &section);
    367 
    368     if(result > 0)
    369       size += result;
    370     else if(result < 0)
    371       throw getVorbisError(result);
    372     else /* eof */
    373       ov_time_seek(&this->oggStream, 0.0);
    374   }
    375 
    376   if(size == 0)
    377     return false;
    378 
    379   alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
    380   if (DEBUG >= 3)
    381     SoundEngine::checkError("OggPlayer::stream()::BUFFER", __LINE__);
    382 
    383   return true;
    384 }
    385 
    386 
    387 /**
    388  * @brief releases a stream
    389  */
    390 void OggPlayer::release()
    391 {
    392   if (this->state & OggPlayer::SourceAllocated)
    393   {
    394     assert(alIsSource(this->source));
    395     if (this->state & OggPlayer::Playing);
    396     {
    397       // Kill the Music Thread.
    398       this->state &= ~OggPlayer::Playing;
    399       this->suspend();
    400 
    401       SoundEngine::checkError("OggPlayer::release()::alSourceStop", __LINE__);
    402     }
    403     empty();
    404     alSourcei(this->source, AL_BUFFER, 0);
    405     SoundEngine::getInstance()->pushALSource(this->source);
     36  /**
     37   * initializes an Ogg-player from a file
     38   * @param fileName the file to load
     39   */
     40  OggPlayer::OggPlayer(const std::string& fileName)
     41  {
     42    this->setClassID(CL_SOUND_OGG_PLAYER, "OggPlayer");
     43
     44    this->state = OggPlayer::None;
     45
    40646    this->source = 0;
    407     this->state &= ~SourceAllocated;
    408   }
    409   if (this->state & OggPlayer::BuffersAllocated)
    410   {
    411     assert (this->buffers[0] != 0 && this->buffers[1] != 0);
    412     alDeleteBuffers(2, buffers);
    413     SoundEngine::checkError("OggPlayer::release()::alDeleteBuffers", __LINE__);
    41447    this->buffers[0] = 0;
    41548    this->buffers[1] = 0;
    416     this->state &= ~OggPlayer::BuffersAllocated;
    417   }
    418 
    419   if (this->state & OggPlayer::FileOpened)
    420   {
    421     ov_clear(&oggStream);
    422     this->state &= ~OggPlayer::FileOpened;
    423   }
    424 
    425 }
    426 
    427 
    428 /**
    429  * @brief empties the buffers
    430  */
    431 void OggPlayer::empty()
    432 {
    433   int queued;
    434 
    435   alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
    436 
    437   while(queued--)
    438   {
    439     ALuint buffer;
    440 
    441     alSourceUnqueueBuffers(source, 1, &buffer);
    442     SoundEngine::checkError("OggPlayer::empty()::unqueue Buffers", __LINE__);
    443   }
    444 }
    445 
    446 
    447 /////////////////////
    448 // DEBUG FUNCTIONS //
    449 /////////////////////
    450 /**
    451  * displays some info about the ogg-file
    452  */
    453 void OggPlayer::debug() const
    454 {
    455   cout
    456   << "version         " << vorbisInfo->version         << "\n"
    457   << "channels        " << vorbisInfo->channels        << "\n"
    458   << "rate (hz)       " << vorbisInfo->rate            << "\n"
    459   << "bitrate upper   " << vorbisInfo->bitrate_upper   << "\n"
    460   << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n"
    461   << "bitrate lower   " << vorbisInfo->bitrate_lower   << "\n"
    462   << "bitrate window  " << vorbisInfo->bitrate_window  << "\n"
    463   << "\n"
    464   << "vendor " << vorbisComment->vendor << "\n";
    465 
    466   for(int i = 0; i < vorbisComment->comments; i++)
    467     cout << "   " << vorbisComment->user_comments[i] << "\n";
    468 
    469   cout << endl;
    470 }
    471 
    472 
    473 void OggPlayer::printState() const
    474 {
    475   PRINTF(0)("OggPlayer is in the following States: ");
    476   if (this->state & OggPlayer::FileOpened)
    477     PRINT(0)("FileOpened ");
    478   if (this->state & OggPlayer::SourceAllocated)
    479     PRINT(0)("SourceAllocated ");
    480   if (this->state & OggPlayer::BuffersAllocated)
    481     PRINT(0)("BuffersAllocated ");
    482   if (this->state & OggPlayer::Stopped)
    483     PRINT(0)("Stopped ");
    484   if (this->state & OggPlayer::Playing)
    485     PRINT(0)("Playing ");
    486   if (this->state & OggPlayer::Paused)
    487     PRINT(0)("Paused ");
    488   if (this->state & OggPlayer::Error)
    489     PRINT(0)("Error ");
    490   PRINT(0)("\n");
    491 }
    492 
    493 /**
    494  * returns errors
    495  * @param code the error-code
    496  * @return the error as a String
    497  */
    498 const char* OggPlayer::getVorbisError(int code)
    499 {
    500   switch(code)
    501   {
     49    this->musicThreadID = NULL;
     50    this->musicMutex = SDL_CreateMutex();
     51
     52    if (!fileName.empty())
     53    {
     54      if (this->open(fileName))
     55        this->setName(fileName);
     56    }
     57
     58  }
     59
     60  /**
     61   * @brief deletes the OggPlayer
     62   */
     63  OggPlayer::~OggPlayer()
     64  {
     65    this->release();
     66    SDL_DestroyMutex(this->musicMutex);
     67  }
     68
     69  ///////////////
     70  // INTERFACE //
     71  ///////////////
     72  /**
     73   * @brief opens a file for playback
     74   * @param fileName the file to open
     75   */
     76  bool OggPlayer::open(const std::string& fileName)
     77  {
     78    MutexLock(this->musicMutex);
     79    // release old Ogg-File (if loaded)
     80    if (this->state & OggPlayer::FileOpened)
     81      this->release();
     82
     83    // allocating Buffers
     84    if (this->buffers[0] == 0)
     85      alGenBuffers(2, this->buffers);
     86    SoundEngine::checkError("Allocating Buffers", __LINE__);
     87    if (this->buffers[0] != 0 && this->buffers[1] != 0)
     88      state |= OggPlayer::BuffersAllocated;
     89    else
     90    {
     91      PRINTF(2)("Unable to allocate al-Buffers\n");
     92      this->release();
     93      return false;
     94    }
     95    // allocating source
     96    if (this->source == 0)
     97      SoundEngine::getInstance()->popALSource(this->source);
     98    if (this->source != 0)
     99      state |= OggPlayer::SourceAllocated;
     100    else
     101    {
     102      PRINTF(2)("No more Sources Availiable (maybe you should consider raising the source-count.)\n");
     103      this->release();
     104      return false;
     105    }
     106
     107    // opening the FILE;
     108    int result;
     109    if(!(oggFile = fopen(fileName.c_str(), "rb")))
     110    {
     111      PRINTF(2)("Could not open Ogg file.");
     112      this->release();
     113      return false;
     114    }
     115    // reading the Stream.
     116    if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
     117    {
     118      PRINTF(2)("Could not open Ogg stream. %s", getVorbisError(result));
     119      fclose(oggFile);
     120      this->release();
     121      return false;
     122    }
     123    this->state |= OggPlayer::FileOpened;
     124
     125    // acquiring the vorbis-properties.
     126    vorbisInfo = ov_info(&oggStream, -1);
     127    vorbisComment = ov_comment(&oggStream, -1);
     128
     129    if(vorbisInfo->channels == 1)
     130      format = AL_FORMAT_MONO16;
     131    else
     132      format = AL_FORMAT_STEREO16;
     133
     134    // setting the Source Properties.
     135    alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
     136    alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
     137    alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
     138    alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
     139    alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
     140    alSourcef (source, AL_GAIN,            SoundEngine::getInstance()->getMusicVolume());
     141    SoundEngine::checkError("OggPlayer::open()::SetSourceProperties", __LINE__);
     142
     143    // Set to State Stopped
     144    this->state |= OggPlayer::Stopped;
     145    return true;
     146  }
     147
     148
     149  /**
     150   * @brief start Playing Music.
     151   * @returns true on success false otherwise.
     152   */
     153  bool OggPlayer::play()
     154  {
     155    if (!(this->state & OggPlayer::FileOpened))
     156      return false;
     157
     158    this->state &= ~(OggPlayer::Stopped | OggPlayer::Paused);
     159
     160    if (!this->playback())
     161      return false;
     162
     163    if (this->musicThreadID == NULL)
     164      return ((this->musicThreadID = SDL_CreateThread(OggPlayer::musicThread, (void*)this)) != NULL);
     165    return true;
     166  }
     167
     168  /**
     169   * @brief stop the OggPlayer from Playing.
     170   */
     171  void OggPlayer::stop()
     172  {
     173    this->state &= ~(OggPlayer::Playing | OggPlayer::Paused);
     174    this->state |= OggPlayer::Stopped;
     175
     176    this->suspend();
     177    this->rewind();
     178  }
     179
     180  /**
     181   * @brief Pause the Playing.
     182   */
     183  void OggPlayer::pause()
     184  {
     185    this->state &= ~OggPlayer::Playing;
     186
     187    if (!(this->state & OggPlayer::Stopped))
     188      this->state |= OggPlayer::Paused;
     189
     190    this->suspend();
     191  }
     192
     193  /**
     194   * @brief rewind to the beginning, and play (if already playing)
     195   */
     196  void OggPlayer::rewind()
     197  {
     198    this->jumpTo(0.0f);
     199  }
     200
     201  /**
     202   * @brief jump to Second timeCode in the MusicFile
     203   * @param timeCode where to jump to.
     204   */
     205  void OggPlayer::jumpTo(float timeCode)
     206  {
     207
     208    if (this->state & OggPlayer::FileOpened)
     209    {
     210      SDL_mutexP(this->musicMutex);
     211      ov_time_seek(&this->oggStream, timeCode);
     212      SDL_mutexV(this->musicMutex);
     213    }
     214  }
     215
     216  /**
     217   * @returns the Length of the Music in Seconds
     218   */
     219  float OggPlayer::length()
     220  {
     221    if (this->state & OggPlayer::FileOpened)
     222      return ov_time_total(&this->oggStream, -1);
     223    else
     224      return 0.0f;
     225  }
     226
     227
     228  /**
     229   * @returns true if the file is playing
     230   */
     231  bool OggPlayer::isPlaying()
     232  {
     233    if (!(this->state & OggPlayer::FileOpened))
     234      return false;
     235    ALenum state;
     236
     237    alGetSourcei(this->source, AL_SOURCE_STATE, &state);
     238
     239    return (state == AL_PLAYING);
     240  }
     241
     242
     243
     244  ////////////////////////
     245  // INTERNAL FUNCTIONS //
     246  ////////////////////////
     247  /**
     248   * @brief creates a Thread for Playing back the music even if the rest of the Engine is slow
     249   * @param oggPlayer the OggPlayer to play back
     250   * @returns -1 on error.
     251   */
     252  int OggPlayer::musicThread(void* oggPlayer)
     253  {
     254    if (oggPlayer == NULL)
     255      return -1;
     256    OggPlayer* ogg = (OggPlayer*)oggPlayer;
     257
     258    PRINTF(4)("STARTIG AUDIO THREAD\n");
     259    while (ogg->state & OggPlayer::Playing)
     260    {
     261      SDL_mutexP(ogg->musicMutex);
     262      ogg->update();
     263      SDL_mutexV(ogg->musicMutex);
     264      SDL_Delay(1);
     265    }
     266    PRINTF(4)("End the AudioThread\n");
     267  }
     268
     269
     270  /**
     271   * @brief plays back the sound
     272   * @return true if running, false otherwise
     273   */
     274  bool OggPlayer::playback()
     275  {
     276    if (!(this->state & OggPlayer::FileOpened))
     277      return false;
     278
     279    if(this->state & OggPlayer::Playing)
     280      return true;
     281    this->state |= OggPlayer::Playing;
     282
     283    SDL_mutexP(this->musicMutex);
     284    if(!this->stream(this->buffers[0]) || !this->stream(this->buffers[1]))
     285    {
     286      SDL_mutexV(this->musicMutex);
     287      this->state &= ~OggPlayer::Playing;
     288      return false;
     289    }
     290
     291    alSourceQueueBuffers(this->source, 2, this->buffers);
     292    if (DEBUG >= 3)
     293      SoundEngine::checkError("OggPlayer::playback()::alSourceQueueBuffers", __LINE__);
     294
     295    alSourcePlay(this->source);
     296    if (DEBUG >= 3)
     297      SoundEngine::checkError("OggPlayer::playback()::alSourcePlay", __LINE__);
     298    SDL_mutexV(this->musicMutex);
     299    return true;
     300  }
     301
     302
     303  /**
     304   * @brief waits for the AudioThread to be finished.
     305   */
     306  void OggPlayer::suspend()
     307  {
     308    if (this->musicThreadID != NULL)
     309    {
     310      assert (!(this->state & Playing));
     311      SDL_WaitThread(this->musicThreadID, NULL);
     312      this->musicThreadID = NULL;
     313    }
     314    if (this->state & OggPlayer::SourceAllocated)
     315    {
     316      alSourceStop(this->source);
     317      alSourcei(this->source, AL_BUFFER, 0);
     318    }
     319  }
     320
     321  /**
     322   * @brief updates the stream, this has to be done every few parts of a second, for sound-consistency
     323   * @returns true, if the Sound is playing flawlessly
     324   */
     325  bool OggPlayer::update()
     326  {
     327    int processed = 0;
     328    bool active = true;
     329
     330    alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
     331    if (DEBUG >= 3)
     332      SoundEngine::checkError("OggPlayer::update()::alGetSourceI", __LINE__);
     333
     334    while(processed--)
     335    {
     336      ALuint buffer;
     337
     338      alSourceUnqueueBuffers(source, 1, &buffer);
     339      if (DEBUG >= 3)
     340        SoundEngine::checkError("OggPlayer::update()::unqueue", __LINE__);
     341
     342      active = stream(buffer);
     343
     344      alSourceQueueBuffers(source, 1, &buffer);
     345      if (DEBUG >= 3)
     346        SoundEngine::checkError("OggPlayer::update()::queue", __LINE__);
     347    }
     348
     349    return active;
     350  }
     351
     352  /**
     353   * @brief gets a new Stream from buffer
     354   * @param buffer the buffer to get the stream from
     355   * @return true, if everything worked as planed
     356   */
     357  bool OggPlayer::stream(ALuint buffer)
     358  {
     359    if (unlikely(!(this->state & Playing)))
     360      return false;
     361    char pcm[OGG_PLAYER_BUFFER_SIZE];
     362    int  size = 0;
     363    int  section;
     364    int  result;
     365
     366    while(size < OGG_PLAYER_BUFFER_SIZE)
     367    {
     368      result = ov_read(&this->oggStream, pcm + size, OGG_PLAYER_BUFFER_SIZE - size, 0, 2, 1, &section);
     369
     370      if(result > 0)
     371        size += result;
     372      else if(result < 0)
     373        throw getVorbisError(result);
     374      else /* eof */
     375        ov_time_seek(&this->oggStream, 0.0);
     376    }
     377
     378    if(size == 0)
     379      return false;
     380
     381    alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
     382    if (DEBUG >= 3)
     383      SoundEngine::checkError("OggPlayer::stream()::BUFFER", __LINE__);
     384
     385    return true;
     386  }
     387
     388
     389  /**
     390   * @brief releases a stream
     391   */
     392  void OggPlayer::release()
     393  {
     394    if (this->state & OggPlayer::SourceAllocated)
     395    {
     396      assert(alIsSource(this->source));
     397      if (this->state & OggPlayer::Playing);
     398      {
     399        // Kill the Music Thread.
     400        this->state &= ~OggPlayer::Playing;
     401        this->suspend();
     402
     403        SoundEngine::checkError("OggPlayer::release()::alSourceStop", __LINE__);
     404      }
     405      empty();
     406      alSourcei(this->source, AL_BUFFER, 0);
     407      SoundEngine::getInstance()->pushALSource(this->source);
     408      this->source = 0;
     409      this->state &= ~SourceAllocated;
     410    }
     411    if (this->state & OggPlayer::BuffersAllocated)
     412    {
     413      assert (this->buffers[0] != 0 && this->buffers[1] != 0);
     414      alDeleteBuffers(2, buffers);
     415      SoundEngine::checkError("OggPlayer::release()::alDeleteBuffers", __LINE__);
     416      this->buffers[0] = 0;
     417      this->buffers[1] = 0;
     418      this->state &= ~OggPlayer::BuffersAllocated;
     419    }
     420
     421    if (this->state & OggPlayer::FileOpened)
     422    {
     423      ov_clear(&oggStream);
     424      this->state &= ~OggPlayer::FileOpened;
     425    }
     426
     427  }
     428
     429
     430  /**
     431   * @brief empties the buffers
     432   */
     433  void OggPlayer::empty()
     434  {
     435    int queued;
     436
     437    alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
     438
     439    while(queued--)
     440    {
     441      ALuint buffer;
     442
     443      alSourceUnqueueBuffers(source, 1, &buffer);
     444      SoundEngine::checkError("OggPlayer::empty()::unqueue Buffers", __LINE__);
     445    }
     446  }
     447
     448
     449  /////////////////////
     450  // DEBUG FUNCTIONS //
     451  /////////////////////
     452  /**
     453   * displays some info about the ogg-file
     454   */
     455  void OggPlayer::debug() const
     456  {
     457    std::cout
     458    << "version         " << vorbisInfo->version         << "\n"
     459    << "channels        " << vorbisInfo->channels        << "\n"
     460    << "rate (hz)       " << vorbisInfo->rate            << "\n"
     461    << "bitrate upper   " << vorbisInfo->bitrate_upper   << "\n"
     462    << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n"
     463    << "bitrate lower   " << vorbisInfo->bitrate_lower   << "\n"
     464    << "bitrate window  " << vorbisInfo->bitrate_window  << "\n"
     465    << "\n"
     466    << "vendor " << vorbisComment->vendor << "\n";
     467
     468    for(int i = 0; i < vorbisComment->comments; i++)
     469      std::cout << "   " << vorbisComment->user_comments[i] << "\n";
     470
     471    std::cout << std::endl;
     472  }
     473
     474
     475  void OggPlayer::printState() const
     476  {
     477    PRINTF(0)("OggPlayer is in the following States: ");
     478    if (this->state & OggPlayer::FileOpened)
     479      PRINT(0)("FileOpened ");
     480    if (this->state & OggPlayer::SourceAllocated)
     481      PRINT(0)("SourceAllocated ");
     482    if (this->state & OggPlayer::BuffersAllocated)
     483      PRINT(0)("BuffersAllocated ");
     484    if (this->state & OggPlayer::Stopped)
     485      PRINT(0)("Stopped ");
     486    if (this->state & OggPlayer::Playing)
     487      PRINT(0)("Playing ");
     488    if (this->state & OggPlayer::Paused)
     489      PRINT(0)("Paused ");
     490    if (this->state & OggPlayer::Error)
     491      PRINT(0)("Error ");
     492    PRINT(0)("\n");
     493  }
     494
     495  /**
     496   * returns errors
     497   * @param code the error-code
     498   * @return the error as a String
     499   */
     500  const char* OggPlayer::getVorbisError(int code)
     501  {
     502    switch(code)
     503    {
    502504    case OV_EREAD:
    503505      return ("Read from media.");
     
    512514    default:
    513515      return ("Unknown Ogg error.");
    514   }
     516    }
     517  }
     518
    515519}
    516 
  • trunk/src/lib/sound/ogg_player.h

    r7331 r7460  
    77#ifndef _OGG_PLAYER_H
    88#define _OGG_PLAYER_H
    9 
    10 using namespace std;
    119
    1210#include "base_object.h"
     
    2220#define OGG_PLAYER_BUFFER_SIZE (8096 * 2)
    2321
     22namespace OrxSound
     23{
     24  // the definition of a Ogg-Player
     25  class OggPlayer : public BaseObject
     26  {
     27  public:
     28    /**
     29     * An enumerator defining in what State the OggPlayer is.
     30     * The OggPlayer can be in multiple States listed here.
     31     * It can as an example be in FileOpened and Stopped.
     32     */
     33    typedef enum {
     34      None                   = 0x000,   //!< Initialized
     35      FileOpened             = 0x100,   //!< File is Opened
     36      SourceAllocated        = 0x200,   //!< Source is Allocated.
     37      BuffersAllocated       = 0x400,   //!< 2 Buffers are Allocated.
     38      Stopped                = 0x010,   //!< OggPlayer is stopped.
     39      Playing                = 0x020,   //!< OggPlayer is Playing.
     40      Paused                 = 0x040,   //!< OggPlayer is Paused.
     41      Error                  = 0x001,   //!< An Error has occured.
     42    } State;
    2443
    25 // the definition of a Ogg-Player
    26 class OggPlayer : public BaseObject
    27 {
    28 public:
    29   /**
    30    * An enumerator defining in what State the OggPlayer is.
    31    * The OggPlayer can be in multiple States listed here.
    32    * It can as an example be in FileOpened and Stopped.
    33    */
    34   typedef enum {
    35     None                   = 0x000,   //!< Initialized
    36     FileOpened             = 0x100,   //!< File is Opened
    37     SourceAllocated        = 0x200,   //!< Source is Allocated.
    38     BuffersAllocated       = 0x400,   //!< 2 Buffers are Allocated.
    39     Stopped                = 0x010,   //!< OggPlayer is stopped.
    40     Playing                = 0x020,   //!< OggPlayer is Playing.
    41     Paused                 = 0x040,   //!< OggPlayer is Paused.
    42     Error                  = 0x001,   //!< An Error has occured.
    43   } State;
     44    OggPlayer(const std::string& fileName = "");
     45    virtual ~OggPlayer();
     46    /** @param state compare this State with the internal State @returns true on match */
     47    bool operator==(OggPlayer::State state) { return this->state & state; };
    4448
    45   OggPlayer(const std::string& fileName = "");
    46   virtual ~OggPlayer();
    47   /** @param state compare this State with the internal State @returns true on match */
    48   bool operator==(OggPlayer::State state) { return this->state & state; };
     49    bool open(const std::string& fileName = "");
    4950
    50   bool open(const std::string& fileName = "");
     51    bool play();
     52    void stop();
     53    void pause();
     54    void rewind(); // convenience
     55    void jumpTo(float timeCode);
    5156
    52   bool play();
    53   void stop();
    54   void pause();
    55   void rewind(); // convenience
    56   void jumpTo(float timeCode);
     57    float length();
     58    bool isPlaying();
     59    bool getState() { return this->state; };
    5760
    58   float length();
    59   bool isPlaying();
    60   bool getState() { return this->state; };
    61 
    62   void debug() const;
    63   void printState() const;
    64   const char* getVorbisError(int code);
     61    void debug() const;
     62    void printState() const;
     63    const char* getVorbisError(int code);
    6564
    6665
    67 private:
    68   static int musicThread(void* oggPlayer);
    69   bool playback();
    70   void suspend();
    71   bool update();
     66  private:
     67    static int musicThread(void* oggPlayer);
     68    bool playback();
     69    void suspend();
     70    bool update();
    7271
    73   void release();
     72    void release();
    7473
    75   bool stream(ALuint buffer);
    76   void empty();
     74    bool stream(ALuint buffer);
     75    void empty();
    7776
    78 private:
    79   FILE*               oggFile;              //!< general file-handler, to open the sound-file
    80   OggVorbis_File      oggStream;            //!< The stream this Ogg-player is playing back
    81   vorbis_info*        vorbisInfo;           //!< The information held in the opened ogg-file
    82   vorbis_comment*     vorbisComment;        //!< Comments about the ogg-file
     77  private:
     78    FILE*               oggFile;              //!< general file-handler, to open the sound-file
     79    OggVorbis_File      oggStream;            //!< The stream this Ogg-player is playing back
     80    vorbis_info*        vorbisInfo;           //!< The information held in the opened ogg-file
     81    vorbis_comment*     vorbisComment;        //!< Comments about the ogg-file
    8382
    84   ALuint              buffers[2];           //!< buffers that handle sequentially buffering of the audio
    85   ALuint              source;               //!< The source we play back on
    86   ALenum              format;               //!< The format we play back
    87   unsigned int        state;                //!< The States the OggPlayer is in (this can be multiple entries from OggPlayer::State).
     83    ALuint              buffers[2];           //!< buffers that handle sequentially buffering of the audio
     84    ALuint              source;               //!< The source we play back on
     85    ALenum              format;               //!< The format we play back
     86    unsigned int        state;                //!< The States the OggPlayer is in (this can be multiple entries from OggPlayer::State).
    8887
    89   SDL_Thread*         musicThreadID;        //!< The Thread in which music is Played back.
    90   SDL_mutex*          musicMutex;           //!< A Mutex so that the two threads do not interfere.
    91 };
     88    SDL_Thread*         musicThreadID;        //!< The Thread in which music is Played back.
     89    SDL_mutex*          musicMutex;           //!< A Mutex so that the two threads do not interfere.
     90  };
    9291
    93 
     92}
    9493#endif /* _OGG_PLAYER_H */
  • trunk/src/lib/sound/sound_buffer.cc

    r7290 r7460  
    2323#include <cassert>
    2424
    25 using namespace std;
     25namespace OrxSound
     26{
     27  //////////////////
     28  /* SOUND-BUFFER */
     29  //////////////////
     30  /**
     31   *  Creates a Soundbuffer out of an inputfile
     32   * @param fileName The name of the File
     33   */
     34  SoundBuffer::SoundBuffer(const std::string& fileName)
     35  {
     36    this->setClassID(CL_SOUND_BUFFER, "SoundBuffer");
     37    this->setName(fileName);
    2638
    27 //////////////////
    28 /* SOUND-BUFFER */
    29 //////////////////
    30 /**
    31  *  Creates a Soundbuffer out of an inputfile
    32  * @param fileName The name of the File
    33  */
    34 SoundBuffer::SoundBuffer(const std::string& fileName)
    35 {
    36   this->setClassID(CL_SOUND_BUFFER, "SoundBuffer");
    37   this->setName(fileName);
    38 
    39   // generate a Buffer
    40   alGenBuffers(1, &this->bufferID);
    41   SoundEngine::checkError("Generate Buffer", __LINE__);
    42   this->loadWAV(fileName);
    43 }
    44 
    45 SoundBuffer::~SoundBuffer()
    46 {
    47   //  SoundEngine::getInstance()->removeBuffer(this);
    48   alDeleteBuffers(1, &this->bufferID);
    49   SoundEngine::checkError("SoundBuffer: Delete Buffer", __LINE__);
    50 }
    51 
    52 /**
    53  * @brief loads a Waveform from the local fileSystem into this Source.
    54  * @param fileName the Name of the File to Load.
    55  * @returns true on success.
    56  */
    57 bool SoundBuffer::loadWAV(const std::string& fileName)
    58 {
    59   SDL_AudioSpec wavSpec;
    60   Uint32 wavLength;
    61   Uint8 *wavBuffer;
    62 
    63   /* Load the WAV */
    64   if( SDL_LoadWAV(fileName.c_str(), &wavSpec, &wavBuffer, &wavLength) == NULL)
    65   {
    66     PRINTF(2)("Could not open %s: %s\n", fileName.c_str(), SDL_GetError());
    67     return false;
     39    // generate a Buffer
     40    alGenBuffers(1, &this->bufferID);
     41    SoundEngine::checkError("Generate Buffer", __LINE__);
     42    this->loadWAV(fileName);
    6843  }
    6944
    70   alBufferData(this->bufferID, SoundBuffer::sdlAudioSpecToAlFormat(&wavSpec), wavBuffer, wavLength, wavSpec.freq);
    71   SDL_FreeWAV(wavBuffer);
    72   if (SoundEngine::checkError("Could not load Wave file", __LINE__))
    73     return true;
    74   else
    75     return false;
     45  SoundBuffer::~SoundBuffer()
     46  {
     47    //  SoundEngine::getInstance()->removeBuffer(this);
     48    alDeleteBuffers(1, &this->bufferID);
     49    SoundEngine::checkError("SoundBuffer: Delete Buffer", __LINE__);
     50  }
     51
     52  /**
     53   * @brief loads a Waveform from the local fileSystem into this Source.
     54   * @param fileName the Name of the File to Load.
     55   * @returns true on success.
     56   */
     57  bool SoundBuffer::loadWAV(const std::string& fileName)
     58  {
     59    SDL_AudioSpec wavSpec;
     60    Uint32 wavLength;
     61    Uint8 *wavBuffer;
     62
     63    /* Load the WAV */
     64    if( SDL_LoadWAV(fileName.c_str(), &wavSpec, &wavBuffer, &wavLength) == NULL)
     65    {
     66      PRINTF(2)("Could not open %s: %s\n", fileName.c_str(), SDL_GetError());
     67      return false;
     68    }
     69
     70    alBufferData(this->bufferID, SoundBuffer::sdlAudioSpecToAlFormat(&wavSpec), wavBuffer, wavLength, wavSpec.freq);
     71    SDL_FreeWAV(wavBuffer);
     72    if (SoundEngine::checkError("Could not load Wave file", __LINE__))
     73      return true;
     74    else
     75      return false;
     76  }
     77
     78  /**
     79   * @brief converts an SDL_AudioSpec into a valid OpenAL AUDIO_FORMAT enumerator
     80   * @param audiospec the AudioSpec to convert.
     81   * @returns the AL_FORMAT
     82   */
     83  ALenum SoundBuffer::sdlAudioSpecToAlFormat(const SDL_AudioSpec* audiospec)
     84  {
     85    assert (audiospec != NULL);
     86    bool stereo = true;
     87    bool is16Bit = true;
     88    if (audiospec->format == AUDIO_U8 || audiospec->format == AUDIO_S8)
     89      is16Bit = false;
     90    if (audiospec->channels == 1)
     91      stereo = false;
     92
     93    if (!stereo && !is16Bit)
     94      return AL_FORMAT_MONO8;
     95    else if (!stereo && is16Bit)
     96      return AL_FORMAT_MONO16;
     97    else if (stereo && !is16Bit)
     98      return AL_FORMAT_STEREO8;
     99    else if (stereo && is16Bit)
     100      return AL_FORMAT_STEREO16;
     101  }
    76102}
    77 
    78 /**
    79  * @brief converts an SDL_AudioSpec into a valid OpenAL AUDIO_FORMAT enumerator
    80  * @param audiospec the AudioSpec to convert.
    81  * @returns the AL_FORMAT
    82  */
    83 ALenum SoundBuffer::sdlAudioSpecToAlFormat(const SDL_AudioSpec* audiospec)
    84 {
    85   assert (audiospec != NULL);
    86   bool stereo = true;
    87   bool is16Bit = true;
    88   if (audiospec->format == AUDIO_U8 || audiospec->format == AUDIO_S8)
    89     is16Bit = false;
    90   if (audiospec->channels == 1)
    91     stereo = false;
    92 
    93   if (!stereo && !is16Bit)
    94     return AL_FORMAT_MONO8;
    95   else if (!stereo && is16Bit)
    96     return AL_FORMAT_MONO16;
    97   else if (stereo && !is16Bit)
    98     return AL_FORMAT_STEREO8;
    99   else if (stereo && is16Bit)
    100     return AL_FORMAT_STEREO16;
    101 }
    102 
  • trunk/src/lib/sound/sound_buffer.h

    r7221 r7460  
    1313typedef struct SDL_AudioSpec;
    1414
    15 //! A class that represents a datastructure to play Sounds.
    16 class SoundBuffer : public BaseObject
     15namespace OrxSound
    1716{
     17  //! A class that represents a datastructure to play Sounds.
     18  class SoundBuffer : public BaseObject
     19  {
    1820  public:
    1921    SoundBuffer(const std::string& fileName);
     
    3335    ALsizei       size;                 //!< The size of the Buffer.
    3436    ALboolean     loop;                 //!< loop information.
    35 };
    36 
     37  };
     38}
    3739#endif /* _SOUND_BUFFER_H */
  • trunk/src/lib/sound/sound_engine.cc

    r7318 r7460  
    2929#include "globals.h"
    3030
    31 using namespace std;
    32 
    33 
    34 //////////////////
    35 /* SOUND-ENGINE */
    36 //////////////////
    37 /**
    38  * @brief standard constructor
    39 */
    40 SoundEngine::SoundEngine ()
     31namespace OrxSound
    4132{
    42   this->setClassID(CL_SOUND_ENGINE, "SoundEngine");
    43   this->setName("SoundEngine");
    44 
    45   this->listener = NULL;
    46   this->bufferList = NULL;
    47   this->sourceList = NULL;
    48 
    49   this->device = NULL;
    50   this->context = NULL;
    51 
    52   this->maxSourceCount = 32;
    53 
    54   this->effectsVolume = .80;
    55   this->musicVolume = .75;
    56 
    57   this->sourceMutex = SDL_CreateMutex();
    58 }
    59 
    60 /**
    61  * @brief the singleton reference to this class
    62 */
    63 SoundEngine* SoundEngine::singletonRef = NULL;
    64 
    65 /**
    66  * @brief standard destructor
    67  */
    68 SoundEngine::~SoundEngine ()
    69 {
    70   // deleting all the SoundSources
    71   if(this->sourceList != NULL)
    72   {
    73     while (this->sourceList->size() > 0)
    74       delete static_cast<SoundSource*>(this->sourceList->front());
    75   }
    76 
    77   while(!this->ALSources.empty())
    78   {
    79     if (alIsSource(this->ALSources.top()))
    80     {
    81       alDeleteSources(1, &this->ALSources.top());
    82       SoundEngine::checkError("Deleting Source", __LINE__);
     33
     34  //////////////////
     35  /* SOUND-ENGINE */
     36  //////////////////
     37  /**
     38   * @brief standard constructor
     39  */
     40  SoundEngine::SoundEngine ()
     41  {
     42    this->setClassID(CL_SOUND_ENGINE, "SoundEngine");
     43    this->setName("SoundEngine");
     44
     45    this->listener = NULL;
     46    this->bufferList = NULL;
     47    this->sourceList = NULL;
     48
     49    this->device = NULL;
     50    this->context = NULL;
     51
     52    this->maxSourceCount = 32;
     53
     54    this->effectsVolume = .80;
     55    this->musicVolume = .75;
     56
     57    this->sourceMutex = SDL_CreateMutex();
     58  }
     59
     60  /**
     61   * @brief the singleton reference to this class
     62  */
     63  SoundEngine* SoundEngine::singletonRef = NULL;
     64
     65  /**
     66   * @brief standard destructor
     67   */
     68  SoundEngine::~SoundEngine ()
     69  {
     70    // deleting all the SoundSources
     71    if(this->sourceList != NULL)
     72    {
     73      while (this->sourceList->size() > 0)
     74        delete static_cast<SoundSource*>(this->sourceList->front());
     75    }
     76
     77    while(!this->ALSources.empty())
     78    {
     79      if (alIsSource(this->ALSources.top()))
     80      {
     81        alDeleteSources(1, &this->ALSources.top());
     82        SoundEngine::checkError("Deleting Source", __LINE__);
     83      }
     84      else
     85        PRINTF(1)("%d is not a Source\n", this->ALSources.top());
     86
     87      this->ALSources.pop();
     88    }
     89
     90    // deleting all the SoundBuffers
     91    if (this->bufferList != NULL)
     92    {
     93      while(this->bufferList->size() > 0)
     94        ResourceManager::getInstance()->unload(static_cast<SoundBuffer*>(this->bufferList->front()));
     95    }
     96
     97    // removing openAL from AudioResource
     98    //! @todo this should be terminated through alc
     99    //alutExit();
     100
     101    SDL_DestroyMutex(this->sourceMutex);
     102
     103    SoundEngine::singletonRef = NULL;
     104  }
     105
     106  /**
     107   * @brief loads the settings of the SoundEngine from an ini-file
     108   */
     109  void SoundEngine::loadSettings()
     110  {
     111    MultiType channels = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_AUDIO_CHANNELS, "32");
     112    this->maxSourceCount = channels.getInt();
     113
     114    MultiType effectsVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_EFFECTS_VOLUME, "80");
     115    this->effectsVolume = effectsVolume.getFloat()/100.0;
     116
     117    MultiType musicVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_MUSIC_VOLUME, "75");
     118    this->musicVolume = musicVolume.getFloat()/100.0;
     119  }
     120
     121  /**
     122   * @brief creates a new SoundSource.
     123   * @param fileName The Name to load the SoundBuffer from
     124   * @param sourceNode The sourceNode to bind this SoundSource to.
     125   * @returns The newly created SoundSource
     126   *
     127   * acctualy this is nothing more than a wrapper around the ResourceManager.
     128  */
     129  SoundSource* SoundEngine::createSource(const std::string& fileName, PNode* sourceNode)
     130  {
     131    SoundBuffer* buffer = NULL;
     132    if (!fileName.empty())
     133    {
     134      buffer= (SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL);
     135      if (buffer == NULL)
     136        PRINTF(2)("Wav-Sound %s could not be loaded onto new Source\n", fileName.c_str());
     137    }
     138    return new SoundSource(sourceNode, buffer);
     139  }
     140
     141  /**
     142   * @brief Sets the doppler values of openAL
     143   * @param dopplerFactor the extent of the doppler-effect
     144   * @param dopplerVelocity the Speed the sound travels
     145  */
     146  void SoundEngine::setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity)
     147  {
     148    alDopplerFactor(dopplerFactor);
     149    this->checkError("Setting Doppler Factor", __LINE__);
     150
     151    alDopplerVelocity(dopplerVelocity);
     152    this->checkError("Setting Doppler Velocity", __LINE__);
     153  }
     154
     155
     156  /**
     157   * @brief retrieves an OpenAL Source from the availiable Sources.
     158   * @param source the Source to fill with the Value.
     159   */
     160  void SoundEngine::popALSource(ALuint& source)
     161  {
     162    assert (source == 0);
     163    /// @TODO try to create more sources if needed
     164    if (!this->ALSources.empty())
     165    {
     166      SDL_mutexP(this->sourceMutex);
     167      source = this->ALSources.top();
     168      this->ALSources.pop();
     169      SDL_mutexV(this->sourceMutex);
     170    }
     171  }
     172
     173
     174  /**
     175   * @brief Pushes an OpenAL Source back into the Stack of known sources
     176   * @param source the Source to push onto the top of the SourceStack
     177   */
     178  void SoundEngine::pushALSource(ALuint& source)
     179  {
     180    if (source != 0)
     181    {
     182      SDL_mutexP(this->sourceMutex);
     183      this->ALSources.push(source);
     184      SDL_mutexV(this->sourceMutex);
     185    }
     186  };
     187
     188
     189  /**
     190   * @brief updates all The positions, Directions and Velocities of all Sounds
     191   */
     192  void SoundEngine::update()
     193  {
     194    // updating the Listeners Position
     195    if (likely(this->listener != NULL))
     196    {
     197      alListener3f(AL_POSITION,
     198                   this->listener->getAbsCoor().x,
     199                   this->listener->getAbsCoor().y,
     200                   this->listener->getAbsCoor().z);
     201      alListener3f(AL_VELOCITY,
     202                   this->listener->getVelocity().x,
     203                   this->listener->getVelocity().y,
     204                   this->listener->getVelocity().z);
     205      Vector absDirV = this->listener->getAbsDirV();
     206      ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z};
     207      alListenerfv(AL_ORIENTATION, orientation);
     208      SoundEngine::checkError("SoundEngine::update() - Listener Error", __LINE__);
    83209    }
    84210    else
    85       PRINTF(1)("%d is not a Source\n", this->ALSources.top());
    86 
    87     this->ALSources.pop();
    88   }
    89 
    90   // deleting all the SoundBuffers
    91   if (this->bufferList != NULL)
    92   {
    93     while(this->bufferList->size() > 0)
    94       ResourceManager::getInstance()->unload(static_cast<SoundBuffer*>(this->bufferList->front()));
    95   }
    96 
    97   // removing openAL from AudioResource
    98   //! @todo this should be terminated through alc
    99   //alutExit();
    100 
    101   SDL_DestroyMutex(this->sourceMutex);
    102 
    103   SoundEngine::singletonRef = NULL;
    104 }
    105 
    106 /**
    107  * @brief loads the settings of the SoundEngine from an ini-file
    108  */
    109 void SoundEngine::loadSettings()
    110 {
    111   MultiType channels = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_AUDIO_CHANNELS, "32");
    112   this->maxSourceCount = channels.getInt();
    113 
    114   MultiType effectsVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_EFFECTS_VOLUME, "80");
    115   this->effectsVolume = effectsVolume.getFloat()/100.0;
    116 
    117   MultiType musicVolume = Preferences::getInstance()->getString(CONFIG_SECTION_AUDIO, CONFIG_NAME_MUSIC_VOLUME, "75");
    118   this->musicVolume = musicVolume.getFloat()/100.0;
    119 }
    120 
    121 /**
    122  * @brief creates a new SoundSource.
    123  * @param fileName The Name to load the SoundBuffer from
    124  * @param sourceNode The sourceNode to bind this SoundSource to.
    125  * @returns The newly created SoundSource
    126  *
    127  * acctualy this is nothing more than a wrapper around the ResourceManager.
    128 */
    129 SoundSource* SoundEngine::createSource(const std::string& fileName, PNode* sourceNode)
    130 {
    131   SoundBuffer* buffer = NULL;
    132   if (!fileName.empty())
    133   {
    134      buffer= (SoundBuffer*)ResourceManager::getInstance()->load(fileName, WAV, RP_LEVEL);
    135      if (buffer == NULL)
    136        PRINTF(2)("Wav-Sound %s could not be loaded onto new Source\n", fileName.c_str());
    137   }
    138     return new SoundSource(sourceNode, buffer);
    139 }
    140 
    141 /**
    142  * @brief Sets the doppler values of openAL
    143  * @param dopplerFactor the extent of the doppler-effect
    144  * @param dopplerVelocity the Speed the sound travels
    145 */
    146 void SoundEngine::setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity)
    147 {
    148   alDopplerFactor(dopplerFactor);
    149   this->checkError("Setting Doppler Factor", __LINE__);
    150 
    151   alDopplerVelocity(dopplerVelocity);
    152   this->checkError("Setting Doppler Velocity", __LINE__);
    153 }
    154 
    155 
    156 /**
    157  * @brief retrieves an OpenAL Source from the availiable Sources.
    158  * @param source the Source to fill with the Value.
    159  */
    160 void SoundEngine::popALSource(ALuint& source)
    161 {
    162   assert (source == 0);
    163   /// @TODO try to create more sources if needed
    164   if (!this->ALSources.empty())
    165   {
    166     SDL_mutexP(this->sourceMutex);
    167     source = this->ALSources.top();
    168     this->ALSources.pop();
    169     SDL_mutexV(this->sourceMutex);
    170   }
    171 }
    172 
    173 
    174 /**
    175  * @brief Pushes an OpenAL Source back into the Stack of known sources
    176  * @param source the Source to push onto the top of the SourceStack
    177  */
    178 void SoundEngine::pushALSource(ALuint& source)
    179 {
    180   if (source != 0)
    181   {
    182     SDL_mutexP(this->sourceMutex);
    183     this->ALSources.push(source);
    184     SDL_mutexV(this->sourceMutex);
    185   }
    186 };
    187 
    188 
    189 /**
    190  * @brief updates all The positions, Directions and Velocities of all Sounds
    191  */
    192 void SoundEngine::update()
    193 {
    194   // updating the Listeners Position
    195   if (likely(this->listener != NULL))
    196   {
    197     alListener3f(AL_POSITION,
    198                  this->listener->getAbsCoor().x,
    199                  this->listener->getAbsCoor().y,
    200                  this->listener->getAbsCoor().z);
    201     alListener3f(AL_VELOCITY,
    202                  this->listener->getVelocity().x,
    203                  this->listener->getVelocity().y,
    204                  this->listener->getVelocity().z);
    205     Vector absDirV = this->listener->getAbsDirV();
    206     ALfloat orientation [6] = {1,0,0, absDirV.x, absDirV.y, absDirV.z};
    207     alListenerfv(AL_ORIENTATION, orientation);
    208     SoundEngine::checkError("SoundEngine::update() - Listener Error", __LINE__);
    209   }
    210   else
    211     PRINTF(2)("no listener defined\n");
    212 
    213   // updating all the Sources positions
    214   if (likely(this->sourceList != NULL || (this->sourceList = ClassList::getList(CL_SOUND_SOURCE)) != NULL))
    215   {
    216     list<BaseObject*>::const_iterator sourceIT;
    217     SoundSource* source;
    218     for (sourceIT = this->sourceList->begin(); sourceIT != this->sourceList->end(); sourceIT++)
    219     {
    220       source = static_cast<SoundSource*>(*sourceIT);
    221       if (source->isPlaying())
     211      PRINTF(2)("no listener defined\n");
     212
     213    // updating all the Sources positions
     214    if (likely(this->sourceList != NULL || (this->sourceList = ClassList::getList(CL_SOUND_SOURCE)) != NULL))
     215    {
     216      std::list<BaseObject*>::const_iterator sourceIT;
     217      SoundSource* source;
     218      for (sourceIT = this->sourceList->begin(); sourceIT != this->sourceList->end(); sourceIT++)
    222219      {
    223         int play = 0x000;
    224         alGetSourcei(source->getID(), AL_SOURCE_STATE, &play);
    225         if (DEBUG > 2)
    226           SoundEngine::checkError("SoundEngine::update() Play", __LINE__);
    227         if(play == AL_PLAYING)
     220        source = static_cast<SoundSource*>(*sourceIT);
     221        if (source->isPlaying())
    228222        {
    229           if (likely(source->getNode() != NULL))
     223          int play = 0x000;
     224          alGetSourcei(source->getID(), AL_SOURCE_STATE, &play);
     225          if (DEBUG > 2)
     226            SoundEngine::checkError("SoundEngine::update() Play", __LINE__);
     227          if(play == AL_PLAYING)
    230228          {
    231             alSource3f(source->getID(), AL_POSITION,
    232                        source->getNode()->getAbsCoor().x,
    233                        source->getNode()->getAbsCoor().y,
    234                        source->getNode()->getAbsCoor().z);
    235             if (DEBUG > 2)
    236               SoundEngine::checkError("SoundEngine::update() Set Source Position", __LINE__);
    237             alSource3f(source->getID(), AL_VELOCITY,
    238                        source->getNode()->getVelocity().x,
    239                        source->getNode()->getVelocity().y,
    240                        source->getNode()->getVelocity().z);
    241             if (DEBUG > 2)
    242               SoundEngine::checkError("SoundEngine::update() Set Source Velocity", __LINE__);
     229            if (likely(source->getNode() != NULL))
     230            {
     231              alSource3f(source->getID(), AL_POSITION,
     232                         source->getNode()->getAbsCoor().x,
     233                         source->getNode()->getAbsCoor().y,
     234                         source->getNode()->getAbsCoor().z);
     235              if (DEBUG > 2)
     236                SoundEngine::checkError("SoundEngine::update() Set Source Position", __LINE__);
     237              alSource3f(source->getID(), AL_VELOCITY,
     238                         source->getNode()->getVelocity().x,
     239                         source->getNode()->getVelocity().y,
     240                         source->getNode()->getVelocity().z);
     241              if (DEBUG > 2)
     242                SoundEngine::checkError("SoundEngine::update() Set Source Velocity", __LINE__);
     243            }
     244          }
     245          else
     246          {
     247            source->stop();
    243248          }
    244249        }
    245         else
    246         {
    247           source->stop();
    248         }
    249250      }
    250251    }
    251   }
    252   SoundEngine::checkError("SoundEngine::update()", __LINE__);
    253 }
    254 
    255 
    256 /**
    257  *  initializes Audio in general
    258 */
    259 bool SoundEngine::initAudio()
    260 {
    261   //   ALenum result;
    262   //   PRINTF(3)("Initialisazing openAL sound engine\n");
    263   //   const char* defaultDevice =(const char*) alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
    264   //   const char* deviceList = (const char*)alcGetString(NULL,ALC_DEVICE_SPECIFIER);
    265   //   const char* devWalk = deviceList;
    266   //   //  if (alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
    267   //   { // try out enumeration extension
    268   //     PRINTF(3)("Enumeration-extension found\n");
    269   //
    270   //     PRINTF(3)("Default device: %s\n", defaultDevice);
    271   //     do
    272   //     {
    273   //       PRINTF(3)("%s\n", devWalk);
    274   //       devWalk += strlen(devWalk)+1;
    275   //     }
    276   //     while (devWalk[0] != '\0');
    277   //  }
    278 
    279   // INITIALIZING THE DEVICE:
    280   //   char deviceName[] =
    281   //   #ifdef __WIN32__
    282   //     "Direct3D";
    283   //   #else
    284   //     "'( ( devices '( native null ) ) )";
    285   //   #endif
    286 
    287   this->device = alcOpenDevice(NULL);
    288   this->checkALCError("opening Device", __LINE__);
    289 
    290   PRINTF(4)("Audio-Specifier: %s\n", (const char*)alcGetString(this->device, ALC_DEVICE_SPECIFIER));
    291   PRINTF(4)("Audio-Extensions: %s\n", (const char*)alcGetString(this->device, ALC_EXTENSIONS));
    292 
    293 
    294   this->context = alcCreateContext(this->device, NULL);
    295   this->checkALCError("creating Context", __LINE__);
    296 
    297   alcMakeContextCurrent(this->context);
    298   this->checkALCError("making Context Current", __LINE__);
    299   // #endif
    300 
    301   this->setDopplerValues(SOUND_DOPPLER_FACTOR, SOUND_DOPPLER_VELOCITY);
    302   this->allocateSources(this->maxSourceCount);
    303   this->checkError("Allocating Sources", __LINE__);
    304 }
    305 
    306 
    307 /**
    308  * Allocates openAL sources
    309  * @param count how many sources to allocate
    310  * @returns true on success, false if at least one source could not be allocated
    311  */
    312 bool SoundEngine::allocateSources(unsigned int count)
    313 {
    314   unsigned int failCount = 0;
    315   for (unsigned int i = 0; i < count; i++)
    316   {
    317     ALuint source = 0;
    318 
    319     alGenSources(1, &source);
    320     this->checkError("allocate Source", __LINE__);
    321     if (!alIsSource(source))
    322     {
    323       PRINTF(5)("not allocated Source\n");
    324       failCount++;
    325       continue;
    326     }
    327 
    328     alSourcef (source, AL_PITCH,    1.0      );
    329     alSourcef (source, AL_GAIN,     this->getEffectsVolume() );
    330     alSourcei (source, AL_LOOPING,  AL_FALSE );
    331     this->ALSources.push(source);
    332   }
    333   if (failCount == 0)
    334     return true;
    335   else
    336   {
    337     PRINTF(2)("Failed to allocate %d of %d SoundSources\n", failCount, count);
    338   }
    339 }
    340 
    341 /**
    342  * @brief checks for an OpenAL error
    343  * @param error the ErrorMessage to display
    344  * @param line on what line did the error occure.
    345  */
    346 bool SoundEngine::checkError(const std::string& error, unsigned int line)
    347 {
    348   ALenum errorCode;
    349   if ((errorCode = alGetError()) != AL_NO_ERROR)
    350   {
    351     PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALErrorString(errorCode));
    352     return false;
    353   }
    354   else
    355     return true;
    356 }
    357 
    358 /**
    359  * @brief check for an ALC error.
    360  * @brief error the Error-String to display
    361  * @param line on that line, the error occured (debugging mode).
    362  */
    363 bool SoundEngine::checkALCError(const std::string& error, unsigned int line)
    364 {
    365   ALenum errorCode;
    366   if ((errorCode = alcGetError(this->device)) != ALC_NO_ERROR)
    367   {
    368     PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALCErrorString(errorCode));
    369     return false;
    370   }
    371   else
    372     return true;
    373 }
    374 
    375 
    376 
    377 void SoundEngine::listDevices()
    378 {
    379   printf("%s\n",(const char*)alcGetString(NULL, ALC_DEVICE_SPECIFIER));
    380 }
    381 
    382 /**
    383  *  Transforms AL-errors into something readable
    384  * @param err The error found
    385 */
    386 const char* SoundEngine::getALErrorString(ALenum err)
    387 {
    388   switch(err)
    389   {
     252    SoundEngine::checkError("SoundEngine::update()", __LINE__);
     253  }
     254
     255
     256  /**
     257   *  initializes Audio in general
     258  */
     259  bool SoundEngine::initAudio()
     260  {
     261    //   ALenum result;
     262    //   PRINTF(3)("Initialisazing openAL sound engine\n");
     263    //   const char* defaultDevice =(const char*) alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
     264    //   const char* deviceList = (const char*)alcGetString(NULL,ALC_DEVICE_SPECIFIER);
     265    //   const char* devWalk = deviceList;
     266    //   //  if (alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
     267    //   { // try out enumeration extension
     268    //     PRINTF(3)("Enumeration-extension found\n");
     269    //
     270    //     PRINTF(3)("Default device: %s\n", defaultDevice);
     271    //     do
     272    //     {
     273    //       PRINTF(3)("%s\n", devWalk);
     274    //       devWalk += strlen(devWalk)+1;
     275    //     }
     276    //     while (devWalk[0] != '\0');
     277    //  }
     278
     279    // INITIALIZING THE DEVICE:
     280    //   char deviceName[] =
     281    //   #ifdef __WIN32__
     282    //     "Direct3D";
     283    //   #else
     284    //     "'( ( devices '( native null ) ) )";
     285    //   #endif
     286
     287    this->device = alcOpenDevice(NULL);
     288    this->checkALCError("opening Device", __LINE__);
     289
     290    PRINTF(4)("Audio-Specifier: %s\n", (const char*)alcGetString(this->device, ALC_DEVICE_SPECIFIER));
     291    PRINTF(4)("Audio-Extensions: %s\n", (const char*)alcGetString(this->device, ALC_EXTENSIONS));
     292
     293
     294    this->context = alcCreateContext(this->device, NULL);
     295    this->checkALCError("creating Context", __LINE__);
     296
     297    alcMakeContextCurrent(this->context);
     298    this->checkALCError("making Context Current", __LINE__);
     299    // #endif
     300
     301    this->setDopplerValues(SOUND_DOPPLER_FACTOR, SOUND_DOPPLER_VELOCITY);
     302    this->allocateSources(this->maxSourceCount);
     303    this->checkError("Allocating Sources", __LINE__);
     304  }
     305
     306
     307  /**
     308   * Allocates openAL sources
     309   * @param count how many sources to allocate
     310   * @returns true on success, false if at least one source could not be allocated
     311   */
     312  bool SoundEngine::allocateSources(unsigned int count)
     313  {
     314    unsigned int failCount = 0;
     315    for (unsigned int i = 0; i < count; i++)
     316    {
     317      ALuint source = 0;
     318
     319      alGenSources(1, &source);
     320      this->checkError("allocate Source", __LINE__);
     321      if (!alIsSource(source))
     322      {
     323        PRINTF(5)("not allocated Source\n");
     324        failCount++;
     325        continue;
     326      }
     327
     328      alSourcef (source, AL_PITCH,    1.0      );
     329      alSourcef (source, AL_GAIN,     this->getEffectsVolume() );
     330      alSourcei (source, AL_LOOPING,  AL_FALSE );
     331      this->ALSources.push(source);
     332    }
     333    if (failCount == 0)
     334      return true;
     335    else
     336    {
     337      PRINTF(2)("Failed to allocate %d of %d SoundSources\n", failCount, count);
     338    }
     339  }
     340
     341  /**
     342   * @brief checks for an OpenAL error
     343   * @param error the ErrorMessage to display
     344   * @param line on what line did the error occure.
     345   */
     346  bool SoundEngine::checkError(const std::string& error, unsigned int line)
     347  {
     348    ALenum errorCode;
     349    if ((errorCode = alGetError()) != AL_NO_ERROR)
     350    {
     351      PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALErrorString(errorCode));
     352      return false;
     353    }
     354    else
     355      return true;
     356  }
     357
     358  /**
     359   * @brief check for an ALC error.
     360   * @brief error the Error-String to display
     361   * @param line on that line, the error occured (debugging mode).
     362   */
     363  bool SoundEngine::checkALCError(const std::string& error, unsigned int line)
     364  {
     365    ALenum errorCode;
     366    if ((errorCode = alcGetError(this->device)) != ALC_NO_ERROR)
     367    {
     368      PRINTF(1)("Error %s (line:%d): '%s'\n", error.c_str(), line, SoundEngine::getALCErrorString(errorCode));
     369      return false;
     370    }
     371    else
     372      return true;
     373  }
     374
     375
     376
     377  void SoundEngine::listDevices()
     378  {
     379    printf("%s\n",(const char*)alcGetString(NULL, ALC_DEVICE_SPECIFIER));
     380  }
     381
     382  /**
     383   *  Transforms AL-errors into something readable
     384   * @param err The error found
     385  */
     386  const char* SoundEngine::getALErrorString(ALenum err)
     387  {
     388    switch(err)
     389    {
    390390    case AL_NO_ERROR:
    391391      return ("AL_NO_ERROR");
     
    400400    case AL_OUT_OF_MEMORY:
    401401      return ("AL_OUT_OF_MEMORY");
    402   };
    403 }
    404 
    405 
    406 const char* SoundEngine::getALCErrorString(ALenum err)
    407 {
    408   switch(err)
    409   {
     402    };
     403  }
     404
     405
     406  const char* SoundEngine::getALCErrorString(ALenum err)
     407  {
     408    switch(err)
     409    {
    410410    case ALC_NO_ERROR:
    411411      return ("AL_NO_ERROR");
     
    420420    case ALC_OUT_OF_MEMORY:
    421421      return("ALC_OUT_OF_MEMORY");
    422   };
     422    };
     423  }
    423424}
  • trunk/src/lib/sound/sound_engine.h

    r7355 r7460  
    2222// FORWARD DECLARATION
    2323class PNode;
    24 class IniParser;
    25 
    26 
    27 //! A class that handles audio via the openAudioLibrary
    28 class SoundEngine : public BaseObject {
     24namespace OrxSound
     25{
     26  //! A class that handles audio via the openAudioLibrary
     27  class SoundEngine : public BaseObject
     28  {
    2929  public:
    3030    virtual ~SoundEngine();
     
    3232    inline static SoundEngine* getInstance() { if (!SoundEngine::singletonRef) SoundEngine::singletonRef = new SoundEngine();  return SoundEngine::singletonRef; };
    3333
     34    SoundSource* createSource(const std::string& fileName, PNode* sourceNode = NULL);
    3435    void loadSettings();
    35 
    36     SoundSource* createSource(const std::string& fileName, PNode* sourceNode = NULL);
     36    bool initAudio();
    3737
    3838    /** @param listener the listener in the scene */
    39     void setListener(PNode* listener) { this->listener = listener; };
     39  void setListener(const PNode* listener) { this->listener = listener; };
    4040    void setDopplerValues(ALfloat dopplerFactor, ALfloat dopplerVelocity);
     41
    4142
    4243
     
    4849    void update();
    4950
    50   // administrative
     51    // administrative
    5152    void popALSource(ALuint& source);
    5253    void pushALSource(ALuint& source);
    5354
    54 
    55     bool initAudio();
    56     bool allocateSources(unsigned int count);
    57 
    58   // error handling:
     55    // error handling:
    5956    static bool checkError(const std::string& error, unsigned int line);
    6057    bool checkALCError(const std::string& error, unsigned int line);
     
    6461  private:
    6562    SoundEngine();
     63    bool allocateSources(unsigned int count);
    6664
    6765    void listDevices();
     
    7573    float                          musicVolume;              //!< the maximum volume of the music in % (0f,1f]
    7674    float                          effectsVolume;            //!< the maximum volume of sound-effects in % (0f,1f]
    77     PNode*                         listener;                 //!< The listener of the Scene
     75    const PNode*                   listener;                 //!< The listener of the Scene
    7876
    7977    const std::list<BaseObject*>*  bufferList;               //!< A list of buffers
     
    8482
    8583    SDL_mutex*                     sourceMutex;              //!< A mutex so we can not harm the stack
    86 };
     84  };
     85}
    8786
    8887#endif /* _SOUND_ENGINE_H */
  • trunk/src/lib/sound/sound_source.cc

    r7386 r7460  
    2222#include "compiler.h"
    2323
    24 using namespace std;
    25 
    26 /**
    27  * @brief creates a SoundSource at position sourceNode with the SoundBuffer buffer
    28  */
    29 SoundSource::SoundSource(const PNode* sourceNode, const SoundBuffer* buffer)
     24namespace OrxSound
    3025{
    31   this->setClassID(CL_SOUND_SOURCE, "SoundSource");
    32 
    33   // adding the Source to the SourcesList of the SoundEngine
    34   this->buffer = buffer;
    35   this->sourceNode = sourceNode;
    36   this->resident = false;
    37 
    38   this->sourceID = 0;
    39   this->bPlay = false;
     26  /**
     27   * @brief creates a SoundSource at position sourceNode with the SoundBuffer buffer
     28   */
     29  SoundSource::SoundSource(const PNode* sourceNode, const SoundBuffer* buffer)
     30  {
     31    this->setClassID(CL_SOUND_SOURCE, "SoundSource");
     32
     33    // adding the Source to the SourcesList of the SoundEngine
     34    this->buffer = buffer;
     35    this->sourceNode = sourceNode;
     36    this->resident = false;
     37
     38    this->sourceID = 0;
     39    this->bPlay = false;
     40  }
     41
     42
     43  /**
     44   * @brief construct a SoundSource out of the another soundSource
     45   * @param source the Source to create this source from.
     46   *
     47   * Copies the buffer from source to this Source.
     48   * Acquires a new SourceID if source is Playing.
     49   */
     50  SoundSource::SoundSource(const SoundSource& source)
     51  {
     52    this->setClassID(CL_SOUND_SOURCE, "SoundSource");
     53
     54    // adding the Source to the SourcesList of the SoundEngine
     55    this->buffer = source.buffer;
     56    this->sourceNode = source.sourceNode;
     57    this->resident = source.resident;
     58
     59    this->sourceID = 0;
     60    if (source.bPlay == true)
     61    {
     62      this->bPlay = true;
     63      SoundEngine::getInstance()->popALSource(this->sourceID);
     64    }
     65    else
     66      this->bPlay = false;
     67  }
     68
     69
     70  /**
     71   * @brief paste a copy of the source into this Source.
     72   * @param source the SoundSource to paste into this one.
     73   * @returns a Reference to this Source.
     74   *
     75   */
     76  SoundSource& SoundSource::operator=(const SoundSource& source)
     77  {
     78    this->buffer = source.buffer;
     79    this->sourceNode = sourceNode;
     80    this->resident = source.resident;
     81
     82    if (source.bPlay)
     83      this->play();
     84    else
     85      this->stop();
     86  }
     87
     88
     89  /**
     90   * @brief compares two Sources with each other.
     91   * @param source the Source to compare against this One.
     92   * Two Sources are the same, if the PNodes match, and the Sound Played are the same.
     93   * The alSource must not match, because no two Sources can have the same alSource.
     94   */
     95  bool SoundSource::operator==(const SoundSource& source)
     96  {
     97    return (this->buffer == source.buffer &&
     98            this->bPlay == source.bPlay &&
     99            this->sourceNode == source.sourceNode);
     100  }
     101
     102
     103  /**
     104   * @brief deletes a SoundSource
     105   */
     106  SoundSource::~SoundSource()
     107  {
     108    this->stop();
     109    if (this->sourceID != 0)
     110      SoundEngine::getInstance()->pushALSource(this->sourceID);
     111  }
     112
     113
     114  /**
     115   * @brief Plays back a SoundSource
     116   */
     117  void SoundSource::play()
     118  {
     119    if (this->buffer && this->retrieveSource())
     120    {
     121      if (this->bPlay)
     122        alSourceStop(this->sourceID);
     123      alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID());
     124      alSourcePlay(this->sourceID);
     125
     126      if (DEBUG >= 3)
     127        SoundEngine::checkError("Play Source", __LINE__);
     128      this->bPlay = true;
     129    }
     130  }
     131
     132
     133  /**
     134   * @brief Plays back buffer on this Source
     135   * @param buffer the buffer to play back on this Source
     136   */
     137  void SoundSource::play(const SoundBuffer* buffer)
     138  {
     139    if (!this->retrieveSource())
     140    {
     141      PRINTF(3)("No more Free sources (You might consider raising the Source-Count).\n");
     142      return;
     143    }
     144
     145    alSourceStop(this->sourceID);
     146    alSourcei (this->sourceID, AL_BUFFER, buffer->getID());
     147    alSourcePlay(this->sourceID);
     148
     149    if (unlikely(this->buffer != NULL))
     150      alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID());
     151    this->bPlay = true;
     152
     153    if (DEBUG >= 3)
     154      SoundEngine::checkError("Play Source", __LINE__);
     155  }
     156
     157
     158  /**
     159   * @brief Stops playback of a SoundSource
     160   */
     161  void SoundSource::stop()
     162  {
     163    this->bPlay = false;
     164    if (this->sourceID != 0)
     165    {
     166      alSourceStop(this->sourceID);
     167      if (DEBUG >= 3)
     168        SoundEngine::checkError("StopSource", __LINE__);
     169      alSourcei(this->sourceID, AL_BUFFER, 0);
     170      if (!this->resident)
     171        SoundEngine::getInstance()->pushALSource(this->sourceID);
     172      this->sourceID = 0;
     173    }
     174  }
     175
     176
     177  /**
     178   * @brief Pauses Playback of a SoundSource
     179   */
     180  void SoundSource::pause()
     181  {
     182    alSourcePause(this->sourceID);
     183    if (DEBUG >= 3)
     184      SoundEngine::checkError("Pause Source", __LINE__);
     185  }
     186
     187
     188  /**
     189   * @brief Rewinds Playback of a SoundSource
     190   */
     191  void SoundSource::rewind()
     192  {
     193    alSourceRewind(this->sourceID);
     194
     195    if (DEBUG >= 3)
     196      SoundEngine::checkError("Rewind Source", __LINE__);
     197  }
     198
     199
     200  /**
     201   * @brief sets the RolloffFactor of the Sound emitted from the SoundSource
     202   * @param rolloffFactor The Factor described
     203   *
     204   * this tells openAL how fast the Sounds decay outward from the Source
     205   */
     206  void SoundSource::setRolloffFactor(ALfloat rolloffFactor)
     207  {
     208    alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor);
     209
     210    if (DEBUG >= 3)
     211      SoundEngine::checkError("Set Source Rolloff-factor", __LINE__);
     212  }
     213
     214
     215  /**
     216   * @brief sets the Positional this Source should be attached to.
     217   * @param sourceNode the Source this is attached to.
     218   * If sourceNode == NULL then the Source will be centered, and Audio will be played on all channels.
     219   */
     220  void SoundSource::setSourceNode(const PNode* sourceNode)
     221  {
     222    this->sourceNode = sourceNode;
     223  }
     224
     225  /**
     226   * @brief retrieve a Source.
     227   */
     228  bool SoundSource::retrieveSource()
     229  {
     230    if (this->sourceID != 0)
     231      return true;
     232    else
     233    {
     234      SoundEngine::getInstance()->popALSource(this->sourceID);
     235      if (this->sourceID != 0)
     236      {
     237        if (unlikely(this->sourceNode == NULL))
     238          resetSource(this->sourceID);
     239        return true;
     240      }
     241    }
     242    return false;
     243  }
     244
     245
     246  /**
     247   * @brief reset an alSource to its default Values.
     248   */
     249  void SoundSource::resetSource(ALuint sourceID)
     250  {
     251    alSource3f(sourceID, AL_POSITION,        0.0, 0.0, 0.0);
     252    alSource3f(sourceID, AL_VELOCITY,        0.0, 0.0, 0.0);
     253    alSource3f(sourceID, AL_DIRECTION,       0.0, 0.0, 0.0);
     254    alSourcef (sourceID, AL_ROLLOFF_FACTOR,  0.0          );
     255    //alSourcei (sourceID, AL_SOURCE_RELATIVE, AL_TRUE      );
     256    alSourcef (sourceID, AL_GAIN,            SoundEngine::getInstance()->getEffectsVolume());
     257  }
    40258}
    41 
    42 
    43 /**
    44  * @brief construct a SoundSource out of the another soundSource
    45  * @param source the Source to create this source from.
    46  *
    47  * Copies the buffer from source to this Source.
    48  * Acquires a new SourceID if source is Playing.
    49  */
    50 SoundSource::SoundSource(const SoundSource& source)
    51 {
    52   this->setClassID(CL_SOUND_SOURCE, "SoundSource");
    53 
    54   // adding the Source to the SourcesList of the SoundEngine
    55   this->buffer = source.buffer;
    56   this->sourceNode = source.sourceNode;
    57   this->resident = source.resident;
    58 
    59   this->sourceID = 0;
    60   if (source.bPlay == true)
    61   {
    62     this->bPlay = true;
    63     SoundEngine::getInstance()->popALSource(this->sourceID);
    64   }
    65   else
    66     this->bPlay = false;
    67 }
    68 
    69 
    70 /**
    71  * @brief paste a copy of the source into this Source.
    72  * @param source the SoundSource to paste into this one.
    73  * @returns a Reference to this Source.
    74  *
    75  */
    76 SoundSource& SoundSource::operator=(const SoundSource& source)
    77 {
    78   this->buffer = source.buffer;
    79   this->sourceNode = sourceNode;
    80   this->resident = source.resident;
    81 
    82   if (source.bPlay)
    83     this->play();
    84   else
    85     this->stop();
    86 }
    87 
    88 
    89 /**
    90  * @brief compares two Sources with each other.
    91  * @param source the Source to compare against this One.
    92  * Two Sources are the same, if the PNodes match, and the Sound Played are the same.
    93  * The alSource must not match, because no two Sources can have the same alSource.
    94  */
    95 bool SoundSource::operator==(const SoundSource& source)
    96 {
    97   return (this->buffer == source.buffer &&
    98           this->bPlay == source.bPlay &&
    99           this->sourceNode == source.sourceNode);
    100 }
    101 
    102 
    103 /**
    104  * @brief deletes a SoundSource
    105  */
    106 SoundSource::~SoundSource()
    107 {
    108   this->stop();
    109   if (this->sourceID != 0)
    110     SoundEngine::getInstance()->pushALSource(this->sourceID);
    111 }
    112 
    113 
    114 /**
    115  * @brief Plays back a SoundSource
    116  */
    117 void SoundSource::play()
    118 {
    119   if (this->buffer && this->retrieveSource())
    120   {
    121     if (this->bPlay)
    122       alSourceStop(this->sourceID);
    123     alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID());
    124       alSourcePlay(this->sourceID);
    125 
    126     if (DEBUG >= 3)
    127       SoundEngine::checkError("Play Source", __LINE__);
    128     this->bPlay = true;
    129   }
    130 }
    131 
    132 
    133 /**
    134  * @brief Plays back buffer on this Source
    135  * @param buffer the buffer to play back on this Source
    136  */
    137 void SoundSource::play(const SoundBuffer* buffer)
    138 {
    139   if (!this->retrieveSource())
    140   {
    141     PRINTF(3)("No more Free sources (You might consider raising the Source-Count).\n");
    142     return;
    143   }
    144 
    145   alSourceStop(this->sourceID);
    146   alSourcei (this->sourceID, AL_BUFFER, buffer->getID());
    147   alSourcePlay(this->sourceID);
    148 
    149   if (unlikely(this->buffer != NULL))
    150     alSourcei (this->sourceID, AL_BUFFER, this->buffer->getID());
    151   this->bPlay = true;
    152 
    153   if (DEBUG >= 3)
    154     SoundEngine::checkError("Play Source", __LINE__);
    155 }
    156 
    157 
    158 /**
    159  * @brief Stops playback of a SoundSource
    160  */
    161 void SoundSource::stop()
    162 {
    163   this->bPlay = false;
    164   if (this->sourceID != 0)
    165   {
    166     alSourceStop(this->sourceID);
    167     if (DEBUG >= 3)
    168       SoundEngine::checkError("StopSource", __LINE__);
    169     alSourcei(this->sourceID, AL_BUFFER, 0);
    170     if (!this->resident)
    171       SoundEngine::getInstance()->pushALSource(this->sourceID);
    172     this->sourceID = 0;
    173   }
    174 }
    175 
    176 
    177 /**
    178  * @brief Pauses Playback of a SoundSource
    179  */
    180 void SoundSource::pause()
    181 {
    182   alSourcePause(this->sourceID);
    183   if (DEBUG >= 3)
    184     SoundEngine::checkError("Pause Source", __LINE__);
    185 }
    186 
    187 
    188 /**
    189  * @brief Rewinds Playback of a SoundSource
    190  */
    191 void SoundSource::rewind()
    192 {
    193   alSourceRewind(this->sourceID);
    194 
    195   if (DEBUG >= 3)
    196     SoundEngine::checkError("Rewind Source", __LINE__);
    197 }
    198 
    199 
    200 /**
    201  * @brief sets the RolloffFactor of the Sound emitted from the SoundSource
    202  * @param rolloffFactor The Factor described
    203  *
    204  * this tells openAL how fast the Sounds decay outward from the Source
    205  */
    206 void SoundSource::setRolloffFactor(ALfloat rolloffFactor)
    207 {
    208   alSourcef(this->sourceID, AL_ROLLOFF_FACTOR, rolloffFactor);
    209 
    210   if (DEBUG >= 3)
    211     SoundEngine::checkError("Set Source Rolloff-factor", __LINE__);
    212 }
    213 
    214 
    215 /**
    216  * @brief sets the Positional this Source should be attached to.
    217  * @param sourceNode the Source this is attached to.
    218  * If sourceNode == NULL then the Source will be centered, and Audio will be played on all channels.
    219  */
    220 void SoundSource::setSourceNode(const PNode* sourceNode)
    221 {
    222   this->sourceNode = sourceNode;
    223 }
    224 
    225 /**
    226  * @brief retrieve a Source.
    227  */
    228 bool SoundSource::retrieveSource()
    229 {
    230   if (this->sourceID != 0)
    231     return true;
    232   else
    233   {
    234     SoundEngine::getInstance()->popALSource(this->sourceID);
    235     if (this->sourceID != 0)
    236     {
    237       if (unlikely(this->sourceNode == NULL))
    238         resetSource(this->sourceID);
    239       return true;
    240     }
    241   }
    242   return false;
    243 }
    244 
    245 
    246 /**
    247  * @brief reset an alSource to its default Values.
    248  */
    249 void SoundSource::resetSource(ALuint sourceID)
    250 {
    251   alSource3f(sourceID, AL_POSITION,        0.0, 0.0, 0.0);
    252   alSource3f(sourceID, AL_VELOCITY,        0.0, 0.0, 0.0);
    253   alSource3f(sourceID, AL_DIRECTION,       0.0, 0.0, 0.0);
    254   alSourcef (sourceID, AL_ROLLOFF_FACTOR,  0.0          );
    255   //alSourcei (sourceID, AL_SOURCE_RELATIVE, AL_TRUE      );
    256   alSourcef (sourceID, AL_GAIN,            SoundEngine::getInstance()->getEffectsVolume());
    257 }
  • trunk/src/lib/sound/sound_source.h

    r7317 r7460  
    1111
    1212// FORWARD DECLARATION
    13 class SoundBuffer;
    1413class PNode;
    15 
    16 //! A class that represents a SoundSource
    17 class SoundSource : public BaseObject
     14namespace OrxSound
    1815{
     16  class SoundBuffer;
     17  //! A class that represents a SoundSource
     18  class SoundSource : public BaseObject
     19  {
    1920  public:
    2021    SoundSource(const PNode* sourceNode = NULL, const SoundBuffer* buffer = NULL);
     
    2526    virtual ~SoundSource();
    2627
    27   // user interaction
     28    // user interaction
    2829    void play();
    2930    void play(const SoundBuffer* buffer);
     
    3233    void rewind();
    3334
    34   // development functions
     35    // development functions
    3536    /** @returns The ID of this Source */
    3637    inline ALuint getID() const { return this->sourceID; };
     
    6061    const SoundBuffer*     buffer;                //!< The buffer to play in this source.
    6162    const PNode*           sourceNode;            //!< The SourceNode representing the position/velocity... of this source.
    62 };
     63  };
     64}
    6365#endif /* _SOUND_SOURCE_H */
  • trunk/src/lib/util/loading/resource_manager.cc

    r7225 r7460  
    434434    case WAV:
    435435      if(isFile(fullName))
    436         tmpResource->pointer = new SoundBuffer(fullName);
     436        tmpResource->pointer = new OrxSound::SoundBuffer(fullName);
    437437      break;
    438438    case OGG:
    439439      if (isFile(fullName))
    440         tmpResource->pointer = new OggPlayer(fullName);
     440        tmpResource->pointer = new OrxSound::OggPlayer(fullName);
    441441      break;
    442442#endif /* NO_AUDIO */
Note: See TracChangeset for help on using the changeset viewer.