8 #include "alure2-alext.h"
10 #include "alure2-aliases.h"
11 #include "alure2-typeviews.h"
14 #if defined(ALURE_STATIC_LIB)
17 #define ALURE_API __declspec(dllimport)
18 #elif defined(__GNUC__)
19 #define ALURE_API __attribute__((visibility("default")))
20 #elif defined(__has_attribute)
21 #if __has_attribute(visibility)
22 #define ALURE_API __attribute__((visibility("default")))
29 #endif /* ALURE_API */
31 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
32 #define EFXEAXREVERBPROPERTIES_DEFINED
42 float flReflectionsGain
;
43 float flReflectionsDelay
;
44 float flReflectionsPan
[3];
45 float flLateReverbGain
;
46 float flLateReverbDelay
;
47 float flLateReverbPan
[3];
50 float flModulationTime
;
51 float flModulationDepth
;
52 float flAirAbsorptionGainHF
;
55 float flRoomRolloffFactor
;
57 } EFXEAXREVERBPROPERTIES
, *LPEFXEAXREVERBPROPERTIES
;
62 // Available class interfaces.
70 class AuxiliaryEffectSlot
;
76 // Opaque class implementations.
77 class DeviceManagerImpl
;
83 class SourceGroupImpl
;
84 class AuxiliaryEffectSlotImpl
;
87 /** Convert a value from decibels to linear gain. */
88 template<typename T
, typename NonRefT
=RemoveRefT
<T
>,
89 typename
=EnableIfT
<std::is_floating_point
<NonRefT
>::value
>>
90 constexpr inline NonRefT
dBToLinear(T
&& value
)
91 { return std::pow(NonRefT(10.0), std::forward
<T
>(value
) / NonRefT(20.0)); }
93 /** Convert a value from linear gain to decibels. */
94 template<typename T
, typename NonRefT
=RemoveRefT
<T
>,
95 typename
=EnableIfT
<std::is_floating_point
<NonRefT
>::value
>>
96 constexpr inline NonRefT
LinearTodB(T
&& value
)
97 { return std::log10(std::forward
<T
>(value
)) * NonRefT(20.0); }
100 * An attribute pair, for passing attributes to Device::createContext and
103 using AttributePair
= std::pair
<ALCint
,ALCint
>;
104 static_assert(sizeof(AttributePair
) == sizeof(ALCint
[2]), "Bad AttributePair size");
105 inline AttributePair
AttributesEnd() noexcept
{ return std::make_pair(0, 0); }
108 struct FilterParams
{
110 ALfloat mGainHF
; // For low-pass and band-pass filters
111 ALfloat mGainLF
; // For high-pass and band-pass filters
116 Array
<ALfloat
,3> mValue
;
119 constexpr Vector3() noexcept
120 : mValue
{{0.0f
, 0.0f
, 0.0f
}}
122 constexpr Vector3(const Vector3
&rhs
) noexcept
123 : mValue
{{rhs
.mValue
[0], rhs
.mValue
[1], rhs
.mValue
[2]}}
125 constexpr Vector3(ALfloat val
) noexcept
126 : mValue
{{val
, val
, val
}}
128 constexpr Vector3(ALfloat x
, ALfloat y
, ALfloat z
) noexcept
131 Vector3(const ALfloat
*vec
) noexcept
132 : mValue
{{vec
[0], vec
[1], vec
[2]}}
135 const ALfloat
*getPtr() const noexcept
136 { return mValue
.data(); }
138 ALfloat
& operator[](size_t i
) noexcept
139 { return mValue
[i
]; }
140 constexpr const ALfloat
& operator[](size_t i
) const noexcept
141 { return mValue
[i
]; }
143 #define ALURE_DECL_OP(op) \
144 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
146 return Vector3(mValue[0] op rhs.mValue[0], \
147 mValue[1] op rhs.mValue[1], \
148 mValue[2] op rhs.mValue[2]); \
155 #define ALURE_DECL_OP(op) \
156 Vector3& operator op(const Vector3 &rhs) noexcept \
158 mValue[0] op rhs.mValue[0]; \
159 mValue[1] op rhs.mValue[1]; \
160 mValue[2] op rhs.mValue[2]; \
169 #define ALURE_DECL_OP(op) \
170 constexpr Vector3 operator op(ALfloat scale) const noexcept \
172 return Vector3(mValue[0] op scale, \
173 mValue[1] op scale, \
174 mValue[2] op scale); \
179 #define ALURE_DECL_OP(op) \
180 Vector3& operator op(ALfloat scale) noexcept \
182 mValue[0] op scale; \
183 mValue[1] op scale; \
184 mValue[2] op scale; \
191 constexpr ALfloat
getLengthSquared() const noexcept
192 { return mValue
[0]*mValue
[0] + mValue
[1]*mValue
[1] + mValue
[2]*mValue
[2]; }
193 ALfloat
getLength() const noexcept
194 { return std::sqrt(getLengthSquared()); }
196 constexpr ALfloat
getDistanceSquared(const Vector3
&pos
) const noexcept
197 { return (pos
- *this).getLengthSquared(); }
198 ALfloat
getDistance(const Vector3
&pos
) const noexcept
199 { return (pos
- *this).getLength(); }
201 static_assert(sizeof(Vector3
) == sizeof(ALfloat
[3]), "Bad Vector3 size");
204 enum class SampleType
{
210 ALURE_API
const char *GetSampleTypeName(SampleType type
);
212 enum class ChannelConfig
{
213 /** 1-channel mono sound. */
215 /** 2-channel stereo sound. */
217 /** 2-channel rear sound (back-left and back-right). */
219 /** 4-channel surround sound. */
221 /** 5.1 surround sound. */
223 /** 6.1 surround sound. */
225 /** 7.1 surround sound. */
227 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
229 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
232 ALURE_API
const char *GetChannelConfigName(ChannelConfig cfg
);
234 ALURE_API ALuint
FramesToBytes(ALuint frames
, ChannelConfig chans
, SampleType type
);
235 ALURE_API ALuint
BytesToFrames(ALuint bytes
, ChannelConfig chans
, SampleType type
);
238 /** Class for storing a major.minor version number. */
244 constexpr Version() noexcept
: mMajor(0), mMinor(0) { }
245 constexpr Version(ALuint _maj
, ALuint _min
) noexcept
: mMajor(_maj
), mMinor(_min
) { }
246 constexpr Version(const Version
&) noexcept
= default;
248 constexpr ALuint
getMajor() const noexcept
{ return mMajor
; }
249 constexpr ALuint
getMinor() const noexcept
{ return mMinor
; }
250 constexpr bool isZero() const noexcept
{ return mMajor
== 0 && mMinor
== 0; }
253 #define MAKE_PIMPL(BaseT, ImplT) \
258 using handle_type = ImplT*; \
260 BaseT() : pImpl(nullptr) { } \
261 BaseT(ImplT *impl) : pImpl(impl) { } \
262 BaseT(const BaseT&) = default; \
263 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
265 BaseT& operator=(const BaseT&) = default; \
266 BaseT& operator=(BaseT&& rhs) \
268 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
272 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
273 bool operator!=(const BaseT &rhs) const { return pImpl != rhs.pImpl; } \
274 bool operator<=(const BaseT &rhs) const { return pImpl <= rhs.pImpl; } \
275 bool operator>=(const BaseT &rhs) const { return pImpl >= rhs.pImpl; } \
276 bool operator<(const BaseT &rhs) const { return pImpl < rhs.pImpl; } \
277 bool operator>(const BaseT &rhs) const { return pImpl > rhs.pImpl; } \
279 operator bool() const { return !!pImpl; } \
281 handle_type getHandle() const { return pImpl; }
283 enum class DeviceEnumeration
{
284 Basic
= ALC_DEVICE_SPECIFIER
,
285 Full
= ALC_ALL_DEVICES_SPECIFIER
,
286 Capture
= ALC_CAPTURE_DEVICE_SPECIFIER
289 enum class DefaultDeviceType
{
290 Basic
= ALC_DEFAULT_DEVICE_SPECIFIER
,
291 Full
= ALC_DEFAULT_ALL_DEVICES_SPECIFIER
,
292 Capture
= ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
296 * A class managing Device objects and other related functionality. This class
297 * is a singleton, only one instance will exist in a process.
299 class ALURE_API DeviceManager
{
300 DeviceManagerImpl
*pImpl
;
302 DeviceManager(DeviceManagerImpl
*impl
) : pImpl(impl
) { }
303 friend class ALDeviceManager
;
306 DeviceManager(const DeviceManager
&) = default;
307 DeviceManager(DeviceManager
&& rhs
) : pImpl(rhs
.pImpl
) { }
309 /** Retrieves the DeviceManager instance. */
310 static DeviceManager
get();
312 /** Queries the existence of a non-device-specific ALC extension. */
313 bool queryExtension(const String
&name
) const;
314 bool queryExtension(const char *name
) const;
316 /** Enumerates available device names of the given type. */
317 Vector
<String
> enumerate(DeviceEnumeration type
) const;
318 /** Retrieves the default device of the given type. */
319 String
defaultDeviceName(DefaultDeviceType type
) const;
322 * Opens the playback device given by name, or the default if blank. Throws
323 * an exception on error.
325 Device
openPlayback(const String
&name
={});
326 Device
openPlayback(const char *name
);
329 * Opens the playback device given by name, or the default if blank.
330 * Returns an empty Device on error.
332 Device
openPlayback(const String
&name
, const std::nothrow_t
&);
333 Device
openPlayback(const char *name
, const std::nothrow_t
&);
335 /** Opens the default playback device. Returns an empty Device on error. */
336 Device
openPlayback(const std::nothrow_t
&);
340 enum class PlaybackName
{
341 Basic
= ALC_DEVICE_SPECIFIER
,
342 Full
= ALC_ALL_DEVICES_SPECIFIER
345 class ALURE_API Device
{
346 MAKE_PIMPL(Device
, DeviceImpl
)
349 /** Retrieves the device name as given by type. */
350 String
getName(PlaybackName type
=PlaybackName::Full
) const;
351 /** Queries the existence of an ALC extension on this device. */
352 bool queryExtension(const String
&name
) const;
353 bool queryExtension(const char *name
) const;
355 /** Retrieves the ALC version supported by this device. */
356 Version
getALCVersion() const;
359 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
360 * extension is unsupported, this will be 0.0.
362 Version
getEFXVersion() const;
364 /** Retrieves the device's playback frequency, in hz. */
365 ALCuint
getFrequency() const;
368 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
369 * is unsupported, this will be 0.
371 ALCuint
getMaxAuxiliarySends() const;
374 * Enumerates available HRTF names. The names are sorted as OpenAL gives
375 * them, such that the index of a given name is the ID to use with
378 * Requires the ALC_SOFT_HRTF extension.
380 Vector
<String
> enumerateHRTFNames() const;
383 * Retrieves whether HRTF is enabled on the device or not.
385 * Requires the ALC_SOFT_HRTF extension.
387 bool isHRTFEnabled() const;
390 * Retrieves the name of the HRTF currently being used by this device.
392 * Requires the ALC_SOFT_HRTF extension.
394 String
getCurrentHRTF() const;
397 * Resets the device, using the specified attributes.
399 * Requires the ALC_SOFT_HRTF extension.
401 void reset(ArrayView
<AttributePair
> attributes
);
404 * Creates a new Context on this device, using the specified attributes.
405 * Throws an exception if context creation fails.
407 Context
createContext(ArrayView
<AttributePair
> attributes
={});
409 * Creates a new Context on this device, using the specified attributes.
410 * Returns an empty Context if context creation fails.
412 Context
createContext(ArrayView
<AttributePair
> attributes
, const std::nothrow_t
&);
413 Context
createContext(const std::nothrow_t
&);
416 * Pauses device processing, stopping updates for its contexts. Multiple
417 * calls are allowed but it is not reference counted, so the device will
418 * resume after one resumeDSP call.
420 * Requires the ALC_SOFT_pause_device extension.
425 * Resumes device processing, restarting updates for its contexts. Multiple
426 * calls are allowed and will no-op.
431 * Closes and frees the device. All previously-created contexts must first
438 enum class DistanceModel
{
439 InverseClamped
= AL_INVERSE_DISTANCE_CLAMPED
,
440 LinearClamped
= AL_LINEAR_DISTANCE_CLAMPED
,
441 ExponentClamped
= AL_EXPONENT_DISTANCE_CLAMPED
,
442 Inverse
= AL_INVERSE_DISTANCE
,
443 Linear
= AL_LINEAR_DISTANCE
,
444 Exponent
= AL_EXPONENT_DISTANCE
,
448 class ALURE_API Context
{
449 MAKE_PIMPL(Context
, ContextImpl
)
452 /** Makes the specified context current for OpenAL operations. */
453 static void MakeCurrent(Context context
);
454 /** Retrieves the current context used for OpenAL operations. */
455 static Context
GetCurrent();
458 * Makes the specified context current for OpenAL operations on the calling
459 * thread only. Requires the ALC_EXT_thread_local_context extension on both
460 * the context's device and the DeviceManager.
462 static void MakeThreadCurrent(Context context
);
463 /** Retrieves the thread-specific context used for OpenAL operations. */
464 static Context
GetThreadCurrent();
467 * Destroys the context. The context must not be current when this is
472 /** Retrieves the Device this context was created from. */
479 * Retrieves a Listener instance for this context. Each context will only
480 * have one listener, which is automatically destroyed with the context.
482 Listener
getListener();
485 * Sets a MessageHandler instance which will be used to provide certain
486 * messages back to the application. Only one handler may be set for a
487 * context at a time. The previously set handler will be returned.
489 SharedPtr
<MessageHandler
> setMessageHandler(SharedPtr
<MessageHandler
> handler
);
491 /** Gets the currently-set message handler. */
492 SharedPtr
<MessageHandler
> getMessageHandler() const;
495 * Specifies the desired interval that the background thread will be woken
496 * up to process tasks, e.g. keeping streaming sources filled. An interval
497 * of 0 means the background thread will only be woken up manually with
498 * calls to update. The default is 0.
500 void setAsyncWakeInterval(std::chrono::milliseconds interval
);
503 * Retrieves the current interval used for waking up the background thread.
505 std::chrono::milliseconds
getAsyncWakeInterval() const;
507 // Functions below require the context to be current
510 * Creates a Decoder instance for the given audio file or resource name.
512 SharedPtr
<Decoder
> createDecoder(StringView name
);
515 * Queries if the channel configuration and sample type are supported by
518 bool isSupported(ChannelConfig channels
, SampleType type
) const;
521 * Queries the list of resamplers supported by the context. If the
522 * AL_SOFT_source_resampler extension is unsupported this will be an empty
523 * array, otherwise there will be at least one entry.
525 ArrayView
<String
> getAvailableResamplers();
527 * Queries the context's default resampler index. Be aware, if the
528 * AL_SOFT_source_resampler extension is unsupported the resampler list
529 * will be empty and this will resturn 0. If you try to access the
530 * resampler list with this index without the extension, undefined behavior
531 * will occur (accessing an out of bounds array index).
533 ALsizei
getDefaultResamplerIndex() const;
536 * Creates and caches a Buffer for the given audio file or resource name.
537 * Multiple calls with the same name will return the same Buffer object.
538 * Cached buffers must be freed using removeBuffer before destroying the
539 * context. If the buffer can't be loaded it will throw an exception.
541 Buffer
getBuffer(StringView name
);
544 * Asynchronously prepares a cached Buffer for the given audio file or
545 * resource name. Multiple calls with the same name will return multiple
546 * SharedFutures for the same Buffer object. Once called, the buffer must
547 * be freed using removeBuffer before destroying the context, even if you
548 * never get the Buffer from the SharedFuture.
550 * The Buffer will be scheduled to load asynchronously, and the caller gets
551 * back a SharedFuture that can be checked later (or waited on) to get the
552 * actual Buffer when it's ready. The application must take care to handle
553 * exceptions from the SharedFuture in case an unrecoverable error ocurred
556 SharedFuture
<Buffer
> getBufferAsync(StringView name
);
559 * Asynchronously prepares cached Buffers for the given audio file or
560 * resource names. Duplicate names and buffers already cached are ignored.
561 * Cached buffers must be freed using removeBuffer before destroying the
564 * The Buffer objects will be scheduled for loading asynchronously, and
565 * should be retrieved later when needed using getBufferAsync or getBuffer.
566 * Buffers that cannot be loaded, for example due to an unsupported format,
567 * will be ignored and a later call to getBuffer or getBufferAsync will
568 * throw an exception.
570 void precacheBuffersAsync(ArrayView
<StringView
> names
);
573 * Creates and caches a Buffer using the given name by reading the given
574 * decoder. The name may alias an audio file, but it must not currently
575 * exist in the buffer cache.
577 Buffer
createBufferFrom(StringView name
, SharedPtr
<Decoder
> decoder
);
580 * Asynchronously prepares a cached Buffer using the given name by reading
581 * the given decoder. The name may alias an audio file, but it must not
582 * currently exist in the buffer cache. Once called, the buffer must be
583 * freed using removeBuffer before destroying the context, even if you
584 * never get the Buffer from the SharedFuture.
586 * The Buffer will be scheduled to load asynchronously, and the caller gets
587 * back a SharedFuture that can be checked later (or waited on) to get the
588 * actual Buffer when it's ready. The application must take care to handle
589 * exceptions from the SharedFuture in case an unrecoverable error ocurred
590 * during the load. The decoder must not have its read or seek methods
591 * called while the buffer is not ready.
593 SharedFuture
<Buffer
> createBufferAsyncFrom(StringView name
, SharedPtr
<Decoder
> decoder
);
596 * Looks for a cached buffer using the given name and returns it. If the
597 * given name does not exist in the cache, and null buffer is returned.
599 Buffer
findBuffer(StringView name
);
602 * Looks for an asynchronously-loading buffer using the given name and
603 * returns a SharedFuture for it. If the given name does not exist in the
604 * cache, an invalid SharedFuture is returned (check with a call to
605 * \c SharedFuture::valid).
607 SharedFuture
<Buffer
> findBufferAsync(StringView name
);
610 * Deletes the cached Buffer object for the given audio file or resource
611 * name. The buffer must not be in use by a Source.
613 void removeBuffer(StringView name
);
615 * Deletes the given cached buffer. The buffer must not be in use by a
618 void removeBuffer(Buffer buffer
);
621 * Creates a new Source for playing audio. There is no practical limit to
622 * the number of sources you may create. You must call Source::release when
623 * the source is no longer needed.
625 Source
createSource();
627 AuxiliaryEffectSlot
createAuxiliaryEffectSlot();
629 Effect
createEffect();
631 SourceGroup
createSourceGroup(StringView name
);
632 SourceGroup
getSourceGroup(StringView name
);
634 /** Sets the doppler factor to apply to all source doppler calculations. */
635 void setDopplerFactor(ALfloat factor
);
638 * Sets the speed of sound propagation, in units per second, to calculate
639 * the doppler effect along with other distance-related time effects. The
640 * default is 343.3 units per second (a realistic speed assuming 1 meter
641 * per unit). If this is adjusted for a different unit scale,
642 * Listener::setMetersPerUnit should also be adjusted.
644 void setSpeedOfSound(ALfloat speed
);
647 * Sets the distance model used to attenuate sources given their distance
648 * from the listener. The default, InverseClamped, provides a realistic 1/r
649 * reduction in volume (that is, every doubling of distance causes the gain
650 * to reduce by half).
652 * The Clamped distance models restrict the source distance for the purpose
653 * of distance attenuation, so a source won't sound closer than its
654 * reference distance or farther than its max distance.
656 void setDistanceModel(DistanceModel model
);
658 /** Updates the context and all sources belonging to this context. */
662 class ALURE_API Listener
{
663 MAKE_PIMPL(Listener
, ListenerImpl
)
666 /** Sets the "master" gain for all context output. */
667 void setGain(ALfloat gain
);
670 * Specifies the listener's 3D position, velocity, and orientation
671 * together (see: setPosition, setVelocity, and setOrientation).
673 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
675 /** Specifies the listener's 3D position. */
676 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
677 void setPosition(const ALfloat
*pos
);
680 * Specifies the listener's 3D velocity, in units per second. As with
681 * OpenAL, this does not actually alter the listener's position, and
682 * instead just alters the pitch as determined by the doppler effect.
684 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
685 void setVelocity(const ALfloat
*vel
);
688 * Specifies the listener's 3D orientation, using position-relative 'at'
689 * and 'up' direction vectors.
691 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
692 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
693 void setOrientation(const ALfloat
*ori
);
696 * Sets the number of meters per unit, used for various effects that rely
697 * on the distance in meters (including air absorption and initial reverb
698 * decay). If this is changed, it's strongly recommended to also set the
699 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
700 * realistic 343.3m/s for sound propagation).
702 void setMetersPerUnit(ALfloat m_u
);
706 class ALURE_API Buffer
{
707 MAKE_PIMPL(Buffer
, BufferImpl
)
710 /** Retrieves the length of the buffer in sample frames. */
711 ALuint
getLength() const;
713 /** Retrieves the buffer's frequency in hz. */
714 ALuint
getFrequency() const;
716 /** Retrieves the buffer's sample configuration. */
717 ChannelConfig
getChannelConfig() const;
719 /** Retrieves the buffer's sample type. */
720 SampleType
getSampleType() const;
723 * Retrieves the storage size used by the buffer, in bytes. Note that the
724 * size in bytes may not be what you expect from the length, as it may take
725 * more space internally than the ChannelConfig and SampleType suggest to
728 ALuint
getSize() const;
731 * Sets the buffer's loop points, used for looping sources. If the current
732 * context does not support the AL_SOFT_loop_points extension, start and
733 * end must be 0 and getLength() respectively. Otherwise, start must be
734 * less than end, and end must be less than or equal to getLength().
736 * The buffer must not be in use when this method is called.
738 * \param start The starting point, in sample frames (inclusive).
739 * \param end The ending point, in sample frames (exclusive).
741 void setLoopPoints(ALuint start
, ALuint end
);
743 /** Retrieves the current loop points as a [start,end) pair. */
744 std::pair
<ALuint
,ALuint
> getLoopPoints() const;
747 * Retrieves the Source objects currently playing the buffer. Stopping the
748 * returned sources will allow the buffer to be removed from the context.
750 Vector
<Source
> getSources() const;
752 /** Retrieves the name the buffer was created with. */
753 StringView
getName() const;
755 /** Queries if the buffer is in use and can't be removed. */
756 bool isInUse() const;
760 enum class Spatialize
{
763 Auto
= 0x0002 /* AL_AUTO_SOFT */
766 class ALURE_API Source
{
767 MAKE_PIMPL(Source
, SourceImpl
)
771 * Plays the source using a buffer. The same buffer may be played from
772 * multiple sources simultaneously.
774 void play(Buffer buffer
);
776 * Plays the source by asynchronously streaming audio from a decoder. The
777 * given decoder must *NOT* have its read or seek methods called from
778 * elsewhere while in use.
780 * \param decoder The decoder object to play audio from.
781 * \param chunk_len The number of sample frames to read for each chunk
782 * update. Smaller values will require more frequent updates and
783 * larger values will handle more data with each chunk.
784 * \param queue_size The number of chunks to keep queued during playback.
785 * Smaller values use less memory while larger values improve
786 * protection against underruns.
788 void play(SharedPtr
<Decoder
> decoder
, ALuint chunk_len
, ALuint queue_size
);
791 * Prepares to play a source using a future buffer. The method will return
792 * right away and the source will begin playing once the future buffer
793 * becomes ready. If the future buffer is already ready, it begins playing
794 * immediately as if you called play(future_buffer.get()).
796 * The future buffer is checked during calls to \c Context::update and the
797 * source will start playback once the future buffer reports it's ready.
798 * Use the isPending method to check if the source is still waiting for the
801 void play(SharedFuture
<Buffer
> future_buffer
);
804 * Stops playback, releasing the buffer or decoder reference. Any pending
805 * playback from a future buffer is canceled.
810 * Fades the source to the specified gain over the given duration, at which
811 * point playback will stop. This gain is in addition to the base gain, and
812 * must be greater than 0 and less than 1. The duration must also be
815 * Pending playback from a future buffer is not immediately canceled, but
816 * the fading starts with this call. If the future buffer then becomes
817 * ready, it will start mid-fade. Pending playback will be canceled if the
818 * fade out completes before the future buffer becomes ready.
820 * Fading is updated during calls to \c Context::update, which should be
821 * called regularly (30 to 50 times per second) for the fading to be
824 void fadeOutToStop(ALfloat gain
, std::chrono::milliseconds duration
);
826 /** Pauses the source if it is playing. */
829 /** Resumes the source if it is paused. */
832 /** Specifies if the source is waiting to play a future buffer. */
833 bool isPending() const;
835 /** Specifies if the source is currently playing. */
836 bool isPlaying() const;
838 /** Specifies if the source is currently paused. */
839 bool isPaused() const;
842 * Sets this source as a child of the given source group. The given source
843 * group's parameters will influence this and all other sources that belong
844 * to it. A source can only be the child of one source group at a time,
845 * although that source group may belong to another source group.
847 * Passing in a null group removes it from its current source group.
849 void setGroup(SourceGroup group
);
851 /** Retrieves the source group this source belongs to. */
852 SourceGroup
getGroup() const;
855 * Specifies the source's playback priority. The lowest priority sources
856 * will be forcefully stopped when no more mixing sources are available and
857 * higher priority sources are played.
859 void setPriority(ALuint priority
);
860 /** Retrieves the source's priority. */
861 ALuint
getPriority() const;
864 * Sets the source's offset, in sample frames. If the source is playing or
865 * paused, it will go to that offset immediately, otherwise the source will
866 * start at the specified offset the next time it's played.
868 void setOffset(uint64_t offset
);
870 * Retrieves the source offset in sample frames and its latency in nano-
871 * seconds. For streaming sources this will be the offset based on the
872 * decoder's read position.
874 * If the AL_SOFT_source_latency extension is unsupported, the latency will
877 std::pair
<uint64_t,std::chrono::nanoseconds
> getSampleOffsetLatency() const;
878 uint64_t getSampleOffset() const { return std::get
<0>(getSampleOffsetLatency()); }
880 * Retrieves the source offset and latency in seconds. For streaming
881 * sources this will be the offset based on the decoder's read position.
883 * If the AL_SOFT_source_latency extension is unsupported, the latency will
886 std::pair
<Seconds
,Seconds
> getSecOffsetLatency() const;
887 Seconds
getSecOffset() const { return std::get
<0>(getSecOffsetLatency()); }
890 * Specifies if the source should loop on the Buffer or Decoder object's
893 void setLooping(bool looping
);
894 bool getLooping() const;
897 * Specifies a linear pitch shift base. A value of 1.0 is the default
900 void setPitch(ALfloat pitch
);
901 ALfloat
getPitch() const;
904 * Specifies the base linear gain. A value of 1.0 is the default normal
907 void setGain(ALfloat gain
);
908 ALfloat
getGain() const;
911 * Specifies the minimum and maximum gain. The source's gain is clamped to
912 * this range after distance attenuation and cone attenuation are applied
913 * to the gain base, although before the filter gain adjustements.
915 void setGainRange(ALfloat mingain
, ALfloat maxgain
);
916 std::pair
<ALfloat
,ALfloat
> getGainRange() const;
917 ALfloat
getMinGain() const { return std::get
<0>(getGainRange()); }
918 ALfloat
getMaxGain() const { return std::get
<1>(getGainRange()); }
921 * Specifies the reference distance and maximum distance the source will
922 * use for the current distance model. For Clamped distance models, the
923 * source's calculated distance is clamped to the specified range before
924 * applying distance-related attenuation.
926 * For all distance models, the reference distance is the distance at which
927 * the source's volume will not have any extra attenuation (an effective
928 * gain multiplier of 1).
930 void setDistanceRange(ALfloat refdist
, ALfloat maxdist
);
931 std::pair
<ALfloat
,ALfloat
> getDistanceRange() const;
932 ALfloat
getReferenceDistance() const { return std::get
<0>(getDistanceRange()); }
933 ALfloat
getMaxDistance() const { return std::get
<1>(getDistanceRange()); }
936 * Specifies the source's 3D position, velocity, and direction together
937 * (see: setPosition, setVelocity, and setDirection).
939 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const Vector3
&direction
);
942 * Specifies the source's 3D position, velocity, and orientation together
943 * (see: setPosition, setVelocity, and setOrientation).
945 void set3DParameters(const Vector3
&position
, const Vector3
&velocity
, const std::pair
<Vector3
,Vector3
> &orientation
);
947 /** Specifies the source's 3D position. */
948 void setPosition(ALfloat x
, ALfloat y
, ALfloat z
);
949 void setPosition(const ALfloat
*pos
);
950 Vector3
getPosition() const;
953 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
954 * this does not actually alter the source's position, and instead just
955 * alters the pitch as determined by the doppler effect.
957 void setVelocity(ALfloat x
, ALfloat y
, ALfloat z
);
958 void setVelocity(const ALfloat
*vel
);
959 Vector3
getVelocity() const;
962 * Specifies the source's 3D facing direction. Deprecated in favor of
965 void setDirection(ALfloat x
, ALfloat y
, ALfloat z
);
966 void setDirection(const ALfloat
*dir
);
967 Vector3
getDirection() const;
970 * Specifies the source's 3D orientation, using position-relative 'at' and
971 * 'up' direction vectors. Note: unlike the AL_EXT_BFORMAT extension this
972 * property comes from, this also affects the facing direction, superceding
975 void setOrientation(ALfloat x1
, ALfloat y1
, ALfloat z1
, ALfloat x2
, ALfloat y2
, ALfloat z2
);
976 void setOrientation(const ALfloat
*at
, const ALfloat
*up
);
977 void setOrientation(const ALfloat
*ori
);
978 std::pair
<Vector3
,Vector3
> getOrientation() const;
981 * Specifies the source's cone angles, in degrees. The inner angle is the
982 * area within which the listener will hear the source with no extra
983 * attenuation, while the listener being outside of the outer angle will
984 * hear the source attenuated according to the outer cone gains. The area
985 * follows the facing direction, so for example an inner angle of 180 means
986 * the entire front face of the source is in the inner cone.
988 void setConeAngles(ALfloat inner
, ALfloat outer
);
989 std::pair
<ALfloat
,ALfloat
> getConeAngles() const;
990 ALfloat
getInnerConeAngle() const { return std::get
<0>(getConeAngles()); }
991 ALfloat
getOuterConeAngle() const { return std::get
<1>(getConeAngles()); }
994 * Specifies the linear gain multiplier when the listener is outside of the
995 * source's outer cone area. The specified gain applies to all frequencies,
996 * while gainhf applies extra attenuation to high frequencies creating a
999 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1001 void setOuterConeGains(ALfloat gain
, ALfloat gainhf
=1.0f
);
1002 std::pair
<ALfloat
,ALfloat
> getOuterConeGains() const;
1003 ALfloat
getOuterConeGain() const { return std::get
<0>(getOuterConeGains()); }
1004 ALfloat
getOuterConeGainHF() const { return std::get
<1>(getOuterConeGains()); }
1007 * Specifies the rolloff factors for the direct and send paths. This is
1008 * effectively a distance scaling relative to the reference distance. Note:
1009 * the room rolloff factor is 0 by default, disabling distance attenuation
1010 * for send paths. This is because the reverb engine will, by default,
1011 * apply a more realistic room decay based on the reverb decay time and
1014 void setRolloffFactors(ALfloat factor
, ALfloat roomfactor
=0.0f
);
1015 std::pair
<ALfloat
,ALfloat
> getRolloffFactors() const;
1016 ALfloat
getRolloffFactor() const { return std::get
<0>(getRolloffFactors()); }
1017 ALfloat
getRoomRolloffFactor() const { return std::get
<1>(getRolloffFactors()); }
1020 * Specifies the doppler factor for the doppler effect's pitch shift. This
1021 * effectively scales the source and listener velocities for the doppler
1024 void setDopplerFactor(ALfloat factor
);
1025 ALfloat
getDopplerFactor() const;
1028 * Specifies if the source's position, velocity, and direction/orientation
1029 * are relative to the listener.
1031 void setRelative(bool relative
);
1032 bool getRelative() const;
1035 * Specifies the source's radius. This causes the source to behave as if
1036 * every point within the spherical area emits sound.
1038 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1040 void setRadius(ALfloat radius
);
1041 ALfloat
getRadius() const;
1044 * Specifies the left and right channel angles, in radians, when playing a
1045 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1046 * in front and positive values going left.
1048 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1050 void setStereoAngles(ALfloat leftAngle
, ALfloat rightAngle
);
1051 std::pair
<ALfloat
,ALfloat
> getStereoAngles() const;
1054 * Specifies if the source always has 3D spatialization features (On),
1055 * never has 3D spatialization features (Off), or if spatialization is
1056 * enabled based on playing a mono sound or not (Auto, default).
1058 * Has no effect without the AL_SOFT_source_spatialize extension.
1060 void set3DSpatialize(Spatialize spatialize
);
1061 Spatialize
get3DSpatialize() const;
1064 * Specifies the index of the resampler to use for this source. The index
1065 * is from the resamplers returned by \c Context::getAvailableResamplers,
1066 * and must be 0 or greater.
1068 * Has no effect without the AL_SOFT_source_resampler extension.
1070 void setResamplerIndex(ALsizei index
);
1071 ALsizei
getResamplerIndex() const;
1074 * Specifies a multiplier for the amount of atmospheric high-frequency
1075 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1076 * -0.05dB per meter, with higher values simulating foggy air and lower
1077 * values simulating dryer air. The default is 0.
1079 void setAirAbsorptionFactor(ALfloat factor
);
1080 ALfloat
getAirAbsorptionFactor() const;
1083 * Specifies to automatically apply adjustments to the direct path's high-
1084 * frequency gain, and the send paths' gain and high-frequency gain. The
1085 * default is true for all.
1087 void setGainAuto(bool directhf
, bool send
, bool sendhf
);
1088 std::tuple
<bool,bool,bool> getGainAuto() const;
1089 bool getDirectGainHFAuto() const { return std::get
<0>(getGainAuto()); }
1090 bool getSendGainAuto() const { return std::get
<1>(getGainAuto()); }
1091 bool getSendGainHFAuto() const { return std::get
<2>(getGainAuto()); }
1093 /** Sets the filter properties on the direct path signal. */
1094 void setDirectFilter(const FilterParams
&filter
);
1096 * Sets the filter properties on the given send path signal. Any auxiliary
1097 * effect slot on the send path remains in place.
1099 void setSendFilter(ALuint send
, const FilterParams
&filter
);
1101 * Connects the effect slot to the given send path. Any filter properties
1102 * on the send path remain as they were.
1104 void setAuxiliarySend(AuxiliaryEffectSlot slot
, ALuint send
);
1106 * Connects the effect slot to the given send path, using the filter
1109 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot
, ALuint send
, const FilterParams
&filter
);
1112 * Releases the source, stopping playback, releasing resources, and
1113 * returning it to the system.
1119 class ALURE_API SourceGroup
{
1120 MAKE_PIMPL(SourceGroup
, SourceGroupImpl
)
1123 /** Retrieves the associated name of the source group. */
1124 StringView
getName() const;
1127 * Adds this source group as a subgroup of the specified source group. This
1128 * method will throw an exception if this group is being added to a group
1129 * it has as a sub-group (i.e. it would create a circular sub-group chain).
1131 void setParentGroup(SourceGroup group
);
1133 /** Retrieves the source group this source group is a child of. */
1134 SourceGroup
getParentGroup() const;
1136 /** Returns the list of sources currently in the group. */
1137 Vector
<Source
> getSources() const;
1139 /** Returns the list of subgroups currently in the group. */
1140 Vector
<SourceGroup
> getSubGroups() const;
1143 * Sets the source group gain, which accumulates with its sources' and
1146 void setGain(ALfloat gain
);
1147 /** Gets the source group gain. */
1148 ALfloat
getGain() const;
1151 * Sets the source group pitch, which accumulates with its sources' and
1152 * sub-groups' pitch.
1154 void setPitch(ALfloat pitch
);
1155 /** Gets the source group pitch. */
1156 ALfloat
getPitch() const;
1159 * Pauses all currently-playing sources that are under this group,
1160 * including sub-groups.
1162 void pauseAll() const;
1164 * Resumes all paused sources that are under this group, including
1167 void resumeAll() const;
1169 /** Stops all sources that are under this group, including sub-groups. */
1170 void stopAll() const;
1173 * Releases the source group, removing all sources from it before being
1185 class ALURE_API AuxiliaryEffectSlot
{
1186 MAKE_PIMPL(AuxiliaryEffectSlot
, AuxiliaryEffectSlotImpl
)
1189 void setGain(ALfloat gain
);
1191 * If set to true, the reverb effect will automatically apply adjustments
1192 * to the source's send slot gains based on the effect properties.
1194 * Has no effect when using non-reverb effects. Default is true.
1196 void setSendAuto(bool sendauto
);
1199 * Updates the effect slot with a new effect. The given effect object may
1200 * be altered or destroyed without affecting the effect slot.
1202 void applyEffect(Effect effect
);
1205 * Releases the effect slot, returning it to the system. It must not be in
1211 * Retrieves each Source object and its pairing send this effect slot is
1212 * set on. Setting a different (or null) effect slot on each source's given
1213 * send will allow the effect slot to be released.
1215 Vector
<SourceSend
> getSourceSends() const;
1217 /** Determines if the effect slot is in use by a source. */
1218 bool isInUse() const;
1222 class ALURE_API Effect
{
1223 MAKE_PIMPL(Effect
, EffectImpl
)
1227 * Updates the effect with the specified reverb properties. If the
1228 * EAXReverb effect is not supported, it will automatically attempt to
1229 * downgrade to the Standard Reverb effect.
1231 void setReverbProperties(const EFXEAXREVERBPROPERTIES
&props
);
1238 * Audio decoder interface. Applications may derive from this, implementing the
1239 * necessary methods, and use it in places the API wants a Decoder object.
1241 class ALURE_API Decoder
{
1245 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1246 virtual ALuint
getFrequency() const = 0;
1247 /** Retrieves the channel configuration of the audio being decoded. */
1248 virtual ChannelConfig
getChannelConfig() const = 0;
1249 /** Retrieves the sample type of the audio being decoded. */
1250 virtual SampleType
getSampleType() const = 0;
1253 * Retrieves the total length of the audio, in sample frames. If unknown,
1254 * returns 0. Note that if the returned length is 0, the decoder may not be
1255 * used to load a Buffer.
1257 virtual uint64_t getLength() const = 0;
1259 * Seek to pos, specified in sample frames. Returns true if the seek was
1262 virtual bool seek(uint64_t pos
) = 0;
1265 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1266 * start >= end, all available samples are included in the loop.
1268 virtual std::pair
<uint64_t,uint64_t> getLoopPoints() const = 0;
1271 * Decodes count sample frames, writing them to ptr, and returns the number
1272 * of sample frames written. Returning less than the requested count
1273 * indicates the end of the audio.
1275 virtual ALuint
read(ALvoid
*ptr
, ALuint count
) = 0;
1279 * Audio decoder factory interface. Applications may derive from this,
1280 * implementing the necessary methods, and use it in places the API wants a
1281 * DecoderFactory object.
1283 class ALURE_API DecoderFactory
{
1285 virtual ~DecoderFactory();
1288 * Creates and returns a Decoder instance for the given resource file. If
1289 * the decoder needs to retain the file handle for reading as-needed, it
1290 * should move the UniquePtr to internal storage.
1292 * \return nullptr if a decoder can't be created from the file.
1294 virtual SharedPtr
<Decoder
> createDecoder(UniquePtr
<std::istream
> &file
) = 0;
1298 * Registers a decoder factory for decoding audio. Registered factories are
1299 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1300 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1301 * name1 < name2. Internal decoder factories are always used after registered
1304 * Alure retains a reference to the DecoderFactory instance and will release it
1305 * (destructing the object) when the library unloads.
1307 * \param name A unique name identifying this decoder factory.
1308 * \param factory A DecoderFactory instance used to create Decoder instances.
1310 ALURE_API
void RegisterDecoder(StringView name
, UniquePtr
<DecoderFactory
> factory
);
1313 * Unregisters a decoder factory by name. Alure returns the instance back to
1316 * \param name The unique name identifying a previously-registered decoder
1319 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1320 * decoder factory with the given name doesn't exist.
1322 ALURE_API UniquePtr
<DecoderFactory
> UnregisterDecoder(StringView name
);
1326 * A file I/O factory interface. Applications may derive from this and set an
1327 * instance to be used by the audio decoders. By default, the library uses
1330 class ALURE_API FileIOFactory
{
1333 * Sets the factory instance to be used by the audio decoders. If a
1334 * previous factory was set, it's returned to the application. Passing in a
1335 * nullptr reverts to the default.
1337 static UniquePtr
<FileIOFactory
> set(UniquePtr
<FileIOFactory
> factory
);
1340 * Gets the current FileIOFactory instance being used by the audio
1343 static FileIOFactory
&get();
1345 virtual ~FileIOFactory();
1347 /** Opens a read-only binary file for the given name. */
1348 virtual UniquePtr
<std::istream
> openFile(const String
&name
) = 0;
1353 * A message handler interface. Applications may derive from this and set an
1354 * instance on a context to receive messages. The base methods are no-ops, so
1355 * derived classes only need to implement methods for relevant messages.
1357 * It's recommended that applications mark their handler methods using the
1358 * override keyword, to ensure they're properly overriding the base methods in
1361 class ALURE_API MessageHandler
{
1363 virtual ~MessageHandler();
1366 * Called when the given device has been disconnected and is no longer
1367 * usable for output. As per the ALC_EXT_disconnect specification,
1368 * disconnected devices remain valid, however all playing sources are
1369 * automatically stopped, any sources that are attempted to play will
1370 * immediately stop, and new contexts may not be created on the device.
1372 * Note that connection status is checked during Context::update calls, so
1373 * that method must be called regularly to be notified when a device is
1374 * disconnected. This method may not be called if the device lacks support
1375 * for the ALC_EXT_disconnect extension.
1377 virtual void deviceDisconnected(Device device
);
1380 * Called when the given source reaches the end of the buffer or stream.
1382 * Sources that stopped automatically will be detected upon a call to
1385 virtual void sourceStopped(Source source
);
1388 * Called when the given source was forced to stop. This can be because
1389 * either there were no more mixing sources and a higher-priority source
1390 * preempted it, or it's part of a SourceGroup (or sub-group thereof) that
1391 * had its SourceGroup::stopAll method called.
1393 virtual void sourceForceStopped(Source source
);
1396 * Called when a new buffer is about to be created and loaded. May be
1397 * called asynchronously for buffers being loaded asynchronously.
1399 * \param name The resource name, as passed to Context::getBuffer.
1400 * \param channels Channel configuration of the given audio data.
1401 * \param type Sample type of the given audio data.
1402 * \param samplerate Sample rate of the given audio data.
1403 * \param data The audio data that is about to be fed to the OpenAL buffer.
1405 virtual void bufferLoading(StringView name
, ChannelConfig channels
, SampleType type
, ALuint samplerate
, ArrayView
<ALbyte
> data
);
1408 * Called when a resource isn't found, allowing the app to substitute in a
1409 * different resource. For buffers being cached, the original name will
1410 * still be used for the cache entry so the app doesn't have to keep track
1411 * of substituted resource names.
1413 * This will be called again if the new name also isn't found.
1415 * \param name The resource name that was not found.
1416 * \return The replacement resource name to use instead. Returning an empty
1417 * string means to stop trying.
1419 virtual String
resourceNotFound(StringView name
);
1424 } // namespace alure
1426 #endif /* AL_ALURE2_H */