Add a method to play a source with a SharedFuture buffer
[alure.git] / include / AL / alure2.h
blob346a4ccb40910675730a52ef74bf102cb6c957e0
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"
17 #ifndef ALURE_API
18 #if defined(ALURE_STATIC_LIB)
19 #define ALURE_API
20 #elif defined(_WIN32)
21 #define ALURE_API __declspec(dllimport)
22 #elif defined(__GNUC__) || (defined(__has_attribute) && __has_attribute(visibility))
23 #define ALURE_API __attribute__((visibility("default")))
24 #else
25 #define ALURE_API
26 #endif
27 #endif /* ALURE_API */
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 DeviceManagerImpl;
62 class Device;
63 class DeviceImpl;
64 class Context;
65 class ContextImpl;
66 class Listener;
67 class ListenerImpl;
68 class Buffer;
69 class BufferImpl;
70 class Source;
71 class SourceImpl;
72 class SourceGroup;
73 class SourceGroupImpl;
74 class AuxiliaryEffectSlot;
75 class AuxiliaryEffectSlotImpl;
76 class Effect;
77 class EffectImpl;
78 class Decoder;
79 class DecoderFactory;
80 class MessageHandler;
82 // Convenience aliases
83 template<typename T> using RemoveRefT = typename std::remove_reference<T>::type;
84 template<bool B> using EnableIfT = typename std::enable_if<B>::type;
87 // Duration in seconds, using double precision
88 using Seconds = std::chrono::duration<double>;
90 // A SharedPtr implementation, defaults to C++11's std::shared_ptr. If this is
91 // changed, you must recompile the library.
92 template<typename... Args> using SharedPtr = std::shared_ptr<Args...>;
93 template<typename T, typename... Args>
94 constexpr inline SharedPtr<T> MakeShared(Args&&... args)
96 return std::make_shared<T>(std::forward<Args>(args)...);
99 // A UniquePtr implementation, defaults to C++11's std::unique_ptr. If this is
100 // changed, you must recompile the library.
101 template<typename... Args> using UniquePtr = std::unique_ptr<Args...>;
102 template<typename T, typename... Args>
103 constexpr inline UniquePtr<T> MakeUnique(Args&&... args)
105 #if __cplusplus >= 201402L
106 return std::make_unique<T>(std::forward<Args>(args)...);
107 #else
108 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
109 #endif
112 // A Promise/Future (+SharedFuture) implementation, defaults to C++11's
113 // std::promise, std::future, and std::shared_future. If this is changed, you
114 // must recompile the library.
115 template<typename... Args> using Promise = std::promise<Args...>;
116 template<typename... Args> using Future = std::future<Args...>;
117 template<typename... Args> using SharedFuture = std::shared_future<Args...>;
119 // A Vector implementation, defaults to C++'s std::vector. If this is changed,
120 // you must recompile the library.
121 template<typename... Args> using Vector = std::vector<Args...>;
123 // A static-sized Array implementation, defaults to C++11's std::array. If this
124 // is changed, you must recompile the library.
125 template<typename T, std::size_t N> using Array = std::array<T, N>;
127 // A String implementation, default's to C++'s std::string. If this is changed,
128 // you must recompile the library.
129 template<typename... Args> using BasicString = std::basic_string<Args...>;
130 using String = BasicString<std::string::value_type>;
132 // Tag specific containers that guarantee contiguous storage. The standard
133 // provides no such mechanism, so we have to manually specify which are
134 // acceptable.
135 template<typename T> struct IsContiguousTag : std::false_type {};
136 template<typename T, size_t N> struct IsContiguousTag<Array<T,N>> : std::true_type {};
137 template<typename T> struct IsContiguousTag<Vector<T>> : std::true_type {};
138 template<typename T> struct IsContiguousTag<BasicString<T>> : std::true_type {};
140 // A rather simple ArrayView container. This allows accepting various array
141 // types (Array, Vector, a static-sized array, a dynamic array + size) without
142 // copying its elements.
143 template<typename T>
144 class ArrayView {
145 public:
146 using value_type = T;
148 using iterator = const value_type*;
149 using const_iterator = const value_type*;
151 using size_type = size_t;
153 static constexpr size_type npos = static_cast<size_type>(-1);
155 private:
156 const value_type *mElems;
157 size_t mNumElems;
159 public:
160 ArrayView() noexcept : mElems(nullptr), mNumElems(0) { }
161 ArrayView(const ArrayView&) noexcept = default;
162 ArrayView(ArrayView&&) noexcept = default;
163 ArrayView(const value_type *elems, size_type num_elems) noexcept
164 : mElems(elems), mNumElems(num_elems) { }
165 template<typename OtherT> ArrayView(RemoveRefT<OtherT>&&) = delete;
166 template<typename OtherT,
167 typename = EnableIfT<IsContiguousTag<RemoveRefT<OtherT>>::value>>
168 ArrayView(const OtherT &rhs) noexcept : mElems(rhs.data()), mNumElems(rhs.size()) { }
169 template<size_t N>
170 ArrayView(const value_type (&elems)[N]) noexcept : mElems(elems), mNumElems(N) { }
172 ArrayView& operator=(const ArrayView&) noexcept = default;
174 const value_type *data() const noexcept { return mElems; }
176 size_type size() const noexcept { return mNumElems; }
177 bool empty() const noexcept { return mNumElems == 0; }
179 const value_type& operator[](size_t i) const { return mElems[i]; }
181 const value_type& front() const { return mElems[0]; }
182 const value_type& back() const { return mElems[mNumElems-1]; }
184 const value_type& at(size_t i) const
186 if(i >= mNumElems)
187 throw std::out_of_range("alure::ArrayView::at: element out of range");
188 return mElems[i];
191 const_iterator begin() const noexcept { return mElems; }
192 const_iterator cbegin() const noexcept { return mElems; }
194 const_iterator end() const noexcept { return mElems + mNumElems; }
195 const_iterator cend() const noexcept { return mElems + mNumElems; }
197 ArrayView slice(size_type pos, size_type len = npos) const noexcept
199 if(pos >= size())
200 return ArrayView(data()+size(), 0);
201 if(len == npos || size()-pos >= len)
202 return ArrayView(data()+pos, size()-pos);
203 return ArrayView(data()+pos, len);
207 template<typename T, typename Tr=std::char_traits<T>>
208 class BasicStringView : public ArrayView<T> {
209 using BaseT = ArrayView<T>;
210 using StringT = BasicString<T,Tr>;
212 public:
213 using typename BaseT::value_type;
214 using typename BaseT::size_type;
215 using BaseT::npos;
216 using traits_type = Tr;
218 BasicStringView() noexcept = default;
219 BasicStringView(const BasicStringView&) noexcept = default;
220 BasicStringView(const value_type *elems, size_type num_elems) noexcept
221 : ArrayView<T>(elems, num_elems) { }
222 BasicStringView(const value_type *elems) : ArrayView<T>(elems, std::strlen(elems)) { }
223 BasicStringView(StringT&&) = delete;
224 BasicStringView(const StringT &rhs) noexcept : ArrayView<T>(rhs) { }
225 #if __cplusplus >= 201703L
226 BasicStringView(const std::basic_string_view<T> &rhs) noexcept
227 : ArrayView<T>(rhs.data(), rhs.length()) { }
228 #endif
230 BasicStringView& operator=(const BasicStringView&) noexcept = default;
232 size_type length() const { return BaseT::size(); }
234 explicit operator StringT() const { return StringT(BaseT::data(), length()); }
235 #if __cplusplus >= 201703L
236 operator std::basic_string_view<T,Tr>() const noexcept
237 { return std::basic_string_view<T,Tr>(BaseT::data(), length()); }
238 #endif
240 StringT operator+(const StringT &rhs) const
242 StringT ret = StringT(*this);
243 ret += rhs;
244 return ret;
246 StringT operator+(const typename StringT::value_type *rhs) const
248 StringT ret = StringT(*this);
249 ret += rhs;
250 return ret;
253 int compare(BasicStringView other) const noexcept
255 int ret = traits_type::compare(
256 BaseT::data(), other.data(), std::min<size_t>(length(), other.length())
258 if(ret == 0)
260 if(length() > other.length()) return 1;
261 if(length() < other.length()) return -1;
262 return 0;
264 return ret;
266 bool operator==(BasicStringView rhs) const noexcept { return compare(rhs) == 0; }
267 bool operator!=(BasicStringView rhs) const noexcept { return compare(rhs) != 0; }
268 bool operator<=(BasicStringView rhs) const noexcept { return compare(rhs) <= 0; }
269 bool operator>=(BasicStringView rhs) const noexcept { return compare(rhs) >= 0; }
270 bool operator<(BasicStringView rhs) const noexcept { return compare(rhs) < 0; }
271 bool operator>(BasicStringView rhs) const noexcept { return compare(rhs) > 0; }
273 BasicStringView substr(size_type pos, size_type len = npos) const noexcept
274 { return BaseT::slice(pos, len); }
276 using StringView = BasicStringView<String::value_type>;
278 // Inline operators to concat String and C-style strings with StringViews.
279 template<typename T, typename Tr>
280 inline BasicString<T,Tr> operator+(const BasicString<T,Tr> &lhs, BasicStringView<T,Tr> rhs)
281 { return BasicString<T,Tr>(lhs).append(rhs.data(), rhs.size()); }
282 template<typename T, typename Tr>
283 inline BasicString<T,Tr> operator+(BasicString<T,Tr> lhs, BasicStringView<T,Tr> rhs)
284 { return std::move(lhs.append(rhs.data(), rhs.size())); }
285 template<typename T, typename Tr>
286 inline BasicString<T,Tr> operator+(const typename BasicString<T,Tr>::value_type *lhs, BasicStringView<T,Tr> rhs)
287 { return lhs + BasicString<T,Tr>(rhs); }
288 template<typename T, typename Tr>
289 inline BasicString<T,Tr>& operator+=(BasicString<T,Tr> &lhs, BasicStringView<T,Tr> rhs)
290 { return lhs.append(rhs.data(), rhs.size()); }
292 // Inline operators to compare String and C-style strings with StringViews.
293 #define ALURE_DECL_STROP(op) \
294 template<typename T, typename Tr> \
295 inline bool operator op(const BasicString<T,Tr> &lhs, BasicStringView<T,Tr> rhs) \
296 { return BasicStringView<T,Tr>(lhs) op rhs; } \
297 template<typename T, typename Tr> \
298 inline bool operator op(const typename BasicString<T,Tr>::value_type *lhs, \
299 BasicStringView<T,Tr> rhs) \
300 { return BasicStringView<T,Tr>(lhs) op rhs; }
301 ALURE_DECL_STROP(==)
302 ALURE_DECL_STROP(!=)
303 ALURE_DECL_STROP(<=)
304 ALURE_DECL_STROP(>=)
305 ALURE_DECL_STROP(<)
306 ALURE_DECL_STROP(>)
307 #undef ALURE_DECL_STROP
309 // Inline operator to write out a StringView to an ostream
310 template<typename T, typename Tr>
311 inline std::basic_ostream<T>& operator<<(std::basic_ostream<T,Tr> &lhs, BasicStringView<T,Tr> rhs)
313 for(auto ch : rhs)
314 lhs << ch;
315 return lhs;
319 /** Convert a value from decibels to linear gain. */
320 template<typename T, typename NonRefT=RemoveRefT<T>,
321 typename=EnableIfT<std::is_floating_point<NonRefT>::value>>
322 constexpr inline NonRefT dBToLinear(T&& value)
323 { return std::pow(NonRefT(10.0), std::forward<T&&>(value) / NonRefT(20.0)); }
325 /** Convert a value from linear gain to decibels. */
326 template<typename T, typename NonRefT=RemoveRefT<T>,
327 typename=EnableIfT<std::is_floating_point<NonRefT>::value>>
328 constexpr inline NonRefT LinearTodB(T&& value)
329 { return std::log10(std::forward<T&&>(value)) * NonRefT(20.0); }
332 * An attribute pair, for passing attributes to Device::createContext and
333 * Device::reset.
335 using AttributePair = std::pair<ALCint,ALCint>;
336 static_assert(sizeof(AttributePair) == sizeof(ALCint[2]), "Bad AttributePair size");
337 constexpr AttributePair AttributesEnd{0, 0};
340 struct FilterParams {
341 ALfloat mGain;
342 ALfloat mGainHF; // For low-pass and band-pass filters
343 ALfloat mGainLF; // For high-pass and band-pass filters
347 class Vector3 {
348 Array<ALfloat,3> mValue;
350 public:
351 constexpr Vector3() noexcept
352 : mValue{{0.0f, 0.0f, 0.0f}}
354 constexpr Vector3(const Vector3 &rhs) noexcept
355 : mValue{{rhs.mValue[0], rhs.mValue[1], rhs.mValue[2]}}
357 constexpr Vector3(ALfloat val) noexcept
358 : mValue{{val, val, val}}
360 constexpr Vector3(ALfloat x, ALfloat y, ALfloat z) noexcept
361 : mValue{{x, y, z}}
363 Vector3(const ALfloat *vec) noexcept
364 : mValue{{vec[0], vec[1], vec[2]}}
367 const ALfloat *getPtr() const noexcept
368 { return mValue.data(); }
370 ALfloat& operator[](size_t i) noexcept
371 { return mValue[i]; }
372 constexpr const ALfloat& operator[](size_t i) const noexcept
373 { return mValue[i]; }
375 #define ALURE_DECL_OP(op) \
376 constexpr Vector3 operator op(const Vector3 &rhs) const noexcept \
378 return Vector3(mValue[0] op rhs.mValue[0], \
379 mValue[1] op rhs.mValue[1], \
380 mValue[2] op rhs.mValue[2]); \
382 ALURE_DECL_OP(+)
383 ALURE_DECL_OP(-)
384 ALURE_DECL_OP(*)
385 ALURE_DECL_OP(/)
386 #undef ALURE_DECL_OP
387 #define ALURE_DECL_OP(op) \
388 Vector3& operator op(const Vector3 &rhs) noexcept \
390 mValue[0] op rhs.mValue[0]; \
391 mValue[1] op rhs.mValue[1]; \
392 mValue[2] op rhs.mValue[2]; \
393 return *this; \
395 ALURE_DECL_OP(+=)
396 ALURE_DECL_OP(-=)
397 ALURE_DECL_OP(*=)
398 ALURE_DECL_OP(/=)
400 #undef ALURE_DECL_OP
401 #define ALURE_DECL_OP(op) \
402 constexpr Vector3 operator op(ALfloat scale) const noexcept \
404 return Vector3(mValue[0] op scale, \
405 mValue[1] op scale, \
406 mValue[2] op scale); \
408 ALURE_DECL_OP(*)
409 ALURE_DECL_OP(/)
410 #undef ALURE_DECL_OP
411 #define ALURE_DECL_OP(op) \
412 Vector3& operator op(ALfloat scale) noexcept \
414 mValue[0] op scale; \
415 mValue[1] op scale; \
416 mValue[2] op scale; \
417 return *this; \
419 ALURE_DECL_OP(*=)
420 ALURE_DECL_OP(/=)
421 #undef ALURE_DECL_OP
423 constexpr ALfloat getLengthSquared() const noexcept
424 { return mValue[0]*mValue[0] + mValue[1]*mValue[1] + mValue[2]*mValue[2]; }
425 ALfloat getLength() const noexcept
426 { return std::sqrt(getLengthSquared()); }
428 constexpr ALfloat getDistanceSquared(const Vector3 &pos) const noexcept
429 { return (pos - *this).getLengthSquared(); }
430 ALfloat getDistance(const Vector3 &pos) const noexcept
431 { return (pos - *this).getLength(); }
433 static_assert(sizeof(Vector3) == sizeof(ALfloat[3]), "Bad Vector3 size");
436 enum class SampleType {
437 UInt8,
438 Int16,
439 Float32,
440 Mulaw
442 ALURE_API const char *GetSampleTypeName(SampleType type);
444 enum class ChannelConfig {
445 /** 1-channel mono sound. */
446 Mono,
447 /** 2-channel stereo sound. */
448 Stereo,
449 /** 2-channel rear sound (back-left and back-right). */
450 Rear,
451 /** 4-channel surround sound. */
452 Quad,
453 /** 5.1 surround sound. */
454 X51,
455 /** 6.1 surround sound. */
456 X61,
457 /** 7.1 surround sound. */
458 X71,
459 /** 3-channel B-Format, using FuMa channel ordering and scaling. */
460 BFormat2D,
461 /** 4-channel B-Format, using FuMa channel ordering and scaling. */
462 BFormat3D
464 ALURE_API const char *GetChannelConfigName(ChannelConfig cfg);
466 ALURE_API ALuint FramesToBytes(ALuint frames, ChannelConfig chans, SampleType type);
467 ALURE_API ALuint BytesToFrames(ALuint bytes, ChannelConfig chans, SampleType type);
470 /** Class for storing a major.minor version number. */
471 class Version {
472 ALuint mMajor : 16;
473 ALuint mMinor : 16;
475 public:
476 constexpr Version(ALuint _maj, ALuint _min) : mMajor(_maj), mMinor(_min) { }
478 constexpr ALuint getMajor() const noexcept { return mMajor; }
479 constexpr ALuint getMinor() const noexcept { return mMinor; }
480 constexpr bool isZero() const noexcept { return mMajor == 0 && mMinor == 0; }
483 #define MAKE_PIMPL(BaseT, ImplT) \
484 private: \
485 ImplT *pImpl; \
487 public: \
488 using handle_type = ImplT*; \
490 BaseT() : pImpl(nullptr) { } \
491 BaseT(ImplT *impl) : pImpl(impl) { } \
492 BaseT(const BaseT&) = default; \
493 BaseT(BaseT&& rhs) : pImpl(rhs.pImpl) { rhs.pImpl = nullptr; } \
495 BaseT& operator=(const BaseT&) = default; \
496 BaseT& operator=(BaseT&& rhs) \
498 pImpl = rhs.pImpl; rhs.pImpl = nullptr; \
499 return *this; \
502 bool operator==(const BaseT &rhs) const { return pImpl == rhs.pImpl; } \
503 bool operator==(BaseT&& rhs) const { return pImpl == rhs.pImpl; } \
505 operator bool() const { return !!pImpl; } \
507 handle_type getHandle() const { return pImpl; }
509 enum class DeviceEnumeration {
510 Basic = ALC_DEVICE_SPECIFIER,
511 Full = ALC_ALL_DEVICES_SPECIFIER,
512 Capture = ALC_CAPTURE_DEVICE_SPECIFIER
515 enum class DefaultDeviceType {
516 Basic = ALC_DEFAULT_DEVICE_SPECIFIER,
517 Full = ALC_DEFAULT_ALL_DEVICES_SPECIFIER,
518 Capture = ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
522 * A class managing Device objects and other related functionality. This class
523 * is a singleton, only one instance will exist in a process.
525 class ALURE_API DeviceManager {
526 DeviceManagerImpl *pImpl;
528 DeviceManager(DeviceManagerImpl *impl) : pImpl(impl) { }
529 friend class ALDeviceManager;
531 public:
532 DeviceManager(const DeviceManager&) = default;
533 DeviceManager(DeviceManager&& rhs) : pImpl(rhs.pImpl) { }
535 /** Retrieves the DeviceManager instance. */
536 static DeviceManager get();
538 /** Queries the existence of a non-device-specific ALC extension. */
539 bool queryExtension(const String &name) const;
540 bool queryExtension(const char *name) const;
542 /** Enumerates available device names of the given type. */
543 Vector<String> enumerate(DeviceEnumeration type) const;
544 /** Retrieves the default device of the given type. */
545 String defaultDeviceName(DefaultDeviceType type) const;
548 * Opens the playback device given by name, or the default if blank. Throws
549 * an exception on error.
551 Device openPlayback(const String &name=String());
552 Device openPlayback(const char *name);
555 * Opens the playback device given by name, or the default if blank.
556 * Returns an empty Device on error.
558 Device openPlayback(const String &name, const std::nothrow_t&);
559 Device openPlayback(const char *name, const std::nothrow_t&);
561 /** Opens the default playback device. Returns an empty Device on error. */
562 Device openPlayback(const std::nothrow_t&);
566 enum class PlaybackName {
567 Basic = ALC_DEVICE_SPECIFIER,
568 Full = ALC_ALL_DEVICES_SPECIFIER
571 class ALURE_API Device {
572 MAKE_PIMPL(Device, DeviceImpl)
574 public:
575 /** Retrieves the device name as given by type. */
576 String getName(PlaybackName type=PlaybackName::Full) const;
577 /** Queries the existence of an ALC extension on this device. */
578 bool queryExtension(const String &name) const;
579 bool queryExtension(const char *name) const;
581 /** Retrieves the ALC version supported by this device. */
582 Version getALCVersion() const;
585 * Retrieves the EFX version supported by this device. If the ALC_EXT_EFX
586 * extension is unsupported, this will be 0.0.
588 Version getEFXVersion() const;
590 /** Retrieves the device's playback frequency, in hz. */
591 ALCuint getFrequency() const;
594 * Retrieves the maximum number of auxiliary source sends. If ALC_EXT_EFX
595 * is unsupported, this will be 0.
597 ALCuint getMaxAuxiliarySends() const;
600 * Enumerates available HRTF names. The names are sorted as OpenAL gives
601 * them, such that the index of a given name is the ID to use with
602 * ALC_HRTF_ID_SOFT.
604 * Requires the ALC_SOFT_HRTF extension.
606 Vector<String> enumerateHRTFNames() const;
609 * Retrieves whether HRTF is enabled on the device or not.
611 * Requires the ALC_SOFT_HRTF extension.
613 bool isHRTFEnabled() const;
616 * Retrieves the name of the HRTF currently being used by this device.
618 * Requires the ALC_SOFT_HRTF extension.
620 String getCurrentHRTF() const;
623 * Resets the device, using the specified attributes.
625 * Requires the ALC_SOFT_HRTF extension.
627 void reset(ArrayView<AttributePair> attributes);
630 * Creates a new Context on this device, using the specified attributes.
631 * Throws an exception if context creation fails.
633 Context createContext(ArrayView<AttributePair> attributes=ArrayView<AttributePair>());
635 * Creates a new Context on this device, using the specified attributes.
636 * Returns an empty Context if context creation fails.
638 Context createContext(ArrayView<AttributePair> attributes, const std::nothrow_t&);
639 Context createContext(const std::nothrow_t&);
642 * Pauses device processing, stopping updates for its contexts. Multiple
643 * calls are allowed but it is not reference counted, so the device will
644 * resume after one resumeDSP call.
646 * Requires the ALC_SOFT_pause_device extension.
648 void pauseDSP();
651 * Resumes device processing, restarting updates for its contexts. Multiple
652 * calls are allowed and will no-op.
654 void resumeDSP();
657 * Closes and frees the device. All previously-created contexts must first
658 * be destroyed.
660 void close();
664 enum class DistanceModel {
665 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
666 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
667 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
668 Inverse = AL_INVERSE_DISTANCE,
669 Linear = AL_LINEAR_DISTANCE,
670 Exponent = AL_EXPONENT_DISTANCE,
671 None = AL_NONE,
674 class ALURE_API Context {
675 MAKE_PIMPL(Context, ContextImpl)
677 public:
678 /** Makes the specified context current for OpenAL operations. */
679 static void MakeCurrent(Context context);
680 /** Retrieves the current context used for OpenAL operations. */
681 static Context GetCurrent();
684 * Makes the specified context current for OpenAL operations on the calling
685 * thread only. Requires the ALC_EXT_thread_local_context extension on both
686 * the context's device and the DeviceManager.
688 static void MakeThreadCurrent(Context context);
689 /** Retrieves the thread-specific context used for OpenAL operations. */
690 static Context GetThreadCurrent();
693 * Destroys the context. The context must not be current when this is
694 * called.
696 void destroy();
698 /** Retrieves the Device this context was created from. */
699 Device getDevice();
701 void startBatch();
702 void endBatch();
705 * Retrieves a Listener instance for this context. Each context will only
706 * have one listener, which is automatically destroyed with the context.
708 Listener getListener();
711 * Sets a MessageHandler instance which will be used to provide certain
712 * messages back to the application. Only one handler may be set for a
713 * context at a time. The previously set handler will be returned.
715 SharedPtr<MessageHandler> setMessageHandler(SharedPtr<MessageHandler> handler);
717 /** Gets the currently-set message handler. */
718 SharedPtr<MessageHandler> getMessageHandler() const;
721 * Specifies the desired interval that the background thread will be woken
722 * up to process tasks, e.g. keeping streaming sources filled. An interval
723 * of 0 means the background thread will only be woken up manually with
724 * calls to update. The default is 0.
726 void setAsyncWakeInterval(std::chrono::milliseconds interval);
729 * Retrieves the current interval used for waking up the background thread.
731 std::chrono::milliseconds getAsyncWakeInterval() const;
733 // Functions below require the context to be current
736 * Creates a Decoder instance for the given audio file or resource name.
738 SharedPtr<Decoder> createDecoder(StringView name);
741 * Queries if the channel configuration and sample type are supported by
742 * the context.
744 bool isSupported(ChannelConfig channels, SampleType type) const;
747 * Queries the list of resamplers supported by the context. If the
748 * AL_SOFT_source_resampler extension is unsupported this will be an empty
749 * array, otherwise there will be at least one entry.
751 ArrayView<String> getAvailableResamplers();
753 * Queries the context's default resampler index. Be aware, if the
754 * AL_SOFT_source_resampler extension is unsupported the resampler list
755 * will be empty and this will resturn 0. If you try to access the
756 * resampler list with this index without the extension, undefined behavior
757 * will occur (accessing an out of bounds array index).
759 ALsizei getDefaultResamplerIndex() const;
762 * Creates and caches a Buffer for the given audio file or resource name.
763 * Multiple calls with the same name will return the same Buffer object.
764 * Cached buffers must be freed using removeBuffer before destroying the
765 * context. If the buffer can't be loaded it will throw an exception.
767 Buffer getBuffer(StringView name);
770 * Asynchronously prepares a cached Buffer for the given audio file or
771 * resource name. Multiple calls with the same name will return multiple
772 * SharedFutures for the same Buffer object. Once called, the buffer must
773 * be freed using removeBuffer before destroying the context, even if you
774 * never get the Buffer from the SharedFuture.
776 * The Buffer will be scheduled to load asynchronously, and the caller gets
777 * back a SharedFuture that can be checked later (or waited on) to get the
778 * actual Buffer when it's ready. The application must take care to handle
779 * exceptions from the SharedFuture in case an unrecoverable error ocurred
780 * during the load.
782 SharedFuture<Buffer> getBufferAsync(StringView name);
785 * Asynchronously prepares cached Buffers for the given audio file or
786 * resource names. Duplicate names and buffers already cached are ignored.
787 * Cached buffers must be freed using removeBuffer before destroying the
788 * context.
790 * The Buffer objects will be scheduled for loading asynchronously, and
791 * should be retrieved later when needed using getBufferAsync or getBuffer.
792 * Buffers that cannot be loaded, for example due to an unsupported format,
793 * will be ignored and a later call to getBuffer or getBufferAsync will
794 * throw an exception.
796 void precacheBuffersAsync(ArrayView<StringView> names);
799 * Creates and caches a Buffer using the given name. The name may alias an
800 * audio file, but it must not currently exist in the buffer cache.
802 Buffer createBufferFrom(StringView name, SharedPtr<Decoder> decoder);
805 * Asynchronously prepares a cached Buffer using the given name. The name
806 * may alias an audio file, but it must not currently exist in the buffer
807 * cache. Once called, the buffer must be freed using removeBuffer before
808 * destroying the context, even if you never get the Buffer from the
809 * SharedFuture.
811 * The Buffer will be scheduled to load asynchronously, and the caller gets
812 * back a SharedFuture that can be checked later (or waited on) to get the
813 * actual Buffer when it's ready. The application must take care to handle
814 * exceptions from the SharedFuture in case an unrecoverable error ocurred
815 * during the load. The decoder must not have its read or seek methods
816 * called while the buffer is not ready.
818 SharedFuture<Buffer> createBufferAsyncFrom(StringView name, SharedPtr<Decoder> decoder);
821 * Deletes the cached Buffer object for the given audio file or resource
822 * name. The buffer must not be in use by a Source.
824 void removeBuffer(StringView name);
826 * Deletes the given cached buffer. The buffer must not be in use by a
827 * Source.
829 void removeBuffer(Buffer buffer);
832 * Creates a new Source. There is no practical limit to the number of
833 * sources you may create. You must call Source::release when the source is
834 * no longer needed.
836 Source createSource();
838 AuxiliaryEffectSlot createAuxiliaryEffectSlot();
840 Effect createEffect();
842 SourceGroup createSourceGroup(StringView name);
843 SourceGroup getSourceGroup(StringView name);
845 /** Sets the doppler factor to apply to all source calculations. */
846 void setDopplerFactor(ALfloat factor);
849 * Sets the speed of sound propagation, in units per second, to calculate
850 * the doppler effect along with other distance-related time effects. The
851 * default is 343.3 units per second (a realistic speed assuming 1 meter
852 * per unit). If this is adjusted for a different unit scale,
853 * Listener::setMetersPerUnit should also be adjusted.
855 void setSpeedOfSound(ALfloat speed);
857 void setDistanceModel(DistanceModel model);
859 /** Updates the context and all sources belonging to this context. */
860 void update();
863 class ALURE_API Listener {
864 MAKE_PIMPL(Listener, ListenerImpl)
866 public:
867 /** Sets the "master" gain for all context output. */
868 void setGain(ALfloat gain);
871 * Specifies the listener's 3D position, velocity, and orientation
872 * together.
874 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
876 /** Specifies the listener's 3D position. */
877 void setPosition(ALfloat x, ALfloat y, ALfloat z);
878 void setPosition(const ALfloat *pos);
881 * Specifies the listener's 3D velocity, in units per second. As with
882 * OpenAL, this does not actually alter the listener's position, and
883 * instead just alters the pitch as determined by the doppler effect.
885 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
886 void setVelocity(const ALfloat *vel);
889 * Specifies the listener's 3D orientation, using position-relative 'at'
890 * and 'up' direction vectors.
892 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
893 void setOrientation(const ALfloat *at, const ALfloat *up);
894 void setOrientation(const ALfloat *ori);
897 * Sets the number of meters per unit, used for various effects that rely
898 * on the distance in meters (including air absorption and initial reverb
899 * decay). If this is changed, it's strongly recommended to also set the
900 * speed of sound (e.g. context.setSpeedOfSound(343.3 / m_u) to maintain a
901 * realistic 343.3m/s for sound propagation).
903 void setMetersPerUnit(ALfloat m_u);
907 class ALURE_API Buffer {
908 MAKE_PIMPL(Buffer, BufferImpl)
910 public:
911 /** Retrieves the length of the buffer in sample frames. */
912 ALuint getLength() const;
914 /** Retrieves the buffer's frequency in hz. */
915 ALuint getFrequency() const;
917 /** Retrieves the buffer's sample configuration. */
918 ChannelConfig getChannelConfig() const;
920 /** Retrieves the buffer's sample type. */
921 SampleType getSampleType() const;
923 /** Retrieves the storage size used by the buffer, in bytes. */
924 ALuint getSize() const;
927 * Sets the buffer's loop points, used for looping sources. If the current
928 * context does not support the AL_SOFT_loop_points extension, start and
929 * end must be 0 and getLength() respectively. Otherwise, start must be
930 * less than end, and end must be less than or equal to getLength().
932 * The buffer must not be in use when this method is called.
934 * \param start The starting point, in sample frames (inclusive).
935 * \param end The ending point, in sample frames (exclusive).
937 void setLoopPoints(ALuint start, ALuint end);
939 /** Retrieves the current loop points as a [start,end) pair. */
940 std::pair<ALuint,ALuint> getLoopPoints() const;
943 * Retrieves the Source objects currently playing the buffer. Stopping the
944 * returned sources will allow the buffer to be removed from the context.
946 Vector<Source> getSources() const;
948 /** Retrieves the name the buffer was created with. */
949 const String &getName() const;
951 /** Queries if the buffer is in use and can't be removed. */
952 bool isInUse() const;
956 enum class Spatialize {
957 Off = AL_FALSE,
958 On = AL_TRUE,
959 Auto = 0x0002 /* AL_AUTO_SOFT */
962 class ALURE_API Source {
963 MAKE_PIMPL(Source, SourceImpl)
965 public:
967 * Plays the source using buffer. The same buffer may be played from
968 * multiple sources simultaneously.
970 void play(Buffer buffer);
972 * Plays the source by streaming audio from decoder. This will use
973 * queuesize buffers, each with updatelen sample frames. The given decoder
974 * must *NOT* have its read or seek methods called from elsewhere while in
975 * use.
977 void play(SharedPtr<Decoder> decoder, ALuint updatelen, ALuint queuesize);
980 * Prepares to play a source using the future buffer. The method will
981 * return right away, and the source will begin playing once the future
982 * buffer becomes ready. If the future buffer is already ready, it begins
983 * playing immediately.
985 * The future buffer is checked during calls to \c Context::update and the
986 * source will start playing once the future buffer reports it's ready. Use
987 * the isPending method to check if the source is still waiting for the
988 * future buffer.
990 void play(SharedFuture<Buffer> future_buffer);
992 /** Stops playback, releasing the buffer or decoder reference. */
993 void stop();
996 * Fades the source to the specified gain over the given duration, at which
997 * point playback will stop. This gain is in addition to the base gain, and
998 * must be greater than 0 and less than 1. The duration must also be
999 * greater than 0.
1001 * Fading is updated during calls to \c Context::update, which should be
1002 * called regularly (30 to 50 times per second) for the fading to be
1003 * smooth.
1005 void fadeOutToStop(ALfloat gain, std::chrono::milliseconds duration);
1007 /** Pauses the source if it is playing. */
1008 void pause();
1010 /** Resumes the source if it is paused. */
1011 void resume();
1013 /** Specifies if the source is waiting to play a future buffer. */
1014 bool isPending() const;
1016 /** Specifies if the source is currently playing. */
1017 bool isPlaying() const;
1019 /** Specifies if the source is currently paused. */
1020 bool isPaused() const;
1023 * Specifies the source's playback priority. Lowest priority sources will
1024 * be evicted first when higher priority sources are played.
1026 void setPriority(ALuint priority);
1027 /** Retrieves the source's priority. */
1028 ALuint getPriority() const;
1031 * Sets the source's offset, in sample frames. If the source is playing or
1032 * paused, it will go to that offset immediately, otherwise the source will
1033 * start at the specified offset the next time it's played.
1035 void setOffset(uint64_t offset);
1037 * Retrieves the source offset in sample frames and its latency in nano-
1038 * seconds. For streaming sources this will be the offset based on the
1039 * decoder's read position.
1041 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1042 * be 0.
1044 std::pair<uint64_t,std::chrono::nanoseconds> getSampleOffsetLatency() const;
1045 uint64_t getSampleOffset() const { return std::get<0>(getSampleOffsetLatency()); }
1047 * Retrieves the source offset and latency in seconds. For streaming
1048 * sources this will be the offset based on the decoder's read position.
1050 * If the AL_SOFT_source_latency extension is unsupported, the latency will
1051 * be 0.
1053 std::pair<Seconds,Seconds> getSecOffsetLatency() const;
1054 Seconds getSecOffset() const { return std::get<0>(getSecOffsetLatency()); }
1057 * Specifies if the source should loop on the Buffer or Decoder object's
1058 * loop points.
1060 void setLooping(bool looping);
1061 bool getLooping() const;
1064 * Specifies a linear pitch shift base. A value of 1.0 is the default
1065 * normal speed.
1067 void setPitch(ALfloat pitch);
1068 ALfloat getPitch() const;
1071 * Specifies the base linear gain. A value of 1.0 is the default normal
1072 * volume.
1074 void setGain(ALfloat gain);
1075 ALfloat getGain() const;
1078 * Specifies the minimum and maximum gain. The source's gain is clamped to
1079 * this range after distance attenuation and cone attenuation are applied
1080 * to the gain base, although before the filter gain adjustements.
1082 void setGainRange(ALfloat mingain, ALfloat maxgain);
1083 std::pair<ALfloat,ALfloat> getGainRange() const;
1084 ALfloat getMinGain() const { return std::get<0>(getGainRange()); }
1085 ALfloat getMaxGain() const { return std::get<1>(getGainRange()); }
1088 * Specifies the reference distance and maximum distance the source will
1089 * use for the current distance model. For Clamped distance models, the
1090 * source's calculated distance is clamped to the specified range before
1091 * applying distance-related attenuation.
1093 * For all distance models, the reference distance is the distance at which
1094 * the source's volume will not have any extra attenuation (an effective
1095 * gain multiplier of 1).
1097 void setDistanceRange(ALfloat refdist, ALfloat maxdist);
1098 std::pair<ALfloat,ALfloat> getDistanceRange() const;
1099 ALfloat getReferenceDistance() const { return std::get<0>(getDistanceRange()); }
1100 ALfloat getMaxDistance() const { return std::get<1>(getDistanceRange()); }
1102 /** Specifies the source's 3D position, velocity, and direction together. */
1103 void set3DParameters(const Vector3 &position, const Vector3 &velocity, const Vector3 &direction);
1105 /** Specifies the source's 3D position, velocity, and orientation together. */
1106 void set3DParameters(const Vector3 &position, const Vector3 &velocity, std::pair<Vector3,Vector3> orientation);
1108 /** Specifies the source's 3D position. */
1109 void setPosition(ALfloat x, ALfloat y, ALfloat z);
1110 void setPosition(const ALfloat *pos);
1111 Vector3 getPosition() const;
1114 * Specifies the source's 3D velocity, in units per second. As with OpenAL,
1115 * this does not actually alter the source's position, and instead just
1116 * alters the pitch as determined by the doppler effect.
1118 void setVelocity(ALfloat x, ALfloat y, ALfloat z);
1119 void setVelocity(const ALfloat *vel);
1120 Vector3 getVelocity() const;
1123 * Specifies the source's 3D facing direction. Deprecated in favor of
1124 * setOrientation.
1126 void setDirection(ALfloat x, ALfloat y, ALfloat z);
1127 void setDirection(const ALfloat *dir);
1128 Vector3 getDirection() const;
1131 * Specifies the source's 3D orientation. Note: unlike the AL_EXT_BFORMAT
1132 * extension this property comes from, this also affects the facing
1133 * direction, superceding setDirection.
1135 void setOrientation(ALfloat x1, ALfloat y1, ALfloat z1, ALfloat x2, ALfloat y2, ALfloat z2);
1136 void setOrientation(const ALfloat *at, const ALfloat *up);
1137 void setOrientation(const ALfloat *ori);
1138 std::pair<Vector3,Vector3> getOrientation() const;
1141 * Specifies the source's cone angles, in degrees. The inner angle is the
1142 * area within which the listener will hear the source with no extra
1143 * attenuation, while the listener being outside of the outer angle will
1144 * hear the source attenuated according to the outer cone gains.
1146 void setConeAngles(ALfloat inner, ALfloat outer);
1147 std::pair<ALfloat,ALfloat> getConeAngles() const;
1148 ALfloat getInnerConeAngle() const { return std::get<0>(getConeAngles()); }
1149 ALfloat getOuterConeAngle() const { return std::get<1>(getConeAngles()); }
1152 * Specifies the linear gain multiplier when the listener is outside of the
1153 * source's outer cone area. The specified gain applies to all frequencies,
1154 * while gainhf applies extra attenuation to high frequencies.
1156 * \param gainhf has no effect without the ALC_EXT_EFX extension.
1158 void setOuterConeGains(ALfloat gain, ALfloat gainhf=1.0f);
1159 std::pair<ALfloat,ALfloat> getOuterConeGains() const;
1160 ALfloat getOuterConeGain() const { return std::get<0>(getOuterConeGains()); }
1161 ALfloat getOuterConeGainHF() const { return std::get<1>(getOuterConeGains()); }
1164 * Specifies the rolloff factors for the direct and send paths. This is
1165 * effectively a distance scaling relative to the reference distance. Note:
1166 * the room rolloff factor is 0 by default, disabling distance attenuation
1167 * for send paths. This is because the reverb engine will, by default,
1168 * apply a more realistic room decay based on the reverb decay time and
1169 * distance.
1171 void setRolloffFactors(ALfloat factor, ALfloat roomfactor=0.0f);
1172 std::pair<ALfloat,ALfloat> getRolloffFactors() const;
1173 ALfloat getRolloffFactor() const { return std::get<0>(getRolloffFactors()); }
1174 ALfloat getRoomRolloffFactor() const { return std::get<1>(getRolloffFactors()); }
1177 * Specifies the doppler factor for the doppler effect's pitch shift. This
1178 * effectively scales the source and listener velocities for the doppler
1179 * calculation.
1181 void setDopplerFactor(ALfloat factor);
1182 ALfloat getDopplerFactor() const;
1185 * Specifies if the source's position, velocity, and direction/orientation
1186 * are relative to the listener.
1188 void setRelative(bool relative);
1189 bool getRelative() const;
1192 * Specifies the source's radius. This causes the source to behave as if
1193 * every point within the spherical area emits sound.
1195 * Has no effect without the AL_EXT_SOURCE_RADIUS extension.
1197 void setRadius(ALfloat radius);
1198 ALfloat getRadius() const;
1201 * Specifies the left and right channel angles, in radians, when playing a
1202 * stereo buffer or stream. The angles go counter-clockwise, with 0 being
1203 * in front and positive values going left.
1205 * Has no effect without the AL_EXT_STEREO_ANGLES extension.
1207 void setStereoAngles(ALfloat leftAngle, ALfloat rightAngle);
1208 std::pair<ALfloat,ALfloat> getStereoAngles() const;
1211 * Specifies if the source always has 3D spatialization features (On),
1212 * never has 3D spatialization features (Off), or if spatialization is
1213 * enabled based on playing a mono sound or not (Auto, default).
1215 * Has no effect without the AL_SOFT_source_spatialize extension.
1217 void set3DSpatialize(Spatialize spatialize);
1218 Spatialize get3DSpatialize() const;
1220 void setResamplerIndex(ALsizei index);
1221 ALsizei getResamplerIndex() const;
1224 * Specifies a multiplier for the amount of atmospheric high-frequency
1225 * absorption, ranging from 0 to 10. A factor of 1 results in a nominal
1226 * -0.05dB per meter, with higher values simulating foggy air and lower
1227 * values simulating dryer air. The default is 0.
1229 void setAirAbsorptionFactor(ALfloat factor);
1230 ALfloat getAirAbsorptionFactor() const;
1232 void setGainAuto(bool directhf, bool send, bool sendhf);
1233 std::tuple<bool,bool,bool> getGainAuto() const;
1234 bool getDirectGainHFAuto() const { return std::get<0>(getGainAuto()); }
1235 bool getSendGainAuto() const { return std::get<1>(getGainAuto()); }
1236 bool getSendGainHFAuto() const { return std::get<2>(getGainAuto()); }
1238 /** Sets the filter properties on the direct path signal. */
1239 void setDirectFilter(const FilterParams &filter);
1241 * Sets the filter properties on the given send path signal. Any auxiliary
1242 * effect slot on the send path remains in place.
1244 void setSendFilter(ALuint send, const FilterParams &filter);
1246 * Connects the effect slot to the given send path. Any filter properties
1247 * on the send path remain as they were.
1249 void setAuxiliarySend(AuxiliaryEffectSlot slot, ALuint send);
1251 * Connects the effect slot to the given send path, using the filter
1252 * properties.
1254 void setAuxiliarySendFilter(AuxiliaryEffectSlot slot, ALuint send, const FilterParams &filter);
1257 * Releases the source, stopping playback, releasing resources, and
1258 * returning it to the system.
1260 void release();
1264 class ALURE_API SourceGroup {
1265 MAKE_PIMPL(SourceGroup, SourceGroupImpl)
1267 public:
1268 /** Retrieves the associated name of the source group. */
1269 const String &getName() const;
1272 * Adds source to the source group. A source may only be part of one group
1273 * at a time, and will automatically be removed from its current group as
1274 * needed.
1276 void addSource(Source source);
1277 /** Removes source from the source group. */
1278 void removeSource(Source source);
1280 /** Adds a list of sources to the group at once. */
1281 void addSources(ArrayView<Source> sources);
1282 /** Removes a list of sources from the source group. */
1283 void removeSources(ArrayView<Source> sources);
1286 * Adds group as a subgroup of the source group. This method will throw an
1287 * exception if group is being added to a group it has as a sub-group (i.e.
1288 * it would create a circular sub-group chain).
1290 void addSubGroup(SourceGroup group);
1291 /** Removes group from the source group. */
1292 void removeSubGroup(SourceGroup group);
1294 /** Returns the list of sources currently in the group. */
1295 Vector<Source> getSources() const;
1297 /** Returns the list of subgroups currently in the group. */
1298 Vector<SourceGroup> getSubGroups() const;
1300 /** Sets the source group gain, which accumulates with its sources. */
1301 void setGain(ALfloat gain);
1302 /** Gets the source group gain. */
1303 ALfloat getGain() const;
1305 /** Sets the source group pitch, which accumulates with its sources. */
1306 void setPitch(ALfloat pitch);
1307 /** Gets the source group pitch. */
1308 ALfloat getPitch() const;
1311 * Pauses all currently-playing sources that are under this group,
1312 * including sub-groups.
1314 void pauseAll() const;
1316 * Resumes all paused sources that are under this group, including
1317 * sub-groups.
1319 void resumeAll() const;
1321 /** Stops all sources that are under this group, including sub-groups. */
1322 void stopAll() const;
1325 * Releases the source group, removing all sources from it before being
1326 * freed.
1328 void release();
1332 struct SourceSend {
1333 Source mSource;
1334 ALuint mSend;
1337 class ALURE_API AuxiliaryEffectSlot {
1338 MAKE_PIMPL(AuxiliaryEffectSlot, AuxiliaryEffectSlotImpl)
1340 public:
1341 void setGain(ALfloat gain);
1343 * If set to true, the reverb effect will automatically apply adjustments
1344 * to the source's send slot gains based on the effect properties.
1346 * Has no effect when using non-reverb effects. Default is true.
1348 void setSendAuto(bool sendauto);
1351 * Updates the effect slot with a new effect. The given effect object may
1352 * be altered or destroyed without affecting the effect slot.
1354 void applyEffect(Effect effect);
1357 * Releases the effect slot, returning it to the system. It must not be in
1358 * use by a source.
1360 void release();
1363 * Retrieves each Source object and its pairing send this effect slot is
1364 * set on. Setting a different (or null) effect slot on each source's given
1365 * send will allow the effect slot to be released.
1367 Vector<SourceSend> getSourceSends() const;
1369 /** Determines if the effect slot is in use by a source. */
1370 bool isInUse() const;
1374 class ALURE_API Effect {
1375 MAKE_PIMPL(Effect, EffectImpl)
1377 public:
1379 * Updates the effect with the specified reverb properties. If the
1380 * EAXReverb effect is not supported, it will automatically attempt to
1381 * downgrade to the Standard Reverb effect.
1383 void setReverbProperties(const EFXEAXREVERBPROPERTIES &props);
1385 void destroy();
1390 * Audio decoder interface. Applications may derive from this, implementing the
1391 * necessary methods, and use it in places the API wants a Decoder object.
1393 class ALURE_API Decoder {
1394 public:
1395 virtual ~Decoder();
1397 /** Retrieves the sample frequency, in hz, of the audio being decoded. */
1398 virtual ALuint getFrequency() const = 0;
1399 /** Retrieves the channel configuration of the audio being decoded. */
1400 virtual ChannelConfig getChannelConfig() const = 0;
1401 /** Retrieves the sample type of the audio being decoded. */
1402 virtual SampleType getSampleType() const = 0;
1405 * Retrieves the total length of the audio, in sample frames. If unknown,
1406 * returns 0. Note that if the returned length is 0, the decoder may not be
1407 * used to load a Buffer.
1409 virtual uint64_t getLength() const = 0;
1411 * Seek to pos, specified in sample frames. Returns true if the seek was
1412 * successful.
1414 virtual bool seek(uint64_t pos) = 0;
1417 * Retrieves the loop points, in sample frames, as a [start,end) pair. If
1418 * start >= end, use all available data.
1420 virtual std::pair<uint64_t,uint64_t> getLoopPoints() const = 0;
1423 * Decodes count sample frames, writing them to ptr, and returns the number
1424 * of sample frames written. Returning less than the requested count
1425 * indicates the end of the audio.
1427 virtual ALuint read(ALvoid *ptr, ALuint count) = 0;
1431 * Audio decoder factory interface. Applications may derive from this,
1432 * implementing the necessary methods, and use it in places the API wants a
1433 * DecoderFactory object.
1435 class ALURE_API DecoderFactory {
1436 public:
1437 virtual ~DecoderFactory();
1440 * Creates and returns a Decoder instance for the given resource file. If
1441 * the decoder needs to retain the file handle for reading as-needed, it
1442 * should move the UniquePtr to internal storage.
1444 * \return nullptr if a decoder can't be created from the file.
1446 virtual SharedPtr<Decoder> createDecoder(UniquePtr<std::istream> &file) = 0;
1450 * Registers a decoder factory for decoding audio. Registered factories are
1451 * used in lexicographical order, e.g. if Factory1 is registered with name1 and
1452 * Factory2 is registered with name2, Factory1 will be used before Factory2 if
1453 * name1 < name2. Internal decoder factories are always used after registered
1454 * ones.
1456 * Alure retains a reference to the DecoderFactory instance and will release it
1457 * (destructing the object) when the library unloads.
1459 * \param name A unique name identifying this decoder factory.
1460 * \param factory A DecoderFactory instance used to create Decoder instances.
1462 ALURE_API void RegisterDecoder(StringView name, UniquePtr<DecoderFactory> factory);
1465 * Unregisters a decoder factory by name. Alure returns the instance back to
1466 * the application.
1468 * \param name The unique name identifying a previously-registered decoder
1469 * factory.
1471 * \return The unregistered decoder factory instance, or 0 (nullptr) if a
1472 * decoder factory with the given name doesn't exist.
1474 ALURE_API UniquePtr<DecoderFactory> UnregisterDecoder(StringView name);
1478 * A file I/O factory interface. Applications may derive from this and set an
1479 * instance to be used by the audio decoders. By default, the library uses
1480 * standard I/O.
1482 class ALURE_API FileIOFactory {
1483 public:
1485 * Sets the factory instance to be used by the audio decoders. If a
1486 * previous factory was set, it's returned to the application. Passing in a
1487 * nullptr reverts to the default.
1489 static UniquePtr<FileIOFactory> set(UniquePtr<FileIOFactory> factory);
1492 * Gets the current FileIOFactory instance being used by the audio
1493 * decoders.
1495 static FileIOFactory &get();
1497 virtual ~FileIOFactory();
1499 /** Opens a read-only binary file for the given name. */
1500 virtual UniquePtr<std::istream> openFile(const String &name) = 0;
1505 * A message handler interface. Applications may derive from this and set an
1506 * instance on a context to receive messages. The base methods are no-ops, so
1507 * derived classes only need to implement methods for relevant messages.
1509 * It's recommended that applications mark their handler methods using the
1510 * override keyword, to ensure they're properly overriding the base methods in
1511 * case they change.
1513 class ALURE_API MessageHandler {
1514 public:
1515 virtual ~MessageHandler();
1518 * Called when the given device has been disconnected and is no longer
1519 * usable for output. As per the ALC_EXT_disconnect specification,
1520 * disconnected devices remain valid, however all playing sources are
1521 * automatically stopped, any sources that are attempted to play will
1522 * immediately stop, and new contexts may not be created on the device.
1524 * Note that connection status is checked during Context::update calls, so
1525 * that method must be called regularly to be notified when a device is
1526 * disconnected. This method may not be called if the device lacks support
1527 * for the ALC_EXT_disconnect extension.
1529 virtual void deviceDisconnected(Device device);
1532 * Called when the given source reaches the end of the buffer or stream.
1534 * Sources that stopped automatically will be detected upon a call to
1535 * Context::update.
1537 virtual void sourceStopped(Source source);
1540 * Called when the given source was forced to stop. This can be because
1541 * either there were no more system sources and a higher-priority source
1542 * preempted it, or it's part of a SourceGroup (or sub-group thereof) that
1543 * had its SourceGroup::stopAll method called.
1545 virtual void sourceForceStopped(Source source);
1548 * Called when a new buffer is about to be created and loaded. May be
1549 * called asynchronously for buffers being loaded asynchronously.
1551 * \param name The resource name, as passed to Context::getBuffer.
1552 * \param channels Channel configuration of the given audio data.
1553 * \param type Sample type of the given audio data.
1554 * \param samplerate Sample rate of the given audio data.
1555 * \param data The audio data that is about to be fed to the OpenAL buffer.
1557 virtual void bufferLoading(StringView name, ChannelConfig channels, SampleType type, ALuint samplerate, ArrayView<ALbyte> data);
1560 * Called when a resource isn't found, allowing the app to substitute in a
1561 * different resource. For buffers created with Context::getBuffer or
1562 * Context::getBufferAsync, the original name will still be used for the
1563 * cache map so the app doesn't have to keep track of substituted resource
1564 * names.
1566 * This will be called again if the new name isn't found.
1568 * \param name The resource name that was not found.
1569 * \return The replacement resource name to use instead. Returning an empty
1570 * string means to stop trying.
1572 virtual String resourceNotFound(StringView name);
1575 #undef MAKE_PIMPL
1577 } // namespace alure
1579 #endif /* AL_ALURE2_H */