18 #include "auxeffectslot.h"
19 #include "sourcegroup.h"
24 class ALBufferStream
{
25 SharedPtr
<Decoder
> mDecoder
;
37 Vector
<ALuint
> mBufferIds
;
41 std::pair
<uint64_t,uint64_t> mLoopPts
;
43 std::atomic
<bool> mDone
;
46 ALBufferStream(SharedPtr
<Decoder
> decoder
, ALuint updatelen
, ALuint numupdates
)
47 : mDecoder(decoder
), mUpdateLen(updatelen
), mNumUpdates(numupdates
),
48 mFormat(AL_NONE
), mFrequency(0), mFrameSize(0), mSilence(0),
49 mCurrentIdx(0), mSamplePos(0), mLoopPts
{0,0}, mHasLooped(false),
54 if(!mBufferIds
.empty())
56 alDeleteBuffers(mBufferIds
.size(), mBufferIds
.data());
61 uint64_t getLength() const { return mDecoder
->getLength(); }
62 uint64_t getPosition() const { return mSamplePos
; }
64 ALuint
getNumUpdates() const { return mNumUpdates
; }
65 ALuint
getUpdateLength() const { return mUpdateLen
; }
67 ALuint
getFrequency() const { return mFrequency
; }
69 bool seek(uint64_t pos
)
71 if(!mDecoder
->seek(pos
))
75 mDone
.store(false, std::memory_order_release
);
81 ALuint srate
= mDecoder
->getFrequency();
82 ChannelConfig chans
= mDecoder
->getChannelConfig();
83 SampleType type
= mDecoder
->getSampleType();
85 mLoopPts
= mDecoder
->getLoopPoints();
86 if(mLoopPts
.first
>= mLoopPts
.second
)
89 mLoopPts
.second
= std::numeric_limits
<uint64_t>::max();
93 mFrameSize
= FramesToBytes(1, chans
, type
);
94 mFormat
= GetFormat(chans
, type
);
95 if(mFormat
== AL_NONE
)
97 std::stringstream sstr
;
98 sstr
<< "Format not supported ("<<GetSampleTypeName(type
)<<", "<<GetChannelConfigName(chans
)<<")";
99 throw std::runtime_error(sstr
.str());
102 mData
.resize(mUpdateLen
* mFrameSize
);
103 if(type
== SampleType::UInt8
) mSilence
= 0x80;
104 else if(type
== SampleType::Mulaw
) mSilence
= 0x7f;
105 else mSilence
= 0x00;
107 mBufferIds
.assign(mNumUpdates
, 0);
108 alGenBuffers(mBufferIds
.size(), mBufferIds
.data());
111 int64_t getLoopStart() const { return mLoopPts
.first
; }
112 int64_t getLoopEnd() const { return mLoopPts
.second
; }
114 bool hasLooped() const { return mHasLooped
; }
115 bool hasMoreData() const { return !mDone
.load(std::memory_order_acquire
); }
116 bool streamMoreData(ALuint srcid
, bool loop
)
118 if(mDone
.load(std::memory_order_acquire
))
122 ALuint len
= mUpdateLen
;
123 if(loop
&& mSamplePos
<= mLoopPts
.second
)
124 len
= std::min
<uint64_t>(len
, mLoopPts
.second
- mSamplePos
);
128 frames
= mDecoder
->read(mData
.data(), len
);
129 mSamplePos
+= frames
;
130 if(frames
< mUpdateLen
&& loop
&& mSamplePos
> 0)
132 if(mSamplePos
< mLoopPts
.second
)
134 mLoopPts
.second
= mSamplePos
;
135 mLoopPts
.first
= std::min(mLoopPts
.first
, mLoopPts
.second
-1);
139 if(!mDecoder
->seek(mLoopPts
.first
))
141 mSamplePos
= mLoopPts
.first
;
144 len
= std::min
<uint64_t>(mUpdateLen
-frames
, mLoopPts
.second
-mLoopPts
.first
);
145 ALuint got
= mDecoder
->read(&mData
[frames
*mFrameSize
], len
);
149 } while(frames
< mUpdateLen
);
151 if(frames
< mUpdateLen
)
153 mDone
.store(true, std::memory_order_release
);
154 if(frames
== 0) return false;
155 mSamplePos
+= mUpdateLen
- frames
;
156 std::fill(mData
.begin() + frames
*mFrameSize
, mData
.end(), mSilence
);
159 alBufferData(mBufferIds
[mCurrentIdx
], mFormat
, mData
.data(), mData
.size(), mFrequency
);
160 alSourceQueueBuffers(srcid
, 1, &mBufferIds
[mCurrentIdx
]);
161 mCurrentIdx
= (mCurrentIdx
+1) % mBufferIds
.size();
167 SourceImpl::SourceImpl(ContextImpl
*context
)
168 : mContext(context
), mId(0), mBuffer(0), mGroup(nullptr), mIsAsync(false),
169 mDirectFilter(AL_FILTER_NULL
)
172 mEffectSlots
.reserve(mContext
->getDevice().getMaxAuxiliarySends());
175 SourceImpl::~SourceImpl()
180 void SourceImpl::resetProperties()
183 mGroup
->eraseSource(this);
188 mFadeGainTarget
= 1.0f
;
191 mPaused
.store(false, std::memory_order_release
);
198 mMaxDist
= std::numeric_limits
<float>::max();
199 mPosition
= Vector3(0.0f
);
200 mVelocity
= Vector3(0.0f
);
201 mDirection
= Vector3(0.0f
);
202 mOrientation
[0] = Vector3(0.0f
, 0.0f
, -1.0f
);
203 mOrientation
[1] = Vector3(0.0f
, 1.0f
, 0.0f
);
204 mConeInnerAngle
= 360.0f
;
205 mConeOuterAngle
= 360.0f
;
206 mConeOuterGain
= 0.0f
;
207 mConeOuterGainHF
= 1.0f
;
208 mRolloffFactor
= 1.0f
;
209 mRoomRolloffFactor
= 0.0f
;
210 mDopplerFactor
= 1.0f
;
211 mAirAbsorptionFactor
= 0.0f
;
213 mStereoAngles
[0] = F_PI
/ 6.0f
;
214 mStereoAngles
[1] = -F_PI
/ 6.0f
;
215 mSpatialize
= Spatialize::Auto
;
216 mResampler
= mContext
->hasExtension(AL::SOFT_source_resampler
) ?
217 alGetInteger(AL_DEFAULT_RESAMPLER_SOFT
) : 0;
220 mDryGainHFAuto
= true;
222 mWetGainHFAuto
= true;
224 mContext
->alDeleteFilters(1, &mDirectFilter
);
226 for(auto &i
: mEffectSlots
)
229 i
.mSlot
->removeSourceSend({Source(this), i
.mSendIdx
});
231 mContext
->alDeleteFilters(1, &i
.mFilter
);
233 mEffectSlots
.clear();
238 void SourceImpl::applyProperties(bool looping
, ALuint offset
) const
240 alSourcei(mId
, AL_LOOPING
, looping
? AL_TRUE
: AL_FALSE
);
241 alSourcei(mId
, AL_SAMPLE_OFFSET
, offset
);
242 alSourcef(mId
, AL_PITCH
, mPitch
* mGroupPitch
);
243 alSourcef(mId
, AL_GAIN
, mGain
* mGroupGain
* mFadeGain
);
244 alSourcef(mId
, AL_MIN_GAIN
, mMinGain
);
245 alSourcef(mId
, AL_MAX_GAIN
, mMaxGain
);
246 alSourcef(mId
, AL_REFERENCE_DISTANCE
, mRefDist
);
247 alSourcef(mId
, AL_MAX_DISTANCE
, mMaxDist
);
248 alSourcefv(mId
, AL_POSITION
, mPosition
.getPtr());
249 alSourcefv(mId
, AL_VELOCITY
, mVelocity
.getPtr());
250 alSourcefv(mId
, AL_DIRECTION
, mDirection
.getPtr());
251 if(mContext
->hasExtension(AL::EXT_BFORMAT
))
252 alSourcefv(mId
, AL_ORIENTATION
, &mOrientation
[0][0]);
253 alSourcef(mId
, AL_CONE_INNER_ANGLE
, mConeInnerAngle
);
254 alSourcef(mId
, AL_CONE_OUTER_ANGLE
, mConeOuterAngle
);
255 alSourcef(mId
, AL_CONE_OUTER_GAIN
, mConeOuterGain
);
256 alSourcef(mId
, AL_ROLLOFF_FACTOR
, mRolloffFactor
);
257 alSourcef(mId
, AL_DOPPLER_FACTOR
, mDopplerFactor
);
258 if(mContext
->hasExtension(AL::EXT_SOURCE_RADIUS
))
259 alSourcef(mId
, AL_SOURCE_RADIUS
, mRadius
);
260 if(mContext
->hasExtension(AL::EXT_STEREO_ANGLES
))
261 alSourcefv(mId
, AL_STEREO_ANGLES
, mStereoAngles
);
262 if(mContext
->hasExtension(AL::SOFT_source_spatialize
))
263 alSourcei(mId
, AL_SOURCE_SPATIALIZE_SOFT
, (ALint
)mSpatialize
);
264 if(mContext
->hasExtension(AL::SOFT_source_resampler
))
265 alSourcei(mId
, AL_SOURCE_RESAMPLER_SOFT
, mResampler
);
266 alSourcei(mId
, AL_SOURCE_RELATIVE
, mRelative
? AL_TRUE
: AL_FALSE
);
267 if(mContext
->hasExtension(AL::EXT_EFX
))
269 alSourcef(mId
, AL_CONE_OUTER_GAINHF
, mConeOuterGainHF
);
270 alSourcef(mId
, AL_ROOM_ROLLOFF_FACTOR
, mRoomRolloffFactor
);
271 alSourcef(mId
, AL_AIR_ABSORPTION_FACTOR
, mAirAbsorptionFactor
);
272 alSourcei(mId
, AL_DIRECT_FILTER_GAINHF_AUTO
, mDryGainHFAuto
? AL_TRUE
: AL_FALSE
);
273 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, mWetGainAuto
? AL_TRUE
: AL_FALSE
);
274 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, mWetGainHFAuto
? AL_TRUE
: AL_FALSE
);
275 alSourcei(mId
, AL_DIRECT_FILTER
, mDirectFilter
);
276 for(const auto &i
: mEffectSlots
)
278 ALuint slotid
= (i
.mSlot
? i
.mSlot
->getId() : 0);
279 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, i
.mSendIdx
, i
.mFilter
);
285 void SourceImpl::unsetGroup()
288 groupPropUpdate(1.0f
, 1.0f
);
291 void SourceImpl::groupPropUpdate(ALfloat gain
, ALfloat pitch
)
295 alSourcef(mId
, AL_PITCH
, mPitch
* pitch
);
296 alSourcef(mId
, AL_GAIN
, mGain
* gain
* mFadeGain
);
303 void SourceImpl::play(Buffer buffer
)
305 BufferImpl
*albuf
= buffer
.getHandle();
306 if(!albuf
) throw std::runtime_error("Buffer is not valid");
307 CheckContext(mContext
);
308 CheckContext(albuf
->getContext());
311 mContext
->removeStream(this);
312 mIsAsync
.store(false, std::memory_order_release
);
314 mFadeGainTarget
= mFadeGain
= 1.0f
;
315 mFadeTimeTarget
= mLastFadeTime
= std::chrono::steady_clock::now();
319 mId
= mContext
->getSourceId(mPriority
);
320 applyProperties(mLooping
, (ALuint
)std::min
<uint64_t>(mOffset
, std::numeric_limits
<ALint
>::max()));
324 mContext
->removeFadingSource(this);
325 mContext
->removePlayingSource(this);
327 alSourcei(mId
, AL_BUFFER
, 0);
328 alSourcei(mId
, AL_LOOPING
, mLooping
? AL_TRUE
: AL_FALSE
);
329 alSourcei(mId
, AL_SAMPLE_OFFSET
, (ALuint
)std::min
<uint64_t>(mOffset
, std::numeric_limits
<ALint
>::max()));
335 mBuffer
->removeSource(Source(this));
337 mBuffer
->addSource(Source(this));
339 alSourcei(mId
, AL_BUFFER
, mBuffer
->getId());
341 mPaused
.store(false, std::memory_order_release
);
342 mContext
->removePendingSource(this);
343 mContext
->addPlayingSource(this, mId
);
346 void SourceImpl::play(SharedPtr
<Decoder
>&& decoder
, ALuint chunk_len
, ALuint queue_size
)
349 throw std::runtime_error("Update length out of range");
351 throw std::runtime_error("Queue size out of range");
352 CheckContext(mContext
);
354 auto stream
= MakeUnique
<ALBufferStream
>(decoder
, chunk_len
, queue_size
);
358 mContext
->removeStream(this);
359 mIsAsync
.store(false, std::memory_order_release
);
361 mFadeGainTarget
= mFadeGain
= 1.0f
;
362 mFadeTimeTarget
= mLastFadeTime
= std::chrono::steady_clock::now();
366 mId
= mContext
->getSourceId(mPriority
);
367 applyProperties(false, 0);
371 mContext
->removeFadingSource(this);
372 mContext
->removePlayingSource(this);
374 alSourcei(mId
, AL_BUFFER
, 0);
375 alSourcei(mId
, AL_LOOPING
, AL_FALSE
);
376 alSourcei(mId
, AL_SAMPLE_OFFSET
, 0);
381 mBuffer
->removeSource(Source(this));
384 mStream
= std::move(stream
);
386 mStream
->seek(mOffset
);
389 for(ALuint i
= 0;i
< mStream
->getNumUpdates();i
++)
391 if(!mStream
->streamMoreData(mId
, mLooping
))
395 mPaused
.store(false, std::memory_order_release
);
397 mContext
->addStream(this);
398 mIsAsync
.store(true, std::memory_order_release
);
399 mContext
->removePendingSource(this);
400 mContext
->addPlayingSource(this);
403 void SourceImpl::play(SharedFuture
<Buffer
>&& future_buffer
)
405 if(!future_buffer
.valid())
406 throw std::runtime_error("Invalid future buffer");
407 if(future_buffer
.wait_for(std::chrono::milliseconds::zero()) == std::future_status::ready
)
409 play(future_buffer
.get());
413 CheckContext(mContext
);
415 mContext
->removeFadingSource(this);
416 mContext
->removePlayingSource(this);
419 mFadeGainTarget
= mFadeGain
= 1.0f
;
420 mFadeTimeTarget
= mLastFadeTime
= std::chrono::steady_clock::now();
422 mContext
->addPendingSource(this, std::move(future_buffer
));
426 void SourceImpl::makeStopped(bool dolock
)
431 mContext
->removeStream(this);
433 mContext
->removeStreamNoLock(this);
435 mIsAsync
.store(false, std::memory_order_release
);
440 alSourcei(mId
, AL_BUFFER
, 0);
441 if(mContext
->hasExtension(AL::EXT_EFX
))
443 alSourcei(mId
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
444 for(auto &i
: mEffectSlots
)
445 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, 0, i
.mSendIdx
, AL_FILTER_NULL
);
447 mContext
->insertSourceId(mId
);
453 mBuffer
->removeSource(Source(this));
456 mPaused
.store(false, std::memory_order_release
);
459 void SourceImpl::stop()
461 CheckContext(mContext
);
462 mContext
->removePendingSource(this);
463 mContext
->removeFadingSource(this);
464 mContext
->removePlayingSource(this);
469 void SourceImpl::fadeOutToStop(ALfloat gain
, std::chrono::milliseconds duration
)
471 if(!(gain
< 1.0f
&& gain
>= 0.0f
))
472 throw std::runtime_error("Fade gain target out of range");
473 if(duration
.count() <= 0)
474 throw std::runtime_error("Fade duration out of range");
475 CheckContext(mContext
);
477 mFadeGainTarget
= std::max
<ALfloat
>(gain
, 0.0001f
);
478 mLastFadeTime
= std::chrono::steady_clock::now();
479 mFadeTimeTarget
= mLastFadeTime
+ duration
;
481 mContext
->addFadingSource(this);
485 void SourceImpl::checkPaused()
487 if(mPaused
.load(std::memory_order_acquire
) || mId
== 0)
491 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
492 // Streaming sources may be in a stopped or initial state if underrun
493 mPaused
.store(state
== AL_PAUSED
|| (mStream
&& mStream
->hasMoreData()),
494 std::memory_order_release
);
497 void SourceImpl::pause()
499 CheckContext(mContext
);
500 if(mPaused
.load(std::memory_order_acquire
))
505 std::lock_guard
<std::mutex
> lock(mMutex
);
508 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
509 // Streaming sources may be in a stopped or initial state if underrun
510 mPaused
.store(state
== AL_PAUSED
|| (mStream
&& mStream
->hasMoreData()),
511 std::memory_order_release
);
515 void SourceImpl::resume()
517 CheckContext(mContext
);
518 if(!mPaused
.load(std::memory_order_acquire
))
523 mPaused
.store(false, std::memory_order_release
);
527 bool SourceImpl::isPending() const
529 CheckContext(mContext
);
530 return mContext
->isPendingSource(this);
533 bool SourceImpl::isPlaying() const
535 CheckContext(mContext
);
536 if(mId
== 0) return false;
539 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
541 throw std::runtime_error("Source state error");
543 return state
== AL_PLAYING
|| (!mPaused
.load(std::memory_order_acquire
) &&
544 mStream
&& mStream
->hasMoreData());
547 bool SourceImpl::isPaused() const
549 CheckContext(mContext
);
550 return mId
!= 0 && mPaused
.load(std::memory_order_acquire
);
554 void SourceImpl::setGroup(SourceGroup group
)
556 CheckContext(mContext
);
558 SourceGroupImpl
*parent
= group
.getHandle();
559 if(parent
== mGroup
) return;
562 mGroup
->eraseSource(this);
566 mGroup
->insertSource(this);
567 mGroupPitch
= mGroup
->getAppliedPitch();
568 mGroupGain
= mGroup
->getAppliedGain();
578 alSourcef(mId
, AL_PITCH
, mPitch
* mGroupPitch
);
579 alSourcef(mId
, AL_GAIN
, mGain
* mGroupGain
* mFadeGain
);
584 bool SourceImpl::checkPending(SharedFuture
<Buffer
> &future
)
586 if(future
.wait_for(std::chrono::milliseconds::zero()) != std::future_status::ready
)
589 BufferImpl
*buffer
= future
.get().getHandle();
590 if(Expect
<false>(buffer
->getContext() != mContext
))
595 mId
= mContext
->getSourceId(mPriority
);
596 applyProperties(mLooping
, (ALuint
)std::min
<uint64_t>(mOffset
, std::numeric_limits
<ALint
>::max()));
601 alSourcei(mId
, AL_BUFFER
, 0);
602 alSourcei(mId
, AL_LOOPING
, mLooping
? AL_TRUE
: AL_FALSE
);
603 alSourcei(mId
, AL_SAMPLE_OFFSET
, (ALuint
)std::min
<uint64_t>(mOffset
, std::numeric_limits
<ALint
>::max()));
608 mBuffer
->addSource(Source(this));
610 alSourcei(mId
, AL_BUFFER
, mBuffer
->getId());
612 mPaused
.store(false, std::memory_order_release
);
613 mContext
->addPlayingSource(this, mId
);
617 bool SourceImpl::fadeUpdate(std::chrono::steady_clock::time_point cur_fade_time
)
619 if((cur_fade_time
- mFadeTimeTarget
).count() >= 0)
621 mLastFadeTime
= mFadeTimeTarget
;
623 if(mFadeGainTarget
>= 1.0f
)
626 alSourcef(mId
, AL_GAIN
, mGain
* mGroupGain
);
629 mContext
->removePendingSource(this);
630 mContext
->removePlayingSource(this);
635 float mult
= std::pow(mFadeGainTarget
/mFadeGain
,
636 float(1.0/Seconds(mFadeTimeTarget
-mLastFadeTime
).count())
639 std::chrono::steady_clock::duration duration
= cur_fade_time
- mLastFadeTime
;
640 mLastFadeTime
= cur_fade_time
;
642 float gain
= mFadeGain
* std::pow(mult
, (float)Seconds(duration
).count());
643 if(Expect
<false>(gain
== mFadeGain
))
645 // Ensure the gain keeps moving toward its target, in case precision
646 // loss results in no change with small steps.
647 gain
= std::nextafter(gain
, mFadeGainTarget
);
652 alSourcef(mId
, AL_GAIN
, mGain
* mGroupGain
* mFadeGain
);
656 bool SourceImpl::playUpdate(ALuint id
)
659 alGetSourcei(id
, AL_SOURCE_STATE
, &state
);
660 if(Expect
<true>(state
== AL_PLAYING
|| state
== AL_PAUSED
))
664 mContext
->send(&MessageHandler::sourceStopped
, Source(this));
668 bool SourceImpl::playUpdate()
670 if(Expect
<true>(mIsAsync
.load(std::memory_order_acquire
)))
674 mContext
->send(&MessageHandler::sourceStopped
, Source(this));
679 ALint
SourceImpl::refillBufferStream()
682 alGetSourcei(mId
, AL_BUFFERS_PROCESSED
, &processed
);
686 alSourceUnqueueBuffers(mId
, 1, &buf
);
691 alGetSourcei(mId
, AL_BUFFERS_QUEUED
, &queued
);
692 for(;(ALuint
)queued
< mStream
->getNumUpdates();queued
++)
694 if(!mStream
->streamMoreData(mId
, mLooping
))
701 bool SourceImpl::updateAsync()
703 std::lock_guard
<std::mutex
> lock(mMutex
);
705 ALint queued
= refillBufferStream();
708 mIsAsync
.store(false, std::memory_order_release
);
713 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
714 if(!mPaused
.load(std::memory_order_acquire
))
716 // Make sure the source is still playing if it's not paused.
717 if(state
!= AL_PLAYING
)
722 // Rewind the source to an initial state if it underrun as it was
724 if(state
== AL_STOPPED
)
731 void SourceImpl::setPriority(ALuint priority
)
733 mPriority
= priority
;
737 void SourceImpl::setOffset(uint64_t offset
)
739 CheckContext(mContext
);
748 if(offset
>= std::numeric_limits
<ALint
>::max())
749 throw std::runtime_error("Offset out of range");
751 alSourcei(mId
, AL_SAMPLE_OFFSET
, (ALint
)offset
);
752 if(alGetError() != AL_NO_ERROR
)
753 throw std::runtime_error("Offset out of range");
757 std::lock_guard
<std::mutex
> lock(mMutex
);
758 if(!mStream
->seek(offset
))
759 throw std::runtime_error("Failed to seek to offset");
761 alSourcei(mId
, AL_BUFFER
, 0);
762 ALint queued
= refillBufferStream();
763 if(queued
> 0 && !mPaused
.load(std::memory_order_acquire
))
768 std::pair
<uint64_t,std::chrono::nanoseconds
> SourceImpl::getSampleOffsetLatency() const
770 std::pair
<uint64_t,std::chrono::nanoseconds
> ret
{0, std::chrono::nanoseconds::zero()};
771 CheckContext(mContext
);
772 if(mId
== 0) return ret
;
776 std::lock_guard
<std::mutex
> lock(mMutex
);
777 ALint queued
= 0, state
= -1, srcpos
= 0;
779 alGetSourcei(mId
, AL_BUFFERS_QUEUED
, &queued
);
780 if(mContext
->hasExtension(AL::SOFT_source_latency
))
783 mContext
->alGetSourcei64vSOFT(mId
, AL_SAMPLE_OFFSET_LATENCY_SOFT
, val
);
785 ret
.second
= std::chrono::nanoseconds(val
[1]);
788 alGetSourcei(mId
, AL_SAMPLE_OFFSET
, &srcpos
);
789 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
791 int64_t streampos
= mStream
->getPosition();
792 if(state
!= AL_STOPPED
)
794 // The amount of samples in the queue waiting to play
795 ALuint inqueue
= queued
*mStream
->getUpdateLength() - srcpos
;
796 if(!mStream
->hasLooped())
798 // A non-looped stream should never have more samples queued
799 // than have been read...
800 streampos
= std::max
<int64_t>(streampos
, inqueue
) - inqueue
;
804 streampos
-= inqueue
;
805 int64_t looplen
= mStream
->getLoopEnd() - mStream
->getLoopStart();
806 while(streampos
< mStream
->getLoopStart())
807 streampos
+= looplen
;
811 ret
.first
= streampos
;
816 if(mContext
->hasExtension(AL::SOFT_source_latency
))
819 mContext
->alGetSourcei64vSOFT(mId
, AL_SAMPLE_OFFSET_LATENCY_SOFT
, val
);
821 ret
.second
= std::chrono::nanoseconds(val
[1]);
824 alGetSourcei(mId
, AL_SAMPLE_OFFSET
, &srcpos
);
829 std::pair
<Seconds
,Seconds
> SourceImpl::getSecOffsetLatency() const
831 std::pair
<Seconds
,Seconds
> ret
{Seconds::zero(), Seconds::zero()};
832 CheckContext(mContext
);
833 if(mId
== 0) return ret
;
837 std::lock_guard
<std::mutex
> lock(mMutex
);
838 ALint queued
= 0, state
= -1;
841 alGetSourcei(mId
, AL_BUFFERS_QUEUED
, &queued
);
842 if(mContext
->hasExtension(AL::SOFT_source_latency
))
845 mContext
->alGetSourcedvSOFT(mId
, AL_SEC_OFFSET_LATENCY_SOFT
, val
);
847 ret
.second
= Seconds(val
[1]);
852 alGetSourcef(mId
, AL_SEC_OFFSET
, &f
);
855 alGetSourcei(mId
, AL_SOURCE_STATE
, &state
);
858 int64_t streampos
= mStream
->getPosition();
859 if(state
!= AL_STOPPED
)
862 frac
= std::modf(srcpos
* mStream
->getFrequency(), &ipos
);
864 // The amount of samples in the queue waiting to play
865 ALuint inqueue
= queued
*mStream
->getUpdateLength() - (ALuint
)ipos
;
866 if(!mStream
->hasLooped())
868 // A non-looped stream should never have more samples queued
869 // than have been read...
870 streampos
= std::max
<int64_t>(streampos
, inqueue
) - inqueue
;
874 streampos
-= inqueue
;
875 int64_t looplen
= mStream
->getLoopEnd() - mStream
->getLoopStart();
876 while(streampos
< mStream
->getLoopStart())
877 streampos
+= looplen
;
881 ret
.first
= Seconds((streampos
+frac
) / mStream
->getFrequency());
885 if(mContext
->hasExtension(AL::SOFT_source_latency
))
888 mContext
->alGetSourcedvSOFT(mId
, AL_SEC_OFFSET_LATENCY_SOFT
, val
);
889 ret
.first
= Seconds(val
[0]);
890 ret
.second
= Seconds(val
[1]);
895 alGetSourcef(mId
, AL_SEC_OFFSET
, &f
);
896 ret
.first
= Seconds(f
);
902 void SourceImpl::setLooping(bool looping
)
904 CheckContext(mContext
);
907 alSourcei(mId
, AL_LOOPING
, looping
? AL_TRUE
: AL_FALSE
);
912 void SourceImpl::setPitch(ALfloat pitch
)
915 throw std::runtime_error("Pitch out of range");
916 CheckContext(mContext
);
918 alSourcef(mId
, AL_PITCH
, pitch
* mGroupPitch
);
923 void SourceImpl::setGain(ALfloat gain
)
926 throw std::runtime_error("Gain out of range");
927 CheckContext(mContext
);
929 alSourcef(mId
, AL_GAIN
, gain
* mGroupGain
* mFadeGain
);
933 void SourceImpl::setGainRange(ALfloat mingain
, ALfloat maxgain
)
935 if(!(mingain
>= 0.0f
&& maxgain
<= 1.0f
&& maxgain
>= mingain
))
936 throw std::runtime_error("Gain range out of range");
937 CheckContext(mContext
);
940 alSourcef(mId
, AL_MIN_GAIN
, mingain
);
941 alSourcef(mId
, AL_MAX_GAIN
, maxgain
);
948 void SourceImpl::setDistanceRange(ALfloat refdist
, ALfloat maxdist
)
950 if(!(refdist
>= 0.0f
&& maxdist
<= std::numeric_limits
<float>::max() && refdist
<= maxdist
))
951 throw std::runtime_error("Distance range out of range");
952 CheckContext(mContext
);
955 alSourcef(mId
, AL_REFERENCE_DISTANCE
, refdist
);
956 alSourcef(mId
, AL_MAX_DISTANCE
, maxdist
);
963 void SourceImpl::set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const Vector3
&direction
)
965 CheckContext(mContext
);
968 Batcher batcher
= mContext
->getBatcher();
969 alSourcefv(mId
, AL_POSITION
, position
.getPtr());
970 alSourcefv(mId
, AL_VELOCITY
, velocity
.getPtr());
971 alSourcefv(mId
, AL_DIRECTION
, direction
.getPtr());
973 mPosition
= position
;
974 mVelocity
= velocity
;
975 mDirection
= direction
;
978 void SourceImpl::set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
)
980 static_assert(sizeof(orientation
) == sizeof(ALfloat
[6]), "Invalid Vector3 pair size");
981 CheckContext(mContext
);
984 Batcher batcher
= mContext
->getBatcher();
985 alSourcefv(mId
, AL_POSITION
, position
.getPtr());
986 alSourcefv(mId
, AL_VELOCITY
, velocity
.getPtr());
987 if(mContext
->hasExtension(AL::EXT_BFORMAT
))
988 alSourcefv(mId
, AL_ORIENTATION
, orientation
.first
.getPtr());
989 alSourcefv(mId
, AL_DIRECTION
, orientation
.first
.getPtr());
991 mPosition
= position
;
992 mVelocity
= velocity
;
993 mDirection
= mOrientation
[0] = orientation
.first
;
994 mOrientation
[1] = orientation
.second
;
998 void SourceImpl::setPosition(ALfloat x
, ALfloat y
, ALfloat z
)
1000 CheckContext(mContext
);
1002 alSource3f(mId
, AL_POSITION
, x
, y
, z
);
1008 void SourceImpl::setPosition(const ALfloat
*pos
)
1010 CheckContext(mContext
);
1012 alSourcefv(mId
, AL_POSITION
, pos
);
1013 mPosition
[0] = pos
[0];
1014 mPosition
[1] = pos
[1];
1015 mPosition
[2] = pos
[2];
1018 void SourceImpl::setVelocity(ALfloat x
, ALfloat y
, ALfloat z
)
1020 CheckContext(mContext
);
1022 alSource3f(mId
, AL_VELOCITY
, x
, y
, z
);
1028 void SourceImpl::setVelocity(const ALfloat
*vel
)
1030 CheckContext(mContext
);
1032 alSourcefv(mId
, AL_VELOCITY
, vel
);
1033 mVelocity
[0] = vel
[0];
1034 mVelocity
[1] = vel
[1];
1035 mVelocity
[2] = vel
[2];
1038 void SourceImpl::setDirection(ALfloat x
, ALfloat y
, ALfloat z
)
1040 CheckContext(mContext
);
1042 alSource3f(mId
, AL_DIRECTION
, x
, y
, z
);
1048 void SourceImpl::setDirection(const ALfloat
*dir
)
1050 CheckContext(mContext
);
1052 alSourcefv(mId
, AL_DIRECTION
, dir
);
1053 mDirection
[0] = dir
[0];
1054 mDirection
[1] = dir
[1];
1055 mDirection
[2] = dir
[2];
1058 void SourceImpl::setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
)
1060 CheckContext(mContext
);
1063 ALfloat ori
[6] = { x1
, y1
, z1
, x2
, y2
, z2
};
1064 if(mContext
->hasExtension(AL::EXT_BFORMAT
))
1065 alSourcefv(mId
, AL_ORIENTATION
, ori
);
1066 alSourcefv(mId
, AL_DIRECTION
, ori
);
1068 mDirection
[0] = mOrientation
[0][0] = x1
;
1069 mDirection
[1] = mOrientation
[0][1] = y1
;
1070 mDirection
[2] = mOrientation
[0][2] = z1
;
1071 mOrientation
[1][0] = x2
;
1072 mOrientation
[1][1] = y2
;
1073 mOrientation
[1][2] = z2
;
1076 void SourceImpl::setOrientation(const ALfloat
*at
, const ALfloat
*up
)
1078 CheckContext(mContext
);
1081 ALfloat ori
[6] = { at
[0], at
[1], at
[2], up
[0], up
[1], up
[2] };
1082 if(mContext
->hasExtension(AL::EXT_BFORMAT
))
1083 alSourcefv(mId
, AL_ORIENTATION
, ori
);
1084 alSourcefv(mId
, AL_DIRECTION
, ori
);
1086 mDirection
[0] = mOrientation
[0][0] = at
[0];
1087 mDirection
[1] = mOrientation
[0][1] = at
[1];
1088 mDirection
[2] = mOrientation
[0][2] = at
[2];
1089 mOrientation
[1][0] = up
[0];
1090 mOrientation
[1][1] = up
[1];
1091 mOrientation
[1][2] = up
[2];
1094 void SourceImpl::setOrientation(const ALfloat
*ori
)
1096 CheckContext(mContext
);
1099 if(mContext
->hasExtension(AL::EXT_BFORMAT
))
1100 alSourcefv(mId
, AL_ORIENTATION
, ori
);
1101 alSourcefv(mId
, AL_DIRECTION
, ori
);
1103 mDirection
[0] = mOrientation
[0][0] = ori
[0];
1104 mDirection
[1] = mOrientation
[0][1] = ori
[1];
1105 mDirection
[2] = mOrientation
[0][2] = ori
[2];
1106 mOrientation
[1][0] = ori
[3];
1107 mOrientation
[1][1] = ori
[4];
1108 mOrientation
[1][2] = ori
[5];
1112 void SourceImpl::setConeAngles(ALfloat inner
, ALfloat outer
)
1114 if(!(inner
>= 0.0f
&& outer
<= 360.0f
&& outer
>= inner
))
1115 throw std::runtime_error("Cone angles out of range");
1116 CheckContext(mContext
);
1119 alSourcef(mId
, AL_CONE_INNER_ANGLE
, inner
);
1120 alSourcef(mId
, AL_CONE_OUTER_ANGLE
, outer
);
1122 mConeInnerAngle
= inner
;
1123 mConeOuterAngle
= outer
;
1126 void SourceImpl::setOuterConeGains(ALfloat gain
, ALfloat gainhf
)
1128 if(!(gain
>= 0.0f
&& gain
<= 1.0f
&& gainhf
>= 0.0f
&& gainhf
<= 1.0f
))
1129 throw std::runtime_error("Outer cone gain out of range");
1130 CheckContext(mContext
);
1133 alSourcef(mId
, AL_CONE_OUTER_GAIN
, gain
);
1134 if(mContext
->hasExtension(AL::EXT_EFX
))
1135 alSourcef(mId
, AL_CONE_OUTER_GAINHF
, gainhf
);
1137 mConeOuterGain
= gain
;
1138 mConeOuterGainHF
= gainhf
;
1142 void SourceImpl::setRolloffFactors(ALfloat factor
, ALfloat roomfactor
)
1144 if(!(factor
>= 0.0f
&& roomfactor
>= 0.0f
))
1145 throw std::runtime_error("Rolloff factor out of range");
1146 CheckContext(mContext
);
1149 alSourcef(mId
, AL_ROLLOFF_FACTOR
, factor
);
1150 if(mContext
->hasExtension(AL::EXT_EFX
))
1151 alSourcef(mId
, AL_ROOM_ROLLOFF_FACTOR
, roomfactor
);
1153 mRolloffFactor
= factor
;
1154 mRoomRolloffFactor
= roomfactor
;
1157 void SourceImpl::setDopplerFactor(ALfloat factor
)
1159 if(!(factor
>= 0.0f
&& factor
<= 1.0f
))
1160 throw std::runtime_error("Doppler factor out of range");
1161 CheckContext(mContext
);
1163 alSourcef(mId
, AL_DOPPLER_FACTOR
, factor
);
1164 mDopplerFactor
= factor
;
1167 void SourceImpl::setAirAbsorptionFactor(ALfloat factor
)
1169 if(!(factor
>= 0.0f
&& factor
<= 10.0f
))
1170 throw std::runtime_error("Absorption factor out of range");
1171 CheckContext(mContext
);
1172 if(mId
!= 0 && mContext
->hasExtension(AL::EXT_EFX
))
1173 alSourcef(mId
, AL_AIR_ABSORPTION_FACTOR
, factor
);
1174 mAirAbsorptionFactor
= factor
;
1177 void SourceImpl::setRadius(ALfloat radius
)
1179 if(!(mRadius
>= 0.0f
))
1180 throw std::runtime_error("Radius out of range");
1181 CheckContext(mContext
);
1182 if(mId
!= 0 && mContext
->hasExtension(AL::EXT_SOURCE_RADIUS
))
1183 alSourcef(mId
, AL_SOURCE_RADIUS
, radius
);
1187 void SourceImpl::setStereoAngles(ALfloat leftAngle
, ALfloat rightAngle
)
1189 CheckContext(mContext
);
1190 if(mId
!= 0 && mContext
->hasExtension(AL::EXT_STEREO_ANGLES
))
1192 ALfloat angles
[2] = { leftAngle
, rightAngle
};
1193 alSourcefv(mId
, AL_STEREO_ANGLES
, angles
);
1195 mStereoAngles
[0] = leftAngle
;
1196 mStereoAngles
[1] = rightAngle
;
1199 void SourceImpl::set3DSpatialize(Spatialize spatialize
)
1201 CheckContext(mContext
);
1202 if(mId
!= 0 && mContext
->hasExtension(AL::SOFT_source_spatialize
))
1203 alSourcei(mId
, AL_SOURCE_SPATIALIZE_SOFT
, (ALint
)spatialize
);
1204 mSpatialize
= spatialize
;
1207 void SourceImpl::setResamplerIndex(ALsizei index
)
1210 throw std::runtime_error("Resampler index out of range");
1211 index
= std::min
<ALsizei
>(index
, mContext
->getAvailableResamplers().size());
1212 if(mId
!= 0 && mContext
->hasExtension(AL::SOFT_source_resampler
))
1213 alSourcei(mId
, AL_SOURCE_RESAMPLER_SOFT
, index
);
1217 void SourceImpl::setRelative(bool relative
)
1219 CheckContext(mContext
);
1221 alSourcei(mId
, AL_SOURCE_RELATIVE
, relative
? AL_TRUE
: AL_FALSE
);
1222 mRelative
= relative
;
1225 void SourceImpl::setGainAuto(bool directhf
, bool send
, bool sendhf
)
1227 CheckContext(mContext
);
1228 if(mId
!= 0 && mContext
->hasExtension(AL::EXT_EFX
))
1230 alSourcei(mId
, AL_DIRECT_FILTER_GAINHF_AUTO
, directhf
? AL_TRUE
: AL_FALSE
);
1231 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, send
? AL_TRUE
: AL_FALSE
);
1232 alSourcei(mId
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, sendhf
? AL_TRUE
: AL_FALSE
);
1234 mDryGainHFAuto
= directhf
;
1235 mWetGainAuto
= send
;
1236 mWetGainHFAuto
= sendhf
;
1240 void SourceImpl::setFilterParams(ALuint
&filterid
, const FilterParams
¶ms
)
1242 if(!mContext
->hasExtension(AL::EXT_EFX
))
1245 if(!(params
.mGain
< 1.0f
|| params
.mGainHF
< 1.0f
|| params
.mGainLF
< 1.0f
))
1248 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_NULL
);
1255 mContext
->alGenFilters(1, &filterid
);
1256 if(alGetError() != AL_NO_ERROR
)
1257 throw std::runtime_error("Failed to create Filter");
1259 bool filterset
= false;
1260 if(params
.mGainHF
< 1.0f
&& params
.mGainLF
< 1.0f
)
1262 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_BANDPASS
);
1263 if(alGetError() == AL_NO_ERROR
)
1265 mContext
->alFilterf(filterid
, AL_BANDPASS_GAIN
, std::min(params
.mGain
, 1.0f
));
1266 mContext
->alFilterf(filterid
, AL_BANDPASS_GAINHF
, std::min(params
.mGainHF
, 1.0f
));
1267 mContext
->alFilterf(filterid
, AL_BANDPASS_GAINLF
, std::min(params
.mGainLF
, 1.0f
));
1271 if(!filterset
&& !(params
.mGainHF
< 1.0f
) && params
.mGainLF
< 1.0f
)
1273 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_HIGHPASS
);
1274 if(alGetError() == AL_NO_ERROR
)
1276 mContext
->alFilterf(filterid
, AL_HIGHPASS_GAIN
, std::min(params
.mGain
, 1.0f
));
1277 mContext
->alFilterf(filterid
, AL_HIGHPASS_GAINLF
, std::min(params
.mGainLF
, 1.0f
));
1283 mContext
->alFilteri(filterid
, AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1284 if(alGetError() == AL_NO_ERROR
)
1286 mContext
->alFilterf(filterid
, AL_LOWPASS_GAIN
, std::min(params
.mGain
, 1.0f
));
1287 mContext
->alFilterf(filterid
, AL_LOWPASS_GAINHF
, std::min(params
.mGainHF
, 1.0f
));
1294 void SourceImpl::setDirectFilter(const FilterParams
&filter
)
1296 if(!(filter
.mGain
>= 0.0f
&& filter
.mGainHF
>= 0.0f
&& filter
.mGainLF
>= 0.0f
))
1297 throw std::runtime_error("Gain value out of range");
1298 CheckContext(mContext
);
1300 setFilterParams(mDirectFilter
, filter
);
1302 alSourcei(mId
, AL_DIRECT_FILTER
, mDirectFilter
);
1305 void SourceImpl::setSendFilter(ALuint send
, const FilterParams
&filter
)
1307 if(!(filter
.mGain
>= 0.0f
&& filter
.mGainHF
>= 0.0f
&& filter
.mGainLF
>= 0.0f
))
1308 throw std::runtime_error("Gain value out of range");
1309 CheckContext(mContext
);
1311 auto siter
= std::lower_bound(mEffectSlots
.begin(), mEffectSlots
.end(), send
,
1312 [](const SendProps
&prop
, ALuint send
) -> bool
1313 { return prop
.mSendIdx
< send
; }
1315 if(siter
== mEffectSlots
.end() || siter
->mSendIdx
!= send
)
1317 ALuint filterid
= 0;
1319 setFilterParams(filterid
, filter
);
1320 if(!filterid
) return;
1322 siter
= mEffectSlots
.emplace(siter
, send
, filterid
);
1325 setFilterParams(siter
->mFilter
, filter
);
1329 ALuint slotid
= (siter
->mSlot
? siter
->mSlot
->getId() : 0);
1330 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, send
, siter
->mFilter
);
1334 void SourceImpl::setAuxiliarySend(AuxiliaryEffectSlot auxslot
, ALuint send
)
1336 AuxiliaryEffectSlotImpl
*slot
= auxslot
.getHandle();
1337 if(slot
) CheckContext(slot
->getContext());
1338 CheckContext(mContext
);
1340 auto siter
= std::lower_bound(mEffectSlots
.begin(), mEffectSlots
.end(), send
,
1341 [](const SendProps
&prop
, ALuint send
) -> bool
1342 { return prop
.mSendIdx
< send
; }
1344 if(siter
== mEffectSlots
.end() || siter
->mSendIdx
!= send
)
1347 slot
->addSourceSend({Source(this), send
});
1348 siter
= mEffectSlots
.emplace(siter
, send
, slot
);
1350 else if(siter
->mSlot
!= slot
)
1352 if(slot
) slot
->addSourceSend({Source(this), send
});
1354 siter
->mSlot
->removeSourceSend({Source(this), send
});
1355 siter
->mSlot
= slot
;
1360 ALuint slotid
= (siter
->mSlot
? siter
->mSlot
->getId() : 0);
1361 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, send
, siter
->mFilter
);
1365 void SourceImpl::setAuxiliarySendFilter(AuxiliaryEffectSlot auxslot
, ALuint send
, const FilterParams
&filter
)
1367 if(!(filter
.mGain
>= 0.0f
&& filter
.mGainHF
>= 0.0f
&& filter
.mGainLF
>= 0.0f
))
1368 throw std::runtime_error("Gain value out of range");
1369 AuxiliaryEffectSlotImpl
*slot
= auxslot
.getHandle();
1370 if(slot
) CheckContext(slot
->getContext());
1371 CheckContext(mContext
);
1373 auto siter
= std::lower_bound(mEffectSlots
.begin(), mEffectSlots
.end(), send
,
1374 [](const SendProps
&prop
, ALuint send
) -> bool
1375 { return prop
.mSendIdx
< send
; }
1377 if(siter
== mEffectSlots
.end() || siter
->mSendIdx
!= send
)
1379 ALuint filterid
= 0;
1381 setFilterParams(filterid
, filter
);
1382 if(!filterid
&& !slot
)
1385 if(slot
) slot
->addSourceSend({Source(this), send
});
1386 siter
= mEffectSlots
.emplace(siter
, send
, slot
, filterid
);
1390 if(siter
->mSlot
!= slot
)
1392 if(slot
) slot
->addSourceSend({Source(this), send
});
1394 siter
->mSlot
->removeSourceSend({Source(this), send
});
1395 siter
->mSlot
= slot
;
1397 setFilterParams(siter
->mFilter
, filter
);
1402 ALuint slotid
= (siter
->mSlot
? siter
->mSlot
->getId() : 0);
1403 alSource3i(mId
, AL_AUXILIARY_SEND_FILTER
, slotid
, send
, siter
->mFilter
);
1408 void SourceImpl::release()
1413 mContext
->freeSource(this);
1417 // Need to use these to avoid extraneous commas in macro parameter lists
1418 using UInt64NSecPair
= std::pair
<uint64_t,std::chrono::nanoseconds
>;
1419 using SecondsPair
= std::pair
<Seconds
,Seconds
>;
1420 using ALfloatPair
= std::pair
<ALfloat
,ALfloat
>;
1421 using Vector3Pair
= std::pair
<Vector3
,Vector3
>;
1422 using BoolTriple
= std::tuple
<bool,bool,bool>;
1424 DECL_THUNK1(void, Source
, play
,, Buffer
)
1425 DECL_THUNK3(void, Source
, play
,, SharedPtr
<Decoder
>, ALuint
, ALuint
)
1426 DECL_THUNK1(void, Source
, play
,, SharedFuture
<Buffer
>)
1427 DECL_THUNK0(void, Source
, stop
,)
1428 DECL_THUNK2(void, Source
, fadeOutToStop
,, ALfloat
, std::chrono::milliseconds
)
1429 DECL_THUNK0(void, Source
, pause
,)
1430 DECL_THUNK0(void, Source
, resume
,)
1431 DECL_THUNK0(bool, Source
, isPending
, const)
1432 DECL_THUNK0(bool, Source
, isPlaying
, const)
1433 DECL_THUNK0(bool, Source
, isPaused
, const)
1434 DECL_THUNK1(void, Source
, setGroup
,, SourceGroup
)
1435 DECL_THUNK0(SourceGroup
, Source
, getGroup
, const)
1436 DECL_THUNK1(void, Source
, setPriority
,, ALuint
)
1437 DECL_THUNK0(ALuint
, Source
, getPriority
, const)
1438 DECL_THUNK1(void, Source
, setOffset
,, uint64_t)
1439 DECL_THUNK0(UInt64NSecPair
, Source
, getSampleOffsetLatency
, const)
1440 DECL_THUNK0(SecondsPair
, Source
, getSecOffsetLatency
, const)
1441 DECL_THUNK1(void, Source
, setLooping
,, bool)
1442 DECL_THUNK0(bool, Source
, getLooping
, const)
1443 DECL_THUNK1(void, Source
, setPitch
,, ALfloat
)
1444 DECL_THUNK0(ALfloat
, Source
, getPitch
, const)
1445 DECL_THUNK1(void, Source
, setGain
,, ALfloat
)
1446 DECL_THUNK0(ALfloat
, Source
, getGain
, const)
1447 DECL_THUNK2(void, Source
, setGainRange
,, ALfloat
, ALfloat
)
1448 DECL_THUNK0(ALfloatPair
, Source
, getGainRange
, const)
1449 DECL_THUNK2(void, Source
, setDistanceRange
,, ALfloat
, ALfloat
)
1450 DECL_THUNK0(ALfloatPair
, Source
, getDistanceRange
, const)
1451 DECL_THUNK3(void, Source
, set3DParameters
,, const Vector3
&, const Vector3
&, const Vector3
&)
1452 DECL_THUNK3(void, Source
, set3DParameters
,, const Vector3
&, const Vector3
&, const Vector3Pair
&)
1453 DECL_THUNK3(void, Source
, setPosition
,, ALfloat
, ALfloat
, ALfloat
)
1454 DECL_THUNK1(void, Source
, setPosition
,, const ALfloat
*)
1455 DECL_THUNK0(Vector3
, Source
, getPosition
, const)
1456 DECL_THUNK3(void, Source
, setVelocity
,, ALfloat
, ALfloat
, ALfloat
)
1457 DECL_THUNK1(void, Source
, setVelocity
,, const ALfloat
*)
1458 DECL_THUNK0(Vector3
, Source
, getVelocity
, const)
1459 DECL_THUNK3(void, Source
, setDirection
,, ALfloat
, ALfloat
, ALfloat
)
1460 DECL_THUNK1(void, Source
, setDirection
,, const ALfloat
*)
1461 DECL_THUNK0(Vector3
, Source
, getDirection
, const)
1462 DECL_THUNK6(void, Source
, setOrientation
,, ALfloat
, ALfloat
, ALfloat
, ALfloat
, ALfloat
, ALfloat
)
1463 DECL_THUNK2(void, Source
, setOrientation
,, const ALfloat
*, const ALfloat
*)
1464 DECL_THUNK1(void, Source
, setOrientation
,, const ALfloat
*)
1465 DECL_THUNK0(Vector3Pair
, Source
, getOrientation
, const)
1466 DECL_THUNK2(void, Source
, setConeAngles
,, ALfloat
, ALfloat
)
1467 DECL_THUNK0(ALfloatPair
, Source
, getConeAngles
, const)
1468 DECL_THUNK2(void, Source
, setOuterConeGains
,, ALfloat
, ALfloat
)
1469 DECL_THUNK0(ALfloatPair
, Source
, getOuterConeGains
, const)
1470 DECL_THUNK2(void, Source
, setRolloffFactors
,, ALfloat
, ALfloat
)
1471 DECL_THUNK0(ALfloatPair
, Source
, getRolloffFactors
, const)
1472 DECL_THUNK1(void, Source
, setDopplerFactor
,, ALfloat
)
1473 DECL_THUNK0(ALfloat
, Source
, getDopplerFactor
, const)
1474 DECL_THUNK1(void, Source
, setRelative
,, bool)
1475 DECL_THUNK0(bool, Source
, getRelative
, const)
1476 DECL_THUNK1(void, Source
, setRadius
,, ALfloat
)
1477 DECL_THUNK0(ALfloat
, Source
, getRadius
, const)
1478 DECL_THUNK2(void, Source
, setStereoAngles
,, ALfloat
, ALfloat
)
1479 DECL_THUNK0(ALfloatPair
, Source
, getStereoAngles
, const)
1480 DECL_THUNK1(void, Source
, set3DSpatialize
,, Spatialize
)
1481 DECL_THUNK0(Spatialize
, Source
, get3DSpatialize
, const)
1482 DECL_THUNK1(void, Source
, setResamplerIndex
,, ALsizei
)
1483 DECL_THUNK0(ALsizei
, Source
, getResamplerIndex
, const)
1484 DECL_THUNK1(void, Source
, setAirAbsorptionFactor
,, ALfloat
)
1485 DECL_THUNK0(ALfloat
, Source
, getAirAbsorptionFactor
, const)
1486 DECL_THUNK3(void, Source
, setGainAuto
,, bool, bool, bool)
1487 DECL_THUNK0(BoolTriple
, Source
, getGainAuto
, const)
1488 DECL_THUNK1(void, Source
, setDirectFilter
,, const FilterParams
&)
1489 DECL_THUNK2(void, Source
, setSendFilter
,, ALuint
, const FilterParams
&)
1490 DECL_THUNK2(void, Source
, setAuxiliarySend
,, AuxiliaryEffectSlot
, ALuint
)
1491 DECL_THUNK3(void, Source
, setAuxiliarySendFilter
,, AuxiliaryEffectSlot
, ALuint
, const FilterParams
&)
1492 void Source::release()