1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2012 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program 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 Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdopenal.h"
21 #include "sound_driver_al.h"
22 #include "listener_al.h"
23 #include "effect_al.h"
24 #include "buffer_al.h"
25 #include "source_al.h"
32 // #define NLSOUND_DEBUG_GAIN
35 using namespace NLMISC
;
39 CSourceAL::CSourceAL(CSoundDriverAL
*soundDriver
) :
40 _SoundDriver(NULL
), _Buffer(NULL
), _Source(AL_NONE
),
41 _DirectFilter(AL_FILTER_NULL
), _EffectFilter(AL_FILTER_NULL
),
42 _IsPlaying(false), _IsPaused(false), _StartTime(0), _IsStreaming(false), _RelativeMode(false),
43 _Pos(0.0f
, 0.0f
, 0.0f
), _Gain(NLSOUND_DEFAULT_GAIN
), _Alpha(1.0),
44 _MinDistance(1.0f
), _MaxDistance(sqrt(numeric_limits
<float>::max())),
45 _Effect(NULL
), _Direct(true),
46 _DirectGain(NLSOUND_DEFAULT_DIRECT_GAIN
), _EffectGain(NLSOUND_DEFAULT_EFFECT_GAIN
),
47 _DirectFilterType(ISource::FilterLowPass
), _EffectFilterType(ISource::FilterLowPass
),
48 _DirectFilterEnabled(false), _EffectFilterEnabled(false),
49 _DirectFilterPassGain(NLSOUND_DEFAULT_FILTER_PASS_GAIN
), _EffectFilterPassGain(NLSOUND_DEFAULT_FILTER_PASS_GAIN
)
51 // create the al source
52 alGenSources(1, &_Source
);
56 if (soundDriver
->getOption(ISoundDriver::OptionManualRolloff
))
58 alSourcef(_Source
, AL_ROLLOFF_FACTOR
, 0);
63 alSourcef(_Source
, AL_ROLLOFF_FACTOR
, soundDriver
->getRolloffFactor());
68 if (soundDriver
->getOption(ISoundDriver::OptionEnvironmentEffects
))
70 alGenFilters(1, &_DirectFilter
);
71 alFilteri(_DirectFilter
, AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
72 alFilterf(_DirectFilter
, AL_LOWPASS_GAIN
, NLSOUND_DEFAULT_DIRECT_GAIN
);
73 alFilterf(_DirectFilter
, AL_LOWPASS_GAINHF
, NLSOUND_DEFAULT_FILTER_PASS_GAIN
);
75 alGenFilters(1, &_EffectFilter
);
76 alFilteri(_EffectFilter
, AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
77 alFilterf(_EffectFilter
, AL_LOWPASS_GAIN
, NLSOUND_DEFAULT_EFFECT_GAIN
);
78 alFilterf(_EffectFilter
, AL_LOWPASS_GAINHF
, NLSOUND_DEFAULT_FILTER_PASS_GAIN
);
82 // if everything went well, the source will be added in the sounddriver
83 _SoundDriver
= soundDriver
;
86 CSourceAL::~CSourceAL()
88 CSoundDriverAL
*soundDriver
= _SoundDriver
;
90 if (soundDriver
) soundDriver
->removeSource(this);
93 void CSourceAL::release()
95 if (_Source
!= AL_NONE
) { alDeleteSources(1, &_Source
); _Source
= AL_NONE
; }
96 if (_DirectFilter
!= AL_FILTER_NULL
) { alDeleteFilters(1, &_DirectFilter
); _DirectFilter
= AL_FILTER_NULL
; }
97 if (_EffectFilter
!= AL_FILTER_NULL
) { alDeleteFilters(1, &_EffectFilter
); _EffectFilter
= AL_FILTER_NULL
; }
101 /// (Internal) Update the 3d changes.
102 void CSourceAL::updateManualRolloff()
104 CVector distanceVector
= _RelativeMode
? _Pos
: (_Pos
- CListenerAL::getInstance()->getPos());
105 float distanceSquare
= distanceVector
.sqrnorm();
106 float rolloff
= ISource::computeManualRolloff(_Alpha
, distanceSquare
, _MinDistance
, _MaxDistance
);
107 alSourcef(_Source
, AL_GAIN
, _Gain
* rolloff
);
109 #ifdef NLSOUND_DEBUG_GAIN
111 alGetSourcef(_Source
, AL_GAIN
, &gain
);
112 nlwarning("Called updateManualRolloff(), physical gain is %f, configured gain is %f, distanceSquare is %f, rolloff is %f", gain
, _Gain
, distanceSquare
, rolloff
);
117 /// Enable or disable streaming mode. Source must be stopped to call this.
118 void CSourceAL::setStreaming(bool streaming
)
120 nlassert(isStopped());
122 // bring the source type to AL_UNDETERMINED
123 alSourcei(_Source
, AL_BUFFER
, AL_NONE
);
126 _IsStreaming
= streaming
;
129 // make sure looping is disabled on OpenAL side
134 /* Set the buffer that will be played (no streaming)
135 * If the buffer is stereo, the source mode becomes stereo and the source relative mode is on,
136 * otherwise the source is considered as a 3D source.
138 void CSourceAL::setStaticBuffer( IBuffer
*buffer
)
141 alSourceStop(_Source
);
145 if ( buffer
== NULL
)
147 alSourcei(_Source
, AL_BUFFER
, AL_NONE
);
153 CBufferAL
*bufferAL
= dynamic_cast<CBufferAL
*>(buffer
);
154 alSourcei(_Source
, AL_BUFFER
, bufferAL
->bufferName() );
157 // Set relative mode if the buffer is stereo
158 setSourceRelativeMode( bufferAL
->isStereo() );
165 IBuffer
*CSourceAL::getStaticBuffer()
170 /// Add a buffer to the streaming queue. A buffer of 100ms length is optimal for streaming.
171 /// Should be called by a thread which checks countStreamingBuffers every 100ms.
172 void CSourceAL::submitStreamingBuffer(IBuffer
*buffer
)
174 CBufferAL
*bufferAL
= static_cast<CBufferAL
*>(buffer
);
175 ALuint bufferName
= bufferAL
->bufferName();
176 nlassert(bufferName
);
178 if (!bufferAL
->isBufferLoaded())
180 nlwarning("AL: MUSICBUG: Streaming buffer was not loaded, skipping buffer. This should not happen.");
184 alSourceQueueBuffers(_Source
, 1, &bufferName
);
186 _QueuedBuffers
.push(bufferAL
);
188 // Resume playback if the internal OpenAL source stopped due to buffer underrun.
190 alGetSourcei(_Source
, AL_SOURCE_STATE
, &srcstate
);
192 if (_IsPlaying
&& (srcstate
== AL_STOPPED
|| srcstate
== AL_INITIAL
))
194 nlwarning("AL: Streaming buffer underrun, resuming playback.");
199 /// Return the amount of buffers in the queue (playing and waiting). 3 buffers is optimal.
200 uint
CSourceAL::countStreamingBuffers() const
202 // a bit ugly here, but makes a much easier/simpler implementation on both drivers
203 ALint buffersProcessed
;
204 alGetSourcei(_Source
, AL_BUFFERS_PROCESSED
, &buffersProcessed
);
205 if (buffersProcessed
&& _QueuedBuffers
.empty())
207 nlwarning("AL: QueuedBuffers is empty, but OpenAL buffers processed > 0");
209 while (buffersProcessed
&& !_QueuedBuffers
.empty())
211 ALuint bufferName
= _QueuedBuffers
.front()->bufferName();
212 alSourceUnqueueBuffers(_Source
, 1, &bufferName
);
214 const_cast<std::queue
<CBufferAL
*> &>(_QueuedBuffers
).pop();
217 // return how many are left in the queue
218 //ALint buffersQueued;
219 //alGetSourcei(_SourceName, AL_BUFFERS_QUEUED, &buffersQueued);
221 //return (uint)buffersQueued;
222 return (uint
)_QueuedBuffers
.size();
225 /// Set looping on/off for future playbacks (default: off)
226 void CSourceAL::setLooping( bool l
)
228 alSourcei(_Source
, AL_LOOPING
, l
?AL_TRUE
:AL_FALSE
);
232 /// Return the looping state
233 bool CSourceAL::getLooping() const
236 alGetSourcei(_Source
, AL_LOOPING
, &b
);
238 return ( b
== AL_TRUE
);
241 /// Play the static buffer (or stream in and play)
242 bool CSourceAL::play()
244 #ifdef NLSOUND_DEBUG_GAIN
247 nlwarning("Called play on a streaming source");
251 // Commit 3D changes before starting play
252 if (_SoundDriver
->getOption(ISoundDriver::OptionManualRolloff
))
253 updateManualRolloff();
257 // Static playing mode
259 alSourcePlay(_Source
);
260 _IsPlaying
= (alGetError() == AL_NO_ERROR
);
262 _StartTime
= CTime::getLocalTime();
265 else if (_IsStreaming
)
269 // called by user as well as by code to resume after buffer underrun
270 if (!_IsPlaying
) // set start time if not playing yet
271 _StartTime
= CTime::getLocalTime();
272 _IsPlaying
= true; // this play always virtually succeed but may not actually be playing
273 if (!_QueuedBuffers
.empty()) // ensure buffers have actually queued
275 alSourcePlay(_Source
);
276 if (alGetError() != AL_NO_ERROR
)
278 nlwarning("AL: MUSICBUG: Unknown error while trying to play streaming source.");
283 nlwarning("AL: MUSICBUG: Trying to play stream with no buffers queued.");
287 alSourcePlay(_Source);
288 _IsPlaying = (alGetError() == AL_NO_ERROR);
290 _StartTime = CTime::getLocalTime(); // TODO: Played time should freeze when buffering fails, and be calculated based on the number of buffers played plus passed time. This is necessary for synchronizing animation with sound.
294 //nlwarning("AL: Cannot play null buffer; streaming not implemented" );
299 nlwarning("Invalid play call, not streaming and no static buffer assigned");
305 void CSourceAL::stop()
309 if ( _Buffer
!= NULL
)
311 // Static playing mode
314 alSourceStop(_Source
);
319 // TODO: Verify streaming mode?
322 alSourceStop(_Source
);
325 while (!_QueuedBuffers
.empty())
327 ALuint bufferName
= _QueuedBuffers
.front()->bufferName();
328 alSourceUnqueueBuffers(_Source
, 1, &bufferName
);
329 _QueuedBuffers
.pop();
333 //nlwarning("AL: Cannot stop null buffer; streaming not implemented" );
338 /// Pause. Call play() to resume.
339 void CSourceAL::pause()
341 if ( _Buffer
!= NULL
)
343 if (_IsPaused
) nlwarning("AL: Called pause() while _IsPaused == true!");
345 // Static playing mode
349 alSourcePause(_Source
);
355 // TODO: Verify streaming mode?
357 alSourcePause(_Source
);
360 //nlwarning("AL: Cannot pause null buffer; streaming not implemented" );
365 /// Return true if play() or pause(), false if stop().
366 bool CSourceAL::isPlaying() const
368 //return !isStopped() && !_IsPaused;
372 alGetSourcei(_Source
, AL_SOURCE_STATE
, &srcstate
);
374 return (srcstate
== AL_PLAYING
|| srcstate
== AL_PAUSED
);
383 /// Return true if playing is finished or stop() has been called.
384 bool CSourceAL::isStopped() const
389 alGetSourcei(_Source
, AL_SOURCE_STATE
, &srcstate
);
391 return (srcstate
== AL_STOPPED
|| srcstate
== AL_INITIAL
);
400 /// Return true if the playing source is paused
401 bool CSourceAL::isPaused() const
406 alGetSourcei(_Source
, AL_SOURCE_STATE
, &srcstate
);
408 return (srcstate
== AL_PAUSED
);
417 /// Returns the number of milliseconds the source has been playing
418 uint32
CSourceAL::getTime()
420 if (!_StartTime
) return 0;
421 return (uint32
)(CTime::getLocalTime() - _StartTime
);
424 /// Set the position vector.
425 void CSourceAL::setPos(const NLMISC::CVector
& pos
, bool /* deffered */)
428 // Coordinate system: conversion from NeL to OpenAL/GL:
429 alSource3f(_Source
, AL_POSITION
, pos
.x
, pos
.z
, -pos
.y
);
433 /// Get the position vector.
434 const NLMISC::CVector
&CSourceAL::getPos() const
439 /// Set the velocity vector (3D mode only)
440 void CSourceAL::setVelocity( const NLMISC::CVector
& vel
, bool /* deferred */)
442 // Coordsys conversion
443 alSource3f(_Source
, AL_VELOCITY
, vel
.x
, vel
.z
, -vel
.y
);
447 /// Get the velocity vector
448 void CSourceAL::getVelocity( NLMISC::CVector
& vel
) const
451 alGetSourcefv(_Source
, AL_VELOCITY
, v
);
453 // Coordsys conversion
454 vel
.set( v
[0], -v
[2], v
[1] );
457 /// Set the direction vector (3D mode only)
458 void CSourceAL::setDirection( const NLMISC::CVector
& dir
)
460 // Coordsys conversion
461 alSource3f(_Source
, AL_DIRECTION
, dir
.x
, dir
.z
, -dir
.y
);
465 /// Get the direction vector
466 void CSourceAL::getDirection( NLMISC::CVector
& dir
) const
469 alGetSourcefv(_Source
, AL_DIRECTION
, v
);
471 // Coordsys conversion
472 dir
.set( v
[0], -v
[2], v
[1] );
475 /// Set the gain (volume value inside [0 , 1]).
476 void CSourceAL::setGain(float gain
)
478 _Gain
= std::min(std::max(gain
, NLSOUND_MIN_GAIN
), NLSOUND_MAX_GAIN
);
479 if (!_SoundDriver
->getOption(ISoundDriver::OptionManualRolloff
))
481 alSourcef(_Source
, AL_GAIN
, _Gain
);
484 #ifdef NLSOUND_DEBUG_GAIN
487 nlwarning("Called setGain(), manual rolloff, commit deferred to play or update, physical gain is %f, configured gain is %f", gain
, _Gain
);
493 float CSourceAL::getGain() const
495 #ifdef NLSOUND_DEBUG_GAIN
497 alGetSourcef(_Source
, AL_GAIN
, &gain
);
498 nlwarning("Called getGain(), physical gain is %f, configured gain is %f", gain
, _Gain
);
504 /// Shift the frequency. 1.0f equals identity, each reduction of 50% equals a pitch shift
505 void CSourceAL::setPitch(float pitch
)
507 alSourcef(_Source
, AL_PITCH
, std::min(std::max(pitch
, NLSOUND_MIN_PITCH
), NLSOUND_MAX_PITCH
));
512 float CSourceAL::getPitch() const
515 alGetSourcef(_Source
, AL_PITCH
, &pitch
);
520 /// Set the source relative mode. If true, positions are interpreted relative to the listener position.
521 void CSourceAL::setSourceRelativeMode( bool mode
)
523 _RelativeMode
= mode
;
524 alSourcei(_Source
, AL_SOURCE_RELATIVE
, mode
?AL_TRUE
:AL_FALSE
);
528 /// Get the source relative mode (3D mode only)
529 bool CSourceAL::getSourceRelativeMode() const
532 //alGetSourcei(_Source, AL_SOURCE_RELATIVE, &b );
534 //return (b==AL_TRUE);
535 return _RelativeMode
;
538 /// Set the min and max distances (3D mode only)
539 void CSourceAL::setMinMaxDistances( float mindist
, float maxdist
, bool /* deferred */)
541 nlassert( (mindist
>= 0.0f
) && (maxdist
>= 0.0f
) );
543 static float maxSqrt
= sqrt(std::numeric_limits
<float>::max());
544 if (maxdist
>= maxSqrt
)
546 nlwarning("SOUND_DEV (OpenAL): Ridiculously high max distance set on source");
550 _MinDistance
= mindist
;
551 _MaxDistance
= maxdist
;
552 if (!_SoundDriver
->getOption(ISoundDriver::OptionManualRolloff
))
554 alSourcef(_Source
, AL_REFERENCE_DISTANCE
, mindist
);
555 alSourcef(_Source
, AL_MAX_DISTANCE
, maxdist
);
560 /// Get the min and max distances
561 void CSourceAL::getMinMaxDistances( float& mindist
, float& maxdist
) const
563 /*alGetSourcef(_Source, AL_REFERENCE_DISTANCE, &mindist );
564 alGetSourcef(_Source, AL_MAX_DISTANCE, &maxdist );
566 mindist
= _MinDistance
;
567 maxdist
= _MaxDistance
;
570 /// Set the cone angles (in radian) and gain (in [0 , 1]) (3D mode only)
571 void CSourceAL::setCone( float innerAngle
, float outerAngle
, float outerGain
)
573 nlassert( (outerGain
>= 0.0f
) && (outerGain
<= 1.0f
) );
574 alSourcef(_Source
, AL_CONE_INNER_ANGLE
, radToDeg(innerAngle
) );
575 alSourcef(_Source
, AL_CONE_OUTER_ANGLE
, radToDeg(outerAngle
) );
576 alSourcef(_Source
, AL_CONE_OUTER_GAIN
, outerGain
);
580 /// Get the cone angles (in radian)
581 void CSourceAL::getCone( float& innerAngle
, float& outerAngle
, float& outerGain
) const
584 alGetSourcef(_Source
, AL_CONE_INNER_ANGLE
, &ina
);
585 innerAngle
= degToRad(ina
);
586 alGetSourcef(_Source
, AL_CONE_OUTER_ANGLE
, &outa
);
587 outerAngle
= degToRad(outa
);
588 alGetSourcef(_Source
, AL_CONE_OUTER_GAIN
, &outerGain
);
592 /** Set the alpha value for the volume-distance curve
594 * Useful only with OptionManualRolloff. value from -1 to 1 (default 0)
596 * alpha.0: the volume will decrease linearly between 0dB and -100 dB
597 * alpha = 1.0: the volume will decrease linearly between 1.0 and 0.0 (linear scale)
598 * alpha = -1.0: the volume will decrease inversely with the distance (1/dist). This
599 * is the default used by DirectSound/OpenAL
601 * For any other value of alpha, an interpolation is be done between the two
602 * adjacent curves. For example, if alpha equals 0.5, the volume will be halfway between
603 * the linear dB curve and the linear amplitude curve.
605 void CSourceAL::setAlpha(double a
)
610 /// (Internal) Setup the effect send filter.
611 void CSourceAL::setupDirectFilter()
613 if (_Direct
&& _DirectGain
> 0)
615 if (_DirectGain
< 1 || (_DirectFilterPassGain
< 1 && _DirectFilterEnabled
))
617 // direct gain is lowered or a filter is applied
618 alFilterf(_DirectFilter
, AL_BANDPASS_GAIN
, _DirectGain
);
619 if (_DirectFilterEnabled
)
621 alFilterf(_DirectFilter
, AL_BANDPASS_GAINLF
, _DirectFilterPassGain
);
622 if (_DirectFilterType
== FilterBandPass
)
623 alFilterf(_DirectFilter
, AL_BANDPASS_GAINHF
, _DirectFilterPassGain
);
627 alFilterf(_DirectFilter
, AL_BANDPASS_GAINLF
, 1.0f
);
628 if (_DirectFilterType
== FilterBandPass
)
629 alFilterf(_DirectFilter
, AL_BANDPASS_GAINHF
, 1.0f
);
631 alSourcei(_Source
, AL_DIRECT_FILTER
, _DirectFilter
);
636 alSourcei(_Source
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
642 alFilterf(_DirectFilter
, AL_BANDPASS_GAIN
, 0.0f
);
643 alSourcei(_Source
, AL_DIRECT_FILTER
, _DirectFilter
);
648 /// Enable or disable direct output [true/false], default: true
649 void CSourceAL::setDirect(bool enable
)
655 /// Return if the direct output is enabled
656 bool CSourceAL::getDirect() const
661 /// Set the gain for the direct path
662 void CSourceAL::setDirectGain(float gain
)
664 _DirectGain
= min(max(gain
, NLSOUND_MIN_GAIN
), NLSOUND_MAX_GAIN
);
668 /// Get the gain for the direct path
669 float CSourceAL::getDirectGain() const
674 /// Enable or disable the filter for the direct channel
675 void CSourceAL::enableDirectFilter(bool enable
)
677 _DirectFilterEnabled
= enable
;
681 /// Check if the filter on the direct channel is enabled
682 bool CSourceAL::isDirectFilterEnabled() const
684 return _DirectFilterEnabled
;
687 /// Set the filter parameters for the direct channel
688 void CSourceAL::setDirectFilter(TFilter filterType
, float /* lowFrequency */, float /* highFrequency */, float passGain
)
690 _DirectFilterType
= filterType
;
691 _DirectFilterPassGain
= passGain
;
695 alFilteri(_DirectFilter
, AL_FILTER_TYPE
, AL_FILTER_HIGHPASS
);
698 alFilteri(_DirectFilter
, AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
701 alFilteri(_DirectFilter
, AL_FILTER_TYPE
, AL_FILTER_BANDPASS
);
707 /// Get the filter parameters for the direct channel
708 void CSourceAL::getDirectFilter(TFilter
&filterType
, float &lowFrequency
, float &highFrequency
, float &passGain
) const
710 filterType
= _DirectFilterType
;
711 lowFrequency
= NLSOUND_DEFAULT_FILTER_PASS_LF
;
712 highFrequency
= NLSOUND_DEFAULT_FILTER_PASS_HF
;
713 passGain
= _DirectFilterPassGain
;
716 /// Set the direct filter gain
717 void CSourceAL::setDirectFilterPassGain(float passGain
)
719 _DirectFilterPassGain
= min(max(passGain
, NLSOUND_MIN_GAIN
), NLSOUND_MAX_GAIN
);
723 /// Get the direct filter gain
724 float CSourceAL::getDirectFilterPassGain() const
726 return _DirectFilterPassGain
;
729 /// (Internal) Setup the effect send filter.
730 void CSourceAL::setupEffectFilter()
732 if (_Effect
&& _EffectGain
> 0)
734 if (_EffectGain
< 1 || (_EffectFilterPassGain
< 1 && _EffectFilterEnabled
))
736 // effect gain is lowered or a filter is applied
737 alFilterf(_EffectFilter
, AL_BANDPASS_GAIN
, _EffectGain
);
738 if (_EffectFilterEnabled
)
740 alFilterf(_EffectFilter
, AL_BANDPASS_GAINLF
, _EffectFilterPassGain
);
741 if (_EffectFilterType
== FilterBandPass
)
742 alFilterf(_EffectFilter
, AL_BANDPASS_GAINHF
, _EffectFilterPassGain
);
746 alFilterf(_EffectFilter
, AL_BANDPASS_GAINLF
, 1.0f
);
747 if (_EffectFilterType
== FilterBandPass
)
748 alFilterf(_EffectFilter
, AL_BANDPASS_GAINHF
, 1.0f
);
750 alSource3i(_Source
, AL_AUXILIARY_SEND_FILTER
, _Effect
->getAuxEffectSlot(), 0, _EffectFilter
);
755 alSource3i(_Source
, AL_AUXILIARY_SEND_FILTER
, _Effect
->getAuxEffectSlot(), 0, AL_FILTER_NULL
);
761 alSource3i(_Source
, AL_AUXILIARY_SEND_FILTER
, AL_EFFECTSLOT_NULL
, 0, AL_FILTER_NULL
);
766 /// Set the effect send for this source, NULL to disable. [IEffect], default: NULL
767 void CSourceAL::setEffect(CEffectAL
*effect
)
773 /// Set the effect send for this source, NULL to disable. [IEffect], default: NULL
774 void CSourceAL::setEffect(IReverbEffect
*reverbEffect
)
776 setEffect(reverbEffect
? dynamic_cast<CEffectAL
*>(reverbEffect
) : NULL
);
779 /// Get the effect send for this source
780 IEffect
*CSourceAL::getEffect() const
782 // return _Effect ? NLMISC::safe_cast<IEffect *>(_Effect) : NULL;
786 /// Set the gain for the effect path
787 void CSourceAL::setEffectGain(float gain
)
789 _EffectGain
= min(max(gain
, NLSOUND_MIN_GAIN
), NLSOUND_MAX_GAIN
);
793 /// Get the gain for the effect path
794 float CSourceAL::getEffectGain() const
799 /// Enable or disable the filter for the effect channel
800 void CSourceAL::enableEffectFilter(bool enable
)
802 _EffectFilterEnabled
= enable
;
806 /// Check if the filter on the effect channel is enabled
807 bool CSourceAL::isEffectFilterEnabled() const
809 return _EffectFilterEnabled
;
812 /// Set the filter parameters for the effect channel
813 void CSourceAL::setEffectFilter(TFilter filterType
, float /* lowFrequency */, float /* highFrequency */, float passGain
)
815 _EffectFilterType
= filterType
;
816 _EffectFilterPassGain
= passGain
;
820 alFilteri(_EffectFilter
, AL_FILTER_TYPE
, AL_FILTER_HIGHPASS
);
823 alFilteri(_EffectFilter
, AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
826 alFilteri(_EffectFilter
, AL_FILTER_TYPE
, AL_FILTER_BANDPASS
);
832 /// Get the filter parameters for the effect channel
833 void CSourceAL::getEffectFilter(TFilter
&filterType
, float &lowFrequency
, float &highFrequency
, float &passGain
) const
835 filterType
= _EffectFilterType
;
836 lowFrequency
= NLSOUND_DEFAULT_FILTER_PASS_LF
;
837 highFrequency
= NLSOUND_DEFAULT_FILTER_PASS_HF
;
838 passGain
= _EffectFilterPassGain
;
841 /// Set the effect filter gain
842 void CSourceAL::setEffectFilterPassGain(float passGain
)
844 _EffectFilterPassGain
= min(max(passGain
, NLSOUND_MIN_GAIN
), NLSOUND_MAX_GAIN
);
848 /// Get the effect filter gain
849 float CSourceAL::getEffectFilterPassGain() const
851 return _EffectFilterPassGain
;