Make AttributesEnd a function to work around a C++11 deficiency
[alure.git] / include / AL / alure2.h
blob54733bf2682fb2b639bb71856ebe76071a6368bb
1 #ifndef AL_ALURE2_H
2 #define AL_ALURE2_H
4 #include <vector>
5 #include <string>
6 #include <memory>
7 #include <cstring>
8 #include <utility>
9 #include <future>
10 #include <chrono>
11 #include <array>
12 #include <cmath>
14 #include "alc.h"
15 #include "al.h"
16 #include "alure2-alext.h"
18 #ifndef ALURE_API
19 #if defined(ALURE_STATIC_LIB)
20 #define ALURE_API
21 #elif defined(_WIN32)
22 #define ALURE_API __declspec(dllimport)
23 #elif defined(__GNUC__)
24 #define ALURE_API __attribute__((visibility("default")))
25 #elif defined(__has_attribute)
26 #if __has_attribute(visibility)
27 #define ALURE_API __attribute__((visibility("default")))
28 #else
29 #define ALURE_API
30 #endif
31 #else
32 #define ALURE_API
33 #endif
34 #endif /* ALURE_API */
36 #ifndef EFXEAXREVERBPROPERTIES_DEFINED
37 #define EFXEAXREVERBPROPERTIES_DEFINED
38 typedef struct {
39 float flDensity;
40 float flDiffusion;
41 float flGain;
42 float flGainHF;
43 float flGainLF;
44 float flDecayTime;
45 float flDecayHFRatio;
46 float flDecayLFRatio;
47 float flReflectionsGain;
48 float flReflectionsDelay;
49 float flReflectionsPan[3];
50 float flLateReverbGain;
51 float flLateReverbDelay;
52 float flLateReverbPan[3];
53 float flEchoTime;
54 float flEchoDepth;
55 float flModulationTime;
56 float flModulationDepth;
57 float flAirAbsorptionGainHF;
58 float flHFReference;
59 float flLFReference;
60 float flRoomRolloffFactor;
61 int iDecayHFLimit;
62 } EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
63 #endif
65 namespace alure {
67 class DeviceManager;
68 class DeviceManagerImpl;
69 class Device;
70 class DeviceImpl;
71 class Context;
72 class ContextImpl;
73 class Listener;
74 class ListenerImpl;
75 class Buffer;
76 class BufferImpl;
77 class Source;
78 class SourceImpl;
79 class SourceGroup;
80 class SourceGroupImpl;
81 class AuxiliaryEffectSlot;
82 class AuxiliaryEffectSlotImpl;
83 class Effect;
84 class EffectImpl;
85 class Decoder;
86 class DecoderFactory;
87 class MessageHandler;
89 // Convenience aliases
90 template<typename T> using RemoveRefT = typename std::remove_reference<T>::type;
91 template<bool B> using EnableIfT = typename std::enable_if<B>::type;
94 // Duration in seconds, using double precision
95 using Seconds = std::chrono::duration<double>;
97 // A SharedPtr implementation, defaults to C++11's std::shared_ptr. If this is
98 // changed, you must recompile the library.
99 template<typename... Args> using SharedPtr = std::shared_ptr<Args...>;
100 template<typename T, typename... Args>
101 constexpr inline SharedPtr<T> MakeShared(Args&&... args)
103 return std::make_shared<T>(std::forward<Args>(args)...);
106 // A UniquePtr implementation, defaults to C++11's std::unique_ptr. If this is
107 // changed, you must recompile the library.
108 template<typename... Args> using UniquePtr = std::unique_ptr<Args...>;
109 template<typename T, typename... Args>
110 constexpr inline UniquePtr<T> MakeUnique(Args&&... args)
112 #if __cplusplus >= 201402L
113 return std::make_unique<T>(std::forward<Args>(args)...);
114 #else
115 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
116 #endif
119 // A Promise/Future (+SharedFuture) implementation, defaults to C++11's
120 // std::promise, std::future, and std::shared_future. If this is changed, you
121 // must recompile the library.
122 template<typename... Args> using Promise = std::promise<Args...>;
123 template<typename... Args> using Future = std::future<Args...>;
124 template<typename... Args> using SharedFuture = std::shared_future<Args...>;
126 // A Vector implementation, defaults to C++'s std::vector. If this is changed,
127 // you must recompile the library.
128 template<typename... Args> using Vector = std::vector<Args...>;
130 // A static-sized Array implementation, defaults to C++11's std::array. If this
131 // is changed, you must recompile the library.
132 template<typename T, std::size_t N> using Array = std::array<T, N>;
134 // A String implementation, default's to C++'s std::string. If this is changed,
135 // you must recompile the library.
136 template<typename... Args> using BasicString = std::basic_string<Args...>;
137 using String = BasicString<std::string::value_type>;
139 // Tag specific containers that guarantee contiguous storage. The standard
140 // provides no such mechanism, so we have to manually specify which are
141 // acceptable.
142 template<typename T> struct IsContiguousTag : std::false_type {};
143 template<typename T, size_t N> struct IsContiguousTag<Array<T,N>> : std::true_type {};
144 template<typename T> struct IsContiguousTag<Vector<T>> : std::true_type {};
145 template<typename T> struct IsContiguousTag<BasicString<T>> : std::true_type {};
147 // A rather simple ArrayView container. This allows accepting various array
148 // types (Array, Vector, a static-sized array, a dynamic array + size) without
149 // copying its elements.
150 template<typename T>
151 class ArrayView {
152 public:
153 using value_type = T;
155 using iterator = const value_type*;
156 using const_iterator = const value_type*;
158 using size_type = size_t;
160 static constexpr size_type npos = static_cast<size_type>(-1);
162 private:
163 const value_type *mElems;
164 size_t mNumElems;
166 public:
167 ArrayView() noexcept : mElems(nullptr), mNumElems(0) { }
168 ArrayView(const ArrayView&) noexcept = default;
169 ArrayView(ArrayView&&) noexcept = default;
170 ArrayView(const value_type *elems, size_type num_elems) noexcept
171 : mElems(elems), mNumElems(num_elems) { }
172 template<typename OtherT> ArrayView(RemoveRefT<OtherT>&&) = delete;
173 template<typename OtherT,
174 typename = EnableIfT<IsContiguousTag<RemoveRefT<OtherT>>::value>>
175 ArrayView(const OtherT &rhs) noexcept : mElems(rhs.data()), mNumElems(rhs.size()) { }
176 template<size_t N>
177 ArrayView(const value_type (&elems)[N]) noexcept : mElems(elems), mNumElems(N) { }
179 ArrayView& operator=(const ArrayView&) noexcept = default;
181 const value_type *data() const noexcept { return mElems; }
183 size_type size() const noexcept { return mNumElems; }
184 bool empty() const noexcept { return mNumElems == 0; }
186 const value_type& operator[](size_t i) const { return mElems[i]; }
188 const value_type& front() const { return mElems[0]; }
189 const value_type& back() const { return mElems[mNumElems-1]; }
191 const value_type& at(size_t i) const
193 if(i >= mNumElems)
194 throw std::out_of_range("alure::ArrayView::at: element out of range");
195 return mElems[i];
198 const_iterator begin() const noexcept { return mElems; }
199 const_iterator cbegin() const noexcept { return mElems; }
201 const_iterator end() const noexcept { return mElems + mNumElems; }
202 const_iterator cend() const noexcept { return mElems + mNumElems; }
204 ArrayView slice(size_type pos, size_type len = npos) const noexcept
206 if(pos >= size())
207 return ArrayView(data()+size(), 0);
208 if(len == npos || size()-pos < len)
209 return ArrayView(data()+pos, size()-pos);
210 return ArrayView(data()+pos, len);
214 template<typename T, typename Tr=std::char_traits<T>>
215 class BasicStringView : public ArrayView<T> {
216 using BaseT = ArrayView<T>;
217 using StringT = BasicString<T,Tr>;
219 public:
220 using typename BaseT::value_type;
221 using typename BaseT::size_type;
222 using BaseT::npos;
223 using char_type = T;
224 using traits_type = Tr;
226 BasicStringView() noexcept = default;
227 BasicStringView(const BasicStringView&) noexcept = default;
228 BasicStringView(const value_type *elems, size_type num_elems) noexcept
229 : ArrayView<T>(elems, num_elems) { }
230 BasicStringView(const value_type *elems) : ArrayView<T>(elems, std::strlen(elems)) { }
231 BasicStringView(StringT&&) = delete;
232 BasicStringView(const StringT &rhs) noexcept : ArrayView<T>(rhs) { }
233 #if __cplusplus >= 201703L
234 BasicStringView(const std::basic_string_view<T> &rhs) noexcept
235 : ArrayView<T>(rhs.data(), rhs.length()) { }
236 #endif
238 BasicStringView& operator=(const BasicStringView&) noexcept = default;
240 size_type length() const { return BaseT::size(); }
242 explicit operator StringT() const { return StringT(BaseT::data(), length()); }
243 #if __cplusplus >= 201703L
244 operator std::basic_string_view<T,Tr>() const noexcept
245 { return std::basic_string_view<T,Tr>(BaseT::data(), length()); }
246 #endif
248 StringT operator+(const StringT &rhs) const
250 StringT ret = StringT(*this);
251 ret += rhs;
252 return ret;
254 StringT operator+(const typename StringT::value_type *rhs) const
256 StringT ret = StringT(*this);
257 ret += rhs;
258 return ret;
261 int compare(BasicStringView other) const noexcept
263 int ret = traits_type::compare(
264 BaseT::data(), other.data(), std::min<size_t>(length(), other.length())
266 if(ret == 0)
268 if(length() > other.length()) return 1;
269 if(length() < other.length()) return -1;
270 return 0;
272 return ret;
274 bool operator==(BasicStringView rhs) const noexcept { return compare(rhs) == 0; }
275 bool operator!=(BasicStringView rhs) const noexcept { return compare(rhs) != 0; }
276 bool operator<=(BasicStringView rhs) const noexcept { return compare(rhs) <= 0; }
277 bool operator>=(BasicStringView rhs) const noexcept { return compare(rhs) >= 0; }
278 bool operator<(BasicStringView rhs) const noexcept { return compare(rhs) < 0; }
279 bool operator>(BasicStringView rhs) const noexcept { return compare(rhs) > 0; }
281 BasicStringView substr(size_type pos, size_type len = npos) const noexcept
283 if(pos >= length())
284 return BasicStringView(BaseT::data()+length(), 0);
285 if(len == npos || length()-pos < len)
286 return BasicStringView(BaseT::data()+pos, length()-pos);
287 return BasicStringView(BaseT::data()+pos, len);
290 size_type find_first_of(char_type ch, size_type pos = 0) const noexcept
292 if(pos >= length()) return npos;
293 const char_type *chpos = traits_type::find(BaseT::data()+pos, length()-pos, ch);
294 if(chpos) return chpos - BaseT::data();
295 return npos;
297 size_type find_first_of(BasicStringView other, size_type pos = 0) const noexcept
299 size_type ret = npos;
300 for(auto ch : other)
301 ret = std::min<size_type>(ret, find_first_of(ch, pos));
302 return ret;
305 using StringView = BasicStringView<String::value_type>;
307 // Inline operators to concat String and C-style strings with StringViews.
308 template<typename T, typename Tr>
309 inline BasicString<T,Tr> operator+(const BasicString<T,Tr> &lhs, BasicStringView<T,Tr> rhs)
310 { return BasicString<T,Tr>(lhs).append(rhs.data(), rhs.size()); }
311 template<typename T, typename Tr>
312 inline BasicString<T,Tr> operator+(BasicString<T,Tr> lhs, BasicStringView<T,Tr> rhs)
313 { return std::move(lhs.append(rhs.data(), rhs.size())); }
314 template<typename T, typename Tr>
315 inline BasicString<T,Tr> operator+(const typename BasicString<T,Tr>::value_type *lhs, BasicStringView<T,Tr> rhs)
316 { return lhs + BasicString<T,Tr>(rhs); }
317 template<typename T, typename Tr>
318 inline BasicString<T,Tr>& operator+=(BasicString<T,Tr> &lhs, BasicStringView<T,Tr> rhs)
319 { return lhs.append(rhs.data(), rhs.size()); }
321 // Inline operators to compare String and C-style strings with StringViews.
322 #define ALURE_DECL_STROP(op) \
323 template<typename T, typename Tr> \
324 inline bool operator op(const BasicString<T,Tr> &lhs, BasicStringView<T,Tr> rhs) \
325 { return BasicStringView<T,Tr>(lhs) op rhs; } \
326 template<typename T, typename Tr> \
327 inline bool operator op(const typename BasicString<T,Tr>::value_type *lhs, \
328 BasicStringView<T,Tr> rhs) \
329 { return BasicStringView<T,Tr>(lhs) op rhs; }
330 ALURE_DECL_STROP(==)
331 ALURE_DECL_STROP(!=)
332 ALURE_DECL_STROP(<=)
333 ALURE_DECL_STROP(>=)
334 ALURE_DECL_STROP(<)
335 ALURE_DECL_STROP(>)
336 #undef ALURE_DECL_STROP
338 // Inline operator to write out a StringView to an ostream
339 template<typename T, typename Tr>
340 inline std::basic_ostream<T>& operator<<(std::basic_ostream<T,Tr> &lhs, BasicStringView<T,Tr> rhs)
342 for(auto ch : rhs)
343 lhs << ch;
344 return lhs;
348 /** Convert a value from decibels to linear gain. */
349 template<typename T, typename NonRefT=RemoveRefT<T>,
350 typename=EnableIfT<std::is_floating_point<NonRefT>::value>>
351 constexpr inline NonRefT dBToLinear(T&& value)
352 { return std::pow(NonRefT(10.0), std::forward<T&&>(value) / NonRefT(20.0)); }
354 /** Convert a value from linear gain to decibels. */
355 template<typename T, typename NonRefT=RemoveRefT<T>,
356 typename=EnableIfT<std::is_floating_point<NonRefT>::value>>
357 constexpr inline NonRefT LinearTodB(T&& value)
358 { return std::log10(std::forward<T&&>(value)) * NonRefT(20.0); }
361 * An attribute pair, for passing attributes to Device::createContext and
362 * Device::reset.
364 using AttributePair = std::pair<ALCint,ALCint>;
365 static_assert(sizeof(AttributePair) == sizeof(ALCint[2]), "Bad AttributePair size");
366 constexpr inline AttributePair AttributesEnd() noexcept
367 { return std::make_pair(0, 0); }
370 struct FilterParams {
371 ALfloat mGain;
372 ALfloat mGainHF; // For low-pass and band-pass filters
373 ALfloat mGainLF; // For high-pass and band-pass filters
377 class Vector3 {
378 Array<ALfloat,3> mValue;
380 public:
381 constexpr Vector3() noexcept
382 : mValue{{0.0f, 0.0f, 0.0f}}
384 constexpr Vector3(const Vector3 &rhs) noexcept
385 : mValue{{rhs.mValue[0], rhs.mValue[1], rhs.mValue[2]}}
387 constexpr Vector3(ALfloat val) noexcept
388 : mValue{{val, val, val}}
390 constexpr Vector3(ALfloat x, ALfloat y, ALfloat z) noexcept
391 : mValue{{x, y, z}}
393 Vector3(const ALfloat *vec) noexcept
394 : mValue{{vec[0], vec[1], vec[2]}}
397 const ALfloat *getPtr() const noexcept
398 { return mValue.data(); }
400 ALfloat& operator[](size_t i) noexcept
401 { return mValue[i]; }
402 constexpr const ALfloat& operator[](size_t i) const noexcept
403 { return mValue[i]; }
405 #define ALURE_DECL_OP(op) \
406 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
408 return Vector3(mValue[0] op rhs.mValue[0], \
409 mValue[1] op rhs.mValue[1], \
410 mValue[2] op rhs.mValue[2]); \
412 ALURE_DECL_OP(+)
413 ALURE_DECL_OP(-)
414 ALURE_DECL_OP(*)
415 ALURE_DECL_OP(/)
416 #undef ALURE_DECL_OP
417 #define ALURE_DECL_OP(op) \
418 Vector3& operator op(const Vector3 &rhs) noexcept \
420 mValue[0] op rhs.mValue[0]; \
421 mValue[1] op rhs.mValue[1]; \
422 mValue[2] op rhs.mValue[2]; \
423 return *this; \
425 ALURE_DECL_OP(+=)
426 ALURE_DECL_OP(-=)
427 ALURE_DECL_OP(*=)
428 ALURE_DECL_OP(/=)
430 #undef ALURE_DECL_OP
431 #define ALURE_DECL_OP(op) \
432 constexpr Vector3 operator op(ALfloat scale) const noexcept \
434 return Vector3(mValue[0] op scale, \
435 mValue[1] op scale, \
436 mValue[2] op scale); \
438 ALURE_DECL_OP(*)
439 ALURE_DECL_OP(/)
440 #undef ALURE_DECL_OP
441 #define ALURE_DECL_OP(op) \
442 Vector3& operator op(ALfloat scale) noexcept \
444 mValue[0] op scale; \
445 mValue[1] op scale; \
446 mValue[2] op scale; \
447 return *this; \
449 ALURE_DECL_OP(*=)
450 ALURE_DECL_OP(/=)
451 #undef ALURE_DECL_OP
453 constexpr ALfloat getLengthSquared() const noexcept
454 { return mValue[0]*mValue[0] + mValue[1]*mValue[1] + mValue[2]*mValue[2]; }
455 ALfloat getLength() const noexcept
456 { return std::sqrt(getLengthSquared()); }
458 constexpr ALfloat getDistanceSquared(const Vector3 &pos) const noexcept
459 { return (pos - *this).getLengthSquared(); }
460 ALfloat getDistance(const Vector3 &pos) const noexcept
461 { return (pos - *this).getLength(); }
463 static_assert(sizeof(Vector3) == sizeof(ALfloat[3]), "Bad Vector3 size");
466 enum class SampleType {
467 UInt8,
468 Int16,
469 Float32,
470 Mulaw
472 ALURE_API const char *GetSampleTypeName(SampleType type);
474 enum class ChannelConfig {
475 /** 1-channel mono sound. */
476 Mono,
477 /** 2-channel stereo sound. */
478 Stereo,
479 /** 2-channel rear sound (back-left and back-right). */
480 Rear,
481 /** 4-channel surround sound. */
482 Quad,
483 /** 5.1 surround sound. */
484 X51,
485 /** 6.1 surround sound. */
486 X61,
487 /** 7.1 surround sound. */
488 X71,
489 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
490 BFormat2D,
491 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
492 BFormat3D
494 ALURE_API const char *GetChannelConfigName(ChannelConfig cfg);
496 ALURE_API ALuint FramesToBytes(ALuint frames, ChannelConfig chans, SampleType type);
497 ALURE_API ALuint BytesToFrames(ALuint bytes, ChannelConfig chans, SampleType type);
500 /** Class for storing a major.minor version number. */
501 class Version {
502 ALuint mMajor : 16;
503 ALuint mMinor : 16;
505 public:
506 constexpr Version(ALuint _maj, ALuint _min) : mMajor(_maj), mMinor(_min) { }
508 constexpr ALuint getMajor() const noexcept { return mMajor; }
509 constexpr ALuint getMinor() const noexcept { return mMinor; }
510 constexpr bool isZero() const noexcept { return mMajor == 0 && mMinor == 0; }
513 #define MAKE_PIMPL(BaseT, ImplT) \
514 private: \
515 ImplT *pImpl; \
517 public: \
518 using handle_type = ImplT*; \
520 BaseT() : pImpl(nullptr) { } \
521 BaseT(ImplT *impl) : pImpl(impl) { } \
522 BaseT(const BaseT&) = default; \
523 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
525 BaseT& operator=(const BaseT&) = default; \
526 BaseT& operator=(BaseT&& rhs) \
528 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
529 return *this; \
532 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
533 bool operator!=(const BaseT &rhs) const { return pImpl != rhs.pImpl; } \
534 bool operator<=(const BaseT &rhs) const { return pImpl <= rhs.pImpl; } \
535 bool operator>=(const BaseT &rhs) const { return pImpl >= rhs.pImpl; } \
536 bool operator<(const BaseT &rhs) const { return pImpl < rhs.pImpl; } \
537 bool operator>(const BaseT &rhs) const { return pImpl > rhs.pImpl; } \
539 operator bool() const { return !!pImpl; } \
541 handle_type getHandle() const { return pImpl; }
543 enum class DeviceEnumeration {
544 Basic = ALC_DEVICE_SPECIFIER,
545 Full = ALC_ALL_DEVICES_SPECIFIER,
546 Capture = ALC_CAPTURE_DEVICE_SPECIFIER
549 enum class DefaultDeviceType {
550 Basic = ALC_DEFAULT_DEVICE_SPECIFIER,
551 Full = ALC_DEFAULT_ALL_DEVICES_SPECIFIER,
552 Capture = ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
556 * A class managing Device objects and other related functionality. This class
557 * is a singleton, only one instance will exist in a process.
559 class ALURE_API DeviceManager {
560 DeviceManagerImpl *pImpl;
562 DeviceManager(DeviceManagerImpl *impl) : pImpl(impl) { }
563 friend class ALDeviceManager;
565 public:
566 DeviceManager(const DeviceManager&) = default;
567 DeviceManager(DeviceManager&& rhs) : pImpl(rhs.pImpl) { }
569 /** Retrieves the DeviceManager instance. */
570 static DeviceManager get();
572 /** Queries the existence of a non-device-specific ALC extension. */
573 bool queryExtension(const String &name) const;
574 bool queryExtension(const char *name) const;
576 /** Enumerates available device names of the given type. */
577 Vector<String> enumerate(DeviceEnumeration type) const;
578 /** Retrieves the default device of the given type. */
579 String defaultDeviceName(DefaultDeviceType type) const;
582 * Opens the playback device given by name, or the default if blank. Throws
583 * an exception on error.
585 Device openPlayback(const String &name=String());
586 Device openPlayback(const char *name);
589 * Opens the playback device given by name, or the default if blank.
590 * Returns an empty Device on error.
592 Device openPlayback(const String &name, const std::nothrow_t&);
593 Device openPlayback(const char *name, const std::nothrow_t&);
595 /** Opens the default playback device. Returns an empty Device on error. */
596 Device openPlayback(const std::nothrow_t&);
600 enum class PlaybackName {
601 Basic = ALC_DEVICE_SPECIFIER,
602 Full = ALC_ALL_DEVICES_SPECIFIER
605 class ALURE_API Device {
606 MAKE_PIMPL(Device, DeviceImpl)
608 public:
609 /** Retrieves the device name as given by type. */
610 String getName(PlaybackName type=PlaybackName::Full) const;
611 /** Queries the existence of an ALC extension on this device. */
612 bool queryExtension(const String &name) const;
613 bool queryExtension(const char *name) const;
615 /** Retrieves the ALC version supported by this device. */
616 Version getALCVersion() const;
619 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
620 * extension is unsupported, this will be 0.0.
622 Version getEFXVersion() const;
624 /** Retrieves the device's playback frequency, in hz. */
625 ALCuint getFrequency() const;
628 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
629 * is unsupported, this will be 0.
631 ALCuint getMaxAuxiliarySends() const;
634 * Enumerates available HRTF names. The names are sorted as OpenAL gives
635 * them, such that the index of a given name is the ID to use with
636 * ALC_HRTF_ID_SOFT.
638 * Requires the ALC_SOFT_HRTF extension.
640 Vector<String> enumerateHRTFNames() const;
643 * Retrieves whether HRTF is enabled on the device or not.
645 * Requires the ALC_SOFT_HRTF extension.
647 bool isHRTFEnabled() const;
650 * Retrieves the name of the HRTF currently being used by this device.
652 * Requires the ALC_SOFT_HRTF extension.
654 String getCurrentHRTF() const;
657 * Resets the device, using the specified attributes.
659 * Requires the ALC_SOFT_HRTF extension.
661 void reset(ArrayView<AttributePair> attributes);
664 * Creates a new Context on this device, using the specified attributes.
665 * Throws an exception if context creation fails.
667 Context createContext(ArrayView<AttributePair> attributes=ArrayView<AttributePair>());
669 * Creates a new Context on this device, using the specified attributes.
670 * Returns an empty Context if context creation fails.
672 Context createContext(ArrayView<AttributePair> attributes, const std::nothrow_t&);
673 Context createContext(const std::nothrow_t&);
676 * Pauses device processing, stopping updates for its contexts. Multiple
677 * calls are allowed but it is not reference counted, so the device will
678 * resume after one resumeDSP call.
680 * Requires the ALC_SOFT_pause_device extension.
682 void pauseDSP();
685 * Resumes device processing, restarting updates for its contexts. Multiple
686 * calls are allowed and will no-op.
688 void resumeDSP();
691 * Closes and frees the device. All previously-created contexts must first
692 * be destroyed.
694 void close();
698 enum class DistanceModel {
699 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
700 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
701 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
702 Inverse = AL_INVERSE_DISTANCE,
703 Linear = AL_LINEAR_DISTANCE,
704 Exponent = AL_EXPONENT_DISTANCE,
705 None = AL_NONE,
708 class ALURE_API Context {
709 MAKE_PIMPL(Context, ContextImpl)
711 public:
712 /** Makes the specified context current for OpenAL operations. */
713 static void MakeCurrent(Context context);
714 /** Retrieves the current context used for OpenAL operations. */
715 static Context GetCurrent();
718 * Makes the specified context current for OpenAL operations on the calling
719 * thread only. Requires the ALC_EXT_thread_local_context extension on both
720 * the context's device and the DeviceManager.
722 static void MakeThreadCurrent(Context context);
723 /** Retrieves the thread-specific context used for OpenAL operations. */
724 static Context GetThreadCurrent();
727 * Destroys the context. The context must not be current when this is
728 * called.
730 void destroy();
732 /** Retrieves the Device this context was created from. */
733 Device getDevice();
735 void startBatch();
736 void endBatch();
739 * Retrieves a Listener instance for this context. Each context will only
740 * have one listener, which is automatically destroyed with the context.
742 Listener getListener();
745 * Sets a MessageHandler instance which will be used to provide certain
746 * messages back to the application. Only one handler may be set for a
747 * context at a time. The previously set handler will be returned.
749 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
751 /** Gets the currently-set message handler. */
752 SharedPtr<MessageHandler> getMessageHandler() const;
755 * Specifies the desired interval that the background thread will be woken
756 * up to process tasks, e.g. keeping streaming sources filled. An interval
757 * of 0 means the background thread will only be woken up manually with
758 * calls to update. The default is 0.
760 void setAsyncWakeInterval(std::chrono::milliseconds interval);
763 * Retrieves the current interval used for waking up the background thread.
765 std::chrono::milliseconds getAsyncWakeInterval() const;
767 // Functions below require the context to be current
770 * Creates a Decoder instance for the given audio file or resource name.
772 SharedPtr<Decoder> createDecoder(StringView name);
775 * Queries if the channel configuration and sample type are supported by
776 * the context.
778 bool isSupported(ChannelConfig channels, SampleType type) const;
781 * Queries the list of resamplers supported by the context. If the
782 * AL_SOFT_source_resampler extension is unsupported this will be an empty
783 * array, otherwise there will be at least one entry.
785 ArrayView<String> getAvailableResamplers();
787 * Queries the context's default resampler index. Be aware, if the
788 * AL_SOFT_source_resampler extension is unsupported the resampler list
789 * will be empty and this will resturn 0. If you try to access the
790 * resampler list with this index without the extension, undefined behavior
791 * will occur (accessing an out of bounds array index).
793 ALsizei getDefaultResamplerIndex() const;
796 * Creates and caches a Buffer for the given audio file or resource name.
797 * Multiple calls with the same name will return the same Buffer object.
798 * Cached buffers must be freed using removeBuffer before destroying the
799 * context. If the buffer can't be loaded it will throw an exception.
801 Buffer getBuffer(StringView name);
804 * Asynchronously prepares a cached Buffer for the given audio file or
805 * resource name. Multiple calls with the same name will return multiple
806 * SharedFutures for the same Buffer object. Once called, the buffer must
807 * be freed using removeBuffer before destroying the context, even if you
808 * never get the Buffer from the SharedFuture.
810 * The Buffer will be scheduled to load asynchronously, and the caller gets
811 * back a SharedFuture that can be checked later (or waited on) to get the
812 * actual Buffer when it's ready. The application must take care to handle
813 * exceptions from the SharedFuture in case an unrecoverable error ocurred
814 * during the load.
816 SharedFuture<Buffer> getBufferAsync(StringView name);
819 * Asynchronously prepares cached Buffers for the given audio file or
820 * resource names. Duplicate names and buffers already cached are ignored.
821 * Cached buffers must be freed using removeBuffer before destroying the
822 * context.
824 * The Buffer objects will be scheduled for loading asynchronously, and
825 * should be retrieved later when needed using getBufferAsync or getBuffer.
826 * Buffers that cannot be loaded, for example due to an unsupported format,
827 * will be ignored and a later call to getBuffer or getBufferAsync will
828 * throw an exception.
830 void precacheBuffersAsync(ArrayView<StringView> names);
833 * Creates and caches a Buffer using the given name. The name may alias an
834 * audio file, but it must not currently exist in the buffer cache.
836 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
839 * Asynchronously prepares a cached Buffer using the given name. The name
840 * may alias an audio file, but it must not currently exist in the buffer
841 * cache. Once called, the buffer must be freed using removeBuffer before
842 * destroying the context, even if you never get the Buffer from the
843 * SharedFuture.
845 * The Buffer will be scheduled to load asynchronously, and the caller gets
846 * back a SharedFuture that can be checked later (or waited on) to get the
847 * actual Buffer when it's ready. The application must take care to handle
848 * exceptions from the SharedFuture in case an unrecoverable error ocurred
849 * during the load. The decoder must not have its read or seek methods
850 * called while the buffer is not ready.
852 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
855 * Deletes the cached Buffer object for the given audio file or resource
856 * name. The buffer must not be in use by a Source.
858 void removeBuffer(StringView name);
860 * Deletes the given cached buffer. The buffer must not be in use by a
861 * Source.
863 void removeBuffer(Buffer buffer);
866 * Creates a new Source. There is no practical limit to the number of
867 * sources you may create. You must call Source::release when the source is
868 * no longer needed.
870 Source createSource();
872 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
874 Effect createEffect();
876 SourceGroup createSourceGroup(StringView name);
877 SourceGroup getSourceGroup(StringView name);
879 /** Sets the doppler factor to apply to all source calculations. */
880 void setDopplerFactor(ALfloat factor);
883 * Sets the speed of sound propagation, in units per second, to calculate
884 * the doppler effect along with other distance-related time effects. The
885 * default is 343.3 units per second (a realistic speed assuming 1 meter
886 * per unit). If this is adjusted for a different unit scale,
887 * Listener::setMetersPerUnit should also be adjusted.
889 void setSpeedOfSound(ALfloat speed);
891 void setDistanceModel(DistanceModel model);
893 /** Updates the context and all sources belonging to this context. */
894 void update();
897 class ALURE_API Listener {
898 MAKE_PIMPL(Listener, ListenerImpl)
900 public:
901 /** Sets the "master" gain for all context output. */
902 void setGain(ALfloat gain);
905 * Specifies the listener's 3D position, velocity, and orientation
906 * together.
908 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const std::pair<Vector3,Vector3> &orientation);
910 /** Specifies the listener's 3D position. */
911 void setPosition(ALfloat x, ALfloat y, ALfloat z);
912 void setPosition(const ALfloat *pos);
915 * Specifies the listener's 3D velocity, in units per second. As with
916 * OpenAL, this does not actually alter the listener's position, and
917 * instead just alters the pitch as determined by the doppler effect.
919 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
920 void setVelocity(const ALfloat *vel);
923 * Specifies the listener's 3D orientation, using position-relative 'at'
924 * and 'up' direction vectors.
926 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
927 void setOrientation(const ALfloat *at, const ALfloat *up);
928 void setOrientation(const ALfloat *ori);
931 * Sets the number of meters per unit, used for various effects that rely
932 * on the distance in meters (including air absorption and initial reverb
933 * decay). If this is changed, it's strongly recommended to also set the
934 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
935 * realistic 343.3m/s for sound propagation).
937 void setMetersPerUnit(ALfloat m_u);
941 class ALURE_API Buffer {
942 MAKE_PIMPL(Buffer, BufferImpl)
944 public:
945 /** Retrieves the length of the buffer in sample frames. */
946 ALuint getLength() const;
948 /** Retrieves the buffer's frequency in hz. */
949 ALuint getFrequency() const;
951 /** Retrieves the buffer's sample configuration. */
952 ChannelConfig getChannelConfig() const;
954 /** Retrieves the buffer's sample type. */
955 SampleType getSampleType() const;
958 * Retrieves the storage size used by the buffer, in bytes. Note that the
959 * size in bytes may not be what you expect from the length, as it may take
960 * more space internally than the ChannelConfig and SampleType suggest to
961 * be more efficient.
963 ALuint getSize() const;
966 * Sets the buffer's loop points, used for looping sources. If the current
967 * context does not support the AL_SOFT_loop_points extension, start and
968 * end must be 0 and getLength() respectively. Otherwise, start must be
969 * less than end, and end must be less than or equal to getLength().
971 * The buffer must not be in use when this method is called.
973 * \param start The starting point, in sample frames (inclusive).
974 * \param end The ending point, in sample frames (exclusive).
976 void setLoopPoints(ALuint start, ALuint end);
978 /** Retrieves the current loop points as a [start,end) pair. */
979 std::pair<ALuint,ALuint> getLoopPoints() const;
982 * Retrieves the Source objects currently playing the buffer. Stopping the
983 * returned sources will allow the buffer to be removed from the context.
985 Vector<Source> getSources() const;
987 /** Retrieves the name the buffer was created with. */
988 StringView getName() const;
990 /** Queries if the buffer is in use and can't be removed. */
991 bool isInUse() const;
995 enum class Spatialize {
996 Off = AL_FALSE,
997 On = AL_TRUE,
998 Auto = 0x0002 /* AL_AUTO_SOFT */
1001 class ALURE_API Source {
1002 MAKE_PIMPL(Source, SourceImpl)
1004 public:
1006 * Plays the source using a buffer. The same buffer may be played from
1007 * multiple sources simultaneously.
1009 void play(Buffer buffer);
1011 * Plays the source by asynchronously streaming audio from a decoder. The
1012 * given decoder must *NOT* have its read or seek methods called from
1013 * elsewhere while in use.
1015 * \param decoder The decoder object to play audio from.
1016 * \param chunk_len The number of sample frames to read for each chunk
1017 * update. Smaller values will require more frequent updates and
1018 * larger values will handle more data with each chunk.
1019 * \param queue_size The number of chunks to keep queued during playback.
1020 * Smaller values use less memory while larger values improve
1021 * protection against underruns.
1023 void play(SharedPtr<Decoder> decoder, ALuint chunk_len, ALuint queue_size);
1026 * Prepares to play a source using a future buffer. The method will return
1027 * right away and the source will begin playing once the future buffer
1028 * becomes ready. If the future buffer is already ready, it begins playing
1029 * immediately as if you called play(future_buffer.get()).
1031 * The future buffer is checked during calls to \c Context::update and the
1032 * source will start playback once the future buffer reports it's ready.
1033 * Use the isPending method to check if the source is still waiting for the
1034 * future buffer.
1036 void play(SharedFuture<Buffer> future_buffer);
1039 * Stops playback, releasing the buffer or decoder reference. Any pending
1040 * playback from a future buffer is canceled.
1042 void stop();
1045 * Fades the source to the specified gain over the given duration, at which
1046 * point playback will stop. This gain is in addition to the base gain, and
1047 * must be greater than 0 and less than 1. The duration must also be
1048 * greater than 0.
1050 * Pending playback from a future buffer is not immediately canceled, but
1051 * the fading starts with this call. If the future buffer then becomes
1052 * ready, it will start mid-fade. Pending playback will be canceled if the
1053 * fade out completes before the future buffer becomes ready.
1055 * Fading is updated during calls to \c Context::update, which should be
1056 * called regularly (30 to 50 times per second) for the fading to be
1057 * smooth.
1059 void fadeOutToStop(ALfloat gain, std::chrono::milliseconds duration);
1061 /** Pauses the source if it is playing. */
1062 void pause();
1064 /** Resumes the source if it is paused. */
1065 void resume();
1067 /** Specifies if the source is waiting to play a future buffer. */
1068 bool isPending() const;
1070 /** Specifies if the source is currently playing. */
1071 bool isPlaying() const;
1073 /** Specifies if the source is currently paused. */
1074 bool isPaused() const;
1077 * Sets this source as a child of the given source group. The given source
1078 * group's parameters will influence this and all other sources that belong
1079 * to it. A source can only be the child of one source group at a time,
1080 * although that source group may belong to another source group.
1082 * Passing in a null group removes it from its current source group.
1084 void setGroup(SourceGroup group);
1086 /** Retrieves the source group this source belongs to. */
1087 SourceGroup getGroup() const;
1090 * Specifies the source's playback priority. Lowest priority sources will
1091 * be evicted first when higher priority sources are played.
1093 void setPriority(ALuint priority);
1094 /** Retrieves the source's priority. */
1095 ALuint getPriority() const;
1098 * Sets the source's offset, in sample frames. If the source is playing or
1099 * paused, it will go to that offset immediately, otherwise the source will
1100 * start at the specified offset the next time it's played.
1102 void setOffset(uint64_t offset);
1104 * Retrieves the source offset in sample frames and its latency in nano-
1105 * seconds. For streaming sources this will be the offset based on the
1106 * decoder's read position.
1108 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1109 * be 0.
1111 std::pair<uint64_t,std::chrono::nanoseconds> getSampleOffsetLatency() const;
1112 uint64_t getSampleOffset() const { return std::get<0>(getSampleOffsetLatency()); }
1114 * Retrieves the source offset and latency in seconds. For streaming
1115 * sources this will be the offset based on the decoder's read position.
1117 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1118 * be 0.
1120 std::pair<Seconds,Seconds> getSecOffsetLatency() const;
1121 Seconds getSecOffset() const { return std::get<0>(getSecOffsetLatency()); }
1124 * Specifies if the source should loop on the Buffer or Decoder object's
1125 * loop points.
1127 void setLooping(bool looping);
1128 bool getLooping() const;
1131 * Specifies a linear pitch shift base. A value of 1.0 is the default
1132 * normal speed.
1134 void setPitch(ALfloat pitch);
1135 ALfloat getPitch() const;
1138 * Specifies the base linear gain. A value of 1.0 is the default normal
1139 * volume.
1141 void setGain(ALfloat gain);
1142 ALfloat getGain() const;
1145 * Specifies the minimum and maximum gain. The source's gain is clamped to
1146 * this range after distance attenuation and cone attenuation are applied
1147 * to the gain base, although before the filter gain adjustements.
1149 void setGainRange(ALfloat mingain, ALfloat maxgain);
1150 std::pair<ALfloat,ALfloat> getGainRange() const;
1151 ALfloat getMinGain() const { return std::get<0>(getGainRange()); }
1152 ALfloat getMaxGain() const { return std::get<1>(getGainRange()); }
1155 * Specifies the reference distance and maximum distance the source will
1156 * use for the current distance model. For Clamped distance models, the
1157 * source's calculated distance is clamped to the specified range before
1158 * applying distance-related attenuation.
1160 * For all distance models, the reference distance is the distance at which
1161 * the source's volume will not have any extra attenuation (an effective
1162 * gain multiplier of 1).
1164 void setDistanceRange(ALfloat refdist, ALfloat maxdist);
1165 std::pair<ALfloat,ALfloat> getDistanceRange() const;
1166 ALfloat getReferenceDistance() const { return std::get<0>(getDistanceRange()); }
1167 ALfloat getMaxDistance() const { return std::get<1>(getDistanceRange()); }
1169 /** Specifies the source's 3D position, velocity, and direction together. */
1170 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const Vector3 &direction);
1172 /** Specifies the source's 3D position, velocity, and orientation together. */
1173 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const std::pair<Vector3,Vector3> &orientation);
1175 /** Specifies the source's 3D position. */
1176 void setPosition(ALfloat x, ALfloat y, ALfloat z);
1177 void setPosition(const ALfloat *pos);
1178 Vector3 getPosition() const;
1181 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
1182 * this does not actually alter the source's position, and instead just
1183 * alters the pitch as determined by the doppler effect.
1185 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
1186 void setVelocity(const ALfloat *vel);
1187 Vector3 getVelocity() const;
1190 * Specifies the source's 3D facing direction. Deprecated in favor of
1191 * setOrientation.
1193 void setDirection(ALfloat x, ALfloat y, ALfloat z);
1194 void setDirection(const ALfloat *dir);
1195 Vector3 getDirection() const;
1198 * Specifies the source's 3D orientation. Note: unlike the AL_EXT_BFORMAT
1199 * extension this property comes from, this also affects the facing
1200 * direction, superceding setDirection.
1202 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
1203 void setOrientation(const ALfloat *at, const ALfloat *up);
1204 void setOrientation(const ALfloat *ori);
1205 std::pair<Vector3,Vector3> getOrientation() const;
1208 * Specifies the source's cone angles, in degrees. The inner angle is the
1209 * area within which the listener will hear the source with no extra
1210 * attenuation, while the listener being outside of the outer angle will
1211 * hear the source attenuated according to the outer cone gains.
1213 void setConeAngles(ALfloat inner, ALfloat outer);
1214 std::pair<ALfloat,ALfloat> getConeAngles() const;
1215 ALfloat getInnerConeAngle() const { return std::get<0>(getConeAngles()); }
1216 ALfloat getOuterConeAngle() const { return std::get<1>(getConeAngles()); }
1219 * Specifies the linear gain multiplier when the listener is outside of the
1220 * source's outer cone area. The specified gain applies to all frequencies,
1221 * while gainhf applies extra attenuation to high frequencies.
1223 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1225 void setOuterConeGains(ALfloat gain, ALfloat gainhf=1.0f);
1226 std::pair<ALfloat,ALfloat> getOuterConeGains() const;
1227 ALfloat getOuterConeGain() const { return std::get<0>(getOuterConeGains()); }
1228 ALfloat getOuterConeGainHF() const { return std::get<1>(getOuterConeGains()); }
1231 * Specifies the rolloff factors for the direct and send paths. This is
1232 * effectively a distance scaling relative to the reference distance. Note:
1233 * the room rolloff factor is 0 by default, disabling distance attenuation
1234 * for send paths. This is because the reverb engine will, by default,
1235 * apply a more realistic room decay based on the reverb decay time and
1236 * distance.
1238 void setRolloffFactors(ALfloat factor, ALfloat roomfactor=0.0f);
1239 std::pair<ALfloat,ALfloat> getRolloffFactors() const;
1240 ALfloat getRolloffFactor() const { return std::get<0>(getRolloffFactors()); }
1241 ALfloat getRoomRolloffFactor() const { return std::get<1>(getRolloffFactors()); }
1244 * Specifies the doppler factor for the doppler effect's pitch shift. This
1245 * effectively scales the source and listener velocities for the doppler
1246 * calculation.
1248 void setDopplerFactor(ALfloat factor);
1249 ALfloat getDopplerFactor() const;
1252 * Specifies if the source's position, velocity, and direction/orientation
1253 * are relative to the listener.
1255 void setRelative(bool relative);
1256 bool getRelative() const;
1259 * Specifies the source's radius. This causes the source to behave as if
1260 * every point within the spherical area emits sound.
1262 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1264 void setRadius(ALfloat radius);
1265 ALfloat getRadius() const;
1268 * Specifies the left and right channel angles, in radians, when playing a
1269 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1270 * in front and positive values going left.
1272 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1274 void setStereoAngles(ALfloat leftAngle, ALfloat rightAngle);
1275 std::pair<ALfloat,ALfloat> getStereoAngles() const;
1278 * Specifies if the source always has 3D spatialization features (On),
1279 * never has 3D spatialization features (Off), or if spatialization is
1280 * enabled based on playing a mono sound or not (Auto, default).
1282 * Has no effect without the AL_SOFT_source_spatialize extension.
1284 void set3DSpatialize(Spatialize spatialize);
1285 Spatialize get3DSpatialize() const;
1288 * Specifies the index of the resampler to use for this source. The index
1289 * is from the resamplers returned by \c Context::getAvailableResamplers,
1290 * and must be 0 or greater.
1292 * Has no effect without the AL_SOFT_source_resampler extension.
1294 void setResamplerIndex(ALsizei index);
1295 ALsizei getResamplerIndex() const;
1298 * Specifies a multiplier for the amount of atmospheric high-frequency
1299 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1300 * -0.05dB per meter, with higher values simulating foggy air and lower
1301 * values simulating dryer air. The default is 0.
1303 void setAirAbsorptionFactor(ALfloat factor);
1304 ALfloat getAirAbsorptionFactor() const;
1306 void setGainAuto(bool directhf, bool send, bool sendhf);
1307 std::tuple<bool,bool,bool> getGainAuto() const;
1308 bool getDirectGainHFAuto() const { return std::get<0>(getGainAuto()); }
1309 bool getSendGainAuto() const { return std::get<1>(getGainAuto()); }
1310 bool getSendGainHFAuto() const { return std::get<2>(getGainAuto()); }
1312 /** Sets the filter properties on the direct path signal. */
1313 void setDirectFilter(const FilterParams &filter);
1315 * Sets the filter properties on the given send path signal. Any auxiliary
1316 * effect slot on the send path remains in place.
1318 void setSendFilter(ALuint send, const FilterParams &filter);
1320 * Connects the effect slot to the given send path. Any filter properties
1321 * on the send path remain as they were.
1323 void setAuxiliarySend(AuxiliaryEffectSlot slot, ALuint send);
1325 * Connects the effect slot to the given send path, using the filter
1326 * properties.
1328 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot, ALuint send, const FilterParams &filter);
1331 * Releases the source, stopping playback, releasing resources, and
1332 * returning it to the system.
1334 void release();
1338 class ALURE_API SourceGroup {
1339 MAKE_PIMPL(SourceGroup, SourceGroupImpl)
1341 public:
1342 /** Retrieves the associated name of the source group. */
1343 StringView getName() const;
1346 * Adds this source group as a subgroup of the specified source group. This
1347 * method will throw an exception if this group is being added to a group
1348 * it has as a sub-group (i.e. it would create a circular sub-group chain).
1350 void setParentGroup(SourceGroup group);
1352 /** Retrieves the source group this source group is a child of. */
1353 SourceGroup getParentGroup() const;
1355 /** Returns the list of sources currently in the group. */
1356 Vector<Source> getSources() const;
1358 /** Returns the list of subgroups currently in the group. */
1359 Vector<SourceGroup> getSubGroups() const;
1362 * Sets the source group gain, which accumulates with its sources' and
1363 * sub-groups' gain.
1365 void setGain(ALfloat gain);
1366 /** Gets the source group gain. */
1367 ALfloat getGain() const;
1370 * Sets the source group pitch, which accumulates with its sources' and
1371 * sub-groups' pitch.
1373 void setPitch(ALfloat pitch);
1374 /** Gets the source group pitch. */
1375 ALfloat getPitch() const;
1378 * Pauses all currently-playing sources that are under this group,
1379 * including sub-groups.
1381 void pauseAll() const;
1383 * Resumes all paused sources that are under this group, including
1384 * sub-groups.
1386 void resumeAll() const;
1388 /** Stops all sources that are under this group, including sub-groups. */
1389 void stopAll() const;
1392 * Releases the source group, removing all sources from it before being
1393 * freed.
1395 void release();
1399 struct SourceSend {
1400 Source mSource;
1401 ALuint mSend;
1404 class ALURE_API AuxiliaryEffectSlot {
1405 MAKE_PIMPL(AuxiliaryEffectSlot, AuxiliaryEffectSlotImpl)
1407 public:
1408 void setGain(ALfloat gain);
1410 * If set to true, the reverb effect will automatically apply adjustments
1411 * to the source's send slot gains based on the effect properties.
1413 * Has no effect when using non-reverb effects. Default is true.
1415 void setSendAuto(bool sendauto);
1418 * Updates the effect slot with a new effect. The given effect object may
1419 * be altered or destroyed without affecting the effect slot.
1421 void applyEffect(Effect effect);
1424 * Releases the effect slot, returning it to the system. It must not be in
1425 * use by a source.
1427 void release();
1430 * Retrieves each Source object and its pairing send this effect slot is
1431 * set on. Setting a different (or null) effect slot on each source's given
1432 * send will allow the effect slot to be released.
1434 Vector<SourceSend> getSourceSends() const;
1436 /** Determines if the effect slot is in use by a source. */
1437 bool isInUse() const;
1441 class ALURE_API Effect {
1442 MAKE_PIMPL(Effect, EffectImpl)
1444 public:
1446 * Updates the effect with the specified reverb properties. If the
1447 * EAXReverb effect is not supported, it will automatically attempt to
1448 * downgrade to the Standard Reverb effect.
1450 void setReverbProperties(const EFXEAXREVERBPROPERTIES &props);
1452 void destroy();
1457 * Audio decoder interface. Applications may derive from this, implementing the
1458 * necessary methods, and use it in places the API wants a Decoder object.
1460 class ALURE_API Decoder {
1461 public:
1462 virtual ~Decoder();
1464 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1465 virtual ALuint getFrequency() const = 0;
1466 /** Retrieves the channel configuration of the audio being decoded. */
1467 virtual ChannelConfig getChannelConfig() const = 0;
1468 /** Retrieves the sample type of the audio being decoded. */
1469 virtual SampleType getSampleType() const = 0;
1472 * Retrieves the total length of the audio, in sample frames. If unknown,
1473 * returns 0. Note that if the returned length is 0, the decoder may not be
1474 * used to load a Buffer.
1476 virtual uint64_t getLength() const = 0;
1478 * Seek to pos, specified in sample frames. Returns true if the seek was
1479 * successful.
1481 virtual bool seek(uint64_t pos) = 0;
1484 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1485 * start >= end, use all available data.
1487 virtual std::pair<uint64_t,uint64_t> getLoopPoints() const = 0;
1490 * Decodes count sample frames, writing them to ptr, and returns the number
1491 * of sample frames written. Returning less than the requested count
1492 * indicates the end of the audio.
1494 virtual ALuint read(ALvoid *ptr, ALuint count) = 0;
1498 * Audio decoder factory interface. Applications may derive from this,
1499 * implementing the necessary methods, and use it in places the API wants a
1500 * DecoderFactory object.
1502 class ALURE_API DecoderFactory {
1503 public:
1504 virtual ~DecoderFactory();
1507 * Creates and returns a Decoder instance for the given resource file. If
1508 * the decoder needs to retain the file handle for reading as-needed, it
1509 * should move the UniquePtr to internal storage.
1511 * \return nullptr if a decoder can't be created from the file.
1513 virtual SharedPtr<Decoder> createDecoder(UniquePtr<std::istream> &file) = 0;
1517 * Registers a decoder factory for decoding audio. Registered factories are
1518 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1519 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1520 * name1 < name2. Internal decoder factories are always used after registered
1521 * ones.
1523 * Alure retains a reference to the DecoderFactory instance and will release it
1524 * (destructing the object) when the library unloads.
1526 * \param name A unique name identifying this decoder factory.
1527 * \param factory A DecoderFactory instance used to create Decoder instances.
1529 ALURE_API void RegisterDecoder(StringView name, UniquePtr<DecoderFactory> factory);
1532 * Unregisters a decoder factory by name. Alure returns the instance back to
1533 * the application.
1535 * \param name The unique name identifying a previously-registered decoder
1536 * factory.
1538 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1539 * decoder factory with the given name doesn't exist.
1541 ALURE_API UniquePtr<DecoderFactory> UnregisterDecoder(StringView name);
1545 * A file I/O factory interface. Applications may derive from this and set an
1546 * instance to be used by the audio decoders. By default, the library uses
1547 * standard I/O.
1549 class ALURE_API FileIOFactory {
1550 public:
1552 * Sets the factory instance to be used by the audio decoders. If a
1553 * previous factory was set, it's returned to the application. Passing in a
1554 * nullptr reverts to the default.
1556 static UniquePtr<FileIOFactory> set(UniquePtr<FileIOFactory> factory);
1559 * Gets the current FileIOFactory instance being used by the audio
1560 * decoders.
1562 static FileIOFactory &get();
1564 virtual ~FileIOFactory();
1566 /** Opens a read-only binary file for the given name. */
1567 virtual UniquePtr<std::istream> openFile(const String &name) = 0;
1572 * A message handler interface. Applications may derive from this and set an
1573 * instance on a context to receive messages. The base methods are no-ops, so
1574 * derived classes only need to implement methods for relevant messages.
1576 * It's recommended that applications mark their handler methods using the
1577 * override keyword, to ensure they're properly overriding the base methods in
1578 * case they change.
1580 class ALURE_API MessageHandler {
1581 public:
1582 virtual ~MessageHandler();
1585 * Called when the given device has been disconnected and is no longer
1586 * usable for output. As per the ALC_EXT_disconnect specification,
1587 * disconnected devices remain valid, however all playing sources are
1588 * automatically stopped, any sources that are attempted to play will
1589 * immediately stop, and new contexts may not be created on the device.
1591 * Note that connection status is checked during Context::update calls, so
1592 * that method must be called regularly to be notified when a device is
1593 * disconnected. This method may not be called if the device lacks support
1594 * for the ALC_EXT_disconnect extension.
1596 virtual void deviceDisconnected(Device device);
1599 * Called when the given source reaches the end of the buffer or stream.
1601 * Sources that stopped automatically will be detected upon a call to
1602 * Context::update.
1604 virtual void sourceStopped(Source source);
1607 * Called when the given source was forced to stop. This can be because
1608 * either there were no more system sources and a higher-priority source
1609 * preempted it, or it's part of a SourceGroup (or sub-group thereof) that
1610 * had its SourceGroup::stopAll method called.
1612 virtual void sourceForceStopped(Source source);
1615 * Called when a new buffer is about to be created and loaded. May be
1616 * called asynchronously for buffers being loaded asynchronously.
1618 * \param name The resource name, as passed to Context::getBuffer.
1619 * \param channels Channel configuration of the given audio data.
1620 * \param type Sample type of the given audio data.
1621 * \param samplerate Sample rate of the given audio data.
1622 * \param data The audio data that is about to be fed to the OpenAL buffer.
1624 virtual void bufferLoading(StringView name, ChannelConfig channels, SampleType type, ALuint samplerate, ArrayView<ALbyte> data);
1627 * Called when a resource isn't found, allowing the app to substitute in a
1628 * different resource. For buffers created with Context::getBuffer or
1629 * Context::getBufferAsync, the original name will still be used for the
1630 * cache map so the app doesn't have to keep track of substituted resource
1631 * names.
1633 * This will be called again if the new name isn't found.
1635 * \param name The resource name that was not found.
1636 * \return The replacement resource name to use instead. Returning an empty
1637 * string means to stop trying.
1639 virtual String resourceNotFound(StringView name);
1642 #undef MAKE_PIMPL
1644 } // namespace alure
1646 #endif /* AL_ALURE2_H */