TORCS  1.3.9
The Open Racing Car Simulator
OpenALMusicPlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  file : OpenAlMusicPlayer.cpp
4  created : Fri Dec 23 17:35:18 CET 2011
5  copyright : (C) 2011 Bernhard Wymann
6  email : berniw@bluewin.ch
7  version : $Id$
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include <stdio.h>
21 #include <tgf.h>
22 #include "OpenALMusicPlayer.h"
23 
24 const int OpenALMusicPlayer::BUFFERSIZE = 4096*64;
25 
27  device(NULL),
28  context(NULL),
29  source(0),
30  stream(soundStream),
31  ready(false)
32 {
33  buffers[0] = 0;
34  buffers[1] = 0;
35 }
36 
37 
38 
39 
41 {
42  if (ready) {
43  stop();
44  }
45 }
46 
47 
48 
49 
51 {
52  if (!ready) {
53  return;
54  }
55 
56  alSourceStop(source);
57 
58  int queued;
59 
60  alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
61  while (queued--) {
62  ALuint buffer;
63  alSourceUnqueueBuffers(source, 1, &buffer);
64  check();
65  }
66 
67  alDeleteSources(1, &source);
68  check();
69  alDeleteBuffers(2, buffers);
70  check();
71 
72  alcMakeContextCurrent(NULL);
73  alcDestroyContext(context);
74  alcCloseDevice(device);
75 
76  ready = false;
77 }
78 
79 
80 
81 
83 {
84  device = alcOpenDevice(NULL);
85  if( device == NULL ) {
86  GfError("OpenALMusicPlayer: OpenAL could not open device\n");
87  return false;
88  }
89 
90  context = alcCreateContext(device, NULL);
91  if(context == NULL) {
92  alcCloseDevice(device);
93  GfError("OpenALMusicPlayer: OpenAL could not create contect for device\n");
94  return false;
95  }
96 
97  alcMakeContextCurrent(context);
98  alcGetError(device);
99 
100  return check();
101 }
102 
103 
104 
105 
107 {
108  alGenBuffers(2, buffers);
109  return check();
110 }
111 
112 
113 
114 
116 {
117  alGenSources(1, &source);
118  if (!check()) {
119  GfError("OpenALMusicPlayer: initSource failed to get sound source.\n");
120  return false;
121  };
122 
123  alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0);
124  alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0);
125  alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0);
126  alSourcef (source, AL_ROLLOFF_FACTOR, 0.0 );
127  alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE );
128 
129  return true;
130 }
131 
132 
133 
134 
136 {
137  int error = alGetError();
138 
139  if(error != AL_NO_ERROR) {
140  GfError("OpenALMusicPlayer: OpenAL error was raised: %d\n", error);
141  return false;
142  }
143 
144  return true;
145 }
146 
147 
148 
149 
151 {
152  ALenum state;
153 
154  alGetSourcei(source, AL_SOURCE_STATE, &state);
155  return (state == AL_PLAYING);
156 }
157 
158 
159 
161 {
162  char pcm[BUFFERSIZE];
163  int size = 0;
164  const char* error = "";
165 
166  if (!stream->read(pcm, BUFFERSIZE, &size, &error)) {
167  GfError("OpenALMusicPlayer: Stream read error: %s\n", error);
168  return false;
169  } else {
170  int format;
171  switch (stream->getSoundFormat()) {
173  format = AL_FORMAT_MONO16;
174  break;
176  format = AL_FORMAT_STEREO16;
177  break;
178  default:
179  GfError("OpenALMusicPlayer: Format error: \n");
180  return false;
181  }
182 
183  alBufferData(buffer, format, pcm, size, stream->getRateInHz());
184  return check();
185  }
186 }
187 
188 
189 
190 
192 {
193  if (!ready) {
195  GfError("OpenALMusicPlayer: Sound stream has invalid format\n");
196  return;
197  }
198 
199  if (initContext() && initBuffers() && initSource()) {
200  ready = true;
201  startPlayback();
202  }
203 
204  return;
205  }
206 }
207 
208 
209 
210 
212 {
213  stream->rewind();
214 }
215 
216 
217 
218 
220 {
221  if (!ready) {
222  return false;
223  }
224 
225  int processed;
226  bool active = true;
227 
228  alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
229 
230  while(processed--) {
231  ALuint buffer;
232 
233  alSourceUnqueueBuffers(source, 1, &buffer);
234  check();
235  active = streamBuffer(buffer);
236  alSourceQueueBuffers(source, 1, &buffer);
237  check();
238  }
239 
240  if (!active && !isPlaying()) {
241  // Try to reanimate playback
242  if(!startPlayback()) {
243  GfError("OpenALMusicPlayer: Cannot play stream.\n");
244  }
245  }
246 
247  return true;
248 }
249 
250 
251 
252 
254 {
255  if(isPlaying()) {
256  return true;
257  }
258 
259  if(!streamBuffer(buffers[0])) {
260  return false;
261  }
262 
263  if(!streamBuffer(buffers[1])) {
264  return false;
265  }
266 
267  alSourceQueueBuffers(source, 2, buffers);
268  alSourcePlay(source);
269 
270  return true;
271 }
#define GfError
Definition: tgf.h:351
OpenALMusicPlayer(SoundStream *soundStream)
SoundStream * stream
virtual bool initBuffers()
ALCcontext * context
virtual bool initSource()
virtual int getRateInHz()=0
virtual bool initContext()
virtual bool startPlayback()
virtual bool read(char *buffer, const int bufferSize, int *resultSize, const char **error)=0
The Gaming Framework API.
virtual bool streamBuffer(ALuint buffer)
virtual bool isPlaying()
virtual bool playAndManageBuffer()
virtual void rewind()=0
static const int BUFFERSIZE
virtual SoundFormat getSoundFormat()=0