TDME2  1.9.200
AudioStream.cpp
Go to the documentation of this file.
2 
3 #if defined(__APPLE__)
4  #define AL_SILENCE_DEPRECATION
5  #include <OpenAL/al.h>
6 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(_WIN32) || defined(__HAIKU__)
7  #include <AL/al.h>
8 #endif
9 
10 #include <array>
11 #include <memory>
12 #include <string>
13 #include <vector>
14 
15 #include <tdme/tdme.h>
16 #include <tdme/audio/Audio.h>
17 #include <tdme/math/Vector3.h>
20 #include <tdme/utilities/Console.h>
21 
23 
24 using std::array;
25 using std::string;
26 using std::to_string;
27 using std::unique_ptr;
28 using std::vector;
29 
30 using tdme::audio::Audio;
34 
35 void AudioStream::setParameters(uint32_t sampleRate, uint8_t channels, const int64_t bufferSize) {
36  this->sampleRate = sampleRate;
37  this->channels = channels;
38  this->data = unique_ptr<ByteBuffer>(ByteBuffer::allocate(bufferSize));
39 }
40 
42  ALint state;
43  alGetSourcei(alSourceId, AL_SOURCE_STATE, &state);
44  return state == AL_PLAYING;
45 }
46 
48 {
49  return isPlayingBuffers() == true || playing == true;
50 }
51 
53 {
54 }
55 
57 {
58  if (initiated == false)
59  return;
60 
61  //
62  stop();
63 
64  // update AL properties
66  ALsizei buffersToPlay = 0;
67  for (auto i = 0; i < alBufferIds.size(); i++) {
68  data->clear();
69  fillBuffer(data.get());
70  // skip if no more data is available
71  if (data->getPosition() == 0) break;
72  // otherwise upload
73  alBufferData(alBufferIds[i], format, data->getBuffer(), data->getPosition(), sampleRate);
74  //
75  if (alGetError() != AL_NO_ERROR) {
76  Console::println(string("AudioStream::play(): '"+ id + "': Could not upload buffer"));
77  }
78  buffersToPlay++;
79  }
80 
81  alSourceQueueBuffers(alSourceId, buffersToPlay, alBufferIds.data());
82  if (alGetError() != AL_NO_ERROR) {
83  Console::println(string("AudioStream::play(): '" + id + "': Could not queue buffers"));
84  }
85  alSourcePlay(alSourceId);
86  if (alGetError() != AL_NO_ERROR) {
87  Console::println(string("AudioStream::play(): '"+ id + "': Could not play source"));
88  }
89 
90  //
91  playing = true;
92 }
93 
95 {
96  if (initiated == false)
97  return;
98 
99  alSourcePause(alSourceId);
100  if (alGetError() != AL_NO_ERROR) {
101  Console::println(string("AudioStream::pause(): '" + id + "': Could not pause"));
102  }
103 }
104 
106 {
107  if (initiated == false)
108  return;
109 
110  alSourceStop(alSourceId);
111  if (alGetError() != AL_NO_ERROR) {
112  Console::println(string("AudioStream::stop(): '" + id + "': Could not stop"));
113  }
114  // determine queued buffers
115  ALint queuedBuffers;
116  alGetSourcei(alSourceId, AL_BUFFERS_QUEUED, &queuedBuffers);
117  if (alGetError() != AL_NO_ERROR) {
118  Console::println(string("AudioStream::stop(): '" + id + "': Could not determine queued buffers"));
119  }
120  // unqueue buffers
121  if (queuedBuffers > 0) {
122  vector<uint32_t> removedBuffers;
123  removedBuffers.resize(queuedBuffers);
124  alSourceUnqueueBuffers(alSourceId, queuedBuffers, removedBuffers.data());
125  if (alGetError() != AL_NO_ERROR) {
126  Console::println(string("AudioStream::stop(): '" + id + "': Could not unqueue buffers"));
127  }
128  }
129 
130  //
131  playing = false;
132 }
133 
135 {
136  switch (channels) {
137  case(1): format = AL_FORMAT_MONO16; break;
138  case(2): format = AL_FORMAT_STEREO16; break;
139  default:
140  Console::println(string("AudioStream::initialize(): '" + id + "': Unsupported number of channels"));
141  }
142 
143  alGenBuffers(alBufferIds.size(), alBufferIds.data());
144  if (alGetError() != AL_NO_ERROR) {
145  Console::println(string("AudioStream::initialize(): '" + id + "': Could not generate buffer"));
146  return false;
147  }
148  // create source
149  alGenSources(1, &alSourceId);
150  if (alGetError() != AL_NO_ERROR) {
151  Console::println(string("AudioStream::initialize(): '" + id + "': Could not generate source"));
152  dispose();
153  return false;
154  }
155  // initiate sound properties
157  initiated = true;
158  return true;
159 }
160 
162 {
163  if (initiated == false)
164  return;
165 
166  // determine processed buffers
167  int32_t processedBuffers;
168  alGetSourcei(alSourceId, AL_BUFFERS_PROCESSED, &processedBuffers);
169  if (alGetError() != AL_NO_ERROR) {
170  Console::println(string("AudioStream::update(): '" + id + "': Could not determine processed buffers"));
171  }
172  if (isPlayingBuffers() == false && playing == true) {
173  play();
174  } else {
175  while (processedBuffers > 0) {
176  // get a processed buffer id and unqueue it
177  uint32_t processedBufferId;
178  alSourceUnqueueBuffers(alSourceId, 1, &processedBufferId);
179  if (alGetError() != AL_NO_ERROR) {
180  Console::println(string("AudioStream::update(): '" + id + "': Could not unqueue buffers"));
181  }
182  // fill processed buffer again
183  data->clear();
184  fillBuffer(data.get());
185  // stop buffer if not filled
186  if (data->getPosition() == 0) {
187  playing = false;
188  } else {
189  // upload buffer data
190  alBufferData(processedBufferId, format, data->getBuffer(), data->getPosition(), sampleRate);
191  if (alGetError() != AL_NO_ERROR) {
192  Console::println(string("AudioStream::update(): '" + id + "': Could not upload buffer"));
193  }
194  // queue it
195  alSourceQueueBuffers(alSourceId, 1, &processedBufferId);
196  if (alGetError() != AL_NO_ERROR) {
197  Console::println(string("AudioStream::update(): '" + id + "': Could not queue buffer"));
198  }
199  // stop buffer if not filled completely
200  if (data->getPosition() < data->getCapacity()) {
201  playing = false;
202  }
203  }
204  // processed it
205  processedBuffers--;
206  }
207  }
208  // update AL properties
210 }
211 
213 {
214  // update sound properties
215  alSourcef(alSourceId, AL_PITCH, pitch);
216  alSourcef(alSourceId, AL_GAIN, gain);
217  alSourcefv(alSourceId, AL_POSITION, sourcePosition.getArray().data());
218  alSourcefv(alSourceId, AL_DIRECTION, sourceDirection.getArray().data());
219  alSourcefv(alSourceId, AL_VELOCITY, sourceVelocity.getArray().data());
220  if (fixed == true) {
221  alSourcef(alSourceId, AL_ROLLOFF_FACTOR, 0.0f);
222  alSourcei(alSourceId, AL_SOURCE_RELATIVE, AL_TRUE);
223  } else {
224  alSourcef(alSourceId, AL_ROLLOFF_FACTOR, 1.0f);
225  alSourcei(alSourceId, AL_SOURCE_RELATIVE, AL_FALSE);
226  }
227 }
228 
230 {
231  if (initiated == false)
232  return;
233  //
234  alDeleteSources(1, &alSourceId);
235  if (alGetError() != AL_NO_ERROR) {
236  Console::println(string("AudioStream::dispose(): '" + id + "': Could not delete source"));
237  }
239  //
240  alDeleteBuffers(alBufferIds.size(), alBufferIds.data());
241  if (alGetError() != AL_NO_ERROR) {
242  Console::println(string("AudioStream::dispose(): '" + id + "': Could not delete buffers"));
243  }
245  //
246  data = nullptr;
247  //
248  initiated = false;
249 }
virtual void play() override
Plays this audio entity.
Definition: AudioStream.cpp:56
virtual void rewind() override
Rewinds this audio entity.
Definition: AudioStream.cpp:52
virtual void dispose() override
Dispose this entity from OpenAL.
void updateProperties()
Updates properties to Open AL.
virtual void update() override
Commits properties to OpenAl.
virtual bool initialize() override
Initiates this OpenAL entity to OpenAl.
virtual bool isPlaying() override
Definition: AudioStream.cpp:47
array< uint32_t, 2 > alBufferIds
Definition: AudioStream.h:30
virtual void fillBuffer(ByteBuffer *data)=0
Fill buffer.
unique_ptr< ByteBuffer > data
Definition: AudioStream.h:34
virtual void stop() override
Stops this audio entity.
virtual void pause() override
Pauses this audio entity.
Definition: AudioStream.cpp:94
Interface to audio module.
Definition: Audio.h:29
static constexpr uint32_t ALSOURCEID_NONE
Definition: Audio.h:36
static constexpr uint32_t ALBUFFERID_NONE
Definition: Audio.h:35
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
const array< float, 3 > & getArray() const
Definition: Vector3.h:366
Byte buffer class.
Definition: ByteBuffer.h:27
Console class.
Definition: Console.h:29