11 #include "alure2-alext.h"
13 #include "alure2-aliases.h"
14 #include "alure2-typeviews.h"
17 #ifndef ALURE_STATIC_LIB
19 #define ALURE_API __declspec(dllimport)
20 #elif defined(__has_attribute)
21 #if __has_attribute(visibility)
22 #define ALURE_API __attribute__((visibility("default")))
24 #elif defined(__GNUC__)
25 #define ALURE_API __attribute__((visibility("default")))
31 #endif /* ALURE_API */
32 #ifndef ALURE_TEMPLATE
33 #ifndef ALURE_STATIC_LIB
34 #define ALURE_TEMPLATE extern template
36 #define ALURE_TEMPLATE template
38 #endif /* ALURE_TEMPLATE */
40 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
41 #define EFXEAXREVERBPROPERTIES_DEFINED
51 float flReflectionsGain
;
52 float flReflectionsDelay
;
53 float flReflectionsPan
[3];
54 float flLateReverbGain
;
55 float flLateReverbDelay
;
56 float flLateReverbPan
[3];
59 float flModulationTime
;
60 float flModulationDepth
;
61 float flAirAbsorptionGainHF
;
64 float flRoomRolloffFactor
;
66 } EFXEAXREVERBPROPERTIES
, *LPEFXEAXREVERBPROPERTIES
;
69 #ifndef EFXCHORUSPROPERTIES_DEFINED
70 #define EFXCHORUSPROPERTIES_DEFINED
78 } EFXCHORUSPROPERTIES
, *LPEFXCHORUSPROPERTIES
;
83 // Available class interfaces.
91 class AuxiliaryEffectSlot
;
98 // Opaque class implementations.
99 class DeviceManagerImpl
;
105 class SourceGroupImpl
;
106 class AuxiliaryEffectSlotImpl
;
111 #ifndef ALURE_STATIC_LIB
112 /****** Explicitly instantiate templates used by the lib ******/
113 ALURE_TEMPLATE
class ALURE_API ALURE_SHARED_PTR_TYPE
<alure::DeviceManagerImpl
>;
119 /** Convert a value from decibels to linear gain. */
120 inline float dBToLinear(float value
) { return std::pow(10.0f
, value
/ 20.0f
); }
121 inline double dBToLinear(double value
) { return std::pow(10.0, value
/ 20.0); }
122 inline double dBToLinear(int value
) { return dBToLinear(double(value
)); }
124 /** Convert a value from linear gain to decibels. */
125 inline float LinearTodB(float value
) { return std::log10(value
) * 20.0f
; }
126 inline double LinearTodB(double value
) { return std::log10(value
) * 20.0; }
129 * An attribute pair, for passing attributes to Device::createContext and
132 struct AttributePair
{
136 static_assert(sizeof(AttributePair
) == sizeof(ALCint
[2]), "Bad AttributePair size");
137 inline AttributePair
AttributesEnd() noexcept
{ return AttributePair
{0, 0}; }
140 struct FilterParams
{
142 ALfloat mGainHF
; // For low-pass and band-pass filters
143 ALfloat mGainLF
; // For high-pass and band-pass filters
148 Array
<ALfloat
,3> mValue
;
151 constexpr Vector3() noexcept
152 : mValue
{{0.0f
, 0.0f
, 0.0f
}}
154 constexpr Vector3(const Vector3
&rhs
) noexcept
155 : mValue
{{rhs
.mValue
[0], rhs
.mValue
[1], rhs
.mValue
[2]}}
157 constexpr Vector3(ALfloat val
) noexcept
158 : mValue
{{val
, val
, val
}}
160 constexpr Vector3(ALfloat x
, ALfloat y
, ALfloat z
) noexcept
163 Vector3(const ALfloat
*vec
) noexcept
164 : mValue
{{vec
[0], vec
[1], vec
[2]}}
167 const ALfloat
*getPtr() const noexcept
168 { return mValue
.data(); }
170 ALfloat
& operator[](size_t i
) noexcept
171 { return mValue
[i
]; }
172 constexpr const ALfloat
& operator[](size_t i
) const noexcept
173 { return mValue
[i
]; }
175 #define ALURE_DECL_OP(op) \
176 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
178 return Vector3(mValue[0] op rhs.mValue[0], \
179 mValue[1] op rhs.mValue[1], \
180 mValue[2] op rhs.mValue[2]); \
187 #define ALURE_DECL_OP(op) \
188 Vector3& operator op(const Vector3 &rhs) noexcept \
190 mValue[0] op rhs.mValue[0]; \
191 mValue[1] op rhs.mValue[1]; \
192 mValue[2] op rhs.mValue[2]; \
201 #define ALURE_DECL_OP(op) \
202 constexpr Vector3 operator op(ALfloat scale) const noexcept \
204 return Vector3(mValue[0] op scale, \
205 mValue[1] op scale, \
206 mValue[2] op scale); \
211 #define ALURE_DECL_OP(op) \
212 Vector3& operator op(ALfloat scale) noexcept \
214 mValue[0] op scale; \
215 mValue[1] op scale; \
216 mValue[2] op scale; \
223 constexpr ALfloat
getLengthSquared() const noexcept
224 { return mValue
[0]*mValue
[0] + mValue
[1]*mValue
[1] + mValue
[2]*mValue
[2]; }
225 ALfloat
getLength() const noexcept
226 { return std::sqrt(getLengthSquared()); }
228 constexpr ALfloat
getDistanceSquared(const Vector3
&pos
) const noexcept
229 { return (pos
- *this).getLengthSquared(); }
230 ALfloat
getDistance(const Vector3
&pos
) const noexcept
231 { return (pos
- *this).getLength(); }
233 static_assert(sizeof(Vector3
) == sizeof(ALfloat
[3]), "Bad Vector3 size");
236 enum class SampleType
{
242 ALURE_API
const char *GetSampleTypeName(SampleType type
);
244 enum class ChannelConfig
{
245 /** 1-channel mono sound. */
247 /** 2-channel stereo sound. */
249 /** 2-channel rear sound (back-left and back-right). */
251 /** 4-channel surround sound. */
253 /** 5.1 surround sound. */
255 /** 6.1 surround sound. */
257 /** 7.1 surround sound. */
259 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
261 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
264 ALURE_API
const char *GetChannelConfigName(ChannelConfig cfg
);
266 ALURE_API ALuint
FramesToBytes(ALuint frames
, ChannelConfig chans
, SampleType type
);
267 ALURE_API ALuint
BytesToFrames(ALuint bytes
, ChannelConfig chans
, SampleType type
) noexcept
;
270 /** Class for storing a major.minor version number. */
276 constexpr Version() noexcept
: mMajor(0), mMinor(0) { }
277 constexpr Version(ALuint _maj
, ALuint _min
) noexcept
: mMajor(_maj
), mMinor(_min
) { }
278 constexpr Version(const Version
&) noexcept
= default;
280 constexpr ALuint
getMajor() const noexcept
{ return mMajor
; }
281 constexpr ALuint
getMinor() const noexcept
{ return mMinor
; }
283 constexpr bool operator==(const Version
&rhs
) const noexcept
284 { return mMajor
== rhs
.mMajor
&& mMinor
== rhs
.mMinor
; }
285 constexpr bool operator!=(const Version
&rhs
) const noexcept
286 { return !(*this == rhs
); }
287 constexpr bool operator<=(const Version
&rhs
) const noexcept
288 { return mMajor
< rhs
.mMajor
|| (mMajor
== rhs
.mMajor
&& mMinor
<= rhs
.mMinor
); }
289 constexpr bool operator>=(const Version
&rhs
) const noexcept
290 { return mMajor
> rhs
.mMajor
|| (mMajor
== rhs
.mMajor
&& mMinor
>= rhs
.mMinor
); }
291 constexpr bool operator<(const Version
&rhs
) const noexcept
292 { return mMajor
< rhs
.mMajor
|| (mMajor
== rhs
.mMajor
&& mMinor
< rhs
.mMinor
); }
293 constexpr bool operator>(const Version
&rhs
) const noexcept
294 { return mMajor
> rhs
.mMajor
|| (mMajor
== rhs
.mMajor
&& mMinor
> rhs
.mMinor
); }
296 constexpr bool isZero() const noexcept
{ return *this == Version
{0,0}; }
300 // Tag type to disctate which types are allowed in AutoObj.
301 template<typename T
> struct IsAutoable
: std::false_type
{ };
302 template<> struct IsAutoable
<Device
> : std::true_type
{ };
303 template<> struct IsAutoable
<Context
> : std::true_type
{ };
304 template<> struct IsAutoable
<Source
> : std::true_type
{ };
305 template<> struct IsAutoable
<SourceGroup
> : std::true_type
{ };
306 template<> struct IsAutoable
<AuxiliaryEffectSlot
> : std::true_type
{ };
307 template<> struct IsAutoable
<Effect
> : std::true_type
{ };
310 * A local storage container to manage objects in a non-copyable, movable, and
311 * auto-destructed manner. Any contained object will have its destroy() method
312 * invoked prior to being overwritten or when going out of scope. The purpose
313 * of this is to optionally provide RAII semantics to Alure's resources, such
314 * as contexts, sources, and effects.
316 * Be aware that destruction order is important, as contexts ultimately "own"
317 * the resources created from them. Said resources automatically become invalid
318 * when their owning context is destroyed. Any AutoObjs containing sources,
319 * effects, etc, should already be destroyed or cleared prior to the context
322 * Also, it is possible for resource destruction to fail if the destroy()
323 * method is called incorrectly (e.g. destroying a source when a different
324 * context is current). This normally results in an exception, but because
325 * destructors aren't allowed to let exceptions leave the function body,
326 * std::terminate will be called as a fatal error instead.
330 static_assert(IsAutoable
<T
>::value
, "Invalid type for AutoObj");
334 template<typename U
=T
>
335 EnableIfT
<!std::is_same
<U
,Device
>::value
,AutoObj
&> do_reset(const U
&obj
={})
337 if(mObj
) mObj
.destroy();
341 template<typename U
=T
>
342 EnableIfT
<std::is_same
<U
,Device
>::value
,AutoObj
&> do_reset(const U
&obj
={})
344 if(mObj
) mObj
.close();
350 using element_type
= T
;
352 AutoObj() noexcept
= default;
353 AutoObj(const AutoObj
&) = delete;
354 AutoObj(AutoObj
&&rhs
) noexcept
: mObj(rhs
.mObj
) { rhs
.mObj
= nullptr; }
355 AutoObj(std::nullptr_t
) noexcept
: mObj(nullptr) { }
356 explicit AutoObj(const element_type
&rhs
) noexcept
: mObj(rhs
) { }
357 ~AutoObj() { do_reset(); }
359 AutoObj
& operator=(const AutoObj
&) = delete;
360 AutoObj
& operator=(AutoObj
&&rhs
)
367 AutoObj
& reset(const element_type
&obj
) { return do_reset(obj
); }
369 element_type
release() noexcept
371 element_type ret
= mObj
;
376 element_type
& get() noexcept
{ return mObj
; }
378 element_type
& operator*() noexcept
{ return mObj
; }
379 element_type
* operator->() noexcept
{ return &mObj
; }
381 operator bool() const noexcept
{ return static_cast<bool>(mObj
); }
384 /** Creates an AutoObj for the given input object type. */
386 inline AutoObj
<T
> MakeAuto(const T
&obj
) { return AutoObj
<T
>(obj
); }
389 enum class DeviceEnumeration
{
390 Basic
= ALC_DEVICE_SPECIFIER
,
391 Full
= ALC_ALL_DEVICES_SPECIFIER
,
392 Capture
= ALC_CAPTURE_DEVICE_SPECIFIER
395 enum class DefaultDeviceType
{
396 Basic
= ALC_DEFAULT_DEVICE_SPECIFIER
,
397 Full
= ALC_DEFAULT_ALL_DEVICES_SPECIFIER
,
398 Capture
= ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
402 * A class managing Device objects and other related functionality. This class
403 * is a singleton, only one instance will exist in a process at a time.
405 class ALURE_API DeviceManager
{
406 SharedPtr
<DeviceManagerImpl
> pImpl
;
408 DeviceManager(SharedPtr
<DeviceManagerImpl
>&& impl
) noexcept
;
412 * Retrieves a reference-counted DeviceManager instance. When the last
413 * reference goes out of scope, the DeviceManager and any remaining managed
414 * resources are automatically cleaned up. Multiple calls will return the
415 * same instance as long as there is still a pre-existing reference to the
416 * instance, or else a new instance will be created.
418 static DeviceManager
getInstance();
420 DeviceManager() noexcept
= default;
421 DeviceManager(const DeviceManager
&) noexcept
= default;
422 DeviceManager(DeviceManager
&& rhs
) noexcept
= default;
425 DeviceManager
& operator=(const DeviceManager
&) noexcept
= default;
426 DeviceManager
& operator=(DeviceManager
&&) noexcept
= default;
427 DeviceManager
& operator=(std::nullptr_t
) noexcept
{ pImpl
= nullptr; return *this; };
429 operator bool() const noexcept
{ return pImpl
!= nullptr; }
431 /** Queries the existence of a non-device-specific ALC extension. */
432 bool queryExtension(const String
&name
) const;
433 bool queryExtension(const char *name
) const;
435 /** Enumerates available device names of the given type. */
436 Vector
<String
> enumerate(DeviceEnumeration type
) const;
437 /** Retrieves the default device of the given type. */
438 String
defaultDeviceName(DefaultDeviceType type
) const;
441 * Opens the playback device given by name, or the default if blank. Throws
442 * an exception on error.
444 Device
openPlayback(const String
&name
={});
445 Device
openPlayback(const char *name
);
448 * Opens the playback device given by name, or the default if blank.
449 * Returns an empty Device on error.
451 Device
openPlayback(const String
&name
, const std::nothrow_t
&) noexcept
;
452 Device
openPlayback(const char *name
, const std::nothrow_t
&) noexcept
;
454 /** Opens the default playback device. Returns an empty Device on error. */
455 Device
openPlayback(const std::nothrow_t
&) noexcept
;
459 #define MAKE_PIMPL(BaseT, ImplT) \
464 using handle_type = ImplT*; \
466 BaseT() noexcept : pImpl(nullptr) { } \
467 BaseT(ImplT *impl) noexcept : pImpl(impl) { } \
468 BaseT(const BaseT&) noexcept = default; \
469 BaseT(BaseT&& rhs) noexcept : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
471 BaseT& operator=(const BaseT&) noexcept = default; \
472 BaseT& operator=(BaseT&& rhs) noexcept \
474 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
478 bool operator==(const BaseT &rhs) const noexcept \
479 { return pImpl == rhs.pImpl; } \
480 bool operator!=(const BaseT &rhs) const noexcept \
481 { return pImpl != rhs.pImpl; } \
482 bool operator<=(const BaseT &rhs) const noexcept \
483 { return pImpl <= rhs.pImpl; } \
484 bool operator>=(const BaseT &rhs) const noexcept \
485 { return pImpl >= rhs.pImpl; } \
486 bool operator<(const BaseT &rhs) const noexcept \
487 { return pImpl < rhs.pImpl; } \
488 bool operator>(const BaseT &rhs) const noexcept \
489 { return pImpl > rhs.pImpl; } \
491 operator bool() const noexcept { return !!pImpl; } \
493 handle_type getHandle() const noexcept { return pImpl; }
495 enum class PlaybackName
{
496 Basic
= ALC_DEVICE_SPECIFIER
,
497 Full
= ALC_ALL_DEVICES_SPECIFIER
500 class ALURE_API Device
{
501 MAKE_PIMPL(Device
, DeviceImpl
)
504 /** Retrieves the device name as given by type. */
505 String
getName(PlaybackName type
=PlaybackName::Full
) const;
506 /** Queries the existence of an ALC extension on this device. */
507 bool queryExtension(const String
&name
) const;
508 bool queryExtension(const char *name
) const;
510 /** Retrieves the ALC version supported by this device. */
511 Version
getALCVersion() const;
514 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
515 * extension is unsupported, this will be 0.0.
517 Version
getEFXVersion() const;
519 /** Retrieves the device's playback frequency, in hz. */
520 ALCuint
getFrequency() const;
523 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
524 * is unsupported, this will be 0.
526 ALCuint
getMaxAuxiliarySends() const;
529 * Enumerates available HRTF names. The names are sorted as OpenAL gives
530 * them, such that the index of a given name is the ID to use with
533 * If the ALC_SOFT_HRTF extension is unavailable, this will return an empty
536 Vector
<String
> enumerateHRTFNames() const;
539 * Retrieves whether HRTF is enabled on the device or not.
541 * If the ALC_SOFT_HRTF extension is unavailable, this will return false
542 * although there could still be HRTF applied at a lower hardware level.
544 bool isHRTFEnabled() const;
547 * Retrieves the name of the HRTF currently being used by this device.
549 * If HRTF is not currently enabled, this will be empty.
551 String
getCurrentHRTF() const;
554 * Resets the device, using the specified attributes.
556 * If the ALC_SOFT_HRTF extension is unavailable, this will be a no-op.
558 void reset(ArrayView
<AttributePair
> attributes
);
561 * Creates a new Context on this device, using the specified attributes.
562 * Throws an exception if context creation fails.
564 Context
createContext(ArrayView
<AttributePair
> attributes
={});
566 * Creates a new Context on this device, using the specified attributes.
567 * Returns an empty Context if context creation fails.
569 Context
createContext(ArrayView
<AttributePair
> attributes
, const std::nothrow_t
&) noexcept
;
570 Context
createContext(const std::nothrow_t
&) noexcept
;
573 * Pauses device processing, stopping updates for its contexts. Multiple
574 * calls are allowed but it is not reference counted, so the device will
575 * resume after one resumeDSP call.
577 * Requires the ALC_SOFT_pause_device extension.
582 * Resumes device processing, restarting updates for its contexts. Multiple
583 * calls are allowed and will no-op.
588 * Retrieves the current clock time for the device. This starts relative to
589 * the device being opened, and does not increment while there are no
590 * contexts nor while processing is paused. This is currently based on
591 * std::chrono::steady_clock, and so may not exactly match the rate that
592 * sources play at. In the future it may utilize an OpenAL extension to
593 * retrieve the audio device's real clock which may tic at a subtly
594 * different rate than the main clock(s).
596 std::chrono::nanoseconds
getClockTime();
599 * Closes and frees the device. All previously-created contexts must first
606 enum class DistanceModel
{
607 InverseClamped
= AL_INVERSE_DISTANCE_CLAMPED
,
608 LinearClamped
= AL_LINEAR_DISTANCE_CLAMPED
,
609 ExponentClamped
= AL_EXPONENT_DISTANCE_CLAMPED
,
610 Inverse
= AL_INVERSE_DISTANCE
,
611 Linear
= AL_LINEAR_DISTANCE
,
612 Exponent
= AL_EXPONENT_DISTANCE
,
616 class ALURE_API Context
{
617 MAKE_PIMPL(Context
, ContextImpl
)
620 /** Makes the specified context current for OpenAL operations. */
621 static void MakeCurrent(Context context
);
622 /** Retrieves the current context used for OpenAL operations. */
623 static Context
GetCurrent();
626 * Makes the specified context current for OpenAL operations on the calling
627 * thread only. Requires the ALC_EXT_thread_local_context extension on both
628 * the context's device and the DeviceManager.
630 static void MakeThreadCurrent(Context context
);
631 /** Retrieves the thread-specific context used for OpenAL operations. */
632 static Context
GetThreadCurrent();
635 * Destroys the context. The context must not be current when this is
640 /** Retrieves the Device this context was created from. */
647 * Retrieves a Listener instance for this context. Each context will only
648 * have one listener, which is automatically destroyed with the context.
650 Listener
getListener();
653 * Sets a MessageHandler instance which will be used to provide certain
654 * messages back to the application. Only one handler may be set for a
655 * context at a time. The previously set handler will be returned.
657 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
659 /** Gets the currently-set message handler. */
660 SharedPtr
<MessageHandler
> getMessageHandler() const;
663 * Specifies the desired interval that the background thread will be woken
664 * up to process tasks, e.g. keeping streaming sources filled. An interval
665 * of 0 means the background thread will only be woken up manually with
666 * calls to update. The default is 0.
668 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
671 * Retrieves the current interval used for waking up the background thread.
673 std::chrono::milliseconds
getAsyncWakeInterval() const;
675 // Functions below require the context to be current
678 * Creates a Decoder instance for the given audio file or resource name.
680 SharedPtr
<Decoder
> createDecoder(StringView name
);
683 * Queries if the channel configuration and sample type are supported by
686 bool isSupported(ChannelConfig channels
, SampleType type
) const;
689 * Queries the list of resamplers supported by the context. If the
690 * AL_SOFT_source_resampler extension is unsupported this will be an empty
691 * array, otherwise there will be at least one entry.
693 ArrayView
<String
> getAvailableResamplers();
695 * Queries the context's default resampler index. Be aware, if the
696 * AL_SOFT_source_resampler extension is unsupported the resampler list
697 * will be empty and this will resturn 0. If you try to access the
698 * resampler list with this index without the extension, undefined behavior
699 * will occur (accessing an out of bounds array index).
701 ALsizei
getDefaultResamplerIndex() const;
704 * Creates and caches a Buffer for the given audio file or resource name.
705 * Multiple calls with the same name will return the same Buffer object.
706 * Cached buffers must be freed using removeBuffer before destroying the
707 * context. If the buffer can't be loaded it will throw an exception.
709 Buffer
getBuffer(StringView name
);
712 * Asynchronously prepares a cached Buffer for the given audio file or
713 * resource name. Multiple calls with the same name will return multiple
714 * SharedFutures for the same Buffer object. Once called, the buffer must
715 * be freed using removeBuffer before destroying the context, even if you
716 * never get the Buffer from the SharedFuture.
718 * The Buffer will be scheduled to load asynchronously, and the caller gets
719 * back a SharedFuture that can be checked later (or waited on) to get the
720 * actual Buffer when it's ready. The application must take care to handle
721 * exceptions from the SharedFuture in case an unrecoverable error ocurred
724 * If the Buffer is already fully loaded and cached, a SharedFuture is
725 * returned in a ready state containing it.
727 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
730 * Asynchronously prepares cached Buffers for the given audio file or
731 * resource names. Duplicate names and buffers already cached are ignored.
732 * Cached buffers must be freed using removeBuffer before destroying the
735 * The Buffer objects will be scheduled for loading asynchronously, and
736 * should be retrieved later when needed using getBufferAsync or getBuffer.
737 * Buffers that cannot be loaded, for example due to an unsupported format,
738 * will be ignored and a later call to getBuffer or getBufferAsync will
739 * throw an exception.
741 void precacheBuffersAsync(ArrayView
<StringView
> names
);
744 * Creates and caches a Buffer using the given name by reading the given
745 * decoder. The name may alias an audio file, but it must not currently
746 * exist in the buffer cache.
748 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
> decoder
);
751 * Asynchronously prepares a cached Buffer using the given name by reading
752 * the given decoder. The name may alias an audio file, but it must not
753 * currently exist in the buffer cache. Once called, the buffer must be
754 * freed using removeBuffer before destroying the context, even if you
755 * never get the Buffer from the SharedFuture.
757 * The Buffer will be scheduled to load asynchronously, and the caller gets
758 * back a SharedFuture that can be checked later (or waited on) to get the
759 * actual Buffer when it's ready. The application must take care to handle
760 * exceptions from the SharedFuture in case an unrecoverable error ocurred
761 * during the load. The decoder must not have its read or seek methods
762 * called while the buffer is not ready.
764 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
> decoder
);
767 * Looks for a cached buffer using the given name and returns it. If the
768 * given name does not exist in the cache, a null buffer is returned.
770 Buffer
findBuffer(StringView name
);
773 * Looks for an asynchronously-loading buffer using the given name and
774 * returns a SharedFuture for it. If the given name does not exist in the
775 * cache, an invalid SharedFuture is returned (check with a call to
776 * \c SharedFuture::valid).
778 * If the Buffer is already fully loaded and cached, a SharedFuture is
779 * returned in a ready state containing it.
781 SharedFuture
<Buffer
> findBufferAsync(StringView name
);
784 * Deletes the cached Buffer object for the given audio file or resource
785 * name, invalidating all Buffer objects with this name. If a source is
786 * currently playing the buffer, it will be stopped first.
788 void removeBuffer(StringView name
);
790 * Deletes the given cached buffer, invalidating all other Buffer objects
791 * with the same name. Equivalent to calling
792 * removeBuffer(buffer.getName()).
794 void removeBuffer(Buffer buffer
);
797 * Creates a new Source for playing audio. There is no practical limit to
798 * the number of sources you may create. You must call Source::destroy when
799 * the source is no longer needed.
801 Source
createSource();
803 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
805 Effect
createEffect();
807 SourceGroup
createSourceGroup();
809 /** Sets the doppler factor to apply to all source doppler calculations. */
810 void setDopplerFactor(ALfloat factor
);
813 * Sets the speed of sound propagation, in units per second, to calculate
814 * the doppler effect along with other distance-related time effects. The
815 * default is 343.3 units per second (a realistic speed assuming 1 meter
816 * per unit). If this is adjusted for a different unit scale,
817 * Listener::setMetersPerUnit should also be adjusted.
819 void setSpeedOfSound(ALfloat speed
);
822 * Sets the distance model used to attenuate sources given their distance
823 * from the listener. The default, InverseClamped, provides a realistic 1/r
824 * reduction in volume (that is, every doubling of distance causes the gain
825 * to reduce by half).
827 * The Clamped distance models restrict the source distance for the purpose
828 * of distance attenuation, so a source won't sound closer than its
829 * reference distance or farther than its max distance.
831 void setDistanceModel(DistanceModel model
);
833 /** Updates the context and all sources belonging to this context. */
837 class ALURE_API Listener
{
838 MAKE_PIMPL(Listener
, ListenerImpl
)
841 /** Sets the "master" gain for all context output. */
842 void setGain(ALfloat gain
);
845 * Specifies the listener's 3D position, velocity, and orientation
846 * together (see: setPosition, setVelocity, and setOrientation).
848 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
850 /** Specifies the listener's 3D position. */
851 void setPosition(const Vector3
&position
);
852 void setPosition(const ALfloat
*pos
);
855 * Specifies the listener's 3D velocity, in units per second. As with
856 * OpenAL, this does not actually alter the listener's position, and
857 * instead just alters the pitch as determined by the doppler effect.
859 void setVelocity(const Vector3
&velocity
);
860 void setVelocity(const ALfloat
*vel
);
863 * Specifies the listener's 3D orientation, using position-relative 'at'
864 * and 'up' direction vectors.
866 void setOrientation(const std::pair
<Vector3
,Vector3
> &orientation
);
867 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
868 void setOrientation(const ALfloat
*ori
);
871 * Sets the number of meters per unit, used for various effects that rely
872 * on the distance in meters including air absorption and initial reverb
873 * decay. If this is changed, it's strongly recommended to also set the
874 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
875 * realistic 343.3m/s for sound propagation).
877 void setMetersPerUnit(ALfloat m_u
);
881 class ALURE_API Buffer
{
882 MAKE_PIMPL(Buffer
, BufferImpl
)
885 /** Retrieves the length of the buffer in sample frames. */
886 ALuint
getLength() const;
888 /** Retrieves the buffer's frequency in hz. */
889 ALuint
getFrequency() const;
891 /** Retrieves the buffer's sample configuration. */
892 ChannelConfig
getChannelConfig() const;
894 /** Retrieves the buffer's sample type. */
895 SampleType
getSampleType() const;
898 * Retrieves the storage size used by the buffer, in bytes. Note that the
899 * size in bytes may not be what you expect from the length, as it may take
900 * more space internally than the ChannelConfig and SampleType suggest to
903 ALuint
getSize() const;
906 * Sets the buffer's loop points, used for looping sources. If the current
907 * context does not support the AL_SOFT_loop_points extension, start and
908 * end must be 0 and getLength() respectively. Otherwise, start must be
909 * less than end, and end must be less than or equal to getLength().
911 * The buffer must not be in use when this method is called.
913 * \param start The starting point, in sample frames (inclusive).
914 * \param end The ending point, in sample frames (exclusive).
916 void setLoopPoints(ALuint start
, ALuint end
);
918 /** Retrieves the current loop points as a [start,end) pair. */
919 std::pair
<ALuint
,ALuint
> getLoopPoints() const;
921 /** Retrieves the Source objects currently playing the buffer. */
922 Vector
<Source
> getSources() const;
924 /** Retrieves the name the buffer was created with. */
925 StringView
getName() const;
928 * Queries the number of sources currently using the buffer. Be aware that
929 * you need to call \c Context::update to reliably ensure the count is kept
930 * updated for when sources reach their end. This is equivalent to calling
931 * getSources().size().
933 size_t getSourceCount() const;
937 enum class Spatialize
{
940 Auto
= 0x0002 /* AL_AUTO_SOFT */
943 class ALURE_API Source
{
944 MAKE_PIMPL(Source
, SourceImpl
)
948 * Plays the source using a buffer. The same buffer may be played from
949 * multiple sources simultaneously.
951 void play(Buffer buffer
);
953 * Plays the source by asynchronously streaming audio from a decoder. The
954 * given decoder must *NOT* have its read or seek methods called from
955 * elsewhere while in use.
957 * \param decoder The decoder object to play audio from.
958 * \param chunk_len The number of sample frames to read for each chunk
959 * update. Smaller values will require more frequent updates and
960 * larger values will handle more data with each chunk.
961 * \param queue_size The number of chunks to keep queued during playback.
962 * Smaller values use less memory while larger values improve
963 * protection against underruns.
965 void play(SharedPtr
<Decoder
> decoder
, ALsizei chunk_len
, ALsizei queue_size
);
968 * Prepares to play a source using a future buffer. The method will return
969 * right away and the source will begin playing once the future buffer
970 * becomes ready. If the future buffer is already ready, it begins playing
971 * immediately as if you called play(future_buffer.get()).
973 * The future buffer is checked during calls to \c Context::update and the
974 * source will start playback once the future buffer reports it's ready.
975 * Use the isPending method to check if the source is still waiting for the
978 void play(SharedFuture
<Buffer
> future_buffer
);
981 * Stops playback, releasing the buffer or decoder reference. Any pending
982 * playback from a future buffer is canceled.
987 * Fades the source to the specified gain over the given duration, at which
988 * point playback will stop. This gain is in addition to the base gain, and
989 * must be greater than 0 and less than 1. The duration must also be
992 * The fading is logarithmic. As a result, the initial drop-off may happen
993 * faster than expected but the fading is more perceptually consistant over
994 * the given duration. It will take just as much time to go from -6dB to
995 * -12dB as it will to go from -40dB to -46dB, for example.
997 * Pending playback from a future buffer is not immediately canceled, but
998 * the fade timer starts with this call. If the future buffer then becomes
999 * ready, it will start mid-fade. Pending playback will be canceled if the
1000 * fade out completes before the future buffer becomes ready.
1002 * Fading is updated during calls to \c Context::update, which should be
1003 * called regularly (30 to 50 times per second) for the fading to be
1006 void fadeOutToStop(ALfloat gain
, std::chrono::milliseconds duration
);
1008 /** Pauses the source if it is playing. */
1011 /** Resumes the source if it is paused. */
1014 /** Specifies if the source is waiting to play a future buffer. */
1015 bool isPending() const;
1017 /** Specifies if the source is currently playing. */
1018 bool isPlaying() const;
1020 /** Specifies if the source is currently paused. */
1021 bool isPaused() const;
1024 * Specifies if the source is currently playing or waiting to play a future
1027 bool isPlayingOrPending() const;
1030 * Sets this source as a child of the given source group. The given source
1031 * group's parameters will influence this and all other sources that belong
1032 * to it. A source can only be the child of one source group at a time,
1033 * although that source group may belong to another source group.
1035 * Passing in a null group removes it from its current source group.
1037 void setGroup(SourceGroup group
);
1039 /** Retrieves the source group this source belongs to. */
1040 SourceGroup
getGroup() const;
1043 * Specifies the source's playback priority. The lowest priority sources
1044 * will be forcefully stopped when no more mixing sources are available and
1045 * higher priority sources are played.
1047 void setPriority(ALuint priority
);
1048 /** Retrieves the source's priority. */
1049 ALuint
getPriority() const;
1052 * Sets the source's offset, in sample frames. If the source is playing or
1053 * paused, it will go to that offset immediately, otherwise the source will
1054 * start at the specified offset the next time it's played.
1056 void setOffset(uint64_t offset
);
1058 * Retrieves the source offset in sample frames and its latency in nano-
1059 * seconds. For streaming sources this will be the offset based on the
1060 * decoder's read position.
1062 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1065 std::pair
<uint64_t,std::chrono::nanoseconds
> getSampleOffsetLatency() const;
1066 uint64_t getSampleOffset() const { return std::get
<0>(getSampleOffsetLatency()); }
1068 * Retrieves the source offset and latency in seconds. For streaming
1069 * sources this will be the offset based on the decoder's read position.
1071 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1074 std::pair
<Seconds
,Seconds
> getSecOffsetLatency() const;
1075 Seconds
getSecOffset() const { return std::get
<0>(getSecOffsetLatency()); }
1078 * Specifies if the source should loop on the Buffer or Decoder object's
1081 void setLooping(bool looping
);
1082 bool getLooping() const;
1085 * Specifies a linear pitch shift base. A value of 1.0 is the default
1088 void setPitch(ALfloat pitch
);
1089 ALfloat
getPitch() const;
1092 * Specifies the base linear gain. A value of 1.0 is the default normal
1095 void setGain(ALfloat gain
);
1096 ALfloat
getGain() const;
1099 * Specifies the minimum and maximum gain. The source's gain is clamped to
1100 * this range after distance attenuation and cone attenuation are applied
1101 * to the gain base, although before the filter gain adjustements.
1103 void setGainRange(ALfloat mingain
, ALfloat maxgain
);
1104 std::pair
<ALfloat
,ALfloat
> getGainRange() const;
1105 ALfloat
getMinGain() const { return std::get
<0>(getGainRange()); }
1106 ALfloat
getMaxGain() const { return std::get
<1>(getGainRange()); }
1109 * Specifies the reference distance and maximum distance the source will
1110 * use for the current distance model. For Clamped distance models, the
1111 * source's calculated distance is clamped to the specified range before
1112 * applying distance-related attenuation.
1114 * For all distance models, the reference distance is the distance at which
1115 * the source's volume will not have any extra attenuation (an effective
1116 * gain multiplier of 1).
1118 void setDistanceRange(ALfloat refdist
, ALfloat maxdist
);
1119 std::pair
<ALfloat
,ALfloat
> getDistanceRange() const;
1120 ALfloat
getReferenceDistance() const { return std::get
<0>(getDistanceRange()); }
1121 ALfloat
getMaxDistance() const { return std::get
<1>(getDistanceRange()); }
1124 * Specifies the source's 3D position, velocity, and direction together
1125 * (see: setPosition, setVelocity, and setDirection).
1127 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const Vector3
&direction
);
1130 * Specifies the source's 3D position, velocity, and orientation together
1131 * (see: setPosition, setVelocity, and setOrientation).
1133 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
1135 /** Specifies the source's 3D position. */
1136 void setPosition(const Vector3
&position
);
1137 void setPosition(const ALfloat
*pos
);
1138 Vector3
getPosition() const;
1141 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
1142 * this does not actually alter the source's position, and instead just
1143 * alters the pitch as determined by the doppler effect.
1145 void setVelocity(const Vector3
&velocity
);
1146 void setVelocity(const ALfloat
*vel
);
1147 Vector3
getVelocity() const;
1150 * Specifies the source's 3D facing direction. Deprecated in favor of
1153 void setDirection(const Vector3
&direction
);
1154 void setDirection(const ALfloat
*dir
);
1155 Vector3
getDirection() const;
1158 * Specifies the source's 3D orientation, using position-relative 'at' and
1159 * 'up' direction vectors. Note: unlike the AL_EXT_BFORMAT extension this
1160 * property comes from, this also affects the facing direction, superceding
1163 void setOrientation(const std::pair
<Vector3
,Vector3
> &orientation
);
1164 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
1165 void setOrientation(const ALfloat
*ori
);
1166 std::pair
<Vector3
,Vector3
> getOrientation() const;
1169 * Specifies the source's cone angles, in degrees. The inner angle is the
1170 * area within which the listener will hear the source with no extra
1171 * attenuation, while the listener being outside of the outer angle will
1172 * hear the source attenuated according to the outer cone gains. The area
1173 * follows the facing direction, so for example an inner angle of 180 means
1174 * the entire front face of the source is in the inner cone.
1176 void setConeAngles(ALfloat inner
, ALfloat outer
);
1177 std::pair
<ALfloat
,ALfloat
> getConeAngles() const;
1178 ALfloat
getInnerConeAngle() const { return std::get
<0>(getConeAngles()); }
1179 ALfloat
getOuterConeAngle() const { return std::get
<1>(getConeAngles()); }
1182 * Specifies the linear gain multiplier when the listener is outside of the
1183 * source's outer cone area. The specified gain applies to all frequencies,
1184 * while gainhf applies extra attenuation to high frequencies creating a
1187 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1189 void setOuterConeGains(ALfloat gain
, ALfloat gainhf
=1.0f
);
1190 std::pair
<ALfloat
,ALfloat
> getOuterConeGains() const;
1191 ALfloat
getOuterConeGain() const { return std::get
<0>(getOuterConeGains()); }
1192 ALfloat
getOuterConeGainHF() const { return std::get
<1>(getOuterConeGains()); }
1195 * Specifies the rolloff factors for the direct and send paths. This is
1196 * effectively a distance scaling relative to the reference distance. Note:
1197 * the room rolloff factor is 0 by default, disabling distance attenuation
1198 * for send paths. This is because the reverb engine will, by default,
1199 * apply a more realistic room decay based on the reverb decay time and
1202 void setRolloffFactors(ALfloat factor
, ALfloat roomfactor
=0.0f
);
1203 std::pair
<ALfloat
,ALfloat
> getRolloffFactors() const;
1204 ALfloat
getRolloffFactor() const { return std::get
<0>(getRolloffFactors()); }
1205 ALfloat
getRoomRolloffFactor() const { return std::get
<1>(getRolloffFactors()); }
1208 * Specifies the doppler factor for the doppler effect's pitch shift. This
1209 * effectively scales the source and listener velocities for the doppler
1212 void setDopplerFactor(ALfloat factor
);
1213 ALfloat
getDopplerFactor() const;
1216 * Specifies if the source's position, velocity, and direction/orientation
1217 * are relative to the listener.
1219 void setRelative(bool relative
);
1220 bool getRelative() const;
1223 * Specifies the source's radius. This causes the source to behave as if
1224 * every point within the spherical area emits sound.
1226 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1228 void setRadius(ALfloat radius
);
1229 ALfloat
getRadius() const;
1232 * Specifies the left and right channel angles, in radians, when playing a
1233 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1234 * in front and positive values going left.
1236 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1238 void setStereoAngles(ALfloat leftAngle
, ALfloat rightAngle
);
1239 std::pair
<ALfloat
,ALfloat
> getStereoAngles() const;
1242 * Specifies if the source always has 3D spatialization features (On),
1243 * never has 3D spatialization features (Off), or if spatialization is
1244 * enabled based on playing a mono sound or not (Auto, default).
1246 * Has no effect without the AL_SOFT_source_spatialize extension.
1248 void set3DSpatialize(Spatialize spatialize
);
1249 Spatialize
get3DSpatialize() const;
1252 * Specifies the index of the resampler to use for this source. The index
1253 * is from the resamplers returned by \c Context::getAvailableResamplers,
1254 * and must be 0 or greater.
1256 * Has no effect without the AL_SOFT_source_resampler extension.
1258 void setResamplerIndex(ALsizei index
);
1259 ALsizei
getResamplerIndex() const;
1262 * Specifies a multiplier for the amount of atmospheric high-frequency
1263 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1264 * -0.05dB per meter, with higher values simulating foggy air and lower
1265 * values simulating dryer air. The default is 0.
1267 void setAirAbsorptionFactor(ALfloat factor
);
1268 ALfloat
getAirAbsorptionFactor() const;
1271 * Specifies to automatically apply adjustments to the direct path's high-
1272 * frequency gain, and the send paths' gain and high-frequency gain. The
1273 * default is true for all.
1275 void setGainAuto(bool directhf
, bool send
, bool sendhf
);
1276 std::tuple
<bool,bool,bool> getGainAuto() const;
1277 bool getDirectGainHFAuto() const { return std::get
<0>(getGainAuto()); }
1278 bool getSendGainAuto() const { return std::get
<1>(getGainAuto()); }
1279 bool getSendGainHFAuto() const { return std::get
<2>(getGainAuto()); }
1281 /** Sets the filter properties on the direct path signal. */
1282 void setDirectFilter(const FilterParams
&filter
);
1284 * Sets the filter properties on the given send path signal. Any auxiliary
1285 * effect slot on the send path remains in place.
1287 void setSendFilter(ALuint send
, const FilterParams
&filter
);
1289 * Connects the effect slot to the given send path. Any filter properties
1290 * on the send path remain as they were.
1292 void setAuxiliarySend(AuxiliaryEffectSlot slot
, ALuint send
);
1294 * Connects the effect slot to the given send path, using the filter
1297 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot
, ALuint send
, const FilterParams
&filter
);
1299 /** Destroys the source, stopping playback and releasing resources. */
1304 class ALURE_API SourceGroup
{
1305 MAKE_PIMPL(SourceGroup
, SourceGroupImpl
)
1309 * Adds this source group as a subgroup of the specified source group. This
1310 * method will throw an exception if this group is being added to a group
1311 * it has as a sub-group (i.e. it would create a circular sub-group chain).
1313 void setParentGroup(SourceGroup group
);
1315 /** Retrieves the source group this source group is a child of. */
1316 SourceGroup
getParentGroup() const;
1318 /** Returns the list of sources currently in the group. */
1319 Vector
<Source
> getSources() const;
1321 /** Returns the list of subgroups currently in the group. */
1322 Vector
<SourceGroup
> getSubGroups() const;
1325 * Sets the source group gain, which accumulates with its sources' and
1328 void setGain(ALfloat gain
);
1329 /** Gets the source group gain. */
1330 ALfloat
getGain() const;
1333 * Sets the source group pitch, which accumulates with its sources' and
1334 * sub-groups' pitch.
1336 void setPitch(ALfloat pitch
);
1337 /** Gets the source group pitch. */
1338 ALfloat
getPitch() const;
1341 * Pauses all currently-playing sources that are under this group,
1342 * including sub-groups.
1344 void pauseAll() const;
1346 * Resumes all paused sources that are under this group, including
1349 void resumeAll() const;
1351 /** Stops all sources that are under this group, including sub-groups. */
1352 void stopAll() const;
1355 * Destroys the source group, removing all sources from it before being
1367 class ALURE_API AuxiliaryEffectSlot
{
1368 MAKE_PIMPL(AuxiliaryEffectSlot
, AuxiliaryEffectSlotImpl
)
1371 void setGain(ALfloat gain
);
1373 * If set to true, the reverb effect will automatically apply adjustments
1374 * to the source's send slot gains based on the effect properties.
1376 * Has no effect when using non-reverb effects. Default is true.
1378 void setSendAuto(bool sendauto
);
1381 * Updates the effect slot with a new effect. The given effect object may
1382 * be altered or destroyed without affecting the effect slot.
1384 void applyEffect(Effect effect
);
1387 * Destroys the effect slot, returning it to the system. If the effect slot
1388 * is currently set on a source send, it will be removed first.
1393 * Retrieves each Source object and its pairing send this effect slot is
1396 Vector
<SourceSend
> getSourceSends() const;
1399 * Queries the number of source sends the effect slot is used by. This is
1400 * equivalent to calling getSourceSends().size().
1402 size_t getUseCount() const;
1406 class ALURE_API Effect
{
1407 MAKE_PIMPL(Effect
, EffectImpl
)
1411 * Updates the effect with the specified reverb properties. If the
1412 * EAXReverb effect is not supported, it will automatically attempt to
1413 * downgrade to the Standard Reverb effect.
1415 void setReverbProperties(const EFXEAXREVERBPROPERTIES
&props
);
1418 * Updates the effect with the specified chorus properties. If the chorus
1419 * effect is not supported, an exception will be thrown.
1421 void setChorusProperties(const EFXCHORUSPROPERTIES
&props
);
1428 * Audio decoder interface. Applications may derive from this, implementing the
1429 * necessary methods, and use it in places the API wants a Decoder object.
1431 class ALURE_API Decoder
{
1435 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1436 virtual ALuint
getFrequency() const noexcept
= 0;
1437 /** Retrieves the channel configuration of the audio being decoded. */
1438 virtual ChannelConfig
getChannelConfig() const noexcept
= 0;
1439 /** Retrieves the sample type of the audio being decoded. */
1440 virtual SampleType
getSampleType() const noexcept
= 0;
1443 * Retrieves the total length of the audio, in sample frames. If unknown,
1444 * returns 0. Note that if the returned length is 0, the decoder may not be
1445 * used to load a Buffer.
1447 virtual uint64_t getLength() const noexcept
= 0;
1449 * Seek to pos, specified in sample frames. Returns true if the seek was
1452 virtual bool seek(uint64_t pos
) noexcept
= 0;
1455 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1456 * start >= end, all available samples are included in the loop.
1458 virtual std::pair
<uint64_t,uint64_t> getLoopPoints() const noexcept
= 0;
1461 * Decodes count sample frames, writing them to ptr, and returns the number
1462 * of sample frames written. Returning less than the requested count
1463 * indicates the end of the audio.
1465 virtual ALuint
read(ALvoid
*ptr
, ALuint count
) noexcept
= 0;
1469 * Audio decoder factory interface. Applications may derive from this,
1470 * implementing the necessary methods, and use it in places the API wants a
1471 * DecoderFactory object.
1473 class ALURE_API DecoderFactory
{
1475 virtual ~DecoderFactory();
1478 * Creates and returns a Decoder instance for the given resource file. If
1479 * the decoder needs to retain the file handle for reading as-needed, it
1480 * should move the UniquePtr to internal storage.
1482 * \return nullptr if a decoder can't be created from the file.
1484 virtual SharedPtr
<Decoder
> createDecoder(UniquePtr
<std::istream
> &file
) noexcept
= 0;
1488 * Registers a decoder factory for decoding audio. Registered factories are
1489 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1490 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1491 * name1 < name2. Internal decoder factories are always used after registered
1494 * Alure retains a reference to the DecoderFactory instance and will release it
1495 * (destructing the object) when the library unloads.
1497 * \param name A unique name identifying this decoder factory.
1498 * \param factory A DecoderFactory instance used to create Decoder instances.
1500 ALURE_API
void RegisterDecoder(StringView name
, UniquePtr
<DecoderFactory
> factory
);
1503 * Unregisters a decoder factory by name. Alure returns the instance back to
1506 * \param name The unique name identifying a previously-registered decoder
1509 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1510 * decoder factory with the given name doesn't exist.
1512 ALURE_API UniquePtr
<DecoderFactory
> UnregisterDecoder(StringView name
) noexcept
;
1516 * A file I/O factory interface. Applications may derive from this and set an
1517 * instance to be used by the audio decoders. By default, the library uses
1520 class ALURE_API FileIOFactory
{
1523 * Sets the factory instance to be used by the audio decoders. If a
1524 * previous factory was set, it's returned to the application. Passing in a
1525 * nullptr reverts to the default.
1527 static UniquePtr
<FileIOFactory
> set(UniquePtr
<FileIOFactory
> factory
) noexcept
;
1530 * Gets the current FileIOFactory instance being used by the audio
1533 static FileIOFactory
&get() noexcept
;
1535 virtual ~FileIOFactory();
1537 /** Opens a read-only binary file for the given name. */
1538 virtual UniquePtr
<std::istream
> openFile(const String
&name
) noexcept
= 0;
1543 * A message handler interface. Applications may derive from this and set an
1544 * instance on a context to receive messages. The base methods are no-ops, so
1545 * derived classes only need to implement methods for relevant messages.
1547 * It's recommended that applications mark their handler methods using the
1548 * override keyword, to ensure they're properly overriding the base methods in
1551 class ALURE_API MessageHandler
{
1553 virtual ~MessageHandler();
1556 * Called when the given device has been disconnected and is no longer
1557 * usable for output. As per the ALC_EXT_disconnect specification,
1558 * disconnected devices remain valid, however all playing sources are
1559 * automatically stopped, any sources that are attempted to play will
1560 * immediately stop, and new contexts may not be created on the device.
1562 * Note that connection status is checked during Context::update calls, so
1563 * that method must be called regularly to be notified when a device is
1564 * disconnected. This method may not be called if the device lacks support
1565 * for the ALC_EXT_disconnect extension.
1567 virtual void deviceDisconnected(Device device
) noexcept
;
1570 * Called when the given source reaches the end of the buffer or stream.
1572 * Sources that stopped automatically will be detected upon a call to
1575 virtual void sourceStopped(Source source
) noexcept
;
1578 * Called when the given source was forced to stop. This can be because
1579 * either there were no more mixing sources and a higher-priority source
1580 * preempted it, it's part of a SourceGroup (or sub-group thereof) that had
1581 * its SourceGroup::stopAll method called, or it was playing a buffer
1582 * that's getting removed.
1584 virtual void sourceForceStopped(Source source
) noexcept
;
1587 * Called when a new buffer is about to be created and loaded. May be
1588 * called asynchronously for buffers being loaded asynchronously.
1590 * \param name The resource name, as passed to Context::getBuffer.
1591 * \param channels Channel configuration of the given audio data.
1592 * \param type Sample type of the given audio data.
1593 * \param samplerate Sample rate of the given audio data.
1594 * \param data The audio data that is about to be fed to the OpenAL buffer.
1596 virtual void bufferLoading(StringView name
, ChannelConfig channels
, SampleType type
, ALuint samplerate
, ArrayView
<ALbyte
> data
) noexcept
;
1599 * Called when a resource isn't found, allowing the app to substitute in a
1600 * different resource. For buffers being cached, the original name will
1601 * still be used for the cache entry so the app doesn't have to keep track
1602 * of substituted resource names.
1604 * This will be called again if the new name also isn't found.
1606 * \param name The resource name that was not found.
1607 * \return The replacement resource name to use instead. Returning an empty
1608 * string means to stop trying.
1610 virtual String
resourceNotFound(StringView name
) noexcept
;
1615 } // namespace alure
1617 #endif /* AL_ALURE2_H */