Add an AutoObj container to auto-destroy resources
[alure.git] / include / AL / alure2.h
blob801ecdc67b406972881ed313c081a555cc8e62a0
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 */
32 #ifndef ALURE_TEMPLATE
33 #ifndef ALURE_STATIC_LIB
34 #define ALURE_TEMPLATE extern template
35 #else
36 #define ALURE_TEMPLATE template
37 #endif
38 #endif /* ALURE_TEMPLATE */
40 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
41 #define EFXEAXREVERBPROPERTIES_DEFINED
42 typedef struct {
43 float flDensity;
44 float flDiffusion;
45 float flGain;
46 float flGainHF;
47 float flGainLF;
48 float flDecayTime;
49 float flDecayHFRatio;
50 float flDecayLFRatio;
51 float flReflectionsGain;
52 float flReflectionsDelay;
53 float flReflectionsPan[3];
54 float flLateReverbGain;
55 float flLateReverbDelay;
56 float flLateReverbPan[3];
57 float flEchoTime;
58 float flEchoDepth;
59 float flModulationTime;
60 float flModulationDepth;
61 float flAirAbsorptionGainHF;
62 float flHFReference;
63 float flLFReference;
64 float flRoomRolloffFactor;
65 int iDecayHFLimit;
66 } EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
67 #endif
69 #ifndef EFXCHORUSPROPERTIES_DEFINED
70 #define EFXCHORUSPROPERTIES_DEFINED
71 typedef struct {
72 int iWaveform;
73 int iPhase;
74 float flRate;
75 float flDepth;
76 float flFeedback;
77 float flDelay;
78 } EFXCHORUSPROPERTIES, *LPEFXCHORUSPROPERTIES;
79 #endif
81 namespace alure {
83 // Available class interfaces.
84 class DeviceManager;
85 class Device;
86 class Context;
87 class Listener;
88 class Buffer;
89 class Source;
90 class SourceGroup;
91 class AuxiliaryEffectSlot;
92 class Effect;
93 class Decoder;
94 class DecoderFactory;
95 class FileIOFactory;
96 class MessageHandler;
98 // Opaque class implementations.
99 class DeviceManagerImpl;
100 class DeviceImpl;
101 class ContextImpl;
102 class ListenerImpl;
103 class BufferImpl;
104 class SourceImpl;
105 class SourceGroupImpl;
106 class AuxiliaryEffectSlotImpl;
107 class EffectImpl;
111 #ifndef ALURE_STATIC_LIB
112 /****** Explicitly instantiate templates used by the lib ******/
113 ALURE_TEMPLATE class ALURE_API ALURE_SHARED_PTR_TYPE<alure::DeviceManagerImpl>;
114 /******/
115 #endif
117 namespace alure {
119 /** Convert a value from decibels to linear gain. */
120 inline float dBToLinear(float value) { return std::pow(10.0f, value / 20.0f); }
121 inline double dBToLinear(double value) { return std::pow(10.0, value / 20.0); }
122 inline double dBToLinear(int value) { return dBToLinear(double(value)); }
124 /** Convert a value from linear gain to decibels. */
125 inline float LinearTodB(float value) { return std::log10(value) * 20.0f; }
126 inline double LinearTodB(double value) { return std::log10(value) * 20.0; }
129 * An attribute pair, for passing attributes to Device::createContext and
130 * Device::reset.
132 using AttributePair = std::pair<ALCint,ALCint>;
133 static_assert(sizeof(AttributePair) == sizeof(ALCint[2]), "Bad AttributePair size");
134 inline AttributePair AttributesEnd() noexcept { return std::make_pair(0, 0); }
137 struct FilterParams {
138 ALfloat mGain;
139 ALfloat mGainHF; // For low-pass and band-pass filters
140 ALfloat mGainLF; // For high-pass and band-pass filters
144 class Vector3 {
145 Array<ALfloat,3> mValue;
147 public:
148 constexpr Vector3() noexcept
149 : mValue{{0.0f, 0.0f, 0.0f}}
151 constexpr Vector3(const Vector3 &rhs) noexcept
152 : mValue{{rhs.mValue[0], rhs.mValue[1], rhs.mValue[2]}}
154 constexpr Vector3(ALfloat val) noexcept
155 : mValue{{val, val, val}}
157 constexpr Vector3(ALfloat x, ALfloat y, ALfloat z) noexcept
158 : mValue{{x, y, z}}
160 Vector3(const ALfloat *vec) noexcept
161 : mValue{{vec[0], vec[1], vec[2]}}
164 const ALfloat *getPtr() const noexcept
165 { return mValue.data(); }
167 ALfloat& operator[](size_t i) noexcept
168 { return mValue[i]; }
169 constexpr const ALfloat& operator[](size_t i) const noexcept
170 { return mValue[i]; }
172 #define ALURE_DECL_OP(op) \
173 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
175 return Vector3(mValue[0] op rhs.mValue[0], \
176 mValue[1] op rhs.mValue[1], \
177 mValue[2] op rhs.mValue[2]); \
179 ALURE_DECL_OP(+)
180 ALURE_DECL_OP(-)
181 ALURE_DECL_OP(*)
182 ALURE_DECL_OP(/)
183 #undef ALURE_DECL_OP
184 #define ALURE_DECL_OP(op) \
185 Vector3& operator op(const Vector3 &rhs) noexcept \
187 mValue[0] op rhs.mValue[0]; \
188 mValue[1] op rhs.mValue[1]; \
189 mValue[2] op rhs.mValue[2]; \
190 return *this; \
192 ALURE_DECL_OP(+=)
193 ALURE_DECL_OP(-=)
194 ALURE_DECL_OP(*=)
195 ALURE_DECL_OP(/=)
197 #undef ALURE_DECL_OP
198 #define ALURE_DECL_OP(op) \
199 constexpr Vector3 operator op(ALfloat scale) const noexcept \
201 return Vector3(mValue[0] op scale, \
202 mValue[1] op scale, \
203 mValue[2] op scale); \
205 ALURE_DECL_OP(*)
206 ALURE_DECL_OP(/)
207 #undef ALURE_DECL_OP
208 #define ALURE_DECL_OP(op) \
209 Vector3& operator op(ALfloat scale) noexcept \
211 mValue[0] op scale; \
212 mValue[1] op scale; \
213 mValue[2] op scale; \
214 return *this; \
216 ALURE_DECL_OP(*=)
217 ALURE_DECL_OP(/=)
218 #undef ALURE_DECL_OP
220 constexpr ALfloat getLengthSquared() const noexcept
221 { return mValue[0]*mValue[0] + mValue[1]*mValue[1] + mValue[2]*mValue[2]; }
222 ALfloat getLength() const noexcept
223 { return std::sqrt(getLengthSquared()); }
225 constexpr ALfloat getDistanceSquared(const Vector3 &pos) const noexcept
226 { return (pos - *this).getLengthSquared(); }
227 ALfloat getDistance(const Vector3 &pos) const noexcept
228 { return (pos - *this).getLength(); }
230 static_assert(sizeof(Vector3) == sizeof(ALfloat[3]), "Bad Vector3 size");
233 enum class SampleType {
234 UInt8,
235 Int16,
236 Float32,
237 Mulaw
239 ALURE_API const char *GetSampleTypeName(SampleType type);
241 enum class ChannelConfig {
242 /** 1-channel mono sound. */
243 Mono,
244 /** 2-channel stereo sound. */
245 Stereo,
246 /** 2-channel rear sound (back-left and back-right). */
247 Rear,
248 /** 4-channel surround sound. */
249 Quad,
250 /** 5.1 surround sound. */
251 X51,
252 /** 6.1 surround sound. */
253 X61,
254 /** 7.1 surround sound. */
255 X71,
256 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
257 BFormat2D,
258 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
259 BFormat3D
261 ALURE_API const char *GetChannelConfigName(ChannelConfig cfg);
263 ALURE_API ALuint FramesToBytes(ALuint frames, ChannelConfig chans, SampleType type);
264 ALURE_API ALuint BytesToFrames(ALuint bytes, ChannelConfig chans, SampleType type) noexcept;
267 /** Class for storing a major.minor version number. */
268 class Version {
269 ALuint mMajor : 16;
270 ALuint mMinor : 16;
272 public:
273 constexpr Version() noexcept : mMajor(0), mMinor(0) { }
274 constexpr Version(ALuint _maj, ALuint _min) noexcept : mMajor(_maj), mMinor(_min) { }
275 constexpr Version(const Version&) noexcept = default;
277 constexpr ALuint getMajor() const noexcept { return mMajor; }
278 constexpr ALuint getMinor() const noexcept { return mMinor; }
280 constexpr bool operator==(const Version &rhs) const noexcept
281 { return mMajor == rhs.mMajor && mMinor == rhs.mMinor; }
282 constexpr bool operator!=(const Version &rhs) const noexcept
283 { return !(*this == rhs); }
284 constexpr bool operator<=(const Version &rhs) const noexcept
285 { return mMajor < rhs.mMajor || (mMajor == rhs.mMajor && mMinor <= rhs.mMinor); }
286 constexpr bool operator>=(const Version &rhs) const noexcept
287 { return mMajor > rhs.mMajor || (mMajor == rhs.mMajor && mMinor >= rhs.mMinor); }
288 constexpr bool operator<(const Version &rhs) const noexcept
289 { return mMajor < rhs.mMajor || (mMajor == rhs.mMajor && mMinor < rhs.mMinor); }
290 constexpr bool operator>(const Version &rhs) const noexcept
291 { return mMajor > rhs.mMajor || (mMajor == rhs.mMajor && mMinor > rhs.mMinor); }
293 constexpr bool isZero() const noexcept { return *this == Version{0,0}; }
297 // Tag type to disctate which types are allowed in AutoObj.
298 template<typename T> struct IsAutoable : std::false_type { };
299 template<> struct IsAutoable<Context> : std::true_type { };
300 template<> struct IsAutoable<Source> : std::true_type { };
301 template<> struct IsAutoable<SourceGroup> : std::true_type { };
302 template<> struct IsAutoable<AuxiliaryEffectSlot> : std::true_type { };
303 template<> struct IsAutoable<Effect> : std::true_type { };
306 * A local storage container to manage objects in a non-copyable, movable, and
307 * auto-destructed manner. Any contained object will have its destroy() method
308 * invoked prior to being overwritten or when going out of scope. The purpose
309 * of this is to optionally provide RAII semantics to Alure's resources, such
310 * as contexts, sources, and effects.
312 * Be aware that destruction order is important, as contexts ultimately "own"
313 * the resources created from them. Said resources automatically become invalid
314 * when their owning context is destroyed. Any AutoObjs containing sources,
315 * effects, etc, should already be destroyed or cleared prior to the context
316 * being destroyed.
318 * Also, it is possible for resource destruction to fail if the destroy()
319 * method is called incorrectly (e.g. destroying a source when a different
320 * context is current). This normally results in an exception, but because
321 * destructors aren't allowed to let exceptions leave the function body,
322 * std::terminate will be called as a fatal error instead.
324 template<typename T>
325 class AutoObj {
326 static_assert(IsAutoable<T>::value, "Invalid type for AutoObj");
328 T mObj;
330 public:
331 using element_type = T;
333 AutoObj() noexcept = default;
334 AutoObj(const AutoObj&) = delete;
335 AutoObj(AutoObj &&rhs) noexcept : mObj(rhs.mObj) { rhs.mObj = nullptr; }
336 AutoObj(std::nullptr_t) noexcept : mObj(nullptr) { }
337 explicit AutoObj(const element_type &rhs) noexcept : mObj(rhs) { }
338 ~AutoObj() { if(mObj) mObj.destroy(); }
340 AutoObj& operator=(const AutoObj&) = delete;
341 AutoObj& operator=(AutoObj &&rhs)
343 if(mObj) mObj.destroy();
344 mObj = rhs.mObj;
345 rhs.mObj = nullptr;
346 return *this;
349 AutoObj& reset(const element_type &obj)
351 if(mObj) mObj.destroy();
352 mObj = obj;
353 return *this;
356 element_type release() noexcept
358 element_type ret = mObj;
359 mObj = nullptr;
360 return ret;
363 element_type& get() noexcept { return mObj; }
365 element_type& operator*() noexcept { return mObj; }
366 element_type* operator->() noexcept { return &mObj; }
369 /** Creates an AutoObj for the given input object type. */
370 template<typename T>
371 inline AutoObj<T> MakeAuto(const T &obj) { return AutoObj<T>(obj); }
374 enum class DeviceEnumeration {
375 Basic = ALC_DEVICE_SPECIFIER,
376 Full = ALC_ALL_DEVICES_SPECIFIER,
377 Capture = ALC_CAPTURE_DEVICE_SPECIFIER
380 enum class DefaultDeviceType {
381 Basic = ALC_DEFAULT_DEVICE_SPECIFIER,
382 Full = ALC_DEFAULT_ALL_DEVICES_SPECIFIER,
383 Capture = ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
387 * A class managing Device objects and other related functionality. This class
388 * is a singleton, only one instance will exist in a process at a time.
390 class ALURE_API DeviceManager {
391 SharedPtr<DeviceManagerImpl> pImpl;
393 DeviceManager(SharedPtr<DeviceManagerImpl>&& impl) noexcept;
395 public:
397 * Retrieves a reference-counted DeviceManager instance. When the last
398 * reference goes out of scope, the DeviceManager and any remaining managed
399 * resources are automatically cleaned up. Multiple calls will return the
400 * same instance as long as there is still a pre-existing reference to the
401 * instance, or else a new instance will be created.
403 static DeviceManager getInstance();
405 DeviceManager() noexcept = default;
406 DeviceManager(const DeviceManager&) noexcept = default;
407 DeviceManager(DeviceManager&& rhs) noexcept = default;
408 ~DeviceManager();
410 DeviceManager& operator=(const DeviceManager&) noexcept = default;
411 DeviceManager& operator=(DeviceManager&&) noexcept = default;
412 DeviceManager& operator=(std::nullptr_t) noexcept { pImpl = nullptr; return *this; };
414 operator bool() const noexcept { return pImpl != nullptr; }
416 /** Queries the existence of a non-device-specific ALC extension. */
417 bool queryExtension(const String &name) const;
418 bool queryExtension(const char *name) const;
420 /** Enumerates available device names of the given type. */
421 Vector<String> enumerate(DeviceEnumeration type) const;
422 /** Retrieves the default device of the given type. */
423 String defaultDeviceName(DefaultDeviceType type) const;
426 * Opens the playback device given by name, or the default if blank. Throws
427 * an exception on error.
429 Device openPlayback(const String &name={});
430 Device openPlayback(const char *name);
433 * Opens the playback device given by name, or the default if blank.
434 * Returns an empty Device on error.
436 Device openPlayback(const String &name, const std::nothrow_t&) noexcept;
437 Device openPlayback(const char *name, const std::nothrow_t&) noexcept;
439 /** Opens the default playback device. Returns an empty Device on error. */
440 Device openPlayback(const std::nothrow_t&) noexcept;
444 #define MAKE_PIMPL(BaseT, ImplT) \
445 private: \
446 ImplT *pImpl; \
448 public: \
449 using handle_type = ImplT*; \
451 BaseT() noexcept : pImpl(nullptr) { } \
452 BaseT(ImplT *impl) noexcept : pImpl(impl) { } \
453 BaseT(const BaseT&) noexcept = default; \
454 BaseT(BaseT&& rhs) noexcept : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
456 BaseT& operator=(const BaseT&) noexcept = default; \
457 BaseT& operator=(BaseT&& rhs) noexcept \
459 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
460 return *this; \
463 bool operator==(const BaseT &rhs) const noexcept \
464 { return pImpl == rhs.pImpl; } \
465 bool operator!=(const BaseT &rhs) const noexcept \
466 { return pImpl != rhs.pImpl; } \
467 bool operator<=(const BaseT &rhs) const noexcept \
468 { return pImpl <= rhs.pImpl; } \
469 bool operator>=(const BaseT &rhs) const noexcept \
470 { return pImpl >= rhs.pImpl; } \
471 bool operator<(const BaseT &rhs) const noexcept \
472 { return pImpl < rhs.pImpl; } \
473 bool operator>(const BaseT &rhs) const noexcept \
474 { return pImpl > rhs.pImpl; } \
476 operator bool() const noexcept { return !!pImpl; } \
478 handle_type getHandle() const noexcept { return pImpl; }
480 enum class PlaybackName {
481 Basic = ALC_DEVICE_SPECIFIER,
482 Full = ALC_ALL_DEVICES_SPECIFIER
485 class ALURE_API Device {
486 MAKE_PIMPL(Device, DeviceImpl)
488 public:
489 /** Retrieves the device name as given by type. */
490 String getName(PlaybackName type=PlaybackName::Full) const;
491 /** Queries the existence of an ALC extension on this device. */
492 bool queryExtension(const String &name) const;
493 bool queryExtension(const char *name) const;
495 /** Retrieves the ALC version supported by this device. */
496 Version getALCVersion() const;
499 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
500 * extension is unsupported, this will be 0.0.
502 Version getEFXVersion() const;
504 /** Retrieves the device's playback frequency, in hz. */
505 ALCuint getFrequency() const;
508 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
509 * is unsupported, this will be 0.
511 ALCuint getMaxAuxiliarySends() const;
514 * Enumerates available HRTF names. The names are sorted as OpenAL gives
515 * them, such that the index of a given name is the ID to use with
516 * ALC_HRTF_ID_SOFT.
518 * If the ALC_SOFT_HRTF extension is unavailable, this will return an empty
519 * vector.
521 Vector<String> enumerateHRTFNames() const;
524 * Retrieves whether HRTF is enabled on the device or not.
526 * If the ALC_SOFT_HRTF extension is unavailable, this will return false
527 * although there could still be HRTF applied at a lower hardware level.
529 bool isHRTFEnabled() const;
532 * Retrieves the name of the HRTF currently being used by this device.
534 * If HRTF is not currently enabled, this will be empty.
536 String getCurrentHRTF() const;
539 * Resets the device, using the specified attributes.
541 * If the ALC_SOFT_HRTF extension is unavailable, this will be a no-op.
543 void reset(ArrayView<AttributePair> attributes);
546 * Creates a new Context on this device, using the specified attributes.
547 * Throws an exception if context creation fails.
549 Context createContext(ArrayView<AttributePair> attributes={});
551 * Creates a new Context on this device, using the specified attributes.
552 * Returns an empty Context if context creation fails.
554 Context createContext(ArrayView<AttributePair> attributes, const std::nothrow_t&) noexcept;
555 Context createContext(const std::nothrow_t&) noexcept;
558 * Pauses device processing, stopping updates for its contexts. Multiple
559 * calls are allowed but it is not reference counted, so the device will
560 * resume after one resumeDSP call.
562 * Requires the ALC_SOFT_pause_device extension.
564 void pauseDSP();
567 * Resumes device processing, restarting updates for its contexts. Multiple
568 * calls are allowed and will no-op.
570 void resumeDSP();
573 * Retrieves the current clock time for the device. This starts relative to
574 * the device being opened, and does not increment while there are no
575 * contexts nor while processing is paused. This is currently based on
576 * std::chrono::steady_clock, and so may not exactly match the rate that
577 * sources play at. In the future it may utilize an OpenAL extension to
578 * retrieve the audio device's real clock which may tic at a subtly
579 * different rate than the main clock(s).
581 std::chrono::nanoseconds getClockTime();
584 * Closes and frees the device. All previously-created contexts must first
585 * be destroyed.
587 void close();
591 enum class DistanceModel {
592 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
593 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
594 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
595 Inverse = AL_INVERSE_DISTANCE,
596 Linear = AL_LINEAR_DISTANCE,
597 Exponent = AL_EXPONENT_DISTANCE,
598 None = AL_NONE,
601 class ALURE_API Context {
602 MAKE_PIMPL(Context, ContextImpl)
604 public:
605 /** Makes the specified context current for OpenAL operations. */
606 static void MakeCurrent(Context context);
607 /** Retrieves the current context used for OpenAL operations. */
608 static Context GetCurrent();
611 * Makes the specified context current for OpenAL operations on the calling
612 * thread only. Requires the ALC_EXT_thread_local_context extension on both
613 * the context's device and the DeviceManager.
615 static void MakeThreadCurrent(Context context);
616 /** Retrieves the thread-specific context used for OpenAL operations. */
617 static Context GetThreadCurrent();
620 * Destroys the context. The context must not be current when this is
621 * called.
623 void destroy();
625 /** Retrieves the Device this context was created from. */
626 Device getDevice();
628 void startBatch();
629 void endBatch();
632 * Retrieves a Listener instance for this context. Each context will only
633 * have one listener, which is automatically destroyed with the context.
635 Listener getListener();
638 * Sets a MessageHandler instance which will be used to provide certain
639 * messages back to the application. Only one handler may be set for a
640 * context at a time. The previously set handler will be returned.
642 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
644 /** Gets the currently-set message handler. */
645 SharedPtr<MessageHandler> getMessageHandler() const;
648 * Specifies the desired interval that the background thread will be woken
649 * up to process tasks, e.g. keeping streaming sources filled. An interval
650 * of 0 means the background thread will only be woken up manually with
651 * calls to update. The default is 0.
653 void setAsyncWakeInterval(std::chrono::milliseconds interval);
656 * Retrieves the current interval used for waking up the background thread.
658 std::chrono::milliseconds getAsyncWakeInterval() const;
660 // Functions below require the context to be current
663 * Creates a Decoder instance for the given audio file or resource name.
665 SharedPtr<Decoder> createDecoder(StringView name);
668 * Queries if the channel configuration and sample type are supported by
669 * the context.
671 bool isSupported(ChannelConfig channels, SampleType type) const;
674 * Queries the list of resamplers supported by the context. If the
675 * AL_SOFT_source_resampler extension is unsupported this will be an empty
676 * array, otherwise there will be at least one entry.
678 ArrayView<String> getAvailableResamplers();
680 * Queries the context's default resampler index. Be aware, if the
681 * AL_SOFT_source_resampler extension is unsupported the resampler list
682 * will be empty and this will resturn 0. If you try to access the
683 * resampler list with this index without the extension, undefined behavior
684 * will occur (accessing an out of bounds array index).
686 ALsizei getDefaultResamplerIndex() const;
689 * Creates and caches a Buffer for the given audio file or resource name.
690 * Multiple calls with the same name will return the same Buffer object.
691 * Cached buffers must be freed using removeBuffer before destroying the
692 * context. If the buffer can't be loaded it will throw an exception.
694 Buffer getBuffer(StringView name);
697 * Asynchronously prepares a cached Buffer for the given audio file or
698 * resource name. Multiple calls with the same name will return multiple
699 * SharedFutures for the same Buffer object. Once called, the buffer must
700 * be freed using removeBuffer before destroying the context, even if you
701 * never get the Buffer from the SharedFuture.
703 * The Buffer will be scheduled to load asynchronously, and the caller gets
704 * back a SharedFuture that can be checked later (or waited on) to get the
705 * actual Buffer when it's ready. The application must take care to handle
706 * exceptions from the SharedFuture in case an unrecoverable error ocurred
707 * during the load.
709 * If the Buffer is already fully loaded and cached, a SharedFuture is
710 * returned in a ready state containing it.
712 SharedFuture<Buffer> getBufferAsync(StringView name);
715 * Asynchronously prepares cached Buffers for the given audio file or
716 * resource names. Duplicate names and buffers already cached are ignored.
717 * Cached buffers must be freed using removeBuffer before destroying the
718 * context.
720 * The Buffer objects will be scheduled for loading asynchronously, and
721 * should be retrieved later when needed using getBufferAsync or getBuffer.
722 * Buffers that cannot be loaded, for example due to an unsupported format,
723 * will be ignored and a later call to getBuffer or getBufferAsync will
724 * throw an exception.
726 void precacheBuffersAsync(ArrayView<StringView> names);
729 * Creates and caches a Buffer using the given name by reading the given
730 * decoder. The name may alias an audio file, but it must not currently
731 * exist in the buffer cache.
733 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
736 * Asynchronously prepares a cached Buffer using the given name by reading
737 * the given decoder. The name may alias an audio file, but it must not
738 * currently exist in the buffer cache. Once called, the buffer must be
739 * freed using removeBuffer before destroying the context, even if you
740 * never get the Buffer from the SharedFuture.
742 * The Buffer will be scheduled to load asynchronously, and the caller gets
743 * back a SharedFuture that can be checked later (or waited on) to get the
744 * actual Buffer when it's ready. The application must take care to handle
745 * exceptions from the SharedFuture in case an unrecoverable error ocurred
746 * during the load. The decoder must not have its read or seek methods
747 * called while the buffer is not ready.
749 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
752 * Looks for a cached buffer using the given name and returns it. If the
753 * given name does not exist in the cache, a null buffer is returned.
755 Buffer findBuffer(StringView name);
758 * Looks for an asynchronously-loading buffer using the given name and
759 * returns a SharedFuture for it. If the given name does not exist in the
760 * cache, an invalid SharedFuture is returned (check with a call to
761 * \c SharedFuture::valid).
763 * If the Buffer is already fully loaded and cached, a SharedFuture is
764 * returned in a ready state containing it.
766 SharedFuture<Buffer> findBufferAsync(StringView name);
769 * Deletes the cached Buffer object for the given audio file or resource
770 * name, invalidating all Buffer objects with this name. If a source is
771 * currently playing the buffer, it will be stopped first.
773 void removeBuffer(StringView name);
775 * Deletes the given cached buffer, invalidating all other Buffer objects
776 * with the same name. Equivalent to calling
777 * removeBuffer(buffer.getName()).
779 void removeBuffer(Buffer buffer);
782 * Creates a new Source for playing audio. There is no practical limit to
783 * the number of sources you may create. You must call Source::destroy when
784 * the source is no longer needed.
786 Source createSource();
788 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
790 Effect createEffect();
792 SourceGroup createSourceGroup();
794 /** Sets the doppler factor to apply to all source doppler calculations. */
795 void setDopplerFactor(ALfloat factor);
798 * Sets the speed of sound propagation, in units per second, to calculate
799 * the doppler effect along with other distance-related time effects. The
800 * default is 343.3 units per second (a realistic speed assuming 1 meter
801 * per unit). If this is adjusted for a different unit scale,
802 * Listener::setMetersPerUnit should also be adjusted.
804 void setSpeedOfSound(ALfloat speed);
807 * Sets the distance model used to attenuate sources given their distance
808 * from the listener. The default, InverseClamped, provides a realistic 1/r
809 * reduction in volume (that is, every doubling of distance causes the gain
810 * to reduce by half).
812 * The Clamped distance models restrict the source distance for the purpose
813 * of distance attenuation, so a source won't sound closer than its
814 * reference distance or farther than its max distance.
816 void setDistanceModel(DistanceModel model);
818 /** Updates the context and all sources belonging to this context. */
819 void update();
822 class ALURE_API Listener {
823 MAKE_PIMPL(Listener, ListenerImpl)
825 public:
826 /** Sets the "master" gain for all context output. */
827 void setGain(ALfloat gain);
830 * Specifies the listener's 3D position, velocity, and orientation
831 * together (see: setPosition, setVelocity, and setOrientation).
833 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const std::pair<Vector3,Vector3> &orientation);
835 /** Specifies the listener's 3D position. */
836 void setPosition(const Vector3 &position);
837 void setPosition(const ALfloat *pos);
840 * Specifies the listener's 3D velocity, in units per second. As with
841 * OpenAL, this does not actually alter the listener's position, and
842 * instead just alters the pitch as determined by the doppler effect.
844 void setVelocity(const Vector3 &velocity);
845 void setVelocity(const ALfloat *vel);
848 * Specifies the listener's 3D orientation, using position-relative 'at'
849 * and 'up' direction vectors.
851 void setOrientation(const std::pair<Vector3,Vector3> &orientation);
852 void setOrientation(const ALfloat *at, const ALfloat *up);
853 void setOrientation(const ALfloat *ori);
856 * Sets the number of meters per unit, used for various effects that rely
857 * on the distance in meters including air absorption and initial reverb
858 * decay. If this is changed, it's strongly recommended to also set the
859 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
860 * realistic 343.3m/s for sound propagation).
862 void setMetersPerUnit(ALfloat m_u);
866 class ALURE_API Buffer {
867 MAKE_PIMPL(Buffer, BufferImpl)
869 public:
870 /** Retrieves the length of the buffer in sample frames. */
871 ALuint getLength() const;
873 /** Retrieves the buffer's frequency in hz. */
874 ALuint getFrequency() const;
876 /** Retrieves the buffer's sample configuration. */
877 ChannelConfig getChannelConfig() const;
879 /** Retrieves the buffer's sample type. */
880 SampleType getSampleType() const;
883 * Retrieves the storage size used by the buffer, in bytes. Note that the
884 * size in bytes may not be what you expect from the length, as it may take
885 * more space internally than the ChannelConfig and SampleType suggest to
886 * be more efficient.
888 ALuint getSize() const;
891 * Sets the buffer's loop points, used for looping sources. If the current
892 * context does not support the AL_SOFT_loop_points extension, start and
893 * end must be 0 and getLength() respectively. Otherwise, start must be
894 * less than end, and end must be less than or equal to getLength().
896 * The buffer must not be in use when this method is called.
898 * \param start The starting point, in sample frames (inclusive).
899 * \param end The ending point, in sample frames (exclusive).
901 void setLoopPoints(ALuint start, ALuint end);
903 /** Retrieves the current loop points as a [start,end) pair. */
904 std::pair<ALuint,ALuint> getLoopPoints() const;
906 /** Retrieves the Source objects currently playing the buffer. */
907 Vector<Source> getSources() const;
909 /** Retrieves the name the buffer was created with. */
910 StringView getName() const;
913 * Queries the number of sources currently using the buffer. Be aware that
914 * you need to call \c Context::update to reliably ensure the count is kept
915 * updated for when sources reach their end. This is equivalent to calling
916 * getSources().size().
918 size_t getSourceCount() const;
922 enum class Spatialize {
923 Off = AL_FALSE,
924 On = AL_TRUE,
925 Auto = 0x0002 /* AL_AUTO_SOFT */
928 class ALURE_API Source {
929 MAKE_PIMPL(Source, SourceImpl)
931 public:
933 * Plays the source using a buffer. The same buffer may be played from
934 * multiple sources simultaneously.
936 void play(Buffer buffer);
938 * Plays the source by asynchronously streaming audio from a decoder. The
939 * given decoder must *NOT* have its read or seek methods called from
940 * elsewhere while in use.
942 * \param decoder The decoder object to play audio from.
943 * \param chunk_len The number of sample frames to read for each chunk
944 * update. Smaller values will require more frequent updates and
945 * larger values will handle more data with each chunk.
946 * \param queue_size The number of chunks to keep queued during playback.
947 * Smaller values use less memory while larger values improve
948 * protection against underruns.
950 void play(SharedPtr<Decoder> decoder, ALsizei chunk_len, ALsizei queue_size);
953 * Prepares to play a source using a future buffer. The method will return
954 * right away and the source will begin playing once the future buffer
955 * becomes ready. If the future buffer is already ready, it begins playing
956 * immediately as if you called play(future_buffer.get()).
958 * The future buffer is checked during calls to \c Context::update and the
959 * source will start playback once the future buffer reports it's ready.
960 * Use the isPending method to check if the source is still waiting for the
961 * future buffer.
963 void play(SharedFuture<Buffer> future_buffer);
966 * Stops playback, releasing the buffer or decoder reference. Any pending
967 * playback from a future buffer is canceled.
969 void stop();
972 * Fades the source to the specified gain over the given duration, at which
973 * point playback will stop. This gain is in addition to the base gain, and
974 * must be greater than 0 and less than 1. The duration must also be
975 * greater than 0.
977 * The fading is logarithmic. As a result, the initial drop-off may happen
978 * faster than expected but the fading is more perceptually consistant over
979 * the given duration. It will take just as much time to go from -6dB to
980 * -12dB as it will to go from -40dB to -46dB, for example.
982 * Pending playback from a future buffer is not immediately canceled, but
983 * the fade timer starts with this call. If the future buffer then becomes
984 * ready, it will start mid-fade. Pending playback will be canceled if the
985 * fade out completes before the future buffer becomes ready.
987 * Fading is updated during calls to \c Context::update, which should be
988 * called regularly (30 to 50 times per second) for the fading to be
989 * smooth.
991 void fadeOutToStop(ALfloat gain, std::chrono::milliseconds duration);
993 /** Pauses the source if it is playing. */
994 void pause();
996 /** Resumes the source if it is paused. */
997 void resume();
999 /** Specifies if the source is waiting to play a future buffer. */
1000 bool isPending() const;
1002 /** Specifies if the source is currently playing. */
1003 bool isPlaying() const;
1005 /** Specifies if the source is currently paused. */
1006 bool isPaused() const;
1009 * Specifies if the source is currently playing or waiting to play a future
1010 * buffer.
1012 bool isPlayingOrPending() const;
1015 * Sets this source as a child of the given source group. The given source
1016 * group's parameters will influence this and all other sources that belong
1017 * to it. A source can only be the child of one source group at a time,
1018 * although that source group may belong to another source group.
1020 * Passing in a null group removes it from its current source group.
1022 void setGroup(SourceGroup group);
1024 /** Retrieves the source group this source belongs to. */
1025 SourceGroup getGroup() const;
1028 * Specifies the source's playback priority. The lowest priority sources
1029 * will be forcefully stopped when no more mixing sources are available and
1030 * higher priority sources are played.
1032 void setPriority(ALuint priority);
1033 /** Retrieves the source's priority. */
1034 ALuint getPriority() const;
1037 * Sets the source's offset, in sample frames. If the source is playing or
1038 * paused, it will go to that offset immediately, otherwise the source will
1039 * start at the specified offset the next time it's played.
1041 void setOffset(uint64_t offset);
1043 * Retrieves the source offset in sample frames and its latency in nano-
1044 * seconds. For streaming sources this will be the offset based on the
1045 * decoder's read position.
1047 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1048 * be 0.
1050 std::pair<uint64_t,std::chrono::nanoseconds> getSampleOffsetLatency() const;
1051 uint64_t getSampleOffset() const { return std::get<0>(getSampleOffsetLatency()); }
1053 * Retrieves the source offset and latency in seconds. For streaming
1054 * sources this will be the offset based on the decoder's read position.
1056 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1057 * be 0.
1059 std::pair<Seconds,Seconds> getSecOffsetLatency() const;
1060 Seconds getSecOffset() const { return std::get<0>(getSecOffsetLatency()); }
1063 * Specifies if the source should loop on the Buffer or Decoder object's
1064 * loop points.
1066 void setLooping(bool looping);
1067 bool getLooping() const;
1070 * Specifies a linear pitch shift base. A value of 1.0 is the default
1071 * normal speed.
1073 void setPitch(ALfloat pitch);
1074 ALfloat getPitch() const;
1077 * Specifies the base linear gain. A value of 1.0 is the default normal
1078 * volume.
1080 void setGain(ALfloat gain);
1081 ALfloat getGain() const;
1084 * Specifies the minimum and maximum gain. The source's gain is clamped to
1085 * this range after distance attenuation and cone attenuation are applied
1086 * to the gain base, although before the filter gain adjustements.
1088 void setGainRange(ALfloat mingain, ALfloat maxgain);
1089 std::pair<ALfloat,ALfloat> getGainRange() const;
1090 ALfloat getMinGain() const { return std::get<0>(getGainRange()); }
1091 ALfloat getMaxGain() const { return std::get<1>(getGainRange()); }
1094 * Specifies the reference distance and maximum distance the source will
1095 * use for the current distance model. For Clamped distance models, the
1096 * source's calculated distance is clamped to the specified range before
1097 * applying distance-related attenuation.
1099 * For all distance models, the reference distance is the distance at which
1100 * the source's volume will not have any extra attenuation (an effective
1101 * gain multiplier of 1).
1103 void setDistanceRange(ALfloat refdist, ALfloat maxdist);
1104 std::pair<ALfloat,ALfloat> getDistanceRange() const;
1105 ALfloat getReferenceDistance() const { return std::get<0>(getDistanceRange()); }
1106 ALfloat getMaxDistance() const { return std::get<1>(getDistanceRange()); }
1109 * Specifies the source's 3D position, velocity, and direction together
1110 * (see: setPosition, setVelocity, and setDirection).
1112 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const Vector3 &direction);
1115 * Specifies the source's 3D position, velocity, and orientation together
1116 * (see: setPosition, setVelocity, and setOrientation).
1118 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const std::pair<Vector3,Vector3> &orientation);
1120 /** Specifies the source's 3D position. */
1121 void setPosition(const Vector3 &position);
1122 void setPosition(const ALfloat *pos);
1123 Vector3 getPosition() const;
1126 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
1127 * this does not actually alter the source's position, and instead just
1128 * alters the pitch as determined by the doppler effect.
1130 void setVelocity(const Vector3 &velocity);
1131 void setVelocity(const ALfloat *vel);
1132 Vector3 getVelocity() const;
1135 * Specifies the source's 3D facing direction. Deprecated in favor of
1136 * setOrientation.
1138 void setDirection(const Vector3 &direction);
1139 void setDirection(const ALfloat *dir);
1140 Vector3 getDirection() const;
1143 * Specifies the source's 3D orientation, using position-relative 'at' and
1144 * 'up' direction vectors. Note: unlike the AL_EXT_BFORMAT extension this
1145 * property comes from, this also affects the facing direction, superceding
1146 * setDirection.
1148 void setOrientation(const std::pair<Vector3,Vector3> &orientation);
1149 void setOrientation(const ALfloat *at, const ALfloat *up);
1150 void setOrientation(const ALfloat *ori);
1151 std::pair<Vector3,Vector3> getOrientation() const;
1154 * Specifies the source's cone angles, in degrees. The inner angle is the
1155 * area within which the listener will hear the source with no extra
1156 * attenuation, while the listener being outside of the outer angle will
1157 * hear the source attenuated according to the outer cone gains. The area
1158 * follows the facing direction, so for example an inner angle of 180 means
1159 * the entire front face of the source is in the inner cone.
1161 void setConeAngles(ALfloat inner, ALfloat outer);
1162 std::pair<ALfloat,ALfloat> getConeAngles() const;
1163 ALfloat getInnerConeAngle() const { return std::get<0>(getConeAngles()); }
1164 ALfloat getOuterConeAngle() const { return std::get<1>(getConeAngles()); }
1167 * Specifies the linear gain multiplier when the listener is outside of the
1168 * source's outer cone area. The specified gain applies to all frequencies,
1169 * while gainhf applies extra attenuation to high frequencies creating a
1170 * low-pass effect.
1172 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1174 void setOuterConeGains(ALfloat gain, ALfloat gainhf=1.0f);
1175 std::pair<ALfloat,ALfloat> getOuterConeGains() const;
1176 ALfloat getOuterConeGain() const { return std::get<0>(getOuterConeGains()); }
1177 ALfloat getOuterConeGainHF() const { return std::get<1>(getOuterConeGains()); }
1180 * Specifies the rolloff factors for the direct and send paths. This is
1181 * effectively a distance scaling relative to the reference distance. Note:
1182 * the room rolloff factor is 0 by default, disabling distance attenuation
1183 * for send paths. This is because the reverb engine will, by default,
1184 * apply a more realistic room decay based on the reverb decay time and
1185 * distance.
1187 void setRolloffFactors(ALfloat factor, ALfloat roomfactor=0.0f);
1188 std::pair<ALfloat,ALfloat> getRolloffFactors() const;
1189 ALfloat getRolloffFactor() const { return std::get<0>(getRolloffFactors()); }
1190 ALfloat getRoomRolloffFactor() const { return std::get<1>(getRolloffFactors()); }
1193 * Specifies the doppler factor for the doppler effect's pitch shift. This
1194 * effectively scales the source and listener velocities for the doppler
1195 * calculation.
1197 void setDopplerFactor(ALfloat factor);
1198 ALfloat getDopplerFactor() const;
1201 * Specifies if the source's position, velocity, and direction/orientation
1202 * are relative to the listener.
1204 void setRelative(bool relative);
1205 bool getRelative() const;
1208 * Specifies the source's radius. This causes the source to behave as if
1209 * every point within the spherical area emits sound.
1211 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1213 void setRadius(ALfloat radius);
1214 ALfloat getRadius() const;
1217 * Specifies the left and right channel angles, in radians, when playing a
1218 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1219 * in front and positive values going left.
1221 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1223 void setStereoAngles(ALfloat leftAngle, ALfloat rightAngle);
1224 std::pair<ALfloat,ALfloat> getStereoAngles() const;
1227 * Specifies if the source always has 3D spatialization features (On),
1228 * never has 3D spatialization features (Off), or if spatialization is
1229 * enabled based on playing a mono sound or not (Auto, default).
1231 * Has no effect without the AL_SOFT_source_spatialize extension.
1233 void set3DSpatialize(Spatialize spatialize);
1234 Spatialize get3DSpatialize() const;
1237 * Specifies the index of the resampler to use for this source. The index
1238 * is from the resamplers returned by \c Context::getAvailableResamplers,
1239 * and must be 0 or greater.
1241 * Has no effect without the AL_SOFT_source_resampler extension.
1243 void setResamplerIndex(ALsizei index);
1244 ALsizei getResamplerIndex() const;
1247 * Specifies a multiplier for the amount of atmospheric high-frequency
1248 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1249 * -0.05dB per meter, with higher values simulating foggy air and lower
1250 * values simulating dryer air. The default is 0.
1252 void setAirAbsorptionFactor(ALfloat factor);
1253 ALfloat getAirAbsorptionFactor() const;
1256 * Specifies to automatically apply adjustments to the direct path's high-
1257 * frequency gain, and the send paths' gain and high-frequency gain. The
1258 * default is true for all.
1260 void setGainAuto(bool directhf, bool send, bool sendhf);
1261 std::tuple<bool,bool,bool> getGainAuto() const;
1262 bool getDirectGainHFAuto() const { return std::get<0>(getGainAuto()); }
1263 bool getSendGainAuto() const { return std::get<1>(getGainAuto()); }
1264 bool getSendGainHFAuto() const { return std::get<2>(getGainAuto()); }
1266 /** Sets the filter properties on the direct path signal. */
1267 void setDirectFilter(const FilterParams &filter);
1269 * Sets the filter properties on the given send path signal. Any auxiliary
1270 * effect slot on the send path remains in place.
1272 void setSendFilter(ALuint send, const FilterParams &filter);
1274 * Connects the effect slot to the given send path. Any filter properties
1275 * on the send path remain as they were.
1277 void setAuxiliarySend(AuxiliaryEffectSlot slot, ALuint send);
1279 * Connects the effect slot to the given send path, using the filter
1280 * properties.
1282 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot, ALuint send, const FilterParams &filter);
1284 /** Destroys the source, stopping playback and releasing resources. */
1285 void destroy();
1289 class ALURE_API SourceGroup {
1290 MAKE_PIMPL(SourceGroup, SourceGroupImpl)
1292 public:
1294 * Adds this source group as a subgroup of the specified source group. This
1295 * method will throw an exception if this group is being added to a group
1296 * it has as a sub-group (i.e. it would create a circular sub-group chain).
1298 void setParentGroup(SourceGroup group);
1300 /** Retrieves the source group this source group is a child of. */
1301 SourceGroup getParentGroup() const;
1303 /** Returns the list of sources currently in the group. */
1304 Vector<Source> getSources() const;
1306 /** Returns the list of subgroups currently in the group. */
1307 Vector<SourceGroup> getSubGroups() const;
1310 * Sets the source group gain, which accumulates with its sources' and
1311 * sub-groups' gain.
1313 void setGain(ALfloat gain);
1314 /** Gets the source group gain. */
1315 ALfloat getGain() const;
1318 * Sets the source group pitch, which accumulates with its sources' and
1319 * sub-groups' pitch.
1321 void setPitch(ALfloat pitch);
1322 /** Gets the source group pitch. */
1323 ALfloat getPitch() const;
1326 * Pauses all currently-playing sources that are under this group,
1327 * including sub-groups.
1329 void pauseAll() const;
1331 * Resumes all paused sources that are under this group, including
1332 * sub-groups.
1334 void resumeAll() const;
1336 /** Stops all sources that are under this group, including sub-groups. */
1337 void stopAll() const;
1340 * Destroys the source group, removing all sources from it before being
1341 * freed.
1343 void destroy();
1347 struct SourceSend {
1348 Source mSource;
1349 ALuint mSend;
1352 class ALURE_API AuxiliaryEffectSlot {
1353 MAKE_PIMPL(AuxiliaryEffectSlot, AuxiliaryEffectSlotImpl)
1355 public:
1356 void setGain(ALfloat gain);
1358 * If set to true, the reverb effect will automatically apply adjustments
1359 * to the source's send slot gains based on the effect properties.
1361 * Has no effect when using non-reverb effects. Default is true.
1363 void setSendAuto(bool sendauto);
1366 * Updates the effect slot with a new effect. The given effect object may
1367 * be altered or destroyed without affecting the effect slot.
1369 void applyEffect(Effect effect);
1372 * Destroys the effect slot, returning it to the system. If the effect slot
1373 * is currently set on a source send, it will be removed first.
1375 void destroy();
1378 * Retrieves each Source object and its pairing send this effect slot is
1379 * set on.
1381 Vector<SourceSend> getSourceSends() const;
1384 * Queries the number of source sends the effect slot is used by. This is
1385 * equivalent to calling getSourceSends().size().
1387 size_t getUseCount() const;
1391 class ALURE_API Effect {
1392 MAKE_PIMPL(Effect, EffectImpl)
1394 public:
1396 * Updates the effect with the specified reverb properties. If the
1397 * EAXReverb effect is not supported, it will automatically attempt to
1398 * downgrade to the Standard Reverb effect.
1400 void setReverbProperties(const EFXEAXREVERBPROPERTIES &props);
1403 * Updates the effect with the specified chorus properties. If the chorus
1404 * effect is not supported, an exception will be thrown.
1406 void setChorusProperties(const EFXCHORUSPROPERTIES &props);
1408 void destroy();
1413 * Audio decoder interface. Applications may derive from this, implementing the
1414 * necessary methods, and use it in places the API wants a Decoder object.
1416 class ALURE_API Decoder {
1417 public:
1418 virtual ~Decoder();
1420 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1421 virtual ALuint getFrequency() const noexcept = 0;
1422 /** Retrieves the channel configuration of the audio being decoded. */
1423 virtual ChannelConfig getChannelConfig() const noexcept = 0;
1424 /** Retrieves the sample type of the audio being decoded. */
1425 virtual SampleType getSampleType() const noexcept = 0;
1428 * Retrieves the total length of the audio, in sample frames. If unknown,
1429 * returns 0. Note that if the returned length is 0, the decoder may not be
1430 * used to load a Buffer.
1432 virtual uint64_t getLength() const noexcept = 0;
1434 * Seek to pos, specified in sample frames. Returns true if the seek was
1435 * successful.
1437 virtual bool seek(uint64_t pos) noexcept = 0;
1440 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1441 * start >= end, all available samples are included in the loop.
1443 virtual std::pair<uint64_t,uint64_t> getLoopPoints() const noexcept = 0;
1446 * Decodes count sample frames, writing them to ptr, and returns the number
1447 * of sample frames written. Returning less than the requested count
1448 * indicates the end of the audio.
1450 virtual ALuint read(ALvoid *ptr, ALuint count) noexcept = 0;
1454 * Audio decoder factory interface. Applications may derive from this,
1455 * implementing the necessary methods, and use it in places the API wants a
1456 * DecoderFactory object.
1458 class ALURE_API DecoderFactory {
1459 public:
1460 virtual ~DecoderFactory();
1463 * Creates and returns a Decoder instance for the given resource file. If
1464 * the decoder needs to retain the file handle for reading as-needed, it
1465 * should move the UniquePtr to internal storage.
1467 * \return nullptr if a decoder can't be created from the file.
1469 virtual SharedPtr<Decoder> createDecoder(UniquePtr<std::istream> &file) noexcept = 0;
1473 * Registers a decoder factory for decoding audio. Registered factories are
1474 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1475 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1476 * name1 < name2. Internal decoder factories are always used after registered
1477 * ones.
1479 * Alure retains a reference to the DecoderFactory instance and will release it
1480 * (destructing the object) when the library unloads.
1482 * \param name A unique name identifying this decoder factory.
1483 * \param factory A DecoderFactory instance used to create Decoder instances.
1485 ALURE_API void RegisterDecoder(StringView name, UniquePtr<DecoderFactory> factory);
1488 * Unregisters a decoder factory by name. Alure returns the instance back to
1489 * the application.
1491 * \param name The unique name identifying a previously-registered decoder
1492 * factory.
1494 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1495 * decoder factory with the given name doesn't exist.
1497 ALURE_API UniquePtr<DecoderFactory> UnregisterDecoder(StringView name) noexcept;
1501 * A file I/O factory interface. Applications may derive from this and set an
1502 * instance to be used by the audio decoders. By default, the library uses
1503 * standard I/O.
1505 class ALURE_API FileIOFactory {
1506 public:
1508 * Sets the factory instance to be used by the audio decoders. If a
1509 * previous factory was set, it's returned to the application. Passing in a
1510 * nullptr reverts to the default.
1512 static UniquePtr<FileIOFactory> set(UniquePtr<FileIOFactory> factory) noexcept;
1515 * Gets the current FileIOFactory instance being used by the audio
1516 * decoders.
1518 static FileIOFactory &get() noexcept;
1520 virtual ~FileIOFactory();
1522 /** Opens a read-only binary file for the given name. */
1523 virtual UniquePtr<std::istream> openFile(const String &name) noexcept = 0;
1528 * A message handler interface. Applications may derive from this and set an
1529 * instance on a context to receive messages. The base methods are no-ops, so
1530 * derived classes only need to implement methods for relevant messages.
1532 * It's recommended that applications mark their handler methods using the
1533 * override keyword, to ensure they're properly overriding the base methods in
1534 * case they change.
1536 class ALURE_API MessageHandler {
1537 public:
1538 virtual ~MessageHandler();
1541 * Called when the given device has been disconnected and is no longer
1542 * usable for output. As per the ALC_EXT_disconnect specification,
1543 * disconnected devices remain valid, however all playing sources are
1544 * automatically stopped, any sources that are attempted to play will
1545 * immediately stop, and new contexts may not be created on the device.
1547 * Note that connection status is checked during Context::update calls, so
1548 * that method must be called regularly to be notified when a device is
1549 * disconnected. This method may not be called if the device lacks support
1550 * for the ALC_EXT_disconnect extension.
1552 virtual void deviceDisconnected(Device device) noexcept;
1555 * Called when the given source reaches the end of the buffer or stream.
1557 * Sources that stopped automatically will be detected upon a call to
1558 * Context::update.
1560 virtual void sourceStopped(Source source) noexcept;
1563 * Called when the given source was forced to stop. This can be because
1564 * either there were no more mixing sources and a higher-priority source
1565 * preempted it, it's part of a SourceGroup (or sub-group thereof) that had
1566 * its SourceGroup::stopAll method called, or it was playing a buffer
1567 * that's getting removed.
1569 virtual void sourceForceStopped(Source source) noexcept;
1572 * Called when a new buffer is about to be created and loaded. May be
1573 * called asynchronously for buffers being loaded asynchronously.
1575 * \param name The resource name, as passed to Context::getBuffer.
1576 * \param channels Channel configuration of the given audio data.
1577 * \param type Sample type of the given audio data.
1578 * \param samplerate Sample rate of the given audio data.
1579 * \param data The audio data that is about to be fed to the OpenAL buffer.
1581 virtual void bufferLoading(StringView name, ChannelConfig channels, SampleType type, ALuint samplerate, ArrayView<ALbyte> data) noexcept;
1584 * Called when a resource isn't found, allowing the app to substitute in a
1585 * different resource. For buffers being cached, the original name will
1586 * still be used for the cache entry so the app doesn't have to keep track
1587 * of substituted resource names.
1589 * This will be called again if the new name also isn't found.
1591 * \param name The resource name that was not found.
1592 * \return The replacement resource name to use instead. Returning an empty
1593 * string means to stop trying.
1595 virtual String resourceNotFound(StringView name) noexcept;
1598 #undef MAKE_PIMPL
1600 } // namespace alure
1602 #endif /* AL_ALURE2_H */