From 101a606120cd4e72e5259fa080a8da2e481a0364 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 31 Mar 2021 18:34:09 +0200 Subject: sokol_audio.h macOS: don't include macOS framework headers by default. (#501) * sokol_audio.h: optionally don't include AudioToolbox * sokol_audio.h: enable SAUDIO_OSX_USE_SYSTEM_HEADERS on iOS --- sokol_audio.h | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 13 deletions(-) (limited to 'sokol_audio.h') diff --git a/sokol_audio.h b/sokol_audio.h index 02fe934b..faea8177 100644 --- a/sokol_audio.h +++ b/sokol_audio.h @@ -24,7 +24,9 @@ SOKOL_API_DECL - same as SOKOL_AUDIO_API_DECL SOKOL_API_IMPL - public function implementation prefix (default: -) - SAUDIO_RING_MAX_SLOTS - max number of slots in the push-audio ring buffer (default 1024) + SAUDIO_RING_MAX_SLOTS - max number of slots in the push-audio ring buffer (default 1024) + SAUDIO_OSX_USE_SYSTEM_HEADERS - define this to force inclusion of system headers on + macOS instead of using embedded CoreAudio declarations If sokol_audio.h is compiled as a DLL, define the following before including the declaration or implementation: @@ -501,10 +503,10 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc); #elif defined(__APPLE__) #define _SAUDIO_APPLE (1) #include - #if defined(TARGET_OS_IPHONE) && !TARGET_OS_IPHONE - #define _SAUDIO_MACOS (1) - #else + #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #define _SAUDIO_IOS (1) + #else + #define _SAUDIO_MACOS (1) #endif #elif defined(__EMSCRIPTEN__) #define _SAUDIO_EMSCRIPTEN @@ -579,14 +581,22 @@ inline void saudio_setup(const saudio_desc& desc) { return saudio_setup(&desc); #elif defined(_SAUDIO_APPLE) #define _SAUDIO_PTHREADS (1) #include - #include #if defined(_SAUDIO_IOS) + // always use system headers on iOS (for now at least) + #if !defined(SAUDIO_OSX_USE_SYSTEM_HEADERS) + #define SAUDIO_OSX_USE_SYSTEM_HEADERS (1) + #endif #if !defined(__cplusplus) #if __has_feature(objc_arc) && !__has_feature(objc_arc_fields) #error "sokol_audio.h on iOS requires __has_feature(objc_arc_field) if ARC is enabled (use a more recent compiler version)" #endif #endif + #include #include + #else + #if defined(SAUDIO_OSX_USE_SYSTEM_HEADERS) + #include + #endif #endif #elif defined(_SAUDIO_ANDROID) #define _SAUDIO_PTHREADS (1) @@ -645,8 +655,97 @@ typedef struct { /*=== COREAUDIO BACKEND DECLARATIONS =========================================*/ #elif defined(_SAUDIO_APPLE) +#if defined(SAUDIO_OSX_USE_SYSTEM_HEADERS) + +typedef AudioQueueRef _saudio_AudioQueueRef; +typedef AudioQueueBufferRef _saudio_AudioQueueBufferRef; +typedef AudioStreamBasicDescription _saudio_AudioStreamBasicDescription; +typedef OSStatus _saudio_OSStatus; + +#define _saudio_kAudioFormatLinearPCM (kAudioFormatLinearPCM) +#define _saudio_kLinearPCMFormatFlagIsFloat (kLinearPCMFormatFlagIsFloat) +#define _saudio_kAudioFormatFlagIsPacked (kAudioFormatFlagIsPacked) + +#else + +// embedded AudioToolbox declarations +typedef uint32_t _saudio_AudioFormatID; +typedef uint32_t _saudio_AudioFormatFlags; +typedef int32_t _saudio_OSStatus; +typedef uint32_t _saudio_SMPTETimeType; +typedef uint32_t _saudio_SMPTETimeFlags; +typedef uint32_t _saudio_AudioTimeStampFlags; +typedef void* _saudio_CFRunLoopRef; +typedef void* _saudio_CFStringRef; +typedef void* _saudio_AudioQueueRef; + +#define _saudio_kAudioFormatLinearPCM ('lpcm') +#define _saudio_kLinearPCMFormatFlagIsFloat (1U << 0) +#define _saudio_kAudioFormatFlagIsPacked (1U << 3) + +typedef struct _saudio_AudioStreamBasicDescription { + double mSampleRate; + _saudio_AudioFormatID mFormatID; + _saudio_AudioFormatFlags mFormatFlags; + uint32_t mBytesPerPacket; + uint32_t mFramesPerPacket; + uint32_t mBytesPerFrame; + uint32_t mChannelsPerFrame; + uint32_t mBitsPerChannel; + uint32_t mReserved; +} _saudio_AudioStreamBasicDescription; + +typedef struct _saudio_AudioStreamPacketDescription { + int64_t mStartOffset; + uint32_t mVariableFramesInPacket; + uint32_t mDataByteSize; +} _saudio_AudioStreamPacketDescription; + +typedef struct _saudio_SMPTETime { + int16_t mSubframes; + int16_t mSubframeDivisor; + uint32_t mCounter; + _saudio_SMPTETimeType mType; + _saudio_SMPTETimeFlags mFlags; + int16_t mHours; + int16_t mMinutes; + int16_t mSeconds; + int16_t mFrames; +} _saudio_SMPTETime; + +typedef struct _saudio_AudioTimeStamp { + double mSampleTime; + uint64_t mHostTime; + double mRateScalar; + uint64_t mWordClockTime; + _saudio_SMPTETime mSMPTETime; + _saudio_AudioTimeStampFlags mFlags; + uint32_t mReserved; +} _saudio_AudioTimeStamp; + +typedef struct _saudio_AudioQueueBuffer { + const uint32_t mAudioDataBytesCapacity; + void* const mAudioData; + uint32_t mAudioDataByteSize; + void * mUserData; + const uint32_t mPacketDescriptionCapacity; + _saudio_AudioStreamPacketDescription* const mPacketDescriptions; + uint32_t mPacketDescriptionCount; +} _saudio_AudioQueueBuffer; +typedef _saudio_AudioQueueBuffer* _saudio_AudioQueueBufferRef; + +typedef void (*_saudio_AudioQueueOutputCallback)(void* user_data, _saudio_AudioQueueRef inAQ, _saudio_AudioQueueBufferRef inBuffer); + +extern _saudio_OSStatus AudioQueueNewOutput(const _saudio_AudioStreamBasicDescription* inFormat, _saudio_AudioQueueOutputCallback inCallbackProc, void* inUserData, _saudio_CFRunLoopRef inCallbackRunLoop, _saudio_CFStringRef inCallbackRunLoopMode, uint32_t inFlags, _saudio_AudioQueueRef* outAQ); +extern _saudio_OSStatus AudioQueueDispose(_saudio_AudioQueueRef inAQ, bool inImmediate); +extern _saudio_OSStatus AudioQueueAllocateBuffer(_saudio_AudioQueueRef inAQ, uint32_t inBufferByteSize, _saudio_AudioQueueBufferRef* outBuffer); +extern _saudio_OSStatus AudioQueueEnqueueBuffer(_saudio_AudioQueueRef inAQ, _saudio_AudioQueueBufferRef inBuffer, uint32_t inNumPacketDescs, const _saudio_AudioStreamPacketDescription* inPacketDescs); +extern _saudio_OSStatus AudioQueueStart(_saudio_AudioQueueRef inAQ, const _saudio_AudioTimeStamp * inStartTime); +extern _saudio_OSStatus AudioQueueStop(_saudio_AudioQueueRef inAQ, bool inImmediate); +#endif // SAUDIO_OSX_USE_SYSTEM_HEADERS + typedef struct { - AudioQueueRef ca_audio_queue; + _saudio_AudioQueueRef ca_audio_queue; #if defined(_SAUDIO_IOS) id ca_interruption_handler; #endif @@ -1078,7 +1177,7 @@ _SOKOL_PRIVATE void _saudio_backend_shutdown(void) { }; #endif // _SAUDIO_IOS /* NOTE: the buffer data callback is called on a separate thread! */ -_SOKOL_PRIVATE void _saudio_coreaudio_callback(void* user_data, AudioQueueRef queue, AudioQueueBufferRef buffer) { +_SOKOL_PRIVATE void _saudio_coreaudio_callback(void* user_data, _saudio_AudioQueueRef queue, _saudio_AudioQueueBufferRef buffer) { _SOKOL_UNUSED(user_data); if (_saudio_has_callback()) { const int num_frames = (int)buffer->mAudioDataByteSize / _saudio.bytes_per_frame; @@ -1111,22 +1210,22 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) { #endif // _SAUDIO_IOS /* create an audio queue with fp32 samples */ - AudioStreamBasicDescription fmt; + _saudio_AudioStreamBasicDescription fmt; memset(&fmt, 0, sizeof(fmt)); - fmt.mSampleRate = (Float64) _saudio.sample_rate; - fmt.mFormatID = kAudioFormatLinearPCM; - fmt.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagIsPacked; + fmt.mSampleRate = (double) _saudio.sample_rate; + fmt.mFormatID = _saudio_kAudioFormatLinearPCM; + fmt.mFormatFlags = _saudio_kLinearPCMFormatFlagIsFloat | _saudio_kAudioFormatFlagIsPacked; fmt.mFramesPerPacket = 1; fmt.mChannelsPerFrame = (uint32_t) _saudio.num_channels; fmt.mBytesPerFrame = (uint32_t)sizeof(float) * (uint32_t)_saudio.num_channels; fmt.mBytesPerPacket = fmt.mBytesPerFrame; fmt.mBitsPerChannel = 32; - OSStatus res = AudioQueueNewOutput(&fmt, _saudio_coreaudio_callback, 0, NULL, NULL, 0, &_saudio.backend.ca_audio_queue); + _saudio_OSStatus res = AudioQueueNewOutput(&fmt, _saudio_coreaudio_callback, 0, NULL, NULL, 0, &_saudio.backend.ca_audio_queue); SOKOL_ASSERT((res == 0) && _saudio.backend.ca_audio_queue); /* create 2 audio buffers */ for (int i = 0; i < 2; i++) { - AudioQueueBufferRef buf = NULL; + _saudio_AudioQueueBufferRef buf = NULL; const uint32_t buf_byte_size = (uint32_t)_saudio.buffer_frames * fmt.mBytesPerFrame; res = AudioQueueAllocateBuffer(_saudio.backend.ca_audio_queue, buf_byte_size, &buf); SOKOL_ASSERT((res == 0) && buf); -- cgit v1.2.3