5#include "cAudioSource.h"
10#include "cAudioSleep.h"
14#if CAUDIO_EFX_ENABLED == 1
15#include "cOpenALDeviceContext.h"
21 ALfloat GetBufferLength(ALuint buffer)
23 ALint size, bits, channels, freq;
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)
32 return (ALfloat)((ALuint)size/channels/(bits/8)) / (ALfloat)freq;
35 ALint GetBufferSize(ALuint buffer)
38 alGetBufferi(buffer, AL_SIZE, &size);
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)
51 cAudioSource::cAudioSource(IAudioDecoder* decoder, IAudioDeviceContext* context)
52 : cAudioSourceBase(context), Decoder(decoder), Loop(false), Valid(false)
55 cAudioMutexBasicLock lock(Mutex);
59 for(
int i=0; i<CAUDIO_SOURCE_NUM_BUFFERS; ++i) {
63#if CAUDIO_EFX_ENABLED == 1
64 for(
int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
67 for(
int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
68 LastEffectTimeStamp[i] = 0;
74 ALboolean state = alIsSource(Source);
79 alGenBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers);
80 state = !checkALError();
83#if CAUDIO_EFX_ENABLED == 1
84 Valid = state && (Decoder != NULL) && (Context != NULL) && (EFX != NULL);
87 ALCdevice* device = alcGetContextsDevice(((cOpenALDeviceContext*)Context)->getOpenALContext());
88 alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &numSlots);
90 EffectSlotsAvailable = (numSlots <= CAUDIO_SOURCE_MAX_EFFECT_SLOTS) ? numSlots : CAUDIO_SOURCE_MAX_EFFECT_SLOTS;
92 Valid = state && (Decoder != NULL) && (Context != NULL);
96 cAudioSource::~cAudioSource()
98 cAudioMutexBasicLock lock(Mutex);
100#if CAUDIO_EFX_ENABLED == 1
101 for(
int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
114 alSourceStop(Source);
117 alSourcei(Source, AL_BUFFER, 0);
119 alDeleteBuffers(CAUDIO_SOURCE_NUM_BUFFERS, Buffers);
128 cAudioSourceBase::cAudioSourceBase(IAudioDeviceContext* context) :
129 Context(context), Volume(1.f), Source(0)
131 alGenSources(1, &Source);
136 cAudioSourceBase::~cAudioSourceBase()
138 alSourceStop(Source);
140 alDeleteSources(1, &Source);
144 signalEvent(ON_RELEASE);
148 bool cAudioSource::drop()
153 Context->getAudioManager()->release(
this);
159 bool cAudioSource::play()
166 alSourcei(Source, AL_BUFFER, 0);
167 BufferPosition = Decoder->getCurrentPosition();
168 BufferTime = Decoder->getCurrentTime();
170 for(
int u = 0; u < CAUDIO_SOURCE_NUM_BUFFERS; u++)
172 int val = stream(Buffers[u]);
182 alSourceQueueBuffers(Source, queueSize, Buffers);
185#if CAUDIO_EFX_ENABLED == 1
187 for(
unsigned int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
190 alSourcePlay(Source);
193 signalEvent(ON_PLAY);
194 oldState = AL_PLAYING;
198 bool cAudioSource::play2d(
const bool& toLoop)
201 alSourcei(Source, AL_SOURCE_RELATIVE,
true);
208 bool cAudioSource::play3d(
const cVector3& position,
const float& soundstr,
const bool& toLoop)
211 alSourcei(Source, AL_SOURCE_RELATIVE,
false);
212 setPosition(position);
213 setStrength(soundstr);
220 void cAudioSource::pause()
223 alSourcePause(Source);
226 signalEvent(ON_PAUSE);
227 oldState = AL_PAUSED;
230 void cAudioSource::stop()
233 alSourceStop(Source);
237 alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
241 alSourceUnqueueBuffers(Source, 1, &buffer);
245 Decoder->setPosition(0,
false);
248 signalEvent(ON_STOP);
249 oldState = AL_STOPPED;
252 void cAudioSource::loop(
const bool& loop)
258 bool cAudioSource::seek(
const float& seconds,
bool relative)
262 if(Decoder->isSeekingSupported())
264 state = Decoder->seek(seconds, relative);
266 BufferPosition = Decoder->getCurrentPosition();
267 BufferTime = Decoder->getCurrentTime();
270 alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
272 BufferPosition -= queued * GetBufferSize(Buffers[0]);
273 BufferTime -= queued * GetBufferLength(Buffers[0]);
279 float cAudioSource::getTotalAudioTime()
281 return Decoder->getTotalTime();
284 int cAudioSource::getTotalAudioSize()
286 return Decoder->getTotalSize();
289 int cAudioSource::getCompressedAudioSize()
291 return Decoder->getCompressedSize();
294 float cAudioSource::getCurrentAudioTime()
297 alGetSourcef(Source, AL_SEC_OFFSET, &time);
298 return BufferTime + time;
301 int cAudioSource::getCurrentAudioPosition()
304 alGetSourcei(Source, AL_BYTE_OFFSET, &offset);
305 return BufferPosition + offset;
308 int cAudioSource::getCurrentCompressedAudioPosition()
310 return Decoder->getCurrentCompressedPosition();
313 bool cAudioSource::update()
319 if(isValid() || isPlaying())
321#if CAUDIO_EFX_ENABLED == 1
323 for(
unsigned int i=0; i<CAUDIO_SOURCE_MAX_EFFECT_SLOTS; ++i)
328 alGetSourcei(Source, AL_BUFFERS_PROCESSED, &processed);
335 alSourceUnqueueBuffers(Source, 1, &buffer);
336 BufferPosition += GetBufferSize(buffer);
337 BufferTime += GetBufferLength(buffer);
346 active = stream(buffer);
351 alSourceQueueBuffers(Source, 1, &buffer);
362 signalEvent(ON_UPDATE);
366 alGetSourcei(Source, AL_SOURCE_STATE, &state);
368 if(state == AL_STOPPED && oldState != state)
371 Decoder->setPosition(0,
false);
373 signalEvent(ON_STOP);
380 bool cAudioSource::isValid()
const
385 bool cAudioSourceBase::isPlaying()
const
388 alGetSourcei(Source, AL_SOURCE_STATE, &state);
390 return (state == AL_PLAYING);
393 bool cAudioSourceBase::isPaused()
const
396 alGetSourcei(Source, AL_SOURCE_STATE, &state);
398 return (state == AL_PAUSED);
401 bool cAudioSourceBase::isStopped()
const
404 alGetSourcei(Source, AL_SOURCE_STATE, &state);
406 return (state == AL_STOPPED);
409 bool cAudioSource::isLooping()
const
414 void cAudioSourceBase::setPosition(
const cVector3& position)
417 alSource3f(Source, AL_POSITION, position.x, position.y, position.z);
421 void cAudioSourceBase::setVelocity(
const cVector3& velocity)
424 alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
428 void cAudioSourceBase::setDirection(
const cVector3& direction)
431 alSource3f(Source, AL_DIRECTION, direction.x, direction.y, direction.z);
435 void cAudioSourceBase::setRolloffFactor(
const float& rolloff)
438 alSourcef(Source, AL_ROLLOFF_FACTOR, rolloff);
442 void cAudioSourceBase::setStrength(
const float& soundstrength)
444 float inverseStrength = 0.0f;
445 if(soundstrength > 0.0f)
446 inverseStrength = 1.0f / soundstrength;
449 alSourcef(Source, AL_ROLLOFF_FACTOR, inverseStrength);
453 void cAudioSourceBase::setMinDistance(
const float& minDistance)
456 alSourcef(Source, AL_REFERENCE_DISTANCE, minDistance);
460 void cAudioSourceBase::setMaxAttenuationDistance(
const float& maxDistance)
463 alSourcef(Source, AL_MAX_DISTANCE, maxDistance);
467 void cAudioSourceBase::setPitch(
const float& pitch)
470 alSourcef (Source, AL_PITCH, pitch);
474 void cAudioSourceBase::setVolume(
const float& volume)
478 alSourcef(Source, AL_GAIN, Volume * Context->getAudioManager()->getMasterVolume());
482 void cAudioSourceBase::setMinVolume(
const float& minVolume)
485 alSourcef(Source, AL_MIN_GAIN, minVolume);
489 void cAudioSourceBase::setMaxVolume(
const float& maxVolume)
492 alSourcef(Source, AL_MAX_GAIN, maxVolume);
496 void cAudioSourceBase::setInnerConeAngle(
const float& innerAngle)
499 alSourcef(Source, AL_CONE_INNER_ANGLE, innerAngle);
503 void cAudioSourceBase::setOuterConeAngle(
const float& outerAngle)
506 alSourcef(Source, AL_CONE_OUTER_ANGLE, outerAngle);
510 void cAudioSourceBase::setOuterConeVolume(
const float& outerVolume)
513 alSourcef(Source, AL_CONE_OUTER_GAIN, outerVolume);
517 void cAudioSourceBase::setDopplerStrength(
const float& dstrength)
520 alSourcef(Source, AL_DOPPLER_FACTOR, dstrength);
524 void cAudioSourceBase::setDopplerVelocity(
const cVector3& dvelocity)
527 alSource3f(Source, AL_DOPPLER_VELOCITY, dvelocity.x, dvelocity.y, dvelocity.z);
531 void cAudioSourceBase::move(
const cVector3& position)
535 cVector3 velocity = position - oldPos;
537 alSource3f(Source, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
538 alSource3f(Source, AL_POSITION, position.x, position.y, position.z);
545 alGetSourcefv(Source, AL_POSITION, &position.x);
553 alGetSourcefv(Source, AL_VELOCITY, &velocity.x);
560 alGetSourcefv(Source, AL_DIRECTION, &direction.x);
565 float cAudioSourceBase::getRolloffFactor()
const
568 alGetSourcef(Source, AL_ROLLOFF_FACTOR, &value);
573 float cAudioSourceBase::getStrength()
const
576 alGetSourcef(Source, AL_ROLLOFF_FACTOR, &value);
579 float inverseStrength = 0.0f;
581 inverseStrength = 1.0f / value;
583 return inverseStrength;
586 float cAudioSourceBase::getMinDistance()
const
589 alGetSourcef(Source, AL_REFERENCE_DISTANCE, &value);
594 float cAudioSourceBase::getMaxDistance()
const
597 alGetSourcef(Source, AL_MAX_DISTANCE, &value);
602 bool cAudioSourceBase::isRelative()
const
605 alGetSourcei(Source, AL_SOURCE_RELATIVE, &relative);
609 float cAudioSourceBase::calculateGain()
const
618 cVector3 lpos = Context->getAudioManager()->getListener()->getPosition();
621 float refDist = getMinDistance();
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();
630 float cAudioSourceBase::getPitch()
const
633 alGetSourcef(Source, AL_PITCH, &value);
638 float cAudioSourceBase::getVolume()
const
643 float cAudioSourceBase::getMinVolume()
const
646 alGetSourcef(Source, AL_MIN_GAIN, &value);
651 float cAudioSourceBase::getMaxVolume()
const
654 alGetSourcef(Source, AL_MAX_GAIN, &value);
659 float cAudioSourceBase::getInnerConeAngle()
const
662 alGetSourcef(Source, AL_CONE_INNER_ANGLE, &value);
667 float cAudioSourceBase::getOuterConeAngle()
const
670 alGetSourcef(Source, AL_CONE_OUTER_ANGLE, &value);
675 float cAudioSourceBase::getOuterConeVolume()
const
678 alGetSourcef(Source, AL_CONE_OUTER_GAIN, &value);
683 float cAudioSourceBase::getDopplerStrength()
const
686 alGetSourcef(Source, AL_DOPPLER_FACTOR, &value);
691 cVector3 cAudioSourceBase::getDopplerVelocity()
const
694 alGetSourcefv(Source, AL_DOPPLER_VELOCITY, &velocity.x);
699#if CAUDIO_EFX_ENABLED == 1
700 unsigned int cAudioSource::getNumEffectSlotsAvailable()
const
702 return EffectSlotsAvailable;
705 bool cAudioSource::attachEffect(
unsigned int slot, IEffect* effect)
707 cAudioMutexBasicLock lock(Mutex);
708 if(slot < EffectSlotsAvailable)
710 Effects[slot] = effect;
713 Effects[slot]->grab();
721 void cAudioSource::removeEffect(
unsigned int slot)
723 cAudioMutexBasicLock lock(Mutex);
724 if(slot < EffectSlotsAvailable)
727 Effects[slot]->drop();
729 Effects[slot] = NULL;
730 LastEffectTimeStamp[slot] = 0;
731 updateEffect(slot,
true);
735 bool cAudioSource::attachFilter(IFilter* filter)
737 cAudioMutexBasicLock lock(Mutex);
747 void cAudioSource::removeFilter()
749 cAudioMutexBasicLock lock(Mutex);
753 LastFilterTimeStamp = 0;
758 void cAudioSource::empty()
761 alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
767 alSourceUnqueueBuffers(Source, 1, &buffer);
772 bool cAudioSource::stream(ALuint buffer)
778 size_t totalread = 0;
779 unsigned int errorcount = 0;
780 char tempbuffer[CAUDIO_SOURCE_BUFFER_SIZE];
781 while( totalread < CAUDIO_SOURCE_BUFFER_SIZE )
783 char tempbuffer2[CAUDIO_SOURCE_BUFFER_SIZE];
785 int actualread = Decoder->readAudioData(tempbuffer2, CAUDIO_SOURCE_BUFFER_SIZE-totalread);
790 memcpy(tempbuffer+totalread,tempbuffer2,actualread);
791 totalread += actualread;
796 getLogger()->
logDebug(
"Audio Source",
"Decoder returned an error: %i (%i of 3)", actualread, errorcount);
808 Decoder->setPosition(0,
false);
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());
827#if CAUDIO_EFX_ENABLED == 1
828 void cAudioSource::updateFilter(
bool remove)
832 if(Filter && Filter->isValid())
834 if(LastFilterTimeStamp != Filter->getLastUpdated())
836 LastFilterTimeStamp = Filter->getLastUpdated();
837 cFilter* theFilter =
static_cast<cFilter*
>(Filter);
840 alSourcei(Source, AL_DIRECT_FILTER, theFilter->getOpenALFilter());
848 alSourcei(Source, AL_DIRECT_FILTER, AL_FILTER_NULL);
852 void cAudioSource::updateEffect(
unsigned int slot,
bool remove)
854 if(slot < EffectSlotsAvailable)
858 if(Effects[slot] && Effects[slot]->isValid())
860 if(LastEffectTimeStamp[slot] != Effects[slot]->getLastUpdated())
862 LastEffectTimeStamp[slot] = Effects[slot]->getLastUpdated();
863 cEffect* theEffect =
static_cast<cEffect*
>(Effects[slot]);
866 ALuint filterID = AL_FILTER_NULL;
867 cFilter* theFilter =
static_cast<cFilter*
>(theEffect->getFilter());
870 filterID = theFilter->getOpenALFilter();
872 alSource3i(Source, AL_AUXILIARY_SEND_FILTER, theEffect->getOpenALEffectSlot(), slot, filterID);
880 alSource3i(Source, AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, slot, AL_FILTER_NULL);
891 eventHandlerList.push_back(handler);
900 for(
int i=0; i<eventHandlerList.size(); i++) {
901 if(eventHandlerList[i] == handler)
902 eventHandlerList.erase(eventHandlerList.begin() + i);
907 void cAudioSourceBase::unRegisterAllEventHandlers()
910 eventHandlerList.clear();
913 void cAudioSourceBase::signalEvent(Events sevent)
916 if(eventHandlerList.empty())
919 size_t size = eventHandlerList.size();
921 for(
int i=0; i<size; )
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;
935 if(size == eventHandlerList.size()) {
938 size = eventHandlerList.size();
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.
float length() const
Returns the length (magnitude) of the vector.
Main namespace for the entire cAudio library.
ALenum convertAudioFormatEnum(AudioFormats format)
Converts our audio format enum to OpenAL's.
CAUDIO_API ILogger * getLogger()
Gets the interface to the logger.
CAUDIO_API void cAudioSleep(unsigned int ms)
Causes the current thread to give up control for a certain duration.