|
@@ -0,0 +1,459 @@
|
|
|
+#define NO_MIN_MAX 1
|
|
|
+#define WIN32_LEAN_AND_MEAN
|
|
|
+#include <windows.h>
|
|
|
+#include <ShlObj.h>
|
|
|
+
|
|
|
+#include <util/dstr.h>
|
|
|
+
|
|
|
+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;
|
|
|
+}
|