Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 7460 in orxonox.OLD for trunk/src/lib/sound/ogg_player.cc


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

orxonox/trunk: Namespaces for sound

File:
1 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 
Note: See TracChangeset for help on using the changeset viewer.