Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4969 was 4961, checked in by bensch, 19 years ago

orxonox/trunk: music now plays back, as one would expect, and the ReosurceManager handles ogg's.
Also the naming has changed a bit, and doxygen tags are complete in ogg_player.h/cc

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