cAudio  2.3.0
3d Audio Engine
 All Classes Namespaces Functions Variables Enumerations Pages
cAudioSource.cpp
1 // Copyright (c) 2008-2011 Raynaldo (Wildicv) Rivera, Joshua (Dark_Kilauea) Jones, Murat (wolfmanfx) Sari
2 // This file is part of the "cAudio Engine"
3 // For conditions of distribution and use, see copyright notice in cAudio.h
4 
5 #include "cAudioSource.h"
6 #include "cAudio.h"
7 #include "cLogger.h"
8 #include "cFilter.h"
9 #include "cEffect.h"
10 #include "cAudioSleep.h"
11 #include <string.h>
12 #include <algorithm>
13 
14 #if CAUDIO_EFX_ENABLED == 1
15 #include "cOpenALDeviceContext.h"
16 #endif
17 
18 namespace
19 {
20  // return buffer length in seconds
21  ALfloat GetBufferLength(ALuint buffer)
22  {
23  ALint size, bits, channels, freq;
24 
25  alGetBufferi(buffer, AL_SIZE, &size);
26  alGetBufferi(buffer, AL_BITS, &bits);
27  alGetBufferi(buffer, AL_CHANNELS, &channels);
28  alGetBufferi(buffer, AL_FREQUENCY, &freq);
29  if(alGetError() != AL_NO_ERROR || !bits || !channels || !freq)
30  return -1.0f;
31 
32  return (ALfloat)((ALuint)size/channels/(bits/8)) / (ALfloat)freq;
33  }
34 
35  ALint GetBufferSize(ALuint buffer)
36  {
37  ALint size;
38  alGetBufferi(buffer, AL_SIZE, &size);
39  return size;
40  }
41 }
42 
43 namespace cAudio
44 {
45 
46 #if CAUDIO_EFX_ENABLED == 1
47  cAudioSource::cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context, cEFXFunctions* oALFunctions)
48  : cAudioSourceBase(context), Decoder(decoder), Loop(false), Valid(false),
49  EFX(oALFunctions), Filter(NULL), EffectSlotsAvailable(0), LastFilterTimeStamp(0)
50 #else
51  cAudioSource::cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context)
52  : cAudioSourceBase(context), Decoder(decoder), Loop(false), Valid(false)
53 #endif
54  {
55  cAudioMutexBasicLock lock(Mutex);
56 
57  BufferPosition = 0;
58  BufferTime = 0;
59  for(int i=0; i<CAUDIO_SOURCE_NUM_BUFFERS; ++i) {
60  Buffers[i] = 0;
61  }
62 
63 #if CAUDIO_EFX_ENABLED == 1
64  for(int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
65  Effects[i] = NULL;
66 
67  for(int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
68  LastEffectTimeStamp[i] = 0;
69 #endif
70 
71  if(Decoder)
72  Decoder->grab();
73 
74  ALboolean state = alIsSource(Source);
75 
76  if (state)
77  {
78  //Generates 3 buffers for the ogg file
79  alGenBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers);
80  state = !checkALError();
81  }
82 
83 #if CAUDIO_EFX_ENABLED == 1
84  Valid = state && (Decoder != NULL) && (Context != NULL) && (EFX != NULL);
85 
86  int numSlots = 0;
87  ALCdevice* device = alcGetContextsDevice(((cOpenALDeviceContext*)Context)->getOpenALContext());
88  alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &numSlots);
89 
90  EffectSlotsAvailable = (numSlots <= CAUDIO_SOURCE_MAX_EFFECT_SLOTS) ? numSlots : CAUDIO_SOURCE_MAX_EFFECT_SLOTS;
91 #else
92  Valid = state && (Decoder != NULL) && (Context != NULL);
93 #endif
94  }
95 
96  cAudioSource::~cAudioSource()
97  {
98  cAudioMutexBasicLock lock(Mutex);
99 
100 #if CAUDIO_EFX_ENABLED == 1
101  for(int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
102  {
103  if(Effects[i])
104  Effects[i]->drop();
105  Effects[i] = NULL;
106  }
107 
108  if(Filter)
109  Filter->drop();
110  Filter = NULL;
111 #endif
112 
113  //Stops the audio Source
114  alSourceStop(Source);
115  checkALError();
116  empty();
117  alSourcei(Source, AL_BUFFER, 0);
118  //deletes the last filled buffer
119  alDeleteBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers);
120  checkALError();
121 
122  if(Decoder) {
123  Decoder->drop();
124  Decoder = NULL;
125  }
126  }
127 
128  cAudioSourceBase::cAudioSourceBase(IAudioDeviceContext* context) :
129  Context(context), Volume(1.f), Source(0)
130  {
131  alGenSources(1, &Source);
132  checkALError();
133  setVolume(Volume);
134  }
135 
136  cAudioSourceBase::~cAudioSourceBase()
137  {
138  alSourceStop(Source);
139  checkALError();
140  alDeleteSources(1, &Source);
141  checkALError();
142 
143  getLogger()->logDebug("Audio Source", "Audio source released.");
144  signalEvent(ON_RELEASE);
145  }
146 
147 
148  bool cAudioSource::drop()
149  {
150  --RefCount;
151  if (RefCount == 0)
152  {
153  Context->getAudioManager()->release(this);
154  return true;
155  }
156  return false;
157  }
158 
159  bool cAudioSource::play()
160  {
161  cAudioMutexBasicLock lock(Mutex);
162  if (!isPaused())
163  {
164  int queueSize = 0;
165  //Purges all buffers from the source
166  alSourcei(Source, AL_BUFFER, 0);
167  BufferPosition = Decoder->getCurrentPosition();
168  BufferTime = Decoder->getCurrentTime();
169  checkALError();
170  for(int u = 0; u < CAUDIO_SOURCE_NUM_BUFFERS; u++)
171  {
172  int val = stream(Buffers[u]);
173 
174  if(val < 0)
175  {
176  return false;
177  }
178  else if(val > 0)
179  ++queueSize;
180  }
181  //Stores the sources 3 buffers to be used in the queue
182  alSourceQueueBuffers(Source, queueSize, Buffers);
183  checkALError();
184  }
185 #if CAUDIO_EFX_ENABLED == 1
186  updateFilter();
187  for(unsigned int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
188  updateEffect(i);
189 #endif
190  alSourcePlay(Source);
191  checkALError();
192  getLogger()->logDebug("Audio Source", "Source playing.");
193  signalEvent(ON_PLAY);
194  oldState = AL_PLAYING;
195  return true;
196  }
197 
198  bool cAudioSource::play2d(const bool& toLoop)
199  {
200  cAudioMutexBasicLock lock(Mutex);
201  alSourcei(Source, AL_SOURCE_RELATIVE, true);
202  loop(toLoop);
203  bool state = play();
204  checkALError();
205  return state;
206  }
207 
208  bool cAudioSource::play3d(const cVector3& position, const float& soundstr, const bool& toLoop)
209  {
210  cAudioMutexBasicLock lock(Mutex);
211  alSourcei(Source, AL_SOURCE_RELATIVE, false);
212  setPosition(position);
213  setStrength(soundstr);
214  loop(toLoop);
215  bool state = play();
216  checkALError();
217  return state;
218  }
219 
220  void cAudioSource::pause()
221  {
222  cAudioMutexBasicLock lock(Mutex);
223  alSourcePause(Source);
224  checkALError();
225  getLogger()->logDebug("Audio Source", "Source paused.");
226  signalEvent(ON_PAUSE);
227  oldState = AL_PAUSED;
228  }
229 
230  void cAudioSource::stop()
231  {
232  cAudioMutexBasicLock lock(Mutex);
233  alSourceStop(Source);
234 
235  //INFO:FIXED EXTREME SLOWDOWN ON IPHONE
236  int queued = 0;
237  alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
238  while ( queued-- )
239  {
240  ALuint buffer;
241  alSourceUnqueueBuffers(Source, 1, &buffer);
242  }
243 
244  //Resets the audio to the beginning
245  Decoder->setPosition(0, false);
246  checkALError();
247  getLogger()->logDebug("Audio Source", "Source stopped.");
248  signalEvent(ON_STOP);
249  oldState = AL_STOPPED;
250  }
251 
252  void cAudioSource::loop(const bool& loop)
253  {
254  cAudioMutexBasicLock lock(Mutex);
255  Loop = loop;
256  }
257 
258  bool cAudioSource::seek(const float& seconds, bool relative)
259  {
260  bool state = false;
261  cAudioMutexBasicLock lock(Mutex);
262  if(Decoder->isSeekingSupported())
263  {
264  state = Decoder->seek(seconds, relative);
265 
266  BufferPosition = Decoder->getCurrentPosition();
267  BufferTime = Decoder->getCurrentTime();
268 
269  int queued = 0;
270  alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
271  if (queued) {
272  BufferPosition -= queued * GetBufferSize(Buffers[0]);
273  BufferTime -= queued * GetBufferLength(Buffers[0]);
274  }
275  }
276  return state;
277  }
278 
279  float cAudioSource::getTotalAudioTime()
280  {
281  return Decoder->getTotalTime();
282  }
283 
284  int cAudioSource::getTotalAudioSize()
285  {
286  return Decoder->getTotalSize();
287  }
288 
289  int cAudioSource::getCompressedAudioSize()
290  {
291  return Decoder->getCompressedSize();
292  }
293 
294  float cAudioSource::getCurrentAudioTime()
295  {
296  float time = -1;
297  alGetSourcef(Source, AL_SEC_OFFSET, &time);
298  return BufferTime + time;
299  }
300 
301  int cAudioSource::getCurrentAudioPosition()
302  {
303  int offset = -1;
304  alGetSourcei(Source, AL_BYTE_OFFSET, &offset);
305  return BufferPosition + offset;
306  }
307 
308  int cAudioSource::getCurrentCompressedAudioPosition()
309  {
310  return Decoder->getCurrentCompressedPosition();
311  }
312 
313  bool cAudioSource::update()
314  {
315  cAudioMutexBasicLock lock(Mutex);
316 
317  int processed = 0;
318  bool active = true;
319  if(isValid() || isPlaying())
320  {
321 #if CAUDIO_EFX_ENABLED == 1
322  updateFilter();
323  for(unsigned int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
324  updateEffect(i);
325 #endif
326 
327  //gets the sound source processed buffers
328  alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed);
329  checkALError();
330 
331  //while there is more data refill buffers with audio data.
332  while (processed--)
333  {
334  ALuint buffer;
335  alSourceUnqueueBuffers(Source, 1, &buffer);
336  BufferPosition += GetBufferSize(buffer);
337  BufferTime += GetBufferLength(buffer);
338 
339  if (checkALError())
340  {
341  processed++;
342  cAudioSleep(1);
343  continue;
344  }
345 
346  active = stream(buffer);
347 
348  //if more in stream continue playing.
349  if(active)
350  {
351  alSourceQueueBuffers(Source, 1, &buffer);
352  }
353 
354  if (checkALError())
355  {
356  processed++;
357  cAudioSleep(1);
358  continue;
359  }
360  }
361 
362  signalEvent(ON_UPDATE);
363  }
364 
365  ALenum state;
366  alGetSourcei(Source, AL_SOURCE_STATE, &state);
367  checkALError();
368  if(state == AL_STOPPED && oldState != state)
369  {
370  //Resets the audio to the beginning
371  Decoder->setPosition(0, false);
372  getLogger()->logDebug("Audio Source", "Source stopped.");
373  signalEvent(ON_STOP);
374  oldState = state;
375  }
376 
377  return active;
378  }
379 
380  bool cAudioSource::isValid() const
381  {
382  return Valid;
383  }
384 
385  bool cAudioSourceBase::isPlaying() const
386  {
387  ALenum state = 0;
388  alGetSourcei(Source, AL_SOURCE_STATE, &state);
389  checkALError();
390  return (state == AL_PLAYING);
391  }
392 
393  bool cAudioSourceBase::isPaused() const
394  {
395  ALenum state = 0;
396  alGetSourcei(Source, AL_SOURCE_STATE, &state);
397  checkALError();
398  return (state == AL_PAUSED);
399  }
400 
401  bool cAudioSourceBase::isStopped() const
402  {
403  ALenum state = 0;
404  alGetSourcei(Source, AL_SOURCE_STATE, &state);
405  checkALError();
406  return (state == AL_STOPPED);
407  }
408 
409  bool cAudioSource::isLooping() const
410  {
411  return Loop;
412  }
413 
414  void cAudioSourceBase::setPosition(const cVector3& position)
415  {
416  cAudioMutexBasicLock lock(Mutex);
417  alSource3f(Source, AL_POSITION, position.x, position.y, position.z);
418  checkALError();
419  }
420 
421  void cAudioSourceBase::setVelocity(const cVector3& velocity)
422  {
423  cAudioMutexBasicLock lock(Mutex);
424  alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
425  checkALError();
426  }
427 
428  void cAudioSourceBase::setDirection(const cVector3& direction)
429  {
430  cAudioMutexBasicLock lock(Mutex);
431  alSource3f(Source, AL_DIRECTION, direction.x, direction.y, direction.z);
432  checkALError();
433  }
434 
435  void cAudioSourceBase::setRolloffFactor(const float& rolloff)
436  {
437  cAudioMutexBasicLock lock(Mutex);
438  alSourcef(Source, AL_ROLLOFF_FACTOR, rolloff);
439  checkALError();
440  }
441 
442  void cAudioSourceBase::setStrength(const float& soundstrength)
443  {
444  float inverseStrength = 0.0f;
445  if(soundstrength > 0.0f)
446  inverseStrength = 1.0f / soundstrength;
447 
448  cAudioMutexBasicLock lock(Mutex);
449  alSourcef(Source, AL_ROLLOFF_FACTOR, inverseStrength);
450  checkALError();
451  }
452 
453  void cAudioSourceBase::setMinDistance(const float& minDistance)
454  {
455  cAudioMutexBasicLock lock(Mutex);
456  alSourcef(Source, AL_REFERENCE_DISTANCE, minDistance);
457  checkALError();
458  }
459 
460  void cAudioSourceBase::setMaxAttenuationDistance(const float& maxDistance)
461  {
462  cAudioMutexBasicLock lock(Mutex);
463  alSourcef(Source, AL_MAX_DISTANCE, maxDistance);
464  checkALError();
465  }
466 
467  void cAudioSourceBase::setPitch(const float& pitch)
468  {
469  cAudioMutexBasicLock lock(Mutex);
470  alSourcef (Source, AL_PITCH, pitch);
471  checkALError();
472  }
473 
474  void cAudioSourceBase::setVolume(const float& volume)
475  {
476  cAudioMutexBasicLock lock(Mutex);
477  Volume = volume;
478  alSourcef(Source, AL_GAIN, Volume * Context->getAudioManager()->getMasterVolume());
479  checkALError();
480  }
481 
482  void cAudioSourceBase::setMinVolume(const float& minVolume)
483  {
484  cAudioMutexBasicLock lock(Mutex);
485  alSourcef(Source, AL_MIN_GAIN, minVolume);
486  checkALError();
487  }
488 
489  void cAudioSourceBase::setMaxVolume(const float& maxVolume)
490  {
491  cAudioMutexBasicLock lock(Mutex);
492  alSourcef(Source, AL_MAX_GAIN, maxVolume);
493  checkALError();
494  }
495 
496  void cAudioSourceBase::setInnerConeAngle(const float& innerAngle)
497  {
498  cAudioMutexBasicLock lock(Mutex);
499  alSourcef(Source, AL_CONE_INNER_ANGLE, innerAngle);
500  checkALError();
501  }
502 
503  void cAudioSourceBase::setOuterConeAngle(const float& outerAngle)
504  {
505  cAudioMutexBasicLock lock(Mutex);
506  alSourcef(Source, AL_CONE_OUTER_ANGLE, outerAngle);
507  checkALError();
508  }
509 
510  void cAudioSourceBase::setOuterConeVolume(const float& outerVolume)
511  {
512  cAudioMutexBasicLock lock(Mutex);
513  alSourcef(Source, AL_CONE_OUTER_GAIN, outerVolume);
514  checkALError();
515  }
516 
517  void cAudioSourceBase::setDopplerStrength(const float& dstrength)
518  {
519  cAudioMutexBasicLock lock(Mutex);
520  alSourcef(Source, AL_DOPPLER_FACTOR, dstrength);
521  checkALError();
522  }
523 
524  void cAudioSourceBase::setDopplerVelocity(const cVector3& dvelocity)
525  {
526  cAudioMutexBasicLock lock(Mutex);
527  alSource3f(Source, AL_DOPPLER_VELOCITY, dvelocity.x, dvelocity.y, dvelocity.z);
528  checkALError();
529  }
530 
531  void cAudioSourceBase::move(const cVector3& position)
532  {
533  cAudioMutexBasicLock lock(Mutex);
534  cVector3 oldPos = getPosition();
535  cVector3 velocity = position - oldPos;
536 
537  alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
538  alSource3f(Source, AL_POSITION, position.x, position.y, position.z);
539  checkALError();
540  }
541 
542  cVector3 cAudioSourceBase::getPosition() const
543  {
544  cVector3 position;
545  alGetSourcefv(Source, AL_POSITION, &position.x);
546  checkALError();
547  return position;
548  }
549 
550  cVector3 cAudioSourceBase::getVelocity() const
551  {
552  cVector3 velocity;
553  alGetSourcefv(Source, AL_VELOCITY, &velocity.x);
554  return velocity;
555  }
556 
557  cVector3 cAudioSourceBase::getDirection() const
558  {
559  cVector3 direction;
560  alGetSourcefv(Source, AL_DIRECTION, &direction.x);
561  checkALError();
562  return direction;
563  }
564 
565  float cAudioSourceBase::getRolloffFactor() const
566  {
567  float value = 0.0f;
568  alGetSourcef(Source, AL_ROLLOFF_FACTOR, &value);
569  checkALError();
570  return value;
571  }
572 
573  float cAudioSourceBase::getStrength() const
574  {
575  float value = 0.0f;
576  alGetSourcef(Source, AL_ROLLOFF_FACTOR, &value);
577  checkALError();
578 
579  float inverseStrength = 0.0f;
580  if(value > 0.0f)
581  inverseStrength = 1.0f / value;
582 
583  return inverseStrength;
584  }
585 
586  float cAudioSourceBase::getMinDistance() const
587  {
588  float value = 0.0f;
589  alGetSourcef(Source, AL_REFERENCE_DISTANCE, &value);
590  checkALError();
591  return value;
592  }
593 
594  float cAudioSourceBase::getMaxDistance() const
595  {
596  float value = 0.0f;
597  alGetSourcef(Source, AL_MAX_DISTANCE, &value);
598  checkALError();
599  return value;
600  }
601 
602  bool cAudioSourceBase::isRelative() const
603  {
604  int relative = 0;
605  alGetSourcei(Source, AL_SOURCE_RELATIVE, &relative);
606  return relative;
607  }
608 
609  float cAudioSourceBase::calculateGain() const
610  {
611  // OpenAL Inverse Distance Clamped Model
612  // distance = max(distance,AL_REFERENCE_DISTANCE);
613  // distance = min(distance,AL_MAX_DISTANCE);
614  // gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE +
615  // AL_ROLLOFF_FACTOR *
616  // (distance – AL_REFERENCE_DISTANCE));
617 
618  cVector3 lpos = Context->getAudioManager()->getListener()->getPosition();
619  cVector3 pos = getPosition();
620 
621  float refDist = getMinDistance();
622  float dist = 0.f;
623  dist = isRelative() ? pos.length() : (pos - lpos).length();
624  dist = std::max(dist, refDist);
625  dist = std::min(dist, getMaxDistance());
626  float gain = refDist / (refDist + getRolloffFactor() * (dist - refDist));
627  return gain * getVolume();
628  }
629 
630  float cAudioSourceBase::getPitch() const
631  {
632  float value = 0.0f;
633  alGetSourcef(Source, AL_PITCH, &value);
634  checkALError();
635  return value;
636  }
637 
638  float cAudioSourceBase::getVolume() const
639  {
640  return Volume;
641  }
642 
643  float cAudioSourceBase::getMinVolume() const
644  {
645  float value = 0.0f;
646  alGetSourcef(Source, AL_MIN_GAIN, &value);
647  checkALError();
648  return value;
649  }
650 
651  float cAudioSourceBase::getMaxVolume() const
652  {
653  float value = 0.0f;
654  alGetSourcef(Source, AL_MAX_GAIN, &value);
655  checkALError();
656  return value;
657  }
658 
659  float cAudioSourceBase::getInnerConeAngle() const
660  {
661  float value = 0.0f;
662  alGetSourcef(Source, AL_CONE_INNER_ANGLE, &value);
663  checkALError();
664  return value;
665  }
666 
667  float cAudioSourceBase::getOuterConeAngle() const
668  {
669  float value = 0.0f;
670  alGetSourcef(Source, AL_CONE_OUTER_ANGLE, &value);
671  checkALError();
672  return value;
673  }
674 
675  float cAudioSourceBase::getOuterConeVolume() const
676  {
677  float value = 0.0f;
678  alGetSourcef(Source, AL_CONE_OUTER_GAIN, &value);
679  checkALError();
680  return value;
681  }
682 
683  float cAudioSourceBase::getDopplerStrength() const
684  {
685  float value = 0.0f;
686  alGetSourcef(Source, AL_DOPPLER_FACTOR, &value);
687  checkALError();
688  return value;
689  }
690 
691  cVector3 cAudioSourceBase::getDopplerVelocity() const
692  {
693  cVector3 velocity;
694  alGetSourcefv(Source, AL_DOPPLER_VELOCITY, &velocity.x);
695  checkALError();
696  return velocity;
697  }
698 
699 #if CAUDIO_EFX_ENABLED == 1
700  unsigned int cAudioSource::getNumEffectSlotsAvailable() const
701  {
702  return EffectSlotsAvailable;
703  }
704 
705  bool cAudioSource::attachEffect(unsigned int slot, IEffect* effect)
706  {
707  cAudioMutexBasicLock lock(Mutex);
708  if(slot < EffectSlotsAvailable)
709  {
710  Effects[slot] = effect;
711 
712  if(Effects[slot])
713  Effects[slot]->grab();
714 
715  updateEffect(slot);
716  return true;
717  }
718  return false;
719  }
720 
721  void cAudioSource::removeEffect(unsigned int slot)
722  {
723  cAudioMutexBasicLock lock(Mutex);
724  if(slot < EffectSlotsAvailable)
725  {
726  if(Effects[slot])
727  Effects[slot]->drop();
728 
729  Effects[slot] = NULL;
730  LastEffectTimeStamp[slot] = 0;
731  updateEffect(slot, true);
732  }
733  }
734 
735  bool cAudioSource::attachFilter(IFilter* filter)
736  {
737  cAudioMutexBasicLock lock(Mutex);
738  Filter = filter;
739 
740  if(Filter)
741  Filter->grab();
742 
743  updateFilter();
744  return true;
745  }
746 
747  void cAudioSource::removeFilter()
748  {
749  cAudioMutexBasicLock lock(Mutex);
750  if(Filter)
751  Filter->drop();
752  Filter = NULL;
753  LastFilterTimeStamp = 0;
754  updateFilter(true);
755  }
756 #endif
757 
758  void cAudioSource::empty()
759  {
760  int queued = 0;
761  alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
762  checkALError();
763 
764  while (queued--)
765  {
766  ALuint buffer;
767  alSourceUnqueueBuffers(Source, 1, &buffer);
768  checkALError();
769  }
770  }
771 
772  bool cAudioSource::stream(ALuint buffer)
773  {
774  if(!Decoder)
775  return false;
776 
777  //stores the calculated data into buffer that is passed to output.
778  size_t totalread = 0;
779  unsigned int errorcount = 0;
780  char tempbuffer[CAUDIO_SOURCE_BUFFER_SIZE];
781  while( totalread < CAUDIO_SOURCE_BUFFER_SIZE )
782  {
783  char tempbuffer2[CAUDIO_SOURCE_BUFFER_SIZE];
784  Mutex.unlock(); // this can take a long time
785  int actualread = Decoder->readAudioData(tempbuffer2, CAUDIO_SOURCE_BUFFER_SIZE-totalread);
786  Mutex.lock();
787 
788  if(actualread > 0)
789  {
790  memcpy(tempbuffer+totalread,tempbuffer2,actualread);
791  totalread += actualread;
792  }
793  if(actualread < 0)
794  {
795  ++errorcount;
796  getLogger()->logDebug("Audio Source", "Decoder returned an error: %i (%i of 3)", actualread, errorcount);
797  if(errorcount >= 3)
798  {
799  stop();
800  break;
801  }
802  }
803  if(actualread == 0)
804  {
805  if(isLooping())
806  {
807  //If we are to loop, set to the beginning and reload from the start
808  Decoder->setPosition(0, false);
809  getLogger()->logDebug("Audio Source", "Buffer looping.");
810  }
811  else
812  break;
813  }
814  }
815 
816  //Second check, in case looping is not enabled, we will return false for end of stream
817  if(totalread == 0)
818  {
819  return false;
820  }
821  getLogger()->logDebug("Audio Source", "Buffered %i bytes of data into buffer %i at %i hz.", totalread, buffer, Decoder->getFrequency());
822  alBufferData(buffer, convertAudioFormatEnum(Decoder->getFormat()), tempbuffer, totalread, Decoder->getFrequency());
823  checkALError();
824  return true;
825  }
826 
827 #if CAUDIO_EFX_ENABLED == 1
828  void cAudioSource::updateFilter(bool remove)
829  {
830  if(!remove)
831  {
832  if(Filter && Filter->isValid())
833  {
834  if(LastFilterTimeStamp != Filter->getLastUpdated())
835  {
836  LastFilterTimeStamp = Filter->getLastUpdated();
837  cFilter* theFilter = static_cast<cFilter*>(Filter);
838  if(theFilter)
839  {
840  alSourcei(Source, AL_DIRECT_FILTER, theFilter->getOpenALFilter());
841  checkALError();
842  return;
843  }
844  }
845  return;
846  }
847  }
848  alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL);
849  checkALError();
850  }
851 
852  void cAudioSource::updateEffect(unsigned int slot, bool remove)
853  {
854  if(slot < EffectSlotsAvailable)
855  {
856  if(!remove)
857  {
858  if(Effects[slot] && Effects[slot]->isValid())
859  {
860  if(LastEffectTimeStamp[slot] != Effects[slot]->getLastUpdated())
861  {
862  LastEffectTimeStamp[slot] = Effects[slot]->getLastUpdated();
863  cEffect* theEffect = static_cast<cEffect*>(Effects[slot]);
864  if(theEffect)
865  {
866  ALuint filterID = AL_FILTER_NULL;
867  cFilter* theFilter = static_cast<cFilter*>(theEffect->getFilter());
868  if(theFilter)
869  {
870  filterID = theFilter->getOpenALFilter();
871  }
872  alSource3i(Source, AL_AUXILIARY_SEND_FILTER, theEffect->getOpenALEffectSlot(), slot, filterID);
873  checkALError();
874  return;
875  }
876  }
877  return;
878  }
879  }
880  alSource3i(Source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, slot, AL_FILTER_NULL);
881  checkALError();
882  }
883  }
884 #endif
885 
886  void cAudioSourceBase::registerEventHandler(ISourceEventHandler* handler)
887  {
888  if(handler)
889  {
890  cAudioMutexBasicLock lock(Mutex);
891  eventHandlerList.push_back(handler);
892  }
893  }
894 
895  void cAudioSourceBase::unRegisterEventHandler(ISourceEventHandler* handler)
896  {
897  if(handler)
898  {
899  cAudioMutexBasicLock lock(Mutex);
900  for(int i=0; i<eventHandlerList.size(); i++) {
901  if(eventHandlerList[i] == handler)
902  eventHandlerList.erase(eventHandlerList.begin() + i);
903  }
904  }
905  }
906 
907  void cAudioSourceBase::unRegisterAllEventHandlers()
908  {
909  cAudioMutexBasicLock lock(Mutex);
910  eventHandlerList.clear();
911  }
912 
913  void cAudioSourceBase::signalEvent(Events sevent)
914  {
915  cAudioMutexBasicLock lock(Mutex);
916  if(eventHandlerList.empty())
917  return;
918 
919  size_t size = eventHandlerList.size();
920 
921  for(int i=0; i<size; )
922  {
923  ISourceEventHandler *handler = eventHandlerList[i];
924 
925  switch(sevent)
926  {
927  case ON_UPDATE: handler->onUpdate(); break;
928  case ON_RELEASE: handler->onRelease(); break;
929  case ON_PLAY: handler->onPlay(); break;
930  case ON_PAUSE: handler->onPause(); break;
931  case ON_STOP: handler->onStop(); break;
932  }
933 
934  // handler may have unregistered itself
935  if(size == eventHandlerList.size()) {
936  i++;
937  } else {
938  size = eventHandlerList.size();
939  }
940  }
941  }
942 }
ALenum convertAudioFormatEnum(AudioFormats format)
Converts our audio format enum to OpenAL&#39;s.
Definition: cOpenALUtil.h:48
virtual void onStop()
This function is called when a source stopped playback.
virtual void logDebug(const char *sender, const char *msg,...)=0
Used to log a debug message to the logging system.
Interface for event handlers on Audio Sources.
virtual void onUpdate()
This function is called when a source updates its buffers.
Class for manipulating vectors in 3D space.
Definition: cVector3.h:22
virtual void onPlay()
This function is called when a source starts playing.
virtual void onPause()
This function is called when a source is paused.
virtual void onRelease()
This function is called when a source is released and soon to be deleted.
float length() const
Returns the length (magnitude) of the vector.
Definition: cVector3.h:99
CAUDIO_API ILogger * getLogger()
Gets the interface to the logger.
Definition: cAudio.cpp:45
CAUDIO_API void cAudioSleep(unsigned int ms)
Causes the current thread to give up control for a certain duration.
Definition: cAudioSleep.cpp:17