cAudio 2.3.0
3d Audio Engine
Loading...
Searching...
No Matches
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
18namespace
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
43namespace 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}
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 onPlay()
This function is called when a source starts playing.
virtual void onUpdate()
This function is called when a source updates its buffers.
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.
virtual void onStop()
This function is called when a source stopped playback.
Class for manipulating vectors in 3D space.
Definition: cVector3.h:23
float length() const
Returns the length (magnitude) of the vector.
Definition: cVector3.h:99
Main namespace for the entire cAudio library.
Definition: cAudioCapture.h:16
ALenum convertAudioFormatEnum(AudioFormats format)
Converts our audio format enum to OpenAL's.
Definition: cOpenALUtil.h:48
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