18 #if defined(ALURE_BUILD_STATIC) || defined(ALURE_STATIC_LIB)
20 #elif defined(ALURE_BUILD_DLL)
21 #define ALURE_API __declspec(dllexport)
23 #define ALURE_API __declspec(dllimport)
31 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
32 #define EFXEAXREVERBPROPERTIES_DEFINED
42 float flReflectionsGain
;
43 float flReflectionsDelay
;
44 float flReflectionsPan
[3];
45 float flLateReverbGain
;
46 float flLateReverbDelay
;
47 float flLateReverbPan
[3];
50 float flModulationTime
;
51 float flModulationDepth
;
52 float flAirAbsorptionGainHF
;
55 float flRoomRolloffFactor
;
57 } EFXEAXREVERBPROPERTIES
, *LPEFXEAXREVERBPROPERTIES
;
63 class DeviceManagerImpl
;
75 class SourceGroupImpl
;
76 class AuxiliaryEffectSlot
;
77 class AuxiliaryEffectSlotImpl
;
86 using RemoveRefT
= typename
std::remove_reference
<T
>::type
;
88 using EnableIfT
= typename
std::enable_if
<B
>::type
;
91 // Duration in seconds, using double precision
92 using Seconds
= std::chrono::duration
<double>;
94 // A SharedPtr implementation, defaults to C++11's std::shared_ptr. If this is
95 // changed, you must recompile the library.
97 using SharedPtr
= std::shared_ptr
<T
>;
98 template<typename T
, typename
... Args
>
99 constexpr inline SharedPtr
<T
> MakeShared(Args
&&... args
)
101 return std::make_shared
<T
>(std::forward
<Args
>(args
)...);
104 // A UniquePtr implementation, defaults to C++11's std::unique_ptr. If this is
105 // changed, you must recompile the library.
106 template<typename T
, typename D
= std::default_delete
<T
>>
107 using UniquePtr
= std::unique_ptr
<T
, D
>;
108 template<typename T
, typename
... Args
>
109 constexpr inline UniquePtr
<T
> MakeUnique(Args
&&... args
)
111 #if __cplusplus >= 201402L
112 return std::make_unique
<T
>(std::forward
<Args
>(args
)...);
114 return std::unique_ptr
<T
>(new T(std::forward
<Args
>(args
)...));
118 // A Vector implementation, defaults to C++'s std::vector. If this is changed,
119 // you must recompile the library.
121 using Vector
= std::vector
<T
>;
123 // A static-sized Array implementation, defaults to C++11's std::array. If this
124 // is changed, you must recompile the library.
125 template<typename T
, std::size_t N
>
126 using Array
= std::array
<T
, N
>;
128 // A String implementation, default's to C++'s std::string. If this is changed,
129 // you must recompile the library.
131 using BasicString
= std::basic_string
<T
>;
132 using String
= BasicString
<std::string::value_type
>;
134 // Tag specific containers that guarantee contiguous storage. The standard
135 // provides no such mechanism, so we have to manually specify which are
138 struct IsContiguousTag
: std::false_type
{};
139 template<typename T
, size_t N
>
140 struct IsContiguousTag
<Array
<T
,N
>> : std::true_type
{};
142 struct IsContiguousTag
<Vector
<T
>> : std::true_type
{};
144 struct IsContiguousTag
<BasicString
<T
>> : std::true_type
{};
146 // A rather simple ArrayView container. This allows accepting various array
147 // types (Array, Vector, a static-sized array, a dynamic array + size) without
148 // copying its elements.
152 using value_type
= T
;
153 using iterator
= const value_type
*;
154 using const_iterator
= const value_type
*;
157 const value_type
*mElems
;
161 ArrayView() noexcept
: mElems(nullptr), mNumElems(0) { }
162 ArrayView(const ArrayView
&) noexcept
= default;
163 ArrayView(ArrayView
&&) noexcept
= default;
164 ArrayView(const value_type
*elems
, size_t num_elems
) noexcept
165 : mElems(elems
), mNumElems(num_elems
) { }
166 template<typename OtherT
> ArrayView(RemoveRefT
<OtherT
>&&) = delete;
167 template<typename OtherT
,
168 typename
= EnableIfT
<IsContiguousTag
<RemoveRefT
<OtherT
>>::value
>>
169 ArrayView(const OtherT
&rhs
) noexcept
: mElems(rhs
.data()), mNumElems(rhs
.size()) { }
171 ArrayView(const value_type (&elems
)[N
]) noexcept
: mElems(elems
), mNumElems(N
) { }
173 ArrayView
& operator=(const ArrayView
&) noexcept
= default;
175 const value_type
*data() const noexcept
{ return mElems
; }
177 size_t size() const noexcept
{ return mNumElems
; }
178 bool empty() const noexcept
{ return mNumElems
== 0; }
180 const value_type
& operator[](size_t i
) const { return mElems
[i
]; }
182 const value_type
& front() const { return mElems
[0]; }
183 const value_type
& back() const { return mElems
[mNumElems
-1]; }
185 const value_type
& at(size_t i
) const
188 throw std::out_of_range("alure::ArrayView::at: element out of range");
192 const_iterator
begin() const noexcept
{ return mElems
; }
193 const_iterator
cbegin() const noexcept
{ return mElems
; }
195 const_iterator
end() const noexcept
{ return mElems
+ mNumElems
; }
196 const_iterator
cend() const noexcept
{ return mElems
+ mNumElems
; }
200 class BasicStringView
: public ArrayView
<T
> {
201 using BaseT
= ArrayView
<T
>;
202 using StringT
= BasicString
<T
>;
205 using typename
BaseT::value_type
;
207 BasicStringView() noexcept
= default;
208 BasicStringView(const BasicStringView
&) noexcept
= default;
209 BasicStringView(const value_type
*elems
, size_t num_elems
) noexcept
210 : ArrayView
<T
>(elems
, num_elems
) { }
211 BasicStringView(const value_type
*elems
) : ArrayView
<T
>(elems
, std::strlen(elems
)) { }
212 BasicStringView(StringT
&&) = delete;
213 BasicStringView(const StringT
&rhs
) noexcept
: ArrayView
<T
>(rhs
) { }
214 #if __cplusplus >= 201703L
215 BasicStringView(const std::basic_string_view
<T
> &rhs
) noexcept
216 : ArrayView
<T
>(rhs
.data(), rhs
.length()) { }
219 BasicStringView
& operator=(const BasicStringView
&) noexcept
= default;
221 size_t length() const { return BaseT::size(); }
223 explicit operator StringT() const { return StringT(BaseT::data(), length()); }
224 #if __cplusplus >= 201703L
225 operator std::basic_string_view
<T
>() const
226 { return std::basic_string_view
<T
>(BaseT::data(), length()); }
229 StringT
operator+(const StringT
&rhs
) const
231 StringT ret
= StringT(*this);
235 StringT
operator+(const typename
StringT::value_type
*rhs
) const
237 StringT ret
= StringT(*this);
242 using StringView
= BasicStringView
<String::value_type
>;
244 // Inline operators to concat String and C-style strings with StringViews.
246 inline BasicString
<T
> operator+(const BasicString
<T
> &lhs
, const BasicStringView
<T
> &rhs
)
247 { return BasicString
<T
>(lhs
).append(rhs
.data(), rhs
.size()); }
249 inline BasicString
<T
> operator+(BasicString
<T
>&& lhs
, const BasicStringView
<T
> &rhs
)
250 { return std::move(lhs
.append(rhs
.data(), rhs
.size())); }
252 inline BasicString
<T
> operator+(const typename BasicString
<T
>::value_type
*lhs
, const BasicStringView
<T
> &rhs
)
253 { return lhs
+ BasicString
<T
>(rhs
); }
255 inline BasicString
<T
>& operator+=(BasicString
<T
> &lhs
, const BasicStringView
<T
> &rhs
)
256 { return lhs
.append(rhs
.data(), rhs
.size()); }
257 // Inline operator to write out a StringView to an ostream
259 inline std::basic_ostream
<T
>& operator<<(std::basic_ostream
<T
> &lhs
, const BasicStringView
<T
> &rhs
)
268 * An attribute pair, for passing attributes to Device::createContext and
271 using AttributePair
= std::pair
<ALCint
,ALCint
>;
272 static_assert(sizeof(AttributePair
) == sizeof(ALCint
[2]), "Bad AttributePair size");
275 struct FilterParams
{
277 ALfloat mGainHF
; // For low-pass and band-pass filters
278 ALfloat mGainLF
; // For high-pass and band-pass filters
282 class ALURE_API Vector3
{
283 Array
<ALfloat
,3> mValue
;
286 constexpr Vector3() noexcept
287 : mValue
{{0.0f
, 0.0f
, 0.0f
}}
289 constexpr Vector3(const Vector3
&rhs
) noexcept
290 : mValue
{{rhs
.mValue
[0], rhs
.mValue
[1], rhs
.mValue
[2]}}
292 constexpr Vector3(ALfloat val
) noexcept
293 : mValue
{{val
, val
, val
}}
295 constexpr Vector3(ALfloat x
, ALfloat y
, ALfloat z
) noexcept
298 Vector3(const ALfloat
*vec
) noexcept
299 : mValue
{{vec
[0], vec
[1], vec
[2]}}
302 const ALfloat
*getPtr() const noexcept
303 { return mValue
.data(); }
305 ALfloat
& operator[](size_t i
) noexcept
306 { return mValue
[i
]; }
307 constexpr const ALfloat
& operator[](size_t i
) const noexcept
308 { return mValue
[i
]; }
310 #define ALURE_DECL_OP(op) \
311 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
313 return Vector3(mValue[0] op rhs.mValue[0], \
314 mValue[1] op rhs.mValue[1], \
315 mValue[2] op rhs.mValue[2]); \
322 #define ALURE_DECL_OP(op) \
323 Vector3& operator op(const Vector3 &rhs) noexcept \
325 mValue[0] op rhs.mValue[0]; \
326 mValue[1] op rhs.mValue[1]; \
327 mValue[2] op rhs.mValue[2]; \
336 #define ALURE_DECL_OP(op) \
337 constexpr Vector3 operator op(ALfloat scale) const noexcept \
339 return Vector3(mValue[0] op scale, \
340 mValue[1] op scale, \
341 mValue[2] op scale); \
346 #define ALURE_DECL_OP(op) \
347 Vector3& operator op(ALfloat scale) noexcept \
349 mValue[0] op scale; \
350 mValue[1] op scale; \
351 mValue[2] op scale; \
358 constexpr ALfloat
getLengthSquared() const noexcept
359 { return mValue
[0]*mValue
[0] + mValue
[1]*mValue
[1] + mValue
[2]*mValue
[2]; }
360 ALfloat
getLength() const noexcept
361 { return std::sqrt(getLengthSquared()); }
363 constexpr ALfloat
getDistanceSquared(const Vector3
&pos
) const noexcept
364 { return (pos
- *this).getLengthSquared(); }
365 ALfloat
getDistance(const Vector3
&pos
) const noexcept
366 { return (pos
- *this).getLength(); }
368 static_assert(sizeof(Vector3
) == sizeof(ALfloat
[3]), "Bad Vector3 size");
371 enum class SampleType
{
377 ALURE_API
const char *GetSampleTypeName(SampleType type
);
379 enum class ChannelConfig
{
380 /** 1-channel mono sound. */
382 /** 2-channel stereo sound. */
384 /** 2-channel rear sound (back-left and back-right). */
386 /** 4-channel surround sound. */
388 /** 5.1 surround sound. */
390 /** 6.1 surround sound. */
392 /** 7.1 surround sound. */
394 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
396 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
399 ALURE_API
const char *GetChannelConfigName(ChannelConfig cfg
);
401 ALURE_API ALuint
FramesToBytes(ALuint frames
, ChannelConfig chans
, SampleType type
);
402 ALURE_API ALuint
BytesToFrames(ALuint bytes
, ChannelConfig chans
, SampleType type
);
405 /** Class for storing a major.minor version number. */
411 constexpr Version(ALuint _maj
, ALuint _min
) : mMajor(_maj
), mMinor(_min
) { }
413 constexpr ALuint
getMajor() const noexcept
{ return mMajor
; }
414 constexpr ALuint
getMinor() const noexcept
{ return mMinor
; }
415 constexpr bool isZero() const noexcept
{ return mMajor
== 0 && mMinor
== 0; }
418 #define MAKE_PIMPL(BaseT, ImplT) \
423 using handle_type = ImplT*; \
425 BaseT() : pImpl(nullptr) { } \
426 BaseT(ImplT *impl) : pImpl(impl) { } \
427 BaseT(const BaseT&) = default; \
428 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
430 BaseT& operator=(const BaseT&) = default; \
431 BaseT& operator=(BaseT&& rhs) \
433 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
437 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
438 bool operator==(BaseT&& rhs) const { return pImpl == rhs.pImpl; } \
440 operator bool() const { return !!pImpl; } \
442 handle_type getHandle() const { return pImpl; }
444 enum class DeviceEnumeration
{
445 Basic
= ALC_DEVICE_SPECIFIER
,
446 Full
= ALC_ALL_DEVICES_SPECIFIER
,
447 Capture
= ALC_CAPTURE_DEVICE_SPECIFIER
450 enum class DefaultDeviceType
{
451 Basic
= ALC_DEFAULT_DEVICE_SPECIFIER
,
452 Full
= ALC_DEFAULT_ALL_DEVICES_SPECIFIER
,
453 Capture
= ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
457 * A class managing Device objects and other related functionality. This class
458 * is a singleton, only one instance will exist in a process.
460 class ALURE_API DeviceManager
{
461 DeviceManagerImpl
*pImpl
;
463 DeviceManager(DeviceManagerImpl
*impl
) : pImpl(impl
) { }
464 friend class ALDeviceManager
;
467 DeviceManager(const DeviceManager
&) = default;
468 DeviceManager(DeviceManager
&& rhs
) : pImpl(rhs
.pImpl
) { }
470 /** Retrieves the DeviceManager instance. */
471 static DeviceManager
get();
473 /** Queries the existence of a non-device-specific ALC extension. */
474 bool queryExtension(StringView name
) const;
475 bool queryExtension(const char *name
) const;
477 /** Enumerates available device names of the given type. */
478 Vector
<String
> enumerate(DeviceEnumeration type
) const;
479 /** Retrieves the default device of the given type. */
480 String
defaultDeviceName(DefaultDeviceType type
) const;
483 * Opens the playback device given by name, or the default if blank. Throws
484 * an exception on error.
486 Device
openPlayback(StringView name
=StringView());
487 Device
openPlayback(const char *name
);
490 * Opens the playback device given by name, or the default if blank.
491 * Returns an empty Device on error.
493 Device
openPlayback(StringView name
, const std::nothrow_t
&);
494 Device
openPlayback(const char *name
, const std::nothrow_t
&);
496 /** Opens the default playback device. Returns an empty Device on error. */
497 Device
openPlayback(const std::nothrow_t
&);
501 enum class PlaybackName
{
502 Basic
= ALC_DEVICE_SPECIFIER
,
503 Full
= ALC_ALL_DEVICES_SPECIFIER
506 class ALURE_API Device
{
507 MAKE_PIMPL(Device
, DeviceImpl
)
510 /** Retrieves the device name as given by type. */
511 String
getName(PlaybackName type
=PlaybackName::Full
) const;
512 /** Queries the existence of an ALC extension on this device. */
513 bool queryExtension(StringView name
) const;
514 bool queryExtension(const char *name
) const;
516 /** Retrieves the ALC version supported by this device. */
517 Version
getALCVersion() const;
520 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
521 * extension is unsupported, this will be 0.0.
523 Version
getEFXVersion() const;
525 /** Retrieves the device's playback frequency, in hz. */
526 ALCuint
getFrequency() const;
529 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
530 * is unsupported, this will be 0.
532 ALCuint
getMaxAuxiliarySends() const;
535 * Enumerates available HRTF names. The names are sorted as OpenAL gives
536 * them, such that the index of a given name is the ID to use with
539 * Requires the ALC_SOFT_HRTF extension.
541 Vector
<String
> enumerateHRTFNames() const;
544 * Retrieves whether HRTF is enabled on the device or not.
546 * Requires the ALC_SOFT_HRTF extension.
548 bool isHRTFEnabled() const;
551 * Retrieves the name of the HRTF currently being used by this device.
553 * Requires the ALC_SOFT_HRTF extension.
555 String
getCurrentHRTF() const;
558 * Resets the device, using the specified attributes.
560 * Requires the ALC_SOFT_HRTF extension.
562 void reset(ArrayView
<AttributePair
> attributes
);
565 * Creates a new Context on this device, using the specified attributes.
567 Context
createContext(ArrayView
<AttributePair
> attributes
=ArrayView
<AttributePair
>());
570 * Pauses device processing, stopping updates for its contexts. Multiple
571 * calls are allowed but it is not reference counted, so the device will
572 * resume after one resumeDSP call.
574 * Requires the ALC_SOFT_pause_device extension.
579 * Resumes device processing, restarting updates for its contexts. Multiple
580 * calls are allowed and will no-op.
585 * Closes and frees the device. All previously-created contexts must first
592 enum class DistanceModel
{
593 InverseClamped
= AL_INVERSE_DISTANCE_CLAMPED
,
594 LinearClamped
= AL_LINEAR_DISTANCE_CLAMPED
,
595 ExponentClamped
= AL_EXPONENT_DISTANCE_CLAMPED
,
596 Inverse
= AL_INVERSE_DISTANCE
,
597 Linear
= AL_LINEAR_DISTANCE
,
598 Exponent
= AL_EXPONENT_DISTANCE
,
602 class ALURE_API Context
{
603 MAKE_PIMPL(Context
, ContextImpl
)
606 /** Makes the specified context current for OpenAL operations. */
607 static void MakeCurrent(Context context
);
608 /** Retrieves the current context used for OpenAL operations. */
609 static Context
GetCurrent();
612 * Makes the specified context current for OpenAL operations on the calling
613 * thread only. Requires the ALC_EXT_thread_local_context extension on both
614 * the context's device and the DeviceManager.
616 static void MakeThreadCurrent(Context context
);
617 /** Retrieves the thread-specific context used for OpenAL operations. */
618 static Context
GetThreadCurrent();
621 * Destroys the context. The context must not be current when this is
626 /** Retrieves the Device this context was created from. */
633 * Retrieves a Listener instance for this context. Each context will only
634 * have one listener, which is automatically destroyed with the context.
636 Listener
getListener();
639 * Sets a MessageHandler instance which will be used to provide certain
640 * messages back to the application. Only one handler may be set for a
641 * context at a time. The previously set handler will be returned.
643 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
645 /** Gets the currently-set message handler. */
646 SharedPtr
<MessageHandler
> getMessageHandler() const;
649 * Specifies the desired interval that the background thread will be woken
650 * up to process tasks, e.g. keeping streaming sources filled. An interval
651 * of 0 means the background thread will only be woken up manually with
652 * calls to update. The default is 0.
654 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
657 * Retrieves the current interval used for waking up the background thread.
659 std::chrono::milliseconds
getAsyncWakeInterval() const;
661 // Functions below require the context to be current
664 * Creates a Decoder instance for the given audio file or resource name.
666 SharedPtr
<Decoder
> createDecoder(const String
&name
);
669 * Queries if the channel configuration and sample type are supported by
672 bool isSupported(ChannelConfig channels
, SampleType type
) const;
675 * Queries the list of resamplers supported by the context. If the
676 * AL_SOFT_source_resampler extension is unsupported this will be an empty
677 * array, otherwise there will be at least one entry.
679 ArrayView
<String
> getAvailableResamplers();
681 * Queries the context's default resampler index. Be aware, if the
682 * AL_SOFT_source_resampler extension is unsupported the resampler list
683 * will be empty and this will resturn 0. If you try to access the
684 * resampler list with this index without the extension, undefined behavior
685 * will occur (accessing an out of bounds array index).
687 ALsizei
getDefaultResamplerIndex() const;
690 * Creates and caches a Buffer for the given audio file or resource name.
691 * Multiple calls with the same name will return the same Buffer object.
692 * Cached buffers must be freed using removeBuffer before destroying the
693 * context. If the buffer can't be loaded it will throw an exception.
695 Buffer
getBuffer(const String
&name
);
698 * Asynchronously prepares a cached Buffer for the given audio file or
699 * resource name. Multiple calls with the same name will return multiple
700 * shared futures for the same Buffer object. Once called, the buffer must
701 * be freed using removeBuffer before destroying the context, even if you
702 * never get the Buffer from the shared_future.
704 * The Buffer will be loaded asynchronously, and the caller gets back a
705 * shared_future immediately that can be checked later (or waited on) to
706 * get the actual Buffer when it's ready. The application must take care to
707 * handle exceptions from the shared_future in case of an unrecoverable
708 * error during the load.
710 std::shared_future
<Buffer
> getBufferAsync(const String
&name
);
713 * Asynchronously prepares cached Buffers for the given audio file or
714 * resource names. Duplicate names and buffers already cached are ignored.
715 * Cached buffers must be freed using removeBuffer before destroying the
718 * The Buffer objects will be scheduled for loading asynchronously, and
719 * should be retrieved later when needed using getBufferAsync or getBuffer.
720 * Buffers that cannot be loaded, for example due to an unsupported format,
721 * will be ignored and a later call to getBuffer or getBufferAsync will
722 * throw an exception.
724 * Note that you should avoid trying to asynchronously cache more than 16
725 * buffers at a time. The internal ringbuffer used to communicate with the
726 * background thread can only hold 16 async load requests, and trying to
727 * add more will cause the call to stall until the background thread
728 * completes some loads for more to be filled in.
730 void precacheBuffersAsync(ArrayView
<String
> names
);
733 * Creates and caches a Buffer using the given name. The name may alias an
734 * audio file, but it must not currently exist in the buffer cache.
736 Buffer
createBufferFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
739 * Asynchronously prepares a cached Buffer using the given name. The name
740 * may alias an audio file, but it must not currently exist in the buffer
741 * cache. Once called, the buffer must be freed using removeBuffer before
742 * destroying the context, even if you never get the Buffer from the
745 * The Buffer will be loaded asynchronously using the given decoder, and
746 * the caller gets back a shared_future immediately that can be checked
747 * later (or waited on) to get the actual Buffer when it's ready. The
748 * application must take care to handle exceptions from the shared_future
749 * in case of an unrecoverable error during the load. The decoder must not
750 * have its read or seek methods called while the buffer is not ready.
752 std::shared_future
<Buffer
> createBufferAsyncFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
755 * Deletes the cached Buffer object for the given audio file or
756 * resource name. The buffer must not be in use by a Source.
758 void removeBuffer(const String
&name
);
760 * Deletes the given cached buffer. The buffer must not be in use by a
763 void removeBuffer(Buffer buffer
);
766 * Creates a new Source. There is no practical limit to the number of
767 * sources you may create. You must call Source::release when the source is
770 Source
createSource();
772 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
774 Effect
createEffect();
776 SourceGroup
createSourceGroup(String name
);
777 SourceGroup
getSourceGroup(const String
&name
);
779 /** Sets the doppler factor to apply to all source calculations. */
780 void setDopplerFactor(ALfloat factor
);
783 * Sets the speed of sound propagation, in units per second, to calculate
784 * the doppler effect along with other distance-related time effects. The
785 * default is 343.3 units per second (a realistic speed assuming 1 meter
786 * per unit). If this is adjusted for a different unit scale,
787 * Listener::setMetersPerUnit should also be adjusted.
789 void setSpeedOfSound(ALfloat speed
);
791 void setDistanceModel(DistanceModel model
);
793 /** Updates the context and all sources belonging to this context. */
797 class ALURE_API Listener
{
798 MAKE_PIMPL(Listener
, ListenerImpl
)
801 /** Sets the "master" gain for all context output. */
802 void setGain(ALfloat gain
);
805 * Specifies the listener's 3D position, velocity, and orientation
808 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
810 /** Specifies the listener's 3D position. */
811 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
812 void setPosition(const ALfloat
*pos
);
815 * Specifies the listener's 3D velocity, in units per second. As with
816 * OpenAL, this does not actually alter the listener's position, and
817 * instead just alters the pitch as determined by the doppler effect.
819 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
820 void setVelocity(const ALfloat
*vel
);
823 * Specifies the listener's 3D orientation, using position-relative 'at'
824 * and 'up' direction vectors.
826 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
827 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
828 void setOrientation(const ALfloat
*ori
);
831 * Sets the number of meters per unit, used for various effects that rely
832 * on the distance in meters (including air absorption and initial reverb
833 * decay). If this is changed, it's strongly recommended to also set the
834 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
835 * realistic 343.3m/s for sound propagation).
837 void setMetersPerUnit(ALfloat m_u
);
841 class ALURE_API Buffer
{
842 MAKE_PIMPL(Buffer
, BufferImpl
)
845 /** Retrieves the length of the buffer in sample frames. */
846 ALuint
getLength() const;
848 /** Retrieves the buffer's frequency in hz. */
849 ALuint
getFrequency() const;
851 /** Retrieves the buffer's sample configuration. */
852 ChannelConfig
getChannelConfig() const;
854 /** Retrieves the buffer's sample type. */
855 SampleType
getSampleType() const;
857 /** Retrieves the storage size used by the buffer, in bytes. */
858 ALuint
getSize() const;
861 * Sets the buffer's loop points, used for looping sources. If the current
862 * context does not support the AL_SOFT_loop_points extension, start and
863 * end must be 0 and getLength() respectively. Otherwise, start must be
864 * less than end, and end must be less than or equal to getLength().
866 * The buffer must not be in use when this method is called.
868 * \param start The starting point, in sample frames (inclusive).
869 * \param end The ending point, in sample frames (exclusive).
871 void setLoopPoints(ALuint start
, ALuint end
);
873 /** Retrieves the current loop points as a [start,end) pair. */
874 std::pair
<ALuint
,ALuint
> getLoopPoints() const;
877 * Retrieves the Source objects currently playing the buffer. Stopping the
878 * returned sources will allow the buffer to be removed from the context.
880 Vector
<Source
> getSources() const;
882 /** Retrieves the name the buffer was created with. */
883 const String
&getName() const;
885 /** Queries if the buffer is in use and can't be removed. */
886 bool isInUse() const;
890 enum class Spatialize
{
893 Auto
= 0x0002 /* AL_AUTO_SOFT */
896 class ALURE_API Source
{
897 MAKE_PIMPL(Source
, SourceImpl
)
901 * Plays the source using buffer. The same buffer may be played from
902 * multiple sources simultaneously.
904 void play(Buffer buffer
);
906 * Plays the source by streaming audio from decoder. This will use
907 * queuesize buffers, each with updatelen sample frames. The given decoder
908 * must *NOT* have its read or seek methods called from elsewhere while in
911 void play(SharedPtr
<Decoder
> decoder
, ALuint updatelen
, ALuint queuesize
);
913 * Stops playback, releasing the buffer or decoder reference.
917 /** Pauses the source if it is playing. */
920 /** Resumes the source if it is paused. */
923 /** Specifies if the source is currently playing. */
924 bool isPlaying() const;
926 /** Specifies if the source is currently paused. */
927 bool isPaused() const;
930 * Specifies the source's playback priority. Lowest priority sources will
931 * be evicted first when higher priority sources are played.
933 void setPriority(ALuint priority
);
934 /** Retrieves the source's priority. */
935 ALuint
getPriority() const;
938 * Sets the source's offset, in sample frames. If the source is playing or
939 * paused, it will go to that offset immediately, otherwise the source will
940 * start at the specified offset the next time it's played.
942 void setOffset(uint64_t offset
);
944 * Retrieves the source offset in sample frames and its latency in nano-
945 * seconds. For streaming sources this will be the offset based on the
946 * decoder's read position.
948 * If the AL_SOFT_source_latency extension is unsupported, the latency will
951 std::pair
<uint64_t,std::chrono::nanoseconds
> getSampleOffsetLatency() const;
952 uint64_t getSampleOffset() const { return std::get
<0>(getSampleOffsetLatency()); }
954 * Retrieves the source offset and latency in seconds. For streaming
955 * sources this will be the offset based on the decoder's read position.
957 * If the AL_SOFT_source_latency extension is unsupported, the latency will
960 std::pair
<Seconds
,Seconds
> getSecOffsetLatency() const;
961 Seconds
getSecOffset() const { return std::get
<0>(getSecOffsetLatency()); }
964 * Specifies if the source should loop on the Buffer or Decoder object's
967 void setLooping(bool looping
);
968 bool getLooping() const;
971 * Specifies a linear pitch shift base. A value of 1.0 is the default
974 void setPitch(ALfloat pitch
);
975 ALfloat
getPitch() const;
978 * Specifies the base linear gain. A value of 1.0 is the default normal
981 void setGain(ALfloat gain
);
982 ALfloat
getGain() const;
985 * Specifies the minimum and maximum gain. The source's gain is clamped to
986 * this range after distance attenuation and cone attenuation are applied
987 * to the gain base, although before the filter gain adjustements.
989 void setGainRange(ALfloat mingain
, ALfloat maxgain
);
990 std::pair
<ALfloat
,ALfloat
> getGainRange() const;
991 ALfloat
getMinGain() const { return std::get
<0>(getGainRange()); }
992 ALfloat
getMaxGain() const { return std::get
<1>(getGainRange()); }
995 * Specifies the reference distance and maximum distance the source will
996 * use for the current distance model. For Clamped distance models, the
997 * source's calculated distance is clamped to the specified range before
998 * applying distance-related attenuation.
1000 * For all distance models, the reference distance is the distance at which
1001 * the source's volume will not have any extra attenuation (an effective
1002 * gain multiplier of 1).
1004 void setDistanceRange(ALfloat refdist
, ALfloat maxdist
);
1005 std::pair
<ALfloat
,ALfloat
> getDistanceRange() const;
1006 ALfloat
getReferenceDistance() const { return std::get
<0>(getDistanceRange()); }
1007 ALfloat
getMaxDistance() const { return std::get
<1>(getDistanceRange()); }
1009 /** Specifies the source's 3D position, velocity, and direction together. */
1010 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const Vector3
&direction
);
1012 /** Specifies the source's 3D position, velocity, and orientation together. */
1013 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
1015 /** Specifies the source's 3D position. */
1016 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
1017 void setPosition(const ALfloat
*pos
);
1018 Vector3
getPosition() const;
1021 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
1022 * this does not actually alter the source's position, and instead just
1023 * alters the pitch as determined by the doppler effect.
1025 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
1026 void setVelocity(const ALfloat
*vel
);
1027 Vector3
getVelocity() const;
1030 * Specifies the source's 3D facing direction. Deprecated in favor of
1033 void setDirection(ALfloat x
, ALfloat y
, ALfloat z
);
1034 void setDirection(const ALfloat
*dir
);
1035 Vector3
getDirection() const;
1038 * Specifies the source's 3D orientation. Note: unlike the AL_EXT_BFORMAT
1039 * extension this property comes from, this also affects the facing
1040 * direction, superceding setDirection.
1042 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
1043 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
1044 void setOrientation(const ALfloat
*ori
);
1045 std::pair
<Vector3
,Vector3
> getOrientation() const;
1048 * Specifies the source's cone angles, in degrees. The inner angle is the
1049 * area within which the listener will hear the source with no extra
1050 * attenuation, while the listener being outside of the outer angle will
1051 * hear the source attenuated according to the outer cone gains.
1053 void setConeAngles(ALfloat inner
, ALfloat outer
);
1054 std::pair
<ALfloat
,ALfloat
> getConeAngles() const;
1055 ALfloat
getInnerConeAngle() const { return std::get
<0>(getConeAngles()); }
1056 ALfloat
getOuterConeAngle() const { return std::get
<1>(getConeAngles()); }
1059 * Specifies the linear gain multiplier when the listener is outside of the
1060 * source's outer cone area. The specified gain applies to all frequencies,
1061 * while gainhf applies extra attenuation to high frequencies.
1063 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1065 void setOuterConeGains(ALfloat gain
, ALfloat gainhf
=1.0f
);
1066 std::pair
<ALfloat
,ALfloat
> getOuterConeGains() const;
1067 ALfloat
getOuterConeGain() const { return std::get
<0>(getOuterConeGains()); }
1068 ALfloat
getOuterConeGainHF() const { return std::get
<1>(getOuterConeGains()); }
1071 * Specifies the rolloff factors for the direct and send paths. This is
1072 * effectively a distance scaling relative to the reference distance. Note:
1073 * the room rolloff factor is 0 by default, disabling distance attenuation
1074 * for send paths. This is because the reverb engine will, by default,
1075 * apply a more realistic room decay based on the reverb decay time and
1078 void setRolloffFactors(ALfloat factor
, ALfloat roomfactor
=0.0f
);
1079 std::pair
<ALfloat
,ALfloat
> getRolloffFactors() const;
1080 ALfloat
getRolloffFactor() const { return std::get
<0>(getRolloffFactors()); }
1081 ALfloat
getRoomRolloffFactor() const { return std::get
<1>(getRolloffFactors()); }
1084 * Specifies the doppler factor for the doppler effect's pitch shift. This
1085 * effectively scales the source and listener velocities for the doppler
1088 void setDopplerFactor(ALfloat factor
);
1089 ALfloat
getDopplerFactor() const;
1092 * Specifies if the source's position, velocity, and direction/orientation
1093 * are relative to the listener.
1095 void setRelative(bool relative
);
1096 bool getRelative() const;
1099 * Specifies the source's radius. This causes the source to behave as if
1100 * every point within the spherical area emits sound.
1102 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1104 void setRadius(ALfloat radius
);
1105 ALfloat
getRadius() const;
1108 * Specifies the left and right channel angles, in radians, when playing a
1109 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1110 * in front and positive values going left.
1112 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1114 void setStereoAngles(ALfloat leftAngle
, ALfloat rightAngle
);
1115 std::pair
<ALfloat
,ALfloat
> getStereoAngles() const;
1118 * Specifies if the source always has 3D spatialization features (On),
1119 * never has 3D spatialization features (Off), or if spatialization is
1120 * enabled based on playing a mono sound or not (Auto, default). Has no
1121 * effect without the AL_SOFT_source_spatialize extension.
1123 void set3DSpatialize(Spatialize spatialize
);
1124 Spatialize
get3DSpatialize() const;
1126 void setResamplerIndex(ALsizei index
);
1127 ALsizei
getResamplerIndex() const;
1130 * Specifies a multiplier for the amount of atmospheric high-frequency
1131 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1132 * -0.05dB per meter, with higher values simulating foggy air and lower
1133 * values simulating dryer air. The default is 0.
1135 void setAirAbsorptionFactor(ALfloat factor
);
1136 ALfloat
getAirAbsorptionFactor() const;
1138 void setGainAuto(bool directhf
, bool send
, bool sendhf
);
1139 std::tuple
<bool,bool,bool> getGainAuto() const;
1140 bool getDirectGainHFAuto() const { return std::get
<0>(getGainAuto()); }
1141 bool getSendGainAuto() const { return std::get
<1>(getGainAuto()); }
1142 bool getSendGainHFAuto() const { return std::get
<2>(getGainAuto()); }
1144 /** Sets the filter properties on the direct path signal. */
1145 void setDirectFilter(const FilterParams
&filter
);
1147 * Sets the filter properties on the given send path signal. Any auxiliary
1148 * effect slot on the send path remains in place.
1150 void setSendFilter(ALuint send
, const FilterParams
&filter
);
1152 * Connects the effect slot to the given send path. Any filter properties
1153 * on the send path remain as they were.
1155 void setAuxiliarySend(AuxiliaryEffectSlot slot
, ALuint send
);
1157 * Connects the effect slot to the given send path, using the filter
1160 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot
, ALuint send
, const FilterParams
&filter
);
1163 * Releases the source, stopping playback, releasing resources, and
1164 * returning it to the system.
1170 class ALURE_API SourceGroup
{
1171 MAKE_PIMPL(SourceGroup
, SourceGroupImpl
)
1174 /** Retrieves the associated name of the source group. */
1175 const String
&getName() const;
1178 * Adds source to the source group. A source may only be part of one group
1179 * at a time, and will automatically be removed from its current group as
1182 void addSource(Source source
);
1183 /** Removes source from the source group. */
1184 void removeSource(Source source
);
1186 /** Adds a list of sources to the group at once. */
1187 void addSources(ArrayView
<Source
> sources
);
1188 /** Removes a list of sources from the source group. */
1189 void removeSources(ArrayView
<Source
> sources
);
1192 * Adds group as a subgroup of the source group. This method will throw an
1193 * exception if group is being added to a group it has as a sub-group (i.e.
1194 * it would create a circular sub-group chain).
1196 void addSubGroup(SourceGroup group
);
1197 /** Removes group from the source group. */
1198 void removeSubGroup(SourceGroup group
);
1200 /** Returns the list of sources currently in the group. */
1201 Vector
<Source
> getSources() const;
1203 /** Returns the list of subgroups currently in the group. */
1204 Vector
<SourceGroup
> getSubGroups() const;
1206 /** Sets the source group gain, which accumulates with its sources. */
1207 void setGain(ALfloat gain
);
1208 /** Gets the source group gain. */
1209 ALfloat
getGain() const;
1211 /** Sets the source group pitch, which accumulates with its sources. */
1212 void setPitch(ALfloat pitch
);
1213 /** Gets the source group pitch. */
1214 ALfloat
getPitch() const;
1217 * Pauses all currently-playing sources that are under this group,
1218 * including sub-groups.
1220 void pauseAll() const;
1222 * Resumes all paused sources that are under this group, including
1225 void resumeAll() const;
1227 /** Stops all sources that are under this group, including sub-groups. */
1228 void stopAll() const;
1231 * Releases the source group, removing all sources from it before being
1243 class ALURE_API AuxiliaryEffectSlot
{
1244 MAKE_PIMPL(AuxiliaryEffectSlot
, AuxiliaryEffectSlotImpl
)
1247 void setGain(ALfloat gain
);
1249 * If set to true, the reverb effect will automatically apply adjustments
1250 * to the source's send slot gains based on the effect properties.
1252 * Has no effect when using non-reverb effects. Default is true.
1254 void setSendAuto(bool sendauto
);
1257 * Updates the effect slot with a new effect. The given effect object may
1258 * be altered or destroyed without affecting the effect slot.
1260 void applyEffect(Effect effect
);
1263 * Releases the effect slot, returning it to the system. It must not be in
1269 * Retrieves each Source object and its pairing send this effect slot is
1270 * set on. Setting a different (or null) effect slot on each source's given
1271 * send will allow the effect slot to be released.
1273 Vector
<SourceSend
> getSourceSends() const;
1275 /** Determines if the effect slot is in use by a source. */
1276 bool isInUse() const;
1280 class ALURE_API Effect
{
1281 MAKE_PIMPL(Effect
, EffectImpl
)
1285 * Updates the effect with the specified reverb properties. If the
1286 * EAXReverb effect is not supported, it will automatically attempt to
1287 * downgrade to the Standard Reverb effect.
1289 void setReverbProperties(const EFXEAXREVERBPROPERTIES
&props
);
1296 * Audio decoder interface. Applications may derive from this, implementing the
1297 * necessary methods, and use it in places the API wants a Decoder object.
1299 class ALURE_API Decoder
{
1303 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1304 virtual ALuint
getFrequency() const = 0;
1305 /** Retrieves the channel configuration of the audio being decoded. */
1306 virtual ChannelConfig
getChannelConfig() const = 0;
1307 /** Retrieves the sample type of the audio being decoded. */
1308 virtual SampleType
getSampleType() const = 0;
1311 * Retrieves the total length of the audio, in sample frames. If unknown,
1312 * returns 0. Note that if the returned length is 0, the decoder may not be
1313 * used to load a Buffer.
1315 virtual uint64_t getLength() const = 0;
1317 * Seek to pos, specified in sample frames. Returns true if the seek was
1320 virtual bool seek(uint64_t pos
) = 0;
1323 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1324 * start >= end, use all available data.
1326 virtual std::pair
<uint64_t,uint64_t> getLoopPoints() const = 0;
1329 * Decodes count sample frames, writing them to ptr, and returns the number
1330 * of sample frames written. Returning less than the requested count
1331 * indicates the end of the audio.
1333 virtual ALuint
read(ALvoid
*ptr
, ALuint count
) = 0;
1337 * Audio decoder factory interface. Applications may derive from this,
1338 * implementing the necessary methods, and use it in places the API wants a
1339 * DecoderFactory object.
1341 class ALURE_API DecoderFactory
{
1343 virtual ~DecoderFactory();
1346 * Creates and returns a Decoder instance for the given resource file. If
1347 * the decoder needs to retain the file handle for reading as-needed, it
1348 * should move the UniquePtr to internal storage.
1350 * \return nullptr if a decoder can't be created from the file.
1352 virtual SharedPtr
<Decoder
> createDecoder(UniquePtr
<std::istream
> &file
) = 0;
1356 * Registers a decoder factory for decoding audio. Registered factories are
1357 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1358 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1359 * name1 < name2. Internal decoder factories are always used after registered
1362 * Alure retains a reference to the DecoderFactory instance and will release it
1363 * (destructing the object) when the library unloads.
1365 * \param name A unique name identifying this decoder factory.
1366 * \param factory A DecoderFactory instance used to create Decoder instances.
1368 ALURE_API
void RegisterDecoder(const String
&name
, UniquePtr
<DecoderFactory
> factory
);
1371 * Unregisters a decoder factory by name. Alure returns the instance back to
1374 * \param name The unique name identifying a previously-registered decoder
1377 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1378 * decoder factory with the given name doesn't exist.
1380 ALURE_API UniquePtr
<DecoderFactory
> UnregisterDecoder(const String
&name
);
1384 * A file I/O factory interface. Applications may derive from this and set an
1385 * instance to be used by the audio decoders. By default, the library uses
1388 class ALURE_API FileIOFactory
{
1391 * Sets the factory instance to be used by the audio decoders. If a
1392 * previous factory was set, it's returned to the application. Passing in a
1393 * nullptr reverts to the default.
1395 static UniquePtr
<FileIOFactory
> set(UniquePtr
<FileIOFactory
> factory
);
1398 * Gets the current FileIOFactory instance being used by the audio
1401 static FileIOFactory
&get();
1403 virtual ~FileIOFactory();
1405 /** Opens a read-only binary file for the given name. */
1406 virtual UniquePtr
<std::istream
> openFile(const String
&name
) = 0;
1411 * A message handler interface. Applications may derive from this and set an
1412 * instance on a context to receive messages. The base methods are no-ops, so
1413 * derived classes only need to implement methods for relevant messages.
1415 * It's recommended that applications mark their handler methods using the
1416 * override keyword, to ensure they're properly overriding the base methods in
1419 class ALURE_API MessageHandler
{
1421 virtual ~MessageHandler();
1424 * Called when the given device has been disconnected and is no longer
1425 * usable for output. As per the ALC_EXT_disconnect specification,
1426 * disconnected devices remain valid, however all playing sources are
1427 * automatically stopped, any sources that are attempted to play will
1428 * immediately stop, and new contexts may not be created on the device.
1430 * Note that connection status is checked during Context::update calls, so
1431 * that method must be called regularly to be notified when a device is
1432 * disconnected. This method may not be called if the device lacks support
1433 * for the ALC_EXT_disconnect extension.
1435 virtual void deviceDisconnected(Device device
);
1438 * Called when the given source reaches the end of the buffer or stream.
1440 * Sources that stopped automatically will be detected upon a call to
1443 virtual void sourceStopped(Source source
);
1446 * Called when the given source was forced to stop. This can be because
1447 * either there were no more system sources and a higher-priority source
1448 * preempted it, or it's part of a SourceGroup (or sub-group thereof) that
1449 * had its SourceGroup::stopAll method called.
1451 virtual void sourceForceStopped(Source source
);
1454 * Called when a new buffer is about to be created and loaded. May be
1455 * called asynchronously for buffers being loaded asynchronously.
1457 * \param name The resource name, as passed to Context::getBuffer.
1458 * \param channels Channel configuration of the given audio data.
1459 * \param type Sample type of the given audio data.
1460 * \param samplerate Sample rate of the given audio data.
1461 * \param data The audio data that is about to be fed to the OpenAL buffer.
1463 virtual void bufferLoading(StringView name
, ChannelConfig channels
, SampleType type
, ALuint samplerate
, ArrayView
<ALbyte
> data
);
1466 * Called when a resource isn't found, allowing the app to substitute in a
1467 * different resource. For buffers created with Context::getBuffer or
1468 * Context::getBufferAsync, the original name will still be used for the
1469 * cache map so the app doesn't have to keep track of substituted resource
1472 * This will be called again if the new name isn't found.
1474 * \param name The resource name that was not found.
1475 * \return The replacement resource name to use instead. Returning an empty
1476 * string means to stop trying.
1478 virtual String
resourceNotFound(StringView name
);
1483 } // namespace alure
1485 #endif /* AL_ALURE2_H */