Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpenALRenderableSource.cpp
Go to the documentation of this file.
1 //
2 // C++ Implementation: Audio::OpenALRenderableListener
3 //
5 #include "OpenALSimpleSound.h"
6 #include "OpenALHelpers.h"
7 #include "config.h"
8 
9 #include "al.h"
10 
11 #include "../../Source.h"
12 #include "../../Listener.h"
13 
14 #include "vs_math.h"
15 
16 namespace Audio {
17 
18  static inline void alSource3f(ALuint source, ALenum param, const Vector3 &v)
19  {
20  ::alSource3f(source, param, ALfloat(v.x), ALfloat(v.y), ALfloat(v.z));
21  }
22 
23  static inline void alSource3f(ALuint source, ALenum param, const LVector3 &v)
24  {
25  ::alSource3f(source, param, ALfloat(v.x), ALfloat(v.y), ALfloat(v.z));
26  }
27 
29  : RenderableSource(source),
30  alSource(0),
31  alBuffersAttached(false)
32  {
33  alGenSources(1,&alSource);
34  }
35 
37  {
38  alDeleteSources(1,&alSource);
39  }
40 
42  throw(Exception)
43  {
44  if (!isPlayingImpl()) {
45  // Make sure we have an attached sound
46  attachALBuffers();
47 
48  // Tell the AL to start playing (from the specified position)
49  clearAlError();
50  ALuint als = getALSource();
51  alSourcePlay(als);
52  checkAlError();
53 
54  if (start != 0)
55  seekImpl(start);
56  }
57  }
58 
60  throw(Exception)
61  {
62  alSourceStop(alSource);
63  }
64 
66  throw(Exception)
67  {
68  ALint state = 0;
69  alGetSourcei(getALSource(), AL_SOURCE_STATE, &state);
70  return (state == AL_PLAYING);
71  }
72 
74  throw(Exception)
75  {
76  ALfloat offs = -1.f;
77  alGetSourcef(getALSource(), AL_SEC_OFFSET, &offs);
78 
79  if (offs < 0.f)
80  throw NotImplementedException("getPlayingTimeImpl");
81 
82  return Timestamp(offs);
83  }
84 
85  void OpenALRenderableSource::updateImpl(int flags, const Listener& sceneListener)
86  throw(Exception)
87  {
88  Source *source = getSource();
89  ALSourceHandle als = getALSource();
90 
91  clearAlError();
92 
93  if (flags & UPDATE_ATTRIBUTES) {
94  // Distance attenuation
95  if (source->isAttenuated()) {
96  alSourcef(als, AL_REFERENCE_DISTANCE, source->getRadius());
97  alSourcef(als, AL_ROLLOFF_FACTOR, 1.f);
98  } else {
99  alSourcef(als, AL_ROLLOFF_FACTOR, 0.f);
100  }
101  // Cone
102  {
103  Range<Scalar> angleRange = source->getAngleRange();
104  alSourcef(als, AL_CONE_INNER_ANGLE, float(angleRange.min) * M_1_PI * 360.f);
105  alSourcef(als, AL_CONE_OUTER_ANGLE, float(angleRange.max) * M_1_PI * 360.f);
106  alSourcef(als, AL_CONE_OUTER_GAIN , 0.f);
107  }
108  // Relativity
109  alSourcei(als, AL_SOURCE_RELATIVE, source->isRelative() ? AL_TRUE : AL_FALSE);
110  // Looping
111  alSourcei(als, AL_LOOPING, source->isLooping() ? AL_TRUE : AL_FALSE);
112  }
113  if (flags & UPDATE_GAIN) {
114  // Gain
115  alSourcef(als, AL_GAIN, source->getGain());
116  }
117  if (flags & UPDATE_LOCATION) {
118  if (source->isRelative()) {
119  alSource3f(als, AL_POSITION, source->getPosition());
120  alSource3f(als, AL_VELOCITY, source->getVelocity());
121  alSource3f(als, AL_DIRECTION, source->getDirection());
122  } else {
123  alSource3f(als, AL_POSITION,
124  source->getPosition() - sceneListener.getPosition() );
125  alSource3f(als, AL_VELOCITY,
126  sceneListener.toLocalDirection(
127  source->getVelocity() - sceneListener.getVelocity()
128  ) );
129  alSource3f(als, AL_DIRECTION,
130  sceneListener.toLocalDirection(
131  source->getDirection()
132  ) );
133  }
134  }
135 
136  checkAlError();
137  }
138 
140  throw(Exception)
141  {
142  if (!alBuffersAttached) {
143  SharedPtr<Sound> sound = getSource()->getSound();
144 
145  if (!sound->isLoaded())
146  sound->load();
147 
148  assert(!sound->isStreaming() && "OpenALRenderableSource can only handle streaming sounds");
149 
150  // Attachment to a simple sound, just assign the AL buffer to this AL source
151  ALBufferHandle alBuffer = dynamic_cast<OpenALSimpleSound*>(sound.get())->getAlBuffer();
152  ALSourceHandle alSource = getALSource();
153  alSourcei(alSource, AL_BUFFER, alBuffer);
154  alBuffersAttached = true;
155 
156  checkAlError();
157  }
158  }
159 
161  throw(Exception)
162  {
163  // Tell the AL to jump to the specified position
164  // NOTE: lots of implementations don't support it
165  // but according to OpenAL 1.1 specs they should
166  clearAlError();
167  ALuint als = getALSource();
168  alSourcef(als, AL_SEC_OFFSET, time);
169 
170  ALenum error = alGetError();
171  if (error == ALC_INVALID_ENUM) {
172  // This version of the AL does not support seeking
173  // fail silently
174  // TODO: must log the fact to console as a warning
175  } else {
176  checkAlErrorCode(error);
177  }
178  }
179 
180 };