From 897fbcfe1c8973e87464d78ce01d2f50c4ea841b Mon Sep 17 00:00:00 2001 From: Palana Date: Fri, 5 Jun 2015 05:25:33 +0200 Subject: [PATCH] coreaudio-encoder: Make encoder available on windows --- plugins/CMakeLists.txt | 4 + plugins/coreaudio-encoder/CMakeLists.txt | 30 +- plugins/coreaudio-encoder/encoder.c | 26 ++ plugins/coreaudio-encoder/windows-imports.h | 459 ++++++++++++++++++++ 4 files changed, 508 insertions(+), 11 deletions(-) create mode 100644 plugins/coreaudio-encoder/windows-imports.h diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index ca0536bfe..2109d9b2b 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,5 +1,9 @@ if(WIN32) + option(BUILD_CA_ENCODER "Build CoreAudio encoder module" ON) + if (BUILD_CA_ENCODER) + add_subdirectory(coreaudio-encoder) + endif() add_subdirectory(win-wasapi) add_subdirectory(win-dshow) add_subdirectory(win-capture) diff --git a/plugins/coreaudio-encoder/CMakeLists.txt b/plugins/coreaudio-encoder/CMakeLists.txt index ae7188f70..61d7e7bf3 100644 --- a/plugins/coreaudio-encoder/CMakeLists.txt +++ b/plugins/coreaudio-encoder/CMakeLists.txt @@ -1,24 +1,32 @@ project(coreaudio-encoder) -find_library(COREFOUNDATION CoreFoundation) -find_library(COREAUDIO CoreAudio) -find_library(AUDIOTOOLBOX AudioToolbox) - -include_directories(${COREFOUNDATION} - ${COREAUDIO} - ${AUDIOTOOLBOX}) - set(coreaudio-encoder_SOURCES encoder.c) +if (WIN32) + set(coreaudio-encoder_HEADERS windows-imports.h) + set(coreaudio-encoder_LIBS ) +else() + find_library(COREFOUNDATION CoreFoundation) + find_library(COREAUDIO CoreAudio) + find_library(AUDIOTOOLBOX AudioToolbox) + set(coreaudio-encoder_HEADERS ) + set(coreaudio-encoder_LIBS + ${COREFOUNDATION} + ${COREAUDIO} + ${AUDIOTOOLBOX}) + + include_directories(${COREFOUNDATION} + ${COREAUDIO} + ${AUDIOTOOLBOX}) +endif() + add_library(coreaudio-encoder MODULE ${coreaudio-encoder_SOURCES} ${coreaudio-encoder_HEADERS}) target_link_libraries(coreaudio-encoder libobs - ${COREFOUNDATION} - ${COREAUDIO} - ${AUDIOTOOLBOX}) + ${coreaudio-encoder_LIBS}) install_obs_plugin_with_data(coreaudio-encoder data) diff --git a/plugins/coreaudio-encoder/encoder.c b/plugins/coreaudio-encoder/encoder.c index a2f035be0..fad88d802 100644 --- a/plugins/coreaudio-encoder/encoder.c +++ b/plugins/coreaudio-encoder/encoder.c @@ -2,7 +2,9 @@ #include #include +#ifndef _WIN32 #include +#endif #define CA_LOG(level, format, ...) \ blog(level, "[CoreAudio encoder]: " format, ##__VA_ARGS__) @@ -14,6 +16,10 @@ CA_LOG_ENCODER(ca->format_name, ca->encoder, level, format, \ ##__VA_ARGS__) +#ifdef _WIN32 +#include "windows-imports.h" +#endif + struct ca_encoder { obs_encoder_t *encoder; const char *format_name; @@ -80,6 +86,7 @@ static const char *code_to_str(OSStatus code) static void log_osstatus(ca_encoder *ca, const char *context, OSStatus code) { +#ifndef _WIN32 CFErrorRef err = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, code, NULL); CFStringRef str = CFErrorCopyDescription(err); @@ -95,6 +102,7 @@ static void log_osstatus(ca_encoder *ca, const char *context, OSStatus code) else CA_LOG(LOG_ERROR, "Error in %s: %s", context, c_str); } else { +#endif const char *code_str = code_to_str(code); if (ca) CA_BLOG(LOG_ERROR, "Error in %s: %s%s%d%s", context, @@ -108,11 +116,13 @@ static void log_osstatus(ca_encoder *ca, const char *context, OSStatus code) code_str ? " (" : "", (int)code, code_str ? ")" : ""); +#ifndef _WIN32 } free(c_str); CFRelease(str); CFRelease(err); +#endif } static void aac_destroy(void *data) @@ -755,6 +765,22 @@ OBS_MODULE_USE_DEFAULT_LOCALE("coreaudio-encoder", "en-US") bool obs_module_load(void) { +#ifdef _WIN32 + if (!load_core_audio()) { + CA_LOG(LOG_WARNING, "Couldn't load CoreAudio AAC encoder"); + return true; + } + + CA_LOG(LOG_INFO, "Adding CoreAudio AAC encoder"); +#endif + obs_register_encoder(&aac_info); return true; } + +#ifdef _WIN32 +void obs_module_unload(void) +{ + unload_core_audio(); +} +#endif diff --git a/plugins/coreaudio-encoder/windows-imports.h b/plugins/coreaudio-encoder/windows-imports.h new file mode 100644 index 000000000..fa17a1249 --- /dev/null +++ b/plugins/coreaudio-encoder/windows-imports.h @@ -0,0 +1,459 @@ +#define NO_MIN_MAX 1 +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include + +typedef unsigned long UInt32; +typedef signed long SInt32; +typedef signed long long SInt64; +typedef double Float64; + +typedef SInt32 OSStatus; +typedef unsigned char Boolean; + +typedef UInt32 AudioFormatPropertyID; + +enum { + kVariableLengthArray = 1 +}; + +struct OpaqueAudioConverter; +typedef struct OpaqueAudioConverter *AudioConverterRef; +typedef UInt32 AudioConverterPropertyID; + +struct AudioValueRange { + Float64 mMinimum; + Float64 mMaximum; +}; +typedef struct AudioValueRange AudioValueRange; + +struct AudioBuffer { + UInt32 mNumberChannels; + UInt32 mDataByteSize; + void* mData; +}; +typedef struct AudioBuffer AudioBuffer; + +struct AudioBufferList { + UInt32 mNumberBuffers; + AudioBuffer mBuffers[kVariableLengthArray]; +}; +typedef struct AudioBufferList AudioBufferList; + +struct AudioStreamBasicDescription { + Float64 mSampleRate; + UInt32 mFormatID; + UInt32 mFormatFlags; + UInt32 mBytesPerPacket; + UInt32 mFramesPerPacket; + UInt32 mBytesPerFrame; + UInt32 mChannelsPerFrame; + UInt32 mBitsPerChannel; + UInt32 mReserved; +}; +typedef struct AudioStreamBasicDescription AudioStreamBasicDescription; + +struct AudioStreamPacketDescription { + SInt64 mStartOffset; + UInt32 mVariableFramesInPacket; + UInt32 mDataByteSize; +}; +typedef struct AudioStreamPacketDescription AudioStreamPacketDescription; + +typedef OSStatus (*AudioConverterComplexInputDataProc) ( + AudioConverterRef inAudioConverter, + UInt32 *ioNumberDataPackets, + AudioBufferList *ioData, + AudioStreamPacketDescription **outDataPacketDescription, + void *inUserData +); + +enum { + kAudioCodecPropertyNameCFString = 'lnam', + kAudioCodecPropertyManufacturerCFString = 'lmak', + kAudioCodecPropertyFormatCFString = 'lfor', + //kAudioCodecPropertyHasVariablePacketByteSizes = 'vpk?', + kAudioCodecPropertySupportedInputFormats = 'ifm#', + kAudioCodecPropertySupportedOutputFormats = 'ofm#', + kAudioCodecPropertyAvailableInputSampleRates = 'aisr', + kAudioCodecPropertyAvailableOutputSampleRates = 'aosr', + kAudioCodecPropertyAvailableBitRateRange = 'abrt', + kAudioCodecPropertyMinimumNumberInputPackets = 'mnip', + kAudioCodecPropertyMinimumNumberOutputPackets = 'mnop', + kAudioCodecPropertyAvailableNumberChannels = 'cmnc', + kAudioCodecPropertyDoesSampleRateConversion = 'lmrc', + kAudioCodecPropertyAvailableInputChannelLayoutTags = 'aicl', + kAudioCodecPropertyAvailableOutputChannelLayoutTags = 'aocl', + kAudioCodecPropertyInputFormatsForOutputFormat = 'if4o', + kAudioCodecPropertyOutputFormatsForInputFormat = 'of4i', + kAudioCodecPropertyFormatInfo = 'acfi', +}; + +enum { + kAudioCodecPropertyInputBufferSize = 'tbuf', + kAudioCodecPropertyPacketFrameSize = 'pakf', + kAudioCodecPropertyMaximumPacketByteSize = 'pakb', + kAudioCodecPropertyCurrentInputFormat = 'ifmt', + kAudioCodecPropertyCurrentOutputFormat = 'ofmt', + kAudioCodecPropertyMagicCookie = 'kuki', + kAudioCodecPropertyUsedInputBufferSize = 'ubuf', + kAudioCodecPropertyIsInitialized = 'init', + kAudioCodecPropertyCurrentTargetBitRate = 'brat', + kAudioCodecPropertyCurrentInputSampleRate = 'cisr', + kAudioCodecPropertyCurrentOutputSampleRate = 'cosr', + kAudioCodecPropertyQualitySetting = 'srcq', + kAudioCodecPropertyApplicableBitRateRange = 'brta', + kAudioCodecPropertyApplicableInputSampleRates = 'isra', + kAudioCodecPropertyApplicableOutputSampleRates = 'osra', + kAudioCodecPropertyPaddedZeros = 'pad0', + kAudioCodecPropertyPrimeMethod = 'prmm', + kAudioCodecPropertyPrimeInfo = 'prim', + kAudioCodecPropertyCurrentInputChannelLayout = 'icl ', + kAudioCodecPropertyCurrentOutputChannelLayout = 'ocl ', + kAudioCodecPropertySettings = 'acs ', + kAudioCodecPropertyFormatList = 'acfl', + kAudioCodecPropertyBitRateControlMode = 'acbf', + kAudioCodecPropertySoundQualityForVBR = 'vbrq', + kAudioCodecPropertyMinimumDelayMode = 'mdel' +}; + +enum { + kAudioCodecBitRateControlMode_Constant = 0, + kAudioCodecBitRateControlMode_LongTermAverage = 1, + kAudioCodecBitRateControlMode_VariableConstrained = 2, + kAudioCodecBitRateControlMode_Variable = 3, +}; + +enum { + kAudioFormatLinearPCM = 'lpcm', + kAudioFormatAC3 = 'ac-3', + kAudioFormat60958AC3 = 'cac3', + kAudioFormatAppleIMA4 = 'ima4', + kAudioFormatMPEG4AAC = 'aac ', + kAudioFormatMPEG4CELP = 'celp', + kAudioFormatMPEG4HVXC = 'hvxc', + kAudioFormatMPEG4TwinVQ = 'twvq', + kAudioFormatMACE3 = 'MAC3', + kAudioFormatMACE6 = 'MAC6', + kAudioFormatULaw = 'ulaw', + kAudioFormatALaw = 'alaw', + kAudioFormatQDesign = 'QDMC', + kAudioFormatQDesign2 = 'QDM2', + kAudioFormatQUALCOMM = 'Qclp', + kAudioFormatMPEGLayer1 = '.mp1', + kAudioFormatMPEGLayer2 = '.mp2', + kAudioFormatMPEGLayer3 = '.mp3', + kAudioFormatTimeCode = 'time', + kAudioFormatMIDIStream = 'midi', + kAudioFormatParameterValueStream = 'apvs', + kAudioFormatAppleLossless = 'alac', + kAudioFormatMPEG4AAC_HE = 'aach', + kAudioFormatMPEG4AAC_LD = 'aacl', + kAudioFormatMPEG4AAC_HE_V2 = 'aacp', + kAudioFormatMPEG4AAC_Spatial = 'aacs', + kAudioFormatAMR = 'samr' +}; + +enum { + kAudioFormatFlagIsFloat = (1L << 0), + kAudioFormatFlagIsBigEndian = (1L << 1), + kAudioFormatFlagIsSignedInteger = (1L << 2), + kAudioFormatFlagIsPacked = (1L << 3), + kAudioFormatFlagIsAlignedHigh = (1L << 4), + kAudioFormatFlagIsNonInterleaved = (1L << 5), + kAudioFormatFlagIsNonMixable = (1L << 6), + kAudioFormatFlagsAreAllClear = (1L << 31), + + kLinearPCMFormatFlagIsFloat = + kAudioFormatFlagIsFloat, + kLinearPCMFormatFlagIsBigEndian = + kAudioFormatFlagIsBigEndian, + kLinearPCMFormatFlagIsSignedInteger = + kAudioFormatFlagIsSignedInteger, + kLinearPCMFormatFlagIsPacked = + kAudioFormatFlagIsPacked, + kLinearPCMFormatFlagIsAlignedHigh = + kAudioFormatFlagIsAlignedHigh, + kLinearPCMFormatFlagIsNonInterleaved = + kAudioFormatFlagIsNonInterleaved, + kLinearPCMFormatFlagIsNonMixable = + kAudioFormatFlagIsNonMixable, + kLinearPCMFormatFlagsAreAllClear = + kAudioFormatFlagsAreAllClear, + + kAppleLosslessFormatFlag_16BitSourceData = 1, + kAppleLosslessFormatFlag_20BitSourceData = 2, + kAppleLosslessFormatFlag_24BitSourceData = 3, + kAppleLosslessFormatFlag_32BitSourceData = 4 +}; + +enum { + kAudioFormatFlagsNativeEndian = 0, +}; + +enum { + // AudioStreamBasicDescription structure properties + kAudioFormatProperty_FormatInfo = 'fmti', + kAudioFormatProperty_FormatName = 'fnam', + kAudioFormatProperty_EncodeFormatIDs = 'acof', + kAudioFormatProperty_DecodeFormatIDs = 'acif', + kAudioFormatProperty_FormatList = 'flst', + kAudioFormatProperty_ASBDFromESDS = 'essd', + kAudioFormatProperty_ChannelLayoutFromESDS = 'escl', + kAudioFormatProperty_OutputFormatList = 'ofls', + kAudioFormatProperty_Encoders = 'aven', + kAudioFormatProperty_Decoders = 'avde', + kAudioFormatProperty_FormatIsVBR = 'fvbr', + kAudioFormatProperty_FormatIsExternallyFramed = 'fexf', + kAudioFormatProperty_AvailableEncodeBitRates = 'aebr', + kAudioFormatProperty_AvailableEncodeSampleRates = 'aesr', + kAudioFormatProperty_AvailableEncodeChannelLayoutTags = 'aecl', + kAudioFormatProperty_AvailableEncodeNumberChannels = 'avnc', + kAudioFormatProperty_ASBDFromMPEGPacket = 'admp', + // + // AudioChannelLayout structure properties + kAudioFormatProperty_BitmapForLayoutTag = 'bmtg', + kAudioFormatProperty_MatrixMixMap = 'mmap', + kAudioFormatProperty_ChannelMap = 'chmp', + kAudioFormatProperty_NumberOfChannelsForLayout = 'nchm', + kAudioFormatProperty_ValidateChannelLayout = 'vacl', + kAudioFormatProperty_ChannelLayoutForTag = 'cmpl', + kAudioFormatProperty_TagForChannelLayout = 'cmpt', + kAudioFormatProperty_ChannelLayoutName = 'lonm', + kAudioFormatProperty_ChannelLayoutSimpleName = 'lsnm', + kAudioFormatProperty_ChannelLayoutForBitmap = 'cmpb', + kAudioFormatProperty_ChannelName = 'cnam', + kAudioFormatProperty_ChannelShortName = 'csnm', + kAudioFormatProperty_TagsForNumberOfChannels = 'tagc', + kAudioFormatProperty_PanningMatrix = 'panm', + kAudioFormatProperty_BalanceFade = 'balf', + // + // ID3 tag (MP3 metadata) properties + kAudioFormatProperty_ID3TagSize = 'id3s', + kAudioFormatProperty_ID3TagToDictionary = 'id3d' +}; + +enum { + kAudioConverterPropertyMinimumInputBufferSize = 'mibs', + kAudioConverterPropertyMinimumOutputBufferSize = 'mobs', + kAudioConverterPropertyMaximumInputBufferSize = 'xibs', + kAudioConverterPropertyMaximumInputPacketSize = 'xips', + kAudioConverterPropertyMaximumOutputPacketSize = 'xops', + kAudioConverterPropertyCalculateInputBufferSize = 'cibs', + kAudioConverterPropertyCalculateOutputBufferSize = 'cobs', + kAudioConverterPropertyInputCodecParameters = 'icdp', + kAudioConverterPropertyOutputCodecParameters = 'ocdp', + kAudioConverterSampleRateConverterAlgorithm = 'srci', + kAudioConverterSampleRateConverterComplexity = 'srca', + kAudioConverterSampleRateConverterQuality = 'srcq', + kAudioConverterSampleRateConverterInitialPhase = 'srcp', + kAudioConverterCodecQuality = 'cdqu', + kAudioConverterPrimeMethod = 'prmm', + kAudioConverterPrimeInfo = 'prim', + kAudioConverterChannelMap = 'chmp', + kAudioConverterDecompressionMagicCookie = 'dmgc', + kAudioConverterCompressionMagicCookie = 'cmgc', + kAudioConverterEncodeBitRate = 'brat', + kAudioConverterEncodeAdjustableSampleRate = 'ajsr', + kAudioConverterInputChannelLayout = 'icl ', + kAudioConverterOutputChannelLayout = 'ocl ', + kAudioConverterApplicableEncodeBitRates = 'aebr', + kAudioConverterAvailableEncodeBitRates = 'vebr', + kAudioConverterApplicableEncodeSampleRates = 'aesr', + kAudioConverterAvailableEncodeSampleRates = 'vesr', + kAudioConverterAvailableEncodeChannelLayoutTags = 'aecl', + kAudioConverterCurrentOutputStreamDescription = 'acod', + kAudioConverterCurrentInputStreamDescription = 'acid', + kAudioConverterPropertySettings = 'acps', + kAudioConverterPropertyBitDepthHint = 'acbd', + kAudioConverterPropertyFormatList = 'flst', +}; + +enum { + kAudioConverterQuality_Max = 0x7F, + kAudioConverterQuality_High = 0x60, + kAudioConverterQuality_Medium = 0x40, + kAudioConverterQuality_Low = 0x20, + kAudioConverterQuality_Min = 0 +}; + +enum { + kAudio_UnimplementedError = -4, + kAudio_FileNotFoundError = -43, + kAudio_FilePermissionError = -54, + kAudio_TooManyFilesOpenError = -42, + kAudio_BadFilePathError = '!pth', // 0x21707468, 561017960 + kAudio_ParamError = -50, + kAudio_MemFullError = -108, + + kAudioConverterErr_FormatNotSupported = 'fmt?', + kAudioConverterErr_OperationNotSupported = 0x6F703F3F, + // 'op??', integer used because of trigraph + kAudioConverterErr_PropertyNotSupported = 'prop', + kAudioConverterErr_InvalidInputSize = 'insz', + kAudioConverterErr_InvalidOutputSize = 'otsz', + // e.g. byte size is not a multiple of the frame size + kAudioConverterErr_UnspecifiedError = 'what', + kAudioConverterErr_BadPropertySizeError = '!siz', + kAudioConverterErr_RequiresPacketDescriptionsError = '!pkd', + kAudioConverterErr_InputSampleRateOutOfRange = '!isr', + kAudioConverterErr_OutputSampleRateOutOfRange = '!osr' +}; + +typedef OSStatus (*AudioConverterNew_t) ( + const AudioStreamBasicDescription *inSourceFormat, + const AudioStreamBasicDescription *inDestinationFormat, + AudioConverterRef *outAudioConverter +); + +typedef OSStatus (*AudioConverterDispose_t) ( + AudioConverterRef inAudioConverter +); + +typedef OSStatus (*AudioConverterReset_t) ( + AudioConverterRef inAudioConverter +); + +typedef OSStatus (*AudioConverterGetProperty_t) ( + AudioConverterRef inAudioConverter, + AudioConverterPropertyID inPropertyID, + UInt32 *ioPropertyDataSize, + void *outPropertyData +); + +typedef OSStatus (*AudioConverterGetPropertyInfo_t) ( + AudioConverterRef inAudioConverter, + AudioConverterPropertyID inPropertyID, + UInt32 *outSize, + Boolean *outWritable +); + +typedef OSStatus (*AudioConverterSetProperty_t) ( + AudioConverterRef inAudioConverter, + AudioConverterPropertyID inPropertyID, + UInt32 inPropertyDataSize, + const void *inPropertyData +); + +typedef OSStatus (*AudioConverterFillComplexBuffer_t) ( + AudioConverterRef inAudioConverter, + AudioConverterComplexInputDataProc inInputDataProc, + void *inInputDataProcUserData, + UInt32 *ioOutputDataPacketSize, + AudioBufferList *outOutputData, + AudioStreamPacketDescription *outPacketDescription +); + +typedef OSStatus (*AudioFormatGetProperty_t) ( + AudioFormatPropertyID inPropertyID, + UInt32 inSpecifierSize, + const void *inSpecifier, + UInt32 *ioPropertyDataSize, + void *outPropertyData +); + +static AudioConverterNew_t AudioConverterNew = NULL; +static AudioConverterDispose_t AudioConverterDispose = NULL; +static AudioConverterReset_t AudioConverterReset = NULL; +static AudioConverterGetProperty_t AudioConverterGetProperty = NULL; +static AudioConverterGetPropertyInfo_t AudioConverterGetPropertyInfo = NULL; +static AudioConverterSetProperty_t AudioConverterSetProperty = NULL; +static AudioConverterFillComplexBuffer_t AudioConverterFillComplexBuffer = NULL; +static AudioFormatGetProperty_t AudioFormatGetProperty = NULL; + +static HMODULE audio_toolbox = NULL; + +static void release_lib(void) +{ +#define RELEASE_LIB(x) if (x) { \ + FreeLibrary(x); \ + x = NULL; \ + } + + RELEASE_LIB(audio_toolbox); +#undef RELEASE_LIB +} + +static bool load_lib(void) +{ + PWSTR common_path; + if (SHGetKnownFolderPath(&FOLDERID_ProgramFilesCommon, 0, NULL, + &common_path) != S_OK) { + CA_LOG(LOG_WARNING, "Could not retrieve common files path"); + return false; + } + + struct dstr path = { 0 }; + dstr_printf(&path, "%S\\Apple\\Apple Application Support", common_path); + CoTaskMemFree(common_path); + + wchar_t *w_path = dstr_to_wcs(&path); + dstr_free(&path); + + SetDllDirectory(w_path); + bfree(w_path); + +#define LOAD_LIB(x, n) x = LoadLibrary(TEXT(n)); \ + if (!x) \ + CA_LOG(LOG_WARNING, "Failed loading library '" n "'"); + + LOAD_LIB(audio_toolbox, "CoreAudioToolbox.dll"); +#undef LOAD_LIB + + SetDllDirectory(NULL); + + if (audio_toolbox) + return true; + + release_lib(); + return false; +} + +static void unload_core_audio(void) +{ + AudioConverterNew = NULL; + AudioConverterDispose = NULL; + AudioConverterReset = NULL; + AudioConverterGetProperty = NULL; + AudioConverterGetPropertyInfo = NULL; + AudioConverterSetProperty = NULL; + AudioConverterFillComplexBuffer = NULL; + AudioFormatGetProperty = NULL; + + release_lib(); +} + +static bool load_core_audio(void) +{ + if (!load_lib()) + return false; + +#define LOAD_SYM_FROM_LIB(sym, lib, dll) \ + if (!(sym = (sym ## _t)GetProcAddress(lib, #sym))) { \ + DWORD err = GetLastError(); \ + CA_LOG(LOG_ERROR, "Couldn't load " #sym " from " \ + dll ": %lu (0x%lx)", err, err); \ + goto unload_everything; \ + } + +#define LOAD_SYM(sym) \ + LOAD_SYM_FROM_LIB(sym, audio_toolbox, "CoreAudioToolbox.dll") + LOAD_SYM(AudioConverterNew); + LOAD_SYM(AudioConverterDispose); + LOAD_SYM(AudioConverterReset); + LOAD_SYM(AudioConverterGetProperty); + LOAD_SYM(AudioConverterGetPropertyInfo); + LOAD_SYM(AudioConverterSetProperty); + LOAD_SYM(AudioConverterFillComplexBuffer); + LOAD_SYM(AudioFormatGetProperty); +#undef LOAD_SYM + + return true; + +unload_everything: + unload_core_audio(); + + return false; +}