16 #if defined(ALURE_BUILD_STATIC) || defined(ALURE_STATIC_LIB)
18 #elif defined(ALURE_BUILD_DLL)
19 #define ALURE_API __declspec(dllexport)
21 #define ALURE_API __declspec(dllimport)
29 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
30 #define EFXEAXREVERBPROPERTIES_DEFINED
40 float flReflectionsGain
;
41 float flReflectionsDelay
;
42 float flReflectionsPan
[3];
43 float flLateReverbGain
;
44 float flLateReverbDelay
;
45 float flLateReverbPan
[3];
48 float flModulationTime
;
49 float flModulationDepth
;
50 float flAirAbsorptionGainHF
;
53 float flRoomRolloffFactor
;
55 } EFXEAXREVERBPROPERTIES
, *LPEFXEAXREVERBPROPERTIES
;
61 class ALDeviceManager
;
74 class AuxiliaryEffectSlot
;
75 class ALAuxiliaryEffectSlot
;
83 // Duration in seconds, using double precision
84 using Seconds
= std::chrono::duration
<double>;
86 // A SharedPtr implementation, defaults to C++11's std::shared_ptr. If this is
87 // changed, you must recompile the library.
89 using SharedPtr
= std::shared_ptr
<T
>;
90 template<typename T
, typename
... Args
>
91 constexpr inline SharedPtr
<T
> MakeShared(Args
&&... args
)
93 return std::make_shared
<T
>(std::forward
<Args
>(args
)...);
96 // A UniquePtr implementation, defaults to C++11's std::unique_ptr. If this is
97 // changed, you must recompile the library.
98 template<typename T
, typename D
= std::default_delete
<T
>>
99 using UniquePtr
= std::unique_ptr
<T
, D
>;
100 template<typename T
, typename
... Args
>
101 constexpr inline UniquePtr
<T
> MakeUnique(Args
&&... args
)
103 #if __cplusplus >= 201402L
104 return std::make_unique
<T
>(std::forward
<Args
>(args
)...);
106 return std::unique_ptr
<T
>(new T(std::forward
<Args
>(args
)...));
110 // A Vector implementation, defaults to C++'s std::vector. If this is changed,
111 // you must recompile the library.
113 using Vector
= std::vector
<T
>;
115 // A static-sized Array implementation, defaults to C++11's std::array. If this
116 // is changed, you must recompile the library.
117 template<typename T
, std::size_t N
>
118 using Array
= std::array
<T
, N
>;
120 // A String implementation, default's to C++'s std::string. If this is changed,
121 // you must recompile the library.
122 using String
= std::string
;
124 // A rather simple ArrayView container. This allows accepting various array
125 // types (Array, Vector, a static-sized array, a dynamic array + size) without
126 // copying its elements.
134 typedef const T
*const_iterator
;
136 ArrayView() : mElems(nullptr), mNumElems(0) { }
137 ArrayView(const ArrayView
&rhs
) : mElems(rhs
.data()), mNumElems(rhs
.size()) { }
138 ArrayView(ArrayView
&& rhs
) : mElems(rhs
.data()), mNumElems(rhs
.size()) { }
139 ArrayView(T
*elems
, size_t num_elems
) : mElems(elems
), mNumElems(num_elems
) { }
141 ArrayView(T (&elems
)[N
]) : mElems(elems
), mNumElems(N
) { }
142 template<typename OtherT
>
143 ArrayView(OtherT
&arr
) : mElems(arr
.data()), mNumElems(arr
.size()) { }
145 ArrayView
& operator=(const ArrayView
&rhs
)
148 mNumElems
= rhs
.size();
150 ArrayView
& operator=(ArrayView
&& rhs
)
153 mNumElems
= rhs
.size();
156 ArrayView
& operator=(T (&elems
)[N
])
161 template<typename OtherT
>
162 ArrayView
& operator=(OtherT
&arr
)
165 mNumElems
= arr
.size();
169 const T
*data() const { return mElems
; }
170 T
*data() { return mElems
; }
172 size_t size() const { return mNumElems
; }
173 bool empty() const { return mNumElems
== 0; }
175 const T
& operator[](size_t i
) const { return mElems
[i
]; }
176 T
& operator[](size_t i
) { return mElems
[i
]; }
178 const T
& front() const { return mElems
[0]; }
179 T
& front() { return mElems
[0]; }
180 const T
& back() const { return mElems
[mNumElems
-1]; }
181 T
& back() { return mElems
[mNumElems
-1]; }
183 const T
& at(size_t i
) const
186 throw std::out_of_range("alure::ArrayView::at: element out of range");
192 throw std::out_of_range("alure::ArrayView::at: element out of range");
196 iterator
begin() { return mElems
; }
197 const_iterator
begin() const { return mElems
; }
198 const_iterator
cbegin() const { return mElems
; }
200 iterator
end() { return mElems
+ mNumElems
; }
201 const_iterator
end() const { return mElems
+ mNumElems
; }
202 const_iterator
cend() const { return mElems
+ mNumElems
; }
207 * An attribute pair, for passing attributes to Device::createContext and
210 using AttributePair
= std::pair
<ALCint
,ALCint
>;
211 static_assert(sizeof(AttributePair
) == sizeof(ALCint
[2]), "Bad AttributePair size");
214 struct FilterParams
{
216 ALfloat mGainHF
; // For low-pass and band-pass filters
217 ALfloat mGainLF
; // For high-pass and band-pass filters
221 class ALURE_API Vector3
{
222 Array
<ALfloat
,3> mValue
;
225 constexpr Vector3() noexcept
226 : mValue
{{0.0f
, 0.0f
, 0.0f
}}
228 constexpr Vector3(const Vector3
&rhs
) noexcept
229 : mValue
{{rhs
.mValue
[0], rhs
.mValue
[1], rhs
.mValue
[2]}}
231 constexpr Vector3(ALfloat val
) noexcept
232 : mValue
{{val
, val
, val
}}
234 constexpr Vector3(ALfloat x
, ALfloat y
, ALfloat z
) noexcept
237 Vector3(const ALfloat
*vec
) noexcept
238 : mValue
{{vec
[0], vec
[1], vec
[2]}}
241 const ALfloat
*getPtr() const noexcept
242 { return mValue
.data(); }
244 ALfloat
& operator[](size_t i
) noexcept
245 { return mValue
[i
]; }
246 constexpr const ALfloat
& operator[](size_t i
) const noexcept
247 { return mValue
[i
]; }
249 #define ALURE_DECL_OP(op) \
250 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
252 return Vector3(mValue[0] op rhs.mValue[0], \
253 mValue[1] op rhs.mValue[1], \
254 mValue[2] op rhs.mValue[2]); \
261 #define ALURE_DECL_OP(op) \
262 Vector3& operator op(const Vector3 &rhs) noexcept \
264 mValue[0] op rhs.mValue[0]; \
265 mValue[1] op rhs.mValue[1]; \
266 mValue[2] op rhs.mValue[2]; \
275 #define ALURE_DECL_OP(op) \
276 constexpr Vector3 operator op(ALfloat scale) const noexcept \
278 return Vector3(mValue[0] op scale, \
279 mValue[1] op scale, \
280 mValue[2] op scale); \
285 #define ALURE_DECL_OP(op) \
286 Vector3& operator op(ALfloat scale) noexcept \
288 mValue[0] op scale; \
289 mValue[1] op scale; \
290 mValue[2] op scale; \
297 constexpr ALfloat
getLengthSquared() const noexcept
298 { return mValue
[0]*mValue
[0] + mValue
[1]*mValue
[1] + mValue
[2]*mValue
[2]; }
299 ALfloat
getLength() const noexcept
300 { return std::sqrt(getLengthSquared()); }
302 constexpr ALfloat
getDistanceSquared(const Vector3
&pos
) const noexcept
303 { return (pos
- *this).getLengthSquared(); }
304 ALfloat
getDistance(const Vector3
&pos
) const noexcept
305 { return (pos
- *this).getLength(); }
307 static_assert(sizeof(Vector3
) == sizeof(ALfloat
[3]), "Bad Vector3 size");
310 enum class SampleType
{
316 ALURE_API
const char *GetSampleTypeName(SampleType type
);
318 enum class ChannelConfig
{
319 /** 1-channel mono sound. */
321 /** 2-channel stereo sound. */
323 /** 2-channel rear sound (back-left and back-right). */
325 /** 4-channel surround sound. */
327 /** 5.1 surround sound. */
329 /** 6.1 surround sound. */
331 /** 7.1 surround sound. */
333 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
335 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
338 ALURE_API
const char *GetChannelConfigName(ChannelConfig cfg
);
340 ALURE_API ALuint
FramesToBytes(ALuint frames
, ChannelConfig chans
, SampleType type
);
341 ALURE_API ALuint
BytesToFrames(ALuint bytes
, ChannelConfig chans
, SampleType type
);
345 * Creates a version number value using the specified major and minor values.
347 constexpr inline ALCuint
MakeVersion(ALCushort major
, ALCushort minor
)
348 { return (major
<<16) | minor
; }
351 * Retrieves the major version of a version number value created by
354 constexpr inline ALCuint
MajorVersion(ALCuint version
)
355 { return version
>>16; }
357 * Retrieves the minor version of a version number value created by
360 constexpr inline ALCuint
MinorVersion(ALCuint version
)
361 { return version
&0xffff; }
364 #define MAKE_PIMPL(BaseT, ImplT) \
369 using handle_type = ImplT*; \
371 BaseT() : pImpl(nullptr) { } \
372 BaseT(ImplT *impl) : pImpl(impl) { } \
373 BaseT(const BaseT&) = default; \
374 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
376 BaseT& operator=(const BaseT&) = default; \
377 BaseT& operator=(BaseT&& rhs) \
379 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
383 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
384 bool operator==(BaseT&& rhs) const { return pImpl == rhs.pImpl; } \
386 operator bool() const { return !!pImpl; } \
388 handle_type getHandle() const { return pImpl; }
390 enum class DeviceEnumeration
{
391 Basic
= ALC_DEVICE_SPECIFIER
,
392 Full
= ALC_ALL_DEVICES_SPECIFIER
,
393 Capture
= ALC_CAPTURE_DEVICE_SPECIFIER
396 enum class DefaultDeviceType
{
397 Basic
= ALC_DEFAULT_DEVICE_SPECIFIER
,
398 Full
= ALC_DEFAULT_ALL_DEVICES_SPECIFIER
,
399 Capture
= ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
403 * A class managing Device objects and other related functionality. This class
404 * is a singleton, only one instance will exist in a process.
406 class ALURE_API DeviceManager
{
407 ALDeviceManager
*pImpl
;
409 DeviceManager(ALDeviceManager
*impl
) : pImpl(impl
) { }
410 friend class ALDeviceManager
;
413 DeviceManager(const DeviceManager
&) = default;
414 DeviceManager(DeviceManager
&& rhs
) : pImpl(rhs
.pImpl
) { }
416 /** Retrieves the DeviceManager instance. */
417 static DeviceManager
get();
419 /** Queries the existence of a non-device-specific ALC extension. */
420 bool queryExtension(const String
&name
) const;
422 /** Enumerates available device names of the given type. */
423 Vector
<String
> enumerate(DeviceEnumeration type
) const;
424 /** Retrieves the default device of the given type. */
425 String
defaultDeviceName(DefaultDeviceType type
) const;
428 * Opens the playback device given by name, or the default if blank. Throws
429 * an exception on error.
431 Device
openPlayback(const String
&name
=String());
434 * Opens the playback device given by name, or the default if blank.
435 * Returns an empty Device on error.
437 Device
openPlayback(const String
&name
, const std::nothrow_t
&);
439 /** Opens the default playback device. Returns an empty Device on error. */
440 Device
openPlayback(const std::nothrow_t
&);
444 enum class PlaybackName
{
445 Basic
= ALC_DEVICE_SPECIFIER
,
446 Full
= ALC_ALL_DEVICES_SPECIFIER
449 class ALURE_API Device
{
450 MAKE_PIMPL(Device
, ALDevice
)
453 /** Retrieves the device name as given by type. */
454 String
getName(PlaybackName type
=PlaybackName::Full
) const;
455 /** Queries the existence of an ALC extension on this device. */
456 bool queryExtension(const String
&name
) const;
459 * Retrieves the ALC version supported by this device, as constructed by
462 ALCuint
getALCVersion() const;
465 * Retrieves the EFX version supported by this device, as constructed by
466 * MakeVersion. If the ALC_EXT_EFX extension is unsupported, this will be
469 ALCuint
getEFXVersion() const;
471 /** Retrieves the device's playback frequency, in hz. */
472 ALCuint
getFrequency() const;
475 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
476 * is unsupported, this will be 0.
478 ALCuint
getMaxAuxiliarySends() const;
481 * Enumerates available HRTF names. The names are sorted as OpenAL gives
482 * them, such that the index of a given name is the ID to use with
485 * Requires the ALC_SOFT_HRTF extension.
487 Vector
<String
> enumerateHRTFNames() const;
490 * Retrieves whether HRTF is enabled on the device or not.
492 * Requires the ALC_SOFT_HRTF extension.
494 bool isHRTFEnabled() const;
497 * Retrieves the name of the HRTF currently being used by this device.
499 * Requires the ALC_SOFT_HRTF extension.
501 String
getCurrentHRTF() const;
504 * Resets the device, using the specified attributes.
506 * Requires the ALC_SOFT_HRTF extension.
508 void reset(ArrayView
<AttributePair
> attributes
);
511 * Creates a new Context on this device, using the specified attributes.
513 Context
createContext(ArrayView
<AttributePair
> attributes
=ArrayView
<AttributePair
>());
516 * Pauses device processing, stopping updates for its contexts. Multiple
517 * calls are allowed but it is not reference counted, so the device will
518 * resume after one resumeDSP call.
520 * Requires the ALC_SOFT_pause_device extension.
525 * Resumes device processing, restarting updates for its contexts. Multiple
526 * calls are allowed and will no-op.
531 * Closes and frees the device. All previously-created contexts must first
538 enum class DistanceModel
{
539 InverseClamped
= AL_INVERSE_DISTANCE_CLAMPED
,
540 LinearClamped
= AL_LINEAR_DISTANCE_CLAMPED
,
541 ExponentClamped
= AL_EXPONENT_DISTANCE_CLAMPED
,
542 Inverse
= AL_INVERSE_DISTANCE
,
543 Linear
= AL_LINEAR_DISTANCE
,
544 Exponent
= AL_EXPONENT_DISTANCE
,
548 class ALURE_API Context
{
549 MAKE_PIMPL(Context
, ALContext
)
552 /** Makes the specified context current for OpenAL operations. */
553 static void MakeCurrent(Context context
);
554 /** Retrieves the current context used for OpenAL operations. */
555 static Context
GetCurrent();
558 * Makes the specified context current for OpenAL operations on the calling
559 * thread only. Requires the ALC_EXT_thread_local_context extension on both
560 * the context's device and the DeviceManager.
562 static void MakeThreadCurrent(Context context
);
563 /** Retrieves the thread-specific context used for OpenAL operations. */
564 static Context
GetThreadCurrent();
567 * Destroys the context. The context must not be current when this is
572 /** Retrieves the Device this context was created from. */
579 * Retrieves a Listener instance for this context. Each context will only
582 Listener
getListener();
585 * Sets a MessageHandler instance which will be used to provide certain
586 * messages back to the application. Only one handler may be set for a
587 * context at a time. The previously set handler will be returned.
589 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
591 /** Gets the currently-set message handler. */
592 SharedPtr
<MessageHandler
> getMessageHandler() const;
595 * Specifies the desired interval that the background thread will be woken
596 * up to process tasks, e.g. keeping streaming sources filled. An interval
597 * of 0 means the background thread will only be woken up manually with
598 * calls to update. The default is 0.
600 void setAsyncWakeInterval(std::chrono::milliseconds msec
);
603 * Retrieves the current interval used for waking up the background thread.
605 std::chrono::milliseconds
getAsyncWakeInterval() const;
607 // Functions below require the context to be current
610 * Creates a Decoder instance for the given audio file or resource name.
612 SharedPtr
<Decoder
> createDecoder(const String
&name
);
615 * Queries if the channel configuration and sample type are supported by
618 bool isSupported(ChannelConfig channels
, SampleType type
) const;
621 * Queries the list of resamplers supported by the context. If the
622 * AL_SOFT_source_resampler extension is unsupported this will be an empty
623 * vector, otherwise there will be at least one entry.
625 const Vector
<String
> &getAvailableResamplers();
627 * Queries the context's default resampler index. Be aware, if the
628 * AL_SOFT_source_resampler extension is unsupported the resampler list
629 * will be empty and this will resturn 0. If you try to access the
630 * resampler list with this index without the extension, undefined behavior
631 * (accessing an out of bounds array index) will occur.
633 ALsizei
getDefaultResamplerIndex() const;
636 * Creates and caches a Buffer for the given audio file or resource name.
637 * Multiple calls with the same name will return the same Buffer object.
639 Buffer
getBuffer(const String
&name
);
642 * Creates and caches a Buffer for the given audio file or resource name.
643 * Multiple calls with the same name will return the same Buffer object.
645 * The returned Buffer object will be scheduled for loading asynchronously,
646 * and must be checked with a call to Buffer::getLoadStatus prior to being
649 Buffer
getBufferAsync(const String
&name
);
652 * Creates and caches a Buffer using the given name. The name may alias an
653 * audio file, but it must not currently exist in the buffer cache. As with
654 * other cached buffers, removeBuffer must be used to remove it from the
657 Buffer
createBufferFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
660 * Creates and caches a Buffer using the given name. The name may alias an
661 * audio file, but it must not currently exist in the buffer cache.
663 * The returned Buffer object will be scheduled for loading asynchronously,
664 * and must be checked with a call to Buffer::getLoadStatus prior to being
665 * played. The given decoder will be held on to and used asynchronously to
666 * load the buffer. The decoder must not have its read or seek methods
667 * called while the buffer load status is pending.
669 Buffer
createBufferAsyncFrom(const String
&name
, SharedPtr
<Decoder
> decoder
);
672 * Deletes the cached Buffer object for the given audio file or
673 * resource name. The buffer must not be in use by a Source.
675 void removeBuffer(const String
&name
);
677 * Deletes the given cached buffer. The buffer must not be in use by a
680 void removeBuffer(Buffer buffer
);
683 * Creates a new Source. There is no practical limit to the number of
684 * sources you may create.
686 Source
createSource();
688 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
690 Effect
createEffect();
692 SourceGroup
createSourceGroup(String name
);
693 SourceGroup
getSourceGroup(const String
&name
);
695 /** Sets the doppler factor to apply to all source calculations. */
696 void setDopplerFactor(ALfloat factor
);
699 * Sets the speed of sound propogation, in units per second, to calculate
700 * the doppler effect along with other distance-related time effects. The
701 * default is 343.3 units per second (a realistic speed assuming 1 meter
704 void setSpeedOfSound(ALfloat speed
);
706 void setDistanceModel(DistanceModel model
);
709 * Updates the context and all sources belonging to this context (you do
710 * not need to call the individual sources' update method if you call this
716 class ALURE_API Listener
{
717 MAKE_PIMPL(Listener
, ALListener
)
720 /** Sets the "master" gain for all context output. */
721 void setGain(ALfloat gain
);
724 * Specifies the listener's 3D position, velocity, and orientation
727 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
729 /** Specifies the listener's 3D position. */
730 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
731 void setPosition(const ALfloat
*pos
);
734 * Specifies the listener's 3D velocity, in units per second. As with
735 * OpenAL, this does not actually alter the listener's position, and
736 * instead just alters the pitch as determined by the doppler effect.
738 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
739 void setVelocity(const ALfloat
*vel
);
742 * Specifies the listener's 3D orientation, using position-relative 'at'
743 * and 'up' direction vectors.
745 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
746 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
747 void setOrientation(const ALfloat
*ori
);
750 * Sets the number of meters per unit, used for various effects that rely
751 * on the distance in meters (including air absorption and initial reverb
752 * decay). If this is changed, it's strongly recommended to also set the
753 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
754 * realistic 343.3m/s for sound propgation).
756 void setMetersPerUnit(ALfloat m_u
);
760 enum class BufferLoadStatus
{
765 class ALURE_API Buffer
{
766 MAKE_PIMPL(Buffer
, ALBuffer
)
770 * Retrieves the length of the buffer in sample frames. The buffer must be
771 * fully loaded before this method is called.
773 ALuint
getLength() const;
775 /** Retrieves the buffer's frequency in hz. */
776 ALuint
getFrequency() const;
778 /** Retrieves the buffer's sample configuration. */
779 ChannelConfig
getChannelConfig() const;
781 /** Retrieves the buffer's sample type. */
782 SampleType
getSampleType() const;
785 * Retrieves the storage size used by the buffer, in bytes. The buffer must
786 * be fully loaded before this method is called.
788 ALuint
getSize() const;
791 * Sets the buffer's loop points, used for looping sources. If the current
792 * context does not support the AL_SOFT_loop_points extension, start and
793 * end must be 0 and getLength() respectively. Otherwise, start must be
794 * less than end, and end must be less than or equal to getLength().
796 * The buffer must not be in use when this method is called, and the buffer
797 * must be fully loaded.
799 * \param start The starting point, in sample frames (inclusive).
800 * \param end The ending point, in sample frames (exclusive).
802 void setLoopPoints(ALuint start
, ALuint end
);
805 * Retrieves the current loop points as a [start,end) pair. The buffer must
806 * be fully loaded before this method is called.
808 std::pair
<ALuint
,ALuint
> getLoopPoints() const;
811 * Retrieves the Source objects currently playing the buffer. Stopping the
812 * returned sources will allow the buffer to be removed from the context.
814 Vector
<Source
> getSources() const;
817 * Queries the buffer's load status. A return of BufferLoadStatus::Pending
818 * indicates the buffer is not finished loading and can't be used with a
819 * call to Source::play. Buffers created with Context::getBuffer will
820 * always return BufferLoadStatus::Ready.
822 BufferLoadStatus
getLoadStatus();
824 /** Retrieves the name the buffer was created with. */
825 const String
&getName() const;
827 /** Queries if the buffer is in use and can't be removed. */
828 bool isInUse() const;
832 enum class Spatialize
{
835 Auto
= 0x0002 /* AL_AUTO_SOFT */
838 class ALURE_API Source
{
839 MAKE_PIMPL(Source
, ALSource
)
843 * Plays the source using buffer. The same buffer may be played from
844 * multiple sources simultaneously.
846 void play(Buffer buffer
);
848 * Plays the source by streaming audio from decoder. This will use
849 * queuesize buffers, each with updatelen sample frames. The given decoder
850 * must *NOT* have its read or seek methods called from elsewhere while in
853 void play(SharedPtr
<Decoder
> decoder
, ALuint updatelen
, ALuint queuesize
);
855 * Stops playback, releasing the buffer or decoder reference.
859 /** Pauses the source if it is playing. */
862 /** Resumes the source if it is paused. */
865 /** Specifies if the source is currently playing. */
866 bool isPlaying() const;
868 /** Specifies if the source is currently paused. */
869 bool isPaused() const;
872 * Specifies the source's playback priority. Lowest priority sources will
873 * be evicted first when higher priority sources are played.
875 void setPriority(ALuint priority
);
876 /** Retrieves the source's priority. */
877 ALuint
getPriority() const;
880 * Sets the source's offset, in sample frames. If the source is playing or
881 * paused, it will go to that offset immediately, otherwise the source will
882 * start at the specified offset the next time it's played.
884 void setOffset(uint64_t offset
);
886 * Retrieves the source offset in sample frames and its latency in nano-
887 * seconds. For streaming sources, this will be the offset from the
888 * beginning of the stream based on the decoder's reported position.
890 * If the AL_SOFT_source_latency extension is unsupported, the latency will
893 std::pair
<uint64_t,std::chrono::nanoseconds
> getSampleOffsetLatency() const;
894 uint64_t getSampleOffset() const { return std::get
<0>(getSampleOffsetLatency()); }
896 * Retrieves the source offset and latency in seconds. For streaming
897 * sources, this will be the offset from the beginning of the stream based
898 * on the decoder's reported position.
900 * If the AL_SOFT_source_latency extension is unsupported, the latency will
903 std::pair
<Seconds
,Seconds
> getSecOffsetLatency() const;
904 Seconds
getSecOffset() const { return std::get
<0>(getSecOffsetLatency()); }
907 * Specifies if the source should loop on the Buffer or Decoder object's
910 void setLooping(bool looping
);
911 bool getLooping() const;
914 * Specifies a linear pitch shift base. A value of 1.0 is the default
917 void setPitch(ALfloat pitch
);
918 ALfloat
getPitch() const;
921 * Specifies the base linear gain. A value of 1.0 is the default normal
924 void setGain(ALfloat gain
);
925 ALfloat
getGain() const;
928 * Specifies the minimum and maximum gain. The source's gain is clamped to
929 * this range after distance attenuation and cone attenuation are applied
930 * to the gain base, although before the filter gain adjustements.
932 void setGainRange(ALfloat mingain
, ALfloat maxgain
);
933 std::pair
<ALfloat
,ALfloat
> getGainRange() const;
934 ALfloat
getMinGain() const { return std::get
<0>(getGainRange()); }
935 ALfloat
getMaxGain() const { return std::get
<1>(getGainRange()); }
938 * Specifies the reference distance and maximum distance the source will
939 * use for the current distance model. For Clamped distance models, the
940 * source's calculated distance is clamped to the specified range before
941 * applying distance-related attenuation.
943 * For all distance models, the reference distance is the distance at which
944 * the source's volume will not have any extra attenuation (an effective
945 * gain multiplier of 1).
947 void setDistanceRange(ALfloat refdist
, ALfloat maxdist
);
948 std::pair
<ALfloat
,ALfloat
> getDistanceRange() const;
949 ALfloat
getReferenceDistance() const { return std::get
<0>(getDistanceRange()); }
950 ALfloat
getMaxDistance() const { return std::get
<1>(getDistanceRange()); }
952 /** Specifies the source's 3D position, velocity, and direction together. */
953 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const Vector3
&direction
);
955 /** Specifies the source's 3D position, velocity, and orientation together. */
956 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, std::pair
<Vector3
,Vector3
> orientation
);
958 /** Specifies the source's 3D position. */
959 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
960 void setPosition(const ALfloat
*pos
);
961 Vector3
getPosition() const;
964 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
965 * this does not actually alter the source's position, and instead just
966 * alters the pitch as determined by the doppler effect.
968 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
969 void setVelocity(const ALfloat
*vel
);
970 Vector3
getVelocity() const;
973 * Specifies the source's 3D facing direction. Deprecated in favor of
976 void setDirection(ALfloat x
, ALfloat y
, ALfloat z
);
977 void setDirection(const ALfloat
*dir
);
978 Vector3
getDirection() const;
981 * Specifies the source's 3D orientation. Note: unlike the AL_EXT_BFORMAT
982 * extension this property comes from, this also affects the facing
983 * direction, superceding setDirection.
985 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
986 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
987 void setOrientation(const ALfloat
*ori
);
988 std::pair
<Vector3
,Vector3
> getOrientation() const;
991 * Specifies the source's cone angles, in degrees. The inner angle is the
992 * area within which the listener will hear the source with no extra
993 * attenuation, while the listener being outside of the outer angle will
994 * hear the source attenuated according to the outer cone gains.
996 void setConeAngles(ALfloat inner
, ALfloat outer
);
997 std::pair
<ALfloat
,ALfloat
> getConeAngles() const;
998 ALfloat
getInnerConeAngle() const { return std::get
<0>(getConeAngles()); }
999 ALfloat
getOuterConeAngle() const { return std::get
<1>(getConeAngles()); }
1002 * Specifies the linear gain multiplier when the listener is outside of the
1003 * source's outer cone area. The specified gain applies to all frequencies,
1004 * while gainhf applies extra attenuation to high frequencies.
1006 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1008 void setOuterConeGains(ALfloat gain
, ALfloat gainhf
=1.0f
);
1009 std::pair
<ALfloat
,ALfloat
> getOuterConeGains() const;
1010 ALfloat
getOuterConeGain() const { return std::get
<0>(getOuterConeGains()); }
1011 ALfloat
getOuterConeGainHF() const { return std::get
<1>(getOuterConeGains()); }
1014 * Specifies the rolloff factors for the direct and send paths. This is
1015 * effectively a distance scaling relative to the reference distance. Note:
1016 * the room rolloff factor is 0 by default, disabling distance attenuation
1017 * for send paths. This is because the reverb engine will, by default,
1018 * apply a more realistic room attenuation based on the reverb decay time
1019 * and direct path attenuation.
1021 void setRolloffFactors(ALfloat factor
, ALfloat roomfactor
=0.0f
);
1022 std::pair
<ALfloat
,ALfloat
> getRolloffFactors() const;
1023 ALfloat
getRolloffFactor() const { return std::get
<0>(getRolloffFactors()); }
1024 ALfloat
getRoomRolloffFactor() const { return std::get
<1>(getRolloffFactors()); }
1027 * Specifies the doppler factor for the doppler effect's pitch shift. This
1028 * effectively scales the source and listener velocities for the doppler
1031 void setDopplerFactor(ALfloat factor
);
1032 ALfloat
getDopplerFactor() const;
1034 /** Specifies if the source properties are relative to the listener. */
1035 void setRelative(bool relative
);
1036 bool getRelative() const;
1039 * Specifies the source's radius. This causes the source to behave as if
1040 * every point within the spherical area emits sound.
1042 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1044 void setRadius(ALfloat radius
);
1045 ALfloat
getRadius() const;
1048 * Specifies the left and right channel angles, in radians, when playing a
1049 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1050 * in front and positive values going left.
1052 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1054 void setStereoAngles(ALfloat leftAngle
, ALfloat rightAngle
);
1055 std::pair
<ALfloat
,ALfloat
> getStereoAngles() const;
1057 void set3DSpatialize(Spatialize spatialize
);
1058 Spatialize
get3DSpatialize() const;
1060 void setResamplerIndex(ALsizei index
);
1061 ALsizei
getResamplerIndex() const;
1063 void setAirAbsorptionFactor(ALfloat factor
);
1064 ALfloat
getAirAbsorptionFactor() const;
1066 void setGainAuto(bool directhf
, bool send
, bool sendhf
);
1067 std::tuple
<bool,bool,bool> getGainAuto() const;
1068 bool getDirectGainHFAuto() const { return std::get
<0>(getGainAuto()); }
1069 bool getSendGainAuto() const { return std::get
<1>(getGainAuto()); }
1070 bool getSendGainHFAuto() const { return std::get
<2>(getGainAuto()); }
1072 /** Sets the filter properties on the direct path signal. */
1073 void setDirectFilter(const FilterParams
&filter
);
1075 * Sets the filter properties on the given send path signal. Any auxiliary
1076 * effect slot on the send path remains in place.
1078 void setSendFilter(ALuint send
, const FilterParams
&filter
);
1080 * Connects the effect slot to the given send path. Any filter properties
1081 * on the send path remain as they were.
1083 void setAuxiliarySend(AuxiliaryEffectSlot slot
, ALuint send
);
1085 * Connects the effect slot to the given send path, using the filter
1088 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot
, ALuint send
, const FilterParams
&filter
);
1091 * Releases the source, stopping playback, releasing resources, and
1092 * returning it to the system.
1098 class ALURE_API SourceGroup
{
1099 MAKE_PIMPL(SourceGroup
, ALSourceGroup
)
1102 /** Retrieves the associated name of the source group. */
1103 const String
&getName() const;
1106 * Adds source to the source group. A source may only be part of one group
1107 * at a time, and will automatically be removed from its current group as
1110 void addSource(Source source
);
1111 /** Removes source from the source group. */
1112 void removeSource(Source source
);
1114 /** Adds a list of sources to the group at once. */
1115 void addSources(ArrayView
<Source
> sources
);
1116 /** Removes a list of sources from the source group. */
1117 void removeSources(ArrayView
<Source
> sources
);
1120 * Adds group as a subgroup of the source group. This method will throw an
1121 * exception if group is being added to a group it has as a sub-group (i.e.
1122 * it would create a circular sub-group chain).
1124 void addSubGroup(SourceGroup group
);
1125 /** Removes group from the source group. */
1126 void removeSubGroup(SourceGroup group
);
1128 /** Returns the list of sources currently in the group. */
1129 Vector
<Source
> getSources() const;
1131 /** Returns the list of subgroups currently in the group. */
1132 Vector
<SourceGroup
> getSubGroups() const;
1134 /** Sets the source group gain, which accumulates with its sources. */
1135 void setGain(ALfloat gain
);
1136 /** Gets the source group gain. */
1137 ALfloat
getGain() const;
1139 /** Sets the source group pitch, which accumulates with its sources. */
1140 void setPitch(ALfloat pitch
);
1141 /** Gets the source group pitch. */
1142 ALfloat
getPitch() const;
1145 * Pauses all currently-playing sources that are under this group,
1146 * including sub-groups.
1148 void pauseAll() const;
1150 * Resumes all paused sources that are under this group, including
1153 void resumeAll() const;
1155 /** Stops all sources that are under this group, including sub-groups. */
1156 void stopAll() const;
1159 * Releases the source group, removing all sources from it before being
1171 class ALURE_API AuxiliaryEffectSlot
{
1172 MAKE_PIMPL(AuxiliaryEffectSlot
, ALAuxiliaryEffectSlot
)
1175 void setGain(ALfloat gain
);
1177 * If set to true, the reverb effect will automatically apply adjustments
1178 * to the source's send slot based on the effect properties.
1180 * Has no effect when using non-reverb effects. Default is true.
1182 void setSendAuto(bool sendauto
);
1185 * Updates the effect slot with a new effect. The given effect object may
1186 * be altered or destroyed without affecting the effect slot.
1188 void applyEffect(Effect effect
);
1191 * Releases the effect slot, returning it to the system. It must not be in
1197 * Retrieves each Source object and its pairing send this effect slot is
1198 * set on. Setting a different (or null) effect slot on each source's given
1199 * send will allow the effect slot to be released.
1201 Vector
<SourceSend
> getSourceSends() const;
1203 /** Determines if the effect slot is in use by a source. */
1204 bool isInUse() const;
1208 class ALURE_API Effect
{
1209 MAKE_PIMPL(Effect
, ALEffect
)
1213 * Updates the effect with the specified reverb properties. If the
1214 * EAXReverb effect is not supported, it will automatically attempt to
1215 * downgrade to the Standard Reverb effect.
1217 void setReverbProperties(const EFXEAXREVERBPROPERTIES
&props
);
1224 * Audio decoder interface. Applications may derive from this, implementing the
1225 * necessary methods, and use it in places the API wants a Decoder object.
1227 class ALURE_API Decoder
{
1231 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1232 virtual ALuint
getFrequency() const = 0;
1233 /** Retrieves the channel configuration of the audio being decoded. */
1234 virtual ChannelConfig
getChannelConfig() const = 0;
1235 /** Retrieves the sample type of the audio being decoded. */
1236 virtual SampleType
getSampleType() const = 0;
1239 * Retrieves the total length of the audio, in sample frames. If unknown,
1240 * returns 0. Note that if the returned length is 0, the decoder may not be
1241 * used to load a Buffer.
1243 virtual uint64_t getLength() const = 0;
1245 * Seek to pos, specified in sample frames. Returns true if the seek was
1248 virtual bool seek(uint64_t pos
) = 0;
1251 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1252 * start >= end, use all available data.
1254 virtual std::pair
<uint64_t,uint64_t> getLoopPoints() const = 0;
1257 * Decodes count sample frames, writing them to ptr, and returns the number
1258 * of sample frames written. Returning less than the requested count
1259 * indicates the end of the audio.
1261 virtual ALuint
read(ALvoid
*ptr
, ALuint count
) = 0;
1265 * Audio decoder factory interface. Applications may derive from this,
1266 * implementing the necessary methods, and use it in places the API wants a
1267 * DecoderFactory object.
1269 class ALURE_API DecoderFactory
{
1271 virtual ~DecoderFactory();
1274 * Creates and returns a Decoder instance for the given resource file. If
1275 * the decoder needs to retain the file handle for reading as-needed, it
1276 * should move the UniquePtr to internal storage.
1278 * \return nullptr if a decoder can't be created from the file.
1280 virtual SharedPtr
<Decoder
> createDecoder(UniquePtr
<std::istream
> &file
) = 0;
1284 * Registers a decoder factory for decoding audio. Registered factories are
1285 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1286 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1287 * name1 < name2. Internal decoder factories are always used after registered
1290 * Alure retains a reference to the DecoderFactory instance and will release it
1291 * (potentially destroying the object) when the library unloads.
1293 * \param name A unique name identifying this decoder factory.
1294 * \param factory A DecoderFactory instance used to create Decoder instances.
1296 ALURE_API
void RegisterDecoder(const String
&name
, UniquePtr
<DecoderFactory
> factory
);
1299 * Unregisters a decoder factory by name. Alure returns the instance back to
1302 * \param name The unique name identifying a previously-registered decoder
1305 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1306 * decoder factory with the given name doesn't exist.
1308 ALURE_API UniquePtr
<DecoderFactory
> UnregisterDecoder(const String
&name
);
1312 * A file I/O factory interface. Applications may derive from this and set an
1313 * instance to be used by the audio decoders. By default, the library uses
1316 class ALURE_API FileIOFactory
{
1319 * Sets the factory instance to be used by the audio decoders. If a
1320 * previous factory was set, it's returned to the application. Passing in a
1321 * NULL factory reverts to the default.
1323 static UniquePtr
<FileIOFactory
> set(UniquePtr
<FileIOFactory
> factory
);
1326 * Gets the current FileIOFactory instance being used by the audio
1329 static FileIOFactory
&get();
1331 virtual ~FileIOFactory();
1333 /** Opens a read-only binary file for the given name. */
1334 virtual UniquePtr
<std::istream
> openFile(const String
&name
) = 0;
1339 * A message handler interface. Applications may derive from this and set an
1340 * instance on a context to receive messages. The base methods are no-ops, so
1341 * derived classes only need to implement methods for relevant messages.
1343 * It's recommended that applications mark their handler methods using the
1344 * override keyword, to ensure they're properly overriding the base methods in
1347 class ALURE_API MessageHandler
{
1349 virtual ~MessageHandler();
1352 * Called when the given device has been disconnected and is no longer
1353 * usable for output. As per the ALC_EXT_disconnect specification,
1354 * disconnected devices remain valid, however all playing sources are
1355 * automatically stopped, any sources that are attempted to play will
1356 * immediately stop, and new contexts may not be created on the device.
1358 * Note that connection status is checked during Context::update calls, so
1359 * that method must be called regularly to be notified when a device is
1360 * disconnected. This method may not be called if the device lacks support
1361 * for the ALC_EXT_disconnect extension.
1363 * WARNING: Do not attempt to clean up resources within this callback
1364 * method, as Alure is in the middle of doing updates. Instead, flag the
1365 * device as having been lost and do cleanup later.
1367 virtual void deviceDisconnected(Device device
);
1370 * Called when the given source reaches the end of the buffer or stream.
1372 * Sources that stopped automatically will be detected upon a call to
1373 * Context::update or Source::update.
1375 virtual void sourceStopped(Source source
);
1378 * Called when the given source was forced to stop. This can be because
1379 * either there were no more system sources and a higher-priority source
1380 * needs to play, or it's part of a SourceGroup (or sub-group thereof) that
1381 * had its SourceGroup::stopAll method called.
1383 virtual void sourceForceStopped(Source source
);
1386 * Called when a new buffer is about to be created and loaded. May be
1387 * called asynchronously for buffers being loaded asynchronously.
1389 * \param name The resource name, as passed to Context::getBuffer.
1390 * \param channels Channel configuration of the given audio data.
1391 * \param type Sample type of the given audio data.
1392 * \param samplerate Sample rate of the given audio data.
1393 * \param data The audio data that is about to be fed to the OpenAL buffer.
1395 virtual void bufferLoading(const String
&name
, ChannelConfig channels
, SampleType type
, ALuint samplerate
, const Vector
<ALbyte
> &data
);
1398 * Called when a resource isn't found, allowing the app to substitute in a
1399 * different resource. For buffers created with Context::getBuffer or
1400 * Context::getBufferAsync, the original name will still be used for the
1401 * cache map so the app doesn't have to keep track of substituted resource
1404 * This will be called again if the new name isn't found.
1406 * \param name The resource name that was not found.
1407 * \return The replacement resource name to use instead. Returning an empty
1408 * string means to stop trying.
1410 virtual String
resourceNotFound(const String
&name
);
1415 } // namespace alure
1417 #endif /* AL_ALURE2_H */