Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/sound/ogg_player.cc @ 7301

Last change on this file since 7301 was 7301, checked in by bensch, 18 years ago

less debug, and music should rewind now

File size: 9.0 KB
RevLine 
[4750]1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15
16   -------------------------------------------------------------------
17   The source of this file comes stright from http://www.devmaster.net
18   Thanks a lot for the nice work, and the easy portability to our Project.
19*/
20
[5283]21#include <iostream>
22
[4750]23#include "ogg_player.h"
24
[4985]25#include "sound_engine.h"
26
[4750]27#include "debug.h"
28
[4961]29/**
30 * initializes an Ogg-player from a file
31 * @param fileName the file to load
32 */
[7221]33OggPlayer::OggPlayer(const std::string& fileName)
[4750]34{
[4961]35  this->setClassID(CL_SOUND_OGG_PLAYER, "OggPlayer");
[6827]36
[7293]37  this->state = None;
38
[6827]39  this->source = 0;
[6842]40  this->buffers[0] = 0;
41  this->buffers[1] = 0;
[6827]42
[7221]43  if (!fileName.empty())
[4961]44  {
[6842]45    if (this->open(fileName))
46      this->setName(fileName);
[4961]47  }
48}
49
[6987]50OggPlayer::~OggPlayer()
[6872]51{
[7290]52  this->release();
[6872]53}
54
[4961]55/**
56 * opens a file for playback
57 * @param fileName the file to open
58 */
[7221]59bool OggPlayer::open(const std::string& fileName)
[4961]60{
[7296]61  // release old Ogg-File
62  if (this->state & FileOpened)
63    this->release();
[7293]64
65  // allocating Buffers
[6842]66  if (this->buffers[0] == 0)
67    alGenBuffers(2, this->buffers);
68  SoundEngine::checkError("Allocating Buffers", __LINE__);
[7293]69  if (this->buffers[0] != 0 && this->buffers[1] != 0)
70    state |= BuffersAllocated;
[7301]71  else
72  {
[7293]73    PRINTF(2)("Unable to allocate al-Buffers\n");
74    this->release();
75    return false;
76  }
77  // allocating source
[6842]78  if (this->source == 0)
79    SoundEngine::getInstance()->popALSource(this->source);
[7293]80  if (this->source != 0)
81    state |= SourceAllocated;
82  else
[6842]83  {
[7296]84    PRINTF(2)("No more Sources Availiable (maybe you should consider raising the source-count.)\n");
[7293]85    this->release();
[6842]86    return false;
87  }
88
[7293]89  // opening the FILE;
[6828]90  int result;
[7221]91  if(!(oggFile = fopen(fileName.c_str(), "rb")))
[6872]92  {
[6828]93    PRINTF(2)("Could not open Ogg file.");
[7293]94    this->release();
[6872]95    return false;
96  }
[7293]97  // reading the Stream.
[6828]98  if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
99  {
100    PRINTF(2)("Could not open Ogg stream. %s", errorString(result));
[6872]101    fclose(oggFile);
[7293]102    this->release();
[6872]103    return false;
[6828]104  }
[7299]105  this->state |= FileOpened;
[4750]106
[7293]107  // acquiring the vorbis-properties.
[6828]108  vorbisInfo = ov_info(&oggStream, -1);
109  vorbisComment = ov_comment(&oggStream, -1);
[7299]110
[6828]111  if(vorbisInfo->channels == 1)
112    format = AL_FORMAT_MONO16;
113  else
114    format = AL_FORMAT_STEREO16;
[4750]115
[7293]116  // setting the Source Properties.
[6828]117  alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
118  alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
119  alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
120  alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
121  alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
122  alSourcef (source, AL_GAIN,            SoundEngine::getInstance()->getMusicVolume());
[7296]123  SoundEngine::checkError("OggPlayer::open()::SetSourceProperties", __LINE__);
[6842]124
125  return true;
[4750]126}
127
[4961]128/**
[7296]129 * @brief releases a stream
[4961]130 */
131void OggPlayer::release()
[4750]132{
[7293]133  if (this->state & SourceAllocated)
134  {
135    assert(alIsSource(this->source));
136    if (this->state & Playing);
137    {
138      alSourceStop(source);
139      SoundEngine::checkError("OggPlayer::release()::alSourceStop", __LINE__);
140      this->state & !Playing;
141    }
142    empty();
[7297]143    alSourcei(this->source, AL_BUFFER, 0);
144    SoundEngine::getInstance()->pushALSource(this->source);
[7293]145    this->source = 0;
146    this->state &= !SourceAllocated;
147  }
148  if (this->state & BuffersAllocated)
149  {
150    assert (this->buffers[0] != 0 && this->buffers[1] != 0);
151    alDeleteBuffers(2, buffers);
152    SoundEngine::checkError("OggPlayer::release()::alDeleteBuffers", __LINE__);
153    this->buffers[0] = 0;
154    this->buffers[1] = 0;
155    this->state &= !BuffersAllocated;
156  }
[4750]157
[7293]158  if (this->state & FileOpened)
159  {
160    ov_clear(&oggStream);
161    this->state &= ! FileOpened;
162  }
[4750]163}
164
165
[4961]166/**
167 * plays back the sound
168 * @return true if running, false otherwise
169 */
170bool OggPlayer::playback()
[4750]171{
[7293]172  if (!(this->state & FileOpened))
[6842]173    return false;
174
[6828]175  if(playing())
176    return true;
[7294]177  this->state |= Playing;
[4750]178
[7296]179  if(!this->stream(this->buffers[0]) || !this->stream(this->buffers[1]))
[6828]180    return false;
[4750]181
[7292]182  alSourceQueueBuffers(this->source, 2, this->buffers);
183  if (DEBUG >= 3)
184    SoundEngine::checkError("OggPlayer::playback()::alSourceQueueBuffers", __LINE__);
[7296]185  if (!alIsBuffer(this->buffers[0])) printf("AHA0\n");
186  if (!alIsBuffer(this->buffers[1])) printf("AHA1\n");
187
188  if (!alIsSource(this->source)) printf("AHA2\n");
189  SoundEngine::checkError("SKJFLKSDJF",__LINE__);
190
[7292]191  alSourcePlay(this->source);
192  if (DEBUG >= 3)
193    SoundEngine::checkError("OggPlayer::playback()::alSourcePlay", __LINE__);
[6828]194  return true;
[4750]195}
196
[4961]197/**
198 *
199 * @returns true if the file is playing
200 */
201bool OggPlayer::playing()
[4750]202{
[7293]203  if (!(this->state & FileOpened))
[6842]204    return false;
[6828]205  ALenum state;
[4750]206
[6828]207  alGetSourcei(this->source, AL_SOURCE_STATE, &state);
[4750]208
[6828]209  return (state == AL_PLAYING);
[4750]210}
211
[4961]212/**
213 * updates the stream, this has to be done every few parts of a second, for sound-consistency
214 * @returns true, if the Sound is playing flawlessly
215 */
216bool OggPlayer::update()
[4750]217{
[7293]218  if (unlikely(!(this->state & Playing)))
[6842]219    return false;
220
[6828]221  int processed;
222  bool active = true;
[4750]223
[6828]224  alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
[7292]225  if (DEBUG >= 3)
226    SoundEngine::checkError("OggPlayer::update()::alGetSourceI", __LINE__);
[4750]227
[6828]228  while(processed--)
229  {
230    ALuint buffer;
[4750]231
[6828]232    alSourceUnqueueBuffers(source, 1, &buffer);
[7292]233    if (DEBUG >= 3)
234      SoundEngine::checkError("OggPlayer::update()::unqueue", __LINE__);
[4750]235
[6828]236    active = stream(buffer);
[4750]237
[6828]238    alSourceQueueBuffers(source, 1, &buffer);
[7292]239    if (DEBUG >= 3)
240      SoundEngine::checkError("OggPlayer::update()::queue", __LINE__);
[6828]241  }
[4750]242
[6828]243  return active;
[4750]244}
245
[4961]246/**
247 * gets a new Stream from buffer
248 * @param buffer the buffer to get the stream from
249 * @return true, if everything worked as planed
250 */
251bool OggPlayer::stream(ALuint buffer)
[4750]252{
[7293]253  if (unlikely(!(this->state & Playing)))
[6987]254    return false;
[7301]255  char pcm[OGG_PLAYER_BUFFER_SIZE];
[6828]256  int  size = 0;
257  int  section;
258  int  result;
[4750]259
[7301]260  while(size < OGG_PLAYER_BUFFER_SIZE)
[6828]261  {
[7301]262    result = ov_read(&this->oggStream, pcm + size, OGG_PLAYER_BUFFER_SIZE - size, 0, 2, 1, &section);
[4750]263
[6828]264    if(result > 0)
265      size += result;
[7301]266    else if(result < 0)
267      throw errorString(result);
268    else /* eof */
269      ov_time_seek(&this->oggStream, 0.0);
[6828]270  }
[4750]271
[6828]272  if(size == 0)
273    return false;
[4750]274
[6828]275  alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
[7292]276  if (DEBUG >= 3)
[7296]277    SoundEngine::checkError("OggPlayer::stream()::BUFFER", __LINE__);
[4750]278
[6828]279  return true;
[4750]280}
281
282
[4961]283/**
284 * empties the buffers
285 */
286void OggPlayer::empty()
[4750]287{
[6828]288  int queued;
[4750]289
[6828]290  alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
[4750]291
[6828]292  while(queued--)
293  {
294    ALuint buffer;
[4750]295
[6828]296    alSourceUnqueueBuffers(source, 1, &buffer);
[7292]297    SoundEngine::checkError("OggPlayer::empty()::unqueue Buffers", __LINE__);
[6828]298  }
[4750]299}
300
301
[4961]302/**
[6828]303 * displays some info about the ogg-file
304 */
305void OggPlayer::debug()
306{
307  cout
[6842]308  << "version         " << vorbisInfo->version         << "\n"
309  << "channels        " << vorbisInfo->channels        << "\n"
310  << "rate (hz)       " << vorbisInfo->rate            << "\n"
311  << "bitrate upper   " << vorbisInfo->bitrate_upper   << "\n"
312  << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n"
313  << "bitrate lower   " << vorbisInfo->bitrate_lower   << "\n"
314  << "bitrate window  " << vorbisInfo->bitrate_window  << "\n"
315  << "\n"
316  << "vendor " << vorbisComment->vendor << "\n";
[6828]317
318  for(int i = 0; i < vorbisComment->comments; i++)
319    cout << "   " << vorbisComment->user_comments[i] << "\n";
320
321  cout << endl;
322}
323
324
[7295]325void OggPlayer::printState()
326{
327  PRINTF(0)("OggPlayer is in the following States: ");
328  if (this->state & FileOpened)
[7301]329    PRINT(0)("FileOpened ");
[7295]330  if (this->state & SourceAllocated)
331    PRINT(0)("SourceAllocated ");
332  if (this->state & BuffersAllocated)
333    PRINT(0)("BuffersAllocated ");
334  if (this->state & Stopped)
335    PRINT(0)("Stopped ");
336  if (this->state & Playing)
337    PRINT(0)("Playing ");
338  if (this->state & Paused)
339    PRINT(0)("Paused ");
340  if (this->state & Error)
341    PRINT(0)("Error ");
342  PRINT(0)("\n");
343}
344
[6828]345/**
[4961]346 * returns errors
347 * @param code the error-code
348 * @return the error as a String
349 */
350const char* OggPlayer::errorString(int code)
[4750]351{
[6828]352  switch(code)
353  {
354    case OV_EREAD:
355      return ("Read from media.");
356    case OV_ENOTVORBIS:
357      return ("Not Vorbis data.");
358    case OV_EVERSION:
359      return ("Vorbis version mismatch.");
360    case OV_EBADHEADER:
361      return ("Invalid Vorbis header.");
362    case OV_EFAULT:
363      return ("Internal logic fault (bug or heap/stack corruption.");
364    default:
365      return ("Unknown Ogg error.");
366  }
[4750]367}
[7295]368
Note: See TracBrowser for help on using the repository browser.