Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

nicer code :)

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