Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: jump to Function in Music (should work)

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