123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- #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 UInt32 AudioChannelLabel;
- typedef UInt32 AudioChannelLayoutTag;
- struct AudioChannelDescription {
- AudioChannelLabel mChannelLabel;
- UInt32 mChannelFlags;
- float mCoordinates[3];
- };
- typedef struct AudioChannelDescription AudioChannelDescription;
- struct AudioChannelLayout {
- AudioChannelLayoutTag mChannelLayoutTag;
- UInt32 mChannelBitmap;
- UInt32 mNumberChannelDescriptions;
- AudioChannelDescription mChannelDescriptions[kVariableLengthArray];
- };
- typedef struct AudioChannelLayout AudioChannelLayout;
- struct AudioConverterPrimeInfo {
- UInt32 leadingFrames;
- UInt32 trailingFrames;
- };
- typedef struct AudioConverterPrimeInfo AudioConverterPrimeInfo;
- 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_ELD = 'aace',
- kAudioFormatMPEG4AAC_ELD_SBR = 'aacf',
- kAudioFormatMPEG4AAC_ELD_V2 = 'aacg',
- kAudioFormatMPEG4AAC_HE_V2 = 'aacp',
- kAudioFormatMPEG4AAC_Spatial = 'aacs',
- kAudioFormatAMR = 'samr',
- kAudioFormatAudible = 'AUDB',
- kAudioFormatiLBC = 'ilbc',
- kAudioFormatDVIIntelIMA = 0x6D730011,
- kAudioFormatMicrosoftGSM = 0x6D730031,
- kAudioFormatAES3 = 'aes3',
- };
- 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);
- typedef OSStatus (*AudioFormatGetPropertyInfo_t)(AudioFormatPropertyID inPropertyID, UInt32 inSpecifierSize,
- const void *inSpecifier, UInt32 *outPropertyDataSize);
- 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 AudioFormatGetPropertyInfo_t AudioFormatGetPropertyInfo = NULL;
- static HMODULE audio_toolbox = NULL;
- static void release_lib(void)
- {
- if (audio_toolbox) {
- FreeLibrary(audio_toolbox);
- audio_toolbox = NULL;
- }
- }
- static bool load_from_shell_path(REFKNOWNFOLDERID rfid, const wchar_t *subpath)
- {
- wchar_t *sh_path;
- if (SHGetKnownFolderPath(rfid, 0, NULL, &sh_path) != S_OK) {
- CA_LOG(LOG_WARNING, "Could not retrieve shell path");
- return false;
- }
- wchar_t path[MAX_PATH];
- _snwprintf(path, MAX_PATH, L"%s\\%s", sh_path, subpath);
- CoTaskMemFree(sh_path);
- SetDllDirectory(path);
- audio_toolbox = LoadLibraryW(L"CoreAudioToolbox.dll");
- SetDllDirectory(nullptr);
- return !!audio_toolbox;
- }
- static bool load_lib(void)
- {
- /* -------------------------------------------- */
- /* attempt to load from path */
- audio_toolbox = LoadLibraryW(L"CoreAudioToolbox.dll");
- if (!!audio_toolbox)
- return true;
- /* -------------------------------------------- */
- /* attempt to load from known install locations */
- struct path_list_t {
- REFKNOWNFOLDERID rfid;
- const wchar_t *subpath;
- };
- path_list_t path_list[] = {
- {FOLDERID_ProgramFilesCommon, L"Apple\\Apple Application Support"},
- {FOLDERID_ProgramFiles, L"iTunes"},
- };
- for (auto &val : path_list) {
- if (load_from_shell_path(val.rfid, val.subpath)) {
- return true;
- }
- }
- return false;
- }
- static void unload_core_audio(void)
- {
- AudioConverterNew = NULL;
- AudioConverterDispose = NULL;
- AudioConverterReset = NULL;
- AudioConverterGetProperty = NULL;
- AudioConverterGetPropertyInfo = NULL;
- AudioConverterSetProperty = NULL;
- AudioConverterFillComplexBuffer = NULL;
- AudioFormatGetProperty = NULL;
- AudioFormatGetPropertyInfo = NULL;
- release_lib();
- }
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable : 4706)
- #endif
- 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);
- LOAD_SYM(AudioFormatGetPropertyInfo);
- #undef LOAD_SYM
- return true;
- unload_everything:
- unload_core_audio();
- return false;
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
|