xoreos  0.0.5
sound.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <cassert>
26 #include <cstring>
27 
28 #include <boost/scope_exit.hpp>
29 
30 #include "src/common/util.h"
31 #include "src/common/readstream.h"
32 #include "src/common/strutil.h"
33 #include "src/common/error.h"
34 #include "src/common/configman.h"
35 #include "src/common/debug.h"
36 
37 #include "src/sound/sound.h"
38 #include "src/sound/audiostream.h"
39 #include "src/sound/decoders/asf.h"
40 #ifdef ENABLE_MAD
41 #include "src/sound/decoders/mp3.h"
42 #endif
43 #ifdef ENABLE_VORBIS
45 #endif
47 
48 #include "src/events/events.h"
49 
51 
52 
56 static const size_t kOpenALBufferCount = 5;
57 
63 static const size_t kOpenALBufferSize = 32768;
64 
65 namespace Sound {
66 
67 SoundManager::Channel::Channel(uint32 i, size_t idx, SoundType t,
68  const TypeList::iterator &ti, AudioStream *s, bool d) :
69  id(i), index(idx), state(AL_PAUSED), stream(s, d), source(0),
70  type(t), typeIt(ti), finishedBuffers(0), gain(1.0f) {
71 
72 }
73 
74 
76 }
77 
79 }
80 
82  for (size_t i = 0; i < kSoundTypeMAX; i++)
83  _types[i].gain = 1.0f;
84 
85  _curID = 1;
86 
87  _ctx = 0;
88 
89  _hasSound = false;
90 
91  _hasMultiChannel = false;
92  _format51 = 0;
93 
94  try {
95  _dev = alcOpenDevice(0);
96  if (!_dev)
97  throw Common::Exception("Could not open OpenAL device");
98 
99  _ctx = alcCreateContext(_dev, 0);
100  if (!_ctx)
101  throw Common::Exception("Could not create OpenAL context: 0x%X", (uint) alGetError());
102 
103  alcMakeContextCurrent(_ctx);
104 
105  ALenum error = alGetError();
106  if (error != AL_NO_ERROR)
107  throw Common::Exception("Could not use OpenAL context: 0x%X", (uint) alGetError());
108 
109  _hasMultiChannel = alIsExtensionPresent("AL_EXT_MCFORMATS") != 0;
110  _format51 = alGetEnumValue("AL_FORMAT_51CHN16");
111 
112  if (!createThread("SoundManager"))
113  throw Common::Exception("Failed to create sound thread: %s", SDL_GetError());
114 
115  _hasSound = true;
116 
117  } catch (...) {
118  Common::exceptionDispatcherWarning("Failed to initialize OpenAL. Disabling sound output!");
119  }
120 
121  _ready = true;
122 
123  if (!_hasSound)
124  return;
125 
126  setListenerGain(ConfigMan.getDouble("volume", 1.0));
127 
128  setTypeGain(kSoundTypeMusic, ConfigMan.getDouble("volume_music", 1.0));
129  setTypeGain(kSoundTypeSFX , ConfigMan.getDouble("volume_sfx" , 1.0));
130  setTypeGain(kSoundTypeVoice, ConfigMan.getDouble("volume_voice", 1.0));
131  setTypeGain(kSoundTypeVideo, ConfigMan.getDouble("volume_video", 1.0));
132 
133  alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
134 }
135 
137  if (!_ready)
138  return;
139 
140  destroyThread();
141 
142  for (size_t i = 0; i < kChannelCount; i++)
143  freeChannel(i);
144 
145  if (_hasSound) {
146  alcMakeContextCurrent(0);
147  alcDestroyContext(_ctx);
148  alcCloseDevice(_dev);
149  }
150 
151  _ready = false;
152 }
153 
154 bool SoundManager::ready() const {
155  return _ready;
156 }
157 
159  checkReady();
160 
162 }
163 
164 bool SoundManager::isValidChannel(const ChannelHandle &handle) const {
165  if ((handle.channel >= kChannelCount) || (handle.id == 0) || !_channels[handle.channel])
166  return false;
167 
168  if (_channels[handle.channel]->id != handle.id)
169  return false;
170 
171  return true;
172 }
173 
176 
177  if ((handle.channel >= kChannelCount) || (handle.id == 0) || !_channels[handle.channel])
178  return false;
179 
180  if (_channels[handle.channel]->id != handle.id)
181  return false;
182 
183  return isPlaying(handle.channel);
184 }
185 
186 bool SoundManager::isPlaying(size_t channel) const {
187  if ((channel >= kChannelCount) || !_channels[channel])
188  return false;
189 
190  // TODO: This might pose a problem should we ever need to wait
191  // for sounds to finish (for syncing, ...). We need to
192  // add a way for audio streams to tell us how long they are
193  // and then check if that time has elapsed.
194  if (!_hasSound)
195  return true;
196 
197  ALenum error = AL_NO_ERROR;
198 
199  ALint val;
200  alGetSourcei(_channels[channel]->source, AL_SOURCE_STATE, &val);
201  if ((error = alGetError()) != AL_NO_ERROR)
202  throw Common::Exception("OpenAL error while getting source state in %s: 0x%X",
203  formatChannel(_channels[channel].get()).c_str(), error);
204 
205  if (val != AL_PLAYING) {
206  if (!_channels[channel]->stream || _channels[channel]->stream->endOfStream()) {
207  ALint buffersQueued;
208  alGetSourcei(_channels[channel]->source, AL_BUFFERS_QUEUED, &buffersQueued);
209  if ((error = alGetError()) != AL_NO_ERROR)
210  throw Common::Exception("OpenAL error while getting queued buffers in %s: 0x%X",
211  formatChannel(_channels[channel].get()).c_str(), error);
212 
213  ALint buffersProcessed;
214  alGetSourcei(_channels[channel]->source, AL_BUFFERS_PROCESSED, &buffersProcessed);
215  if ((error = alGetError()) != AL_NO_ERROR)
216  throw Common::Exception("OpenAL error while getting processed buffers in %s: 0x%X",
217  formatChannel(_channels[channel].get()).c_str(), error);
218 
219  if (buffersQueued == buffersProcessed)
220  return false;
221  }
222 
223  if (_channels[channel]->state != AL_PLAYING)
224  return true;
225 
226  alSourcePlay(_channels[channel]->source);
227  }
228 
229  return true;
230 }
231 
234 
235  if ((handle.channel == 0) || (handle.id == 0) || !_channels[handle.channel])
236  return false;
237 
238  if (_channels[handle.channel]->id != handle.id)
239  return false;
240 
241  return _channels[handle.channel]->state == AL_PAUSED;
242 }
243 
245  bool isMP3 = false;
246  uint32 tag = stream->readUint32BE();
247 
248  if (tag == 0xfff360c4) {
249  // Modified WAVE file (used in streamsounds folder, at least in KotOR 1/2)
250  stream = new Common::SeekableSubReadStream(stream, 0x1D6, stream->size(), true);
251 
252  } else if (tag == MKTAG('R', 'I', 'F', 'F')) {
253  stream->seek(12);
254  tag = stream->readUint32BE();
255 
256  if (tag != MKTAG('f', 'm', 't', ' '))
257  throw Common::Exception("Broken WAVE file (%s)", Common::debugTag(tag).c_str());
258 
259  // Skip fmt chunk
260  stream->skip(stream->readUint32LE());
261  tag = stream->readUint32BE();
262 
263  while ((tag == MKTAG('f', 'a', 'c', 't')) || (tag == MKTAG('P', 'A', 'D', ' ')) ||
264  (tag == MKTAG('c', 'u', 'e', ' ')) || (tag == MKTAG('L', 'I', 'S', 'T')) ||
265  (tag == MKTAG('s', 'm', 'p', 'l'))) {
266  // Skip useless chunks
267  stream->skip(stream->readUint32LE());
268  tag = stream->readUint32BE();
269  }
270 
271  if (tag != MKTAG('d', 'a', 't', 'a'))
272  throw Common::Exception("Found invalid tag in WAVE file: %s", Common::debugTag(tag).c_str());
273 
274  uint32 dataSize = stream->readUint32LE();
275  if (dataSize == 0) {
276  isMP3 = true;
277  stream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->size(), true);
278  } else
279  // Just a regular WAVE
280  stream->seek(0);
281 
282  } else if ((tag == MKTAG('B', 'M', 'U', ' ')) &&
283  (stream->readUint32BE() == MKTAG('V', '1', '.', '0'))) {
284 
285  // BMU files: MP3 with extra header
286  isMP3 = true;
287  stream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->size(), true);
288 
289  } else if (tag == MKTAG('O', 'g', 'g', 'S')) {
290 
291 #ifdef ENABLE_VORBIS
292  stream->seek(0);
293  return makeVorbisStream(stream, true);
294 #else
295  throw Common::Exception("Vorbis decoding disabled when building without libvorbis");
296 #endif
297 
298  } else if (tag == 0x3026B275) {
299 
300  // ASF (most probably with WMAv2)
301  stream->seek(0);
302  return makeASFStream(stream, true);
303 
304  } else if (((tag & 0xFFFFFF00) | 0x20) == MKTAG('I', 'D', '3', ' ')) {
305 
306  // ID3v2 tag found => Should be MP3.
307  stream->seek(0);
308  isMP3 = true;
309 
310  } else if ((tag & 0xFFFA0000) == 0xFFFA0000) {
311 
312  // MPEG sync + MPEG1 layer 3 bits found => Should be MP3.
313  // NOTE: To decrease the chances of false positives, we could look at more than just the first frame.
314  stream->seek(0);
315  isMP3 = true;
316 
317  } else
318  throw Common::Exception("Unknown sound format %s", Common::debugTag(tag).c_str());
319 
320  if (isMP3)
321 #ifdef ENABLE_MAD
322  return makeMP3Stream(stream, true);
323 #else
324  throw Common::Exception("MP3 decoding disabled when building without libmad");
325 #endif
326 
327  return makeWAVStream(stream, true);
328 }
329 
330 ChannelHandle SoundManager::playAudioStream(AudioStream *audStream, SoundType type, bool disposeAfterUse) {
331  assert((type >= 0) && (type < kSoundTypeMAX));
332 
333  checkReady();
334 
335  if (!audStream)
336  throw Common::Exception("No audio stream");
337 
339 
340  ChannelHandle handle = newChannel();
341 
342  bool success = false;
343  BOOST_SCOPE_EXIT ( (&success) (&handle) (this_) ) {
344  if (!success)
345  this_->freeChannel(handle);
346  } BOOST_SCOPE_EXIT_END
347 
348  const TypeList::iterator typeEndIt = _types[type].list.end();
349 
350  _channels[handle.channel].reset(new Channel(handle.id, handle.channel, type, typeEndIt, audStream, disposeAfterUse));
351  Channel &channel = *_channels[handle.channel];
352 
353  if (!channel.stream)
354  throw Common::Exception("Could not detect stream type");
355 
356  ALenum error = AL_NO_ERROR;
357 
358  if (_hasSound) {
359  // Create the source
360  alGenSources(1, &channel.source);
361  if ((error = alGetError()) != AL_NO_ERROR)
362  throw Common::Exception("OpenAL error while generating sources: 0x%X", error);
363 
364  // Create all needed buffers
365  for (size_t i = 0; i < kOpenALBufferCount; i++) {
366  ALuint buffer;
367 
368  alGenBuffers(1, &buffer);
369  if ((error = alGetError()) != AL_NO_ERROR)
370  throw Common::Exception("OpenAL error while generating buffers: 0x%X", error);
371 
372  if (fillBuffer(channel, buffer, channel.stream.get(), channel.bufferSize[buffer])) {
373  // If we could fill the buffer with data, queue it
374 
375  alSourceQueueBuffers(channel.source, 1, &buffer);
376  if ((error = alGetError()) != AL_NO_ERROR)
377  throw Common::Exception("OpenAL error while queueing buffers: 0x%X", error);
378 
379  } else
380  // If not, put it into our free list
381  channel.freeBuffers.push_back(buffer);
382 
383  channel.buffers.push_back(buffer);
384  }
385 
386  // Set the gain to the current sound type gain
387  alSourcef(channel.source, AL_GAIN, _types[channel.type].gain);
388  // Set the sound per default as relative.
389  alSourcei(channel.source, AL_SOURCE_RELATIVE, AL_TRUE);
390  }
391 
392  // Add the channel to the correct type list
393  _types[channel.type].list.push_back(&channel);
394  channel.typeIt = --_types[channel.type].list.end();
395 
396  debugC(Common::kDebugSound, 2, "Created sound channel %s", formatChannel(handle).c_str());
397 
398  success = true;
399  return handle;
400 }
401 
403  checkReady();
404 
405  if (!wavStream)
406  throw Common::Exception("No stream");
407 
408  AudioStream *audioStream = makeAudioStream(wavStream);
409 
410  if (!audioStream)
411  throw Common::Exception("No audio stream");
412 
413  if (loop) {
414  RewindableAudioStream *reAudStream = dynamic_cast<RewindableAudioStream *>(audioStream);
415  if (!reAudStream)
416  warning("SoundManager::playSoundFile(): The input stream cannot be rewound, this will not loop.");
417  else
418  audioStream = makeLoopingAudioStream(reAudStream, 0);
419  }
420 
421  return playAudioStream(audioStream, type);
422 }
423 
425  if ((handle.channel >= kChannelCount) || (handle.id == 0))
426  return 0;
427 
428  if (!_channels[handle.channel])
429  return 0;
430 
431  if (_channels[handle.channel]->id != handle.id)
432  return 0;
433 
434  return _channels[handle.channel].get();
435 }
436 
438  if ((handle.channel >= kChannelCount) || (handle.id == 0))
439  return 0;
440 
441  if (!_channels[handle.channel])
442  return 0;
443 
444  if (_channels[handle.channel]->id != handle.id)
445  return 0;
446 
447  return _channels[handle.channel].get();
448 }
449 
452 
453  Channel *channel = getChannel(handle);
454  if (!channel || !channel->stream)
455  throw Common::Exception("Invalid channel");
456 
457  channel->state = AL_PLAYING;
458 
459  debugC(Common::kDebugSound, 1, "Start sound channel %s", formatChannel(handle).c_str());
460 
461  triggerUpdate();
462 }
463 
466 
467  Channel *channel = getChannel(handle);
468  if (!channel || !channel->stream)
469  throw Common::Exception("Invalid channel");
470 
471  pauseChannel(channel);
472 }
473 
474 void SoundManager::pauseChannel(ChannelHandle &handle, bool pause) {
476 
477  Channel *channel = getChannel(handle);
478  if (!channel || !channel->stream)
479  throw Common::Exception("Invalid channel");
480 
481  debugC(Common::kDebugSound, 1, "%s sound channel %s", pause ? "Pause" : "Unpause",
482  formatChannel(handle).c_str());
483 
484  pauseChannel(channel, pause);
485 }
486 
489 
490  if (isValidChannel(handle))
491  debugC(Common::kDebugSound, 1, "Stop sound channel %s", formatChannel(handle).c_str());
492 
493  freeChannel(handle);
494 }
495 
496 void SoundManager::pauseAll(bool pause) {
498 
499  for (size_t i = 0; i < kChannelCount; i++)
500  pauseChannel(_channels[i].get(), pause);
501 }
502 
505 
506  for (size_t i = 0; i < kChannelCount; i++)
507  freeChannel(i);
508 }
509 
511  checkReady();
512 
514 
515  if (_hasSound)
516  alListenerf(AL_GAIN, gain);
517 }
518 
519 void SoundManager::setListenerPosition(float x, float y, float z) {
520  checkReady();
521 
523 
524  alListener3f(AL_POSITION, x, y, z);
525 }
526 
527 void SoundManager::setListenerOrientation(float dirX, float dirY, float dirZ, float upX, float upY, float upZ) {
528  checkReady();
529 
531 
532  float orientation[] = {dirX, dirY, dirZ, upX, upY, upZ};
533  alListenerfv(AL_ORIENTATION, orientation);
534 }
535 
536 void SoundManager::setChannelPosition(const ChannelHandle &handle, float x, float y, float z) {
538 
539  Channel *channel = getChannel(handle);
540  if (!channel || !channel->stream)
541  throw Common::Exception("Invalid channel");
542 
543  if (channel->stream->getChannels() > 1)
544  throw Common::Exception("Cannot set position of a non-mono sound in %s",
545  formatChannel(handle).c_str());
546 
547  if (_hasSound)
548  alSource3f(channel->source, AL_POSITION, x, y, z);
549 }
550 
551 void SoundManager::getChannelPosition(const ChannelHandle &handle, float &x, float &y, float &z) {
553 
554  Channel *channel = getChannel(handle);
555  if (!channel || !channel->stream)
556  throw Common::Exception("Invalid channel");
557 
558  if (channel->stream->getChannels() > 1)
559  throw Common::Exception("Cannot get position of a non-mono sound in %s",
560  formatChannel(handle).c_str());
561 
562  if (_hasSound)
563  alGetSource3f(channel->source, AL_POSITION, &x, &y, &z);
564 }
565 
566 void SoundManager::setChannelGain(const ChannelHandle &handle, float gain) {
568 
569  Channel *channel = getChannel(handle);
570  if (!channel || !channel->stream)
571  throw Common::Exception("Invalid channel");
572 
573  channel->gain = gain;
574 
575  if (_hasSound)
576  alSourcef(channel->source, AL_GAIN, _types[channel->type].gain * gain);
577 }
578 
579 void SoundManager::setChannelPitch(const ChannelHandle &handle, float pitch) {
581 
582  Channel *channel = getChannel(handle);
583  if (!channel || !channel->stream)
584  throw Common::Exception("Invalid channel");
585 
586  if (_hasSound)
587  alSourcef(channel->source, AL_PITCH, pitch);
588 }
589 
590 void SoundManager::setChannelRelative(const ChannelHandle &handle, bool relative) {
592 
593  Channel *channel = getChannel(handle);
594  if (!channel || !channel->stream)
595  throw Common::Exception("Invalid channel");
596 
597  if (_hasSound)
598  alSourcei(channel->source, AL_SOURCE_RELATIVE, relative ? AL_TRUE : AL_FALSE);
599 }
600 
601 void SoundManager::setChannelDistance(const ChannelHandle &handle, float minDistance, float maxDistance) {
603 
604  Channel *channel = getChannel(handle);
605  if (!channel || !channel->stream)
606  throw Common::Exception("Invalid channel");
607 
608  if (_hasSound) {
609  alSourcef(channel->source, AL_REFERENCE_DISTANCE, minDistance);
610  alSourcef(channel->source, AL_MAX_DISTANCE, maxDistance);
611  }
612 }
613 
616 
617  Channel *channel = getChannel(handle);
618  if (!channel || !channel->stream)
619  return 0;
620 
621  // Update the queued/unqueued buffers to make sure the channel is up-to-date
622  bufferData(*channel);
623 
624  // The position within the currently playing buffer
625  ALint currentPosition;
626  alGetSourcei(channel->source, AL_BYTE_OFFSET, &currentPosition);
627 
628  // Total number of bytes processed
629  uint64 byteCount = channel->finishedBuffers + currentPosition;
630 
631  // Number of 16bit samples per channel
632  return byteCount / channel->stream->getChannels() / 2;
633 }
634 
637 
638  Channel *channel = getChannel(handle);
639  if (!channel || !channel->stream)
640  return 0;
641 
642  return (getChannelSamplesPlayed(handle) * 1000) / channel->stream->getRate();
643 }
644 
645 void SoundManager::setTypeGain(SoundType type, float gain) {
646  assert((type >= 0) && (type < kSoundTypeMAX));
647 
649 
650  // Set the new type gain
651  _types[type].gain = gain;
652 
653  // Update all currently playing channels of that type
654  for (TypeList::iterator t = _types[type].list.begin(); t != _types[type].list.end(); ++t) {
655  assert(*t);
656 
657  if (_hasSound)
658  alSourcef((*t)->source, AL_GAIN, (*t)->gain * gain);
659  }
660 }
661 
662 bool SoundManager::fillBuffer(const Channel &channel, ALuint alBuffer,
663  AudioStream *stream, ALsizei &bufferedSize) const {
664 
665  bufferedSize = 0;
666 
667  if (!stream)
668  throw Common::Exception("No stream in %s", formatChannel(&channel).c_str());
669 
670  if (!_hasSound)
671  return true;
672 
673  if (stream->endOfData())
674  return false;
675 
676  ALenum format;
677 
678  const int channelCount = stream->getChannels();
679  if (channelCount == 1) {
680  format = AL_FORMAT_MONO16;
681  } else if (channelCount == 2) {
682  format = AL_FORMAT_STEREO16;
683  } else if (channelCount == 6) {
684  if (!_hasMultiChannel) {
685  warning("SoundManager::fillBuffer(): TODO: !_hasMultiChannel in %s",
686  formatChannel(&channel).c_str());
687  return false;
688  }
689 
690  format = _format51;
691 
692  } else {
693  warning("SoundManager::fillBuffer(): Unsupported channel count in %s: %d",
694  formatChannel(&channel).c_str(), channelCount);
695  return false;
696  }
697 
698  // Read in the required amount of samples
699  size_t numSamples = kOpenALBufferSize / 2;
700 
702  std::memset(buffer.get(), 0, kOpenALBufferSize);
703 
704  numSamples = stream->readBuffer(reinterpret_cast<int16 *>(buffer.get()), numSamples);
705  if (numSamples == AudioStream::kSizeInvalid) {
706  warning("Failed reading from stream while filling buffer in %s", formatChannel(&channel).c_str());
707  return false;
708  }
709 
710  bufferedSize = numSamples * 2;
711  alBufferData(alBuffer, format, buffer.get(), bufferedSize, stream->getRate());
712 
713  ALenum error = alGetError();
714  if (error != AL_NO_ERROR) {
715  warning("OpenAL error while filling buffer in %s: 0x%X", formatChannel(&channel).c_str(), error);
716  return false;
717  }
718 
719  return true;
720 }
721 
722 void SoundManager::bufferData(size_t channel) {
723  if ((channel >= kChannelCount) || !_channels[channel])
724  return;
725 
726  bufferData(*_channels[channel]);
727 }
728 
730  if (!channel.stream)
731  return;
732 
733  if (!_hasSound)
734  return;
735 
736  ALenum error = AL_NO_ERROR;
737 
738  // Get the number of buffers that have been processed
739  ALint buffersProcessed = -1;
740  alGetSourcei(channel.source, AL_BUFFERS_PROCESSED, &buffersProcessed);
741  if ((error = alGetError()) != AL_NO_ERROR)
742  throw Common::Exception("OpenAL error while getting processed buffers in %s: 0x%X",
743  formatChannel(&channel).c_str(), error);
744 
745  assert(buffersProcessed >= 0);
746 
747  if ((size_t)buffersProcessed > kOpenALBufferCount)
748  throw Common::Exception("Got more processed buffers than total source buffers in %s?!?",
749  formatChannel(&channel).c_str());
750 
751  // Unqueue the processed buffers
752  ALuint freeBuffers[kOpenALBufferCount];
753  alSourceUnqueueBuffers(channel.source, buffersProcessed, freeBuffers);
754  if ((error = alGetError()) != AL_NO_ERROR)
755  throw Common::Exception("OpenAL error while unqueueing buffers in %s: 0x%X",
756  formatChannel(&channel).c_str(), error);
757 
758  // Put them into the free buffers list
759  for (size_t i = 0; i < (size_t)buffersProcessed; i++) {
760  channel.freeBuffers.push_back(freeBuffers[i]);
761 
762  channel.finishedBuffers += channel.bufferSize[freeBuffers[i]];
763  }
764 
765  // Buffer as long as we still have data and free buffers
766  std::list<ALuint>::iterator buffer = channel.freeBuffers.begin();
767  while (buffer != channel.freeBuffers.end()) {
768  if (!fillBuffer(channel, *buffer, channel.stream.get(), channel.bufferSize[*buffer]))
769  break;
770 
771  alSourceQueueBuffers(channel.source, 1, &*buffer);
772  if ((error = alGetError()) != AL_NO_ERROR)
773  throw Common::Exception("OpenAL error while queueing buffers in %s: 0x%X",
774  formatChannel(&channel).c_str(), error);
775 
776  buffer = channel.freeBuffers.erase(buffer);
777  }
778 }
779 
781  if (!_ready)
782  throw Common::Exception("SoundManager not ready");
783 }
784 
787 
788  size_t channelCount = 0;
789  for (size_t i = 0; i < kChannelCount; i++) {
790  if (!_channels[i])
791  continue;
792 
793  channelCount++;
794 
795  // Free the channel if it is no longer playing
796  if (!isPlaying(i)) {
797  freeChannel(i);
798  continue;
799  }
800 
801  // Try to buffer some more data
802  bufferData(i);
803  }
804 
805  debugC(Common::kDebugSound, 9, "Active sound channel: %s", Common::composeString(channelCount).c_str());
806 }
807 
809  size_t foundChannel = kChannelInvalid;
810 
811  for (size_t i = 0; (i < kChannelCount) && (foundChannel == kChannelInvalid); i++)
812  if (!_channels[i])
813  foundChannel = i;
814 
815  if (foundChannel == kChannelInvalid)
816  throw Common::Exception("All sound channels occupied");
817 
818  ChannelHandle handle;
819 
820  handle.channel = foundChannel;
821  handle.id = _curID++;
822 
823  // ID 0 is reserved for "invalid ID"
824  if (_curID == 0)
825  _curID++;
826 
827  return handle;
828 }
829 
830 void SoundManager::pauseChannel(Channel *channel, bool pause) {
831  if (!channel || channel->id == 0)
832  return;
833 
834  ALenum error = AL_NO_ERROR;
835  if (pause) {
836  if (_hasSound) {
837  alSourcePause(channel->source);
838  if ((error = alGetError()) != AL_NO_ERROR)
839  warning("OpenAL error while attempting to pause channel %s: 0x%X",
840  formatChannel(channel).c_str(), error);
841  }
842 
843  channel->state = AL_PAUSED;
844  } else
845  channel->state = AL_PLAYING;
846 
847  triggerUpdate();
848 }
849 
851  if (!channel)
852  return;
853 
854  if (channel->state == AL_PAUSED)
855  pauseChannel(channel, false);
856  else if (channel->state == AL_PLAYING)
857  pauseChannel(channel, true);
858 }
859 
861  if ((handle.channel < kChannelCount) && (handle.id != 0) && _channels[handle.channel])
862  // Only free if there is a channel to free
863  if (handle.id == _channels[handle.channel]->id)
864  // Only free if the IDs match
865  freeChannel(handle.channel);
866 
867  handle.channel = kChannelInvalid;
868  handle.id = 0;
869 }
870 
871 void SoundManager::freeChannel(size_t channel) {
872  if (channel >= kChannelCount)
873  return;
874 
875  Channel *c = _channels[channel].get();
876  if (!c)
877  // Nothing to do
878  return;
879 
880  // Discard the stream
881  c->stream.reset();
882 
883  if (_hasSound) {
884  // Delete the channel's OpenAL source
885  if (c->source)
886  alDeleteSources(1, &c->source);
887 
888  // Delete the OpenAL buffers
889  for (std::list<ALuint>::iterator buffer = c->buffers.begin(); buffer != c->buffers.end(); ++buffer)
890  alDeleteBuffers(1, &*buffer);
891  }
892 
893  // Remove the channel from the type list
894  if (c->typeIt != _types[c->type].list.end())
895  _types[c->type].list.erase(c->typeIt);
896 
897  // And finally delete the channel itself
898  _channels[channel].reset();
899 }
900 
902  while (!_killThread.load(boost::memory_order_relaxed)) {
903  update();
904  _needUpdate.wait(100);
905  }
906 }
907 
909  if (!channel)
910  return "[0:0]";
911 
912  return "[" + Common::composeString(channel->index) + ":" + Common::composeString(channel->id) + "]";
913 }
914 
916  return formatChannel(getChannel(handle));
917 }
918 
919 } // End of namespace Sound
TypeList::iterator typeIt
Iterator into the type list.
Definition: sound.h:218
bool _ready
Was the sound subsystem successfully initialized?
Definition: sound.h:228
void getChannelPosition(const ChannelHandle &handle, float &x, float &y, float &z)
Get the position of the channel.
Definition: sound.cpp:551
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
static AudioStream * makeAudioStream(Common::SeekableReadStream *stream)
Create an audio stream from this data stream.
Definition: sound.cpp:244
void setTypeGain(SoundType type, float gain)
Set the gain/volume of all channels of a specific type.
Definition: sound.cpp:645
"GSound", global, non-engine sound.
Definition: debugman.h:43
float gain
The sound type&#39;s current gain.
Definition: sound.h:197
void deinit()
Deinitialize the sound subsystem.
Definition: sound.cpp:136
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
void debugC(Common::DebugChannel channel, uint32 level, const char *s,...)
Definition: debug.cpp:34
A class holding an UTF-8 string.
Definition: ustring.h:48
void init()
Initialize the sound subsystem.
Definition: sound.cpp:81
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
bool destroyThread()
Definition: thread.cpp:64
void setChannelRelative(const ChannelHandle &handle, bool relative)
Set if the channel is relative.
Definition: sound.cpp:590
ALint state
The sound&#39;s state.
Definition: sound.h:206
Utility functions for debug output.
The global config manager.
TypeList list
The list of channels for that type.
Definition: sound.h:198
Decoding RIFF WAVE (Resource Interchange File Format Waveform).
UString composeString(T value)
Convert any POD integer, float/double or bool type into a string.
Definition: strutil.cpp:276
uint64_t uint64
Definition: types.h:206
virtual int getChannels() const =0
Return the number channels in this stream.
bool isValidChannel(const ChannelHandle &handle) const
Does this channel handle point to an existing channel?
Definition: sound.cpp:164
virtual int getRate() const =0
Sample rate of the stream.
boost::atomic< bool > _killThread
Definition: thread.h:53
Common::ScopedPtr< Channel > _channels[kChannelCount]
The sound channels.
Definition: sound.h:235
void startChannel(ChannelHandle &handle)
Start the channel.
Definition: sound.cpp:450
void stopAll()
Stop all channels.
Definition: sound.cpp:503
static const size_t kOpenALBufferCount
Control how many buffers per sound OpenAL will create.
Definition: sound.cpp:56
void setChannelPitch(const ChannelHandle &handle, float pitch)
Set the pitch of the channel.
Definition: sound.cpp:579
void setListenerOrientation(float dirX, float dirY, float dirZ, float upX, float upY, float upZ)
Set the orientation of the listener.
Definition: sound.cpp:527
RewindableAudioStream * makeASFStream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Try to load a ASF from the given seekable stream and create a RewindableAudioStream from that data...
Definition: asf.cpp:481
Utility templates and functions for working with strings and streams.
Exception that provides a stack of explanations.
Definition: error.h:36
A sound channel.
Definition: sound.h:202
static const size_t kOpenALBufferSize
Number of bytes per OpenAL buffer.
Definition: sound.cpp:63
void exceptionDispatcherWarning(const char *s,...)
Exception dispatcher that prints the exception as a warning, and adds another reason on top...
Definition: error.cpp:158
std::list< ALuint > buffers
List of buffers for that channel.
Definition: sound.h:212
bool wait(uint32 timeout=0)
Definition: mutex.cpp:121
Definition: game.h:37
Basic exceptions to throw.
A rewindable audio stream.
Definition: audiostream.h:125
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
bool createThread(const UString &name="")
Definition: thread.cpp:44
float gain
The channel&#39;s gain.
Definition: sound.h:223
bool isPaused(const ChannelHandle &handle)
Is that channel currently paused?
Definition: sound.cpp:232
#define ConfigMan
Shortcut for accessing the config manager.
Definition: configman.h:176
Utility templates and functions.
ALuint source
OpenAL source for this channel.
Definition: sound.h:210
RewindableAudioStream * makeWAVStream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Try to load a WAVE from the given seekable stream and create an AudioStream from that data...
Definition: wave.cpp:38
virtual size_t readBuffer(int16 *buffer, const size_t numSamples)=0
Fill the given buffer with up to numSamples samples.
uint64 getChannelDurationPlayed(const ChannelHandle &handle)
Return the time this channel has already played in milliseconds.
Definition: sound.cpp:635
static const size_t kSizeInvalid
Definition: audiostream.h:72
#define DECLARE_SINGLETON(T)
Note that you need to use this macro from the global namespace.
Definition: singleton.h:122
Common::Condition _needUpdate
Condition to signal that an update is needed.
Definition: sound.h:243
void checkReady()
Check that the SoundManager was properly initialized.
Definition: sound.cpp:780
void bufferData(Channel &channel)
Buffer more sound from the channel to the OpenAL buffers.
Definition: sound.cpp:729
ALCdevice * _dev
Definition: sound.h:245
The global events manager.
Common::UString formatChannel(const ChannelHandle &handle) const
Return a string representing the channel referenced by this handle.
Definition: sound.cpp:915
void setChannelGain(const ChannelHandle &handle, float gain)
Set the gain/volume of the channel.
Definition: sound.cpp:566
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
Definition: readstream.h:317
Common::Mutex _mutex
Definition: sound.h:240
void update()
Update the sound information.
Definition: sound.cpp:785
The global sound manager, handling all sound output.
RewindableAudioStream * makeVorbisStream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Create a new RewindableAudioStream from the Ogg Vorbis data in the given stream.
Definition: vorbis.cpp:516
Video/Movie.
Definition: types.h:47
void setChannelPosition(const ChannelHandle &handle, float x, float y, float z)
Set the position the channel is being played.
Definition: sound.cpp:536
StackException Exception
Definition: error.h:59
void setListenerGain(float gain)
Set the gain of the listener (= the global master volume).
Definition: sound.cpp:510
SoundType type
The channel&#39;s sound type.
Definition: sound.h:217
void warning(const char *s,...)
Definition: util.cpp:33
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
std::list< ALuint > freeBuffers
List of free buffers not filled with data.
Definition: sound.h:213
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
Convenience class that locks a mutex on creation and unlocks it on destruction.
Definition: mutex.h:71
Voice/Speech.
Definition: types.h:46
static const size_t kChannelCount
Maximal number of channels.
Definition: sound.h:190
Type _types[kSoundTypeMAX]
The sound types.
Definition: sound.h:236
std::map< ALuint, ALsizei > bufferSize
Size of a buffer in bytes.
Definition: sound.h:215
uint32 _curID
The ID the next sound will get.
Definition: sound.h:238
uint32 readUint32BE()
Read an unsigned 32-bit word stored in big endian (MSB first) order from the stream and return it...
Definition: readstream.h:166
bool _hasSound
Do we have working sound output?
Definition: sound.h:230
const Channel * getChannel(const ChannelHandle &handle) const
Return the channel the handle refers to.
Definition: sound.cpp:424
void stopChannel(ChannelHandle &handle)
Stop and free the channel.
Definition: sound.cpp:487
Generic audio input stream.
Definition: audiostream.h:70
void setChannelDistance(const ChannelHandle &handle, float minDistance, float maxDistance)
Set the min and max distance for the channel.
Definition: sound.cpp:601
ChannelHandle playAudioStream(AudioStream *audStream, SoundType type, bool disposeAfterUse=true)
Play an audio stream.
Definition: sound.cpp:330
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
uint32 id
The channel&#39;s ID.
Definition: sound.h:203
bool _hasMultiChannel
Do we have the multi-channel extension?
Definition: sound.h:232
Decoding Ogg Vorbis.
A handle to a sound channel.
Definition: types.h:35
SoundType
The type of a sound.
Definition: types.h:43
uint32_t uint32
Definition: types.h:204
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
Definition: strutil.cpp:117
ALCcontext * _ctx
Definition: sound.h:246
void pauseChannel(ChannelHandle &handle, bool pause)
Pause the channel.
Definition: sound.cpp:474
void setListenerPosition(float x, float y, float z)
Set the position of the listener.
Definition: sound.cpp:519
void pauseAll(bool pause)
Pause all channels.
Definition: sound.cpp:496
size_t index
The channel&#39;s index.
Definition: sound.h:204
Sound effect.
Definition: types.h:45
static const size_t kChannelInvalid
Definition: types.h:32
Common::DisposablePtr< AudioStream > stream
The actual audio stream.
Definition: sound.h:208
AudioStream * makeLoopingAudioStream(RewindableAudioStream *stream, size_t loops)
Wrapper functionality to efficiently create a stream, which might be looped.
void triggerUpdate()
Signal that one of streams currently being played has changed and should be updated immediately...
Definition: sound.cpp:158
bool fillBuffer(const Channel &channel, ALuint alBuffer, AudioStream *stream, ALsizei &bufferedSize) const
Fill the buffer with data from the audio stream.
Definition: sound.cpp:662
bool ready() const
Was the sound subsystem successfully initialized?
Definition: sound.cpp:154
Decoding Microsoft&#39;s Advanced Streaming Format.
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
Decoding MP3 (MPEG-1 Audio Layer 3).
RewindableAudioStream * makeMP3Stream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Create a new SeekableAudioStream from the MP3 data in the given stream.
Definition: mp3.cpp:353
uint64 finishedBuffers
Number of bytes in all buffers that finished playing and were unqueued.
Definition: sound.h:221
ChannelHandle playSoundFile(Common::SeekableReadStream *wavStream, SoundType type, bool loop=false)
Play a sound file.
Definition: sound.cpp:402
void NORETURN_PRE error(const char *s,...)
Definition: util.cpp:86
uint64 getChannelSamplesPlayed(const ChannelHandle &handle)
Return the number of samples this channel has already played.
Definition: sound.cpp:614
void freeChannel(ChannelHandle &handle)
Stop and free a channel.
Definition: sound.cpp:860
size_t channel
Definition: types.h:36
bool isPlaying(const ChannelHandle &handle)
Is that channel currently playing a sound?
Definition: sound.cpp:174
Interface for a seekable & readable data stream.
Definition: readstream.h:265
Streaming audio.
ALenum _format51
The value for the 5.1 multi-channel format.
Definition: sound.h:233
uint8 byte
Definition: types.h:209
The sound manager.
Definition: sound.h:60
unsigned int uint
Definition: types.h:211
virtual bool endOfData() const =0
End of data reached? If this returns true, it means that at this time there is no data available in t...
void threadMethod()
Definition: sound.cpp:901
ChannelHandle newChannel()
Look for a free place in the channel vector.
Definition: sound.cpp:808