Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6846 was 6842, checked in by bensch, 19 years ago

orxonox/trunk: ogg-player does not segfault, when no sources are availiable

File size: 6.3 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 */
33OggPlayer::OggPlayer(const char* fileName)
[4750]34{
[4961]35  this->setClassID(CL_SOUND_OGG_PLAYER, "OggPlayer");
[6827]36
[6842]37  this->trackLoaded = false;
[6827]38  this->source = 0;
[6842]39  this->buffers[0] = 0;
40  this->buffers[1] = 0;
[6827]41
[4961]42  if (fileName != NULL)
43  {
[6842]44    if (this->open(fileName))
45      this->setName(fileName);
[4961]46  }
47}
48
49/**
50 * opens a file for playback
51 * @param fileName the file to open
52 */
[6842]53bool OggPlayer::open(const char* fileName)
[4961]54{
[6842]55  if (this->buffers[0] == 0)
56    alGenBuffers(2, this->buffers);
57  SoundEngine::checkError("Allocating Buffers", __LINE__);
58
59  if (this->source == 0)
60    SoundEngine::getInstance()->popALSource(this->source);
61  if (this->source == 0)
62  {
63    this->trackLoaded = false;
64    return false;
65  }
66  printf("OK\n");
67
[6828]68  int result;
[4750]69
[6828]70  if(!(oggFile = fopen(fileName, "rb")))
71    PRINTF(2)("Could not open Ogg file.");
[4750]72
[6828]73  if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
74  {
75    fclose(oggFile);
[4750]76
[6828]77    PRINTF(2)("Could not open Ogg stream. %s", errorString(result));
78  }
[4750]79
[6828]80  vorbisInfo = ov_info(&oggStream, -1);
81  vorbisComment = ov_comment(&oggStream, -1);
[4750]82
[6828]83  if(vorbisInfo->channels == 1)
84    format = AL_FORMAT_MONO16;
85  else
86    format = AL_FORMAT_STEREO16;
[4750]87
[6828]88  alSource3f(source, AL_POSITION,        0.0, 0.0, 0.0);
89  alSource3f(source, AL_VELOCITY,        0.0, 0.0, 0.0);
90  alSource3f(source, AL_DIRECTION,       0.0, 0.0, 0.0);
91  alSourcef (source, AL_ROLLOFF_FACTOR,  0.0          );
92  alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE      );
93  alSourcef (source, AL_GAIN,            SoundEngine::getInstance()->getMusicVolume());
[6842]94
95  this->trackLoaded = true;
96  return true;
[4750]97}
98
[4961]99/**
100 * releases a stream
101 */
102void OggPlayer::release()
[4750]103{
[6828]104  alSourceStop(source);
105  empty();
106  SoundEngine::getInstance()->pushALSource(source);
[6842]107  this->source = 0;
[6828]108  check();
[6842]109  alDeleteBuffers(2, buffers);
110  this->buffers[0] = 0;
111  this->buffers[1] = 0;
[6828]112  check();
[4750]113
[6828]114  ov_clear(&oggStream);
[6842]115  this->trackLoaded = false;
[4750]116}
117
118
[4961]119/**
120 * plays back the sound
121 * @return true if running, false otherwise
122 */
123bool OggPlayer::playback()
[4750]124{
[6842]125  if (!this->trackLoaded)
126    return false;
127
[6828]128  if(playing())
129    return true;
[4750]130
[6828]131  if(!stream(buffers[0]))
132    return false;
[4750]133
[6828]134  if(!stream(buffers[1]))
135    return false;
[4750]136
[6828]137  alSourceQueueBuffers(source, 2, buffers);
138  alSourcePlay(source);
[4750]139
[6828]140  return true;
[4750]141}
142
[4961]143/**
144 *
145 * @returns true if the file is playing
146 */
147bool OggPlayer::playing()
[4750]148{
[6842]149  if (!this->trackLoaded)
150    return false;
[6828]151  ALenum state;
[4750]152
[6828]153  alGetSourcei(this->source, AL_SOURCE_STATE, &state);
[4750]154
[6828]155  return (state == AL_PLAYING);
[4750]156}
157
[4961]158/**
159 * updates the stream, this has to be done every few parts of a second, for sound-consistency
160 * @returns true, if the Sound is playing flawlessly
161 */
162bool OggPlayer::update()
[4750]163{
[6842]164  if (!this->trackLoaded)
165    return false;
166
[6828]167  int processed;
168  bool active = true;
[4750]169
[6828]170  alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
[4750]171
[6828]172  while(processed--)
173  {
174    ALuint buffer;
[4750]175
[6828]176    alSourceUnqueueBuffers(source, 1, &buffer);
177    check();
[4750]178
[6828]179    active = stream(buffer);
[4750]180
[6828]181    alSourceQueueBuffers(source, 1, &buffer);
182    check();
183  }
[4750]184
[6828]185  return active;
[4750]186}
187
[4961]188/**
189 * gets a new Stream from buffer
190 * @param buffer the buffer to get the stream from
191 * @return true, if everything worked as planed
192 */
193bool OggPlayer::stream(ALuint buffer)
[4750]194{
[6828]195  char pcm[BUFFER_SIZE];
196  int  size = 0;
197  int  section;
198  int  result;
[4750]199
[6828]200  while(size < BUFFER_SIZE)
201  {
202    result = ov_read(&oggStream, pcm + size, BUFFER_SIZE - size, 0, 2, 1, &section);
[4750]203
[6828]204    if(result > 0)
205      size += result;
206    else
207      if(result < 0)
208        throw errorString(result);
209      else
210        break;
211  }
[4750]212
[6828]213  if(size == 0)
214    return false;
[4750]215
[6828]216  alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
217  check();
[4750]218
[6828]219  return true;
[4750]220}
221
222
[4961]223/**
224 * empties the buffers
225 */
226void OggPlayer::empty()
[4750]227{
[6828]228  int queued;
[4750]229
[6828]230  alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
[4750]231
[6828]232  while(queued--)
233  {
234    ALuint buffer;
[4750]235
[6828]236    alSourceUnqueueBuffers(source, 1, &buffer);
237    check();
238  }
[4750]239}
240
[4961]241/**
242 * checks for errors
243 */
244void OggPlayer::check()
[4750]245{
[6828]246  int error = alGetError();
[4750]247
[6828]248  if(error != AL_NO_ERROR)
249    PRINTF(2)("OpenAL error was raised.");
[4750]250}
251
[6828]252
253
[4961]254/**
[6828]255 * displays some info about the ogg-file
256 */
257void OggPlayer::debug()
258{
259  cout
[6842]260  << "version         " << vorbisInfo->version         << "\n"
261  << "channels        " << vorbisInfo->channels        << "\n"
262  << "rate (hz)       " << vorbisInfo->rate            << "\n"
263  << "bitrate upper   " << vorbisInfo->bitrate_upper   << "\n"
264  << "bitrate nominal " << vorbisInfo->bitrate_nominal << "\n"
265  << "bitrate lower   " << vorbisInfo->bitrate_lower   << "\n"
266  << "bitrate window  " << vorbisInfo->bitrate_window  << "\n"
267  << "\n"
268  << "vendor " << vorbisComment->vendor << "\n";
[6828]269
270  for(int i = 0; i < vorbisComment->comments; i++)
271    cout << "   " << vorbisComment->user_comments[i] << "\n";
272
273  cout << endl;
274}
275
276
277/**
[4961]278 * returns errors
279 * @param code the error-code
280 * @return the error as a String
281 */
282const char* OggPlayer::errorString(int code)
[4750]283{
[6828]284  switch(code)
285  {
286    case OV_EREAD:
287      return ("Read from media.");
288    case OV_ENOTVORBIS:
289      return ("Not Vorbis data.");
290    case OV_EVERSION:
291      return ("Vorbis version mismatch.");
292    case OV_EBADHEADER:
293      return ("Invalid Vorbis header.");
294    case OV_EFAULT:
295      return ("Internal logic fault (bug or heap/stack corruption.");
296    default:
297      return ("Unknown Ogg error.");
298  }
[4750]299}
Note: See TracBrowser for help on using the repository browser.