| 
							- /*!
 - 	@file		AudioUnitSDK/AUUtility.h
 - 	@copyright	© 2000-2021 Apple Inc. All rights reserved.
 - */
 - #ifndef AudioUnitSDK_AUUtility_h
 - #define AudioUnitSDK_AUUtility_h
 - 
 - // OS
 - #if defined __has_include && __has_include(<CoreAudioTypes/CoreAudioTypes.h>)
 - #include <CoreAudioTypes/CoreAudioTypes.h>
 - #else
 - #include <CoreAudio/CoreAudioTypes.h>
 - #endif
 - #include <libkern/OSByteOrder.h>
 - #include <mach/mach_time.h>
 - #include <os/log.h>
 - #include <syslog.h>
 - 
 - // std
 - #include <bitset>
 - #include <cstddef>
 - #include <exception>
 - #include <mutex>
 - #include <string>
 - #include <system_error>
 - #include <vector>
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark General
 - 
 - #ifdef AUSDK_NO_DEPRECATIONS
 - #define AUSDK_DEPRECATED(msg)
 - #else
 - #define AUSDK_DEPRECATED(msg) [[deprecated(msg)]] // NOLINT macro
 - #endif
 - 
 - #ifndef AUSDK_LOG_OBJECT
 - #define AUSDK_LOG_OBJECT OS_LOG_DEFAULT // NOLINT macro
 - #endif
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark Version
 - 
 - #define AUSDK_VERSION_MAJOR 1
 - #define AUSDK_VERSION_MINOR 1
 - #define AUSDK_VERSION_PATCH 0
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark Error-handling macros
 - 
 - #ifdef AUSDK_NO_LOGGING
 - #define AUSDK_LogError(...) /* NOLINT macro */
 - #else
 - #define AUSDK_LogError(...) /* NOLINT macro */                                                     \
 - 	if (__builtin_available(macOS 10.11, *)) {                                                     \
 - 		os_log_error(AUSDK_LOG_OBJECT, __VA_ARGS__);                                               \
 - 	} else {                                                                                       \
 - 		syslog(LOG_ERR, __VA_ARGS__);                                                              \
 - 	}
 - #endif
 - 
 - #define AUSDK_Catch(result) /* NOLINT(cppcoreguidelines-macro-usage) */                            \
 - 	catch (const ausdk::AUException& exc) { (result) = exc.mError; }                               \
 - 	catch (const std::bad_alloc&) { (result) = kAudio_MemFullError; }                              \
 - 	catch (const OSStatus& catch_err) { (result) = catch_err; }                                    \
 - 	catch (const std::system_error& exc) { (result) = exc.code().value(); }                        \
 - 	catch (...) { (result) = -1; }
 - 
 - #define AUSDK_Require(expr, error) /* NOLINT(cppcoreguidelines-macro-usage) */                     \
 - 	do {                                                                                           \
 - 		if (!(expr)) {                                                                             \
 - 			return error;                                                                          \
 - 		}                                                                                          \
 - 	} while (0) /* NOLINT */
 - 
 - #define AUSDK_Require_noerr(expr) /* NOLINT(cppcoreguidelines-macro-usage) */                      \
 - 	do {                                                                                           \
 - 		if (const auto status_tmp_macro_detail_ = (expr); status_tmp_macro_detail_ != noErr) {     \
 - 			return status_tmp_macro_detail_;                                                       \
 - 		}                                                                                          \
 - 	} while (0)
 - 
 - #pragma mark -
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - namespace ausdk {
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - /// A subclass of std::runtime_error that holds an OSStatus error.
 - class AUException : public std::runtime_error {
 - public:
 - 	explicit AUException(OSStatus err)
 - 		: std::runtime_error{ std::string("OSStatus ") + std::to_string(err) }, mError{ err }
 - 	{
 - 	}
 - 
 - 	const OSStatus mError;
 - };
 - 
 - inline void ThrowExceptionIf(bool condition, OSStatus err)
 - {
 - 	if (condition) {
 - 		AUSDK_LogError("throwing %d", static_cast<int>(err));
 - 		throw AUException{ err };
 - 	}
 - }
 - 
 - [[noreturn]] inline void Throw(OSStatus err)
 - {
 - 	AUSDK_LogError("throwing %d", static_cast<int>(err));
 - 	throw AUException{ err };
 - }
 - 
 - inline void ThrowQuietIf(bool condition, OSStatus err)
 - {
 - 	if (condition) {
 - 		throw AUException{ err };
 - 	}
 - }
 - 
 - [[noreturn]] inline void ThrowQuiet(OSStatus err) { throw AUException{ err }; }
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - /// Wrap a std::recursive_mutex in a C++ Mutex (named requirement). Methods are virtual to support
 - /// customization.
 - class AUMutex {
 - public:
 - 	AUMutex() = default;
 - 	virtual ~AUMutex() = default;
 - 
 - 	AUMutex(const AUMutex&) = delete;
 - 	AUMutex(AUMutex&&) = delete;
 - 	AUMutex& operator=(const AUMutex&) = delete;
 - 	AUMutex& operator=(AUMutex&&) = delete;
 - 
 - 	virtual void lock() { mImpl.lock(); }
 - 	virtual void unlock() { mImpl.unlock(); }
 - 	virtual bool try_lock() { return mImpl.try_lock(); }
 - 
 - private:
 - 	std::recursive_mutex mImpl;
 - };
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - /// Implement optional locking at AudioUnit non-realtime entry points (required only for a small
 - /// number of plug-ins which must synchronize against external entry points).
 - class AUEntryGuard {
 - public:
 - 	explicit AUEntryGuard(AUMutex* maybeMutex) : mMutex{ maybeMutex }
 - 	{
 - 		if (mMutex != nullptr) {
 - 			mMutex->lock();
 - 		}
 - 	}
 - 
 - 	~AUEntryGuard()
 - 	{
 - 		if (mMutex != nullptr) {
 - 			mMutex->unlock();
 - 		}
 - 	}
 - 
 - 	AUEntryGuard(const AUEntryGuard&) = delete;
 - 	AUEntryGuard(AUEntryGuard&&) = delete;
 - 	AUEntryGuard& operator=(const AUEntryGuard&) = delete;
 - 	AUEntryGuard& operator=(AUEntryGuard&&) = delete;
 - 
 - private:
 - 	AUMutex* mMutex;
 - };
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark ASBD
 - 
 - /// Utility functions relating to AudioStreamBasicDescription.
 - namespace ASBD {
 - 
 - constexpr bool IsInterleaved(const AudioStreamBasicDescription& format) noexcept
 - {
 - 	return (format.mFormatFlags & kLinearPCMFormatFlagIsNonInterleaved) == 0u;
 - }
 - 
 - constexpr UInt32 NumberInterleavedChannels(const AudioStreamBasicDescription& format) noexcept
 - {
 - 	return IsInterleaved(format) ? format.mChannelsPerFrame : 1;
 - }
 - 
 - constexpr UInt32 NumberChannelStreams(const AudioStreamBasicDescription& format) noexcept
 - {
 - 	return IsInterleaved(format) ? 1 : format.mChannelsPerFrame;
 - }
 - 
 - constexpr bool IsCommonFloat32(const AudioStreamBasicDescription& format) noexcept
 - {
 - 	return (
 - 		format.mFormatID == kAudioFormatLinearPCM && format.mFramesPerPacket == 1 &&
 - 		format.mBytesPerPacket == format.mBytesPerFrame
 - 		// so far, it's a valid PCM format
 - 		&& (format.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0 &&
 - 		(format.mChannelsPerFrame == 1 ||
 - 			(format.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) &&
 - 		((format.mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian) &&
 - 		format.mBitsPerChannel == 32 // NOLINT
 - 		&& format.mBytesPerFrame == NumberInterleavedChannels(format) * sizeof(float));
 - }
 - 
 - constexpr AudioStreamBasicDescription CreateCommonFloat32(
 - 	Float64 sampleRate, UInt32 numChannels, bool interleaved = false) noexcept
 - {
 - 	constexpr auto sampleSize = sizeof(Float32);
 - 
 - 	AudioStreamBasicDescription asbd{};
 - 	asbd.mFormatID = kAudioFormatLinearPCM;
 - 	asbd.mFormatFlags = kAudioFormatFlagIsFloat |
 - 						static_cast<AudioFormatFlags>(kAudioFormatFlagsNativeEndian) |
 - 						kAudioFormatFlagIsPacked;
 - 	asbd.mBitsPerChannel = 8 * sampleSize; // NOLINT magic number
 - 	asbd.mChannelsPerFrame = numChannels;
 - 	asbd.mFramesPerPacket = 1;
 - 	asbd.mSampleRate = sampleRate;
 - 	if (interleaved) {
 - 		asbd.mBytesPerPacket = asbd.mBytesPerFrame = numChannels * sampleSize;
 - 	} else {
 - 		asbd.mBytesPerPacket = asbd.mBytesPerFrame = sampleSize;
 - 		asbd.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
 - 	}
 - 	return asbd;
 - }
 - 
 - constexpr bool MinimalSafetyCheck(const AudioStreamBasicDescription& x) noexcept
 - {
 - 	// This function returns false if there are sufficiently unreasonable values in any field.
 - 	// It is very conservative so even some very unlikely values will pass.
 - 	// This is just meant to catch the case where the data from a file is corrupted.
 - 
 - 	return (x.mSampleRate >= 0.) && (x.mSampleRate < 3e6) // NOLINT SACD sample rate is 2.8224 MHz
 - 		   && (x.mBytesPerPacket < 1000000)               // NOLINT
 - 		   && (x.mFramesPerPacket < 1000000)              // NOLINT
 - 		   && (x.mBytesPerFrame < 1000000)                // NOLINT
 - 		   && (x.mChannelsPerFrame > 0) && (x.mChannelsPerFrame <= 1024) // NOLINT
 - 		   && (x.mBitsPerChannel <= 1024)                                // NOLINT
 - 		   && (x.mFormatID != 0) &&
 - 		   !(x.mFormatID == kAudioFormatLinearPCM &&
 - 			   (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
 - }
 - 
 - inline bool IsEqual(
 - 	const AudioStreamBasicDescription& lhs, const AudioStreamBasicDescription& rhs) noexcept
 - {
 - 	return memcmp(&lhs, &rhs, sizeof(AudioStreamBasicDescription)) == 0;
 - }
 - 
 - } // namespace ASBD
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark ACL
 - 
 - /// Utility functions relating to AudioChannelLayout.
 - namespace ACL {
 - 
 - constexpr bool operator==(const AudioChannelLayout& lhs, const AudioChannelLayout& rhs) noexcept
 - {
 - 	if (lhs.mChannelLayoutTag != rhs.mChannelLayoutTag) {
 - 		return false;
 - 	}
 - 	if (lhs.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
 - 		return lhs.mChannelBitmap == rhs.mChannelBitmap;
 - 	}
 - 	if (lhs.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
 - 		if (lhs.mNumberChannelDescriptions != rhs.mNumberChannelDescriptions) {
 - 			return false;
 - 		}
 - 		for (auto i = 0u; i < lhs.mNumberChannelDescriptions; ++i) {
 - 			const auto& lhdesc = lhs.mChannelDescriptions[i]; // NOLINT array subscript
 - 			const auto& rhdesc = rhs.mChannelDescriptions[i]; // NOLINT array subscript
 - 
 - 			if (lhdesc.mChannelLabel != rhdesc.mChannelLabel) {
 - 				return false;
 - 			}
 - 			if (lhdesc.mChannelLabel == kAudioChannelLabel_UseCoordinates) {
 - 				if (memcmp(&lhdesc, &rhdesc, sizeof(AudioChannelDescription)) != 0) {
 - 					return false;
 - 				}
 - 			}
 - 		}
 - 	}
 - 	return true;
 - }
 - 
 - } // namespace ACL
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - /// Utility wrapper for the variably-sized AudioChannelLayout struct.
 - class AUChannelLayout {
 - public:
 - 	AUChannelLayout() : AUChannelLayout(0, kAudioChannelLayoutTag_UseChannelDescriptions, 0) {}
 - 
 - 	/// Can construct from a layout tag.
 - 	explicit AUChannelLayout(AudioChannelLayoutTag inTag) : AUChannelLayout(0, inTag, 0) {}
 - 
 - 	AUChannelLayout(uint32_t inNumberChannelDescriptions, AudioChannelLayoutTag inChannelLayoutTag,
 - 		AudioChannelBitmap inChannelBitMap)
 - 		: mStorage(
 - 			  kHeaderSize + (inNumberChannelDescriptions * sizeof(AudioChannelDescription)), {})
 - 	{
 - 		auto* const acl = reinterpret_cast<AudioChannelLayout*>(mStorage.data()); // NOLINT
 - 
 - 		acl->mChannelLayoutTag = inChannelLayoutTag;
 - 		acl->mChannelBitmap = inChannelBitMap;
 - 		acl->mNumberChannelDescriptions = inNumberChannelDescriptions;
 - 	}
 - 
 - 	/// Implicit conversion from AudioChannelLayout& is allowed.
 - 	AUChannelLayout(const AudioChannelLayout& acl) // NOLINT
 - 		: mStorage(kHeaderSize + (acl.mNumberChannelDescriptions * sizeof(AudioChannelDescription)))
 - 	{
 - 		memcpy(mStorage.data(), &acl, mStorage.size());
 - 	}
 - 
 - 	bool operator==(const AUChannelLayout& other) const noexcept
 - 	{
 - 		return ACL::operator==(Layout(), other.Layout());
 - 	}
 - 
 - 	bool operator!=(const AUChannelLayout& y) const noexcept { return !(*this == y); }
 - 
 - 	[[nodiscard]] bool IsValid() const noexcept { return NumberChannels() > 0; }
 - 
 - 	[[nodiscard]] const AudioChannelLayout& Layout() const noexcept { return *LayoutPtr(); }
 - 
 - 	[[nodiscard]] const AudioChannelLayout* LayoutPtr() const noexcept
 - 	{
 - 		return reinterpret_cast<const AudioChannelLayout*>(mStorage.data()); // NOLINT
 - 	}
 - 
 - 	/// After default construction, this method will return
 - 	/// kAudioChannelLayoutTag_UseChannelDescriptions with 0 channel descriptions.
 - 	[[nodiscard]] AudioChannelLayoutTag Tag() const noexcept { return Layout().mChannelLayoutTag; }
 - 
 - 	[[nodiscard]] uint32_t NumberChannels() const noexcept { return NumberChannels(*LayoutPtr()); }
 - 
 - 	[[nodiscard]] uint32_t Size() const noexcept { return static_cast<uint32_t>(mStorage.size()); }
 - 
 - 	static uint32_t NumberChannels(const AudioChannelLayout& inLayout) noexcept
 - 	{
 - 		if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
 - 			return inLayout.mNumberChannelDescriptions;
 - 		}
 - 		if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
 - 			return static_cast<uint32_t>(
 - 				std::bitset<32>(inLayout.mChannelBitmap).count()); // NOLINT magic #
 - 		}
 - 		return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
 - 	}
 - 
 - private:
 - 	constexpr static size_t kHeaderSize = offsetof(AudioChannelLayout, mChannelDescriptions[0]);
 - 	std::vector<std::byte> mStorage;
 - };
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark AudioBufferList
 - 
 - /// Utility functions relating to AudioBufferList.
 - namespace ABL {
 - 
 - // if the return result is odd, there was a null buffer.
 - inline uint32_t IsBogusAudioBufferList(const AudioBufferList& abl)
 - {
 - 	const AudioBuffer *buf = abl.mBuffers, *const bufEnd = buf + abl.mNumberBuffers;
 - 	uint32_t sum =
 - 		0; // defeat attempts by the compiler to optimize away the code that touches the buffers
 - 	uint32_t anyNull = 0;
 - 	for (; buf < bufEnd; ++buf) {
 - 		const uint32_t* const p = static_cast<const uint32_t*>(buf->mData);
 - 		if (p == nullptr) {
 - 			anyNull = 1;
 - 			continue;
 - 		}
 - 		const auto dataSize = buf->mDataByteSize;
 - 		if (dataSize >= sizeof(*p)) {
 - 			const size_t frameCount = dataSize / sizeof(*p);
 - 			sum += p[0];
 - 			sum += p[frameCount - 1];
 - 		}
 - 	}
 - 	return anyNull | (sum & ~1u);
 - }
 - 
 - } // namespace ABL
 - 
 - // -------------------------------------------------------------------------------------------------
 - #pragma mark -
 - #pragma mark HostTime
 - 
 - /// Utility functions relating to Mach absolute time.
 - namespace HostTime {
 - 
 - /// Returns the current host time
 - inline uint64_t Current() { return mach_absolute_time(); }
 - 
 - /// Returns the frequency of the host timebase, in ticks per second.
 - inline double Frequency()
 - {
 - 	struct mach_timebase_info timeBaseInfo {
 - 	}; // NOLINT
 - 	mach_timebase_info(&timeBaseInfo);
 - 	//	the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9
 - 	return static_cast<double>(timeBaseInfo.denom) / static_cast<double>(timeBaseInfo.numer) *
 - 		   1.0e9; // NOLINT
 - }
 - 
 - } // namespace HostTime
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - /// Basic RAII wrapper for CoreFoundation types
 - template <typename T>
 - class Owned {
 - 	explicit Owned(T obj, bool fromget) noexcept : mImpl{ obj }
 - 	{
 - 		if (fromget) {
 - 			retainRef();
 - 		}
 - 	}
 - 
 - public:
 - 	static Owned from_get(T obj) noexcept { return Owned{ obj, true }; }
 - 
 - 	static Owned from_create(T obj) noexcept { return Owned{ obj, false }; }
 - 	static Owned from_copy(T obj) noexcept { return Owned{ obj, false }; }
 - 
 - 	Owned() noexcept = default;
 - 	~Owned() noexcept { releaseRef(); }
 - 
 - 	Owned(const Owned& other) noexcept : mImpl{ other.mImpl } { retainRef(); }
 - 
 - 	Owned(Owned&& other) noexcept : mImpl{ std::exchange(other.mImpl, nullptr) } {}
 - 
 - 	Owned& operator=(const Owned& other) noexcept
 - 	{
 - 		if (this != &other) {
 - 			releaseRef();
 - 			mImpl = other.mImpl;
 - 			retainRef();
 - 		}
 - 		return *this;
 - 	}
 - 
 - 	Owned& operator=(Owned&& other) noexcept
 - 	{
 - 		std::swap(mImpl, other.mImpl);
 - 		return *this;
 - 	}
 - 
 - 	T operator*() const noexcept { return get(); }
 - 	T get() const noexcept { return mImpl; }
 - 
 - 	/// As with `unique_ptr<T>::release()`, releases ownership of the reference to the caller (not
 - 	/// to be confused with decrementing the reference count as with `CFRelease()`).
 - 	T release() noexcept { return std::exchange(mImpl, nullptr); }
 - 
 - 	/// This is a from_get operation.
 - 	Owned& operator=(T cfobj) noexcept
 - 	{
 - 		if (mImpl != cfobj) {
 - 			releaseRef();
 - 			mImpl = cfobj;
 - 			retainRef();
 - 		}
 - 		return *this;
 - 	}
 - 
 - private:
 - 	void retainRef() noexcept
 - 	{
 - 		if (mImpl != nullptr) {
 - 			CFRetain(mImpl);
 - 		}
 - 	}
 - 
 - 	void releaseRef() noexcept
 - 	{
 - 		if (mImpl != nullptr) {
 - 			CFRelease(mImpl);
 - 		}
 - 	}
 - 
 - 	T mImpl{ nullptr };
 - };
 - 
 - // -------------------------------------------------------------------------------------------------
 - 
 - constexpr bool safe_isprint(char in_char) noexcept { return (in_char >= ' ') && (in_char <= '~'); }
 - 
 - inline std::string make_string_from_4cc(uint32_t in_4cc) noexcept
 - {
 - #if !TARGET_RT_BIG_ENDIAN
 - 	in_4cc = OSSwapInt32(in_4cc); // NOLINT
 - #endif
 - 
 - 	char* const string = reinterpret_cast<char*>(&in_4cc); // NOLINT
 - 	for (size_t i = 0; i < sizeof(in_4cc); ++i) {
 - 		if (!safe_isprint(string[i])) { // NOLINT
 - 			string[i] = '.';            // NOLINT
 - 		}
 - 	}
 - 	return std::string{ string, sizeof(in_4cc) };
 - }
 - 
 - } // namespace ausdk
 - 
 - #endif // AudioUnitSDK_AUUtility_h
 
 
  |