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
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
37  this->source = 0;
38
[4961]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{
[6828]52  int result;
[4750]53
[6828]54  if(!(oggFile = fopen(fileName, "rb")))
55    PRINTF(2)("Could not open Ogg file.");
[4750]56
[6828]57  if((result = ov_open(oggFile, &oggStream, NULL, 0)) < 0)
58  {
59    fclose(oggFile);
[4750]60
[6828]61    PRINTF(2)("Could not open Ogg stream. %s", errorString(result));
62  }
[4750]63
[6828]64  vorbisInfo = ov_info(&oggStream, -1);
65  vorbisComment = ov_comment(&oggStream, -1);
[4750]66
[6828]67  if(vorbisInfo->channels == 1)
68    format = AL_FORMAT_MONO16;
69  else
70    format = AL_FORMAT_STEREO16;
[4750]71
72
[6828]73  alGenBuffers(2, buffers);
74  check();
75  SoundEngine::getInstance()->popALSource(this->source);
76  check();
[4750]77
[6828]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());
[4750]84}
85
[4961]86/**
87 * releases a stream
88 */
89void OggPlayer::release()
[4750]90{
[6828]91  alSourceStop(source);
92  empty();
93  SoundEngine::getInstance()->pushALSource(source);
94  check();
95  alDeleteBuffers(1, buffers);
96  check();
[4750]97
[6828]98  ov_clear(&oggStream);
[4750]99}
100
101
[4961]102/**
103 * plays back the sound
104 * @return true if running, false otherwise
105 */
106bool OggPlayer::playback()
[4750]107{
[6828]108  if(playing())
109    return true;
[4750]110
[6828]111  if(!stream(buffers[0]))
112    return false;
[4750]113
[6828]114  if(!stream(buffers[1]))
115    return false;
[4750]116
[6828]117  alSourceQueueBuffers(source, 2, buffers);
118  alSourcePlay(source);
[4750]119
[6828]120  return true;
[4750]121}
122
[4961]123/**
124 *
125 * @returns true if the file is playing
126 */
127bool OggPlayer::playing()
[4750]128{
[6828]129  ALenum state;
[4750]130
[6828]131  alGetSourcei(this->source, AL_SOURCE_STATE, &state);
[4750]132
[6828]133  return (state == AL_PLAYING);
[4750]134}
135
[4961]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()
[4750]141{
[6828]142  int processed;
143  bool active = true;
[4750]144
[6828]145  alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
[4750]146
[6828]147  while(processed--)
148  {
149    ALuint buffer;
[4750]150
[6828]151    alSourceUnqueueBuffers(source, 1, &buffer);
152    check();
[4750]153
[6828]154    active = stream(buffer);
[4750]155
[6828]156    alSourceQueueBuffers(source, 1, &buffer);
157    check();
158  }
[4750]159
[6828]160  return active;
[4750]161}
162
[4961]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)
[4750]169{
[6828]170  char pcm[BUFFER_SIZE];
171  int  size = 0;
172  int  section;
173  int  result;
[4750]174
[6828]175  while(size < BUFFER_SIZE)
176  {
177    result = ov_read(&oggStream, pcm + size, BUFFER_SIZE - size, 0, 2, 1, &section);
[4750]178
[6828]179    if(result > 0)
180      size += result;
181    else
182      if(result < 0)
183        throw errorString(result);
184      else
185        break;
186  }
[4750]187
[6828]188  if(size == 0)
189    return false;
[4750]190
[6828]191  alBufferData(buffer, format, pcm, size, vorbisInfo->rate);
192  check();
[4750]193
[6828]194  return true;
[4750]195}
196
197
[4961]198/**
199 * empties the buffers
200 */
201void OggPlayer::empty()
[4750]202{
[6828]203  int queued;
[4750]204
[6828]205  alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
[4750]206
[6828]207  while(queued--)
208  {
209    ALuint buffer;
[4750]210
[6828]211    alSourceUnqueueBuffers(source, 1, &buffer);
212    check();
213  }
[4750]214}
215
[4961]216/**
217 * checks for errors
218 */
219void OggPlayer::check()
[4750]220{
[6828]221  int error = alGetError();
[4750]222
[6828]223  if(error != AL_NO_ERROR)
224    PRINTF(2)("OpenAL error was raised.");
[4750]225}
226
[6828]227
228
[4961]229/**
[6828]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/**
[4961]253 * returns errors
254 * @param code the error-code
255 * @return the error as a String
256 */
257const char* OggPlayer::errorString(int code)
[4750]258{
[6828]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  }
[4750]274}
Note: See TracBrowser for help on using the repository browser.