Add comparison operators to the Version class
[alure.git] / include / AL / alure2.h
blob63aeca7d485cabaa3f799182a7ed3ff8a1267b85
1 #ifndef AL_ALURE2_H
2 #define AL_ALURE2_H
4 #include <type_traits>
5 #include <utility>
6 #include <tuple>
7 #include <cmath>
9 #include "alc.h"
10 #include "al.h"
11 #include "alure2-alext.h"
13 #include "alure2-aliases.h"
14 #include "alure2-typeviews.h"
16 #ifndef ALURE_API
17 #ifndef ALURE_STATIC_LIB
18 #if defined(_WIN32)
19 #define ALURE_API __declspec(dllimport)
20 #elif defined(__has_attribute)
21 #if __has_attribute(visibility)
22 #define ALURE_API __attribute__((visibility("default")))
23 #endif
24 #elif defined(__GNUC__)
25 #define ALURE_API __attribute__((visibility("default")))
26 #endif
27 #endif
28 #ifndef ALURE_API
29 #define ALURE_API
30 #endif
31 #endif /* ALURE_API */
33 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
34 #define EFXEAXREVERBPROPERTIES_DEFINED
35 typedef struct {
36 float flDensity;
37 float flDiffusion;
38 float flGain;
39 float flGainHF;
40 float flGainLF;
41 float flDecayTime;
42 float flDecayHFRatio;
43 float flDecayLFRatio;
44 float flReflectionsGain;
45 float flReflectionsDelay;
46 float flReflectionsPan[3];
47 float flLateReverbGain;
48 float flLateReverbDelay;
49 float flLateReverbPan[3];
50 float flEchoTime;
51 float flEchoDepth;
52 float flModulationTime;
53 float flModulationDepth;
54 float flAirAbsorptionGainHF;
55 float flHFReference;
56 float flLFReference;
57 float flRoomRolloffFactor;
58 int iDecayHFLimit;
59 } EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
60 #endif
62 namespace alure {
64 // Available class interfaces.
65 class DeviceManager;
66 class Device;
67 class Context;
68 class Listener;
69 class Buffer;
70 class Source;
71 class SourceGroup;
72 class AuxiliaryEffectSlot;
73 class Effect;
74 class Decoder;
75 class DecoderFactory;
76 class MessageHandler;
78 // Opaque class implementations.
79 class DeviceManagerImpl;
80 class DeviceImpl;
81 class ContextImpl;
82 class ListenerImpl;
83 class BufferImpl;
84 class SourceImpl;
85 class SourceGroupImpl;
86 class AuxiliaryEffectSlotImpl;
87 class EffectImpl;
89 /** Convert a value from decibels to linear gain. */
90 template<typename T, typename NonRefT=RemoveRefT<T>,
91 typename=EnableIfT<std::is_floating_point<NonRefT>::value>>
92 constexpr inline NonRefT dBToLinear(T&& value)
93 { return std::pow(NonRefT(10.0), std::forward<T>(value) / NonRefT(20.0)); }
95 /** Convert a value from linear gain to decibels. */
96 template<typename T, typename NonRefT=RemoveRefT<T>,
97 typename=EnableIfT<std::is_floating_point<NonRefT>::value>>
98 constexpr inline NonRefT LinearTodB(T&& value)
99 { return std::log10(std::forward<T>(value)) * NonRefT(20.0); }
102 * An attribute pair, for passing attributes to Device::createContext and
103 * Device::reset.
105 using AttributePair = std::pair<ALCint,ALCint>;
106 static_assert(sizeof(AttributePair) == sizeof(ALCint[2]), "Bad AttributePair size");
107 inline AttributePair AttributesEnd() noexcept { return std::make_pair(0, 0); }
110 struct FilterParams {
111 ALfloat mGain;
112 ALfloat mGainHF; // For low-pass and band-pass filters
113 ALfloat mGainLF; // For high-pass and band-pass filters
117 class Vector3 {
118 Array<ALfloat,3> mValue;
120 public:
121 constexpr Vector3() noexcept
122 : mValue{{0.0f, 0.0f, 0.0f}}
124 constexpr Vector3(const Vector3 &rhs) noexcept
125 : mValue{{rhs.mValue[0], rhs.mValue[1], rhs.mValue[2]}}
127 constexpr Vector3(ALfloat val) noexcept
128 : mValue{{val, val, val}}
130 constexpr Vector3(ALfloat x, ALfloat y, ALfloat z) noexcept
131 : mValue{{x, y, z}}
133 Vector3(const ALfloat *vec) noexcept
134 : mValue{{vec[0], vec[1], vec[2]}}
137 const ALfloat *getPtr() const noexcept
138 { return mValue.data(); }
140 ALfloat& operator[](size_t i) noexcept
141 { return mValue[i]; }
142 constexpr const ALfloat& operator[](size_t i) const noexcept
143 { return mValue[i]; }
145 #define ALURE_DECL_OP(op) \
146 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
148 return Vector3(mValue[0] op rhs.mValue[0], \
149 mValue[1] op rhs.mValue[1], \
150 mValue[2] op rhs.mValue[2]); \
152 ALURE_DECL_OP(+)
153 ALURE_DECL_OP(-)
154 ALURE_DECL_OP(*)
155 ALURE_DECL_OP(/)
156 #undef ALURE_DECL_OP
157 #define ALURE_DECL_OP(op) \
158 Vector3& operator op(const Vector3 &rhs) noexcept \
160 mValue[0] op rhs.mValue[0]; \
161 mValue[1] op rhs.mValue[1]; \
162 mValue[2] op rhs.mValue[2]; \
163 return *this; \
165 ALURE_DECL_OP(+=)
166 ALURE_DECL_OP(-=)
167 ALURE_DECL_OP(*=)
168 ALURE_DECL_OP(/=)
170 #undef ALURE_DECL_OP
171 #define ALURE_DECL_OP(op) \
172 constexpr Vector3 operator op(ALfloat scale) const noexcept \
174 return Vector3(mValue[0] op scale, \
175 mValue[1] op scale, \
176 mValue[2] op scale); \
178 ALURE_DECL_OP(*)
179 ALURE_DECL_OP(/)
180 #undef ALURE_DECL_OP
181 #define ALURE_DECL_OP(op) \
182 Vector3& operator op(ALfloat scale) noexcept \
184 mValue[0] op scale; \
185 mValue[1] op scale; \
186 mValue[2] op scale; \
187 return *this; \
189 ALURE_DECL_OP(*=)
190 ALURE_DECL_OP(/=)
191 #undef ALURE_DECL_OP
193 constexpr ALfloat getLengthSquared() const noexcept
194 { return mValue[0]*mValue[0] + mValue[1]*mValue[1] + mValue[2]*mValue[2]; }
195 ALfloat getLength() const noexcept
196 { return std::sqrt(getLengthSquared()); }
198 constexpr ALfloat getDistanceSquared(const Vector3 &pos) const noexcept
199 { return (pos - *this).getLengthSquared(); }
200 ALfloat getDistance(const Vector3 &pos) const noexcept
201 { return (pos - *this).getLength(); }
203 static_assert(sizeof(Vector3) == sizeof(ALfloat[3]), "Bad Vector3 size");
206 enum class SampleType {
207 UInt8,
208 Int16,
209 Float32,
210 Mulaw
212 ALURE_API const char *GetSampleTypeName(SampleType type);
214 enum class ChannelConfig {
215 /** 1-channel mono sound. */
216 Mono,
217 /** 2-channel stereo sound. */
218 Stereo,
219 /** 2-channel rear sound (back-left and back-right). */
220 Rear,
221 /** 4-channel surround sound. */
222 Quad,
223 /** 5.1 surround sound. */
224 X51,
225 /** 6.1 surround sound. */
226 X61,
227 /** 7.1 surround sound. */
228 X71,
229 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
230 BFormat2D,
231 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
232 BFormat3D
234 ALURE_API const char *GetChannelConfigName(ChannelConfig cfg);
236 ALURE_API ALuint FramesToBytes(ALuint frames, ChannelConfig chans, SampleType type);
237 ALURE_API ALuint BytesToFrames(ALuint bytes, ChannelConfig chans, SampleType type);
240 /** Class for storing a major.minor version number. */
241 class Version {
242 ALuint mMajor : 16;
243 ALuint mMinor : 16;
245 public:
246 constexpr Version() noexcept : mMajor(0), mMinor(0) { }
247 constexpr Version(ALuint _maj, ALuint _min) noexcept : mMajor(_maj), mMinor(_min) { }
248 constexpr Version(const Version&) noexcept = default;
250 constexpr ALuint getMajor() const noexcept { return mMajor; }
251 constexpr ALuint getMinor() const noexcept { return mMinor; }
253 constexpr bool operator==(const Version &rhs) const noexcept
254 { return mMajor == rhs.mMajor && mMinor == rhs.mMinor; }
255 constexpr bool operator!=(const Version &rhs) const noexcept
256 { return !(*this == rhs); }
257 constexpr bool operator<=(const Version &rhs) const noexcept
258 { return mMajor < rhs.mMajor || (mMajor == rhs.mMajor && mMinor <= rhs.mMinor); }
259 constexpr bool operator>=(const Version &rhs) const noexcept
260 { return mMajor > rhs.mMajor || (mMajor == rhs.mMajor && mMinor >= rhs.mMinor); }
261 constexpr bool operator<(const Version &rhs) const noexcept
262 { return mMajor < rhs.mMajor || (mMajor == rhs.mMajor && mMinor < rhs.mMinor); }
263 constexpr bool operator>(const Version &rhs) const noexcept
264 { return mMajor > rhs.mMajor || (mMajor == rhs.mMajor && mMinor > rhs.mMinor); }
266 constexpr bool isZero() const noexcept { return *this == Version{0,0}; }
269 #define MAKE_PIMPL(BaseT, ImplT) \
270 private: \
271 ImplT *pImpl; \
273 public: \
274 using handle_type = ImplT*; \
276 BaseT() : pImpl(nullptr) { } \
277 BaseT(ImplT *impl) : pImpl(impl) { } \
278 BaseT(const BaseT&) = default; \
279 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
281 BaseT& operator=(const BaseT&) = default; \
282 BaseT& operator=(BaseT&& rhs) \
284 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
285 return *this; \
288 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
289 bool operator!=(const BaseT &rhs) const { return pImpl != rhs.pImpl; } \
290 bool operator<=(const BaseT &rhs) const { return pImpl <= rhs.pImpl; } \
291 bool operator>=(const BaseT &rhs) const { return pImpl >= rhs.pImpl; } \
292 bool operator<(const BaseT &rhs) const { return pImpl < rhs.pImpl; } \
293 bool operator>(const BaseT &rhs) const { return pImpl > rhs.pImpl; } \
295 operator bool() const { return !!pImpl; } \
297 handle_type getHandle() const { return pImpl; }
299 enum class DeviceEnumeration {
300 Basic = ALC_DEVICE_SPECIFIER,
301 Full = ALC_ALL_DEVICES_SPECIFIER,
302 Capture = ALC_CAPTURE_DEVICE_SPECIFIER
305 enum class DefaultDeviceType {
306 Basic = ALC_DEFAULT_DEVICE_SPECIFIER,
307 Full = ALC_DEFAULT_ALL_DEVICES_SPECIFIER,
308 Capture = ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
312 * A class managing Device objects and other related functionality. This class
313 * is a singleton, only one instance will exist in a process.
315 class ALURE_API DeviceManager {
316 DeviceManagerImpl *pImpl;
318 DeviceManager(DeviceManagerImpl *impl) : pImpl(impl) { }
319 friend class ALDeviceManager;
321 public:
322 DeviceManager(const DeviceManager&) = default;
323 DeviceManager(DeviceManager&& rhs) : pImpl(rhs.pImpl) { }
325 /** Retrieves the DeviceManager instance. */
326 static DeviceManager get();
328 /** Queries the existence of a non-device-specific ALC extension. */
329 bool queryExtension(const String &name) const;
330 bool queryExtension(const char *name) const;
332 /** Enumerates available device names of the given type. */
333 Vector<String> enumerate(DeviceEnumeration type) const;
334 /** Retrieves the default device of the given type. */
335 String defaultDeviceName(DefaultDeviceType type) const;
338 * Opens the playback device given by name, or the default if blank. Throws
339 * an exception on error.
341 Device openPlayback(const String &name={});
342 Device openPlayback(const char *name);
345 * Opens the playback device given by name, or the default if blank.
346 * Returns an empty Device on error.
348 Device openPlayback(const String &name, const std::nothrow_t&);
349 Device openPlayback(const char *name, const std::nothrow_t&);
351 /** Opens the default playback device. Returns an empty Device on error. */
352 Device openPlayback(const std::nothrow_t&);
356 enum class PlaybackName {
357 Basic = ALC_DEVICE_SPECIFIER,
358 Full = ALC_ALL_DEVICES_SPECIFIER
361 class ALURE_API Device {
362 MAKE_PIMPL(Device, DeviceImpl)
364 public:
365 /** Retrieves the device name as given by type. */
366 String getName(PlaybackName type=PlaybackName::Full) const;
367 /** Queries the existence of an ALC extension on this device. */
368 bool queryExtension(const String &name) const;
369 bool queryExtension(const char *name) const;
371 /** Retrieves the ALC version supported by this device. */
372 Version getALCVersion() const;
375 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
376 * extension is unsupported, this will be 0.0.
378 Version getEFXVersion() const;
380 /** Retrieves the device's playback frequency, in hz. */
381 ALCuint getFrequency() const;
384 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
385 * is unsupported, this will be 0.
387 ALCuint getMaxAuxiliarySends() const;
390 * Enumerates available HRTF names. The names are sorted as OpenAL gives
391 * them, such that the index of a given name is the ID to use with
392 * ALC_HRTF_ID_SOFT.
394 * Requires the ALC_SOFT_HRTF extension.
396 Vector<String> enumerateHRTFNames() const;
399 * Retrieves whether HRTF is enabled on the device or not.
401 * Requires the ALC_SOFT_HRTF extension.
403 bool isHRTFEnabled() const;
406 * Retrieves the name of the HRTF currently being used by this device.
408 * Requires the ALC_SOFT_HRTF extension.
410 String getCurrentHRTF() const;
413 * Resets the device, using the specified attributes.
415 * Requires the ALC_SOFT_HRTF extension.
417 void reset(ArrayView<AttributePair> attributes);
420 * Creates a new Context on this device, using the specified attributes.
421 * Throws an exception if context creation fails.
423 Context createContext(ArrayView<AttributePair> attributes={});
425 * Creates a new Context on this device, using the specified attributes.
426 * Returns an empty Context if context creation fails.
428 Context createContext(ArrayView<AttributePair> attributes, const std::nothrow_t&);
429 Context createContext(const std::nothrow_t&);
432 * Pauses device processing, stopping updates for its contexts. Multiple
433 * calls are allowed but it is not reference counted, so the device will
434 * resume after one resumeDSP call.
436 * Requires the ALC_SOFT_pause_device extension.
438 void pauseDSP();
441 * Resumes device processing, restarting updates for its contexts. Multiple
442 * calls are allowed and will no-op.
444 void resumeDSP();
447 * Closes and frees the device. All previously-created contexts must first
448 * be destroyed.
450 void close();
454 enum class DistanceModel {
455 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
456 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
457 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
458 Inverse = AL_INVERSE_DISTANCE,
459 Linear = AL_LINEAR_DISTANCE,
460 Exponent = AL_EXPONENT_DISTANCE,
461 None = AL_NONE,
464 class ALURE_API Context {
465 MAKE_PIMPL(Context, ContextImpl)
467 public:
468 /** Makes the specified context current for OpenAL operations. */
469 static void MakeCurrent(Context context);
470 /** Retrieves the current context used for OpenAL operations. */
471 static Context GetCurrent();
474 * Makes the specified context current for OpenAL operations on the calling
475 * thread only. Requires the ALC_EXT_thread_local_context extension on both
476 * the context's device and the DeviceManager.
478 static void MakeThreadCurrent(Context context);
479 /** Retrieves the thread-specific context used for OpenAL operations. */
480 static Context GetThreadCurrent();
483 * Destroys the context. The context must not be current when this is
484 * called.
486 void destroy();
488 /** Retrieves the Device this context was created from. */
489 Device getDevice();
491 void startBatch();
492 void endBatch();
495 * Retrieves a Listener instance for this context. Each context will only
496 * have one listener, which is automatically destroyed with the context.
498 Listener getListener();
501 * Sets a MessageHandler instance which will be used to provide certain
502 * messages back to the application. Only one handler may be set for a
503 * context at a time. The previously set handler will be returned.
505 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
507 /** Gets the currently-set message handler. */
508 SharedPtr<MessageHandler> getMessageHandler() const;
511 * Specifies the desired interval that the background thread will be woken
512 * up to process tasks, e.g. keeping streaming sources filled. An interval
513 * of 0 means the background thread will only be woken up manually with
514 * calls to update. The default is 0.
516 void setAsyncWakeInterval(std::chrono::milliseconds interval);
519 * Retrieves the current interval used for waking up the background thread.
521 std::chrono::milliseconds getAsyncWakeInterval() const;
523 // Functions below require the context to be current
526 * Creates a Decoder instance for the given audio file or resource name.
528 SharedPtr<Decoder> createDecoder(StringView name);
531 * Queries if the channel configuration and sample type are supported by
532 * the context.
534 bool isSupported(ChannelConfig channels, SampleType type) const;
537 * Queries the list of resamplers supported by the context. If the
538 * AL_SOFT_source_resampler extension is unsupported this will be an empty
539 * array, otherwise there will be at least one entry.
541 ArrayView<String> getAvailableResamplers();
543 * Queries the context's default resampler index. Be aware, if the
544 * AL_SOFT_source_resampler extension is unsupported the resampler list
545 * will be empty and this will resturn 0. If you try to access the
546 * resampler list with this index without the extension, undefined behavior
547 * will occur (accessing an out of bounds array index).
549 ALsizei getDefaultResamplerIndex() const;
552 * Creates and caches a Buffer for the given audio file or resource name.
553 * Multiple calls with the same name will return the same Buffer object.
554 * Cached buffers must be freed using removeBuffer before destroying the
555 * context. If the buffer can't be loaded it will throw an exception.
557 Buffer getBuffer(StringView name);
560 * Asynchronously prepares a cached Buffer for the given audio file or
561 * resource name. Multiple calls with the same name will return multiple
562 * SharedFutures for the same Buffer object. Once called, the buffer must
563 * be freed using removeBuffer before destroying the context, even if you
564 * never get the Buffer from the SharedFuture.
566 * The Buffer will be scheduled to load asynchronously, and the caller gets
567 * back a SharedFuture that can be checked later (or waited on) to get the
568 * actual Buffer when it's ready. The application must take care to handle
569 * exceptions from the SharedFuture in case an unrecoverable error ocurred
570 * during the load.
572 SharedFuture<Buffer> getBufferAsync(StringView name);
575 * Asynchronously prepares cached Buffers for the given audio file or
576 * resource names. Duplicate names and buffers already cached are ignored.
577 * Cached buffers must be freed using removeBuffer before destroying the
578 * context.
580 * The Buffer objects will be scheduled for loading asynchronously, and
581 * should be retrieved later when needed using getBufferAsync or getBuffer.
582 * Buffers that cannot be loaded, for example due to an unsupported format,
583 * will be ignored and a later call to getBuffer or getBufferAsync will
584 * throw an exception.
586 void precacheBuffersAsync(ArrayView<StringView> names);
589 * Creates and caches a Buffer using the given name by reading the given
590 * decoder. The name may alias an audio file, but it must not currently
591 * exist in the buffer cache.
593 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
596 * Asynchronously prepares a cached Buffer using the given name by reading
597 * the given decoder. The name may alias an audio file, but it must not
598 * currently exist in the buffer cache. Once called, the buffer must be
599 * freed using removeBuffer before destroying the context, even if you
600 * never get the Buffer from the SharedFuture.
602 * The Buffer will be scheduled to load asynchronously, and the caller gets
603 * back a SharedFuture that can be checked later (or waited on) to get the
604 * actual Buffer when it's ready. The application must take care to handle
605 * exceptions from the SharedFuture in case an unrecoverable error ocurred
606 * during the load. The decoder must not have its read or seek methods
607 * called while the buffer is not ready.
609 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
612 * Looks for a cached buffer using the given name and returns it. If the
613 * given name does not exist in the cache, and null buffer is returned.
615 Buffer findBuffer(StringView name);
618 * Looks for an asynchronously-loading buffer using the given name and
619 * returns a SharedFuture for it. If the given name does not exist in the
620 * cache, an invalid SharedFuture is returned (check with a call to
621 * \c SharedFuture::valid).
623 SharedFuture<Buffer> findBufferAsync(StringView name);
626 * Deletes the cached Buffer object for the given audio file or resource
627 * name. The buffer must not be in use by a Source.
629 void removeBuffer(StringView name);
631 * Deletes the given cached buffer. The buffer must not be in use by a
632 * Source.
634 void removeBuffer(Buffer buffer);
637 * Creates a new Source for playing audio. There is no practical limit to
638 * the number of sources you may create. You must call Source::release when
639 * the source is no longer needed.
641 Source createSource();
643 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
645 Effect createEffect();
647 SourceGroup createSourceGroup(StringView name);
648 SourceGroup getSourceGroup(StringView name);
650 /** Sets the doppler factor to apply to all source doppler calculations. */
651 void setDopplerFactor(ALfloat factor);
654 * Sets the speed of sound propagation, in units per second, to calculate
655 * the doppler effect along with other distance-related time effects. The
656 * default is 343.3 units per second (a realistic speed assuming 1 meter
657 * per unit). If this is adjusted for a different unit scale,
658 * Listener::setMetersPerUnit should also be adjusted.
660 void setSpeedOfSound(ALfloat speed);
663 * Sets the distance model used to attenuate sources given their distance
664 * from the listener. The default, InverseClamped, provides a realistic 1/r
665 * reduction in volume (that is, every doubling of distance causes the gain
666 * to reduce by half).
668 * The Clamped distance models restrict the source distance for the purpose
669 * of distance attenuation, so a source won't sound closer than its
670 * reference distance or farther than its max distance.
672 void setDistanceModel(DistanceModel model);
674 /** Updates the context and all sources belonging to this context. */
675 void update();
678 class ALURE_API Listener {
679 MAKE_PIMPL(Listener, ListenerImpl)
681 public:
682 /** Sets the "master" gain for all context output. */
683 void setGain(ALfloat gain);
686 * Specifies the listener's 3D position, velocity, and orientation
687 * together (see: setPosition, setVelocity, and setOrientation).
689 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const std::pair<Vector3,Vector3> &orientation);
691 /** Specifies the listener's 3D position. */
692 void setPosition(ALfloat x, ALfloat y, ALfloat z);
693 void setPosition(const ALfloat *pos);
696 * Specifies the listener's 3D velocity, in units per second. As with
697 * OpenAL, this does not actually alter the listener's position, and
698 * instead just alters the pitch as determined by the doppler effect.
700 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
701 void setVelocity(const ALfloat *vel);
704 * Specifies the listener's 3D orientation, using position-relative 'at'
705 * and 'up' direction vectors.
707 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
708 void setOrientation(const ALfloat *at, const ALfloat *up);
709 void setOrientation(const ALfloat *ori);
712 * Sets the number of meters per unit, used for various effects that rely
713 * on the distance in meters (including air absorption and initial reverb
714 * decay). If this is changed, it's strongly recommended to also set the
715 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
716 * realistic 343.3m/s for sound propagation).
718 void setMetersPerUnit(ALfloat m_u);
722 class ALURE_API Buffer {
723 MAKE_PIMPL(Buffer, BufferImpl)
725 public:
726 /** Retrieves the length of the buffer in sample frames. */
727 ALuint getLength() const;
729 /** Retrieves the buffer's frequency in hz. */
730 ALuint getFrequency() const;
732 /** Retrieves the buffer's sample configuration. */
733 ChannelConfig getChannelConfig() const;
735 /** Retrieves the buffer's sample type. */
736 SampleType getSampleType() const;
739 * Retrieves the storage size used by the buffer, in bytes. Note that the
740 * size in bytes may not be what you expect from the length, as it may take
741 * more space internally than the ChannelConfig and SampleType suggest to
742 * be more efficient.
744 ALuint getSize() const;
747 * Sets the buffer's loop points, used for looping sources. If the current
748 * context does not support the AL_SOFT_loop_points extension, start and
749 * end must be 0 and getLength() respectively. Otherwise, start must be
750 * less than end, and end must be less than or equal to getLength().
752 * The buffer must not be in use when this method is called.
754 * \param start The starting point, in sample frames (inclusive).
755 * \param end The ending point, in sample frames (exclusive).
757 void setLoopPoints(ALuint start, ALuint end);
759 /** Retrieves the current loop points as a [start,end) pair. */
760 std::pair<ALuint,ALuint> getLoopPoints() const;
763 * Retrieves the Source objects currently playing the buffer. Stopping the
764 * returned sources will allow the buffer to be removed from the context.
766 Vector<Source> getSources() const;
768 /** Retrieves the name the buffer was created with. */
769 StringView getName() const;
771 /** Queries if the buffer is in use and can't be removed. */
772 bool isInUse() const;
776 enum class Spatialize {
777 Off = AL_FALSE,
778 On = AL_TRUE,
779 Auto = 0x0002 /* AL_AUTO_SOFT */
782 class ALURE_API Source {
783 MAKE_PIMPL(Source, SourceImpl)
785 public:
787 * Plays the source using a buffer. The same buffer may be played from
788 * multiple sources simultaneously.
790 void play(Buffer buffer);
792 * Plays the source by asynchronously streaming audio from a decoder. The
793 * given decoder must *NOT* have its read or seek methods called from
794 * elsewhere while in use.
796 * \param decoder The decoder object to play audio from.
797 * \param chunk_len The number of sample frames to read for each chunk
798 * update. Smaller values will require more frequent updates and
799 * larger values will handle more data with each chunk.
800 * \param queue_size The number of chunks to keep queued during playback.
801 * Smaller values use less memory while larger values improve
802 * protection against underruns.
804 void play(SharedPtr<Decoder> decoder, ALuint chunk_len, ALuint queue_size);
807 * Prepares to play a source using a future buffer. The method will return
808 * right away and the source will begin playing once the future buffer
809 * becomes ready. If the future buffer is already ready, it begins playing
810 * immediately as if you called play(future_buffer.get()).
812 * The future buffer is checked during calls to \c Context::update and the
813 * source will start playback once the future buffer reports it's ready.
814 * Use the isPending method to check if the source is still waiting for the
815 * future buffer.
817 void play(SharedFuture<Buffer> future_buffer);
820 * Stops playback, releasing the buffer or decoder reference. Any pending
821 * playback from a future buffer is canceled.
823 void stop();
826 * Fades the source to the specified gain over the given duration, at which
827 * point playback will stop. This gain is in addition to the base gain, and
828 * must be greater than 0 and less than 1. The duration must also be
829 * greater than 0.
831 * Pending playback from a future buffer is not immediately canceled, but
832 * the fading starts with this call. If the future buffer then becomes
833 * ready, it will start mid-fade. Pending playback will be canceled if the
834 * fade out completes before the future buffer becomes ready.
836 * Fading is updated during calls to \c Context::update, which should be
837 * called regularly (30 to 50 times per second) for the fading to be
838 * smooth.
840 void fadeOutToStop(ALfloat gain, std::chrono::milliseconds duration);
842 /** Pauses the source if it is playing. */
843 void pause();
845 /** Resumes the source if it is paused. */
846 void resume();
848 /** Specifies if the source is waiting to play a future buffer. */
849 bool isPending() const;
851 /** Specifies if the source is currently playing. */
852 bool isPlaying() const;
854 /** Specifies if the source is currently paused. */
855 bool isPaused() const;
858 * Sets this source as a child of the given source group. The given source
859 * group's parameters will influence this and all other sources that belong
860 * to it. A source can only be the child of one source group at a time,
861 * although that source group may belong to another source group.
863 * Passing in a null group removes it from its current source group.
865 void setGroup(SourceGroup group);
867 /** Retrieves the source group this source belongs to. */
868 SourceGroup getGroup() const;
871 * Specifies the source's playback priority. The lowest priority sources
872 * will be forcefully stopped when no more mixing sources are available and
873 * 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 based on the
888 * decoder's read position.
890 * If the AL_SOFT_source_latency extension is unsupported, the latency will
891 * be 0.
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 based on the decoder's read position.
899 * If the AL_SOFT_source_latency extension is unsupported, the latency will
900 * be 0.
902 std::pair<Seconds,Seconds> getSecOffsetLatency() const;
903 Seconds getSecOffset() const { return std::get<0>(getSecOffsetLatency()); }
906 * Specifies if the source should loop on the Buffer or Decoder object's
907 * loop points.
909 void setLooping(bool looping);
910 bool getLooping() const;
913 * Specifies a linear pitch shift base. A value of 1.0 is the default
914 * normal speed.
916 void setPitch(ALfloat pitch);
917 ALfloat getPitch() const;
920 * Specifies the base linear gain. A value of 1.0 is the default normal
921 * volume.
923 void setGain(ALfloat gain);
924 ALfloat getGain() const;
927 * Specifies the minimum and maximum gain. The source's gain is clamped to
928 * this range after distance attenuation and cone attenuation are applied
929 * to the gain base, although before the filter gain adjustements.
931 void setGainRange(ALfloat mingain, ALfloat maxgain);
932 std::pair<ALfloat,ALfloat> getGainRange() const;
933 ALfloat getMinGain() const { return std::get<0>(getGainRange()); }
934 ALfloat getMaxGain() const { return std::get<1>(getGainRange()); }
937 * Specifies the reference distance and maximum distance the source will
938 * use for the current distance model. For Clamped distance models, the
939 * source's calculated distance is clamped to the specified range before
940 * applying distance-related attenuation.
942 * For all distance models, the reference distance is the distance at which
943 * the source's volume will not have any extra attenuation (an effective
944 * gain multiplier of 1).
946 void setDistanceRange(ALfloat refdist, ALfloat maxdist);
947 std::pair<ALfloat,ALfloat> getDistanceRange() const;
948 ALfloat getReferenceDistance() const { return std::get<0>(getDistanceRange()); }
949 ALfloat getMaxDistance() const { return std::get<1>(getDistanceRange()); }
952 * Specifies the source's 3D position, velocity, and direction together
953 * (see: setPosition, setVelocity, and setDirection).
955 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const Vector3 &direction);
958 * Specifies the source's 3D position, velocity, and orientation together
959 * (see: setPosition, setVelocity, and setOrientation).
961 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const std::pair<Vector3,Vector3> &orientation);
963 /** Specifies the source's 3D position. */
964 void setPosition(ALfloat x, ALfloat y, ALfloat z);
965 void setPosition(const ALfloat *pos);
966 Vector3 getPosition() const;
969 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
970 * this does not actually alter the source's position, and instead just
971 * alters the pitch as determined by the doppler effect.
973 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
974 void setVelocity(const ALfloat *vel);
975 Vector3 getVelocity() const;
978 * Specifies the source's 3D facing direction. Deprecated in favor of
979 * setOrientation.
981 void setDirection(ALfloat x, ALfloat y, ALfloat z);
982 void setDirection(const ALfloat *dir);
983 Vector3 getDirection() const;
986 * Specifies the source's 3D orientation, using position-relative 'at' and
987 * 'up' direction vectors. Note: unlike the AL_EXT_BFORMAT extension this
988 * property comes from, this also affects the facing direction, superceding
989 * setDirection.
991 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
992 void setOrientation(const ALfloat *at, const ALfloat *up);
993 void setOrientation(const ALfloat *ori);
994 std::pair<Vector3,Vector3> getOrientation() const;
997 * Specifies the source's cone angles, in degrees. The inner angle is the
998 * area within which the listener will hear the source with no extra
999 * attenuation, while the listener being outside of the outer angle will
1000 * hear the source attenuated according to the outer cone gains. The area
1001 * follows the facing direction, so for example an inner angle of 180 means
1002 * the entire front face of the source is in the inner cone.
1004 void setConeAngles(ALfloat inner, ALfloat outer);
1005 std::pair<ALfloat,ALfloat> getConeAngles() const;
1006 ALfloat getInnerConeAngle() const { return std::get<0>(getConeAngles()); }
1007 ALfloat getOuterConeAngle() const { return std::get<1>(getConeAngles()); }
1010 * Specifies the linear gain multiplier when the listener is outside of the
1011 * source's outer cone area. The specified gain applies to all frequencies,
1012 * while gainhf applies extra attenuation to high frequencies creating a
1013 * low-pass effect.
1015 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1017 void setOuterConeGains(ALfloat gain, ALfloat gainhf=1.0f);
1018 std::pair<ALfloat,ALfloat> getOuterConeGains() const;
1019 ALfloat getOuterConeGain() const { return std::get<0>(getOuterConeGains()); }
1020 ALfloat getOuterConeGainHF() const { return std::get<1>(getOuterConeGains()); }
1023 * Specifies the rolloff factors for the direct and send paths. This is
1024 * effectively a distance scaling relative to the reference distance. Note:
1025 * the room rolloff factor is 0 by default, disabling distance attenuation
1026 * for send paths. This is because the reverb engine will, by default,
1027 * apply a more realistic room decay based on the reverb decay time and
1028 * distance.
1030 void setRolloffFactors(ALfloat factor, ALfloat roomfactor=0.0f);
1031 std::pair<ALfloat,ALfloat> getRolloffFactors() const;
1032 ALfloat getRolloffFactor() const { return std::get<0>(getRolloffFactors()); }
1033 ALfloat getRoomRolloffFactor() const { return std::get<1>(getRolloffFactors()); }
1036 * Specifies the doppler factor for the doppler effect's pitch shift. This
1037 * effectively scales the source and listener velocities for the doppler
1038 * calculation.
1040 void setDopplerFactor(ALfloat factor);
1041 ALfloat getDopplerFactor() const;
1044 * Specifies if the source's position, velocity, and direction/orientation
1045 * are relative to the listener.
1047 void setRelative(bool relative);
1048 bool getRelative() const;
1051 * Specifies the source's radius. This causes the source to behave as if
1052 * every point within the spherical area emits sound.
1054 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1056 void setRadius(ALfloat radius);
1057 ALfloat getRadius() const;
1060 * Specifies the left and right channel angles, in radians, when playing a
1061 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1062 * in front and positive values going left.
1064 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1066 void setStereoAngles(ALfloat leftAngle, ALfloat rightAngle);
1067 std::pair<ALfloat,ALfloat> getStereoAngles() const;
1070 * Specifies if the source always has 3D spatialization features (On),
1071 * never has 3D spatialization features (Off), or if spatialization is
1072 * enabled based on playing a mono sound or not (Auto, default).
1074 * Has no effect without the AL_SOFT_source_spatialize extension.
1076 void set3DSpatialize(Spatialize spatialize);
1077 Spatialize get3DSpatialize() const;
1080 * Specifies the index of the resampler to use for this source. The index
1081 * is from the resamplers returned by \c Context::getAvailableResamplers,
1082 * and must be 0 or greater.
1084 * Has no effect without the AL_SOFT_source_resampler extension.
1086 void setResamplerIndex(ALsizei index);
1087 ALsizei getResamplerIndex() const;
1090 * Specifies a multiplier for the amount of atmospheric high-frequency
1091 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1092 * -0.05dB per meter, with higher values simulating foggy air and lower
1093 * values simulating dryer air. The default is 0.
1095 void setAirAbsorptionFactor(ALfloat factor);
1096 ALfloat getAirAbsorptionFactor() const;
1099 * Specifies to automatically apply adjustments to the direct path's high-
1100 * frequency gain, and the send paths' gain and high-frequency gain. The
1101 * default is true for all.
1103 void setGainAuto(bool directhf, bool send, bool sendhf);
1104 std::tuple<bool,bool,bool> getGainAuto() const;
1105 bool getDirectGainHFAuto() const { return std::get<0>(getGainAuto()); }
1106 bool getSendGainAuto() const { return std::get<1>(getGainAuto()); }
1107 bool getSendGainHFAuto() const { return std::get<2>(getGainAuto()); }
1109 /** Sets the filter properties on the direct path signal. */
1110 void setDirectFilter(const FilterParams &filter);
1112 * Sets the filter properties on the given send path signal. Any auxiliary
1113 * effect slot on the send path remains in place.
1115 void setSendFilter(ALuint send, const FilterParams &filter);
1117 * Connects the effect slot to the given send path. Any filter properties
1118 * on the send path remain as they were.
1120 void setAuxiliarySend(AuxiliaryEffectSlot slot, ALuint send);
1122 * Connects the effect slot to the given send path, using the filter
1123 * properties.
1125 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot, ALuint send, const FilterParams &filter);
1128 * Releases the source, stopping playback, releasing resources, and
1129 * returning it to the system.
1131 void release();
1135 class ALURE_API SourceGroup {
1136 MAKE_PIMPL(SourceGroup, SourceGroupImpl)
1138 public:
1139 /** Retrieves the associated name of the source group. */
1140 StringView getName() const;
1143 * Adds this source group as a subgroup of the specified source group. This
1144 * method will throw an exception if this group is being added to a group
1145 * it has as a sub-group (i.e. it would create a circular sub-group chain).
1147 void setParentGroup(SourceGroup group);
1149 /** Retrieves the source group this source group is a child of. */
1150 SourceGroup getParentGroup() const;
1152 /** Returns the list of sources currently in the group. */
1153 Vector<Source> getSources() const;
1155 /** Returns the list of subgroups currently in the group. */
1156 Vector<SourceGroup> getSubGroups() const;
1159 * Sets the source group gain, which accumulates with its sources' and
1160 * sub-groups' gain.
1162 void setGain(ALfloat gain);
1163 /** Gets the source group gain. */
1164 ALfloat getGain() const;
1167 * Sets the source group pitch, which accumulates with its sources' and
1168 * sub-groups' pitch.
1170 void setPitch(ALfloat pitch);
1171 /** Gets the source group pitch. */
1172 ALfloat getPitch() const;
1175 * Pauses all currently-playing sources that are under this group,
1176 * including sub-groups.
1178 void pauseAll() const;
1180 * Resumes all paused sources that are under this group, including
1181 * sub-groups.
1183 void resumeAll() const;
1185 /** Stops all sources that are under this group, including sub-groups. */
1186 void stopAll() const;
1189 * Releases the source group, removing all sources from it before being
1190 * freed.
1192 void release();
1196 struct SourceSend {
1197 Source mSource;
1198 ALuint mSend;
1201 class ALURE_API AuxiliaryEffectSlot {
1202 MAKE_PIMPL(AuxiliaryEffectSlot, AuxiliaryEffectSlotImpl)
1204 public:
1205 void setGain(ALfloat gain);
1207 * If set to true, the reverb effect will automatically apply adjustments
1208 * to the source's send slot gains based on the effect properties.
1210 * Has no effect when using non-reverb effects. Default is true.
1212 void setSendAuto(bool sendauto);
1215 * Updates the effect slot with a new effect. The given effect object may
1216 * be altered or destroyed without affecting the effect slot.
1218 void applyEffect(Effect effect);
1221 * Releases the effect slot, returning it to the system. It must not be in
1222 * use by a source.
1224 void release();
1227 * Retrieves each Source object and its pairing send this effect slot is
1228 * set on. Setting a different (or null) effect slot on each source's given
1229 * send will allow the effect slot to be released.
1231 Vector<SourceSend> getSourceSends() const;
1233 /** Determines if the effect slot is in use by a source. */
1234 bool isInUse() const;
1238 class ALURE_API Effect {
1239 MAKE_PIMPL(Effect, EffectImpl)
1241 public:
1243 * Updates the effect with the specified reverb properties. If the
1244 * EAXReverb effect is not supported, it will automatically attempt to
1245 * downgrade to the Standard Reverb effect.
1247 void setReverbProperties(const EFXEAXREVERBPROPERTIES &props);
1249 void destroy();
1254 * Audio decoder interface. Applications may derive from this, implementing the
1255 * necessary methods, and use it in places the API wants a Decoder object.
1257 class ALURE_API Decoder {
1258 public:
1259 virtual ~Decoder();
1261 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1262 virtual ALuint getFrequency() const = 0;
1263 /** Retrieves the channel configuration of the audio being decoded. */
1264 virtual ChannelConfig getChannelConfig() const = 0;
1265 /** Retrieves the sample type of the audio being decoded. */
1266 virtual SampleType getSampleType() const = 0;
1269 * Retrieves the total length of the audio, in sample frames. If unknown,
1270 * returns 0. Note that if the returned length is 0, the decoder may not be
1271 * used to load a Buffer.
1273 virtual uint64_t getLength() const = 0;
1275 * Seek to pos, specified in sample frames. Returns true if the seek was
1276 * successful.
1278 virtual bool seek(uint64_t pos) = 0;
1281 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1282 * start >= end, all available samples are included in the loop.
1284 virtual std::pair<uint64_t,uint64_t> getLoopPoints() const = 0;
1287 * Decodes count sample frames, writing them to ptr, and returns the number
1288 * of sample frames written. Returning less than the requested count
1289 * indicates the end of the audio.
1291 virtual ALuint read(ALvoid *ptr, ALuint count) = 0;
1295 * Audio decoder factory interface. Applications may derive from this,
1296 * implementing the necessary methods, and use it in places the API wants a
1297 * DecoderFactory object.
1299 class ALURE_API DecoderFactory {
1300 public:
1301 virtual ~DecoderFactory();
1304 * Creates and returns a Decoder instance for the given resource file. If
1305 * the decoder needs to retain the file handle for reading as-needed, it
1306 * should move the UniquePtr to internal storage.
1308 * \return nullptr if a decoder can't be created from the file.
1310 virtual SharedPtr<Decoder> createDecoder(UniquePtr<std::istream> &file) = 0;
1314 * Registers a decoder factory for decoding audio. Registered factories are
1315 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1316 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1317 * name1 < name2. Internal decoder factories are always used after registered
1318 * ones.
1320 * Alure retains a reference to the DecoderFactory instance and will release it
1321 * (destructing the object) when the library unloads.
1323 * \param name A unique name identifying this decoder factory.
1324 * \param factory A DecoderFactory instance used to create Decoder instances.
1326 ALURE_API void RegisterDecoder(StringView name, UniquePtr<DecoderFactory> factory);
1329 * Unregisters a decoder factory by name. Alure returns the instance back to
1330 * the application.
1332 * \param name The unique name identifying a previously-registered decoder
1333 * factory.
1335 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1336 * decoder factory with the given name doesn't exist.
1338 ALURE_API UniquePtr<DecoderFactory> UnregisterDecoder(StringView name);
1342 * A file I/O factory interface. Applications may derive from this and set an
1343 * instance to be used by the audio decoders. By default, the library uses
1344 * standard I/O.
1346 class ALURE_API FileIOFactory {
1347 public:
1349 * Sets the factory instance to be used by the audio decoders. If a
1350 * previous factory was set, it's returned to the application. Passing in a
1351 * nullptr reverts to the default.
1353 static UniquePtr<FileIOFactory> set(UniquePtr<FileIOFactory> factory);
1356 * Gets the current FileIOFactory instance being used by the audio
1357 * decoders.
1359 static FileIOFactory &get();
1361 virtual ~FileIOFactory();
1363 /** Opens a read-only binary file for the given name. */
1364 virtual UniquePtr<std::istream> openFile(const String &name) = 0;
1369 * A message handler interface. Applications may derive from this and set an
1370 * instance on a context to receive messages. The base methods are no-ops, so
1371 * derived classes only need to implement methods for relevant messages.
1373 * It's recommended that applications mark their handler methods using the
1374 * override keyword, to ensure they're properly overriding the base methods in
1375 * case they change.
1377 class ALURE_API MessageHandler {
1378 public:
1379 virtual ~MessageHandler();
1382 * Called when the given device has been disconnected and is no longer
1383 * usable for output. As per the ALC_EXT_disconnect specification,
1384 * disconnected devices remain valid, however all playing sources are
1385 * automatically stopped, any sources that are attempted to play will
1386 * immediately stop, and new contexts may not be created on the device.
1388 * Note that connection status is checked during Context::update calls, so
1389 * that method must be called regularly to be notified when a device is
1390 * disconnected. This method may not be called if the device lacks support
1391 * for the ALC_EXT_disconnect extension.
1393 virtual void deviceDisconnected(Device device);
1396 * Called when the given source reaches the end of the buffer or stream.
1398 * Sources that stopped automatically will be detected upon a call to
1399 * Context::update.
1401 virtual void sourceStopped(Source source);
1404 * Called when the given source was forced to stop. This can be because
1405 * either there were no more mixing sources and a higher-priority source
1406 * preempted it, or it's part of a SourceGroup (or sub-group thereof) that
1407 * had its SourceGroup::stopAll method called.
1409 virtual void sourceForceStopped(Source source);
1412 * Called when a new buffer is about to be created and loaded. May be
1413 * called asynchronously for buffers being loaded asynchronously.
1415 * \param name The resource name, as passed to Context::getBuffer.
1416 * \param channels Channel configuration of the given audio data.
1417 * \param type Sample type of the given audio data.
1418 * \param samplerate Sample rate of the given audio data.
1419 * \param data The audio data that is about to be fed to the OpenAL buffer.
1421 virtual void bufferLoading(StringView name, ChannelConfig channels, SampleType type, ALuint samplerate, ArrayView<ALbyte> data);
1424 * Called when a resource isn't found, allowing the app to substitute in a
1425 * different resource. For buffers being cached, the original name will
1426 * still be used for the cache entry so the app doesn't have to keep track
1427 * of substituted resource names.
1429 * This will be called again if the new name also isn't found.
1431 * \param name The resource name that was not found.
1432 * \return The replacement resource name to use instead. Returning an empty
1433 * string means to stop trying.
1435 virtual String resourceNotFound(StringView name);
1438 #undef MAKE_PIMPL
1440 } // namespace alure
1442 #endif /* AL_ALURE2_H */