Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

trunk: Music plays

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