Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

minor

File size: 8.1 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{
[7293]61  // release old State
62  if (state & FileOpened)
63    release();
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;
71  else  {
72    PRINTF(2)("Unable to allocate al-Buffers\n");
73    this->release();
74    return false;
75  }
76  // allocating source
[6842]77  if (this->source == 0)
78    SoundEngine::getInstance()->popALSource(this->source);
[7293]79  if (this->source != 0)
80    state |= SourceAllocated;
81  else
[6842]82  {
[7293]83    PRINTF(2)("No more Sources Availiable (maybe you should consider raising the source-count\n");
84    this->release();
[6842]85    return false;
86  }
87
[7293]88  // opening the FILE;
[6828]89  int result;
[7221]90  if(!(oggFile = fopen(fileName.c_str(), "rb")))
[6872]91  {
[6828]92    PRINTF(2)("Could not open Ogg file.");
[7293]93    this->release();
[6872]94    return false;
95  }
[7293]96  // reading the Stream.
[6828]97  if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
98  {
99    PRINTF(2)("Could not open Ogg stream. %s", errorString(result));
[6872]100    fclose(oggFile);
[7293]101    this->release();
[6872]102    return false;
[6828]103  }
[4750]104
[7293]105  // acquiring the vorbis-properties.
[6828]106  vorbisInfo = ov_info(&oggStream, -1);
107  vorbisComment = ov_comment(&oggStream, -1);
[7293]108  this->state |= FileOpened;
[6828]109  if(vorbisInfo->channels == 1)
110    format = AL_FORMAT_MONO16;
111  else
112    format = AL_FORMAT_STEREO16;
[4750]113
[7293]114  // setting the Source Properties.
[6828]115  alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
116  alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
117  alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
118  alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
119  alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
120  alSourcef (source, AL_GAIN,            SoundEngine::getInstance()->getMusicVolume());
[7292]121  SoundEngine::checkError("OggPlayer::SetSourceProperties", __LINE__);
[6842]122
123  return true;
[4750]124}
125
[4961]126/**
127 * releases a stream
128 */
129void OggPlayer::release()
[4750]130{
[7293]131  if (this->state & SourceAllocated)
132  {
133    assert(alIsSource(this->source));
134    if (this->state & Playing);
135    {
136      alSourceStop(source);
137      SoundEngine::checkError("OggPlayer::release()::alSourceStop", __LINE__);
138      this->state & !Playing;
139    }
140    empty();
141    SoundEngine::getInstance()->pushALSource(source);
142    this->source = 0;
143    this->state &= !SourceAllocated;
144  }
145  if (this->state & BuffersAllocated)
146  {
147    assert (this->buffers[0] != 0 && this->buffers[1] != 0);
148    alDeleteBuffers(2, buffers);
149    SoundEngine::checkError("OggPlayer::release()::alDeleteBuffers", __LINE__);
150    this->buffers[0] = 0;
151    this->buffers[1] = 0;
152    this->state &= !BuffersAllocated;
153  }
[4750]154
[7293]155  if (this->state & FileOpened)
156  {
157    ov_clear(&oggStream);
158    this->state &= ! FileOpened;
159  }
[4750]160}
161
162
[4961]163/**
164 * plays back the sound
165 * @return true if running, false otherwise
166 */
167bool OggPlayer::playback()
[4750]168{
[7293]169  if (!(this->state & FileOpened))
[6842]170    return false;
171
[6828]172  if(playing())
173    return true;
[7294]174  this->state |= Playing;
[4750]175
[7292]176  if(!stream(buffers[0]) || !stream(buffers[1]))
[6828]177    return false;
[4750]178
[7292]179  alSourceQueueBuffers(this->source, 2, this->buffers);
180  if (DEBUG >= 3)
181    SoundEngine::checkError("OggPlayer::playback()::alSourceQueueBuffers", __LINE__);
182  alSourcePlay(this->source);
183  if (DEBUG >= 3)
184    SoundEngine::checkError("OggPlayer::playback()::alSourcePlay", __LINE__);
[6828]185  return true;
[4750]186}
187
[4961]188/**
189 *
190 * @returns true if the file is playing
191 */
192bool OggPlayer::playing()
[4750]193{
[7293]194  if (!(this->state & FileOpened))
[6842]195    return false;
[6828]196  ALenum state;
[4750]197
[6828]198  alGetSourcei(this->source, AL_SOURCE_STATE, &state);
[4750]199
[6828]200  return (state == AL_PLAYING);
[4750]201}
202
[4961]203/**
204 * updates the stream, this has to be done every few parts of a second, for sound-consistency
205 * @returns true, if the Sound is playing flawlessly
206 */
207bool OggPlayer::update()
[4750]208{
[7293]209  if (unlikely(!(this->state & Playing)))
[6842]210    return false;
211
[6828]212  int processed;
213  bool active = true;
[4750]214
[6828]215  alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
[7292]216  if (DEBUG >= 3)
217    SoundEngine::checkError("OggPlayer::update()::alGetSourceI", __LINE__);
[4750]218
[6828]219  while(processed--)
220  {
221    ALuint buffer;
[4750]222
[6828]223    alSourceUnqueueBuffers(source, 1, &buffer);
[7292]224    if (DEBUG >= 3)
225      SoundEngine::checkError("OggPlayer::update()::unqueue", __LINE__);
[4750]226
[6828]227    active = stream(buffer);
[4750]228
[6828]229    alSourceQueueBuffers(source, 1, &buffer);
[7292]230    if (DEBUG >= 3)
231      SoundEngine::checkError("OggPlayer::update()::queue", __LINE__);
[6828]232  }
[4750]233
[6828]234  return active;
[4750]235}
236
[4961]237/**
238 * gets a new Stream from buffer
239 * @param buffer the buffer to get the stream from
240 * @return true, if everything worked as planed
241 */
242bool OggPlayer::stream(ALuint buffer)
[4750]243{
[7293]244  if (unlikely(!(this->state & Playing)))
[6987]245    return false;
[6828]246  char pcm[BUFFER_SIZE];
247  int  size = 0;
248  int  section;
249  int  result;
[4750]250
[6828]251  while(size < BUFFER_SIZE)
252  {
253    result = ov_read(&oggStream, pcm + size, BUFFER_SIZE - size, 0, 2, 1, &section);
[4750]254
[6828]255    if(result > 0)
256      size += result;
257    else
258      if(result < 0)
259        throw errorString(result);
260      else
261        break;
262  }
[4750]263
[6828]264  if(size == 0)
265    return false;
[4750]266
[6828]267  alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
[7292]268  if (DEBUG >= 3)
269    SoundEngine::checkError("OggPlayer::playback()::BUFFER", __LINE__);
[4750]270
[6828]271  return true;
[4750]272}
273
274
[4961]275/**
276 * empties the buffers
277 */
278void OggPlayer::empty()
[4750]279{
[6828]280  int queued;
[4750]281
[6828]282  alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
[4750]283
[6828]284  while(queued--)
285  {
286    ALuint buffer;
[4750]287
[6828]288    alSourceUnqueueBuffers(source, 1, &buffer);
[7292]289    SoundEngine::checkError("OggPlayer::empty()::unqueue Buffers", __LINE__);
[6828]290  }
[4750]291}
292
293
[4961]294/**
[6828]295 * displays some info about the ogg-file
296 */
297void OggPlayer::debug()
298{
299  cout
[6842]300  << "version         " << vorbisInfo->version         << "\n"
301  << "channels        " << vorbisInfo->channels        << "\n"
302  << "rate (hz)       " << vorbisInfo->rate            << "\n"
303  << "bitrate upper   " << vorbisInfo->bitrate_upper   << "\n"
304  << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n"
305  << "bitrate lower   " << vorbisInfo->bitrate_lower   << "\n"
306  << "bitrate window  " << vorbisInfo->bitrate_window  << "\n"
307  << "\n"
308  << "vendor " << vorbisComment->vendor << "\n";
[6828]309
310  for(int i = 0; i < vorbisComment->comments; i++)
311    cout << "   " << vorbisComment->user_comments[i] << "\n";
312
313  cout << endl;
314}
315
316
317/**
[4961]318 * returns errors
319 * @param code the error-code
320 * @return the error as a String
321 */
322const char* OggPlayer::errorString(int code)
[4750]323{
[6828]324  switch(code)
325  {
326    case OV_EREAD:
327      return ("Read from media.");
328    case OV_ENOTVORBIS:
329      return ("Not Vorbis data.");
330    case OV_EVERSION:
331      return ("Vorbis version mismatch.");
332    case OV_EBADHEADER:
333      return ("Invalid Vorbis header.");
334    case OV_EFAULT:
335      return ("Internal logic fault (bug or heap/stack corruption.");
336    default:
337      return ("Unknown Ogg error.");
338  }
[4750]339}
Note: See TracBrowser for help on using the repository browser.