Use pImpl for the DeviceManager
[alure.git] / include / AL / alure2.h
blob682596a720cdf19e6c35b3d056c5c79fbadb53b8
1 #ifndef AL_ALURE2_H
2 #define AL_ALURE2_H
4 #include <vector>
5 #include <string>
6 #include <memory>
7 #include <utility>
8 #include <chrono>
9 #include <array>
10 #include <cmath>
12 #include "alc.h"
13 #include "al.h"
15 #ifdef _WIN32
16 #if defined(ALURE_BUILD_STATIC) || defined(ALURE_STATIC_LIB)
17 #define ALURE_API
18 #elif defined(ALURE_BUILD_DLL)
19 #define ALURE_API __declspec(dllexport)
20 #else
21 #define ALURE_API __declspec(dllimport)
22 #endif
24 #else
26 #define ALURE_API
27 #endif
29 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
30 #define EFXEAXREVERBPROPERTIES_DEFINED
31 typedef struct {
32 float flDensity;
33 float flDiffusion;
34 float flGain;
35 float flGainHF;
36 float flGainLF;
37 float flDecayTime;
38 float flDecayHFRatio;
39 float flDecayLFRatio;
40 float flReflectionsGain;
41 float flReflectionsDelay;
42 float flReflectionsPan[3];
43 float flLateReverbGain;
44 float flLateReverbDelay;
45 float flLateReverbPan[3];
46 float flEchoTime;
47 float flEchoDepth;
48 float flModulationTime;
49 float flModulationDepth;
50 float flAirAbsorptionGainHF;
51 float flHFReference;
52 float flLFReference;
53 float flRoomRolloffFactor;
54 int iDecayHFLimit;
55 } EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
56 #endif
58 namespace alure {
60 class DeviceManager;
61 class ALDeviceManager;
62 class Device;
63 class ALDevice;
64 class Context;
65 class ALContext;
66 class Listener;
67 class ALListener;
68 class Buffer;
69 class ALBuffer;
70 class Source;
71 class ALSource;
72 class SourceGroup;
73 class ALSourceGroup;
74 class AuxiliaryEffectSlot;
75 class ALAuxiliaryEffectSlot;
76 class Effect;
77 class ALEffect;
78 class Decoder;
79 class DecoderFactory;
80 class MessageHandler;
83 // Duration in seconds, using double precision
84 using Seconds = std::chrono::duration<double>;
86 // A SharedPtr implementation, defaults to C++11's std::shared_ptr. If this is
87 // changed, you must recompile the library.
88 template<typename T>
89 using SharedPtr = std::shared_ptr<T>;
90 template<typename T, typename... Args>
91 constexpr inline SharedPtr<T> MakeShared(Args&&... args)
93 return std::make_shared<T>(std::forward<Args>(args)...);
96 // A UniquePtr implementation, defaults to C++11's std::unique_ptr. If this is
97 // changed, you must recompile the library.
98 template<typename T, typename D = std::default_delete<T>>
99 using UniquePtr = std::unique_ptr<T, D>;
100 template<typename T, typename... Args>
101 constexpr inline UniquePtr<T> MakeUnique(Args&&... args)
103 #if __cplusplus >= 201402L
104 return std::make_unique<T>(std::forward<Args>(args)...);
105 #else
106 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
107 #endif
110 // A Vector implementation, defaults to C++'s std::vector. If this is changed,
111 // you must recompile the library.
112 template<typename T>
113 using Vector = std::vector<T>;
115 // A String implementation, default's to C++'s std::string. If this is changed,
116 // you must recompile the library.
117 using String = std::string;
119 // A rather simple ArrayView container. This allows accepting various array
120 // types (std::array, Vector, a static-sized array, a dynamic array + size)
121 // without copying its elements.
122 template<typename T>
123 class ArrayView {
124 T *mElems;
125 size_t mNumElems;
127 public:
128 typedef T *iterator;
129 typedef const T *const_iterator;
131 ArrayView() : mElems(nullptr), mNumElems(0) { }
132 ArrayView(const ArrayView &rhs) : mElems(rhs.data()), mNumElems(rhs.size()) { }
133 ArrayView(ArrayView&& rhs) : mElems(rhs.data()), mNumElems(rhs.size()) { }
134 ArrayView(T *elems, size_t num_elems) : mElems(elems), mNumElems(num_elems) { }
135 template<size_t N>
136 ArrayView(T (&elems)[N]) : mElems(elems), mNumElems(N) { }
137 template<typename OtherT>
138 ArrayView(OtherT &arr) : mElems(arr.data()), mNumElems(arr.size()) { }
140 ArrayView& operator=(const ArrayView &rhs)
142 mElems = rhs.data();
143 mNumElems = rhs.size();
145 ArrayView& operator=(ArrayView&& rhs)
147 mElems = rhs.data();
148 mNumElems = rhs.size();
150 template<size_t N>
151 ArrayView& operator=(T (&elems)[N])
153 mElems = elems;
154 mNumElems = N;
156 template<typename OtherT>
157 ArrayView& operator=(OtherT &arr)
159 mElems = arr.data();
160 mNumElems = arr.size();
164 const T *data() const { return mElems; }
165 T *data() { return mElems; }
167 size_t size() const { return mNumElems; }
168 bool empty() const { return mNumElems == 0; }
170 const T& operator[](size_t i) const { return mElems[i]; }
171 T& operator[](size_t i) { return mElems[i]; }
173 const T& front() const { return mElems[0]; }
174 T& front() { return mElems[0]; }
175 const T& back() const { return mElems[mNumElems-1]; }
176 T& back() { return mElems[mNumElems-1]; }
178 const T& at(size_t i) const
180 if(i >= mNumElems)
181 throw std::out_of_range("alure::ArrayView::at: element out of range");
182 return mElems[i];
184 T& at(size_t i)
186 if(i >= mNumElems)
187 throw std::out_of_range("alure::ArrayView::at: element out of range");
188 return mElems[i];
191 iterator begin() { return mElems; }
192 const_iterator begin() const { return mElems; }
193 const_iterator cbegin() const { return mElems; }
195 iterator end() { return mElems + mNumElems; }
196 const_iterator end() const { return mElems + mNumElems; }
197 const_iterator cend() const { return mElems + mNumElems; }
202 * An attribute pair, for passing attributes to Device::createContext and
203 * Device::reset.
205 using AttributePair = std::pair<ALCint,ALCint>;
206 static_assert(sizeof(AttributePair) == sizeof(ALCint[2]), "Bad AttributePair size");
209 struct FilterParams {
210 ALfloat mGain;
211 ALfloat mGainHF; // For low-pass and band-pass filters
212 ALfloat mGainLF; // For high-pass and band-pass filters
216 class ALURE_API Vector3 {
217 std::array<ALfloat,3> mValue;
219 public:
220 constexpr Vector3() noexcept
221 : mValue{{0.0f, 0.0f, 0.0f}}
223 constexpr Vector3(const Vector3 &rhs) noexcept
224 : mValue{{rhs.mValue[0], rhs.mValue[1], rhs.mValue[2]}}
226 constexpr Vector3(ALfloat val) noexcept
227 : mValue{{val, val, val}}
229 constexpr Vector3(ALfloat x, ALfloat y, ALfloat z) noexcept
230 : mValue{{x, y, z}}
232 Vector3(const ALfloat *vec) noexcept
233 : mValue{{vec[0], vec[1], vec[2]}}
236 const ALfloat *getPtr() const noexcept
237 { return mValue.data(); }
239 ALfloat& operator[](size_t i) noexcept
240 { return mValue[i]; }
241 constexpr const ALfloat& operator[](size_t i) const noexcept
242 { return mValue[i]; }
244 #define ALURE_DECL_OP(op) \
245 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
247 return Vector3(mValue[0] op rhs.mValue[0], \
248 mValue[1] op rhs.mValue[1], \
249 mValue[2] op rhs.mValue[2]); \
251 ALURE_DECL_OP(+)
252 ALURE_DECL_OP(-)
253 ALURE_DECL_OP(*)
254 ALURE_DECL_OP(/)
255 #undef ALURE_DECL_OP
256 #define ALURE_DECL_OP(op) \
257 Vector3& operator op(const Vector3 &rhs) noexcept \
259 mValue[0] op rhs.mValue[0]; \
260 mValue[1] op rhs.mValue[1]; \
261 mValue[2] op rhs.mValue[2]; \
262 return *this; \
264 ALURE_DECL_OP(+=)
265 ALURE_DECL_OP(-=)
266 ALURE_DECL_OP(*=)
267 ALURE_DECL_OP(/=)
269 #undef ALURE_DECL_OP
270 #define ALURE_DECL_OP(op) \
271 constexpr Vector3 operator op(ALfloat scale) const noexcept \
273 return Vector3(mValue[0] op scale, \
274 mValue[1] op scale, \
275 mValue[2] op scale); \
277 ALURE_DECL_OP(*)
278 ALURE_DECL_OP(/)
279 #undef ALURE_DECL_OP
280 #define ALURE_DECL_OP(op) \
281 Vector3& operator op(ALfloat scale) noexcept \
283 mValue[0] op scale; \
284 mValue[1] op scale; \
285 mValue[2] op scale; \
286 return *this; \
288 ALURE_DECL_OP(*=)
289 ALURE_DECL_OP(/=)
290 #undef ALURE_DECL_OP
292 constexpr ALfloat getLengthSquared() const noexcept
293 { return mValue[0]*mValue[0] + mValue[1]*mValue[1] + mValue[2]*mValue[2]; }
294 ALfloat getLength() const noexcept
295 { return std::sqrt(getLengthSquared()); }
297 constexpr ALfloat getDistanceSquared(const Vector3 &pos) const noexcept
298 { return (pos - *this).getLengthSquared(); }
299 ALfloat getDistance(const Vector3 &pos) const noexcept
300 { return (pos - *this).getLength(); }
302 static_assert(sizeof(Vector3) == sizeof(ALfloat[3]), "Bad Vector3 size");
305 enum class SampleType {
306 UInt8,
307 Int16,
308 Float32,
309 Mulaw
311 ALURE_API const char *GetSampleTypeName(SampleType type);
313 enum class ChannelConfig {
314 /** 1-channel mono sound. */
315 Mono,
316 /** 2-channel stereo sound. */
317 Stereo,
318 /** 2-channel rear sound (back-left and back-right). */
319 Rear,
320 /** 4-channel surround sound. */
321 Quad,
322 /** 5.1 surround sound. */
323 X51,
324 /** 6.1 surround sound. */
325 X61,
326 /** 7.1 surround sound. */
327 X71,
328 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
329 BFormat2D,
330 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
331 BFormat3D
333 ALURE_API const char *GetChannelConfigName(ChannelConfig cfg);
335 ALURE_API ALuint FramesToBytes(ALuint frames, ChannelConfig chans, SampleType type);
336 ALURE_API ALuint BytesToFrames(ALuint bytes, ChannelConfig chans, SampleType type);
340 * Creates a version number value using the specified major and minor values.
342 constexpr inline ALCuint MakeVersion(ALCushort major, ALCushort minor)
343 { return (major<<16) | minor; }
346 * Retrieves the major version of a version number value created by
347 * MakeVersion.
349 constexpr inline ALCuint MajorVersion(ALCuint version)
350 { return version>>16; }
352 * Retrieves the minor version of a version number value created by
353 * MakeVersion.
355 constexpr inline ALCuint MinorVersion(ALCuint version)
356 { return version&0xffff; }
359 #define MAKE_PIMPL(BaseT, ImplT) \
360 private: \
361 ImplT *pImpl; \
363 public: \
364 using handle_type = ImplT*; \
366 BaseT() : pImpl(nullptr) { } \
367 BaseT(ImplT *impl) : pImpl(impl) { } \
368 BaseT(const BaseT&) = default; \
369 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
371 BaseT& operator=(const BaseT&) = default; \
372 BaseT& operator=(BaseT&& rhs) \
374 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
375 return *this; \
378 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
379 bool operator==(BaseT&& rhs) const { return pImpl == rhs.pImpl; } \
381 operator bool() const { return !!pImpl; } \
383 handle_type getHandle() const { return pImpl; }
385 enum class DeviceEnumeration {
386 Basic = ALC_DEVICE_SPECIFIER,
387 Full = ALC_ALL_DEVICES_SPECIFIER,
388 Capture = ALC_CAPTURE_DEVICE_SPECIFIER
391 enum class DefaultDeviceType {
392 Basic = ALC_DEFAULT_DEVICE_SPECIFIER,
393 Full = ALC_DEFAULT_ALL_DEVICES_SPECIFIER,
394 Capture = ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
398 * A class managing Device objects and other related functionality. This class
399 * is a singleton, only one instance will exist in a process.
401 class ALURE_API DeviceManager {
402 ALDeviceManager *pImpl;
404 DeviceManager(ALDeviceManager *impl) : pImpl(impl) { }
405 friend class ALDeviceManager;
407 public:
408 DeviceManager(const DeviceManager&) = default;
409 DeviceManager(DeviceManager&& rhs) : pImpl(rhs.pImpl) { }
411 /** Retrieves the DeviceManager instance. */
412 static DeviceManager get();
414 /** Queries the existence of a non-device-specific ALC extension. */
415 bool queryExtension(const String &name) const;
417 /** Enumerates available device names of the given type. */
418 Vector<String> enumerate(DeviceEnumeration type) const;
419 /** Retrieves the default device of the given type. */
420 String defaultDeviceName(DefaultDeviceType type) const;
423 * Opens the playback device given by name, or the default if blank. Throws
424 * an exception on error.
426 Device openPlayback(const String &name=String());
429 * Opens the playback device given by name, or the default if blank.
430 * Returns an empty Device on error.
432 Device openPlayback(const String &name, const std::nothrow_t&);
434 /** Opens the default playback device. Returns an empty Device on error. */
435 Device openPlayback(const std::nothrow_t&);
439 enum class PlaybackName {
440 Basic = ALC_DEVICE_SPECIFIER,
441 Full = ALC_ALL_DEVICES_SPECIFIER
444 class ALURE_API Device {
445 MAKE_PIMPL(Device, ALDevice)
447 public:
448 /** Retrieves the device name as given by type. */
449 String getName(PlaybackName type=PlaybackName::Full) const;
450 /** Queries the existence of an ALC extension on this device. */
451 bool queryExtension(const String &name) const;
454 * Retrieves the ALC version supported by this device, as constructed by
455 * MakeVersion.
457 ALCuint getALCVersion() const;
460 * Retrieves the EFX version supported by this device, as constructed by
461 * MakeVersion. If the ALC_EXT_EFX extension is unsupported, this will be
462 * 0.
464 ALCuint getEFXVersion() const;
466 /** Retrieves the device's playback frequency, in hz. */
467 ALCuint getFrequency() const;
470 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
471 * is unsupported, this will be 0.
473 ALCuint getMaxAuxiliarySends() const;
476 * Enumerates available HRTF names. The names are sorted as OpenAL gives
477 * them, such that the index of a given name is the ID to use with
478 * ALC_HRTF_ID_SOFT.
480 * Requires the ALC_SOFT_HRTF extension.
482 Vector<String> enumerateHRTFNames() const;
485 * Retrieves whether HRTF is enabled on the device or not.
487 * Requires the ALC_SOFT_HRTF extension.
489 bool isHRTFEnabled() const;
492 * Retrieves the name of the HRTF currently being used by this device.
494 * Requires the ALC_SOFT_HRTF extension.
496 String getCurrentHRTF() const;
499 * Resets the device, using the specified attributes.
501 * Requires the ALC_SOFT_HRTF extension.
503 void reset(ArrayView<AttributePair> attributes);
506 * Creates a new Context on this device, using the specified attributes.
508 Context createContext(ArrayView<AttributePair> attributes=ArrayView<AttributePair>());
511 * Pauses device processing, stopping updates for its contexts. Multiple
512 * calls are allowed but it is not reference counted, so the device will
513 * resume after one resumeDSP call.
515 * Requires the ALC_SOFT_pause_device extension.
517 void pauseDSP();
520 * Resumes device processing, restarting updates for its contexts. Multiple
521 * calls are allowed and will no-op.
523 void resumeDSP();
526 * Closes and frees the device. All previously-created contexts must first
527 * be destroyed.
529 void close();
533 enum class DistanceModel {
534 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
535 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
536 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
537 Inverse = AL_INVERSE_DISTANCE,
538 Linear = AL_LINEAR_DISTANCE,
539 Exponent = AL_EXPONENT_DISTANCE,
540 None = AL_NONE,
543 class ALURE_API Context {
544 MAKE_PIMPL(Context, ALContext)
546 public:
547 /** Makes the specified context current for OpenAL operations. */
548 static void MakeCurrent(Context context);
549 /** Retrieves the current context used for OpenAL operations. */
550 static Context GetCurrent();
553 * Makes the specified context current for OpenAL operations on the calling
554 * thread only. Requires the ALC_EXT_thread_local_context extension on both
555 * the context's device and the DeviceManager.
557 static void MakeThreadCurrent(Context context);
558 /** Retrieves the thread-specific context used for OpenAL operations. */
559 static Context GetThreadCurrent();
562 * Destroys the context. The context must not be current when this is
563 * called.
565 void destroy();
567 /** Retrieves the Device this context was created from. */
568 Device getDevice();
570 void startBatch();
571 void endBatch();
574 * Retrieves a Listener instance for this context. Each context will only
575 * have one listener.
577 Listener getListener();
580 * Sets a MessageHandler instance which will be used to provide certain
581 * messages back to the application. Only one handler may be set for a
582 * context at a time. The previously set handler will be returned.
584 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
586 /** Gets the currently-set message handler. */
587 SharedPtr<MessageHandler> getMessageHandler() const;
590 * Specifies the desired interval that the background thread will be woken
591 * up to process tasks, e.g. keeping streaming sources filled. An interval
592 * of 0 means the background thread will only be woken up manually with
593 * calls to update. The default is 0.
595 void setAsyncWakeInterval(std::chrono::milliseconds msec);
598 * Retrieves the current interval used for waking up the background thread.
600 std::chrono::milliseconds getAsyncWakeInterval() const;
602 // Functions below require the context to be current
605 * Creates a Decoder instance for the given audio file or resource name.
607 SharedPtr<Decoder> createDecoder(const String &name);
610 * Queries if the channel configuration and sample type are supported by
611 * the context.
613 bool isSupported(ChannelConfig channels, SampleType type) const;
616 * Queries the list of resamplers supported by the context. If the
617 * AL_SOFT_source_resampler extension is unsupported this will be an empty
618 * vector, otherwise there will be at least one entry.
620 const Vector<String> &getAvailableResamplers();
622 * Queries the context's default resampler index. Be aware, if the
623 * AL_SOFT_source_resampler extension is unsupported the resampler list
624 * will be empty and this will resturn 0. If you try to access the
625 * resampler list with this index without the extension, undefined behavior
626 * (accessing an out of bounds array index) will occur.
628 ALsizei getDefaultResamplerIndex() const;
631 * Creates and caches a Buffer for the given audio file or resource name.
632 * Multiple calls with the same name will return the same Buffer object.
634 Buffer getBuffer(const String &name);
637 * Creates and caches a Buffer for the given audio file or resource name.
638 * Multiple calls with the same name will return the same Buffer object.
640 * The returned Buffer object will be scheduled for loading asynchronously,
641 * and must be checked with a call to Buffer::getLoadStatus prior to being
642 * played.
644 Buffer getBufferAsync(const String &name);
647 * Creates and caches a Buffer using the given name. The name may alias an
648 * audio file, but it must not currently exist in the buffer cache. As with
649 * other cached buffers, removeBuffer must be used to remove it from the
650 * cache.
652 Buffer createBufferFrom(const String &name, SharedPtr<Decoder> decoder);
655 * Creates and caches a Buffer using the given name. The name may alias an
656 * audio file, but it must not currently exist in the buffer cache.
658 * The returned Buffer object will be scheduled for loading asynchronously,
659 * and must be checked with a call to Buffer::getLoadStatus prior to being
660 * played. The given decoder will be held on to and used asynchronously to
661 * load the buffer. The decoder must not have its read or seek methods
662 * called while the buffer load status is pending.
664 Buffer createBufferAsyncFrom(const String &name, SharedPtr<Decoder> decoder);
667 * Deletes the cached Buffer object for the given audio file or
668 * resource name. The buffer must not be in use by a Source.
670 void removeBuffer(const String &name);
672 * Deletes the given cached buffer. The buffer must not be in use by a
673 * Source.
675 void removeBuffer(Buffer buffer);
678 * Creates a new Source. There is no practical limit to the number of
679 * sources you may create.
681 Source createSource();
683 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
685 Effect createEffect();
687 SourceGroup createSourceGroup(String name);
688 SourceGroup getSourceGroup(const String &name);
690 void setDopplerFactor(ALfloat factor);
692 void setSpeedOfSound(ALfloat speed);
694 void setDistanceModel(DistanceModel model);
697 * Updates the context and all sources belonging to this context (you do
698 * not need to call the individual sources' update method if you call this
699 * function).
701 void update();
704 class ALURE_API Listener {
705 MAKE_PIMPL(Listener, ALListener)
707 public:
708 void setGain(ALfloat gain);
710 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
712 void setPosition(ALfloat x, ALfloat y, ALfloat z);
713 void setPosition(const ALfloat *pos);
715 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
716 void setVelocity(const ALfloat *vel);
718 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
719 void setOrientation(const ALfloat *at, const ALfloat *up);
720 void setOrientation(const ALfloat *ori);
722 void setMetersPerUnit(ALfloat m_u);
726 enum class BufferLoadStatus {
727 Pending,
728 Ready
731 class ALURE_API Buffer {
732 MAKE_PIMPL(Buffer, ALBuffer)
734 public:
736 * Retrieves the length of the buffer in sample frames. The buffer must be
737 * fully loaded before this method is called.
739 ALuint getLength() const;
741 /** Retrieves the buffer's frequency in hz. */
742 ALuint getFrequency() const;
744 /** Retrieves the buffer's sample configuration. */
745 ChannelConfig getChannelConfig() const;
747 /** Retrieves the buffer's sample type. */
748 SampleType getSampleType() const;
751 * Retrieves the storage size used by the buffer, in bytes. The buffer must
752 * be fully loaded before this method is called.
754 ALuint getSize() const;
757 * Sets the buffer's loop points, used for looping sources. If the current
758 * context does not support the AL_SOFT_loop_points extension, start and
759 * end must be 0 and getLength() respectively. Otherwise, start must be
760 * less than end, and end must be less than or equal to getLength().
762 * The buffer must not be in use when this method is called, and the buffer
763 * must be fully loaded.
765 * \param start The starting point, in sample frames (inclusive).
766 * \param end The ending point, in sample frames (exclusive).
768 void setLoopPoints(ALuint start, ALuint end);
771 * Retrieves the current loop points as a [start,end) pair. The buffer must
772 * be fully loaded before this method is called.
774 std::pair<ALuint,ALuint> getLoopPoints() const;
777 * Retrieves the Source objects currently playing the buffer. Stopping the
778 * returned sources will allow the buffer to be removed from the context.
780 Vector<Source> getSources() const;
783 * Queries the buffer's load status. A return of BufferLoadStatus::Pending
784 * indicates the buffer is not finished loading and can't be used with a
785 * call to Source::play. Buffers created with Context::getBuffer will
786 * always return BufferLoadStatus::Ready.
788 BufferLoadStatus getLoadStatus();
790 /** Retrieves the name the buffer was created with. */
791 const String &getName() const;
793 /** Queries if the buffer is in use and can't be removed. */
794 bool isInUse() const;
798 enum class Spatialize {
799 Off = AL_FALSE,
800 On = AL_TRUE,
801 Auto = 0x0002 /* AL_AUTO_SOFT */
804 class ALURE_API Source {
805 MAKE_PIMPL(Source, ALSource)
807 public:
809 * Plays the source using buffer. The same buffer may be played from
810 * multiple sources simultaneously.
812 void play(Buffer buffer);
814 * Plays the source by streaming audio from decoder. This will use
815 * queuesize buffers, each with updatelen sample frames. The given decoder
816 * must *NOT* have its read or seek methods called from elsewhere while in
817 * use.
819 void play(SharedPtr<Decoder> decoder, ALuint updatelen, ALuint queuesize);
821 * Stops playback, releasing the buffer or decoder reference.
823 void stop();
825 /** Pauses the source if it is playing. */
826 void pause();
828 /** Resumes the source if it is paused. */
829 void resume();
831 /** Specifies if the source is currently playing. */
832 bool isPlaying() const;
834 /** Specifies if the source is currently paused. */
835 bool isPaused() const;
838 * Specifies the source's playback priority. Lowest priority sources will
839 * be evicted first when higher priority sources are played.
841 void setPriority(ALuint priority);
842 /** Retrieves the source's priority. */
843 ALuint getPriority() const;
846 * Sets the source's offset, in sample frames. If the source is playing or
847 * paused, it will go to that offset immediately, otherwise the source will
848 * start at the specified offset the next time it's played.
850 void setOffset(uint64_t offset);
852 * Retrieves the source offset in sample frames and its latency in nano-
853 * seconds. For streaming sources, this will be the offset from the
854 * beginning of the stream based on the decoder's reported position.
856 * If the AL_SOFT_source_latency extension is unsupported, the latency will
857 * be 0.
859 std::pair<uint64_t,std::chrono::nanoseconds> getSampleOffsetLatency() const;
860 uint64_t getSampleOffset() const { return std::get<0>(getSampleOffsetLatency()); }
862 * Retrieves the source offset and latency in seconds. For streaming
863 * sources, this will be the offset from the beginning of the stream based
864 * on the decoder's reported position.
866 * If the AL_SOFT_source_latency extension is unsupported, the latency will
867 * be 0.
869 std::pair<Seconds,Seconds> getSecOffsetLatency() const;
870 Seconds getSecOffset() const { return std::get<0>(getSecOffsetLatency()); }
873 * Specifies if the source should loop on the Buffer or Decoder object's
874 * loop points.
876 void setLooping(bool looping);
877 bool getLooping() const;
880 * Specifies a linear pitch shift base. A value of 1.0 is the default
881 * normal speed.
883 void setPitch(ALfloat pitch);
884 ALfloat getPitch() const;
887 * Specifies the base linear gain. A value of 1.0 is the default normal
888 * volume.
890 void setGain(ALfloat gain);
891 ALfloat getGain() const;
894 * Specifies the minimum and maximum gain. The source's gain is clamped to
895 * this range after distance attenuation and cone attenuation are applied
896 * to the gain base, although before the filter gain adjustements.
898 void setGainRange(ALfloat mingain, ALfloat maxgain);
899 std::pair<ALfloat,ALfloat> getGainRange() const;
900 ALfloat getMinGain() const { return std::get<0>(getGainRange()); }
901 ALfloat getMaxGain() const { return std::get<1>(getGainRange()); }
904 * Specifies the reference distance and maximum distance the source will
905 * use for the current distance model. For Clamped distance models, the
906 * source's calculated distance is clamped to the specified range before
907 * applying distance-related attenuation.
909 * For all distance models, the reference distance is the distance at which
910 * the source's volume will not have any extra attenuation (an effective
911 * gain multiplier of 1).
913 void setDistanceRange(ALfloat refdist, ALfloat maxdist);
914 std::pair<ALfloat,ALfloat> getDistanceRange() const;
915 ALfloat getReferenceDistance() const { return std::get<0>(getDistanceRange()); }
916 ALfloat getMaxDistance() const { return std::get<1>(getDistanceRange()); }
918 /** Specifies the source's 3D position, velocity, and direction together. */
919 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const Vector3 &direction);
921 /** Specifies the source's 3D position, velocity, and orientation together. */
922 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
924 /** Specifies the source's 3D position. */
925 void setPosition(ALfloat x, ALfloat y, ALfloat z);
926 void setPosition(const ALfloat *pos);
927 Vector3 getPosition() const;
930 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
931 * this does not actually alter the source's position, and instead just
932 * alters the pitch as determined by the doppler effect.
934 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
935 void setVelocity(const ALfloat *vel);
936 Vector3 getVelocity() const;
939 * Specifies the source's 3D facing direction. Deprecated in favor of
940 * setOrientation.
942 void setDirection(ALfloat x, ALfloat y, ALfloat z);
943 void setDirection(const ALfloat *dir);
944 Vector3 getDirection() const;
947 * Specifies the source's 3D orientation. Note: unlike the AL_EXT_BFORMAT
948 * extension this property comes from, this also affects the facing
949 * direction, superceding setDirection.
951 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
952 void setOrientation(const ALfloat *at, const ALfloat *up);
953 void setOrientation(const ALfloat *ori);
954 std::pair<Vector3,Vector3> getOrientation() const;
957 * Specifies the source's cone angles, in degrees. The inner angle is the
958 * area within which the listener will hear the source with no extra
959 * attenuation, while the listener being outside of the outer angle will
960 * hear the source attenuated according to the outer cone gains.
962 void setConeAngles(ALfloat inner, ALfloat outer);
963 std::pair<ALfloat,ALfloat> getConeAngles() const;
964 ALfloat getInnerConeAngle() const { return std::get<0>(getConeAngles()); }
965 ALfloat getOuterConeAngle() const { return std::get<1>(getConeAngles()); }
968 * Specifies the linear gain multiplier when the listener is outside of the
969 * source's outer cone area. The specified gain applies to all frequencies,
970 * while gainhf applies extra attenuation to high frequencies.
972 * \param gainhf has no effect without the ALC_EXT_EFX extension.
974 void setOuterConeGains(ALfloat gain, ALfloat gainhf=1.0f);
975 std::pair<ALfloat,ALfloat> getOuterConeGains() const;
976 ALfloat getOuterConeGain() const { return std::get<0>(getOuterConeGains()); }
977 ALfloat getOuterConeGainHF() const { return std::get<1>(getOuterConeGains()); }
980 * Specifies the rolloff factors for the direct and send paths. This is
981 * effectively a distance scaling relative to the reference distance. Note:
982 * the room rolloff factor is 0 by default, disabling distance attenuation
983 * for send paths. This is because the reverb engine will, by default,
984 * apply a more realistic room attenuation based on the reverb decay time
985 * and direct path attenuation.
987 void setRolloffFactors(ALfloat factor, ALfloat roomfactor=0.0f);
988 std::pair<ALfloat,ALfloat> getRolloffFactors() const;
989 ALfloat getRolloffFactor() const { return std::get<0>(getRolloffFactors()); }
990 ALfloat getRoomRolloffFactor() const { return std::get<1>(getRolloffFactors()); }
993 * Specifies the doppler factor for the doppler effect's pitch shift. This
994 * effectively scales the source and listener velocities for the doppler
995 * calculation.
997 void setDopplerFactor(ALfloat factor);
998 ALfloat getDopplerFactor() const;
1000 /** Specifies if the source properties are relative to the listener. */
1001 void setRelative(bool relative);
1002 bool getRelative() const;
1005 * Specifies the source's radius. This causes the source to behave as if
1006 * every point within the spherical area emits sound.
1008 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1010 void setRadius(ALfloat radius);
1011 ALfloat getRadius() const;
1014 * Specifies the left and right channel angles, in radians, when playing a
1015 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1016 * in front and positive values going left.
1018 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1020 void setStereoAngles(ALfloat leftAngle, ALfloat rightAngle);
1021 std::pair<ALfloat,ALfloat> getStereoAngles() const;
1023 void set3DSpatialize(Spatialize spatialize);
1024 Spatialize get3DSpatialize() const;
1026 void setResamplerIndex(ALsizei index);
1027 ALsizei getResamplerIndex() const;
1029 void setAirAbsorptionFactor(ALfloat factor);
1030 ALfloat getAirAbsorptionFactor() const;
1032 void setGainAuto(bool directhf, bool send, bool sendhf);
1033 std::tuple<bool,bool,bool> getGainAuto() const;
1034 bool getDirectGainHFAuto() const { return std::get<0>(getGainAuto()); }
1035 bool getSendGainAuto() const { return std::get<1>(getGainAuto()); }
1036 bool getSendGainHFAuto() const { return std::get<2>(getGainAuto()); }
1038 /** Sets the filter properties on the direct path signal. */
1039 void setDirectFilter(const FilterParams &filter);
1041 * Sets the filter properties on the given send path signal. Any auxiliary
1042 * effect slot on the send path remains in place.
1044 void setSendFilter(ALuint send, const FilterParams &filter);
1046 * Connects the effect slot slot to the given send path. Any filter
1047 * properties on the send path remain as they were.
1049 void setAuxiliarySend(AuxiliaryEffectSlot slot, ALuint send);
1051 * Connects the effect slot slot to the given send path, using the filter
1052 * properties.
1054 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot, ALuint send, const FilterParams &filter);
1057 * Releases the source, stopping playback, releasing resources, and
1058 * returning it to the system.
1060 void release();
1064 class ALURE_API SourceGroup {
1065 MAKE_PIMPL(SourceGroup, ALSourceGroup)
1067 public:
1068 /** Retrieves the associated name of the source group. */
1069 const String &getName() const;
1072 * Adds source to the source group. A source may only be part of one group
1073 * at a time, and will automatically be removed from its current group as
1074 * needed.
1076 void addSource(Source source);
1077 /** Removes source from the source group. */
1078 void removeSource(Source source);
1080 /** Adds a list of sources to the group at once. */
1081 void addSources(ArrayView<Source> sources);
1082 /** Removes a list of sources from the source group. */
1083 void removeSources(ArrayView<Source> sources);
1086 * Adds group as a subgroup of the source group. This method will throw an
1087 * exception if group is being added to a group it has as a sub-group (i.e.
1088 * it would create a circular sub-group chain).
1090 void addSubGroup(SourceGroup group);
1091 /** Removes group from the source group. */
1092 void removeSubGroup(SourceGroup group);
1094 /** Returns the list of sources currently in the group. */
1095 Vector<Source> getSources() const;
1097 /** Returns the list of subgroups currently in the group. */
1098 Vector<SourceGroup> getSubGroups() const;
1100 /** Sets the source group gain, which accumulates with its sources. */
1101 void setGain(ALfloat gain);
1102 /** Gets the source group gain. */
1103 ALfloat getGain() const;
1105 /** Sets the source group pitch, which accumulates with its sources. */
1106 void setPitch(ALfloat pitch);
1107 /** Gets the source group pitch. */
1108 ALfloat getPitch() const;
1111 * Pauses all currently-playing sources that are under this group,
1112 * including sub-groups.
1114 void pauseAll() const;
1116 * Resumes all paused sources that are under this group, including
1117 * sub-groups.
1119 void resumeAll() const;
1121 /** Stops all sources that are under this group, including sub-groups. */
1122 void stopAll() const;
1125 * Releases the source group, removing all sources from it before being
1126 * freed.
1128 void release();
1132 struct SourceSend {
1133 Source mSource;
1134 ALuint mSend;
1137 class ALURE_API AuxiliaryEffectSlot {
1138 MAKE_PIMPL(AuxiliaryEffectSlot, ALAuxiliaryEffectSlot)
1140 public:
1141 void setGain(ALfloat gain);
1143 * If set to true, the reverb effect will automatically apply adjustments
1144 * to the source's send slot based on the effect properties.
1146 * Has no effect when using non-reverb effects. Default is true.
1148 void setSendAuto(bool sendauto);
1151 * Updates the effect slot with a new effect. The given effect object may
1152 * be altered or destroyed without affecting the effect slot.
1154 void applyEffect(Effect effect);
1157 * Releases the effect slot, returning it to the system. It must not be in
1158 * use by a source.
1160 void release();
1163 * Retrieves each Source object and its pairing send this effect slot is
1164 * set on. Setting a different (or null) effect slot on each source's given
1165 * send will allow the effect slot to be released.
1167 Vector<SourceSend> getSourceSends() const;
1169 /** Determines if the effect slot is in use by a source. */
1170 bool isInUse() const;
1174 class ALURE_API Effect {
1175 MAKE_PIMPL(Effect, ALEffect)
1177 public:
1179 * Updates the effect with the specified reverb properties. If the
1180 * EAXReverb effect is not supported, it will automatically attempt to
1181 * downgrade to the Standard Reverb effect.
1183 void setReverbProperties(const EFXEAXREVERBPROPERTIES &props);
1185 void destroy();
1190 * Audio decoder interface. Applications may derive from this, implementing the
1191 * necessary methods, and use it in places the API wants a Decoder object.
1193 class ALURE_API Decoder {
1194 public:
1195 virtual ~Decoder() { }
1197 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1198 virtual ALuint getFrequency() const = 0;
1199 /** Retrieves the channel configuration of the audio being decoded. */
1200 virtual ChannelConfig getChannelConfig() const = 0;
1201 /** Retrieves the sample type of the audio being decoded. */
1202 virtual SampleType getSampleType() const = 0;
1205 * Retrieves the total length of the audio, in sample frames. If unknown,
1206 * returns 0. Note that if the returned length is 0, the decoder may not be
1207 * used to load a Buffer.
1209 virtual uint64_t getLength() const = 0;
1211 * Retrieves the current sample frame position (i.e. the number of sample
1212 * frames from the beginning).
1214 virtual uint64_t getPosition() const = 0;
1216 * Seek to pos, specified in sample frames. Returns true if the seek was
1217 * successful.
1219 virtual bool seek(uint64_t pos) = 0;
1222 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1223 * start >= end, use all available data.
1225 virtual std::pair<uint64_t,uint64_t> getLoopPoints() const = 0;
1228 * Decodes count sample frames, writing them to ptr, and returns the number
1229 * of sample frames written. Returning less than the requested count
1230 * indicates the end of the audio.
1232 virtual ALuint read(ALvoid *ptr, ALuint count) = 0;
1236 * Audio decoder factory interface. Applications may derive from this,
1237 * implementing the necessary methods, and use it in places the API wants a
1238 * DecoderFactory object.
1240 class ALURE_API DecoderFactory {
1241 public:
1242 virtual ~DecoderFactory() { }
1245 * Creates and returns a Decoder instance for the given resource file. If
1246 * the decoder needs to retain the file handle for reading as-needed, it
1247 * should move the UniquePtr to internal storage.
1249 * \return nullptr if a decoder can't be created from the file.
1251 virtual SharedPtr<Decoder> createDecoder(UniquePtr<std::istream> &file) = 0;
1255 * Registers a decoder factory for decoding audio. Registered factories are
1256 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1257 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1258 * name1 < name2. Internal decoder factories are always used after registered
1259 * ones.
1261 * Alure retains a reference to the DecoderFactory instance and will release it
1262 * (potentially destroying the object) when the library unloads.
1264 * \param name A unique name identifying this decoder factory.
1265 * \param factory A DecoderFactory instance used to create Decoder instances.
1267 ALURE_API void RegisterDecoder(const String &name, UniquePtr<DecoderFactory> factory);
1270 * Unregisters a decoder factory by name. Alure returns the instance back to
1271 * the application.
1273 * \param name The unique name identifying a previously-registered decoder
1274 * factory.
1276 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1277 * decoder factory with the given name doesn't exist.
1279 ALURE_API UniquePtr<DecoderFactory> UnregisterDecoder(const String &name);
1283 * A file I/O factory interface. Applications may derive from this and set an
1284 * instance to be used by the audio decoders. By default, the library uses
1285 * standard I/O.
1287 class ALURE_API FileIOFactory {
1288 public:
1290 * Sets the factory instance to be used by the audio decoders. If a
1291 * previous factory was set, it's returned to the application. Passing in a
1292 * NULL factory reverts to the default.
1294 static UniquePtr<FileIOFactory> set(UniquePtr<FileIOFactory> factory);
1297 * Gets the current FileIOFactory instance being used by the audio
1298 * decoders.
1300 static FileIOFactory &get();
1302 virtual ~FileIOFactory() { }
1304 /** Opens a read-only binary file for the given name. */
1305 virtual UniquePtr<std::istream> openFile(const String &name) = 0;
1310 * A message handler interface. Applications may derive from this and set an
1311 * instance on a context to receive messages. The base methods are no-ops, so
1312 * derived classes only need to implement methods for relevant messages.
1314 * It's recommended that applications mark their handler methods using the
1315 * override keyword, to ensure they're properly overriding the base methods in
1316 * case they change.
1318 class ALURE_API MessageHandler {
1319 public:
1320 virtual ~MessageHandler();
1323 * Called when the given device has been disconnected and is no longer
1324 * usable for output. As per the ALC_EXT_disconnect specification,
1325 * disconnected devices remain valid, however all playing sources are
1326 * automatically stopped, any sources that are attempted to play will
1327 * immediately stop, and new contexts may not be created on the device.
1329 * Note that connection status is checked during Context::update calls, so
1330 * that method must be called regularly to be notified when a device is
1331 * disconnected. This method may not be called if the device lacks support
1332 * for the ALC_EXT_disconnect extension.
1334 * WARNING: Do not attempt to clean up resources within this callback
1335 * method, as Alure is in the middle of doing updates. Instead, flag the
1336 * device as having been lost and do cleanup later.
1338 virtual void deviceDisconnected(Device device);
1341 * Called when the given source reaches the end of the buffer or stream.
1343 * Sources that stopped automatically will be detected upon a call to
1344 * Context::update or Source::update.
1346 virtual void sourceStopped(Source source);
1349 * Called when the given source was forced to stop. This can be because
1350 * either there were no more system sources and a higher-priority source
1351 * needs to play, or it's part of a SourceGroup (or sub-group thereof) that
1352 * had its SourceGroup::stopAll method called.
1354 virtual void sourceForceStopped(Source source);
1357 * Called when a new buffer is about to be created and loaded. May be
1358 * called asynchronously for buffers being loaded asynchronously.
1360 * \param name The resource name, as passed to Context::getBuffer.
1361 * \param channels Channel configuration of the given audio data.
1362 * \param type Sample type of the given audio data.
1363 * \param samplerate Sample rate of the given audio data.
1364 * \param data The audio data that is about to be fed to the OpenAL buffer.
1366 virtual void bufferLoading(const String &name, ChannelConfig channels, SampleType type, ALuint samplerate, const Vector<ALbyte> &data);
1369 * Called when a resource isn't found, allowing the app to substitute in a
1370 * different resource. For buffers created with Context::getBuffer or
1371 * Context::getBufferAsync, the original name will still be used for the
1372 * cache map so the app doesn't have to keep track of substituted resource
1373 * names.
1375 * This will be called again if the new name isn't found.
1377 * \param name The resource name that was not found.
1378 * \return The replacement resource name to use instead. Returning an empty
1379 * string means to stop trying.
1381 virtual String resourceNotFound(const String &name);
1384 #undef MAKE_PIMPL
1386 } // namespace alure
1388 #endif /* AL_ALURE2_H */