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();
ALenum convertAudioFormatEnum(AudioFormats format)
Converts our audio format enum to OpenAL's.
virtual void onStop()
This function is called when a source stopped playback.
float length() const
Returns the length (magnitude) of the vector.
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.
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.
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.
Main namespace for the entire cAudio library.