18 #include "auxeffectslot.h"
19 #include "sourcegroup.h"
24 class ALBufferStream
{
25 SharedPtr
<Decoder
> mDecoder
;
37 Vector
<ALuint
> mBufferIds
;
40 std::pair
<uint64_t,uint64_t> mLoopPts
;
41 std::atomic
<bool> mHasLooped
;
42 std::atomic
<bool> mDone
;
45 ALBufferStream(SharedPtr
<Decoder
> decoder
, ALuint updatelen
, ALuint numupdates
)
46 : mDecoder(decoder
), mUpdateLen(updatelen
), mNumUpdates(numupdates
),
47 mFormat(AL_NONE
), mFrequency(0), mFrameSize(0), mSilence(0),
48 mCurrentIdx(0), mLoopPts
{0,0}, mHasLooped(false), mDone(false)
52 if(!mBufferIds
.empty())
54 alDeleteBuffers(mBufferIds
.size(), &mBufferIds
[0]);
59 uint64_t getLength() const { return mDecoder
->getLength(); }
60 uint64_t getPosition() const { return mDecoder
->getPosition(); }
62 ALuint
getNumUpdates() const { return mNumUpdates
; }
63 ALuint
getUpdateLength() const { return mUpdateLen
; }
65 ALuint
getFrequency() const { return mFrequency
; }
67 bool seek(uint64_t pos
)
69 if(!mDecoder
->seek(pos
))
71 mHasLooped
.store(false, std::memory_order_release
);
72 mDone
.store(false, std::memory_order_release
);
78 ALuint srate
= mDecoder
->getFrequency();
79 ChannelConfig chans
= mDecoder
->getChannelConfig();
80 SampleType type
= mDecoder
->getSampleType();
82 mLoopPts
= mDecoder
->getLoopPoints();
83 if(mLoopPts
.first
>= mLoopPts
.second
)
86 mLoopPts
.second
= std::numeric_limits
<uint64_t>::max();
90 mFrameSize
= FramesToBytes(1, chans
, type
);
91 mFormat
= GetFormat(chans
, type
);
92 if(mFormat
== AL_NONE
)
94 std::stringstream sstr
;
95 sstr
<< "Format not supported ("<<GetSampleTypeName(type
)<<", "<<GetChannelConfigName(chans
)<<")";
96 throw std::runtime_error(sstr
.str());
99 mData
.resize(mUpdateLen
* mFrameSize
);
100 if(type
== SampleType::UInt8
) mSilence
= 0x80;
101 else if(type
== SampleType::Mulaw
) mSilence
= 0x7f;
102 else mSilence
= 0x00;
104 mBufferIds
.assign(mNumUpdates
, 0);
105 alGenBuffers(mBufferIds
.size(), &mBufferIds
[0]);
108 int64_t getLoopStart() const { return mLoopPts
.first
; }
109 int64_t getLoopEnd() const { return mLoopPts
.second
; }
111 bool hasLooped() const { return mHasLooped
.load(std::memory_order_acquire
); }
112 bool hasMoreData() const { return !mDone
.load(std::memory_order_acquire
); }
113 bool streamMoreData(ALuint srcid
, bool loop
)
115 if(mDone
.load(std::memory_order_acquire
))
120 frames
= mDecoder
->read(&mData
[0], mUpdateLen
);
123 ALuint len
= mUpdateLen
;
124 uint64_t pos
= mDecoder
->getPosition();
125 if(pos
<= mLoopPts
.second
)
126 len
= std::min
<uint64_t>(len
, mLoopPts
.second
- pos
);
130 frames
= mDecoder
->read(&mData
[0], len
);
131 if(frames
< mUpdateLen
&& loop
&& pos
+frames
> 0)
133 if(pos
+frames
< mLoopPts
.second
)
135 mLoopPts
.second
= pos
+frames
;
136 mLoopPts
.first
= std::min(mLoopPts
.first
, mLoopPts
.second
-1);
140 if(!mDecoder
->seek(mLoopPts
.first
))
142 mHasLooped
.store(true, std::memory_order_release
);
144 len
= std::min
<uint64_t>(mUpdateLen
-frames
, mLoopPts
.second
-mLoopPts
.first
);
145 ALuint got
= mDecoder
->read(&mData
[frames
*mFrameSize
], len
);
148 } while(frames
< mUpdateLen
);
151 if(frames
< mUpdateLen
)
153 mDone
.store(true, std::memory_order_release
);
154 if(frames
== 0) return false;
155 std::fill(mData
.begin() + frames
*mFrameSize
, mData
.end(), mSilence
);
158 alBufferData(mBufferIds
[mCurrentIdx
], mFormat
, &mData
[0], mData
.size(), mFrequency
);
159 alSourceQueueBuffers(srcid
, 1, &mBufferIds
[mCurrentIdx
]);
160 mCurrentIdx
= (mCurrentIdx
+1) % mBufferIds
.size();
166 ALSource::ALSource(ALContext
*context
)
167 : mContext(context
), mId(0), mBuffer(0), mGroup(nullptr), mIsAsync(false),
168 mDirectFilter(AL_FILTER_NULL
)
173 ALSource::~ALSource()
178 void ALSource::resetProperties()
181 mGroup
->removeSource(Source(this));
184 mPaused
.store(false, std::memory_order_release
);
191 mMaxDist
= std::numeric_limits
<float>::max();
192 mPosition
= Vector3(0.0f
);
193 mVelocity
= Vector3(0.0f
);
194 mDirection
= Vector3(0.0f
);
195 mOrientation
[0] = Vector3(0.0f
, 0.0f
, -1.0f
);
196 mOrientation
[1] = Vector3(0.0f
, 1.0f
, 0.0f
);
197 mConeInnerAngle
= 360.0f
;
198 mConeOuterAngle
= 360.0f
;
199 mConeOuterGain
= 0.0f
;
200 mConeOuterGainHF
= 1.0f
;
201 mRolloffFactor
= 1.0f
;
202 mRoomRolloffFactor
= 0.0f
;
203 mDopplerFactor
= 1.0f
;
204 mAirAbsorptionFactor
= 0.0f
;
206 mStereoAngles
[0] = F_PI
/ 6.0f
;
207 mStereoAngles
[1] = -F_PI
/ 6.0f
;
208 mSpatialize
= Spatialize::Auto
;
209 mResampler
= mContext
->hasExtension(SOFT_source_resampler
) ?
210 alGetInteger(AL_DEFAULT_RESAMPLER_SOFT
) : 0;
213 mDryGainHFAuto
= true;
215 mWetGainHFAuto
= true;
217 mContext
->alDeleteFilters(1, &mDirectFilter
);
219 for(auto &i
: mEffectSlots
)
222 i
.second
.mSlot
->removeSourceSend(Source(this), i
.first
);
224 mContext
->alDeleteFilters(1, &i
.second
.mFilter
);
226 mEffectSlots
.clear();
231 void ALSource::applyProperties(bool looping
, ALuint offset
) const
233 alSourcei(mId
, AL_LOOPING
, looping
? AL_TRUE
: AL_FALSE
);
234 alSourcei(mId
, AL_SAMPLE_OFFSET
, offset
);
237 alSourcef(mId
, AL_PITCH
, mPitch
* mGroup
->getAppliedPitch());
238 alSourcef(mId
, AL_GAIN
, mGain
* mGroup
->getAppliedGain());
242 alSourcef(mId
, AL_PITCH
, mPitch
);
243 alSourcef(mId
, AL_GAIN
, mGain
);
245 alSourcef(mId
, AL_MIN_GAIN
, mMinGain
);
246 alSourcef(mId
, AL_MAX_GAIN
, mMaxGain
);
247 alSourcef(mId
, AL_REFERENCE_DISTANCE
, mRefDist
);
248 alSourcef(mId
, AL_MAX_DISTANCE
, mMaxDist
);
249 alSourcefv(mId
, AL_POSITION
, mPosition
.getPtr());
250 alSourcefv(mId
, AL_VELOCITY
, mVelocity
.getPtr());
251 alSourcefv(mId
, AL_DIRECTION
, mDirection
.getPtr());
252 if(mContext
->hasExtension(EXT_BFORMAT
))
253 alSourcefv(mId
, AL_ORIENTATION
, &mOrientation
[0][0]);
254 alSourcef(mId
, AL_CONE_INNER_ANGLE
, mConeInnerAngle
);
255 alSourcef(mId
, AL_CONE_OUTER_ANGLE
, mConeOuterAngle
);
256 alSourcef(mId
, AL_CONE_OUTER_GAIN
, mConeOuterGain
);
257 alSourcef(mId
, AL_ROLLOFF_FACTOR
, mRolloffFactor
);
258 alSourcef(mId
, AL_DOPPLER_FACTOR
, mDopplerFactor
);
259 if(mContext
->hasExtension(EXT_SOURCE_RADIUS
))
260 alSourcef(mId
, AL_SOURCE_RADIUS
, mRadius
);
261 if(mContext
->hasExtension(EXT_STEREO_ANGLES
))
262 alSourcefv(mId
, AL_STEREO_ANGLES
, mStereoAngles
);
263 if(mContext
->hasExtension(SOFT_source_spatialize
))
264 alSourcei(mId
, AL_SOURCE_SPATIALIZE_SOFT
, (ALint
)mSpatialize
);
265 if(mContext
->hasExtension(SOFT_source_resampler
))
266 alSourcei(mId
, AL_SOURCE_RESAMPLER_SOFT
, mResampler
);
267 alSourcei(mId
, AL_SOURCE_RELATIVE
, mRelative
? AL_TRUE
: AL_FALSE
);
268 if(mContext
->hasExtension(EXT_EFX
))
270 alSourcef(mId
, AL_CONE_OUTER_GAINHF
, mConeOuterGainHF
);
271 alSourcef(mId
, AL_ROOM_ROLLOFF_FACTOR
, mRoomRolloffFactor
);
272 alSourcef(mId
, AL_AIR_ABSORPTION_FACTOR
, mAirAbsorptionFactor
);
273 alSourcei(mId
, AL_DIRECT_FILTER_GAINHF_AUTO
, mDryGainHFAuto
? AL_TRUE
: AL_FALSE
);
274 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, mWetGainAuto
? AL_TRUE
: AL_FALSE
);
275 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, mWetGainHFAuto
? AL_TRUE
: AL_FALSE
);
276 alSourcei(mId
, AL_DIRECT_FILTER
, mDirectFilter
);
277 for(const auto &i
: mEffectSlots
)
279 ALuint slotid
= (i
.second
.mSlot
? i
.second
.mSlot
->getId() : 0);
280 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, i
.first
, i
.second
.mFilter
);
286 void ALSource::setGroup(ALSourceGroup
*group
)
289 mGroup
->removeSource(Source(this));
294 void ALSource::unsetGroup()
300 void ALSource::groupUpdate()
306 alSourcef(mId
, AL_PITCH
, mPitch
* mGroup
->getAppliedPitch());
307 alSourcef(mId
, AL_GAIN
, mGain
* mGroup
->getAppliedGain());
311 alSourcef(mId
, AL_PITCH
, mPitch
);
312 alSourcef(mId
, AL_GAIN
, mGain
);
317 void ALSource::groupPropUpdate(ALfloat gain
, ALfloat pitch
)
321 alSourcef(mId
, AL_PITCH
, mPitch
* pitch
);
322 alSourcef(mId
, AL_GAIN
, mGain
* gain
);
327 void ALSource::play(Buffer buffer
)
329 ALBuffer
*albuf
= buffer
.getHandle();
330 if(!albuf
) throw std::runtime_error("Buffer is not valid");
331 CheckContext(mContext
);
332 CheckContext(albuf
->getContext());
334 if(!albuf
->isReady())
335 throw std::runtime_error("Buffer is not ready");
337 if(mIsAsync
.load(std::memory_order_acquire
))
339 mContext
->removeStream(this);
340 mIsAsync
.store(false, std::memory_order_release
);
345 mId
= mContext
->getSourceId(mPriority
);
346 applyProperties(mLooping
, (ALuint
)std::min
<uint64_t>(mOffset
, std::numeric_limits
<ALint
>::max()));
351 alSourcei(mId
, AL_BUFFER
, 0);
352 alSourcei(mId
, AL_LOOPING
, mLooping
? AL_TRUE
: AL_FALSE
);
353 alSourcei(mId
, AL_SAMPLE_OFFSET
, (ALuint
)std::min
<uint64_t>(mOffset
, std::numeric_limits
<ALint
>::max()));
360 mBuffer
->removeSource(Source(this));
362 mBuffer
->addSource(Source(this));
364 alSourcei(mId
, AL_BUFFER
, mBuffer
->getId());
366 mPaused
.store(false, std::memory_order_release
);
369 void ALSource::play(SharedPtr
<Decoder
> decoder
, ALuint updatelen
, ALuint queuesize
)
372 throw std::runtime_error("Update length out of range");
374 throw std::runtime_error("Queue size out of range");
375 CheckContext(mContext
);
377 auto stream
= MakeUnique
<ALBufferStream
>(decoder
, updatelen
, queuesize
);
380 if(mIsAsync
.load(std::memory_order_acquire
))
382 mContext
->removeStream(this);
383 mIsAsync
.store(false, std::memory_order_release
);
388 mId
= mContext
->getSourceId(mPriority
);
389 applyProperties(false, 0);
394 alSourcei(mId
, AL_BUFFER
, 0);
395 alSourcei(mId
, AL_LOOPING
, AL_FALSE
);
396 alSourcei(mId
, AL_SAMPLE_OFFSET
, 0);
400 mBuffer
->removeSource(Source(this));
403 mStream
= std::move(stream
);
405 mStream
->seek(mOffset
);
408 for(ALuint i
= 0;i
< mStream
->getNumUpdates();i
++)
410 if(!mStream
->streamMoreData(mId
, mLooping
))
414 mPaused
.store(false, std::memory_order_release
);
416 mContext
->addStream(this);
417 mIsAsync
.store(true, std::memory_order_release
);
421 void ALSource::makeStopped()
423 if(mIsAsync
.load(std::memory_order_acquire
))
425 mContext
->removeStreamNoLock(this);
426 mIsAsync
.store(false, std::memory_order_release
);
432 alSourcei(mId
, AL_BUFFER
, 0);
433 if(mContext
->hasExtension(EXT_EFX
))
435 alSourcei(mId
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
436 for(auto &i
: mEffectSlots
)
437 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, 0, i
.first
, AL_FILTER_NULL
);
439 mContext
->insertSourceId(mId
);
444 mBuffer
->removeSource(Source(this));
449 mPaused
.store(false, std::memory_order_release
);
452 void ALSource::stop()
454 CheckContext(mContext
);
459 void ALSource::checkPaused()
461 if(mPaused
.load(std::memory_order_acquire
) || mId
== 0)
465 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
466 // Streaming sources may be in a stopped state if underrun
467 mPaused
.store((state
== AL_PAUSED
) ||
468 (state
== AL_STOPPED
&& mStream
&& mStream
->hasMoreData()),
469 std::memory_order_release
);
472 void ALSource::pause()
474 CheckContext(mContext
);
475 if(mPaused
.load(std::memory_order_acquire
))
480 std::lock_guard
<std::mutex
> lock(mMutex
);
483 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
484 // Streaming sources may be in a stopped state if underrun
485 mPaused
.store((state
== AL_PAUSED
) ||
486 (state
== AL_STOPPED
&& mStream
&& mStream
->hasMoreData()),
487 std::memory_order_release
);
491 void ALSource::resume()
493 CheckContext(mContext
);
494 if(!mPaused
.load(std::memory_order_acquire
))
499 mPaused
.store(false, std::memory_order_release
);
503 bool ALSource::isPlaying() const
505 CheckContext(mContext
);
506 if(mId
== 0) return false;
509 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
511 throw std::runtime_error("Source state error");
513 return state
== AL_PLAYING
|| (!mPaused
.load(std::memory_order_acquire
) &&
514 mStream
&& mStream
->hasMoreData());
517 bool ALSource::isPaused() const
519 CheckContext(mContext
);
520 if(mId
== 0) return false;
523 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
525 throw std::runtime_error("Source state error");
527 return state
== AL_PAUSED
|| mPaused
.load(std::memory_order_acquire
);
531 ALint
ALSource::refillBufferStream()
534 alGetSourcei(mId
, AL_BUFFERS_PROCESSED
, &processed
);
538 alSourceUnqueueBuffers(mId
, 1, &buf
);
543 alGetSourcei(mId
, AL_BUFFERS_QUEUED
, &queued
);
544 for(;(ALuint
)queued
< mStream
->getNumUpdates();queued
++)
546 if(!mStream
->streamMoreData(mId
, mLooping
))
554 void ALSource::updateNoCtxCheck()
561 if(!mIsAsync
.load(std::memory_order_acquire
))
564 mContext
->send(&MessageHandler::sourceStopped
, Source(this));
570 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
571 if(state
!= AL_PLAYING
&& state
!= AL_PAUSED
)
574 mContext
->send(&MessageHandler::sourceStopped
, Source(this));
579 bool ALSource::updateAsync()
581 std::lock_guard
<std::mutex
> lock(mMutex
);
583 ALint queued
= refillBufferStream();
586 mIsAsync
.store(false, std::memory_order_release
);
589 if(!mPaused
.load(std::memory_order_acquire
))
592 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
593 if(state
!= AL_PLAYING
)
600 void ALSource::setPriority(ALuint priority
)
602 mPriority
= priority
;
606 void ALSource::setOffset(uint64_t offset
)
608 CheckContext(mContext
);
617 if(offset
>= std::numeric_limits
<ALint
>::max())
618 throw std::runtime_error("Offset out of range");
620 alSourcei(mId
, AL_SAMPLE_OFFSET
, (ALint
)offset
);
621 if(alGetError() != AL_NO_ERROR
)
622 throw std::runtime_error("Offset out of range");
626 std::lock_guard
<std::mutex
> lock(mMutex
);
627 if(!mStream
->seek(offset
))
628 throw std::runtime_error("Failed to seek to offset");
630 alSourcei(mId
, AL_BUFFER
, 0);
631 ALint queued
= refillBufferStream();
632 if(queued
> 0 && !mPaused
)
637 std::pair
<uint64_t,std::chrono::nanoseconds
> ALSource::getSampleOffsetLatency() const
639 CheckContext(mContext
);
641 return { 0, std::chrono::nanoseconds::zero() };
645 std::lock_guard
<std::mutex
> lock(mMutex
);
646 ALint queued
= 0, state
= -1, srcpos
= 0;
647 std::chrono::nanoseconds
latency(0);
649 alGetSourcei(mId
, AL_BUFFERS_QUEUED
, &queued
);
650 if(mContext
->hasExtension(SOFT_source_latency
))
653 mContext
->alGetSourcei64vSOFT(mId
, AL_SAMPLE_OFFSET_LATENCY_SOFT
, val
);
655 latency
= std::chrono::nanoseconds(val
[1]);
658 alGetSourcei(mId
, AL_SAMPLE_OFFSET
, &srcpos
);
659 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
661 int64_t streampos
= mStream
->getPosition();
662 if(state
!= AL_STOPPED
)
664 // The amount of samples in the queue waiting to play
665 ALuint inqueue
= queued
*mStream
->getUpdateLength() - srcpos
;
666 if(!mStream
->hasLooped())
668 // A non-looped stream should never have more samples queued
669 // than have been read...
670 streampos
= std::max
<int64_t>(streampos
, inqueue
) - inqueue
;
674 streampos
-= inqueue
;
675 int64_t looplen
= mStream
->getLoopEnd() - mStream
->getLoopStart();
676 while(streampos
< mStream
->getLoopStart())
677 streampos
+= looplen
;
681 return { streampos
, latency
};
684 std::chrono::nanoseconds
latency(0);
686 if(mContext
->hasExtension(SOFT_source_latency
))
689 mContext
->alGetSourcei64vSOFT(mId
, AL_SAMPLE_OFFSET_LATENCY_SOFT
, val
);
691 latency
= std::chrono::nanoseconds(val
[1]);
694 alGetSourcei(mId
, AL_SAMPLE_OFFSET
, &srcpos
);
695 return { srcpos
, latency
};
698 std::pair
<Seconds
,Seconds
> ALSource::getSecOffsetLatency() const
700 CheckContext(mContext
);
702 return { Seconds::zero(), Seconds::zero() };
706 std::lock_guard
<std::mutex
> lock(mMutex
);
707 ALint queued
= 0, state
= -1;
709 Seconds
latency(0.0);
711 alGetSourcei(mId
, AL_BUFFERS_QUEUED
, &queued
);
712 if(mContext
->hasExtension(SOFT_source_latency
))
715 mContext
->alGetSourcedvSOFT(mId
, AL_SEC_OFFSET_LATENCY_SOFT
, val
);
717 latency
= Seconds(val
[1]);
722 alGetSourcef(mId
, AL_SEC_OFFSET
, &f
);
725 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
728 int64_t streampos
= mStream
->getPosition();
729 if(state
!= AL_STOPPED
)
732 frac
= std::modf(srcpos
* mStream
->getFrequency(), &ipos
);
734 // The amount of samples in the queue waiting to play
735 ALuint inqueue
= queued
*mStream
->getUpdateLength() - (ALuint
)ipos
;
736 if(!mStream
->hasLooped())
738 // A non-looped stream should never have more samples queued
739 // than have been read...
740 streampos
= std::max
<int64_t>(streampos
, inqueue
) - inqueue
;
744 streampos
-= inqueue
;
745 int64_t looplen
= mStream
->getLoopEnd() - mStream
->getLoopStart();
746 while(streampos
< mStream
->getLoopStart())
747 streampos
+= looplen
;
751 return { Seconds((streampos
+frac
) / mStream
->getFrequency()), latency
};
754 ALdouble srcpos
= 0.0;
755 Seconds
latency(0.0);
756 if(mContext
->hasExtension(SOFT_source_latency
))
759 mContext
->alGetSourcedvSOFT(mId
, AL_SAMPLE_OFFSET_LATENCY_SOFT
, val
);
761 latency
= Seconds(val
[1]);
766 alGetSourcef(mId
, AL_SEC_OFFSET
, &f
);
769 return { Seconds(srcpos
), latency
};
773 void ALSource::setLooping(bool looping
)
775 CheckContext(mContext
);
778 alSourcei(mId
, AL_LOOPING
, looping
? AL_TRUE
: AL_FALSE
);
783 void ALSource::setPitch(ALfloat pitch
)
786 throw std::runtime_error("Pitch out of range");
787 CheckContext(mContext
);
789 alSourcef(mId
, AL_PITCH
, pitch
* (mGroup
? mGroup
->getAppliedPitch() : 1.0f
));
794 void ALSource::setGain(ALfloat gain
)
797 throw std::runtime_error("Gain out of range");
798 CheckContext(mContext
);
800 alSourcef(mId
, AL_GAIN
, gain
* (mGroup
? mGroup
->getAppliedGain() : 1.0f
));
804 void ALSource::setGainRange(ALfloat mingain
, ALfloat maxgain
)
806 if(!(mingain
>= 0.0f
&& maxgain
<= 1.0f
&& maxgain
>= mingain
))
807 throw std::runtime_error("Gain range out of range");
808 CheckContext(mContext
);
811 alSourcef(mId
, AL_MIN_GAIN
, mingain
);
812 alSourcef(mId
, AL_MAX_GAIN
, maxgain
);
819 void ALSource::setDistanceRange(ALfloat refdist
, ALfloat maxdist
)
821 if(!(refdist
>= 0.0f
&& maxdist
<= std::numeric_limits
<float>::max() && refdist
<= maxdist
))
822 throw std::runtime_error("Distance range out of range");
823 CheckContext(mContext
);
826 alSourcef(mId
, AL_REFERENCE_DISTANCE
, refdist
);
827 alSourcef(mId
, AL_MAX_DISTANCE
, maxdist
);
834 void ALSource::set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const Vector3
&direction
)
836 CheckContext(mContext
);
839 Batcher batcher
= mContext
->getBatcher();
840 alSourcefv(mId
, AL_POSITION
, position
.getPtr());
841 alSourcefv(mId
, AL_VELOCITY
, velocity
.getPtr());
842 alSourcefv(mId
, AL_DIRECTION
, direction
.getPtr());
844 mPosition
= position
;
845 mVelocity
= velocity
;
846 mDirection
= direction
;
849 void ALSource::set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
)
851 static_assert(sizeof(orientation
) == sizeof(ALfloat
[6]), "Invalid Vector3 pair size");
852 CheckContext(mContext
);
855 Batcher batcher
= mContext
->getBatcher();
856 alSourcefv(mId
, AL_POSITION
, position
.getPtr());
857 alSourcefv(mId
, AL_VELOCITY
, velocity
.getPtr());
858 if(mContext
->hasExtension(EXT_BFORMAT
))
859 alSourcefv(mId
, AL_ORIENTATION
, orientation
.first
.getPtr());
860 alSourcefv(mId
, AL_DIRECTION
, orientation
.first
.getPtr());
862 mPosition
= position
;
863 mVelocity
= velocity
;
864 mDirection
= mOrientation
[0] = orientation
.first
;
865 mOrientation
[1] = orientation
.second
;
869 void ALSource::setPosition(ALfloat x
, ALfloat y
, ALfloat z
)
871 CheckContext(mContext
);
873 alSource3f(mId
, AL_POSITION
, x
, y
, z
);
879 void ALSource::setPosition(const ALfloat
*pos
)
881 CheckContext(mContext
);
883 alSourcefv(mId
, AL_POSITION
, pos
);
884 mPosition
[0] = pos
[0];
885 mPosition
[1] = pos
[1];
886 mPosition
[2] = pos
[2];
889 void ALSource::setVelocity(ALfloat x
, ALfloat y
, ALfloat z
)
891 CheckContext(mContext
);
893 alSource3f(mId
, AL_VELOCITY
, x
, y
, z
);
899 void ALSource::setVelocity(const ALfloat
*vel
)
901 CheckContext(mContext
);
903 alSourcefv(mId
, AL_VELOCITY
, vel
);
904 mVelocity
[0] = vel
[0];
905 mVelocity
[1] = vel
[1];
906 mVelocity
[2] = vel
[2];
909 void ALSource::setDirection(ALfloat x
, ALfloat y
, ALfloat z
)
911 CheckContext(mContext
);
913 alSource3f(mId
, AL_DIRECTION
, x
, y
, z
);
919 void ALSource::setDirection(const ALfloat
*dir
)
921 CheckContext(mContext
);
923 alSourcefv(mId
, AL_DIRECTION
, dir
);
924 mDirection
[0] = dir
[0];
925 mDirection
[1] = dir
[1];
926 mDirection
[2] = dir
[2];
929 void ALSource::setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
)
931 CheckContext(mContext
);
934 ALfloat ori
[6] = { x1
, y1
, z1
, x2
, y2
, z2
};
935 if(mContext
->hasExtension(EXT_BFORMAT
))
936 alSourcefv(mId
, AL_ORIENTATION
, ori
);
937 alSourcefv(mId
, AL_DIRECTION
, ori
);
939 mDirection
[0] = mOrientation
[0][0] = x1
;
940 mDirection
[1] = mOrientation
[0][1] = y1
;
941 mDirection
[2] = mOrientation
[0][2] = z1
;
942 mOrientation
[1][0] = x2
;
943 mOrientation
[1][1] = y2
;
944 mOrientation
[1][2] = z2
;
947 void ALSource::setOrientation(const ALfloat
*at
, const ALfloat
*up
)
949 CheckContext(mContext
);
952 ALfloat ori
[6] = { at
[0], at
[1], at
[2], up
[0], up
[1], up
[2] };
953 if(mContext
->hasExtension(EXT_BFORMAT
))
954 alSourcefv(mId
, AL_ORIENTATION
, ori
);
955 alSourcefv(mId
, AL_DIRECTION
, ori
);
957 mDirection
[0] = mOrientation
[0][0] = at
[0];
958 mDirection
[1] = mOrientation
[0][1] = at
[1];
959 mDirection
[2] = mOrientation
[0][2] = at
[2];
960 mOrientation
[1][0] = up
[0];
961 mOrientation
[1][1] = up
[1];
962 mOrientation
[1][2] = up
[2];
965 void ALSource::setOrientation(const ALfloat
*ori
)
967 CheckContext(mContext
);
970 if(mContext
->hasExtension(EXT_BFORMAT
))
971 alSourcefv(mId
, AL_ORIENTATION
, ori
);
972 alSourcefv(mId
, AL_DIRECTION
, ori
);
974 mDirection
[0] = mOrientation
[0][0] = ori
[0];
975 mDirection
[1] = mOrientation
[0][1] = ori
[1];
976 mDirection
[2] = mOrientation
[0][2] = ori
[2];
977 mOrientation
[1][0] = ori
[3];
978 mOrientation
[1][1] = ori
[4];
979 mOrientation
[1][2] = ori
[5];
983 void ALSource::setConeAngles(ALfloat inner
, ALfloat outer
)
985 if(!(inner
>= 0.0f
&& outer
<= 360.0f
&& outer
>= inner
))
986 throw std::runtime_error("Cone angles out of range");
987 CheckContext(mContext
);
990 alSourcef(mId
, AL_CONE_INNER_ANGLE
, inner
);
991 alSourcef(mId
, AL_CONE_OUTER_ANGLE
, outer
);
993 mConeInnerAngle
= inner
;
994 mConeOuterAngle
= outer
;
997 void ALSource::setOuterConeGains(ALfloat gain
, ALfloat gainhf
)
999 if(!(gain
>= 0.0f
&& gain
<= 1.0f
&& gainhf
>= 0.0f
&& gainhf
<= 1.0f
))
1000 throw std::runtime_error("Outer cone gain out of range");
1001 CheckContext(mContext
);
1004 alSourcef(mId
, AL_CONE_OUTER_GAIN
, gain
);
1005 if(mContext
->hasExtension(EXT_EFX
))
1006 alSourcef(mId
, AL_CONE_OUTER_GAINHF
, gainhf
);
1008 mConeOuterGain
= gain
;
1009 mConeOuterGainHF
= gainhf
;
1013 void ALSource::setRolloffFactors(ALfloat factor
, ALfloat roomfactor
)
1015 if(!(factor
>= 0.0f
&& roomfactor
>= 0.0f
))
1016 throw std::runtime_error("Rolloff factor out of range");
1017 CheckContext(mContext
);
1020 alSourcef(mId
, AL_ROLLOFF_FACTOR
, factor
);
1021 if(mContext
->hasExtension(EXT_EFX
))
1022 alSourcef(mId
, AL_ROOM_ROLLOFF_FACTOR
, roomfactor
);
1024 mRolloffFactor
= factor
;
1025 mRoomRolloffFactor
= roomfactor
;
1028 void ALSource::setDopplerFactor(ALfloat factor
)
1030 if(!(factor
>= 0.0f
&& factor
<= 1.0f
))
1031 throw std::runtime_error("Doppler factor out of range");
1032 CheckContext(mContext
);
1034 alSourcef(mId
, AL_DOPPLER_FACTOR
, factor
);
1035 mDopplerFactor
= factor
;
1038 void ALSource::setAirAbsorptionFactor(ALfloat factor
)
1040 if(!(factor
>= 0.0f
&& factor
<= 10.0f
))
1041 throw std::runtime_error("Absorption factor out of range");
1042 CheckContext(mContext
);
1043 if(mId
!= 0 && mContext
->hasExtension(EXT_EFX
))
1044 alSourcef(mId
, AL_AIR_ABSORPTION_FACTOR
, factor
);
1045 mAirAbsorptionFactor
= factor
;
1048 void ALSource::setRadius(ALfloat radius
)
1050 if(!(mRadius
>= 0.0f
))
1051 throw std::runtime_error("Radius out of range");
1052 CheckContext(mContext
);
1053 if(mId
!= 0 && mContext
->hasExtension(EXT_SOURCE_RADIUS
))
1054 alSourcef(mId
, AL_SOURCE_RADIUS
, radius
);
1058 void ALSource::setStereoAngles(ALfloat leftAngle
, ALfloat rightAngle
)
1060 CheckContext(mContext
);
1061 if(mId
!= 0 && mContext
->hasExtension(EXT_STEREO_ANGLES
))
1063 ALfloat angles
[2] = { leftAngle
, rightAngle
};
1064 alSourcefv(mId
, AL_STEREO_ANGLES
, angles
);
1066 mStereoAngles
[0] = leftAngle
;
1067 mStereoAngles
[1] = rightAngle
;
1070 void ALSource::set3DSpatialize(Spatialize spatialize
)
1072 CheckContext(mContext
);
1073 if(mId
!= 0 && mContext
->hasExtension(SOFT_source_spatialize
))
1074 alSourcei(mId
, AL_SOURCE_SPATIALIZE_SOFT
, (ALint
)spatialize
);
1075 mSpatialize
= spatialize
;
1078 void ALSource::setResamplerIndex(ALsizei index
)
1081 throw std::runtime_error("Resampler index out of range");
1082 index
= std::min
<ALsizei
>(index
, mContext
->getAvailableResamplers().size());
1083 if(mId
!= 0 && mContext
->hasExtension(SOFT_source_resampler
))
1084 alSourcei(mId
, AL_SOURCE_RESAMPLER_SOFT
, index
);
1088 void ALSource::setRelative(bool relative
)
1090 CheckContext(mContext
);
1092 alSourcei(mId
, AL_SOURCE_RELATIVE
, relative
? AL_TRUE
: AL_FALSE
);
1093 mRelative
= relative
;
1096 void ALSource::setGainAuto(bool directhf
, bool send
, bool sendhf
)
1098 CheckContext(mContext
);
1099 if(mId
!= 0 && mContext
->hasExtension(EXT_EFX
))
1101 alSourcei(mId
, AL_DIRECT_FILTER_GAINHF_AUTO
, directhf
? AL_TRUE
: AL_FALSE
);
1102 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, send
? AL_TRUE
: AL_FALSE
);
1103 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, sendhf
? AL_TRUE
: AL_FALSE
);
1105 mDryGainHFAuto
= directhf
;
1106 mWetGainAuto
= send
;
1107 mWetGainHFAuto
= sendhf
;
1111 void ALSource::setFilterParams(ALuint
&filterid
, const FilterParams
¶ms
)
1113 if(!mContext
->hasExtension(EXT_EFX
))
1116 if(!(params
.mGain
< 1.0f
|| params
.mGainHF
< 1.0f
|| params
.mGainLF
< 1.0f
))
1119 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_NULL
);
1126 mContext
->alGenFilters(1, &filterid
);
1127 if(alGetError() != AL_NO_ERROR
)
1128 throw std::runtime_error("Failed to create Filter");
1130 bool filterset
= false;
1131 if(params
.mGainHF
< 1.0f
&& params
.mGainLF
< 1.0f
)
1133 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_BANDPASS
);
1134 if(alGetError() == AL_NO_ERROR
)
1136 mContext
->alFilterf(filterid
, AL_BANDPASS_GAIN
, std::min(params
.mGain
, 1.0f
));
1137 mContext
->alFilterf(filterid
, AL_BANDPASS_GAINHF
, std::min(params
.mGainHF
, 1.0f
));
1138 mContext
->alFilterf(filterid
, AL_BANDPASS_GAINLF
, std::min(params
.mGainLF
, 1.0f
));
1142 if(!filterset
&& !(params
.mGainHF
< 1.0f
) && params
.mGainLF
< 1.0f
)
1144 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_HIGHPASS
);
1145 if(alGetError() == AL_NO_ERROR
)
1147 mContext
->alFilterf(filterid
, AL_HIGHPASS_GAIN
, std::min(params
.mGain
, 1.0f
));
1148 mContext
->alFilterf(filterid
, AL_HIGHPASS_GAINLF
, std::min(params
.mGainLF
, 1.0f
));
1154 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1155 if(alGetError() == AL_NO_ERROR
)
1157 mContext
->alFilterf(filterid
, AL_LOWPASS_GAIN
, std::min(params
.mGain
, 1.0f
));
1158 mContext
->alFilterf(filterid
, AL_LOWPASS_GAINHF
, std::min(params
.mGainHF
, 1.0f
));
1165 void ALSource::setDirectFilter(const FilterParams
&filter
)
1167 if(!(filter
.mGain
>= 0.0f
&& filter
.mGainHF
>= 0.0f
&& filter
.mGainLF
>= 0.0f
))
1168 throw std::runtime_error("Gain value out of range");
1169 CheckContext(mContext
);
1171 setFilterParams(mDirectFilter
, filter
);
1173 alSourcei(mId
, AL_DIRECT_FILTER
, mDirectFilter
);
1176 void ALSource::setSendFilter(ALuint send
, const FilterParams
&filter
)
1178 if(!(filter
.mGain
>= 0.0f
&& filter
.mGainHF
>= 0.0f
&& filter
.mGainLF
>= 0.0f
))
1179 throw std::runtime_error("Gain value out of range");
1180 CheckContext(mContext
);
1182 SendPropMap::iterator siter
= mEffectSlots
.find(send
);
1183 if(siter
== mEffectSlots
.end())
1185 ALuint filterid
= 0;
1187 setFilterParams(filterid
, filter
);
1188 if(!filterid
) return;
1190 siter
= mEffectSlots
.insert(std::make_pair(send
, SendProps(filterid
))).first
;
1193 setFilterParams(siter
->second
.mFilter
, filter
);
1197 ALuint slotid
= (siter
->second
.mSlot
? siter
->second
.mSlot
->getId() : 0);
1198 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, send
, siter
->second
.mFilter
);
1202 void ALSource::setAuxiliarySend(AuxiliaryEffectSlot auxslot
, ALuint send
)
1204 ALAuxiliaryEffectSlot
*slot
= auxslot
.getHandle();
1205 if(slot
) CheckContext(slot
->getContext());
1206 CheckContext(mContext
);
1208 SendPropMap::iterator siter
= mEffectSlots
.find(send
);
1209 if(siter
== mEffectSlots
.end())
1212 slot
->addSourceSend(Source(this), send
);
1213 siter
= mEffectSlots
.insert(std::make_pair(send
, SendProps(slot
))).first
;
1215 else if(siter
->second
.mSlot
!= slot
)
1217 if(slot
) slot
->addSourceSend(Source(this), send
);
1218 if(siter
->second
.mSlot
)
1219 siter
->second
.mSlot
->removeSourceSend(Source(this), send
);
1220 siter
->second
.mSlot
= slot
;
1225 ALuint slotid
= (siter
->second
.mSlot
? siter
->second
.mSlot
->getId() : 0);
1226 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, send
, siter
->second
.mFilter
);
1230 void ALSource::setAuxiliarySendFilter(AuxiliaryEffectSlot auxslot
, ALuint send
, const FilterParams
&filter
)
1232 if(!(filter
.mGain
>= 0.0f
&& filter
.mGainHF
>= 0.0f
&& filter
.mGainLF
>= 0.0f
))
1233 throw std::runtime_error("Gain value out of range");
1234 ALAuxiliaryEffectSlot
*slot
= auxslot
.getHandle();
1235 if(slot
) CheckContext(slot
->getContext());
1236 CheckContext(mContext
);
1238 SendPropMap::iterator siter
= mEffectSlots
.find(send
);
1239 if(siter
== mEffectSlots
.end())
1241 ALuint filterid
= 0;
1243 setFilterParams(filterid
, filter
);
1244 if(!filterid
&& !slot
)
1247 if(slot
) slot
->addSourceSend(Source(this), send
);
1248 siter
= mEffectSlots
.insert(std::make_pair(send
, SendProps(slot
, filterid
))).first
;
1252 if(siter
->second
.mSlot
!= slot
)
1254 if(slot
) slot
->addSourceSend(Source(this), send
);
1255 if(siter
->second
.mSlot
)
1256 siter
->second
.mSlot
->removeSourceSend(Source(this), send
);
1257 siter
->second
.mSlot
= slot
;
1259 setFilterParams(siter
->second
.mFilter
, filter
);
1264 ALuint slotid
= (siter
->second
.mSlot
? siter
->second
.mSlot
->getId() : 0);
1265 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, send
, siter
->second
.mFilter
);
1270 void ALSource::release()
1272 CheckContext(mContext
);
1274 if(mIsAsync
.load(std::memory_order_acquire
))
1276 mContext
->removeStream(this);
1277 mIsAsync
.store(false, std::memory_order_release
);
1282 alSourceRewind(mId
);
1283 alSourcei(mId
, AL_BUFFER
, 0);
1284 if(mContext
->hasExtension(EXT_EFX
))
1286 alSourcei(mId
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
1287 for(auto &i
: mEffectSlots
)
1288 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, 0, i
.first
, AL_FILTER_NULL
);
1290 mContext
->insertSourceId(mId
);
1294 mContext
->freeSource(this);
1297 mContext
->alDeleteFilters(1, &mDirectFilter
);
1298 mDirectFilter
= AL_FILTER_NULL
;
1300 for(auto &i
: mEffectSlots
)
1303 i
.second
.mSlot
->removeSourceSend(Source(this), i
.first
);
1304 if(i
.second
.mFilter
)
1305 mContext
->alDeleteFilters(1, &i
.second
.mFilter
);
1307 mEffectSlots
.clear();
1310 mBuffer
->removeSource(Source(this));
1319 // Need to use these to avoid extraneous commas in macro parameter lists
1320 using UInt64NSecPair
= std::pair
<uint64_t,std::chrono::nanoseconds
>;
1321 using SecondsPair
= std::pair
<Seconds
,Seconds
>;
1322 using ALfloatPair
= std::pair
<ALfloat
,ALfloat
>;
1323 using Vector3Pair
= std::pair
<Vector3
,Vector3
>;
1324 using BoolTriple
= std::tuple
<bool,bool,bool>;
1326 DECL_THUNK1(void, Source
, play
,, Buffer
)
1327 DECL_THUNK3(void, Source
, play
,, SharedPtr
<Decoder
>, ALuint
, ALuint
)
1328 DECL_THUNK0(void, Source
, stop
,)
1329 DECL_THUNK0(void, Source
, pause
,)
1330 DECL_THUNK0(void, Source
, resume
,)
1331 DECL_THUNK0(bool, Source
, isPlaying
, const)
1332 DECL_THUNK0(bool, Source
, isPaused
, const)
1333 DECL_THUNK1(void, Source
, setPriority
,, ALuint
)
1334 DECL_THUNK0(ALuint
, Source
, getPriority
, const)
1335 DECL_THUNK1(void, Source
, setOffset
,, uint64_t)
1336 DECL_THUNK0(UInt64NSecPair
, Source
, getSampleOffsetLatency
, const)
1337 DECL_THUNK0(SecondsPair
, Source
, getSecOffsetLatency
, const)
1338 DECL_THUNK1(void, Source
, setLooping
,, bool)
1339 DECL_THUNK0(bool, Source
, getLooping
, const)
1340 DECL_THUNK1(void, Source
, setPitch
,, ALfloat
)
1341 DECL_THUNK0(ALfloat
, Source
, getPitch
, const)
1342 DECL_THUNK1(void, Source
, setGain
,, ALfloat
)
1343 DECL_THUNK0(ALfloat
, Source
, getGain
, const)
1344 DECL_THUNK2(void, Source
, setGainRange
,, ALfloat
, ALfloat
)
1345 DECL_THUNK0(ALfloatPair
, Source
, getGainRange
, const)
1346 DECL_THUNK2(void, Source
, setDistanceRange
,, ALfloat
, ALfloat
)
1347 DECL_THUNK0(ALfloatPair
, Source
, getDistanceRange
, const)
1348 DECL_THUNK3(void, Source
, set3DParameters
,, const Vector3
&, const Vector3
&, const Vector3
&)
1349 DECL_THUNK3(void, Source
, set3DParameters
,, const Vector3
&, const Vector3
&, Vector3Pair
)
1350 DECL_THUNK3(void, Source
, setPosition
,, ALfloat
, ALfloat
, ALfloat
)
1351 DECL_THUNK1(void, Source
, setPosition
,, const ALfloat
*)
1352 DECL_THUNK0(Vector3
, Source
, getPosition
, const)
1353 DECL_THUNK3(void, Source
, setVelocity
,, ALfloat
, ALfloat
, ALfloat
)
1354 DECL_THUNK1(void, Source
, setVelocity
,, const ALfloat
*)
1355 DECL_THUNK0(Vector3
, Source
, getVelocity
, const)
1356 DECL_THUNK3(void, Source
, setDirection
,, ALfloat
, ALfloat
, ALfloat
)
1357 DECL_THUNK1(void, Source
, setDirection
,, const ALfloat
*)
1358 DECL_THUNK0(Vector3
, Source
, getDirection
, const)
1359 DECL_THUNK6(void, Source
, setOrientation
,, ALfloat
, ALfloat
, ALfloat
, ALfloat
, ALfloat
, ALfloat
)
1360 DECL_THUNK2(void, Source
, setOrientation
,, const ALfloat
*, const ALfloat
*)
1361 DECL_THUNK1(void, Source
, setOrientation
,, const ALfloat
*)
1362 DECL_THUNK0(Vector3Pair
, Source
, getOrientation
, const)
1363 DECL_THUNK2(void, Source
, setConeAngles
,, ALfloat
, ALfloat
)
1364 DECL_THUNK0(ALfloatPair
, Source
, getConeAngles
, const)
1365 DECL_THUNK2(void, Source
, setOuterConeGains
,, ALfloat
, ALfloat
)
1366 DECL_THUNK0(ALfloatPair
, Source
, getOuterConeGains
, const)
1367 DECL_THUNK2(void, Source
, setRolloffFactors
,, ALfloat
, ALfloat
)
1368 DECL_THUNK0(ALfloatPair
, Source
, getRolloffFactors
, const)
1369 DECL_THUNK1(void, Source
, setDopplerFactor
,, ALfloat
)
1370 DECL_THUNK0(ALfloat
, Source
, getDopplerFactor
, const)
1371 DECL_THUNK1(void, Source
, setRelative
,, bool)
1372 DECL_THUNK0(bool, Source
, getRelative
, const)
1373 DECL_THUNK1(void, Source
, setRadius
,, ALfloat
)
1374 DECL_THUNK0(ALfloat
, Source
, getRadius
, const)
1375 DECL_THUNK2(void, Source
, setStereoAngles
,, ALfloat
, ALfloat
)
1376 DECL_THUNK0(ALfloatPair
, Source
, getStereoAngles
, const)
1377 DECL_THUNK1(void, Source
, set3DSpatialize
,, Spatialize
)
1378 DECL_THUNK0(Spatialize
, Source
, get3DSpatialize
, const)
1379 DECL_THUNK1(void, Source
, setResamplerIndex
,, ALsizei
)
1380 DECL_THUNK0(ALsizei
, Source
, getResamplerIndex
, const)
1381 DECL_THUNK1(void, Source
, setAirAbsorptionFactor
,, ALfloat
)
1382 DECL_THUNK0(ALfloat
, Source
, getAirAbsorptionFactor
, const)
1383 DECL_THUNK3(void, Source
, setGainAuto
,, bool, bool, bool)
1384 DECL_THUNK0(BoolTriple
, Source
, getGainAuto
, const)
1385 DECL_THUNK1(void, Source
, setDirectFilter
,, const FilterParams
&)
1386 DECL_THUNK2(void, Source
, setSendFilter
,, ALuint
, const FilterParams
&)
1387 DECL_THUNK2(void, Source
, setAuxiliarySend
,, AuxiliaryEffectSlot
, ALuint
)
1388 DECL_THUNK3(void, Source
, setAuxiliarySendFilter
,, AuxiliaryEffectSlot
, ALuint
, const FilterParams
&)
1389 void Source::release()