diff --git a/AudioUnitSDK.xcodeproj/project.pbxproj b/AudioUnitSDK.xcodeproj/project.pbxproj index c824daf..881d102 100644 --- a/AudioUnitSDK.xcodeproj/project.pbxproj +++ b/AudioUnitSDK.xcodeproj/project.pbxproj @@ -3,11 +3,11 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 394A97042576BF1700897571 /* AUMIDIUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 394A97032576BF1700897571 /* AUMIDIUtility.h */; }; + 394A97042576BF1700897571 /* AUMIDIUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = 394A97032576BF1700897571 /* AUMIDIUtility.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9100832E24DF0EB6003E57AE /* AUInputElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914EC75924D9181600725ABE /* AUInputElement.cpp */; }; 9100832F24DF0EE7003E57AE /* AUOutputElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914EC75824D9181600725ABE /* AUOutputElement.cpp */; }; 9100833024DF0F2C003E57AE /* AUBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914EC76224D9181600725ABE /* AUBase.cpp */; }; @@ -146,21 +146,22 @@ name = Frameworks; sourceTree = ""; }; - 9100837324E06B8F003E57AE /* Tools */ = { + 9100837324E06B8F003E57AE /* tools */ = { isa = PBXGroup; children = ( 9100837424E06BA7003E57AE /* build.sh */, ); - path = Tools; + path = tools; sourceTree = ""; }; 910C29C524D910D300B9116B = { isa = PBXGroup; children = ( - 9100837324E06B8F003E57AE /* Tools */, - 910C29D524D910FA00B9116B /* Source */, - 9100833624DF1C82003E57AE /* EmptyPlugIns */, - 91E93AC124E8962D00BF7289 /* Tests */, + B487F106284500520074F0B2 /* include */, + B487F108284500630074F0B2 /* src */, + 9100837324E06B8F003E57AE /* tools */, + B487F109284501700074F0B2 /* demos */, + 91E93AC124E8962D00BF7289 /* tests */, 910C29CF24D910D300B9116B /* Products */, 9100834024DF1EEB003E57AE /* Frameworks */, ); @@ -176,47 +177,78 @@ name = Products; sourceTree = ""; }; - 910C29D524D910FA00B9116B /* Source */ = { + 91E93AC124E8962D00BF7289 /* tests */ = { + isa = PBXGroup; + children = ( + 91E93AC224E8962D00BF7289 /* Tests.mm */, + 91E93AC424E8962D00BF7289 /* Info.plist */, + ); + path = tests; + sourceTree = ""; + }; + B487F106284500520074F0B2 /* include */ = { + isa = PBXGroup; + children = ( + B4888687282AC1D800521D1A /* AudioUnitSDK */, + ); + path = include; + sourceTree = ""; + }; + B487F108284500630074F0B2 /* src */ = { + isa = PBXGroup; + children = ( + B48885E4282A6D6D00521D1A /* AudioUnitSDK */, + ); + path = src; + sourceTree = ""; + }; + B487F109284501700074F0B2 /* demos */ = { + isa = PBXGroup; + children = ( + 9100833624DF1C82003E57AE /* EmptyPlugIns */, + ); + path = demos; + sourceTree = ""; + }; + B48885E4282A6D6D00521D1A /* AudioUnitSDK */ = { isa = PBXGroup; children = ( 914EC76224D9181600725ABE /* AUBase.cpp */, - 914EC76124D9181600725ABE /* AUBase.h */, 914EC77524D920CC00725ABE /* AUBuffer.cpp */, - 914EC77624D920CC00725ABE /* AUBuffer.h */, 919B0CC42555C72000C59BDC /* AUBufferAllocator.cpp */, - 914EC77A24D9225800725ABE /* AudioUnitSDK.h */, 9100834F24DF3245003E57AE /* AUEffectBase.cpp */, - 9100834924DF3245003E57AE /* AUEffectBase.h */, 914EC75924D9181600725ABE /* AUInputElement.cpp */, - 914EC76024D9181600725ABE /* AUInputElement.h */, 9100834E24DF3245003E57AE /* AUMIDIBase.cpp */, - 9100834424DF3245003E57AE /* AUMIDIBase.h */, 9100834C24DF3245003E57AE /* AUMIDIEffectBase.cpp */, - 9100834524DF3245003E57AE /* AUMIDIEffectBase.h */, - 394A97032576BF1700897571 /* AUMIDIUtility.h */, 914EC75824D9181600725ABE /* AUOutputElement.cpp */, - 914EC75B24D9181600725ABE /* AUOutputElement.h */, 914EC77324D91FFA00725ABE /* AUPlugInDispatch.cpp */, - 914EC75F24D9181600725ABE /* AUPlugInDispatch.h */, 914EC75D24D9181600725ABE /* AUScopeElement.cpp */, - 914EC75C24D9181600725ABE /* AUScopeElement.h */, - 9100835224DF3DAC003E57AE /* AUSilentTimeout.h */, - 9100832D24DF0C5B003E57AE /* AUUtility.h */, 910C29D724D9115100B9116B /* ComponentBase.cpp */, - 910C29D624D9115100B9116B /* ComponentBase.h */, 9100834624DF3245003E57AE /* MusicDeviceBase.cpp */, - 9100834B24DF3245003E57AE /* MusicDeviceBase.h */, ); - path = Source; + path = AudioUnitSDK; sourceTree = ""; }; - 91E93AC124E8962D00BF7289 /* Tests */ = { + B4888687282AC1D800521D1A /* AudioUnitSDK */ = { isa = PBXGroup; children = ( - 91E93AC224E8962D00BF7289 /* Tests.mm */, - 91E93AC424E8962D00BF7289 /* Info.plist */, + 914EC76124D9181600725ABE /* AUBase.h */, + 914EC77624D920CC00725ABE /* AUBuffer.h */, + 914EC77A24D9225800725ABE /* AudioUnitSDK.h */, + 9100834924DF3245003E57AE /* AUEffectBase.h */, + 914EC76024D9181600725ABE /* AUInputElement.h */, + 9100834424DF3245003E57AE /* AUMIDIBase.h */, + 9100834524DF3245003E57AE /* AUMIDIEffectBase.h */, + 394A97032576BF1700897571 /* AUMIDIUtility.h */, + 914EC75B24D9181600725ABE /* AUOutputElement.h */, + 914EC75F24D9181600725ABE /* AUPlugInDispatch.h */, + 914EC75C24D9181600725ABE /* AUScopeElement.h */, + 9100835224DF3DAC003E57AE /* AUSilentTimeout.h */, + 9100832D24DF0C5B003E57AE /* AUUtility.h */, + 910C29D624D9115100B9116B /* ComponentBase.h */, + 9100834B24DF3245003E57AE /* MusicDeviceBase.h */, ); - path = Tests; + path = AudioUnitSDK; sourceTree = ""; }; /* End PBXGroup section */ @@ -360,6 +392,7 @@ /* Begin PBXShellScriptBuildPhase section */ 9100837924E1A54B003E57AE /* Install clang-format hook */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -436,12 +469,14 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = S5585LNN66; - INFOPLIST_FILE = EmptyPlugIns/Info.plist; + DEVELOPMENT_TEAM = ""; + HEADER_SEARCH_PATHS = include; + INFOPLIST_FILE = demos/EmptyPlugIns/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; PRODUCT_BUNDLE_IDENTIFIER = com.apple.audio.EmptyPlugIns; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + USE_HEADERMAP = NO; WRAPPER_EXTENSION = bundle; }; name = Debug; @@ -451,12 +486,14 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = S5585LNN66; - INFOPLIST_FILE = EmptyPlugIns/Info.plist; + DEVELOPMENT_TEAM = ""; + HEADER_SEARCH_PATHS = include; + INFOPLIST_FILE = demos/EmptyPlugIns/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; PRODUCT_BUNDLE_IDENTIFIER = com.apple.audio.EmptyPlugIns; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + USE_HEADERMAP = NO; WRAPPER_EXTENSION = bundle; }; name = Release; @@ -514,6 +551,7 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; LLVM_LTO = NO; MACOSX_DEPLOYMENT_TARGET = 11.0; @@ -521,9 +559,14 @@ MTL_FAST_MATH = YES; SDKROOT = macosx; SUPPORTED_PLATFORMS = "macosx iphoneos appletvos watchos"; + SUPPORTS_MACCATALYST = YES; WARNING_CFLAGS = ( "-Wall", "-Wextra", + "-Wimport-preprocessor-directive-pedantic", + "-Wunreachable-code-break", + "-Wunreachable-code-return", + "-Wvla", ); }; name = Debug; @@ -575,6 +618,7 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; LLVM_LTO = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; @@ -582,9 +626,14 @@ MTL_FAST_MATH = YES; SDKROOT = macosx; SUPPORTED_PLATFORMS = "macosx iphoneos appletvos watchos"; + SUPPORTS_MACCATALYST = YES; WARNING_CFLAGS = ( "-Wall", "-Wextra", + "-Wimport-preprocessor-directive-pedantic", + "-Wunreachable-code-break", + "-Wunreachable-code-return", + "-Wvla", ); }; name = Release; @@ -595,9 +644,12 @@ CODE_SIGN_STYLE = Automatic; EXECUTABLE_PREFIX = lib; GCC_SYMBOLS_PRIVATE_EXTERN = YES; + HEADER_SEARCH_PATHS = include; OTHER_CFLAGS = "-fvisibility=hidden"; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/AudioUnitSDK; + SUPPORTS_MACCATALYST = YES; + USE_HEADERMAP = NO; }; name = Debug; }; @@ -607,9 +659,12 @@ CODE_SIGN_STYLE = Automatic; EXECUTABLE_PREFIX = lib; GCC_SYMBOLS_PRIVATE_EXTERN = YES; + HEADER_SEARCH_PATHS = include; OTHER_CFLAGS = "-fvisibility=hidden"; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/AudioUnitSDK; + SUPPORTS_MACCATALYST = YES; + USE_HEADERMAP = NO; }; name = Release; }; @@ -617,7 +672,8 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Tests/Info.plist; + HEADER_SEARCH_PATHS = include; + INFOPLIST_FILE = tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -625,6 +681,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.audio.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + USE_HEADERMAP = NO; }; name = Debug; }; @@ -632,7 +689,8 @@ isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Tests/Info.plist; + HEADER_SEARCH_PATHS = include; + INFOPLIST_FILE = tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -640,6 +698,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.apple.audio.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + USE_HEADERMAP = NO; }; name = Release; }; diff --git a/Tools/FindUB.sh b/Tools/FindUB.sh new file mode 100755 index 0000000..bdc22ab --- /dev/null +++ b/Tools/FindUB.sh @@ -0,0 +1,17 @@ +#! /bin/sh + +# Certain types can only safely be accessed through pointers, not C++ references. +# This is due to their being variably-sized. +# Find code that uses references to the problem types. + +SearchDir="$1" + +if [ -z "$SearchDir" ] ; then + SearchDir=. +fi + +egrep -r "(AURenderEvent|MIDI(Packet|Event)List)\s*(const\s*)?&" "$SearchDir" +if [ $? -eq 0 ]; then + echo "error: forming reference to a type which causes UB " + exit 1 +fi diff --git a/EmptyPlugIns/EmptyPlugIns.cpp b/demos/EmptyPlugIns/EmptyPlugIns.cpp similarity index 82% rename from EmptyPlugIns/EmptyPlugIns.cpp rename to demos/EmptyPlugIns/EmptyPlugIns.cpp index acef229..87ccbc5 100644 --- a/EmptyPlugIns/EmptyPlugIns.cpp +++ b/demos/EmptyPlugIns/EmptyPlugIns.cpp @@ -3,8 +3,8 @@ // EmptyPlugIns // -#include "AUEffectBase.h" -#include "MusicDeviceBase.h" +#include +#include // ------------------------------------------------------------------------------------------------- @@ -14,10 +14,7 @@ class AUBase_Derived : public ausdk::AUBase { public: explicit AUBase_Derived(AudioComponentInstance ci) : Base{ ci, 1, 1 } {} - bool StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) override - { - return true; - } + bool StreamFormatWritable(AudioUnitScope, AudioUnitElement) override { return true; } bool CanScheduleParameters() const override { return false; } }; @@ -43,10 +40,7 @@ class MusicDeviceBase_Derived : public ausdk::MusicDeviceBase { public: explicit MusicDeviceBase_Derived(AudioComponentInstance ci) : Base{ ci, 0, 1 } {} - bool StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) override - { - return true; - } + bool StreamFormatWritable(AudioUnitScope, AudioUnitElement) override { return true; } bool CanScheduleParameters() const override { return false; } }; diff --git a/EmptyPlugIns/Info.plist b/demos/EmptyPlugIns/Info.plist similarity index 100% rename from EmptyPlugIns/Info.plist rename to demos/EmptyPlugIns/Info.plist diff --git a/hooks/pre-commit b/hooks/pre-commit index 237a86f..c30d3dc 100755 --- a/hooks/pre-commit +++ b/hooks/pre-commit @@ -1,4 +1,4 @@ -#! /bin/sh +#! /bin/zsh # This pre-commit hook uses clang-format to format the staged changes. if ! git rev-parse --verify HEAD >/dev/null 2>&1 @@ -9,19 +9,12 @@ fi set -e -# do the formatting REPO_ROOT=$(git rev-parse --show-toplevel) DIFF_ARGS="--name-only --diff-filter=ACMRT" -while read -r FILE +git diff-index ${=DIFF_ARGS} --cached HEAD | grep -E "\.(h|hpp|c|cpp|m|mm)$" | while read -r FILE do - # an empty line read is possible when the input is empty - if [[ -z $FILE ]] - then - continue - fi - FILE_PATH="${REPO_ROOT}"/"${FILE}" - if [[ `git diff $DIFF_ARGS "${FILE_PATH}"` == $FILE ]] + if [[ `git diff ${=DIFF_ARGS} "${FILE_PATH}"` == $FILE ]] then echo -e "\xF0\x9F\x94\xA5 \xE2\x98\xA0 \xF0\x9F\x94\xA5 WARNING: creating a stash for file due to unstaged changes: ${FILE}" # format before stashing to avoid a merge conflict when applying the stash after commit @@ -31,4 +24,4 @@ do xcrun clang-format -i "${FILE_PATH}" git add "${FILE_PATH}" -done <<< "`git diff-index $DIFF_ARGS --cached HEAD | grep -E "\.(h|hpp|c|cpp|m|mm)$"`" +done diff --git a/Source/AUBase.h b/include/AudioUnitSDK/AUBase.h similarity index 96% rename from Source/AUBase.h rename to include/AudioUnitSDK/AUBase.h index 679eca7..02f0d3d 100644 --- a/Source/AUBase.h +++ b/include/AudioUnitSDK/AUBase.h @@ -7,13 +7,13 @@ #define AudioUnitSDK_AUBase_h // module -#include "AUBuffer.h" -#include "AUInputElement.h" -#include "AUMIDIUtility.h" -#include "AUOutputElement.h" -#include "AUPlugInDispatch.h" -#include "AUScopeElement.h" -#include "AUUtility.h" +#include +#include +#include +#include +#include +#include +#include // OS #include @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -83,7 +82,7 @@ class AUBase : public ComponentBase { void DoCleanup(); // Overrides to this method can assume that they will only be called exactly once - // when transitioning from an uninitialized state. + // when transitioning from an initialized state to an uninitialized state. virtual void Cleanup(); virtual OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement); @@ -268,7 +267,7 @@ class AUBase : public ComponentBase { if (inScope >= kNumScopes) { AUScope* const scope = GetScopeExtended(inScope); - AUSDK_ThrowQuietIf(scope == nullptr, kAudioUnitErr_InvalidScope); + ThrowQuietIf(scope == nullptr, kAudioUnitErr_InvalidScope); return *scope; } return mScopes[inScope]; // NOLINT @@ -372,8 +371,8 @@ class AUBase : public ComponentBase { OSStatus CallHostBeatAndTempo(Float64* outCurrentBeat, Float64* outCurrentTempo) const { return (mHostCallbackInfo.beatAndTempoProc != nullptr - ? (*mHostCallbackInfo.beatAndTempoProc)(mHostCallbackInfo.hostUserData, - outCurrentBeat, outCurrentTempo) + ? (*mHostCallbackInfo.beatAndTempoProc)( + mHostCallbackInfo.hostUserData, outCurrentBeat, outCurrentTempo) : -1); } @@ -399,7 +398,7 @@ class AUBase : public ComponentBase { : -1); } - [[nodiscard]] const char* GetLoggingString(); + [[nodiscard]] const char* GetLoggingString() const noexcept; AUMutex* GetMutex() noexcept { return mAUMutex; } // The caller of SetMutex is responsible for the managing the lifetime of the @@ -437,7 +436,7 @@ class AUBase : public ComponentBase { #if AUSDK_MIDI2_AVAILABLE virtual OSStatus MIDIEventList( - UInt32 /*inOffsetSampleFrame*/, const MIDIEventList& /*eventList*/) + UInt32 /*inOffsetSampleFrame*/, const MIDIEventList* /*eventList*/) { return kAudio_UnimplementedError; } @@ -560,6 +559,8 @@ class AUBase : public ComponentBase { bool HasIcon(); + [[nodiscard]] std::string CreateLoggingString() const; + protected: //. Returns size. outLayoutPtr may be null if querying only for size. virtual UInt32 GetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, @@ -647,6 +648,10 @@ class AUBase : public ComponentBase { void add(const RenderCallback& rc) { const std::lock_guard guard{ mLock }; + const auto iter = std::find(mImpl.begin(), mImpl.end(), rc); + if (iter != mImpl.end()) { + return; + } mImpl.emplace_back(rc); } @@ -699,16 +704,18 @@ class AUBase : public ComponentBase { AudioTimeStamp mCurrentRenderTime{}; UInt32 mMaxFramesPerSlice{ 0 }; OSStatus mLastRenderError{ noErr }; +#ifndef AUSDK_NO_LOGGING + const double mHostTimeFrequency{ + HostTime::Frequency() + }; // cache because there is calculation cost +#endif AUPreset mCurrentPreset{ -1, nullptr }; bool mUsesFixedBlockSize{ false }; -#if AUSDK_MIDI2_AVAILABLE - std::optional mHostMIDIProtocol; -#endif ParameterEventList mParamEventList; PropertyListeners mPropertyListeners; bool mBuffersAllocated{ false }; - std::string mLogString; + const std::string mLogString; Owned mNickName; /*! @var mAUMutex diff --git a/Source/AUBuffer.h b/include/AudioUnitSDK/AUBuffer.h similarity index 92% rename from Source/AUBuffer.h rename to include/AudioUnitSDK/AUBuffer.h index 1e40cf4..df882c9 100644 --- a/Source/AUBuffer.h +++ b/include/AudioUnitSDK/AUBuffer.h @@ -5,7 +5,7 @@ #ifndef AudioUnitSDK_AUBuffer_h #define AudioUnitSDK_AUBuffer_h -#include "AUUtility.h" +#include #include @@ -83,7 +83,7 @@ class AUBufferList { AudioBufferList& SetBufferList(const AudioBufferList& abl) { - AUSDK_ThrowIf(mAllocatedStreams < abl.mNumberBuffers, -1); + ausdk::ThrowExceptionIf(mAllocatedStreams < abl.mNumberBuffers, -1); mPtrState = EPtrState::ToExternalMemory; auto& myabl = mBuffers->mAudioBufferList; memcpy(&myabl, &abl, @@ -96,7 +96,8 @@ class AUBufferList { void SetBuffer(UInt32 index, const AudioBuffer& ab) { auto& myabl = mBuffers->mAudioBufferList; - AUSDK_ThrowIf(mPtrState == EPtrState::Invalid || index >= myabl.mNumberBuffers, -1); + ausdk::ThrowExceptionIf( + mPtrState == EPtrState::Invalid || index >= myabl.mNumberBuffers, -1); mPtrState = EPtrState::ToExternalMemory; myabl.mBuffers[index] = ab; // NOLINT } @@ -105,13 +106,13 @@ class AUBufferList { [[nodiscard]] AudioBufferList& GetBufferList() const { - AUSDK_ThrowIf(mPtrState == EPtrState::Invalid, -1); + ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1); return mBuffers->mAudioBufferList; } void CopyBufferListTo(AudioBufferList& abl) const { - AUSDK_ThrowIf(mPtrState == EPtrState::Invalid, -1); + ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1); memcpy(&abl, &mBuffers->mAudioBufferList, static_cast( reinterpret_cast(&abl.mBuffers[abl.mNumberBuffers]) - // NOLINT @@ -120,7 +121,7 @@ class AUBufferList { void CopyBufferContentsTo(AudioBufferList& destabl) const { - AUSDK_ThrowIf(mPtrState == EPtrState::Invalid, -1); + ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1); const auto& srcabl = mBuffers->mAudioBufferList; const AudioBuffer* srcbuf = srcabl.mBuffers; // NOLINT AudioBuffer* destbuf = destabl.mBuffers; // NOLINT diff --git a/Source/AUEffectBase.h b/include/AudioUnitSDK/AUEffectBase.h similarity index 98% rename from Source/AUEffectBase.h rename to include/AudioUnitSDK/AUEffectBase.h index 1f68358..55104b6 100644 --- a/Source/AUEffectBase.h +++ b/include/AudioUnitSDK/AUEffectBase.h @@ -5,8 +5,8 @@ #ifndef AudioUnitSDK_AUEffectBase_h #define AudioUnitSDK_AUEffectBase_h -#include "AUBase.h" -#include "AUSilentTimeout.h" +#include +#include #include diff --git a/Source/AUInputElement.h b/include/AudioUnitSDK/AUInputElement.h similarity index 88% rename from Source/AUInputElement.h rename to include/AudioUnitSDK/AUInputElement.h index a12d39c..d25cafa 100644 --- a/Source/AUInputElement.h +++ b/include/AudioUnitSDK/AUInputElement.h @@ -5,8 +5,8 @@ #ifndef AudioUnitSDK_AUInputElement_h #define AudioUnitSDK_AUInputElement_h -#include "AUBuffer.h" -#include "AUScopeElement.h" +#include +#include namespace ausdk { @@ -75,6 +75,14 @@ inline OSStatus AUInputElement::PullInputWithBufferList(AudioUnitRenderActionFla return kAudioUnitErr_NoConnection; } +#if !TARGET_OS_IPHONE || DEBUG + if (theResult == noErr) { // if there's already an error, there's no point (and maybe some harm) + // in validating. + if (ABL::IsBogusAudioBufferList(inBufferList) & 1) { + return kAudioUnitErr_InvalidPropertyValue; + } + } +#endif return theResult; } diff --git a/Source/AUMIDIBase.h b/include/AudioUnitSDK/AUMIDIBase.h similarity index 96% rename from Source/AUMIDIBase.h rename to include/AudioUnitSDK/AUMIDIBase.h index c916fe7..6a8923c 100644 --- a/Source/AUMIDIBase.h +++ b/include/AudioUnitSDK/AUMIDIBase.h @@ -5,7 +5,7 @@ #ifndef AudioUnitSDK_AUMIDIBase_h #define AudioUnitSDK_AUMIDIBase_h -#include "AUBase.h" +#include #ifndef AUSDK_HAVE_XML_NAMES @@ -16,8 +16,6 @@ #define AUSDK_HAVE_MIDI_MAPPING TARGET_OS_OSX // NOLINT(cppcoreguidelines-macro-usage) #endif -struct MIDIPacketList; - namespace ausdk { #if AUSDK_HAVE_MIDI_MAPPING @@ -79,14 +77,12 @@ class AUMIDIBase { #if AUSDK_MIDI2_AVAILABLE virtual OSStatus MIDIEventList( - UInt32 /*inOffsetSampleFrame*/, const MIDIEventList& /*eventList*/) + UInt32 /*inOffsetSampleFrame*/, const MIDIEventList* /*eventList*/) { return kAudio_UnimplementedError; } #endif - OSStatus HandleMIDIPacketList(const MIDIPacketList& pktlist); - virtual OSStatus SysEx(const UInt8* inData, UInt32 inLength); virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, diff --git a/Source/AUMIDIEffectBase.h b/include/AudioUnitSDK/AUMIDIEffectBase.h similarity index 94% rename from Source/AUMIDIEffectBase.h rename to include/AudioUnitSDK/AUMIDIEffectBase.h index a2a2814..90e1f5b 100644 --- a/Source/AUMIDIEffectBase.h +++ b/include/AudioUnitSDK/AUMIDIEffectBase.h @@ -5,8 +5,8 @@ #ifndef AudioUnitSDK_AUMIDIEffectBase_h #define AudioUnitSDK_AUMIDIEffectBase_h -#include "AUEffectBase.h" -#include "AUMIDIBase.h" +#include +#include namespace ausdk { diff --git a/Source/AUMIDIUtility.h b/include/AudioUnitSDK/AUMIDIUtility.h similarity index 77% rename from Source/AUMIDIUtility.h rename to include/AudioUnitSDK/AUMIDIUtility.h index e678a45..9dee84b 100644 --- a/Source/AUMIDIUtility.h +++ b/include/AudioUnitSDK/AUMIDIUtility.h @@ -6,13 +6,15 @@ #define AudioUnitSDK_AUMIDIUtility_h // OS +#if defined __has_include && __has_include() #include +#endif #if defined(__MAC_12_0) || defined(__IPHONE_15_0) #define AUSDK_MIDI2_AVAILABLE 1 #endif #if AUSDK_MIDI2_AVAILABLE -#import +#include #endif #endif // AudioUnitSDK_AUMIDIUtility_h diff --git a/Source/AUOutputElement.h b/include/AudioUnitSDK/AUOutputElement.h similarity index 91% rename from Source/AUOutputElement.h rename to include/AudioUnitSDK/AUOutputElement.h index 716f0f1..6419d84 100644 --- a/Source/AUOutputElement.h +++ b/include/AudioUnitSDK/AUOutputElement.h @@ -5,8 +5,8 @@ #ifndef AudioUnitSDK_AUOutputElement_h #define AudioUnitSDK_AUOutputElement_h -#include "AUBuffer.h" -#include "AUScopeElement.h" +#include +#include namespace ausdk { diff --git a/Source/AUPlugInDispatch.h b/include/AudioUnitSDK/AUPlugInDispatch.h similarity index 98% rename from Source/AUPlugInDispatch.h rename to include/AudioUnitSDK/AUPlugInDispatch.h index b185747..3f9c69a 100644 --- a/Source/AUPlugInDispatch.h +++ b/include/AudioUnitSDK/AUPlugInDispatch.h @@ -5,7 +5,7 @@ #ifndef AudioUnitSDK_AUPlugInDispatch_h #define AudioUnitSDK_AUPlugInDispatch_h -#include "ComponentBase.h" +#include namespace ausdk { diff --git a/Source/AUScopeElement.h b/include/AudioUnitSDK/AUScopeElement.h similarity index 96% rename from Source/AUScopeElement.h rename to include/AudioUnitSDK/AUScopeElement.h index a3f25a3..0963110 100644 --- a/Source/AUScopeElement.h +++ b/include/AudioUnitSDK/AUScopeElement.h @@ -6,9 +6,9 @@ #define AudioUnitSDK_AUScopeElement_h // module -#include "AUBuffer.h" -#include "AUUtility.h" -#include "ComponentBase.h" +#include +#include +#include // OS #include @@ -257,7 +257,7 @@ class AUIOElement : public AUElement { if (mWillAllocate) { return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames); } - AUSDK_Throw(kAudioUnitErr_InvalidPropertyValue); + Throw(kAudioUnitErr_InvalidPropertyValue); } AudioBufferList& PrepareNullBuffer(UInt32 nFrames) @@ -398,21 +398,22 @@ class AUScope { [[nodiscard]] AUElement* SafeGetElement(UInt32 elementIndex) const { AUElement* const element = GetElement(elementIndex); - AUSDK_ThrowIf(element == nullptr, kAudioUnitErr_InvalidElement); + ausdk::ThrowExceptionIf(element == nullptr, kAudioUnitErr_InvalidElement); return element; } [[nodiscard]] AUIOElement* GetIOElement(UInt32 elementIndex) const { AUElement* const element = GetElement(elementIndex); AUIOElement* const ioel = element != nullptr ? element->AsIOElement() : nullptr; - AUSDK_ThrowIf(ioel == nullptr, kAudioUnitErr_InvalidElement); + ausdk::ThrowExceptionIf(ioel == nullptr, kAudioUnitErr_InvalidElement); return ioel; } [[nodiscard]] bool HasElementWithName() const; void AddElementNamesToDict(CFMutableDictionaryRef inNameDict) const; - [[nodiscard]] bool RestoreElementNames(CFDictionaryRef inNameDict) const; + [[nodiscard]] std::vector RestoreElementNames( + CFDictionaryRef inNameDict) const; [[nodiscard]] AudioUnitScope GetScope() const noexcept { return mScope; } diff --git a/Source/AUSilentTimeout.h b/include/AudioUnitSDK/AUSilentTimeout.h similarity index 95% rename from Source/AUSilentTimeout.h rename to include/AudioUnitSDK/AUSilentTimeout.h index e811f91..1e08303 100644 --- a/Source/AUSilentTimeout.h +++ b/include/AudioUnitSDK/AUSilentTimeout.h @@ -5,7 +5,7 @@ #ifndef AudioUnitSDK_AUSilentTimeout_h #define AudioUnitSDK_AUSilentTimeout_h -#include +#include // for UInt32 #include namespace ausdk { diff --git a/Source/AUUtility.h b/include/AudioUnitSDK/AUUtility.h similarity index 83% rename from Source/AUUtility.h rename to include/AudioUnitSDK/AUUtility.h index d68ff64..2c8816f 100644 --- a/Source/AUUtility.h +++ b/include/AudioUnitSDK/AUUtility.h @@ -6,10 +6,15 @@ #define AudioUnitSDK_AUUtility_h // OS +#if defined __has_include && __has_include() #include +#else +#include +#endif #include #include #include +#include // std #include @@ -39,38 +44,23 @@ #pragma mark Version #define AUSDK_VERSION_MAJOR 1 -#define AUSDK_VERSION_MINOR 0 +#define AUSDK_VERSION_MINOR 1 #define AUSDK_VERSION_PATCH 0 // ------------------------------------------------------------------------------------------------- #pragma mark - #pragma mark Error-handling macros -#define AUSDK_LogError(...) os_log_error(AUSDK_LOG_OBJECT, __VA_ARGS__) /* NOLINT macro */ - -#define AUSDK_ThrowIf(cond, err) /* NOLINT(cppcoreguidelines-macro-usage) */ \ - do { \ - if (cond) { \ - AUSDK_LogError("throwing %d", static_cast(err)); \ - throw ausdk::AUException{ err }; \ - } \ - } while (0) - -#define AUSDK_Throw(err) /* NOLINT(cppcoreguidelines-macro-usage) */ \ - do { \ - AUSDK_LogError("throwing %d", static_cast(err)); \ - throw ausdk::AUException{ err }; \ - } while (0) - -#define AUSDK_ThrowQuietIf(cond, err) /* NOLINT(cppcoreguidelines-macro-usage) */ \ - do { \ - if (cond) { \ - throw ausdk::AUException{ err }; \ - } \ - } while (0) - -#define AUSDK_ThrowQuiet(err) /* NOLINT(cppcoreguidelines-macro-usage) */ \ - throw ausdk::AUException { err } +#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; } \ @@ -112,6 +102,29 @@ class AUException : public std::runtime_error { const OSStatus mError; }; +inline void ThrowExceptionIf(bool condition, OSStatus err) +{ + if (condition) { + AUSDK_LogError("throwing %d", static_cast(err)); + throw AUException{ err }; + } +} + +[[noreturn]] inline void Throw(OSStatus err) +{ + AUSDK_LogError("throwing %d", static_cast(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 @@ -206,8 +219,9 @@ constexpr AudioStreamBasicDescription CreateCommonFloat32( AudioStreamBasicDescription asbd{}; asbd.mFormatID = kAudioFormatLinearPCM; - asbd.mFormatFlags = - kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; + asbd.mFormatFlags = kAudioFormatFlagIsFloat | + static_cast(kAudioFormatFlagsNativeEndian) | + kAudioFormatFlagIsPacked; asbd.mBitsPerChannel = 8 * sampleSize; // NOLINT magic number asbd.mChannelsPerFrame = numChannels; asbd.mFramesPerPacket = 1; @@ -356,45 +370,56 @@ class AUChannelLayout { // ------------------------------------------------------------------------------------------------- #pragma mark - -#pragma mark HostTime +#pragma mark AudioBufferList -/// Utility functions relating to Mach absolute time. -namespace HostTime { +/// Utility functions relating to AudioBufferList. +namespace ABL { -struct timebase_info { - timebase_info() - { - struct mach_timebase_info theTimeBaseInfo { - }; // NOLINT - mach_timebase_info(&theTimeBaseInfo); - // the frequency of that clock is: (sToNanosDenominator / sToNanosNumerator) * 10^9 - mFrequency = static_cast(theTimeBaseInfo.denom) / - static_cast(theTimeBaseInfo.numer) * 1.0e9; // NOLINT - mToNanosNumerator = theTimeBaseInfo.numer; - mToNanosDenominator = theTimeBaseInfo.denom; - mInverseFrequency = 1.0 / mFrequency; +// 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(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); +} - double mFrequency{}; ///< ticks per second - double mInverseFrequency{}; ///< seconds per tick - uint64_t mToNanosNumerator{}; ///< from mach_timebase_info.numer - uint64_t mToNanosDenominator{}; ///< mach_timebase_info.denom +} // namespace ABL - static const timebase_info& instance() - { - static timebase_info info; - return info; - } -}; +// ------------------------------------------------------------------------------------------------- +#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(); } +inline uint64_t Current() { return mach_absolute_time(); } /// Returns the frequency of the host timebase, in ticks per second. -inline double frequency() { return timebase_info::instance().mFrequency; } - -/// Returns the inverse frequency of the host timebase. -inline double inverse_frequency() { return timebase_info::instance().mInverseFrequency; } +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(timeBaseInfo.denom) / static_cast(timeBaseInfo.numer) * + 1.0e9; // NOLINT +} } // namespace HostTime diff --git a/Source/AudioUnitSDK.h b/include/AudioUnitSDK/AudioUnitSDK.h similarity index 100% rename from Source/AudioUnitSDK.h rename to include/AudioUnitSDK/AudioUnitSDK.h diff --git a/Source/ComponentBase.h b/include/AudioUnitSDK/ComponentBase.h similarity index 99% rename from Source/ComponentBase.h rename to include/AudioUnitSDK/ComponentBase.h index b0ed5df..ece9602 100644 --- a/Source/ComponentBase.h +++ b/include/AudioUnitSDK/ComponentBase.h @@ -5,9 +5,11 @@ #ifndef AudioUnitSDK_ComponentBase_h #define AudioUnitSDK_ComponentBase_h +// module +#include + // OS #include -#include // std #include diff --git a/Source/MusicDeviceBase.h b/include/AudioUnitSDK/MusicDeviceBase.h similarity index 95% rename from Source/MusicDeviceBase.h rename to include/AudioUnitSDK/MusicDeviceBase.h index 953bd1c..f4eb5f4 100644 --- a/Source/MusicDeviceBase.h +++ b/include/AudioUnitSDK/MusicDeviceBase.h @@ -5,7 +5,7 @@ #ifndef AudioUnitSDK_MusicDeviceBase_h #define AudioUnitSDK_MusicDeviceBase_h -#include "AUMIDIBase.h" +#include namespace ausdk { @@ -35,7 +35,7 @@ class MusicDeviceBase : public AUBase, public AUMIDIBase { #if AUSDK_MIDI2_AVAILABLE OSStatus MIDIEventList( - UInt32 inOffsetSampleFrame, const struct MIDIEventList& eventList) override + UInt32 inOffsetSampleFrame, const struct MIDIEventList* eventList) override { return AUMIDIBase::MIDIEventList(inOffsetSampleFrame, eventList); } diff --git a/readme.md b/readme.md index 07c81e7..87bb8b3 100644 --- a/readme.md +++ b/readme.md @@ -11,7 +11,7 @@ The AudioUnitSDK contains a set of base classes as well as utility sources requi ## Building the project 1. Open AudioUnitSDK.xcodeproj 2. Build the AudioUnitSDK target -3. Add headers from $(BUILT_PRODUCTS_DIR)/usr/local/include/AudioUnitSDK to your projects include path +3. Add the `include` folder to your projects Header Search Paths 4. Link libAudioUnitSDK.a to your project @@ -20,4 +20,16 @@ Alternatively, you can add the AudioUnitSDK source directly to your project and ## Supported Deployment Targets macOS (OS X) 10.9 / iOS 9.0 or later. +## Changelog + +### Version 1.1.0 + +The `Source` folder was split in two folders: `include` for public headers, and `src` for private source files. +Users building the AudioUnitSDK sources from within their Xcode project should update the source file locations and change the include path to `path/to/AudioUnitSDK/include`. +Include directives should be prefixed with AudioUnitSDK (i.e. `#include "AudioUnitSDK/AUBase.h"` instead of `#include "AUBase.h"`). + +### Version 1.0.0 + +Initial upload. + Copyright (C) 2021 Apple Inc. All rights reserved. \ No newline at end of file diff --git a/Source/AUBase.cpp b/src/AudioUnitSDK/AUBase.cpp similarity index 94% rename from Source/AUBase.cpp rename to src/AudioUnitSDK/AUBase.cpp index e2097a3..9b58f8e 100644 --- a/Source/AUBase.cpp +++ b/src/AudioUnitSDK/AUBase.cpp @@ -2,15 +2,16 @@ @file AudioUnitSDK/AUBase.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUBase.h" -#include "AUInputElement.h" -#include "AUOutputElement.h" +#include +#include +#include +#include + #include #include +#include #include -#include "AUUtility.h" - namespace ausdk { #if TARGET_OS_MAC && (TARGET_CPU_X86 || TARGET_CPU_X86_64) @@ -67,7 +68,6 @@ static CFStringRef kManufacturerString = nullptr; // NOLINT non-const global static CFStringRef kDataString = nullptr; // NOLINT non-const global static CFStringRef kNameString = nullptr; // NOLINT non-const global static CFStringRef kRenderQualityString = nullptr; // NOLINT non-const global -static CFStringRef kCPULoadString = nullptr; // NOLINT non-const global static CFStringRef kElementNameString = nullptr; // NOLINT non-const global static CFStringRef kPartString = nullptr; // NOLINT non-const global @@ -78,7 +78,8 @@ static constexpr auto kNoLastRenderedSampleTime = std::numeric_limits:: AUBase::AUBase(AudioComponentInstance inInstance, UInt32 numInputElements, UInt32 numOutputElements, UInt32 numGroupElements) : ComponentBase(inInstance), mInitNumInputEls(numInputElements), - mInitNumOutputEls(numOutputElements), mInitNumGroupEls(numGroupElements) + mInitNumOutputEls(numOutputElements), mInitNumGroupEls(numGroupElements), + mLogString(CreateLoggingString()) { ResetRenderTime(); @@ -91,7 +92,6 @@ AUBase::AUBase(AudioComponentInstance inInstance, UInt32 numInputElements, UInt3 kDataString = CFSTR(kAUPresetDataKey); // NOLINT kNameString = CFSTR(kAUPresetNameKey); // NOLINT kRenderQualityString = CFSTR(kAUPresetRenderQualityKey); // NOLINT - kCPULoadString = CFSTR(kAUPresetCPULoadKey); // NOLINT kElementNameString = CFSTR(kAUPresetElementNameKey); // NOLINT kPartString = CFSTR(kAUPresetPartKey); // NOLINT }); @@ -450,14 +450,6 @@ OSStatus AUBase::DispatchGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScop outWritable = true; break; -#if AUSDK_MIDI2_AVAILABLE - case kAudioUnitProperty_HostMIDIProtocol: - AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); - outDataSize = sizeof(MIDIProtocolID); - outWritable = true; - break; -#endif - default: result = GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); validateElement = false; @@ -658,16 +650,6 @@ OSStatus AUBase::DispatchGetProperty( } break; -#if AUSDK_MIDI2_AVAILABLE - case kAudioUnitProperty_HostMIDIProtocol: - if (const auto hostProtocol = mHostMIDIProtocol) { - *static_cast(outData) = *hostProtocol; - } else { - result = kAudioUnitErr_PropertyNotInUse; - } - break; -#endif - default: result = GetProperty(inID, inScope, inElement, outData); break; @@ -860,16 +842,6 @@ OSStatus AUBase::DispatchSetProperty(AudioUnitPropertyID inID, AudioUnitScope in break; } -#if AUSDK_MIDI2_AVAILABLE - case kAudioUnitProperty_HostMIDIProtocol: { - AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); - AUSDK_Require(inDataSize == sizeof(MIDIProtocolID), kAudioUnitErr_InvalidPropertyValue); - mHostMIDIProtocol = *static_cast(inData); - PropertyChanged(inID, inScope, inElement); - break; - } -#endif - default: result = SetProperty(inID, inScope, inElement, inData, inDataSize); if (result == noErr) { @@ -925,15 +897,6 @@ OSStatus AUBase::DispatchRemovePropertyValue( break; } -#if AUSDK_MIDI2_AVAILABLE - case kAudioUnitProperty_HostMIDIProtocol: { - AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); - mHostMIDIProtocol = {}; - PropertyChanged(inID, inScope, inElement); - break; - } -#endif - default: result = RemovePropertyValue(inID, inScope, inElement); break; @@ -1242,16 +1205,18 @@ OSStatus AUBase::DoRender(AudioUnitRenderActionFlags& ioActionFlags, try { AUSDK_Require(IsInitialized(), errorExit(kAudioUnitErr_Uninitialized)); if (inFramesToProcess > mMaxFramesPerSlice) { +#ifndef AUSDK_NO_LOGGING static UInt64 lastTimeMessagePrinted = 0; - const UInt64 now = HostTime::current(); + const UInt64 now = HostTime::Current(); if (static_cast(now - lastTimeMessagePrinted) > - HostTime::frequency()) { // not more than once per second. + mHostTimeFrequency) { // not more than once per second. lastTimeMessagePrinted = now; AUSDK_LogError("kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=%u, " "mMaxFramesPerSlice=%u", static_cast(inFramesToProcess), static_cast(mMaxFramesPerSlice)); } +#endif return errorExit(kAudioUnitErr_TooManyFramesToProcess); } AUSDK_Require(!UsesFixedBlockSize() || inFramesToProcess == GetMaxFramesPerSlice(), @@ -1649,7 +1614,7 @@ AudioStreamBasicDescription AUBase::GetStreamFormat( element = Outputs().GetIOElement(0); break; default: - AUSDK_Throw(kAudioUnitErr_InvalidScope); + Throw(kAudioUnitErr_InvalidScope); } return element->GetStreamFormat(); } @@ -1687,7 +1652,7 @@ OSStatus AUBase::ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inE element = Outputs().GetIOElement(0); break; default: - AUSDK_Throw(kAudioUnitErr_InvalidScope); + Throw(kAudioUnitErr_InvalidScope); } element->SetStreamFormat(inNewFormat); PropertyChanged(kAudioUnitProperty_StreamFormat, inScope, inElement); @@ -1803,16 +1768,6 @@ OSStatus AUBase::SaveState(CFPropertyListRef* outData) AddNumToDictionary(*dict, kRenderQualityString, value); } - // Does the unit support the CPULoad Quality property - if so, save it... - Float32 cpuLoad = 0.0f; - result = DispatchGetProperty(kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &cpuLoad); - - if (result == noErr) { - CFNumberRef num = CFNumberCreate(nullptr, kCFNumberFloatType, &cpuLoad); - CFDictionarySetValue(*dict, kCPULoadString, num); - CFRelease(num); - } - // Do we have any element names for any of our scopes? // first check to see if we have any names... bool foundName = false; @@ -1861,9 +1816,8 @@ OSStatus AUBase::RestoreState(CFPropertyListRef plist) // first step -> check the saved version in the data ref // at this point we're only dealing with version==0 const auto* cfnum = static_cast(CFDictionaryGetValue(dict, kVersionString)); - if (cfnum == nullptr) { - return kAudioUnitErr_InvalidPropertyValue; - } + AUSDK_Require(cfnum != nullptr, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(CFGetTypeID(cfnum) == CFNumberGetTypeID(), kAudioUnitErr_InvalidPropertyValue); SInt32 value = 0; CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); if (value != kCurrentSavedStateVersion) { @@ -1875,18 +1829,16 @@ OSStatus AUBase::RestoreState(CFPropertyListRef plist) // We're not checking the type, since there may be different versions (effect, format-converter, // offline) of essentially the same AU cfnum = static_cast(CFDictionaryGetValue(dict, kSubtypeString)); - if (cfnum == nullptr) { - return kAudioUnitErr_InvalidPropertyValue; - } + AUSDK_Require(cfnum != nullptr, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(CFGetTypeID(cfnum) == CFNumberGetTypeID(), kAudioUnitErr_InvalidPropertyValue); CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); if (static_cast(value) != desc.componentSubType) { return kAudioUnitErr_InvalidPropertyValue; } cfnum = static_cast(CFDictionaryGetValue(dict, kManufacturerString)); - if (cfnum == nullptr) { - return kAudioUnitErr_InvalidPropertyValue; - } + AUSDK_Require(cfnum != nullptr, kAudioUnitErr_InvalidPropertyValue); + AUSDK_Require(CFGetTypeID(cfnum) == CFNumberGetTypeID(), kAudioUnitErr_InvalidPropertyValue); CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); if (static_cast(value) != desc.componentManufacturer) { return kAudioUnitErr_InvalidPropertyValue; @@ -1894,7 +1846,7 @@ OSStatus AUBase::RestoreState(CFPropertyListRef plist) // fourth step -> restore the state of all of the parameters for each scope and element const auto* const data = static_cast(CFDictionaryGetValue(dict, kDataString)); - if (data != nullptr) { + if ((data != nullptr) && (CFGetTypeID(data) == CFDataGetTypeID())) { const UInt8* p = CFDataGetBytePtr(data); const UInt8* const pend = p + CFDataGetLength(data); // NOLINT @@ -1917,7 +1869,7 @@ OSStatus AUBase::RestoreState(CFPropertyListRef plist) if (mCurrentPreset.presetName != nullptr) { CFRelease(mCurrentPreset.presetName); } - if (name != nullptr) { + if ((name != nullptr) && (CFGetTypeID(name) == CFStringGetTypeID())) { mCurrentPreset.presetName = name; mCurrentPreset.presetNumber = -1; } else { // no name entry make the default one @@ -1929,35 +1881,26 @@ OSStatus AUBase::RestoreState(CFPropertyListRef plist) PropertyChanged(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0); // Does the dict contain render quality information? - if (CFDictionaryGetValueIfPresent( - dict, kRenderQualityString, reinterpret_cast(&cfnum))) { // NOLINT + cfnum = static_cast(CFDictionaryGetValue(dict, kRenderQualityString)); + if (cfnum && (CFGetTypeID(cfnum) == CFNumberGetTypeID())) { CFNumberGetValue(cfnum, kCFNumberSInt32Type, &value); DispatchSetProperty( kAudioUnitProperty_RenderQuality, kAudioUnitScope_Global, 0, &value, sizeof(value)); } - // Does the unit support the CPULoad Quality property - if so, save it... - if (CFDictionaryGetValueIfPresent( - dict, kCPULoadString, reinterpret_cast(&cfnum))) { // NOLINT - auto floatValue = std::numeric_limits::quiet_NaN; - CFNumberGetValue(cfnum, kCFNumberFloatType, &floatValue); - DispatchSetProperty( - kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &floatValue, sizeof(floatValue)); - } - // Do we have any element names for any of our scopes? - CFDictionaryRef nameDict = nullptr; - if (CFDictionaryGetValueIfPresent( - dict, kElementNameString, reinterpret_cast(&nameDict))) { // NOLINT + const auto nameDict = + static_cast(CFDictionaryGetValue(dict, kElementNameString)); + if (nameDict && (CFGetTypeID(nameDict) == CFDictionaryGetTypeID())) { for (AudioUnitScope i = 0; i < kNumScopes; ++i) { const CFStringRef key = CFStringCreateWithFormat( nullptr, nullptr, CFSTR("%u"), static_cast(i)); // NOLINT - CFDictionaryRef elementDict = nullptr; - if (CFDictionaryGetValueIfPresent( - nameDict, key, reinterpret_cast(&elementDict))) { // NOLINT - const bool didAddElements = GetScope(i).RestoreElementNames(elementDict); - if (didAddElements) { - PropertyChanged(kAudioUnitProperty_ElementCount, i, 0); + const auto elementDict = + static_cast(CFDictionaryGetValue(nameDict, key)); + if (elementDict && (CFGetTypeID(elementDict) == CFDictionaryGetTypeID())) { + const auto restoredElements = GetScope(i).RestoreElementNames(elementDict); + for (const auto& element : restoredElements) { + PropertyChanged(kAudioUnitProperty_ElementName, i, element); } } CFRelease(key); @@ -2073,7 +2016,7 @@ OSStatus AUBase::CopyClumpName(AudioUnitScope /*inScope*/, UInt32 /*inClumpID*/, void AUBase::SetNumberOfElements(AudioUnitScope inScope, UInt32 numElements) { if (inScope == kAudioUnitScope_Global && numElements != 1) { - AUSDK_Throw(kAudioUnitErr_InvalidScope); + Throw(kAudioUnitErr_InvalidScope); } GetScope(inScope).SetNumberOfElements(numElements); @@ -2096,22 +2039,23 @@ std::unique_ptr AUBase::CreateElement(AudioUnitScope scope, AudioUnit default: break; } - AUSDK_Throw(kAudioUnitErr_InvalidScope); - - return {}; // get rid of compiler warning + Throw(kAudioUnitErr_InvalidScope); } -const char* AUBase::GetLoggingString() +const char* AUBase::GetLoggingString() const noexcept { return mLogString.c_str(); } + +std::string AUBase::CreateLoggingString() const { - if (!mLogString.empty()) { - AudioComponentDescription desc = GetComponentDescription(); - std::array buf{}; + const auto desc = GetComponentDescription(); + std::array buf{}; + [[maybe_unused]] const int printCount = snprintf(buf.data(), buf.size(), "AU (%p): ", GetComponentInstance()); // NOLINT - mLogString = std::string{ buf.data() } + make_string_from_4cc(desc.componentType) + '/' + - make_string_from_4cc(desc.componentSubType) + '/' + - make_string_from_4cc(desc.componentManufacturer); - } - return mLogString.c_str(); +#if DEBUG + assert(printCount < static_cast(buf.size())); +#endif + return buf.data() + make_string_from_4cc(desc.componentType) + '/' + + make_string_from_4cc(desc.componentSubType) + '/' + + make_string_from_4cc(desc.componentManufacturer); } } // namespace ausdk diff --git a/Source/AUBuffer.cpp b/src/AudioUnitSDK/AUBuffer.cpp similarity index 94% rename from Source/AUBuffer.cpp rename to src/AudioUnitSDK/AUBuffer.cpp index a7747b6..b62dfbf 100644 --- a/Source/AUBuffer.cpp +++ b/src/AudioUnitSDK/AUBuffer.cpp @@ -2,8 +2,8 @@ @file AudioUnitSDK/AUBuffer.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUBuffer.h" -#include "AUUtility.h" +#include +#include namespace ausdk { @@ -123,7 +123,7 @@ AudioBufferList& AllocatedBuffer::PrepareNull(UInt32 channelsPerBuffer, UInt32 b AudioBufferList& AUBufferList::PrepareBuffer( const AudioStreamBasicDescription& format, UInt32 nFrames) { - AUSDK_ThrowIf(nFrames > mAllocatedFrames, kAudioUnitErr_TooManyFramesToProcess); + ausdk::ThrowExceptionIf(nFrames > mAllocatedFrames, kAudioUnitErr_TooManyFramesToProcess); UInt32 nStreams = 0; UInt32 channelsPerStream = 0; @@ -135,7 +135,7 @@ AudioBufferList& AUBufferList::PrepareBuffer( channelsPerStream = 1; } - AUSDK_ThrowIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported); + ausdk::ThrowExceptionIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported); auto& abl = mBuffers->Prepare(channelsPerStream, nFrames * format.mBytesPerFrame); mPtrState = EPtrState::ToMyMemory; return abl; @@ -154,7 +154,7 @@ AudioBufferList& AUBufferList::PrepareNullBuffer( channelsPerStream = 1; } - AUSDK_ThrowIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported); + ausdk::ThrowExceptionIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported); auto& abl = mBuffers->PrepareNull(channelsPerStream, nFrames * format.mBytesPerFrame); mPtrState = EPtrState::ToExternalMemory; return abl; diff --git a/Source/AUBufferAllocator.cpp b/src/AudioUnitSDK/AUBufferAllocator.cpp similarity index 88% rename from Source/AUBufferAllocator.cpp rename to src/AudioUnitSDK/AUBufferAllocator.cpp index 86b471f..577ccbf 100644 --- a/Source/AUBufferAllocator.cpp +++ b/src/AudioUnitSDK/AUBufferAllocator.cpp @@ -2,7 +2,7 @@ @file AudioUnitSDK/AUBufferAllocator.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUBuffer.h" +#include namespace ausdk { diff --git a/Source/AUEffectBase.cpp b/src/AudioUnitSDK/AUEffectBase.cpp similarity index 99% rename from Source/AUEffectBase.cpp rename to src/AudioUnitSDK/AUEffectBase.cpp index 82bb0c9..424883a 100644 --- a/Source/AUEffectBase.cpp +++ b/src/AudioUnitSDK/AUEffectBase.cpp @@ -2,7 +2,8 @@ @file AudioUnitSDK/AUEffectBase.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUEffectBase.h" +#include + #include /* @@ -165,7 +166,7 @@ OSStatus AUEffectBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inSc if (tempNewSetting != IsBypassEffect()) { if (!tempNewSetting && IsBypassEffect() && IsInitialized()) { // turning bypass off and we're initialized - Reset(0, 0); + Reset(kAudioUnitScope_Global, 0); } SetBypassEffect(tempNewSetting); } diff --git a/Source/AUInputElement.cpp b/src/AudioUnitSDK/AUInputElement.cpp similarity index 98% rename from Source/AUInputElement.cpp rename to src/AudioUnitSDK/AUInputElement.cpp index 84d2484..dafc8a3 100644 --- a/Source/AUInputElement.cpp +++ b/src/AudioUnitSDK/AUInputElement.cpp @@ -2,7 +2,7 @@ @file AudioUnitSDK/AUInputElement.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUBase.h" +#include namespace ausdk { diff --git a/Source/AUMIDIBase.cpp b/src/AudioUnitSDK/AUMIDIBase.cpp similarity index 58% rename from Source/AUMIDIBase.cpp rename to src/AudioUnitSDK/AUMIDIBase.cpp index bdc3a60..ea3fb7b 100644 --- a/Source/AUMIDIBase.cpp +++ b/src/AudioUnitSDK/AUMIDIBase.cpp @@ -2,34 +2,19 @@ @file AudioUnitSDK/AUMIDIBase.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUMIDIBase.h" +#include #include namespace ausdk { -// MIDI status bytes -enum : uint8_t { - kMIDIStatus_NoteOff = 0x80, - kMIDIStatus_NoteOn = 0x90, - kMIDIStatus_PolyPressure = 0xA0, - kMIDIStatus_ControlChange = 0xB0, - kMIDIStatus_ProgramChange = 0xC0, - kMIDIStatus_ChannelPressure = 0xD0, - kMIDIStatus_PitchWheel = 0xE0, - kMIDIStatus_System = 0xF0, - - kMIDIController_AllSoundOff = 120, - kMIDIController_ResetAllControllers = 121, - kMIDIController_AllNotesOff = 123 -}; - -constexpr bool isMIDIStatus(uint8_t x) noexcept { return (x & 0x80) == 0x0U; } // NOLINT +// MIDI CC data bytes +constexpr uint8_t kMIDIController_AllSoundOff = 120u; +constexpr uint8_t kMIDIController_ResetAllControllers = 121u; +constexpr uint8_t kMIDIController_AllNotesOff = 123u; OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) { - OSStatus result = noErr; - (void)inScope; (void)inElement; (void)outDataSize; @@ -43,7 +28,7 @@ OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnit AUSDK_Require(GetXMLNames(nullptr) == noErr, kAudioUnitErr_InvalidProperty); outDataSize = sizeof(CFURLRef); outWritable = false; - break; + return noErr; #endif #if AUSDK_HAVE_MIDI_MAPPING @@ -53,8 +38,7 @@ OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnit AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); outWritable = true; outDataSize = sizeof(AUParameterMIDIMapping) * mMIDIMapper->GetNumberMaps(); - result = noErr; - break; + return noErr; case kAudioUnitProperty_HotMapParameterMIDIMapping: case kAudioUnitProperty_AddParameterMIDIMapping: @@ -64,15 +48,12 @@ OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnit AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); outWritable = true; outDataSize = sizeof(AUParameterMIDIMapping); - result = noErr; - break; + return noErr; #endif default: - result = kAudioUnitErr_InvalidProperty; - break; + return kAudioUnitErr_InvalidProperty; } - return result; } OSStatus AUMIDIBase::DelegateGetProperty( @@ -82,15 +63,12 @@ OSStatus AUMIDIBase::DelegateGetProperty( (void)inElement; (void)outData; - OSStatus result = noErr; - switch (inID) { // NOLINT if/else?! #if AUSDK_HAVE_XML_NAMES case kMusicDeviceProperty_MIDIXMLNames: AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); - result = GetXMLNames(static_cast(outData)); - break; + return GetXMLNames(static_cast(outData)); #endif #if AUSDK_HAVE_MIDI_MAPPING @@ -98,28 +76,24 @@ OSStatus AUMIDIBase::DelegateGetProperty( AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); - AUParameterMIDIMapping* maps = (static_cast(outData)); + AUParameterMIDIMapping* const maps = (static_cast(outData)); mMIDIMapper->GetMaps(maps); - result = noErr; - break; + return noErr; } case kAudioUnitProperty_HotMapParameterMIDIMapping: { AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty); AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope); AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); - AUParameterMIDIMapping* map = (static_cast(outData)); + AUParameterMIDIMapping* const map = (static_cast(outData)); mMIDIMapper->GetHotParameterMap(*map); - result = noErr; - break; + return noErr; } #endif default: - result = kAudioUnitErr_InvalidProperty; - break; + return kAudioUnitErr_InvalidProperty; } - return result; } OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope, @@ -130,8 +104,6 @@ OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScop (void)inData; (void)inDataSize; - OSStatus result = noErr; - switch (inID) { #if AUSDK_HAVE_MIDI_MAPPING @@ -144,8 +116,7 @@ OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScop maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance); mAUBaseInstance.PropertyChanged( kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0); - result = noErr; - break; + return noErr; } case kAudioUnitProperty_RemoveParameterMIDIMapping: { @@ -160,8 +131,7 @@ OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScop mAUBaseInstance.PropertyChanged( kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0); } - result = noErr; - break; + return noErr; } case kAudioUnitProperty_HotMapParameterMIDIMapping: { @@ -170,8 +140,7 @@ OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScop AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement); const auto& map = *static_cast(inData); mMIDIMapper->SetHotMapping(map); - result = noErr; - break; + return noErr; } case kAudioUnitProperty_AllParameterMIDIMappings: { @@ -181,96 +150,16 @@ OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScop const auto* const mappings = static_cast(inData); mMIDIMapper->ReplaceAllMaps( mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance); - result = noErr; - break; + return noErr; } #endif default: - result = kAudioUnitErr_InvalidProperty; - break; + return kAudioUnitErr_InvalidProperty; } - return result; } - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -#pragma mark ____MIDIDispatch - - -constexpr const Byte* NextMIDIEvent(const Byte* event, const Byte* end) noexcept -{ - const Byte c = *event; - switch (c & 0xF0U) { // NOLINT - default: // data byte -- assume in sysex - while (!isMIDIStatus(*++event) && event < end) { // NOLINT - ; - } - break; - case kMIDIStatus_NoteOff: - case kMIDIStatus_NoteOn: - case kMIDIStatus_PolyPressure: - case kMIDIStatus_ControlChange: - case kMIDIStatus_PitchWheel: - event += 3; // NOLINT - break; - case kMIDIStatus_ProgramChange: - case kMIDIStatus_ChannelPressure: - event += 2; // NOLINT - break; - case kMIDIStatus_System: - switch (c) { - case 0xF0: // NOLINT - while (!isMIDIStatus(*++event) && event < end) { // NOLINT - ; - } - break; - case 0xF1: // NOLINT - case 0xF3: // NOLINT - event += 2; // NOLINT - break; - case 0xF2: // NOLINT - event += 3; // NOLINT - break; - default: - ++event; // // NOLINT - break; - } - } - return (event >= end) ? end : event; -} - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// AUMIDIBase::HandleMIDIPacketList -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -OSStatus AUMIDIBase::HandleMIDIPacketList(const MIDIPacketList& pktlist) -{ - if (!mAUBaseInstance.IsInitialized()) { - return kAudioUnitErr_Uninitialized; - } - - auto nPackets = pktlist.numPackets; - const MIDIPacket* pkt = pktlist.packet; // NOLINT - - while (nPackets-- > 0) { - const Byte* event = pkt->data; // NOLINT - const Byte* packetEnd = event + pkt->length; // NOLINT - const auto startFrame = static_cast(pkt->timeStamp); - while (event < packetEnd) { - const Byte status = event[0]; // NOLINT - if (isMIDIStatus(status)) { - // really a status byte (not sysex continuation) - HandleMIDIEvent(status & 0xF0, status & 0x0F, event[1], event[2], // NOLINT - startFrame); - // note that we're generating a bogus channel number for system messages (0xF0-FF) - } - event = NextMIDIEvent(event, packetEnd); - } - pkt = reinterpret_cast(packetEnd); // NOLINT - } - return noErr; -} +constexpr uint8_t MIDIStatusNibbleValue(uint8_t status) noexcept { return (status & 0xF0U) >> 4u; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // AUMIDIBase::HandleMIDIEvent @@ -296,78 +185,58 @@ OSStatus AUMIDIBase::HandleMIDIEvent( } } #endif - - OSStatus result = noErr; - - switch (status) { - case kMIDIStatus_NoteOn: + switch (MIDIStatusNibbleValue(status)) { + case kMIDICVStatusNoteOn: if (data2 != 0u) { - result = HandleNoteOn(channel, data1, data2, inStartFrame); + return HandleNoteOn(channel, data1, data2, inStartFrame); } else { // zero velocity translates to note off - result = HandleNoteOff(channel, data1, data2, inStartFrame); + return HandleNoteOff(channel, data1, data2, inStartFrame); } - break; - case kMIDIStatus_NoteOff: - result = HandleNoteOff(channel, data1, data2, inStartFrame); - break; + case kMIDICVStatusNoteOff: + return HandleNoteOff(channel, data1, data2, inStartFrame); default: - result = HandleNonNoteEvent(status, channel, data1, data2, inStartFrame); - break; + return HandleNonNoteEvent(status, channel, data1, data2, inStartFrame); } - - return result; } OSStatus AUMIDIBase::HandleNonNoteEvent( UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame) { - OSStatus result = noErr; - - switch (status) { - case kMIDIStatus_PitchWheel: - result = HandlePitchWheel(channel, data1, data2, inStartFrame); - break; + switch (MIDIStatusNibbleValue(status)) { + case kMIDICVStatusPitchBend: + return HandlePitchWheel(channel, data1, data2, inStartFrame); - case kMIDIStatus_ProgramChange: - result = HandleProgramChange(channel, data1); - break; + case kMIDICVStatusProgramChange: + return HandleProgramChange(channel, data1); - case kMIDIStatus_ChannelPressure: - result = HandleChannelPressure(channel, data1, inStartFrame); - break; + case kMIDICVStatusChannelPressure: + return HandleChannelPressure(channel, data1, inStartFrame); - case kMIDIStatus_ControlChange: { + case kMIDICVStatusControlChange: { switch (data1) { case kMIDIController_AllNotesOff: - result = HandleAllNotesOff(channel); - break; + return HandleAllNotesOff(channel); case kMIDIController_ResetAllControllers: - result = HandleResetAllControllers(channel); - break; + return HandleResetAllControllers(channel); case kMIDIController_AllSoundOff: - result = HandleAllSoundOff(channel); - break; + return HandleAllSoundOff(channel); default: - result = HandleControlChange(channel, data1, data2, inStartFrame); - break; + return HandleControlChange(channel, data1, data2, inStartFrame); } - break; } - case kMIDIStatus_PolyPressure: - result = HandlePolyPressure(channel, data1, data2, inStartFrame); - break; + case kMIDICVStatusPolyPressure: + return HandlePolyPressure(channel, data1, data2, inStartFrame); default: - break; + return noErr; } - return result; } OSStatus AUMIDIBase::SysEx(const UInt8* inData, UInt32 inLength) diff --git a/Source/AUMIDIEffectBase.cpp b/src/AudioUnitSDK/AUMIDIEffectBase.cpp similarity index 97% rename from Source/AUMIDIEffectBase.cpp rename to src/AudioUnitSDK/AUMIDIEffectBase.cpp index e852b94..6519bfe 100644 --- a/Source/AUMIDIEffectBase.cpp +++ b/src/AudioUnitSDK/AUMIDIEffectBase.cpp @@ -2,7 +2,7 @@ @file AudioUnitSDK/AUMIDIEffectBase.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUMIDIEffectBase.h" +#include namespace ausdk { diff --git a/Source/AUOutputElement.cpp b/src/AudioUnitSDK/AUOutputElement.cpp similarity index 89% rename from Source/AUOutputElement.cpp rename to src/AudioUnitSDK/AUOutputElement.cpp index f8fd939..6951f42 100644 --- a/Source/AUOutputElement.cpp +++ b/src/AudioUnitSDK/AUOutputElement.cpp @@ -2,8 +2,8 @@ @file AudioUnitSDK/AUOutputElement.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUOutputElement.h" -#include "AUBase.h" +#include +#include namespace ausdk { diff --git a/Source/AUPlugInDispatch.cpp b/src/AudioUnitSDK/AUPlugInDispatch.cpp similarity index 95% rename from Source/AUPlugInDispatch.cpp rename to src/AudioUnitSDK/AUPlugInDispatch.cpp index ddc59da..b06725d 100644 --- a/Source/AUPlugInDispatch.cpp +++ b/src/AudioUnitSDK/AUPlugInDispatch.cpp @@ -2,10 +2,11 @@ @file AudioUnitSDK/AUPlugInDispatch.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUPlugInDispatch.h" -#include "AUBase.h" -#include "AUUtility.h" -#include "ComponentBase.h" +#include +#include +#include +#include + #include #include @@ -31,12 +32,9 @@ class AUInstanceGuard { }; // ------------------------------------------------------------------------------------------------ -static bool IsValidParamValue(AudioUnitParameterValue value) -{ - return not(std::isnan(value) || std::isinf(value)); -} +static bool IsValidParameterValue(AudioUnitParameterValue value) { return std::isfinite(value); } -static bool AreValidParamEvents(const AudioUnitParameterEvent* events, UInt32 numEvents) +static bool AreValidParameterEvents(const AudioUnitParameterEvent* events, UInt32 numEvents) { if (events == nullptr) { return true; @@ -46,15 +44,15 @@ static bool AreValidParamEvents(const AudioUnitParameterEvent* events, UInt32 nu const auto& event = events[i]; // NOLINT switch (event.eventType) { case kParameterEvent_Immediate: { - if (!IsValidParamValue(event.eventValues.immediate.value)) { // NOLINT + if (!IsValidParameterValue(event.eventValues.immediate.value)) { // NOLINT return false; } break; } case kParameterEvent_Ramped: { - if (!IsValidParamValue(event.eventValues.ramp.startValue) || // NOLINT - !IsValidParamValue(event.eventValues.ramp.endValue)) { // NOLINT + if (!IsValidParameterValue(event.eventValues.ramp.startValue) || // NOLINT + !IsValidParameterValue(event.eventValues.ramp.endValue)) { // NOLINT return false; } break; @@ -276,7 +274,7 @@ static OSStatus AUMethodGetParameter(void* self, AudioUnitParameterID param, Aud static OSStatus AUMethodSetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset) { - if (!IsValidParamValue(value)) { + if (!IsValidParameterValue(value)) { return kAudioUnitErr_InvalidParameterValue; } @@ -292,7 +290,7 @@ static OSStatus AUMethodSetParameter(void* self, AudioUnitParameterID param, Aud static OSStatus AUMethodScheduleParameters( void* self, const AudioUnitParameterEvent* events, UInt32 numEvents) { - if (!AreValidParamEvents(events, numEvents)) { + if (!AreValidParameterEvents(events, numEvents)) { return kAudioUnitErr_InvalidParameterValue; } @@ -518,7 +516,11 @@ static OSStatus AUMethodMIDIEventList( OSStatus result = noErr; try { // this is a potential render-time method; no lock - result = AUInstance(self)->MIDIEventList(inOffsetSampleFrame, *eventList); + + // Note that a MIDIEventList is variably-sized and can be backed by less memory than + // required, so it is Undefined Behavior to form a reference to it; we must only use + // pointers. + result = AUInstance(self)->MIDIEventList(inOffsetSampleFrame, eventList); } AUSDK_Catch(result) return result; diff --git a/Source/AUScopeElement.cpp b/src/AudioUnitSDK/AUScopeElement.cpp similarity index 93% rename from Source/AUScopeElement.cpp rename to src/AudioUnitSDK/AUScopeElement.cpp index 7ff5e50..571a24a 100644 --- a/Source/AUScopeElement.cpp +++ b/src/AudioUnitSDK/AUScopeElement.cpp @@ -2,9 +2,11 @@ @file AudioUnitSDK/AUScopeElement.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "AUScopeElement.h" -#include "AUBase.h" +#include +#include + #include + #include namespace ausdk { @@ -44,11 +46,12 @@ bool AUElement::HasParameterID(AudioUnitParameterID paramID) const AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID) const { if (mUseIndexedParameters) { - AUSDK_ThrowIf(paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter); + ausdk::ThrowExceptionIf( + paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter); return mIndexedParameters[paramID].load(std::memory_order_acquire); } const auto i = mParameters.find(paramID); - AUSDK_ThrowIf(i == mParameters.end(), kAudioUnitErr_InvalidParameter); + ausdk::ThrowExceptionIf(i == mParameters.end(), kAudioUnitErr_InvalidParameter); return (*i).second.load(std::memory_order_acquire); } @@ -58,7 +61,8 @@ void AUElement::SetParameter( AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized) { if (mUseIndexedParameters) { - AUSDK_ThrowIf(paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter); + ausdk::ThrowExceptionIf( + paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter); mIndexedParameters[paramID].store(inValue, std::memory_order_release); } else { const auto i = mParameters.find(paramID); @@ -68,7 +72,7 @@ void AUElement::SetParameter( // The AU should not be creating new parameters once initialized. // If a client tries to set an undefined parameter, we could throw as follows, // but this might cause a regression. So it is better to just fail silently. - // AUSDK_THROW(kAudioUnitErr_InvalidParameter); + // Throw(kAudioUnitErr_InvalidParameter); AUSDK_LogError( "Warning: %s SetParameter for undefined param ID %u while initialized. " "Ignoring.", @@ -213,8 +217,8 @@ AUIOElement::AUIOElement(AUBase& audioUnit) : AUElement(audioUnit), mWillAllocat { mStreamFormat = AudioStreamBasicDescription{ .mSampleRate = AUBase::kAUDefaultSampleRate, .mFormatID = kAudioFormatLinearPCM, - .mFormatFlags = - kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved, // NOLINT + .mFormatFlags = AudioFormatFlags(kAudioFormatFlagsNativeFloatPacked) | + AudioFormatFlags(kAudioFormatFlagIsNonInterleaved), // NOLINT .mBytesPerPacket = sizeof(float), .mFramesPerPacket = 1, .mBytesPerFrame = sizeof(float), @@ -359,10 +363,10 @@ void AUScope::AddElementNamesToDict(CFMutableDictionaryRef inNameDict) const //_____________________________________________________________________________ // -bool AUScope::RestoreElementNames(CFDictionaryRef inNameDict) const +std::vector AUScope::RestoreElementNames(CFDictionaryRef inNameDict) const { // first we have to see if we have enough elements - bool didAddElements = false; + std::vector restoredElements; const auto maxElNum = GetNumberOfElements(); const auto dictSize = @@ -379,14 +383,17 @@ bool AUScope::RestoreElementNames(CFDictionaryRef inNameDict) const if ((result != 0) && (static_cast(intKey) < maxElNum)) { auto* const elName = static_cast(CFDictionaryGetValue(inNameDict, keys[i])); - AUElement* const element = GetElement(intKey); - if (element != nullptr) { - element->SetName(elName); + if ((elName != nullptr) && (CFGetTypeID(elName) == CFStringGetTypeID())) { + AUElement* const element = GetElement(intKey); + if (element != nullptr) { + element->SetName(elName); + restoredElements.push_back(intKey); + } } } } - return didAddElements; + return restoredElements; } void AUScope::SaveState(CFMutableDataRef data) const diff --git a/Source/ComponentBase.cpp b/src/AudioUnitSDK/ComponentBase.cpp similarity index 96% rename from Source/ComponentBase.cpp rename to src/AudioUnitSDK/ComponentBase.cpp index 8b8bad8..d043591 100644 --- a/Source/ComponentBase.cpp +++ b/src/AudioUnitSDK/ComponentBase.cpp @@ -3,8 +3,8 @@ @copyright © 2000-2021 Apple Inc. All rights reserved. */ // self -#include "ComponentBase.h" -#include "AUUtility.h" +#include +#include // std #include diff --git a/Source/MusicDeviceBase.cpp b/src/AudioUnitSDK/MusicDeviceBase.cpp similarity index 98% rename from Source/MusicDeviceBase.cpp rename to src/AudioUnitSDK/MusicDeviceBase.cpp index 786a68c..19404b4 100644 --- a/Source/MusicDeviceBase.cpp +++ b/src/AudioUnitSDK/MusicDeviceBase.cpp @@ -2,7 +2,7 @@ @file AudioUnitSDK/MusicDeviceBase.cpp @copyright © 2000-2021 Apple Inc. All rights reserved. */ -#include "MusicDeviceBase.h" +#include namespace ausdk { diff --git a/Tests/Info.plist b/tests/Info.plist similarity index 100% rename from Tests/Info.plist rename to tests/Info.plist diff --git a/Tests/Tests.mm b/tests/Tests.mm similarity index 98% rename from Tests/Tests.mm rename to tests/Tests.mm index 9376187..0c49dcd 100644 --- a/Tests/Tests.mm +++ b/tests/Tests.mm @@ -5,7 +5,7 @@ #import -#import "AudioUnitSDK.h" +#import @interface Tests : XCTestCase diff --git a/Tools/build.sh b/tools/build.sh similarity index 100% rename from Tools/build.sh rename to tools/build.sh