Browse Source

AU: Replace CoreAudioUtilityClasses with files from new SDK

v7.0.9
reuk 3 years ago
parent
commit
f8e91d4003
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
87 changed files with 7700 additions and 15819 deletions
  1. +22
    -0
      BREAKING-CHANGES.txt
  2. +1
    -1
      README.md
  3. +1
    -1
      docs/doxygen/Doxyfile
  4. +2
    -0
      extras/Build/CMake/JUCEModuleSupport.cmake
  5. +0
    -71
      extras/Build/CMake/JUCEUtils.cmake
  6. +20
    -8
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
  7. +2061
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.cpp
  8. +733
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.h
  9. +188
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.cpp
  10. +166
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.h
  11. +15
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBufferAllocator.cpp
  12. +400
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.cpp
  13. +194
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.h
  14. +85
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.cpp
  15. +91
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.h
  16. +251
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.cpp
  17. +169
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.h
  18. +53
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.cpp
  19. +40
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.h
  20. +20
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIUtility.h
  21. +27
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.cpp
  22. +33
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.h
  23. +773
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.cpp
  24. +110
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.h
  25. +442
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.cpp
  26. +435
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.h
  27. +49
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUSilentTimeout.h
  28. +524
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUUtility.h
  29. +22
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/AudioUnitSDK.h
  30. +98
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.cpp
  31. +162
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.h
  32. +202
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt
  33. +117
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.cpp
  34. +64
    -0
      modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.h
  35. +0
    -2400
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp
  36. +0
    -1054
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h
  37. +0
    -75
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBaseHelper.h
  38. +0
    -219
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.cpp
  39. +0
    -267
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.h
  40. +0
    -438
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.cpp
  41. +0
    -82
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.h
  42. +0
    -151
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.cpp
  43. +0
    -119
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.h
  44. +0
    -155
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputFormatConverter.h
  45. +0
    -495
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.cpp
  46. +0
    -213
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.h
  47. +0
    -76
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.cpp
  48. +0
    -82
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.h
  49. +0
    -63
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.cpp
  50. +0
    -66
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.h
  51. +0
    -668
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.cpp
  52. +0
    -144
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.h
  53. +0
    -566
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.cpp
  54. +0
    -553
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.h
  55. +0
    -93
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUSilentTimeout.h
  56. +0
    -163
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUTimestampGenerator.h
  57. +0
    -88
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUViewLocalizedStringKeys.h
  58. +0
    -401
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.cpp
  59. +0
    -191
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.h
  60. +0
    -305
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomic.h
  61. +0
    -239
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomicStack.h
  62. +0
    -153
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp
  63. +0
    -199
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.h
  64. +0
    -508
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAutoDisposer.h
  65. +0
    -583
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugMacros.h
  66. +0
    -115
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugPrintf.h
  67. +0
    -83
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAException.h
  68. +0
    -234
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAHostTimeBase.h
  69. +0
    -68
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMath.h
  70. +0
    -345
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.cpp
  71. +0
    -163
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.h
  72. +0
    -97
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAReferenceCounted.h
  73. +0
    -879
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp
  74. +0
    -424
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.h
  75. +0
    -233
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAThreadSafeList.h
  76. +0
    -194
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.cpp
  77. +0
    -101
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.h
  78. +0
    -60
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnitTypes.h
  79. +0
    -361
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAXException.h
  80. +0
    -369
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.cpp
  81. +0
    -353
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.h
  82. +0
    -354
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp
  83. +0
    -126
      modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.h
  84. +94
    -155
      modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  85. +0
    -150
      modules/juce_audio_plugin_client/AUResources.r
  86. +0
    -50
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r
  87. +36
    -15
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm

+ 22
- 0
BREAKING-CHANGES.txt View File

@@ -4,6 +4,28 @@ JUCE breaking changes
develop
=======

Change
------
Resource forks are no longer generated for Audio Unit plug-ins.

Possible Issues
---------------
New builds of JUCE Audio Units may no longer load in old hosts that use the
Component Manager to discover plug-ins.

Workaround
----------
No workaround is available.

Rationale
---------
The Component Manager is deprecated in macOS 10.8 and later, so the majority of
hosts have now implemented support for the new plist-based discovery mechanism.
The new AudioUnitSDK (https://github.com/apple/AudioUnitSDK) provided by Apple
to replace the old Core Audio Utility Classes no longer includes the files
required to generate resource forks.


Change
------
Previously, the AudioProcessorGraph would call processBlockBypassed on any


+ 1
- 1
README.md View File

@@ -94,7 +94,7 @@ The JUCE framework contains the following dependencies:
- [Oboe](modules/juce_audio_devices/native/oboe/) ([Apache 2.0](modules/juce_audio_devices/native/oboe/LICENSE))
- [FLAC](modules/juce_audio_formats/codecs/flac/) ([BSD](modules/juce_audio_formats/codecs/flac/Flac%20Licence.txt))
- [Ogg Vorbis](modules/juce_audio_formats/codecs/oggvorbis/) ([BSD](modules/juce_audio_formats/codecs/oggvorbis/Ogg%20Vorbis%20Licence.txt))
- [CoreAudioUtilityClasses](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/) ([Apple](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp))
- [AudioUnitSDK](modules/juce_audio_plugin_client/AU/AudioUnitSDK/) ([Apache 2.0](modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt))
- [AUResources.r](modules/juce_audio_plugin_client/AUResources.r) ([Apple](modules/juce_audio_plugin_client/AUResources.r))
- [LV2](modules/juce_audio_processors/format_types/LV2_SDK/) ([ISC](modules/juce_audio_processors/format_types/LV2_SDK/lv2/COPYING))
- [pslextensions](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h) ([Public domain](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h))


+ 1
- 1
docs/doxygen/Doxyfile View File

@@ -849,7 +849,7 @@ EXCLUDE = build/juce_graphics/image_formats \
build/juce_audio_formats/codecs/flac \
build/juce_audio_formats/codecs/oggvorbis \
build/juce_audio_devices/native \
build/juce_audio_plugin_client/AU/CoreAudioUtilityClasses \
build/juce_audio_plugin_client/AU/AudioUnitSDK \
build/juce_browser_plugin_client/juce_browser_plugin.h \
build/juce_core/native \
build/juce_events/native \


+ 2
- 0
extras/Build/CMake/JUCEModuleSupport.cmake View File

@@ -327,6 +327,8 @@ function(_juce_add_plugin_wrapper_target format path out_path)
_juce_link_frameworks("${target_name}" INTERFACE AudioUnit)
endif()
elseif(format STREQUAL "AU")
target_compile_features("${target_name}" INTERFACE cxx_std_17)
target_include_directories("${target_name}" INTERFACE "${out_path}/juce_audio_plugin_client/AU")
_juce_link_frameworks("${target_name}" INTERFACE AudioUnit CoreAudioKit)
endif()
endfunction()


+ 0
- 71
extras/Build/CMake/JUCEUtils.cmake View File

@@ -87,12 +87,6 @@ set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD FALSE)
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
_juce_create_pkgconfig_target(JUCE_CURL_LINUX_DEPS libcurl)
_juce_create_pkgconfig_target(JUCE_BROWSER_LINUX_DEPS webkit2gtk-4.0 gtk+-x11-3.0)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
find_program(JUCE_XCRUN xcrun)

if(NOT JUCE_XCRUN)
message(WARNING "failed to find xcrun; older resource-based AU plug-ins may not work correctly")
endif()
endif()

# We set up default/fallback copy dirs here. If you need different copy dirs, use
@@ -153,67 +147,6 @@ endfunction()

# ==================================================================================================

function(_juce_add_au_resource_fork shared_code_target au_target)
if(NOT JUCE_XCRUN)
return()
endif()

get_target_property(product_name ${shared_code_target} JUCE_PRODUCT_NAME)
get_target_property(module_sources juce::juce_audio_plugin_client_AU INTERFACE_SOURCES)

list(FILTER module_sources INCLUDE REGEX "/juce_audio_plugin_client_AU.r$")

if(NOT module_sources)
message(FATAL_ERROR "Failed to find AU resource file input")
endif()

list(GET module_sources 0 au_rez_sources)

get_target_property(juce_library_code ${shared_code_target} JUCE_GENERATED_SOURCES_DIRECTORY)
# We don't want our AU AppConfig.h to end up on peoples' include paths if we can help it
set(secret_au_resource_dir "${juce_library_code}/${au_target}/secret")
set(secret_au_plugindefines "${secret_au_resource_dir}/JucePluginDefines.h")

set(au_rez_output "${secret_au_resource_dir}/${product_name}.rsrc")

target_sources(${au_target} PRIVATE "${au_rez_output}")
set_source_files_properties("${au_rez_output}" PROPERTIES
GENERATED TRUE
MACOSX_PACKAGE_LOCATION Resources)

set(defs_file $<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},JUCE_DEFS_FILE>>)

# Passing all our compile definitions using generator expressions is really painful
# because some of the definitions have pipes and quotes and dollars and goodness-knows
# what else that the shell would very much like to claim for itself, thank you very much.
# CMake definitely knows how to escape all these things, because it's perfectly happy to pass
# them to compiler invocations, but I have no idea how to get it to escape them
# in a custom command.
# In the end, it's simplest to generate a special single-purpose appconfig just for the
# resource compiler.
add_custom_command(OUTPUT "${secret_au_plugindefines}"
COMMAND juce::juceaide auplugindefines "${defs_file}" "${secret_au_plugindefines}"
DEPENDS "${defs_file}"
VERBATIM)

add_custom_command(OUTPUT "${au_rez_output}"
COMMAND "${JUCE_XCRUN}" Rez
-d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64" -d "arm64_$arm64"
-I "${secret_au_resource_dir}"
-I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers"
-I "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/AudioUnit.framework/Headers"
-isysroot "${CMAKE_OSX_SYSROOT}"
"${au_rez_sources}"
-useDF
-o "${au_rez_output}"
DEPENDS "${secret_au_plugindefines}"
VERBATIM)

set(au_resource_directory "$<TARGET_BUNDLE_DIR:${au_target}>/Contents/Resources")
endfunction()

# ==================================================================================================

# Ideally, we'd check the preprocessor defs on the target to see whether
# JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off,
# and then link libraries as appropriate.
@@ -1285,10 +1218,6 @@ function(_juce_configure_plugin_targets target)
_juce_configure_app_bundle(${target} ${target}_Standalone)
endif()

if(TARGET ${target}_AU)
_juce_add_au_resource_fork(${target} ${target}_AU)
endif()

if(TARGET ${target}_AAX)
target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk)
endif()


+ 20
- 8
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h View File

@@ -1048,7 +1048,7 @@ public:
struct XcodeTarget : build_tools::ProjectType::Target
{
//==============================================================================
XcodeTarget (build_tools::ProjectType::Target::Type targetType, const XcodeProjectExporter& exporter)
XcodeTarget (Type targetType, const XcodeProjectExporter& exporter)
: Target (targetType),
owner (exporter)
{
@@ -1699,10 +1699,17 @@ public:
s.set ("CODE_SIGN_ENTITLEMENTS", getEntitlementsFilename().quoted());
{
auto cppStandard = owner.project.getCppStandardString();
const auto cppStandard = [&]() -> String
{
if (owner.project.getCppStandardString() == "latest")
return owner.project.getLatestNumberedCppStandardString();
// The AudioUnitSDK requires C++17
if (type == AudioUnitPlugIn)
return "17";
if (cppStandard == "latest")
cppStandard = owner.project.getLatestNumberedCppStandardString();
return owner.project.getCppStandardString();
}();
s.set ("CLANG_CXX_LANGUAGE_STANDARD", (String (owner.shouldUseGNUExtensions() ? "gnu++"
: "c++") + cppStandard).quoted());
@@ -1970,10 +1977,15 @@ public:
if (owner.project.getEnabledModules().isModuleEnabled ("juce_audio_plugin_client"))
{
// Needed to compile .r files
paths.add (owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client")
.rebased (owner.projectFolder, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder)
.toUnixStyle());
const auto pluginClientModule = owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client");
for (const auto& path : { pluginClientModule, // For AU resource fork
pluginClientModule.getChildFile ("AU") }) // For AudioUnitSDK includes
{
paths.add (path.rebased (owner.projectFolder,
owner.getTargetFolder(),
build_tools::RelativePath::buildTargetFolder)
.toUnixStyle());
}
}
sanitiseAndEscapeSearchPaths (config, paths);


+ 2061
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.cpp
File diff suppressed because it is too large
View File


+ 733
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBase.h View File

@@ -0,0 +1,733 @@
/*!
@file AudioUnitSDK/AUBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/

#ifndef AudioUnitSDK_AUBase_h
#define AudioUnitSDK_AUBase_h

// module
#include <AudioUnitSDK/AUBuffer.h>
#include <AudioUnitSDK/AUInputElement.h>
#include <AudioUnitSDK/AUMIDIUtility.h>
#include <AudioUnitSDK/AUOutputElement.h>
#include <AudioUnitSDK/AUPlugInDispatch.h>
#include <AudioUnitSDK/AUScopeElement.h>
#include <AudioUnitSDK/AUUtility.h>

// OS
#include <TargetConditionals.h>

// std
#include <algorithm>
#include <array>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>

// ________________________________________________________________________

namespace ausdk {

/*!
@class AUBase
@brief Abstract base class for an Audio Unit implementation.
*/
class AUBase : public ComponentBase {
public:
constexpr static double kAUDefaultSampleRate = 44100.0;
#if !TARGET_OS_WIN32
constexpr static UInt32 kAUDefaultMaxFramesPerSlice = 1156;
// this allows enough default frames for a 512 dest 44K and SRC from 96K
// add a padding of 4 frames for any vector rounding
#else
constexpr static UInt32 kAUDefaultMaxFramesPerSlice = 2048;
#endif

AUBase(AudioComponentInstance inInstance, UInt32 numInputElements, UInt32 numOutputElements,
UInt32 numGroupElements = 0);
~AUBase() override;

AUBase(const AUBase&) = delete;
AUBase(AUBase&&) = delete;
AUBase& operator=(const AUBase&) = delete;
AUBase& operator=(AUBase&&) = delete;

/// Called immediately after construction, when virtual methods work. Or, a subclass may call
/// this in order to have access to elements in its constructor.
void CreateElements();

virtual void CreateExtendedElements() {}

#pragma mark -
#pragma mark AU dispatch
// ________________________________________________________________________
// Virtual methods (mostly) directly corresponding to the entry points. Many of these
// have useful implementations here and will not need overriding.

/// Implements the entry point and ensures that Initialize is called exactly once from an
/// uninitialized state.
OSStatus DoInitialize();

// Overrides to this method can assume that they will only be called exactly once
// when transitioning from an uninitialized state.
virtual OSStatus Initialize();

[[nodiscard]] bool IsInitialized() const noexcept { return mInitialized; }
[[nodiscard]] bool HasBegunInitializing() const noexcept { return mHasBegunInitializing; }

/// Implements the entry point and ensures that Cleanup is called exactly once from an
/// initialized state.
void DoCleanup();

// Overrides to this method can assume that they will only be called exactly once
// when transitioning from an initialized state to an uninitialized state.
virtual void Cleanup();

virtual OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement);

// Note about GetPropertyInfo, GetProperty, SetProperty:
// Certain properties are trapped out in these dispatch functions and handled with different
// virtual methods. (To discourage hacks and keep vtable size down, these are non-virtual)

OSStatus DispatchGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable);
OSStatus DispatchGetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData);
OSStatus DispatchSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize);
OSStatus DispatchRemovePropertyValue(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement);

virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable);
virtual OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData);
virtual OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize);
virtual OSStatus RemovePropertyValue(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement);

virtual OSStatus AddPropertyListener(
AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc, void* inProcRefCon);
virtual OSStatus RemovePropertyListener(AudioUnitPropertyID inID,
AudioUnitPropertyListenerProc inProc, void* inProcRefCon, bool refConSpecified);

virtual OSStatus SetRenderNotification(AURenderCallback inProc, void* inRefCon);
virtual OSStatus RemoveRenderNotification(AURenderCallback inProc, void* inRefCon);

virtual OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope inScope,
AudioUnitElement inElement, AudioUnitParameterValue& outValue);
virtual OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope inScope,
AudioUnitElement inElement, AudioUnitParameterValue inValue, UInt32 inBufferOffsetInFrames);

[[nodiscard]] virtual bool CanScheduleParameters() const = 0;
virtual OSStatus ScheduleParameter(
const AudioUnitParameterEvent* inParameterEvent, UInt32 inNumEvents);

OSStatus DoRender(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp,
UInt32 inBusNumber, UInt32 inFramesToProcess, AudioBufferList& ioData);
OSStatus DoProcess(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp,
UInt32 inFramesToProcess, AudioBufferList& ioData);
OSStatus DoProcessMultiple(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, UInt32 inFramesToProcess,
UInt32 inNumberInputBufferLists, const AudioBufferList** inInputBufferLists,
UInt32 inNumberOutputBufferLists, AudioBufferList** ioOutputBufferLists);

virtual OSStatus ProcessBufferLists(AudioUnitRenderActionFlags& /*ioActionFlags*/,
const AudioBufferList& /*inBuffer*/, AudioBufferList& /*outBuffer*/,
UInt32 /*inFramesToProcess*/)
{
return kAudio_UnimplementedError;
}

virtual OSStatus ProcessMultipleBufferLists(AudioUnitRenderActionFlags& /*ioActionFlags*/,
UInt32 /*inFramesToProcess*/, UInt32 /*inNumberInputBufferLists*/,
const AudioBufferList** /*inInputBufferLists*/, UInt32 /*inNumberOutputBufferLists*/,
AudioBufferList** /*ioOutputBufferLists*/)
{
return kAudio_UnimplementedError;
}

virtual OSStatus ComplexRender(AudioUnitRenderActionFlags& /*ioActionFlags*/,
const AudioTimeStamp& /*inTimeStamp*/, UInt32 /*inOutputBusNumber*/,
UInt32 /*inNumberOfPackets*/, UInt32* /*outNumberOfPackets*/,
AudioStreamPacketDescription* /*outPacketDescriptions*/, AudioBufferList& /*ioData*/,
void* /*outMetadata*/, UInt32* /*outMetadataByteSize*/)
{
return kAudio_UnimplementedError;
}

// Override this method if your AU processes multiple output busses completely independently --
// you'll want to just call Render without the NeedsToRender check.
// Otherwise, override Render().
//
// N.B. Implementations of this method can assume that the output's buffer list has already been
// prepared and access it with GetOutput(inBusNumber)->GetBufferList() instead of
// GetOutput(inBusNumber)->PrepareBuffer(nFrames) -- if PrepareBuffer is called, a
// copy may occur after rendering.
virtual OSStatus RenderBus(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, UInt32 /*inBusNumber*/, UInt32 inNumberFrames)
{
if (NeedsToRender(inTimeStamp)) {
return Render(ioActionFlags, inTimeStamp, inNumberFrames);
}
return noErr; // was presumably already rendered via another bus
}

// N.B. For a unit with only one output bus, it can assume in its implementation of this
// method that the output's buffer list has already been prepared and access it with
// GetOutput(0)->GetBufferList() instead of GetOutput(0)->PrepareBuffer(nFrames)
// -- if PrepareBuffer is called, a copy may occur after rendering.
virtual OSStatus Render(AudioUnitRenderActionFlags& /*ioActionFlags*/,
const AudioTimeStamp& /*inTimeStamp*/, UInt32 /*inNumberFrames*/)
{
return noErr;
}


#pragma mark -
#pragma mark Property Dispatch

// ________________________________________________________________________
// These are called from DispatchGetProperty/DispatchGetPropertyInfo/DispatchSetProperty

virtual bool BusCountWritable(AudioUnitScope /*inScope*/) { return false; }
virtual OSStatus SetBusCount(AudioUnitScope inScope, UInt32 inCount);
virtual OSStatus SetConnection(const AudioUnitConnection& inConnection);
virtual OSStatus SetInputCallback(
UInt32 inPropertyID, AudioUnitElement inElement, AURenderCallback inProc, void* inRefCon);

virtual OSStatus GetParameterList(
AudioUnitScope inScope, AudioUnitParameterID* outParameterList, UInt32& outNumParameters);
// outParameterList may be a null pointer
virtual OSStatus GetParameterInfo(AudioUnitScope inScope, AudioUnitParameterID inParameterID,
AudioUnitParameterInfo& outParameterInfo);

virtual OSStatus GetParameterHistoryInfo(AudioUnitScope inScope,
AudioUnitParameterID inParameterID, Float32& outUpdatesPerSecond,
Float32& outHistoryDurationInSeconds);
virtual OSStatus SaveState(CFPropertyListRef* outData);
virtual void SaveExtendedScopes(CFMutableDataRef /*outData*/) {}
virtual OSStatus RestoreState(CFPropertyListRef plist);
virtual OSStatus GetParameterValueStrings(
AudioUnitScope inScope, AudioUnitParameterID inParameterID, CFArrayRef* outStrings);
virtual OSStatus CopyClumpName(AudioUnitScope inScope, UInt32 inClumpID,
UInt32 inDesiredNameLength, CFStringRef* outClumpName);
virtual OSStatus GetPresets(CFArrayRef* outData) const;

/// Set the default preset for the unit. The number of the preset must be >= 0 and the name
/// should be valid, or the preset will be rejected.
bool SetAFactoryPresetAsCurrent(const AUPreset& inPreset);

// Called when the host sets a new, valid preset.
// If this is a valid preset, then the subclass sets its state to that preset
// and returns noErr.
// If not a valid preset, return an error, and the pre-existing preset is restored.
virtual OSStatus NewFactoryPresetSet(const AUPreset& inNewFactoryPreset);
virtual OSStatus NewCustomPresetSet(const AUPreset& inNewCustomPreset);
virtual CFURLRef CopyIconLocation();

// default is no latency, and unimplemented tail time
virtual Float64 GetLatency() { return 0.0; }
virtual Float64 GetTailTime() { return 0.0; }
virtual bool SupportsTail() { return false; }

// Stream formats: scope will always be input or output
bool IsStreamFormatWritable(AudioUnitScope scope, AudioUnitElement element);

virtual bool StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) = 0;

// pass in a pointer to get the struct, and num channel infos
// you can pass in NULL to just get the number
// a return value of 0 (the default in AUBase) means the property is not supported...
virtual UInt32 SupportedNumChannels(const AUChannelInfo** outInfo);

/// Will only be called after StreamFormatWritable has succeeded. Default implementation
/// requires non-interleaved native-endian 32-bit float, any sample rate, any number of
/// channels; override when other formats are supported. A subclass's override can choose to
/// always return true and trap invalid formats in ChangeStreamFormat.
virtual bool ValidFormat(AudioUnitScope inScope, AudioUnitElement inElement,
const AudioStreamBasicDescription& inNewFormat);

virtual AudioStreamBasicDescription GetStreamFormat(
AudioUnitScope inScope, AudioUnitElement inElement);

// Will only be called after StreamFormatWritable
// and ValidFormat have succeeded.
virtual OSStatus ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement,
const AudioStreamBasicDescription& inPrevFormat,
const AudioStreamBasicDescription& inNewFormat);

// ________________________________________________________________________
// Methods useful for subclasses
AUScope& GetScope(AudioUnitScope inScope)
{
if (inScope >= kNumScopes) {
AUScope* const scope = GetScopeExtended(inScope);

ThrowQuietIf(scope == nullptr, kAudioUnitErr_InvalidScope);
return *scope;
}
return mScopes[inScope]; // NOLINT
}

virtual AUScope* GetScopeExtended(AudioUnitScope /*inScope*/) { return nullptr; }

AUScope& GlobalScope() { return mScopes[kAudioUnitScope_Global]; }
AUScope& Inputs() { return mScopes[kAudioUnitScope_Input]; }
AUScope& Outputs() { return mScopes[kAudioUnitScope_Output]; }
AUScope& Groups() { return mScopes[kAudioUnitScope_Group]; }
AUElement* Globals() { return mScopes[kAudioUnitScope_Global].GetElement(0); }

void SetNumberOfElements(AudioUnitScope inScope, UInt32 numElements);
virtual std::unique_ptr<AUElement> CreateElement(
AudioUnitScope scope, AudioUnitElement element);

AUElement* GetElement(AudioUnitScope inScope, AudioUnitElement inElement)
{
return GetScope(inScope).GetElement(inElement);
}

AUSDK_DEPRECATED("Use IOElement()")
AUIOElement* GetIOElement(AudioUnitScope inScope, AudioUnitElement inElement)
{
return &IOElement(inScope, inElement);
}

AUIOElement& IOElement(AudioUnitScope inScope, AudioUnitElement inElement)
{
return *GetScope(inScope).GetIOElement(inElement);
}

AUSDK_DEPRECATED("Use Element()")
AUElement* SafeGetElement(AudioUnitScope inScope, AudioUnitElement inElement)
{
return &Element(inScope, inElement);
}

AUElement& Element(AudioUnitScope inScope, AudioUnitElement inElement)
{
return *GetScope(inScope).SafeGetElement(inElement);
}

AUSDK_DEPRECATED("Use Input()")
AUInputElement* GetInput(AudioUnitElement inElement) { return &Input(inElement); }
AUInputElement& Input(AudioUnitElement inElement)
{
return static_cast<AUInputElement&>(*Inputs().SafeGetElement(inElement)); // NOLINT downcast
}

AUSDK_DEPRECATED("Use Output()")
AUOutputElement* GetOutput(AudioUnitElement inElement) { return &Output(inElement); }
AUOutputElement& Output(AudioUnitElement inElement)
{
return static_cast<AUOutputElement&>( // NOLINT downcast
*Outputs().SafeGetElement(inElement));
}

AUSDK_DEPRECATED("Use Group()")
AUElement* GetGroup(AudioUnitElement inElement) { return &Group(inElement); }
AUElement& Group(AudioUnitElement inElement) { return *Groups().SafeGetElement(inElement); }

OSStatus PullInput(UInt32 inBusNumber, AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, UInt32 inNumberFrames)
{
AUInputElement& input = Input(inBusNumber); // throws if error
return input.PullInput(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
}

[[nodiscard]] UInt32 GetMaxFramesPerSlice() const noexcept { return mMaxFramesPerSlice; }

[[nodiscard]] bool UsesFixedBlockSize() const noexcept { return mUsesFixedBlockSize; }

void SetUsesFixedBlockSize(bool inUsesFixedBlockSize) noexcept
{
mUsesFixedBlockSize = inUsesFixedBlockSize;
}

[[nodiscard]] virtual bool InRenderThread() const
{
return std::this_thread::get_id() == mRenderThreadID;
}

/// Says whether an input is connected or has a callback.
bool HasInput(AudioUnitElement inElement)
{
auto* const in =
static_cast<AUInputElement*>(Inputs().GetElement(inElement)); // NOLINT downcast
return in != nullptr && in->IsActive();
}

virtual void PropertyChanged(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement);

// These calls can be used to call a Host's Callbacks. The method returns -1 if the host
// hasn't supplied the callback. Any other result is returned by the host.
// As in the API contract, for a parameter's value, you specify a pointer
// to that data type. Specify NULL for a parameter that you are not interested
// as this can save work in the host.
OSStatus CallHostBeatAndTempo(Float64* outCurrentBeat, Float64* outCurrentTempo) const
{
return (mHostCallbackInfo.beatAndTempoProc != nullptr
? (*mHostCallbackInfo.beatAndTempoProc)(
mHostCallbackInfo.hostUserData, outCurrentBeat, outCurrentTempo)
: -1);
}

OSStatus CallHostMusicalTimeLocation(UInt32* outDeltaSampleOffsetToNextBeat,
Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator,
Float64* outCurrentMeasureDownBeat) const
{
return (mHostCallbackInfo.musicalTimeLocationProc != nullptr
? (*mHostCallbackInfo.musicalTimeLocationProc)(mHostCallbackInfo.hostUserData,
outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator,
outTimeSig_Denominator, outCurrentMeasureDownBeat)
: -1);
}

OSStatus CallHostTransportState(Boolean* outIsPlaying, Boolean* outTransportStateChanged,
Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, Float64* outCycleStartBeat,
Float64* outCycleEndBeat) const
{
return (mHostCallbackInfo.transportStateProc != nullptr
? (*mHostCallbackInfo.transportStateProc)(mHostCallbackInfo.hostUserData,
outIsPlaying, outTransportStateChanged, outCurrentSampleInTimeLine,
outIsCycling, outCycleStartBeat, outCycleEndBeat)
: -1);
}

[[nodiscard]] const char* GetLoggingString() const noexcept;

AUMutex* GetMutex() noexcept { return mAUMutex; }
// The caller of SetMutex is responsible for the managing the lifetime of the
// mutex object and, if deleted before the AUBase instance, is responsible
// for calling SetMutex(nullptr)
void SetMutex(AUMutex* mutex) noexcept { mAUMutex = mutex; }

#pragma mark -
#pragma mark AU Output Base Dispatch
// ________________________________________________________________________
// ________________________________________________________________________
// ________________________________________________________________________
// output unit methods
virtual OSStatus Start() { return kAudio_UnimplementedError; }

virtual OSStatus Stop() { return kAudio_UnimplementedError; }

#pragma mark -
#pragma mark AU Music Base Dispatch
// ________________________________________________________________________
// ________________________________________________________________________
// ________________________________________________________________________
// music device/music effect methods

virtual OSStatus MIDIEvent(
UInt32 /*inStatus*/, UInt32 /*inData1*/, UInt32 /*inData2*/, UInt32 /*inOffsetSampleFrame*/)
{
return kAudio_UnimplementedError;
}

virtual OSStatus SysEx(const UInt8* /*inData*/, UInt32 /*inLength*/)
{
return kAudio_UnimplementedError;
}

#if AUSDK_MIDI2_AVAILABLE
virtual OSStatus MIDIEventList(
UInt32 /*inOffsetSampleFrame*/, const MIDIEventList* /*eventList*/)
{
return kAudio_UnimplementedError;
}
#endif

virtual OSStatus StartNote(MusicDeviceInstrumentID /*inInstrument*/,
MusicDeviceGroupID /*inGroupID*/, NoteInstanceID* /*outNoteInstanceID*/,
UInt32 /*inOffsetSampleFrame*/, const MusicDeviceNoteParams& /*inParams*/)
{
return kAudio_UnimplementedError;
}

virtual OSStatus StopNote(MusicDeviceGroupID /*inGroupID*/, NoteInstanceID /*inNoteInstanceID*/,
UInt32 /*inOffsetSampleFrame*/)
{
return kAudio_UnimplementedError;
}

/// Obsolete
static OSStatus PrepareInstrument(MusicDeviceInstrumentID /*inInstrument*/)
{
return kAudio_UnimplementedError;
}

/// Obsolete
static OSStatus ReleaseInstrument(MusicDeviceInstrumentID /*inInstrument*/)
{
return kAudio_UnimplementedError;
}

// ________________________________________________________________________
// ________________________________________________________________________
// ________________________________________________________________________

protected:
#pragma mark -
#pragma mark Implementation methods
void PostConstructorInternal() final;
void PreDestructorInternal() final;

/// needs to be called when mMaxFramesPerSlice changes
virtual void ReallocateBuffers();

virtual void DeallocateIOBuffers();

static void FillInParameterName(
AudioUnitParameterInfo& ioInfo, CFStringRef inName, bool inShouldRelease)
{
ioInfo.cfNameString = inName;
ioInfo.flags |= kAudioUnitParameterFlag_HasCFNameString;
if (inShouldRelease) {
ioInfo.flags |= kAudioUnitParameterFlag_CFNameRelease;
}
CFStringGetCString(inName, &ioInfo.name[0], offsetof(AudioUnitParameterInfo, clumpID),
kCFStringEncodingUTF8);
}

static void HasClump(AudioUnitParameterInfo& ioInfo, UInt32 inClumpID) noexcept
{
ioInfo.clumpID = inClumpID;
ioInfo.flags |= kAudioUnitParameterFlag_HasClump;
}

virtual void SetMaxFramesPerSlice(UInt32 nFrames);

[[nodiscard]] virtual OSStatus CanSetMaxFrames() const;

[[nodiscard]] bool WantsRenderThreadID() const noexcept { return mWantsRenderThreadID; }

void SetWantsRenderThreadID(bool inFlag);

OSStatus SetRenderError(OSStatus inErr)
{
if (inErr != noErr && mLastRenderError == 0) {
mLastRenderError = inErr;
PropertyChanged(kAudioUnitProperty_LastRenderError, kAudioUnitScope_Global, 0);
}
return inErr;
}

struct PropertyListener {
AudioUnitPropertyID propertyID{ 0 };
AudioUnitPropertyListenerProc listenerProc{ nullptr };
void* listenerRefCon{ nullptr };
};
using PropertyListeners = std::vector<PropertyListener>;

[[nodiscard]] const PropertyListeners& GetPropertyListeners() const noexcept
{
return mPropertyListeners;
}

HostCallbackInfo& GetHostCallbackInfo() noexcept { return mHostCallbackInfo; }

private:
// shared between Render and RenderSlice, inlined to minimize function call overhead
OSStatus DoRenderBus(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, UInt32 inBusNumber, AUOutputElement& theOutput,
UInt32 inNumberFrames, AudioBufferList& ioData)
{
if (ioData.mBuffers[0].mData == nullptr ||
(theOutput.WillAllocateBuffer() && Outputs().GetNumberOfElements() > 1)) {
// will render into cache buffer
theOutput.PrepareBuffer(inNumberFrames);
} else {
// will render into caller's buffer
theOutput.SetBufferList(ioData);
}
const OSStatus result = RenderBus(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
if (result == noErr) {
if (ioData.mBuffers[0].mData == nullptr) {
theOutput.CopyBufferListTo(ioData);
} else {
theOutput.CopyBufferContentsTo(ioData);
theOutput.InvalidateBufferList();
}
}
return result;
}

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,
AudioChannelLayout* outLayoutPtr, bool& outWritable);

/// Layout is non-null.
virtual OSStatus SetAudioChannelLayout(
AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout);

virtual OSStatus RemoveAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element);

virtual std::vector<AudioChannelLayoutTag> GetChannelLayoutTags(
AudioUnitScope scope, AudioUnitElement element);

bool NeedsToRender(const AudioTimeStamp& inTimeStamp)
{
const bool needsToRender = (inTimeStamp.mSampleTime != mCurrentRenderTime.mSampleTime);
if (needsToRender) { // only copy this if we need to render
mCurrentRenderTime = inTimeStamp;
}
return needsToRender;
}

// Scheduled parameter implementation:

using ParameterEventList = std::vector<AudioUnitParameterEvent>;

// Usually, you won't override this method. You only need to call this if your DSP code
// is prepared to handle scheduled immediate and ramped parameter changes.
// Before calling this method, it is assumed you have already called PullInput() on the input
// busses for which the DSP code depends. ProcessForScheduledParams() will call (potentially
// repeatedly) virtual method ProcessScheduledSlice() to perform the actual DSP for a given
// sub-division of the buffer. The job of ProcessForScheduledParams() is to sub-divide the
// buffer into smaller pieces according to the scheduled times found in the ParameterEventList
// (usually coming directly from a previous call to ScheduleParameter() ), setting the
// appropriate immediate or ramped parameter values for the corresponding scopes and elements,
// then calling ProcessScheduledSlice() to do the actual DSP for each of these divisions.
virtual OSStatus ProcessForScheduledParams(
ParameterEventList& inParamList, UInt32 inFramesToProcess, void* inUserData);

// This method is called (potentially repeatedly) by ProcessForScheduledParams()
// in order to perform the actual DSP required for this portion of the entire buffer
// being processed. The entire buffer can be divided up into smaller "slices"
// according to the timestamps on the scheduled parameters...
//
// sub-classes wishing to handle scheduled parameter changes should override this method
// in order to do the appropriate DSP. AUEffectBase already overrides this for standard
// effect AudioUnits.
virtual OSStatus ProcessScheduledSlice(void* /*inUserData*/, UInt32 /*inStartFrameInBuffer*/,
UInt32 /*inSliceFramesToProcess*/, UInt32 /*inTotalBufferFrames*/)
{
// default implementation does nothing.
return noErr;
}

[[nodiscard]] const AudioTimeStamp& CurrentRenderTime() const noexcept
{
return mCurrentRenderTime;
}
void ResetRenderTime();

// ________________________________________________________________________
// Private data members to discourage hacking in subclasses
private:
struct RenderCallback {
RenderCallback() = default;

RenderCallback(AURenderCallback proc, void* ref)
: mRenderNotify(proc), mRenderNotifyRefCon(ref)
{
}

AURenderCallback mRenderNotify = nullptr;
void* mRenderNotifyRefCon = nullptr;

bool operator==(const RenderCallback& other) const
{
return this->mRenderNotify == other.mRenderNotify &&
this->mRenderNotifyRefCon == other.mRenderNotifyRefCon;
}
};

class RenderCallbackList {
public:
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);
}

void remove(const RenderCallback& rc)
{
const std::lock_guard guard{ mLock };
const auto iter = std::find(mImpl.begin(), mImpl.end(), rc);
if (iter != mImpl.end()) {
mImpl.erase(iter);
}
}

template <typename F>
void foreach (F&& func)
{
const std::lock_guard guard{ mLock };
for (const auto& cb : mImpl) {
func(cb);
}
}

private:
AUMutex mLock;
std::vector<RenderCallback> mImpl;
};

protected:
static constexpr AudioUnitScope kNumScopes = 4;

ParameterEventList& GetParamEventList() noexcept { return mParamEventList; }
void SetBuffersAllocated(bool b) noexcept { mBuffersAllocated = b; }

[[nodiscard]] CFStringRef GetContextName() const { return *mContextName; }
void SetContextName(CFStringRef str) { mContextName = str; }

[[nodiscard]] CFStringRef GetNickName() const { return *mNickName; }

private:
bool mElementsCreated{ false };
bool mInitialized{ false };
bool mHasBegunInitializing{ false };
const UInt32 mInitNumInputEls;
const UInt32 mInitNumOutputEls;
const UInt32 mInitNumGroupEls;
std::array<AUScope, kNumScopes> mScopes;
RenderCallbackList mRenderCallbacks;
bool mRenderCallbacksTouched{ false };
std::thread::id mRenderThreadID{};
bool mWantsRenderThreadID{ false };
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 };

ParameterEventList mParamEventList;
PropertyListeners mPropertyListeners;
bool mBuffersAllocated{ false };
const std::string mLogString;
Owned<CFStringRef> mNickName;

/*! @var mAUMutex
If non-null, guards all non-realtime entry points into the AudioUnit. Most AudioUnits
do not need to use this. It's useful for the case of an AU which must synchronize
an external source of callbacks against entry from the host.
*/
AUMutex* mAUMutex{ nullptr };
HostCallbackInfo mHostCallbackInfo{};
Owned<CFStringRef> mContextName;
};

} // namespace ausdk

#endif // AudioUnitSDK_AUBase_h

+ 188
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.cpp View File

@@ -0,0 +1,188 @@
/*!
@file AudioUnitSDK/AUBuffer.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUBuffer.h>
#include <AudioUnitSDK/AUUtility.h>

namespace ausdk {

inline void ThrowBadAlloc()
{
AUSDK_LogError("AUBuffer throwing bad_alloc");
throw std::bad_alloc();
}

// x: number to be rounded; y: the power of 2 to which to round
constexpr uint32_t RoundUpToMultipleOfPowerOf2(uint32_t x, uint32_t y) noexcept
{
const auto mask = y - 1;
#if DEBUG
assert((mask & y) == 0u); // verifies that y is a power of 2 NOLINT
#endif
return (x + mask) & ~mask;
}

// a * b + c
static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c)
{
if (a == 0 || b == 0) {
return c; // prevent zero divide
}

if (a > (0xFFFFFFFF - c) / b) { // NOLINT magic
ThrowBadAlloc();
}

return a * b + c;
}

AllocatedBuffer* BufferAllocator::Allocate(
UInt32 numberBuffers, UInt32 maxBytesPerBuffer, UInt32 /*reservedFlags*/)
{
constexpr size_t kAlignment = 16;
constexpr size_t kMaxBufferListSize = 65536;

// Check for a reasonable number of buffers (obviate a more complicated check with offsetof).
if (numberBuffers > kMaxBufferListSize / sizeof(AudioBuffer)) {
throw std::out_of_range("AudioBuffers::Allocate: Too many buffers");
}

maxBytesPerBuffer = RoundUpToMultipleOfPowerOf2(maxBytesPerBuffer, kAlignment);

const auto bufferDataSize = SafeMultiplyAddUInt32(numberBuffers, maxBytesPerBuffer, 0);
void* bufferData = nullptr;
if (bufferDataSize > 0) {
bufferData = malloc(bufferDataSize);
// don't use calloc(); it might not actually touch the memory and cause a VM fault later
memset(bufferData, 0, bufferDataSize);
}

const auto implSize = static_cast<uint32_t>(
offsetof(AllocatedBuffer, mAudioBufferList.mBuffers[std::max(UInt32(1), numberBuffers)]));
auto* const implMem = malloc(implSize);
auto* const allocatedBuffer =
new (implMem) AllocatedBuffer{ .mMaximumNumberBuffers = numberBuffers,
.mMaximumBytesPerBuffer = maxBytesPerBuffer,
.mHeaderSize = implSize,
.mBufferDataSize = bufferDataSize,
.mBufferData = bufferData };
allocatedBuffer->mAudioBufferList.mNumberBuffers = numberBuffers;
return allocatedBuffer;
}

void BufferAllocator::Deallocate(AllocatedBuffer* allocatedBuffer)
{
if (allocatedBuffer->mBufferData != nullptr) {
free(allocatedBuffer->mBufferData);
}
allocatedBuffer->~AllocatedBuffer();
free(allocatedBuffer);
}


AudioBufferList& AllocatedBuffer::Prepare(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer)
{
if (mAudioBufferList.mNumberBuffers > mMaximumNumberBuffers) {
throw std::out_of_range("AllocatedBuffer::Prepare(): too many buffers");
}
if (bytesPerBuffer > mMaximumBytesPerBuffer) {
throw std::out_of_range("AllocatedBuffer::Prepare(): insufficient capacity");
}

auto* ptr = static_cast<Byte*>(mBufferData);
auto* const ptrend = ptr + mBufferDataSize;

for (UInt32 bufIdx = 0, nBufs = mAudioBufferList.mNumberBuffers; bufIdx < nBufs; ++bufIdx) {
auto& buf = mAudioBufferList.mBuffers[bufIdx]; // NOLINT
buf.mNumberChannels = channelsPerBuffer;
buf.mDataByteSize = bytesPerBuffer;
buf.mData = ptr;
ptr += mMaximumBytesPerBuffer; // NOLINT ptr math
}
if (ptr > ptrend) {
throw std::out_of_range("AllocatedBuffer::Prepare(): insufficient capacity");
}
return mAudioBufferList;
}

AudioBufferList& AllocatedBuffer::PrepareNull(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer)
{
if (mAudioBufferList.mNumberBuffers > mMaximumNumberBuffers) {
throw std::out_of_range("AllocatedBuffer::PrepareNull(): too many buffers");
}
for (UInt32 bufIdx = 0, nBufs = mAudioBufferList.mNumberBuffers; bufIdx < nBufs; ++bufIdx) {
auto& buf = mAudioBufferList.mBuffers[bufIdx]; // NOLINT
buf.mNumberChannels = channelsPerBuffer;
buf.mDataByteSize = bytesPerBuffer;
buf.mData = nullptr;
}
return mAudioBufferList;
}

AudioBufferList& AUBufferList::PrepareBuffer(
const AudioStreamBasicDescription& format, UInt32 nFrames)
{
ausdk::ThrowExceptionIf(nFrames > mAllocatedFrames, kAudioUnitErr_TooManyFramesToProcess);

UInt32 nStreams = 0;
UInt32 channelsPerStream = 0;
if (ASBD::IsInterleaved(format)) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
}

ausdk::ThrowExceptionIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported);
auto& abl = mBuffers->Prepare(channelsPerStream, nFrames * format.mBytesPerFrame);
mPtrState = EPtrState::ToMyMemory;
return abl;
}

AudioBufferList& AUBufferList::PrepareNullBuffer(
const AudioStreamBasicDescription& format, UInt32 nFrames)
{
UInt32 nStreams = 0;
UInt32 channelsPerStream = 0;
if (ASBD::IsInterleaved(format)) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
}

ausdk::ThrowExceptionIf(nStreams > mAllocatedStreams, kAudioUnitErr_FormatNotSupported);
auto& abl = mBuffers->PrepareNull(channelsPerStream, nFrames * format.mBytesPerFrame);
mPtrState = EPtrState::ToExternalMemory;
return abl;
}

void AUBufferList::Allocate(const AudioStreamBasicDescription& format, UInt32 nFrames)
{
auto& alloc = BufferAllocator::instance();
if (mBuffers != nullptr) {
alloc.Deallocate(mBuffers);
}
const uint32_t nstreams = ASBD::IsInterleaved(format) ? 1 : format.mChannelsPerFrame;
mBuffers = alloc.Allocate(nstreams, nFrames * format.mBytesPerFrame, 0u);
mAllocatedFrames = nFrames;
mAllocatedStreams = nstreams;
mPtrState = EPtrState::Invalid;
}

void AUBufferList::Deallocate()
{
if (mBuffers != nullptr) {
BufferAllocator::instance().Deallocate(mBuffers);
mBuffers = nullptr;
}

mAllocatedFrames = 0;
mAllocatedStreams = 0;
mPtrState = EPtrState::Invalid;
}

} // namespace ausdk

+ 166
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBuffer.h View File

@@ -0,0 +1,166 @@
/*!
@file AudioUnitSDK/AUBuffer.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUBuffer_h
#define AudioUnitSDK_AUBuffer_h

#include <AudioUnitSDK/AUUtility.h>

#include <AudioToolbox/AudioUnit.h>

#include <cstddef>
#include <optional>

namespace ausdk {

/// struct created/destroyed by allocator. Do not attempt to manually create/destroy.
struct AllocatedBuffer {
const UInt32 mMaximumNumberBuffers;
const UInt32 mMaximumBytesPerBuffer;
const UInt32 mReservedA[2]; // NOLINT C-style array
const UInt32 mHeaderSize;
const UInt32 mBufferDataSize;
const UInt32 mReservedB[2]; // NOLINT C-style array
void* const mBufferData;
void* const mReservedC;

AudioBufferList mAudioBufferList;
// opaque variable-length data may follow the AudioBufferList

AudioBufferList& Prepare(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer);
AudioBufferList& PrepareNull(UInt32 channelsPerBuffer, UInt32 bytesPerBuffer);
};

/*!
@class BufferAllocator
@brief Class which allocates memory for internal audio buffers.

To customize, create a subclass and install an instance into the global via set_instance().
*/
class BufferAllocator {
public:
/// Obtain the global instance, creating it if necessary.
static BufferAllocator& instance();

/// A client may install a custom global instance via this method. Throws an exception if
/// a default instance has already been created.
static void set_instance(BufferAllocator& instance);

BufferAllocator() = default;
virtual ~BufferAllocator() = default;

// Rule of 5
BufferAllocator(const BufferAllocator&) = delete;
BufferAllocator(BufferAllocator&&) = delete;
BufferAllocator& operator=(const BufferAllocator&) = delete;
BufferAllocator& operator=(BufferAllocator&&) = delete;

// N.B. Must return zeroed memory aligned to at least 16 bytes.
virtual AllocatedBuffer* Allocate(
UInt32 numberBuffers, UInt32 maxBytesPerBuffer, UInt32 reservedFlags);
virtual void Deallocate(AllocatedBuffer* allocatedBuffer);
};

/*!
@class AUBufferList
@brief Manages an `AudioBufferList` backed by allocated memory buffers.
*/
class AUBufferList {
enum class EPtrState { Invalid, ToMyMemory, ToExternalMemory };

public:
AUBufferList() = default;
~AUBufferList() { Deallocate(); }

AUBufferList(const AUBufferList&) = delete;
AUBufferList(AUBufferList&&) = delete;
AUBufferList& operator=(const AUBufferList&) = delete;
AUBufferList& operator=(AUBufferList&&) = delete;

AudioBufferList& PrepareBuffer(const AudioStreamBasicDescription& format, UInt32 nFrames);
AudioBufferList& PrepareNullBuffer(const AudioStreamBasicDescription& format, UInt32 nFrames);

AudioBufferList& SetBufferList(const AudioBufferList& abl)
{
ausdk::ThrowExceptionIf(mAllocatedStreams < abl.mNumberBuffers, -1);
mPtrState = EPtrState::ToExternalMemory;
auto& myabl = mBuffers->mAudioBufferList;
memcpy(&myabl, &abl,
static_cast<size_t>(
reinterpret_cast<const std::byte*>(&abl.mBuffers[abl.mNumberBuffers]) - // NOLINT
reinterpret_cast<const std::byte*>(&abl))); // NOLINT
return myabl;
}

void SetBuffer(UInt32 index, const AudioBuffer& ab)
{
auto& myabl = mBuffers->mAudioBufferList;
ausdk::ThrowExceptionIf(
mPtrState == EPtrState::Invalid || index >= myabl.mNumberBuffers, -1);
mPtrState = EPtrState::ToExternalMemory;
myabl.mBuffers[index] = ab; // NOLINT
}

void InvalidateBufferList() noexcept { mPtrState = EPtrState::Invalid; }

[[nodiscard]] AudioBufferList& GetBufferList() const
{
ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1);
return mBuffers->mAudioBufferList;
}

void CopyBufferListTo(AudioBufferList& abl) const
{
ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1);
memcpy(&abl, &mBuffers->mAudioBufferList,
static_cast<size_t>(
reinterpret_cast<std::byte*>(&abl.mBuffers[abl.mNumberBuffers]) - // NOLINT
reinterpret_cast<std::byte*>(&abl))); // NOLINT
}

void CopyBufferContentsTo(AudioBufferList& destabl) const
{
ausdk::ThrowExceptionIf(mPtrState == EPtrState::Invalid, -1);
const auto& srcabl = mBuffers->mAudioBufferList;
const AudioBuffer* srcbuf = srcabl.mBuffers; // NOLINT
AudioBuffer* destbuf = destabl.mBuffers; // NOLINT

for (UInt32 i = 0; i < destabl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) { // NOLINT
if (i >=
srcabl.mNumberBuffers) { // duplicate last source to additional outputs [4341137]
--srcbuf; // NOLINT
}
if (destbuf->mData != srcbuf->mData) {
memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
}
destbuf->mDataByteSize = srcbuf->mDataByteSize;
}
}

void Allocate(const AudioStreamBasicDescription& format, UInt32 nFrames);

void Deallocate();

// AudioBufferList utilities
static void ZeroBuffer(AudioBufferList& abl)
{
AudioBuffer* buf = abl.mBuffers; // NOLINT
for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++buf) { // NOLINT
memset(buf->mData, 0, buf->mDataByteSize);
}
}

[[nodiscard]] UInt32 GetAllocatedFrames() const noexcept { return mAllocatedFrames; }

private:
EPtrState mPtrState{ EPtrState::Invalid };
AllocatedBuffer* mBuffers = nullptr; // only valid between Allocate and Deallocate

UInt32 mAllocatedStreams{ 0 };
UInt32 mAllocatedFrames{ 0 };
};

} // namespace ausdk

#endif // AudioUnitSDK_AUBuffer_h

+ 15
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUBufferAllocator.cpp View File

@@ -0,0 +1,15 @@
/*!
@file AudioUnitSDK/AUBufferAllocator.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUBuffer.h>

namespace ausdk {

BufferAllocator& BufferAllocator::instance()
{
__attribute__((no_destroy)) static BufferAllocator global;
return global;
}

} // namespace ausdk

+ 400
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.cpp View File

@@ -0,0 +1,400 @@
/*!
@file AudioUnitSDK/AUEffectBase.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUEffectBase.h>

#include <cstddef>

/*
This class does not deal as well as it should with N-M effects...

The problem areas are (if the channels don't match):
ProcessInPlace if the channels don't match - there will be problems if InputChan !=
OutputChan Bypass - its just passing the buffers through when not processing them
*/

namespace ausdk {

//_____________________________________________________________________________
//
AUEffectBase::AUEffectBase(AudioComponentInstance audioUnit, bool inProcessesInPlace)
: AUBase(audioUnit, 1, 1), // 1 in bus, 1 out bus
mProcessesInPlace(inProcessesInPlace)
#if TARGET_OS_IPHONE
,
mOnlyOneKernel(false)
#endif
{
}

//_____________________________________________________________________________
//
void AUEffectBase::Cleanup()
{
mKernelList.clear();
mMainOutput = nullptr;
mMainInput = nullptr;
}


//_____________________________________________________________________________
//
OSStatus AUEffectBase::Initialize()
{
// get our current numChannels for input and output
const auto auNumInputs = static_cast<SInt16>(Input(0).GetStreamFormat().mChannelsPerFrame);
const auto auNumOutputs = static_cast<SInt16>(Output(0).GetStreamFormat().mChannelsPerFrame);

// does the unit publish specific information about channel configurations?
const AUChannelInfo* auChannelConfigs = nullptr;
const UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);

if ((numIOconfigs > 0) && (auChannelConfigs != nullptr)) {
bool foundMatch = false;
for (UInt32 i = 0; (i < numIOconfigs) && !foundMatch; ++i) {
const SInt16 configNumInputs = auChannelConfigs[i].inChannels; // NOLINT
const SInt16 configNumOutputs = auChannelConfigs[i].outChannels; // NOLINT
if ((configNumInputs < 0) && (configNumOutputs < 0)) {
// unit accepts any number of channels on input and output
if (((configNumInputs == -1) && (configNumOutputs == -2)) ||
((configNumInputs == -2) &&
(configNumOutputs == -1))) { // NOLINT repeated branch below
foundMatch = true;
// unit accepts any number of channels on input and output IFF they are the same
// number on both scopes
} else if (((configNumInputs == -1) && (configNumOutputs == -1)) &&
(auNumInputs == auNumOutputs)) {
foundMatch = true;
// unit has specified a particular number of channels on both scopes
} else {
continue;
}
} else {
// the -1 case on either scope is saying that the unit doesn't care about the
// number of channels on that scope
const bool inputMatch = (auNumInputs == configNumInputs) || (configNumInputs == -1);
const bool outputMatch =
(auNumOutputs == configNumOutputs) || (configNumOutputs == -1);
if (inputMatch && outputMatch) {
foundMatch = true;
}
}
}
if (!foundMatch) {
return kAudioUnitErr_FormatNotSupported;
}
} else {
// there is no specifically published channel info
// so for those kinds of effects, the assumption is that the channels (whatever their
// number) should match on both scopes
if ((auNumOutputs != auNumInputs) || (auNumOutputs == 0)) {
return kAudioUnitErr_FormatNotSupported;
}
}
MaintainKernels();

mMainOutput = &Output(0);
mMainInput = &Input(0);

const AudioStreamBasicDescription format = GetStreamFormat(kAudioUnitScope_Output, 0);
mBytesPerFrame = format.mBytesPerFrame;

return noErr;
}

OSStatus AUEffectBase::Reset(AudioUnitScope inScope, AudioUnitElement inElement)
{
for (auto& kernel : mKernelList) {
if (kernel) {
kernel->Reset();
}
}

return AUBase::Reset(inScope, inElement);
}

OSStatus AUEffectBase::GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable)
{
if (inScope == kAudioUnitScope_Global) {
switch (inID) {
case kAudioUnitProperty_BypassEffect:
case kAudioUnitProperty_InPlaceProcessing:
outWritable = true;
outDataSize = sizeof(UInt32);
return noErr;
default:
break;
}
}
return AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
}


OSStatus AUEffectBase::GetProperty(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData)
{
if (inScope == kAudioUnitScope_Global) {
switch (inID) {
case kAudioUnitProperty_BypassEffect:
*static_cast<UInt32*>(outData) = (IsBypassEffect() ? 1 : 0); // NOLINT
return noErr;
case kAudioUnitProperty_InPlaceProcessing:
*static_cast<UInt32*>(outData) = (mProcessesInPlace ? 1 : 0); // NOLINT
return noErr;
default:
break;
}
}
return AUBase::GetProperty(inID, inScope, inElement, outData);
}


OSStatus AUEffectBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
{
if (inScope == kAudioUnitScope_Global) {
switch (inID) {
case kAudioUnitProperty_BypassEffect: {
if (inDataSize < sizeof(UInt32)) {
return kAudioUnitErr_InvalidPropertyValue;
}

const bool tempNewSetting = *static_cast<const UInt32*>(inData) != 0;
// we're changing the state of bypass
if (tempNewSetting != IsBypassEffect()) {
if (!tempNewSetting && IsBypassEffect() &&
IsInitialized()) { // turning bypass off and we're initialized
Reset(kAudioUnitScope_Global, 0);
}
SetBypassEffect(tempNewSetting);
}
return noErr;
}
case kAudioUnitProperty_InPlaceProcessing:
mProcessesInPlace = *static_cast<const UInt32*>(inData) != 0;
return noErr;
default:
break;
}
}
return AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
}


void AUEffectBase::MaintainKernels()
{
#if TARGET_OS_IPHONE
const UInt32 nKernels = mOnlyOneKernel ? 1 : GetNumberOfChannels();
#else
const UInt32 nKernels = GetNumberOfChannels();
#endif

if (mKernelList.size() < nKernels) {
mKernelList.reserve(nKernels);
for (auto i = static_cast<UInt32>(mKernelList.size()); i < nKernels; ++i) {
mKernelList.push_back(NewKernel());
}
} else {
while (mKernelList.size() > nKernels) {
mKernelList.pop_back();
}
}

for (UInt32 i = 0; i < nKernels; i++) {
if (mKernelList[i]) {
mKernelList[i]->SetChannelNum(i);
}
}
}

bool AUEffectBase::StreamFormatWritable(AudioUnitScope /*scope*/, AudioUnitElement /*element*/)
{
return !IsInitialized();
}

OSStatus AUEffectBase::ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement,
const AudioStreamBasicDescription& inPrevFormat, const AudioStreamBasicDescription& inNewFormat)
{
const OSStatus result =
AUBase::ChangeStreamFormat(inScope, inElement, inPrevFormat, inNewFormat);
if (result == noErr) {
// for the moment this only dependency we know about
// where a parameter's range may change is with the sample rate
// and effects are only publishing parameters in the global scope!
if (GetParamHasSampleRateDependency() &&
inPrevFormat.mSampleRate != inNewFormat.mSampleRate) {
PropertyChanged(kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0);
}
}

return result;
}


// ____________________________________________________________________________
//
// This method is called (potentially repeatedly) by ProcessForScheduledParams()
// in order to perform the actual DSP required for this portion of the entire buffer
// being processed. The entire buffer can be divided up into smaller "slices"
// according to the timestamps on the scheduled parameters...
//
OSStatus AUEffectBase::ProcessScheduledSlice(void* inUserData, UInt32 /*inStartFrameInBuffer*/,
UInt32 inSliceFramesToProcess, UInt32 /*inTotalBufferFrames*/)
{
const ScheduledProcessParams& sliceParams = *static_cast<ScheduledProcessParams*>(inUserData);

AudioUnitRenderActionFlags& actionFlags = *sliceParams.actionFlags;
AudioBufferList& inputBufferList = *sliceParams.inputBufferList;
AudioBufferList& outputBufferList = *sliceParams.outputBufferList;

UInt32 channelSize = inSliceFramesToProcess * mBytesPerFrame;
// fix the size of the buffer we're operating on before we render this slice of time
for (UInt32 i = 0; i < inputBufferList.mNumberBuffers; i++) {
inputBufferList.mBuffers[i].mDataByteSize = // NOLINT
inputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT
}

for (UInt32 i = 0; i < outputBufferList.mNumberBuffers; i++) {
outputBufferList.mBuffers[i].mDataByteSize = // NOLINT
outputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT
}
// process the buffer
const OSStatus result =
ProcessBufferLists(actionFlags, inputBufferList, outputBufferList, inSliceFramesToProcess);

// we just partially processed the buffers, so increment the data pointers to the next part of
// the buffer to process
for (UInt32 i = 0; i < inputBufferList.mNumberBuffers; i++) {
inputBufferList.mBuffers[i].mData = // NOLINT
static_cast<std::byte*>(inputBufferList.mBuffers[i].mData) + // NOLINT
inputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT
}

for (UInt32 i = 0; i < outputBufferList.mNumberBuffers; i++) {
outputBufferList.mBuffers[i].mData = // NOLINT
static_cast<std::byte*>(outputBufferList.mBuffers[i].mData) + // NOLINT
outputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT
}

return result;
}

// ____________________________________________________________________________
//

OSStatus AUEffectBase::Render(
AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp, UInt32 nFrames)
{
if (!HasInput(0)) {
return kAudioUnitErr_NoConnection;
}

OSStatus result = noErr;

result = mMainInput->PullInput(ioActionFlags, inTimeStamp, 0 /* element */, nFrames);

if (result == noErr) {
if (ProcessesInPlace() && mMainOutput->WillAllocateBuffer()) {
mMainOutput->SetBufferList(mMainInput->GetBufferList());
}

if (ShouldBypassEffect()) {
// leave silence bit alone

if (!ProcessesInPlace()) {
mMainInput->CopyBufferContentsTo(mMainOutput->GetBufferList());
}
} else {
auto& paramEventList = GetParamEventList();

if (paramEventList.empty()) {
// this will read/write silence bit
result = ProcessBufferLists(ioActionFlags, mMainInput->GetBufferList(),
mMainOutput->GetBufferList(), nFrames);
} else {
// deal with scheduled parameters...

AudioBufferList& inputBufferList = mMainInput->GetBufferList();
AudioBufferList& outputBufferList = mMainOutput->GetBufferList();

ScheduledProcessParams processParams{ .actionFlags = &ioActionFlags,
.inputBufferList = &inputBufferList,
.outputBufferList = &outputBufferList };

// divide up the buffer into slices according to scheduled params then
// do the DSP for each slice (ProcessScheduledSlice() called for each slice)
result = ProcessForScheduledParams(paramEventList, nFrames, &processParams);


// fixup the buffer pointers to how they were before we started
const UInt32 channelSize = nFrames * mBytesPerFrame;
for (UInt32 i = 0; i < inputBufferList.mNumberBuffers; i++) {
const UInt32 size =
inputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT
inputBufferList.mBuffers[i].mData = // NOLINT
static_cast<std::byte*>(inputBufferList.mBuffers[i].mData) - size; // NOLINT
inputBufferList.mBuffers[i].mDataByteSize = size; // NOLINT
}

for (UInt32 i = 0; i < outputBufferList.mNumberBuffers; i++) {
const UInt32 size =
outputBufferList.mBuffers[i].mNumberChannels * channelSize; // NOLINT
outputBufferList.mBuffers[i].mData = // NOLINT
static_cast<std::byte*>(outputBufferList.mBuffers[i].mData) -
size; // NOLINT
outputBufferList.mBuffers[i].mDataByteSize = size; // NOLINT
}
}
}

if (((ioActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0u) &&
!ProcessesInPlace()) {
AUBufferList::ZeroBuffer(mMainOutput->GetBufferList());
}
}

return result;
}


OSStatus AUEffectBase::ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags,
const AudioBufferList& inBuffer, AudioBufferList& outBuffer, UInt32 inFramesToProcess)
{
if (ShouldBypassEffect()) {
return noErr;
}

bool ioSilence = false;

const bool silentInput = IsInputSilent(ioActionFlags, inFramesToProcess);
ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;

for (UInt32 channel = 0; channel < mKernelList.size(); ++channel) {
auto& kernel = mKernelList[channel];

if (!kernel) {
continue;
}

ioSilence = silentInput;
const AudioBuffer* const srcBuffer = &inBuffer.mBuffers[channel]; // NOLINT subscript
AudioBuffer* const destBuffer = &outBuffer.mBuffers[channel]; // NOLINT subscript

kernel->Process(static_cast<const Float32*>(srcBuffer->mData),
static_cast<Float32*>(destBuffer->mData), inFramesToProcess, ioSilence);

if (!ioSilence) {
ioActionFlags &= ~kAudioUnitRenderAction_OutputIsSilence;
}
}

return noErr;
}

Float64 AUEffectBase::GetSampleRate() { return Output(0).GetStreamFormat().mSampleRate; }

UInt32 AUEffectBase::GetNumberOfChannels() { return Output(0).GetStreamFormat().mChannelsPerFrame; }

} // namespace ausdk

+ 194
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUEffectBase.h View File

@@ -0,0 +1,194 @@
/*!
@file AudioUnitSDK/AUEffectBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUEffectBase_h
#define AudioUnitSDK_AUEffectBase_h

#include <AudioUnitSDK/AUBase.h>
#include <AudioUnitSDK/AUSilentTimeout.h>

#include <memory>

namespace ausdk {

class AUKernelBase;

/*!
@class AUEffectBase
@brief Base class for an effect with one input stream, one output stream, and any number of
channels.
*/
class AUEffectBase : public AUBase {
public:
explicit AUEffectBase(AudioComponentInstance audioUnit, bool inProcessesInPlace = true);

AUEffectBase(const AUEffectBase&) = delete;
AUEffectBase(AUEffectBase&&) = delete;
AUEffectBase& operator=(const AUEffectBase&) = delete;
AUEffectBase& operator=(AUEffectBase&&) = delete;

~AUEffectBase() override = default;

OSStatus Initialize() override;
void Cleanup() override;
OSStatus Reset(AudioUnitScope inScope, AudioUnitElement inElement) override;
OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) override;
OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData) override;
OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize) override;
bool StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) override;
OSStatus ChangeStreamFormat(AudioUnitScope inScope, AudioUnitElement inElement,
const AudioStreamBasicDescription& inPrevFormat,
const AudioStreamBasicDescription& inNewFormat) override;
OSStatus Render(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp,
UInt32 nFrames) override;

// our virtual methods

// If your unit processes N to N channels, and there are no interactions between channels,
// it can override NewKernel to create a mono processing object per channel. Otherwise,
// don't override NewKernel, and instead, override ProcessBufferLists.
virtual std::unique_ptr<AUKernelBase> NewKernel() { return {}; }
OSStatus ProcessBufferLists(AudioUnitRenderActionFlags& ioActionFlags,
const AudioBufferList& inBuffer, AudioBufferList& outBuffer,
UInt32 inFramesToProcess) override;

// convenience format accessors (use output 0's format)
Float64 GetSampleRate();
UInt32 GetNumberOfChannels();

// convenience wrappers for accessing parameters in the global scope
using AUBase::SetParameter;

void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value)
{
Globals()->SetParameter(paramID, value);
}

using AUBase::GetParameter;

AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID)
{
return Globals()->GetParameter(paramID);
}

[[nodiscard]] bool CanScheduleParameters() const override { return true; }

// This is used for the property value - to reflect to the UI if an effect is bypassed
[[nodiscard]] bool IsBypassEffect() const noexcept { return mBypassEffect; }

virtual void SetBypassEffect(bool inFlag) { mBypassEffect = inFlag; }

void SetParamHasSampleRateDependency(bool inFlag) noexcept { mParamSRDep = inFlag; }
[[nodiscard]] bool GetParamHasSampleRateDependency() const noexcept { return mParamSRDep; }

/// Context, passed as `void* userData`, for `ProcessScheduledSlice()`.
struct ScheduledProcessParams {
AudioUnitRenderActionFlags* actionFlags = nullptr;
AudioBufferList* inputBufferList = nullptr;
AudioBufferList* outputBufferList = nullptr;
};

OSStatus ProcessScheduledSlice(void* inUserData, UInt32 inStartFrameInBuffer,
UInt32 inSliceFramesToProcess, UInt32 inTotalBufferFrames) override;

[[nodiscard]] bool ProcessesInPlace() const noexcept { return mProcessesInPlace; }
void SetProcessesInPlace(bool inProcessesInPlace) noexcept
{
mProcessesInPlace = inProcessesInPlace;
}

using KernelList = std::vector<std::unique_ptr<AUKernelBase>>;

protected:
void MaintainKernels();

// This is used in the render call to see if an effect is bypassed
// It can return a different status than IsBypassEffect (though it MUST take that into account)
virtual bool ShouldBypassEffect() { return IsBypassEffect(); }

[[nodiscard]] AUKernelBase* GetKernel(UInt32 index) const
{
return (index < mKernelList.size()) ? mKernelList[index].get() : nullptr;
}
[[nodiscard]] const KernelList& GetKernelList() const noexcept { return mKernelList; }

bool IsInputSilent(AudioUnitRenderActionFlags inActionFlags, UInt32 inFramesToProcess)
{
bool inputSilent = (inActionFlags & kAudioUnitRenderAction_OutputIsSilence) != 0;

// take latency and tail time into account when propagating the silent bit
const auto silentTimeoutFrames =
static_cast<UInt32>(GetSampleRate() * (GetLatency() + GetTailTime()));
mSilentTimeout.Process(inFramesToProcess, silentTimeoutFrames, inputSilent);
return inputSilent;
}

#if TARGET_OS_IPHONE
void SetOnlyOneKernel(bool inUseOnlyOneKernel) noexcept
{
mOnlyOneKernel = inUseOnlyOneKernel;
} // set in ctor of subclass that wants it.
#endif

private:
KernelList mKernelList;
bool mBypassEffect{ false };
bool mParamSRDep{ false };
bool mProcessesInPlace;
AUSilentTimeout mSilentTimeout;
AUOutputElement* mMainOutput{ nullptr };
AUInputElement* mMainInput{ nullptr };

#if TARGET_OS_IPHONE
bool mOnlyOneKernel;
#endif
UInt32 mBytesPerFrame = 0;
};


/*!
@class AUKernelBase
@brief Base class for a signal-processing "kernel", an object that performs DSP on one channel
of an audio stream.
*/
class AUKernelBase {
public:
explicit AUKernelBase(AUEffectBase& inAudioUnit) : mAudioUnit(inAudioUnit) {}

AUSDK_DEPRECATED("Construct with a reference")
explicit AUKernelBase(AUEffectBase* inAudioUnit) : mAudioUnit(*inAudioUnit) {}

AUKernelBase(const AUKernelBase&) = delete;
AUKernelBase(AUKernelBase&&) = delete;
AUKernelBase& operator=(const AUKernelBase&) = delete;
AUKernelBase& operator=(AUKernelBase&&) = delete;

virtual ~AUKernelBase() = default;

virtual void Reset() {}

virtual void Process(const Float32* /*inSourceP*/, Float32* /*inDestP*/,
UInt32 /*inFramesToProcess*/, bool& /*ioSilence*/) = 0;

Float64 GetSampleRate() { return mAudioUnit.GetSampleRate(); }

AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID)
{
return mAudioUnit.GetParameter(paramID);
}

void SetChannelNum(UInt32 inChan) noexcept { mChannelNum = inChan; }
[[nodiscard]] UInt32 GetChannelNum() const noexcept { return mChannelNum; }

protected:
AUEffectBase& mAudioUnit; // NOLINT protected
UInt32 mChannelNum = 0; // NOLINT protected
};

} // namespace ausdk

#endif // AudioUnitSDK_AUEffectBase_h

+ 85
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.cpp View File

@@ -0,0 +1,85 @@
/*!
@file AudioUnitSDK/AUInputElement.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUBase.h>

namespace ausdk {

constexpr bool HasGoodBufferPointers(const AudioBufferList& abl, UInt32 nBytes) noexcept
{
const AudioBuffer* buf = abl.mBuffers; // NOLINT
for (UInt32 i = abl.mNumberBuffers; i-- > 0; ++buf) { // NOLINT
if (buf->mData == nullptr || buf->mDataByteSize < nBytes) {
return false;
}
}
return true;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::SetConnection
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AUInputElement::SetConnection(const AudioUnitConnection& conn)
{
if (conn.sourceAudioUnit == nullptr) {
Disconnect();
return;
}

mInputType = EInputType::FromConnection;
mConnection = conn;
AllocateBuffer();
}

void AUInputElement::Disconnect()
{
mInputType = EInputType::NoInput;
IOBuffer().Deallocate();
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::SetInputCallback
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AUInputElement::SetInputCallback(AURenderCallback proc, void* refCon)
{
if (proc == nullptr) {
Disconnect();
} else {
mInputType = EInputType::FromCallback;
mInputProc = proc;
mInputProcRefCon = refCon;
AllocateBuffer();
}
}

OSStatus AUInputElement::SetStreamFormat(const AudioStreamBasicDescription& fmt)
{
const OSStatus err = AUIOElement::SetStreamFormat(fmt);
if (err == noErr) {
AllocateBuffer();
}
return err;
}

OSStatus AUInputElement::PullInput(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, AudioUnitElement inElement, UInt32 nFrames)
{
if (!IsActive()) {
return kAudioUnitErr_NoConnection;
}

auto& iob = IOBuffer();

AudioBufferList& pullBuffer = (HasConnection() || !WillAllocateBuffer())
? iob.PrepareNullBuffer(GetStreamFormat(), nFrames)
: iob.PrepareBuffer(GetStreamFormat(), nFrames);

return PullInputWithBufferList(ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer);
}

} // namespace ausdk

+ 91
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUInputElement.h View File

@@ -0,0 +1,91 @@
/*!
@file AudioUnitSDK/AUInputElement.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUInputElement_h
#define AudioUnitSDK_AUInputElement_h

#include <AudioUnitSDK/AUBuffer.h>
#include <AudioUnitSDK/AUScopeElement.h>

namespace ausdk {

/*!
@class AUInputElement
@brief Implements an audio unit input element, managing the source of input from a callback
or connection.
*/
class AUInputElement : public AUIOElement {
public:
using AUIOElement::AUIOElement;

// AUElement override
OSStatus SetStreamFormat(const AudioStreamBasicDescription& fmt) override;
[[nodiscard]] bool NeedsBufferSpace() const override { return IsCallback(); }
void SetConnection(const AudioUnitConnection& conn);
void SetInputCallback(AURenderCallback proc, void* refCon);
[[nodiscard]] bool IsActive() const noexcept { return mInputType != EInputType::NoInput; }
[[nodiscard]] bool IsCallback() const noexcept
{
return mInputType == EInputType::FromCallback;
}
[[nodiscard]] bool HasConnection() const noexcept
{
return mInputType == EInputType::FromConnection;
}
OSStatus PullInput(AudioUnitRenderActionFlags& ioActionFlags, const AudioTimeStamp& inTimeStamp,
AudioUnitElement inElement, UInt32 nFrames);
OSStatus PullInputWithBufferList(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, AudioUnitElement inElement, UInt32 nFrames,
AudioBufferList& inBufferList);

protected:
void Disconnect();

private:
enum class EInputType { NoInput, FromConnection, FromCallback };
EInputType mInputType{ EInputType::NoInput };

// if from callback:
AURenderCallback mInputProc{ nullptr };
void* mInputProcRefCon{ nullptr };

// if from connection:
AudioUnitConnection mConnection{};
};

inline OSStatus AUInputElement::PullInputWithBufferList(AudioUnitRenderActionFlags& ioActionFlags,
const AudioTimeStamp& inTimeStamp, AudioUnitElement inElement, UInt32 nFrames,
AudioBufferList& inBufferList)
{
OSStatus theResult = noErr;

if (HasConnection()) {
// only support connections for V2 audio units
theResult = AudioUnitRender(mConnection.sourceAudioUnit, &ioActionFlags, &inTimeStamp,
mConnection.sourceOutputNumber, nFrames, &inBufferList);
} else {
// kFromCallback:
theResult = (mInputProc)(mInputProcRefCon, &ioActionFlags, &inTimeStamp, inElement, nFrames,
&inBufferList);
}

if (mInputType == EInputType::NoInput) { // defense: the guy upstream could have disconnected
// it's a horrible thing to do, but may happen!
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;
}

} // namespace ausdk

#endif // AudioUnitSDK_AUInputElement_h

+ 251
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.cpp View File

@@ -0,0 +1,251 @@
/*!
@file AudioUnitSDK/AUMIDIBase.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUMIDIBase.h>
#include <CoreMIDI/CoreMIDI.h>

namespace ausdk {

// 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)
{
(void)inScope;
(void)inElement;
(void)outDataSize;
(void)outWritable;

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);
AUSDK_Require(GetXMLNames(nullptr) == noErr, kAudioUnitErr_InvalidProperty);
outDataSize = sizeof(CFURLRef);
outWritable = false;
return noErr;
#endif

#if AUSDK_HAVE_MIDI_MAPPING
case kAudioUnitProperty_AllParameterMIDIMappings:
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
outWritable = true;
outDataSize = sizeof(AUParameterMIDIMapping) * mMIDIMapper->GetNumberMaps();
return noErr;

case kAudioUnitProperty_HotMapParameterMIDIMapping:
case kAudioUnitProperty_AddParameterMIDIMapping:
case kAudioUnitProperty_RemoveParameterMIDIMapping:
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
outWritable = true;
outDataSize = sizeof(AUParameterMIDIMapping);
return noErr;
#endif

default:
return kAudioUnitErr_InvalidProperty;
}
}

OSStatus AUMIDIBase::DelegateGetProperty(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData)
{
(void)inScope;
(void)inElement;
(void)outData;

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);
return GetXMLNames(static_cast<CFURLRef*>(outData));
#endif

#if AUSDK_HAVE_MIDI_MAPPING
case kAudioUnitProperty_AllParameterMIDIMappings: {
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
AUParameterMIDIMapping* const maps = (static_cast<AUParameterMIDIMapping*>(outData));
mMIDIMapper->GetMaps(maps);
return noErr;
}

case kAudioUnitProperty_HotMapParameterMIDIMapping: {
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
AUParameterMIDIMapping* const map = (static_cast<AUParameterMIDIMapping*>(outData));
mMIDIMapper->GetHotParameterMap(*map);
return noErr;
}
#endif

default:
return kAudioUnitErr_InvalidProperty;
}
}

OSStatus AUMIDIBase::DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
{
(void)inScope;
(void)inElement;
(void)inData;
(void)inDataSize;

switch (inID) {

#if AUSDK_HAVE_MIDI_MAPPING
case kAudioUnitProperty_AddParameterMIDIMapping: {
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
const auto* const maps = static_cast<const AUParameterMIDIMapping*>(inData);
mMIDIMapper->AddParameterMapping(
maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
mAUBaseInstance.PropertyChanged(
kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
return noErr;
}

case kAudioUnitProperty_RemoveParameterMIDIMapping: {
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
const auto* const maps = static_cast<const AUParameterMIDIMapping*>(inData);
bool didChange = false;
mMIDIMapper->RemoveParameterMapping(
maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
if (didChange) {
mAUBaseInstance.PropertyChanged(
kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
}
return noErr;
}

case kAudioUnitProperty_HotMapParameterMIDIMapping: {
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
const auto& map = *static_cast<const AUParameterMIDIMapping*>(inData);
mMIDIMapper->SetHotMapping(map);
return noErr;
}

case kAudioUnitProperty_AllParameterMIDIMappings: {
AUSDK_Require(mMIDIMapper, kAudioUnitErr_InvalidProperty);
AUSDK_Require(inScope == kAudioUnitScope_Global, kAudioUnitErr_InvalidScope);
AUSDK_Require(inElement == 0, kAudioUnitErr_InvalidElement);
const auto* const mappings = static_cast<const AUParameterMIDIMapping*>(inData);
mMIDIMapper->ReplaceAllMaps(
mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
return noErr;
}
#endif

default:
return kAudioUnitErr_InvalidProperty;
}
}

constexpr uint8_t MIDIStatusNibbleValue(uint8_t status) noexcept { return (status & 0xF0U) >> 4u; }

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUMIDIBase::HandleMIDIEvent
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus AUMIDIBase::HandleMIDIEvent(
UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
{
if (!mAUBaseInstance.IsInitialized()) {
return kAudioUnitErr_Uninitialized;
}

#if AUSDK_HAVE_MIDI_MAPPING
// you potentially have a choice to make here - if a param mapping matches, do you still want to
// process the MIDI event or not. The default behaviour is to continue on with the MIDI event.
if (mMIDIMapper) {
if (mMIDIMapper->HandleHotMapping(status, channel, data1, mAUBaseInstance)) {
mAUBaseInstance.PropertyChanged(
kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
} else {
mMIDIMapper->FindParameterMapEventMatch(
status, channel, data1, data2, inStartFrame, mAUBaseInstance);
}
}
#endif
switch (MIDIStatusNibbleValue(status)) {
case kMIDICVStatusNoteOn:
if (data2 != 0u) {
return HandleNoteOn(channel, data1, data2, inStartFrame);
} else {
// zero velocity translates to note off
return HandleNoteOff(channel, data1, data2, inStartFrame);
}

case kMIDICVStatusNoteOff:
return HandleNoteOff(channel, data1, data2, inStartFrame);

default:
return HandleNonNoteEvent(status, channel, data1, data2, inStartFrame);
}
}

OSStatus AUMIDIBase::HandleNonNoteEvent(
UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
{
switch (MIDIStatusNibbleValue(status)) {
case kMIDICVStatusPitchBend:
return HandlePitchWheel(channel, data1, data2, inStartFrame);

case kMIDICVStatusProgramChange:
return HandleProgramChange(channel, data1);

case kMIDICVStatusChannelPressure:
return HandleChannelPressure(channel, data1, inStartFrame);

case kMIDICVStatusControlChange: {
switch (data1) {
case kMIDIController_AllNotesOff:
return HandleAllNotesOff(channel);

case kMIDIController_ResetAllControllers:
return HandleResetAllControllers(channel);

case kMIDIController_AllSoundOff:
return HandleAllSoundOff(channel);

default:
return HandleControlChange(channel, data1, data2, inStartFrame);
}
}

case kMIDICVStatusPolyPressure:
return HandlePolyPressure(channel, data1, data2, inStartFrame);

default:
return noErr;
}
}

OSStatus AUMIDIBase::SysEx(const UInt8* inData, UInt32 inLength)
{
if (!mAUBaseInstance.IsInitialized()) {
return kAudioUnitErr_Uninitialized;
}

return HandleSysEx(inData, inLength);
}

} // namespace ausdk

+ 169
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIBase.h View File

@@ -0,0 +1,169 @@
/*!
@file AudioUnitSDK/AUMIDIBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUMIDIBase_h
#define AudioUnitSDK_AUMIDIBase_h

#include <AudioUnitSDK/AUBase.h>


#ifndef AUSDK_HAVE_XML_NAMES
#define AUSDK_HAVE_XML_NAMES TARGET_OS_OSX // NOLINT(cppcoreguidelines-macro-usage)
#endif

#ifndef AUSDK_HAVE_MIDI_MAPPING
#define AUSDK_HAVE_MIDI_MAPPING TARGET_OS_OSX // NOLINT(cppcoreguidelines-macro-usage)
#endif

namespace ausdk {

#if AUSDK_HAVE_MIDI_MAPPING
/// Abstract interface for parameter MIDI mapping
class AUMIDIMapper {
public:
AUMIDIMapper() = default;
virtual ~AUMIDIMapper() = default;

AUMIDIMapper(const AUMIDIMapper&) = delete;
AUMIDIMapper(AUMIDIMapper&&) = delete;
AUMIDIMapper& operator=(const AUMIDIMapper&) = delete;
AUMIDIMapper& operator=(AUMIDIMapper&&) = delete;

[[nodiscard]] virtual UInt32 GetNumberMaps() const = 0;
virtual void GetMaps(AUParameterMIDIMapping* outMapping) = 0;
virtual void GetHotParameterMap(AUParameterMIDIMapping& outMapping) = 0;

virtual void AddParameterMapping(
const AUParameterMIDIMapping* maps, UInt32 count, AUBase& auBase) = 0;
virtual void RemoveParameterMapping(
const AUParameterMIDIMapping* maps, UInt32 count, bool& outDidChange) = 0;
virtual void SetHotMapping(const AUParameterMIDIMapping& mapping) = 0;
virtual void ReplaceAllMaps(
const AUParameterMIDIMapping* maps, UInt32 count, AUBase& auBase) = 0;

virtual bool HandleHotMapping(UInt8 status, UInt8 channel, UInt8 data1, AUBase& auBase) = 0;
virtual bool FindParameterMapEventMatch(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2,
UInt32 inStartFrame, AUBase& auBase) = 0;
};
#endif

// ________________________________________________________________________
// AUMIDIBase
//
/*!
@class AUMIDIBase
@brief Auxiliary class supporting MIDI events.
*/
class AUMIDIBase {
public:
explicit AUMIDIBase(AUBase& inBase) : mAUBaseInstance(inBase) {}

virtual ~AUMIDIBase() = default;

AUMIDIBase(const AUMIDIBase&) = delete;
AUMIDIBase(AUMIDIBase&&) = delete;
AUMIDIBase& operator=(const AUMIDIBase&) = delete;
AUMIDIBase& operator=(AUMIDIBase&&) = delete;

virtual OSStatus MIDIEvent(
UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
{
const UInt32 strippedStatus = inStatus & 0xf0U; // NOLINT
const UInt32 channel = inStatus & 0x0fU; // NOLINT

return HandleMIDIEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame);
}

#if AUSDK_MIDI2_AVAILABLE
virtual OSStatus MIDIEventList(
UInt32 /*inOffsetSampleFrame*/, const MIDIEventList* /*eventList*/)
{
return kAudio_UnimplementedError;
}
#endif

virtual OSStatus SysEx(const UInt8* inData, UInt32 inLength);

virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable);
virtual OSStatus DelegateGetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData);
virtual OSStatus DelegateSetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize);

protected:
// MIDI dispatch
virtual OSStatus HandleMIDIEvent(
UInt8 inStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame);
virtual OSStatus HandleNonNoteEvent(
UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame);

// Old name
AUSDK_DEPRECATED("HandleMIDIEvent")
OSStatus HandleMidiEvent(
UInt8 inStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame)
{
return HandleMIDIEvent(inStatus, inChannel, inData1, inData2, inStartFrame);
}

#if AUSDK_HAVE_XML_NAMES
virtual OSStatus GetXMLNames(CFURLRef* /*outNameDocument*/)
{
return kAudioUnitErr_InvalidProperty;
} // if not overridden, it's unsupported
#endif

// channel messages
virtual OSStatus HandleNoteOn(
UInt8 /*inChannel*/, UInt8 /*inNoteNumber*/, UInt8 /*inVelocity*/, UInt32 /*inStartFrame*/)
{
return noErr;
}
virtual OSStatus HandleNoteOff(
UInt8 /*inChannel*/, UInt8 /*inNoteNumber*/, UInt8 /*inVelocity*/, UInt32 /*inStartFrame*/)
{
return noErr;
}
virtual OSStatus HandleControlChange(
UInt8 /*inChannel*/, UInt8 /*inController*/, UInt8 /*inValue*/, UInt32 /*inStartFrame*/)
{
return noErr;
}
virtual OSStatus HandlePitchWheel(
UInt8 /*inChannel*/, UInt8 /*inPitch1*/, UInt8 /*inPitch2*/, UInt32 /*inStartFrame*/)
{
return noErr;
}
virtual OSStatus HandleChannelPressure(
UInt8 /*inChannel*/, UInt8 /*inValue*/, UInt32 /*inStartFrame*/)
{
return noErr;
}
virtual OSStatus HandleProgramChange(UInt8 /*inChannel*/, UInt8 /*inValue*/) { return noErr; }
virtual OSStatus HandlePolyPressure(
UInt8 /*inChannel*/, UInt8 /*inKey*/, UInt8 /*inValue*/, UInt32 /*inStartFrame*/)
{
return noErr;
}
virtual OSStatus HandleResetAllControllers(UInt8 /*inChannel*/) { return noErr; }
virtual OSStatus HandleAllNotesOff(UInt8 /*inChannel*/) { return noErr; }
virtual OSStatus HandleAllSoundOff(UInt8 /*inChannel*/) { return noErr; }

// System messages
virtual OSStatus HandleSysEx(const UInt8* /*inData*/, UInt32 /*inLength*/) { return noErr; }

#if AUSDK_HAVE_MIDI_MAPPING
void SetMIDIMapper(const std::shared_ptr<AUMIDIMapper>& mapper) { mMIDIMapper = mapper; }
#endif

private:
AUBase& mAUBaseInstance;
#if AUSDK_HAVE_MIDI_MAPPING
std::shared_ptr<AUMIDIMapper> mMIDIMapper;
#endif
};

} // namespace ausdk

#endif // AudioUnitSDK_AUMIDIBase_h

+ 53
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.cpp View File

@@ -0,0 +1,53 @@
/*!
@file AudioUnitSDK/AUMIDIEffectBase.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUMIDIEffectBase.h>

namespace ausdk {

AUMIDIEffectBase::AUMIDIEffectBase(AudioComponentInstance inInstance, bool inProcessesInPlace)
: AUEffectBase(inInstance, inProcessesInPlace), AUMIDIBase(*static_cast<AUBase*>(this))
{
}

OSStatus AUMIDIEffectBase::GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable)
{
OSStatus result =
AUEffectBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);

if (result == kAudioUnitErr_InvalidProperty) {
result =
AUMIDIBase::DelegateGetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
}

return result;
}

OSStatus AUMIDIEffectBase::GetProperty(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData)
{
OSStatus result = AUEffectBase::GetProperty(inID, inScope, inElement, outData);

if (result == kAudioUnitErr_InvalidProperty) {
result = AUMIDIBase::DelegateGetProperty(inID, inScope, inElement, outData);
}

return result;
}

OSStatus AUMIDIEffectBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
{

OSStatus result = AUEffectBase::SetProperty(inID, inScope, inElement, inData, inDataSize);

if (result == kAudioUnitErr_InvalidProperty) {
result = AUMIDIBase::DelegateSetProperty(inID, inScope, inElement, inData, inDataSize);
}

return result;
}

} // namespace ausdk

+ 40
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIEffectBase.h View File

@@ -0,0 +1,40 @@
/*!
@file AudioUnitSDK/AUMIDIEffectBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUMIDIEffectBase_h
#define AudioUnitSDK_AUMIDIEffectBase_h

#include <AudioUnitSDK/AUEffectBase.h>
#include <AudioUnitSDK/AUMIDIBase.h>

namespace ausdk {

/*!
@class AUMIDIEffectBase
@brief Subclass of AUEffectBase and AUMIDIBase, providing an abstract base class for
music effects.
*/
class AUMIDIEffectBase : public AUEffectBase, public AUMIDIBase {
public:
explicit AUMIDIEffectBase(AudioComponentInstance inInstance, bool inProcessesInPlace = false);
OSStatus MIDIEvent(
UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame) override
{
return AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
OSStatus SysEx(const UInt8* inData, UInt32 inLength) override
{
return AUMIDIBase::SysEx(inData, inLength);
}
OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) override;
OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData) override;
OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize) override;
};

} // namespace ausdk

#endif // AudioUnitSDK_AUMIDIEffectBase_h

+ 20
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUMIDIUtility.h View File

@@ -0,0 +1,20 @@
/*!
@file AudioUnitSDK/AUMIDIUtility.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUMIDIUtility_h
#define AudioUnitSDK_AUMIDIUtility_h

// OS
#if defined __has_include && __has_include(<AvailabilityVersions.h>)
#include <AvailabilityVersions.h>
#endif
#if defined(__MAC_12_0) || defined(__IPHONE_15_0)
#define AUSDK_MIDI2_AVAILABLE 1
#endif

#if AUSDK_MIDI2_AVAILABLE
#include <CoreMIDI/MIDIServices.h>
#endif

#endif // AudioUnitSDK_AUMIDIUtility_h

+ 27
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.cpp View File

@@ -0,0 +1,27 @@
/*!
@file AudioUnitSDK/AUOutputElement.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUBase.h>
#include <AudioUnitSDK/AUOutputElement.h>

namespace ausdk {

AUOutputElement::AUOutputElement(AUBase& audioUnit) : AUIOElement(audioUnit) { AllocateBuffer(); }

AUOutputElement::AUOutputElement(AUBase& audioUnit, const AudioStreamBasicDescription& format)
: AUIOElement{ audioUnit, format }
{
AllocateBuffer();
}

OSStatus AUOutputElement::SetStreamFormat(const AudioStreamBasicDescription& desc)
{
const OSStatus result = AUIOElement::SetStreamFormat(desc); // inherited
if (result == noErr) {
AllocateBuffer();
}
return result;
}

} // namespace ausdk

+ 33
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUOutputElement.h View File

@@ -0,0 +1,33 @@
/*!
@file AudioUnitSDK/AUOutputElement.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUOutputElement_h
#define AudioUnitSDK_AUOutputElement_h

#include <AudioUnitSDK/AUBuffer.h>
#include <AudioUnitSDK/AUScopeElement.h>

namespace ausdk {

/*!
@class AUOutputElement
@brief Implements an audio unit output element.
*/
class AUOutputElement : public AUIOElement {
public:
explicit AUOutputElement(AUBase& audioUnit);

AUOutputElement(AUBase& audioUnit, const AudioStreamBasicDescription& format);

AUSDK_DEPRECATED("Construct with a reference")
explicit AUOutputElement(AUBase* audioUnit) : AUOutputElement(*audioUnit) {}

// AUElement override
OSStatus SetStreamFormat(const AudioStreamBasicDescription& desc) override;
[[nodiscard]] bool NeedsBufferSpace() const override { return true; }
};

} // namespace ausdk

#endif // AudioUnitSDK_AUOutputElement_h

+ 773
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.cpp View File

@@ -0,0 +1,773 @@
/*!
@file AudioUnitSDK/AUPlugInDispatch.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUBase.h>
#include <AudioUnitSDK/AUPlugInDispatch.h>
#include <AudioUnitSDK/AUUtility.h>
#include <AudioUnitSDK/ComponentBase.h>

#include <cmath>
#include <cstddef>

#define CATCH_EXCEPTIONS_IN_RENDER_METHODS TARGET_OS_OSX // NOLINT
#define HAVE_MUSICDEVICE_PREPARE_RELEASE TARGET_OS_OSX // NOLINT

namespace ausdk {

// ------------------------------------------------------------------------------------------------
static auto AUInstance(void* self)
{
return reinterpret_cast<AUBase*>( // NOLINT reinterpret_cast
&(static_cast<AudioComponentPlugInInstance*>(self)->mInstanceStorage));
}

// ------------------------------------------------------------------------------------------------
class AUInstanceGuard {
public:
explicit AUInstanceGuard(void* self) : mGuard(AUInstance(self)->GetMutex()) {}

private:
const AUEntryGuard mGuard;
};

// ------------------------------------------------------------------------------------------------
static bool IsValidParameterValue(AudioUnitParameterValue value) { return std::isfinite(value); }

static bool AreValidParameterEvents(const AudioUnitParameterEvent* events, UInt32 numEvents)
{
if (events == nullptr) {
return true;
}

for (UInt32 i = 0; i < numEvents; ++i) {
const auto& event = events[i]; // NOLINT
switch (event.eventType) {
case kParameterEvent_Immediate: {
if (!IsValidParameterValue(event.eventValues.immediate.value)) { // NOLINT
return false;
}
break;
}

case kParameterEvent_Ramped: {
if (!IsValidParameterValue(event.eventValues.ramp.startValue) || // NOLINT
!IsValidParameterValue(event.eventValues.ramp.endValue)) { // NOLINT
return false;
}
break;
}

default:
break;
}
}

return true;
}

// ------------------------------------------------------------------------------------------------
static OSStatus AUMethodInitialize(void* self)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->DoInitialize();
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodUninitialize(void* self)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
AUInstance(self)->DoCleanup();
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodGetPropertyInfo(void* self, AudioUnitPropertyID prop, AudioUnitScope scope,
AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
{
OSStatus result = noErr;
try {
UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when
// there is an error. This is a problem for auval.
bool writable = false;

const AUInstanceGuard guard(self);
result = AUInstance(self)->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
if (outDataSize != nullptr) {
*outDataSize = dataSize;
}
if (outWritable != nullptr) {
*outWritable = static_cast<Boolean>(writable);
}
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodGetProperty(void* self, AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData, UInt32* ioDataSize)
{
OSStatus result = noErr;
try {
bool writable = false;

const AUInstanceGuard guard(self);
if (ioDataSize == nullptr) {
AUSDK_LogError("AudioUnitGetProperty: null size pointer");
return kAudio_ParamError;
}
if (outData == nullptr) {
UInt32 dataSize = 0;

result = AUInstance(self)->DispatchGetPropertyInfo(
inID, inScope, inElement, dataSize, writable);
*ioDataSize = dataSize;
return result;
}

const auto clientBufferSize = *ioDataSize;
if (clientBufferSize == 0) {
AUSDK_LogError("AudioUnitGetProperty: *ioDataSize == 0 on entry");
return kAudio_ParamError;
}

UInt32 actualPropertySize = 0;
result = AUInstance(self)->DispatchGetPropertyInfo(
inID, inScope, inElement, actualPropertySize, writable);
if (result != noErr) {
return result;
}

std::vector<std::byte> tempBuffer;
void* destBuffer = nullptr;
if (clientBufferSize < actualPropertySize) {
tempBuffer.resize(actualPropertySize);
destBuffer = tempBuffer.data();
} else {
destBuffer = outData;
}

result = AUInstance(self)->DispatchGetProperty(inID, inScope, inElement, destBuffer);

if (result == noErr) {
if (clientBufferSize < actualPropertySize && !tempBuffer.empty()) {
memcpy(outData, tempBuffer.data(), clientBufferSize);
// ioDataSize remains correct, the number of bytes we wrote
} else {
*ioDataSize = actualPropertySize;
}
} else {
*ioDataSize = 0;
}
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodSetProperty(void* self, AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
if ((inData != nullptr) && (inDataSize != 0u)) {
result =
AUInstance(self)->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
} else {
if (inData == nullptr && inDataSize == 0) {
result = AUInstance(self)->DispatchRemovePropertyValue(inID, inScope, inElement);
} else {
if (inData == nullptr) {
AUSDK_LogError("AudioUnitSetProperty: inData == NULL");
return kAudio_ParamError;
}

if (inDataSize == 0) {
AUSDK_LogError("AudioUnitSetProperty: inDataSize == 0");
return kAudio_ParamError;
}
}
}
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodAddPropertyListener(
void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void* userData)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->AddPropertyListener(prop, proc, userData);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodRemovePropertyListener(
void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->RemovePropertyListener(prop, proc, nullptr, false);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodRemovePropertyListenerWithUserData(
void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void* userData)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->RemovePropertyListener(prop, proc, userData, true);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodAddRenderNotify(void* self, AURenderCallback proc, void* userData)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->SetRenderNotification(proc, userData);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodRemoveRenderNotify(void* self, AURenderCallback proc, void* userData)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->RemoveRenderNotification(proc, userData);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodGetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope,
AudioUnitElement elem, AudioUnitParameterValue* value)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = (value == nullptr ? kAudio_ParamError
: AUInstance(self)->GetParameter(param, scope, elem, *value));
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodSetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope,
AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
{
if (!IsValidParameterValue(value)) {
return kAudioUnitErr_InvalidParameterValue;
}

OSStatus result = noErr;
try {
// this is a (potentially) realtime method; no lock
result = AUInstance(self)->SetParameter(param, scope, elem, value, bufferOffset);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodScheduleParameters(
void* self, const AudioUnitParameterEvent* events, UInt32 numEvents)
{
if (!AreValidParameterEvents(events, numEvents)) {
return kAudioUnitErr_InvalidParameterValue;
}

OSStatus result = noErr;
try {
// this is a (potentially) realtime method; no lock
result = AUInstance(self)->ScheduleParameter(events, numEvents);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodRender(void* self, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames,
AudioBufferList* ioData)
{
OSStatus result = noErr;

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
try {
#endif
// this is a processing method; no lock
AudioUnitRenderActionFlags tempFlags{};

if (inTimeStamp == nullptr || ioData == nullptr) {
result = kAudio_ParamError;
} else {
if (ioActionFlags == nullptr) {
tempFlags = 0;
ioActionFlags = &tempFlags;
}
result = AUInstance(self)->DoRender(
*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
}

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
}
AUSDK_Catch(result)
#endif

return result;
}

static OSStatus AUMethodComplexRender(void* self, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets,
UInt32* outNumberOfPackets, AudioStreamPacketDescription* outPacketDescriptions,
AudioBufferList* ioData, void* outMetadata, UInt32* outMetadataByteSize)
{
OSStatus result = noErr;

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
try {
#endif
// this is a processing method; no lock
AudioUnitRenderActionFlags tempFlags{};

if (inTimeStamp == nullptr || ioData == nullptr) {
result = kAudio_ParamError;
} else {
if (ioActionFlags == nullptr) {
tempFlags = 0;
ioActionFlags = &tempFlags;
}
result = AUInstance(self)->ComplexRender(*ioActionFlags, *inTimeStamp,
inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions,
*ioData, outMetadata, outMetadataByteSize);
}

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
}
AUSDK_Catch(result)
#endif

return result;
}

static OSStatus AUMethodReset(void* self, AudioUnitScope scope, AudioUnitElement elem)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->Reset(scope, elem);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodProcess(void* self, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inNumberFrames, AudioBufferList* ioData)
{
OSStatus result = noErr;

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
try {
#endif
// this is a processing method; no lock
bool doParamCheck = true;

AudioUnitRenderActionFlags tempFlags{};

if (ioActionFlags == nullptr) {
tempFlags = 0;
ioActionFlags = &tempFlags;
} else {
if ((*ioActionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) != 0u) {
doParamCheck = false;
}
}

if (doParamCheck && (inTimeStamp == nullptr || ioData == nullptr)) {
result = kAudio_ParamError;
} else {
result =
AUInstance(self)->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
}

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
}
AUSDK_Catch(result)
#endif

return result;
}

static OSStatus AUMethodProcessMultiple(void* self, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists,
const AudioBufferList** inInputBufferLists, UInt32 inNumberOutputBufferLists,
AudioBufferList** ioOutputBufferLists)
{
OSStatus result = noErr;

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
try {
#endif
// this is a processing method; no lock
bool doParamCheck = true;

AudioUnitRenderActionFlags tempFlags{};

if (ioActionFlags == nullptr) {
tempFlags = 0;
ioActionFlags = &tempFlags;
} else {
if ((*ioActionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) != 0u) {
doParamCheck = false;
}
}

if (doParamCheck && (inTimeStamp == nullptr || inInputBufferLists == nullptr ||
ioOutputBufferLists == nullptr)) {
result = kAudio_ParamError;
} else {
result = AUInstance(self)->DoProcessMultiple(*ioActionFlags, *inTimeStamp,
inNumberFrames, inNumberInputBufferLists, inInputBufferLists,
inNumberOutputBufferLists, ioOutputBufferLists);
}

#if CATCH_EXCEPTIONS_IN_RENDER_METHODS
}
AUSDK_Catch(result)
#endif

return result;
}
// ------------------------------------------------------------------------------------------------

static OSStatus AUMethodStart(void* self)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->Start();
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodStop(void* self)
{
OSStatus result = noErr;
try {
const AUInstanceGuard guard(self);
result = AUInstance(self)->Stop();
}
AUSDK_Catch(result)
return result;
}

// ------------------------------------------------------------------------------------------------

// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
static OSStatus AUMethodMIDIEvent(
void* self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUInstance(self)->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodSysEx(void* self, const UInt8* inData, UInt32 inLength)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUInstance(self)->SysEx(inData, inLength);
}
AUSDK_Catch(result)
return result;
}

#if AUSDK_MIDI2_AVAILABLE
static OSStatus AUMethodMIDIEventList(
void* self, UInt32 inOffsetSampleFrame, const struct MIDIEventList* eventList)
{
if (eventList == nullptr) {
return kAudio_ParamError;
}

OSStatus result = noErr;
try {
// this is a potential render-time method; no lock

// 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;
}
#endif

static OSStatus AUMethodStartNote(void* self, MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID, NoteInstanceID* outNoteInstanceID, UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams* inParams)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
if (inParams == nullptr) {
result = kAudio_ParamError;
} else {
result = AUInstance(self)->StartNote(
inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodStopNote(void* self, MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUInstance(self)->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
}
AUSDK_Catch(result)
return result;
}

#if HAVE_MUSICDEVICE_PREPARE_RELEASE
static OSStatus AUMethodPrepareInstrument(void* self, MusicDeviceInstrumentID inInstrument)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUInstance(self)->PrepareInstrument(inInstrument); // NOLINT static via instance
}
AUSDK_Catch(result)
return result;
}

static OSStatus AUMethodReleaseInstrument(void* self, MusicDeviceInstrumentID inInstrument)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUInstance(self)->ReleaseInstrument(inInstrument); // NOLINT static via instance
}
AUSDK_Catch(result)
return result;
}
#endif // HAVE_MUSICDEVICE_PREPARE_RELEASE


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark -
#pragma mark Lookup Methods

AudioComponentMethod AUBaseLookup::Lookup(SInt16 selector)
{
switch (selector) {
case kAudioUnitInitializeSelect:
return (AudioComponentMethod)AUMethodInitialize; // NOLINT cast
case kAudioUnitUninitializeSelect:
return (AudioComponentMethod)AUMethodUninitialize; // NOLINT cast
case kAudioUnitGetPropertyInfoSelect:
return (AudioComponentMethod)AUMethodGetPropertyInfo; // NOLINT cast
case kAudioUnitGetPropertySelect:
return (AudioComponentMethod)AUMethodGetProperty; // NOLINT cast
case kAudioUnitSetPropertySelect:
return (AudioComponentMethod)AUMethodSetProperty; // NOLINT cast
case kAudioUnitAddPropertyListenerSelect:
return (AudioComponentMethod)AUMethodAddPropertyListener; // NOLINT cast
case kAudioUnitRemovePropertyListenerSelect:
return (AudioComponentMethod)AUMethodRemovePropertyListener; // NOLINT cast
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData; // NOLINT cast
case kAudioUnitAddRenderNotifySelect:
return (AudioComponentMethod)AUMethodAddRenderNotify; // NOLINT cast
case kAudioUnitRemoveRenderNotifySelect:
return (AudioComponentMethod)AUMethodRemoveRenderNotify; // NOLINT cast
case kAudioUnitGetParameterSelect:
return (AudioComponentMethod)AUMethodGetParameter; // NOLINT cast
case kAudioUnitSetParameterSelect:
return (AudioComponentMethod)AUMethodSetParameter; // NOLINT cast
case kAudioUnitScheduleParametersSelect:
return (AudioComponentMethod)AUMethodScheduleParameters; // NOLINT cast
case kAudioUnitRenderSelect:
return (AudioComponentMethod)AUMethodRender; // NOLINT cast
case kAudioUnitResetSelect:
return (AudioComponentMethod)AUMethodReset; // NOLINT cast
default:
break;
}
return nullptr;
}

AudioComponentMethod AUOutputLookup::Lookup(SInt16 selector)
{
const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

switch (selector) {
case kAudioOutputUnitStartSelect:
return (AudioComponentMethod)AUMethodStart; // NOLINT cast
case kAudioOutputUnitStopSelect:
return (AudioComponentMethod)AUMethodStop; // NOLINT cast
default:
break;
}
return nullptr;
}

AudioComponentMethod AUComplexOutputLookup::Lookup(SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

method = AUOutputLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

if (selector == kAudioUnitComplexRenderSelect) {
return (AudioComponentMethod)AUMethodComplexRender; // NOLINT cast
}
return nullptr;
}

AudioComponentMethod AUBaseProcessLookup::Lookup(SInt16 selector)
{
const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

if (selector == kAudioUnitProcessSelect) {
return (AudioComponentMethod)AUMethodProcess; // NOLINT cast
}

return nullptr;
}

AudioComponentMethod AUBaseProcessMultipleLookup::Lookup(SInt16 selector)
{
const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

if (selector == kAudioUnitProcessMultipleSelect) {
return (AudioComponentMethod)AUMethodProcessMultiple; // NOLINT cast
}

return nullptr;
}

AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup(SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

method = AUBaseProcessMultipleLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

method = AUBaseProcessLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

return nullptr;
}

inline AudioComponentMethod MIDI_Lookup(SInt16 selector)
{
switch (selector) {
case kMusicDeviceMIDIEventSelect:
return (AudioComponentMethod)AUMethodMIDIEvent; // NOLINT cast
case kMusicDeviceSysExSelect:
return (AudioComponentMethod)AUMethodSysEx; // NOLINT cast
#if AUSDK_MIDI2_AVAILABLE
case kMusicDeviceMIDIEventListSelect:
return (AudioComponentMethod)AUMethodMIDIEventList; // NOLINT cast
#endif
default:
break;
}
return nullptr;
}

AudioComponentMethod AUMIDILookup::Lookup(SInt16 selector)
{
const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

return MIDI_Lookup(selector);
}

AudioComponentMethod AUMIDIProcessLookup::Lookup(SInt16 selector)
{
const AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

return MIDI_Lookup(selector);
}

AudioComponentMethod AUMusicLookup::Lookup(SInt16 selector)
{
const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method != nullptr) {
return method;
}

switch (selector) {
case kMusicDeviceStartNoteSelect:
return (AudioComponentMethod)AUMethodStartNote; // NOLINT cast
case kMusicDeviceStopNoteSelect:
return (AudioComponentMethod)AUMethodStopNote; // NOLINT cast
#if HAVE_MUSICDEVICE_PREPARE_RELEASE
case kMusicDevicePrepareInstrumentSelect:
return (AudioComponentMethod)AUMethodPrepareInstrument; // NOLINT cast
case kMusicDeviceReleaseInstrumentSelect:
return (AudioComponentMethod)AUMethodReleaseInstrument; // NOLINT cast
#endif
default:
break;
}
return MIDI_Lookup(selector);
}

} // namespace ausdk

+ 110
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUPlugInDispatch.h View File

@@ -0,0 +1,110 @@
/*!
@file AudioUnitSDK/AUPlugInDispatch.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUPlugInDispatch_h
#define AudioUnitSDK_AUPlugInDispatch_h

#include <AudioUnitSDK/ComponentBase.h>

namespace ausdk {

/// Method lookup for a basic AUBase subclass.
struct AUBaseLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for a basic AUBase subclass.
template <class Implementor>
class AUBaseFactory : public APFactory<AUBaseLookup, Implementor> {
};

/// Method lookup for a AUBase subclass which implements I/O methods (Start, Stop).
struct AUOutputLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements I/O methods (Start, Stop).
template <class Implementor>
class AUOutputBaseFactory : public APFactory<AUOutputLookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements I/O methods (Start, Stop) and
/// ComplexRender.
struct AUComplexOutputLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements I/O methods (Start, Stop) and ComplexRender.
template <class Implementor>
class AUOutputComplexBaseFactory : public APFactory<AUComplexOutputLookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements Process.
struct AUBaseProcessLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements Process.
template <class Implementor>
class AUBaseProcessFactory : public APFactory<AUBaseProcessLookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements ProcessMultiple.
struct AUBaseProcessMultipleLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements ProcessMultiple.
template <class Implementor>
class AUBaseProcessMultipleFactory : public APFactory<AUBaseProcessMultipleLookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements Process and ProcessMultiple.
struct AUBaseProcessAndMultipleLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements Process and ProcessMultiple.
template <class Implementor>
class AUBaseProcessAndMultipleFactory
: public APFactory<AUBaseProcessAndMultipleLookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements MusicDevice methods (MIDIEvent and SysEx).
struct AUMIDILookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements MusicDevice methods (MIDIEvent and SysEx).
template <class Implementor>
class AUMIDIEffectFactory : public APFactory<AUMIDILookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements Process and MusicDevice methods (MIDIEvent
/// and SysEx).
struct AUMIDIProcessLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements Process and MusicDevice methods (MIDIEvent
/// and SysEx).
template <class Implementor>
class AUMIDIProcessFactory : public APFactory<AUMIDIProcessLookup, Implementor> {
};

/// Method lookup for an AUBase subclass which implements the full set of MusicDevice methods
/// (MIDIEvent, SysEx, StartNote, StopNote).
struct AUMusicLookup {
static AudioComponentMethod Lookup(SInt16 selector);
};

/// Factory for an AUBase subclass which implements the full set of MusicDevice methods
/// (MIDIEvent, SysEx, StartNote, StopNote).
template <class Implementor>
class AUMusicDeviceFactory : public APFactory<AUMusicLookup, Implementor> {
};

} // namespace ausdk

#endif // AudioUnitSDK_AUPlugInDispatch_h

+ 442
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.cpp View File

@@ -0,0 +1,442 @@
/*!
@file AudioUnitSDK/AUScopeElement.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/AUBase.h>
#include <AudioUnitSDK/AUScopeElement.h>

#include <AudioToolbox/AudioUnitProperties.h>

#include <array>

namespace ausdk {

//_____________________________________________________________________________
//
// By default, parameterIDs may be arbitrarily spaced, and a flat map
// will be used for access. Calling UseIndexedParameters() will
// instead use an STL vector for faster indexed access.
// This assumes the paramIDs are numbered 0.....inNumberOfParameters-1
// Call this before defining/adding any parameters with SetParameter()
//
void AUElement::UseIndexedParameters(UInt32 inNumberOfParameters)
{
mIndexedParameters.resize(inNumberOfParameters);
mUseIndexedParameters = true;
}

//_____________________________________________________________________________
//
// Helper method.
// returns whether the specified paramID is known to the element
//
bool AUElement::HasParameterID(AudioUnitParameterID paramID) const
{
if (mUseIndexedParameters) {
return paramID < mIndexedParameters.size();
}

return mParameters.find(paramID) != mParameters.end();
}

//_____________________________________________________________________________
//
// caller assumes that this is actually an immediate parameter
//
AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID) const
{
if (mUseIndexedParameters) {
ausdk::ThrowExceptionIf(
paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter);
return mIndexedParameters[paramID].load(std::memory_order_acquire);
}
const auto i = mParameters.find(paramID);
ausdk::ThrowExceptionIf(i == mParameters.end(), kAudioUnitErr_InvalidParameter);
return (*i).second.load(std::memory_order_acquire);
}

//_____________________________________________________________________________
//
void AUElement::SetParameter(
AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized)
{
if (mUseIndexedParameters) {
ausdk::ThrowExceptionIf(
paramID >= mIndexedParameters.size(), kAudioUnitErr_InvalidParameter);
mIndexedParameters[paramID].store(inValue, std::memory_order_release);
} else {
const auto i = mParameters.find(paramID);

if (i == mParameters.end()) {
if (mAudioUnit.IsInitialized() && !okWhenInitialized) {
// 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.
// Throw(kAudioUnitErr_InvalidParameter);
AUSDK_LogError(
"Warning: %s SetParameter for undefined param ID %u while initialized. "
"Ignoring.",
mAudioUnit.GetLoggingString(), static_cast<unsigned>(paramID));
} else {
// create new entry in map for the paramID (only happens first time)
mParameters[paramID] = ParameterValue{ inValue };
}
} else {
// paramID already exists in map so simply change its value
(*i).second.store(inValue, std::memory_order_release);
}
}
}

//_____________________________________________________________________________
//
void AUElement::SetScheduledEvent(AudioUnitParameterID paramID,
const AudioUnitParameterEvent& inEvent, UInt32 /*inSliceOffsetInBuffer*/,
UInt32 /*inSliceDurationFrames*/, bool okWhenInitialized)
{
if (inEvent.eventType != kParameterEvent_Immediate) {
AUSDK_LogError("Warning: %s was passed a ramped parameter event but does not implement "
"them. Ignoring.",
mAudioUnit.GetLoggingString());
return;
}
SetParameter(paramID, inEvent.eventValues.immediate.value, okWhenInitialized); // NOLINT
}

//_____________________________________________________________________________
//
void AUElement::GetParameterList(AudioUnitParameterID* outList)
{
if (mUseIndexedParameters) {
const auto nparams = static_cast<UInt32>(mIndexedParameters.size());
for (UInt32 i = 0; i < nparams; i++) {
*outList++ = (AudioUnitParameterID)i; // NOLINT
}
} else {
for (const auto& param : mParameters) {
*outList++ = param.first; // NOLINT
}
}
}

//_____________________________________________________________________________
//
void AUElement::SaveState(AudioUnitScope scope, CFMutableDataRef data)
{
AudioUnitParameterInfo paramInfo{};
const CFIndex countOffset = CFDataGetLength(data);
uint32_t paramsWritten = 0;

const auto appendBytes = [data](const void* bytes, CFIndex length) {
CFDataAppendBytes(data, static_cast<const UInt8*>(bytes), length);
};

const auto appendParameter = [&](AudioUnitParameterID paramID, AudioUnitParameterValue value) {
struct {
UInt32 paramID;
UInt32 value; // really a big-endian float
} entry{};
static_assert(sizeof(entry) == (sizeof(entry.paramID) + sizeof(entry.value)));

if (mAudioUnit.GetParameterInfo(scope, paramID, paramInfo) == noErr) {
if ((paramInfo.flags & kAudioUnitParameterFlag_CFNameRelease) != 0u) {
if (paramInfo.cfNameString != nullptr) {
CFRelease(paramInfo.cfNameString);
}
if (paramInfo.unit == kAudioUnitParameterUnit_CustomUnit &&
paramInfo.unitName != nullptr) {
CFRelease(paramInfo.unitName);
}
}
if (((paramInfo.flags & kAudioUnitParameterFlag_OmitFromPresets) != 0u) ||
((paramInfo.flags & kAudioUnitParameterFlag_MeterReadOnly) != 0u)) {
return;
}
}

entry.paramID = CFSwapInt32HostToBig(paramID);
entry.value = CFSwapInt32HostToBig(*reinterpret_cast<UInt32*>(&value)); // NOLINT

appendBytes(&entry, sizeof(entry));
++paramsWritten;
};

constexpr UInt32 placeholderCount = 0;
appendBytes(&placeholderCount, sizeof(placeholderCount));

if (mUseIndexedParameters) {
const auto nparams = static_cast<UInt32>(mIndexedParameters.size());
for (UInt32 i = 0; i < nparams; i++) {
appendParameter(i, mIndexedParameters[i]);
}
} else {
for (const auto& item : mParameters) {
appendParameter(item.first, item.second);
}
}

const auto count_BE = CFSwapInt32HostToBig(paramsWritten);
memcpy(CFDataGetMutableBytePtr(data) + countOffset, // NOLINT ptr math
&count_BE, sizeof(count_BE));
}

//_____________________________________________________________________________
//
const UInt8* AUElement::RestoreState(const UInt8* state)
{
union FloatInt32 {
UInt32 i;
AudioUnitParameterValue f;
};
const UInt8* p = state;
const UInt32 nparams = CFSwapInt32BigToHost(*reinterpret_cast<const UInt32*>(p)); // NOLINT
p += sizeof(UInt32); // NOLINT

for (UInt32 i = 0; i < nparams; ++i) {
struct {
AudioUnitParameterID paramID;
AudioUnitParameterValue value;
} entry{};
static_assert(sizeof(entry) == (sizeof(entry.paramID) + sizeof(entry.value)));

entry.paramID = CFSwapInt32BigToHost(*reinterpret_cast<const UInt32*>(p)); // NOLINT
p += sizeof(UInt32); // NOLINT
FloatInt32 temp{}; // NOLINT
temp.i = CFSwapInt32BigToHost(*reinterpret_cast<const UInt32*>(p)); // NOLINT
entry.value = temp.f; // NOLINT
p += sizeof(AudioUnitParameterValue); // NOLINT

SetParameter(entry.paramID, entry.value);
}
return p;
}

//_____________________________________________________________________________
//
AUIOElement::AUIOElement(AUBase& audioUnit) : AUElement(audioUnit), mWillAllocate(true)
{
mStreamFormat = AudioStreamBasicDescription{ .mSampleRate = AUBase::kAUDefaultSampleRate,
.mFormatID = kAudioFormatLinearPCM,
.mFormatFlags = AudioFormatFlags(kAudioFormatFlagsNativeFloatPacked) |
AudioFormatFlags(kAudioFormatFlagIsNonInterleaved), // NOLINT
.mBytesPerPacket = sizeof(float),
.mFramesPerPacket = 1,
.mBytesPerFrame = sizeof(float),
.mChannelsPerFrame = 2,
.mBitsPerChannel = 32, // NOLINT
.mReserved = 0 };
}

//_____________________________________________________________________________
//
OSStatus AUIOElement::SetStreamFormat(const AudioStreamBasicDescription& format)
{
mStreamFormat = format;

// Clear the previous channel layout if it is inconsistent with the newly set format;
// preserve it if it is acceptable, in case the new format has no layout.
if (ChannelLayout().IsValid() && NumberChannels() != ChannelLayout().NumberChannels()) {
RemoveAudioChannelLayout();
}

return noErr;
}

//_____________________________________________________________________________
// inFramesToAllocate == 0 implies the AudioUnit's max-frames-per-slice will be used
void AUIOElement::AllocateBuffer(UInt32 inFramesToAllocate)
{
if (GetAudioUnit().HasBegunInitializing()) {
UInt32 framesToAllocate =
inFramesToAllocate > 0 ? inFramesToAllocate : GetAudioUnit().GetMaxFramesPerSlice();

mIOBuffer.Allocate(
mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0);
}
}

//_____________________________________________________________________________
//
void AUIOElement::DeallocateBuffer() { mIOBuffer.Deallocate(); }

//_____________________________________________________________________________
//
// AudioChannelLayout support

// return an empty vector (ie. NO channel layouts) if the AU doesn't require channel layout
// knowledge
std::vector<AudioChannelLayoutTag> AUIOElement::GetChannelLayoutTags() { return {}; }

// outLayoutPtr WILL be NULL if called to determine layout size
UInt32 AUIOElement::GetAudioChannelLayout(AudioChannelLayout* outLayoutPtr, bool& outWritable)
{
outWritable = true;

UInt32 size = mChannelLayout.IsValid() ? mChannelLayout.Size() : 0;
if (size > 0 && outLayoutPtr != nullptr) {
memcpy(outLayoutPtr, &mChannelLayout.Layout(), size);
}

return size;
}

// the incoming channel map will be at least as big as a basic AudioChannelLayout
// but its contents will determine its actual size
// Subclass should overide if channel map is writable
OSStatus AUIOElement::SetAudioChannelLayout(const AudioChannelLayout& inLayout)
{
if (NumberChannels() != AUChannelLayout::NumberChannels(inLayout)) {
return kAudioUnitErr_InvalidPropertyValue;
}
mChannelLayout = inLayout;
return noErr;
}

// Some units support optional usage of channel maps - typically converter units
// that can do channel remapping between different maps. In that optional case
// the user should be able to remove a channel map if that is possible.
// Typically this is NOT the case (e.g., the 3DMixer even in the stereo case
// needs to know if it is rendering to speakers or headphones)
OSStatus AUIOElement::RemoveAudioChannelLayout()
{
mChannelLayout = {};
return noErr;
}

//_____________________________________________________________________________
//
void AUScope::SetNumberOfElements(UInt32 numElements)
{
if (mDelegate != nullptr) {
return mDelegate->SetNumberOfElements(numElements);
}

if (numElements > mElements.size()) {
mElements.reserve(numElements);
while (numElements > mElements.size()) {
auto elem = mCreator->CreateElement(GetScope(), static_cast<UInt32>(mElements.size()));
mElements.push_back(std::move(elem));
}
} else {
while (numElements < mElements.size()) {
mElements.pop_back();
}
}
}

//_____________________________________________________________________________
//
bool AUScope::HasElementWithName() const
{
for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
AUElement* const el = GetElement(i);
if ((el != nullptr) && el->HasName()) {
return true;
}
}
return false;
}

//_____________________________________________________________________________
//

void AUScope::AddElementNamesToDict(CFMutableDictionaryRef inNameDict) const
{
if (HasElementWithName()) {
const auto elementDict =
Owned<CFMutableDictionaryRef>::from_create(CFDictionaryCreateMutable(
nullptr, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
AUElement* const el = GetElement(i);
if (el != nullptr && el->HasName()) {
const auto key = Owned<CFStringRef>::from_create(CFStringCreateWithFormat(
nullptr, nullptr, CFSTR("%u"), static_cast<unsigned>(i)));
CFDictionarySetValue(*elementDict, *key, *el->GetName());
}
}

const auto key = Owned<CFStringRef>::from_create(
CFStringCreateWithFormat(nullptr, nullptr, CFSTR("%u"), static_cast<unsigned>(mScope)));
CFDictionarySetValue(inNameDict, *key, *elementDict);
}
}

//_____________________________________________________________________________
//
std::vector<AudioUnitElement> AUScope::RestoreElementNames(CFDictionaryRef inNameDict) const
{
// first we have to see if we have enough elements
std::vector<AudioUnitElement> restoredElements;
const auto maxElNum = GetNumberOfElements();

const auto dictSize =
static_cast<size_t>(std::max(CFDictionaryGetCount(inNameDict), CFIndex(0)));
std::vector<CFStringRef> keys(dictSize);
CFDictionaryGetKeysAndValues(
inNameDict, reinterpret_cast<const void**>(keys.data()), nullptr); // NOLINT
for (size_t i = 0; i < dictSize; i++) {
unsigned int intKey = 0;
std::array<char, 32> string{};
CFStringGetCString(keys[i], string.data(), string.size(), kCFStringEncodingASCII);
const int result = sscanf(string.data(), "%u", &intKey); // NOLINT
// check if sscanf succeeded and element index is less than max elements.
if ((result != 0) && (static_cast<UInt32>(intKey) < maxElNum)) {
auto* const elName =
static_cast<CFStringRef>(CFDictionaryGetValue(inNameDict, keys[i]));
if ((elName != nullptr) && (CFGetTypeID(elName) == CFStringGetTypeID())) {
AUElement* const element = GetElement(intKey);
if (element != nullptr) {
element->SetName(elName);
restoredElements.push_back(intKey);
}
}
}
}

return restoredElements;
}

void AUScope::SaveState(CFMutableDataRef data) const
{
const AudioUnitElement nElems = GetNumberOfElements();
for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
AUElement* const element = GetElement(ielem);
const UInt32 nparams = element->GetNumberOfParameters();
if (nparams > 0) {
struct {
const UInt32 scope;
const UInt32 element;
} hdr{ .scope = CFSwapInt32HostToBig(GetScope()),
.element = CFSwapInt32HostToBig(ielem) };
static_assert(sizeof(hdr) == (sizeof(hdr.scope) + sizeof(hdr.element)));
CFDataAppendBytes(data, reinterpret_cast<const UInt8*>(&hdr), sizeof(hdr)); // NOLINT

element->SaveState(mScope, data);
}
}
}

const UInt8* AUScope::RestoreState(const UInt8* state) const
{
const UInt8* p = state;
const UInt32 elementIdx = CFSwapInt32BigToHost(*reinterpret_cast<const UInt32*>(p)); // NOLINT
p += sizeof(UInt32); // NOLINT
AUElement* const element = GetElement(elementIdx);
if (element == nullptr) {
struct {
AudioUnitParameterID paramID;
AudioUnitParameterValue value;
} entry{};
static_assert(sizeof(entry) == (sizeof(entry.paramID) + sizeof(entry.value)));
const UInt32 nparams = CFSwapInt32BigToHost(*reinterpret_cast<const UInt32*>(p)); // NOLINT
p += sizeof(UInt32); // NOLINT

p += nparams * sizeof(entry); // NOLINT
} else {
p = element->RestoreState(p);
}

return p;
}

} // namespace ausdk

+ 435
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUScopeElement.h View File

@@ -0,0 +1,435 @@
/*!
@file AudioUnitSDK/AUScopeElement.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUScopeElement_h
#define AudioUnitSDK_AUScopeElement_h

// module
#include <AudioUnitSDK/AUBuffer.h>
#include <AudioUnitSDK/AUUtility.h>
#include <AudioUnitSDK/ComponentBase.h>

// OS
#include <AudioToolbox/AudioUnit.h>

// std
#include <algorithm>
#include <atomic>
#include <memory>
#include <vector>

namespace ausdk {

class AUBase;

/// Wrap an atomic in a copy-constructible/assignable object. This allows storing atomic values in a
/// vector (not directly possible since atomics are not copy-constructible/assignable).
template <typename T>
class AtomicValue {
public:
AtomicValue() = default;
explicit AtomicValue(T val) : mValue{ val } {}
~AtomicValue() = default;

AtomicValue(const AtomicValue& other) : mValue{ other.mValue.load() } {}
AtomicValue(AtomicValue&& other) noexcept : mValue{ other.mValue.load() } {}

AtomicValue& operator=(const AtomicValue& other)
{
if (&other != this) {
mValue.store(other.mValue.load());
}
return *this;
}

AtomicValue& operator=(AtomicValue&& other) noexcept
{
mValue.store(other.mValue.load());
return *this;
}

T load(std::memory_order m = std::memory_order_seq_cst) const { return mValue.load(m); }
void store(T v, std::memory_order m = std::memory_order_seq_cst) { mValue.store(v, m); }

operator T() const { return load(); } // NOLINT implicit conversions OK

AtomicValue& operator=(T value)
{
store(value);
return *this;
}

private:
std::atomic<T> mValue{};
};

/// A bare-bones reinvention of boost::flat_map, just enough to hold parameters in sorted vectors.
template <typename Key, typename Value>
class flat_map {
using KVPair = std::pair<Key, Value>;
using Impl = std::vector<std::pair<Key, Value>>;

static bool keyless(const KVPair& item, Key k) { return k > item.first; }

Impl mImpl;

public:
using iterator = typename Impl::iterator;
using const_iterator = typename Impl::const_iterator;

[[nodiscard]] bool empty() const { return mImpl.empty(); }
[[nodiscard]] size_t size() const { return mImpl.size(); }
[[nodiscard]] const_iterator begin() const { return mImpl.begin(); }
[[nodiscard]] const_iterator end() const { return mImpl.end(); }
iterator begin() { return mImpl.begin(); }
iterator end() { return mImpl.end(); }
const_iterator cbegin() { return mImpl.cbegin(); }
const_iterator cend() { return mImpl.cend(); }

[[nodiscard]] const_iterator lower_bound(Key k) const
{
return std::lower_bound(mImpl.begin(), mImpl.end(), k, keyless);
}

iterator lower_bound(Key k) { return std::lower_bound(mImpl.begin(), mImpl.end(), k, keyless); }

[[nodiscard]] const_iterator find(Key k) const
{
auto iter = lower_bound(k);
if (iter != mImpl.end()) {
if ((*iter).first != k) {
iter = mImpl.end();
}
}
return iter;
}

iterator find(Key k)
{
auto iter = lower_bound(k);
if (iter != mImpl.end()) {
if ((*iter).first != k) {
iter = mImpl.end();
}
}
return iter;
}

class ItemProxy {
public:
ItemProxy(flat_map& map, Key k) : mMap{ map }, mKey{ k } {}

operator Value() const // NOLINT implicit conversion is OK
{
const auto iter = mMap.find(mKey);
if (iter == mMap.end()) {
throw std::runtime_error("Invalid map key");
}
return (*iter).second;
}

ItemProxy& operator=(const Value& v)
{
const auto iter = mMap.lower_bound(mKey);
if (iter != mMap.end() && (*iter).first == mKey) {
(*iter).second = v;
} else {
mMap.mImpl.insert(iter, { mKey, v });
}
return *this;
}

private:
flat_map& mMap;
const Key mKey;
};

ItemProxy operator[](Key k) { return ItemProxy{ *this, k }; }
};

// ____________________________________________________________________________
//
class AUIOElement;

/// An organizational unit for parameters, with a name.
class AUElement {
using ParameterValue = AtomicValue<float>;
using ParameterMap = flat_map<AudioUnitParameterID, ParameterValue>;

public:
explicit AUElement(AUBase& audioUnit) : mAudioUnit(audioUnit), mUseIndexedParameters(false) {}

AUSDK_DEPRECATED("Construct with a reference")
explicit AUElement(AUBase* audioUnit) : AUElement(*audioUnit) {}

AUElement(const AUElement&) = delete;
AUElement(AUElement&&) = delete;
AUElement& operator=(const AUElement&) = delete;
AUElement& operator=(AUElement&&) = delete;

virtual ~AUElement() = default;

virtual UInt32 GetNumberOfParameters()
{
return mUseIndexedParameters ? static_cast<UInt32>(mIndexedParameters.size())
: static_cast<UInt32>(mParameters.size());
}
virtual void GetParameterList(AudioUnitParameterID* outList);
[[nodiscard]] bool HasParameterID(AudioUnitParameterID paramID) const;
[[nodiscard]] AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID) const;

// Only set okWhenInitialized to true when you know the outside world cannot access this
// element. Otherwise the parameter map could get corrupted.
void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value,
bool okWhenInitialized = false);

// Only set okWhenInitialized to true when you know the outside world cannot access this
// element. Otherwise the parameter map could get corrupted. N.B. This only handles
// immediate parameters. Override to implement ramping. Called from
// AUBase::ProcessForScheduledParams.
virtual void SetScheduledEvent(AudioUnitParameterID paramID,
const AudioUnitParameterEvent& inEvent, UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames, bool okWhenInitialized = false);

[[nodiscard]] AUBase& GetAudioUnit() const noexcept { return mAudioUnit; }

void SaveState(AudioUnitScope scope, CFMutableDataRef data);
const UInt8* RestoreState(const UInt8* state);

[[nodiscard]] Owned<CFStringRef> GetName() const { return mElementName; }
void SetName(CFStringRef inName) { mElementName = inName; }

[[nodiscard]] bool HasName() const { return *mElementName != nil; }

virtual void UseIndexedParameters(UInt32 inNumberOfParameters);

virtual AUIOElement* AsIOElement() { return nullptr; }

private:
// --
AUBase& mAudioUnit;
ParameterMap mParameters;
bool mUseIndexedParameters;
std::vector<ParameterValue> mIndexedParameters;
Owned<CFStringRef> mElementName;
};


// ____________________________________________________________________________
//

/// A subclass of AUElement which represents an input or output bus, and has an associated
/// audio format and buffers.
class AUIOElement : public AUElement {
public:
explicit AUIOElement(AUBase& audioUnit);

AUIOElement(AUBase& audioUnit, const AudioStreamBasicDescription& format)
: AUIOElement{ audioUnit }
{
mStreamFormat = format;
}

AUSDK_DEPRECATED("Construct with a reference")
explicit AUIOElement(AUBase* audioUnit) : AUIOElement(*audioUnit) {}

[[nodiscard]] const AudioStreamBasicDescription& GetStreamFormat() const noexcept
{
return mStreamFormat;
}

virtual OSStatus SetStreamFormat(const AudioStreamBasicDescription& format);

virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);

void DeallocateBuffer();

/// Determines (via subclass override) whether the element's buffer list needs to be allocated.
[[nodiscard]] virtual bool NeedsBufferSpace() const = 0;

void SetWillAllocateBuffer(bool inFlag) noexcept { mWillAllocate = inFlag; }

[[nodiscard]] bool WillAllocateBuffer() const noexcept { return mWillAllocate; }

AudioBufferList& PrepareBuffer(UInt32 nFrames)
{
if (mWillAllocate) {
return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
}
Throw(kAudioUnitErr_InvalidPropertyValue);
}

AudioBufferList& PrepareNullBuffer(UInt32 nFrames)
{
return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
}
AudioBufferList& SetBufferList(AudioBufferList& abl) { return mIOBuffer.SetBufferList(abl); }
void SetBuffer(UInt32 index, AudioBuffer& ab) { mIOBuffer.SetBuffer(index, ab); }
void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
[[nodiscard]] AudioBufferList& GetBufferList() const { return mIOBuffer.GetBufferList(); }

[[nodiscard]] float* GetFloat32ChannelData(UInt32 ch)
{
if (IsInterleaved()) {
return static_cast<float*>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch; // NOLINT
}
return static_cast<float*>(mIOBuffer.GetBufferList().mBuffers[ch].mData); // NOLINT
}

void CopyBufferListTo(AudioBufferList& abl) const { mIOBuffer.CopyBufferListTo(abl); }
void CopyBufferContentsTo(AudioBufferList& abl) const { mIOBuffer.CopyBufferContentsTo(abl); }
[[nodiscard]] bool IsInterleaved() const noexcept { return ASBD::IsInterleaved(mStreamFormat); }
[[nodiscard]] UInt32 NumberChannels() const noexcept { return mStreamFormat.mChannelsPerFrame; }
[[nodiscard]] UInt32 NumberInterleavedChannels() const noexcept
{
return ASBD::NumberInterleavedChannels(mStreamFormat);
}
virtual std::vector<AudioChannelLayoutTag> GetChannelLayoutTags();

[[nodiscard]] const AUChannelLayout& ChannelLayout() const { return mChannelLayout; }

// Old layout methods
virtual OSStatus SetAudioChannelLayout(const AudioChannelLayout& inLayout);
virtual UInt32 GetAudioChannelLayout(AudioChannelLayout* outLayoutPtr, bool& outWritable);

virtual OSStatus RemoveAudioChannelLayout();

/*! @fn AsIOElement*/
AUIOElement* AsIOElement() override { return this; }

protected:
AUBufferList& IOBuffer() noexcept { return mIOBuffer; }
void ForceSetAudioChannelLayout(const AudioChannelLayout& inLayout)
{
mChannelLayout = inLayout;
}

private:
AudioStreamBasicDescription mStreamFormat{};
AUChannelLayout mChannelLayout{};
AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed
// for output: output cache, usually allocated early on
bool mWillAllocate{ false };
};

// ____________________________________________________________________________
//
/*!
@class AUScopeDelegate
@brief Provides a way to customize a scope, thereby obtaining virtual scopes.

Can be used to implement scopes with variable numbers of elements.
*/
class AUScopeDelegate {
public:
AUScopeDelegate() = default;

virtual ~AUScopeDelegate() = default;

AUScopeDelegate(const AUScopeDelegate&) = delete;
AUScopeDelegate(AUScopeDelegate&&) = delete;
AUScopeDelegate& operator=(const AUScopeDelegate&) = delete;
AUScopeDelegate& operator=(AUScopeDelegate&&) = delete;

void Initialize(AUBase* creator, AudioUnitScope scope, UInt32 numElements)
{
mCreator = creator;
mScope = scope;
SetNumberOfElements(numElements);
}
virtual void SetNumberOfElements(UInt32 numElements) = 0;
virtual UInt32 GetNumberOfElements() = 0;
virtual AUElement* GetElement(UInt32 elementIndex) = 0;

[[nodiscard]] AUBase* GetCreator() const noexcept { return mCreator; }
[[nodiscard]] AudioUnitScope GetScope() const noexcept { return mScope; }


private:
AUBase* mCreator{ nullptr };
AudioUnitScope mScope{ 0 };
};

// ____________________________________________________________________________
//
/*!
@class AUScope
@brief Organizes one or more elements into an addressable group (e.g. global, input, output).
*/
class AUScope {
public:
AUScope() = default;

~AUScope() = default;

AUScope(const AUScope&) = delete;
AUScope(AUScope&&) = delete;
AUScope& operator=(const AUScope&) = delete;
AUScope& operator=(AUScope&&) = delete;

void Initialize(AUBase* creator, AudioUnitScope scope, UInt32 numElements)
{
mCreator = creator;
mScope = scope;

if (mDelegate != nullptr) {
return mDelegate->Initialize(creator, scope, numElements);
}

SetNumberOfElements(numElements);
}
void SetNumberOfElements(UInt32 numElements);
[[nodiscard]] UInt32 GetNumberOfElements() const
{
if (mDelegate != nullptr) {
return mDelegate->GetNumberOfElements();
}

return static_cast<UInt32>(mElements.size());
}
[[nodiscard]] AUElement* GetElement(UInt32 elementIndex) const
{
if (mDelegate != nullptr) {
return mDelegate->GetElement(elementIndex);
}
return elementIndex < mElements.size() ? mElements[elementIndex].get() : nullptr;
}
[[nodiscard]] AUElement* SafeGetElement(UInt32 elementIndex) const
{
AUElement* const element = GetElement(elementIndex);
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::ThrowExceptionIf(ioel == nullptr, kAudioUnitErr_InvalidElement);
return ioel;
}

[[nodiscard]] bool HasElementWithName() const;
void AddElementNamesToDict(CFMutableDictionaryRef inNameDict) const;

[[nodiscard]] std::vector<AudioUnitElement> RestoreElementNames(
CFDictionaryRef inNameDict) const;

[[nodiscard]] AudioUnitScope GetScope() const noexcept { return mScope; }

void SetDelegate(AUScopeDelegate* inDelegate) noexcept { mDelegate = inDelegate; }
void SaveState(CFMutableDataRef data) const;
const UInt8* RestoreState(const UInt8* state) const;

private:
using ElementVector = std::vector<std::unique_ptr<AUElement>>;

AUBase* mCreator{ nullptr };
AudioUnitScope mScope{ 0 };
ElementVector mElements;
AUScopeDelegate* mDelegate{ nullptr };
};

} // namespace ausdk

#endif // AudioUnitSDK_AUScopeElement_h

+ 49
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUSilentTimeout.h View File

@@ -0,0 +1,49 @@
/*!
@file AudioUnitSDK/AUSilentTimeout.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUSilentTimeout_h
#define AudioUnitSDK_AUSilentTimeout_h

#include <CoreFoundation/CFBase.h> // for UInt32
#include <algorithm>

namespace ausdk {

/*!
@class AUSilentTimeout
@brief Utility to assist in propagating a silence flag from signal-processing
input to output, factoring in a processing delay.
*/
class AUSilentTimeout {
public:
AUSilentTimeout() = default;

void Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool& ioSilence)
{
if (ioSilence) {
if (mResetTimer) {
mTimeoutCounter = inTimeoutLimit;
mResetTimer = false;
}

if (mTimeoutCounter > 0) {
mTimeoutCounter -= std::min(inFramesToProcess, mTimeoutCounter);
ioSilence = false;
}
} else {
// signal to reset the next time we receive silence
mResetTimer = true;
}
}

void Reset() { mResetTimer = true; }

private:
UInt32 mTimeoutCounter{ 0 };
bool mResetTimer{ false };
};

} // namespace ausdk

#endif // AudioUnitSDK_AUSilentTimeout_h

+ 524
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AUUtility.h View File

@@ -0,0 +1,524 @@
/*!
@file AudioUnitSDK/AUUtility.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_AUUtility_h
#define AudioUnitSDK_AUUtility_h

// OS
#if defined __has_include && __has_include(<CoreAudioTypes/CoreAudioTypes.h>)
#include <CoreAudioTypes/CoreAudioTypes.h>
#else
#include <CoreAudio/CoreAudioTypes.h>
#endif
#include <libkern/OSByteOrder.h>
#include <mach/mach_time.h>
#include <os/log.h>
#include <syslog.h>

// std
#include <bitset>
#include <cstddef>
#include <exception>
#include <mutex>
#include <string>
#include <system_error>
#include <vector>

// -------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark General

#ifdef AUSDK_NO_DEPRECATIONS
#define AUSDK_DEPRECATED(msg)
#else
#define AUSDK_DEPRECATED(msg) [[deprecated(msg)]] // NOLINT macro
#endif

#ifndef AUSDK_LOG_OBJECT
#define AUSDK_LOG_OBJECT OS_LOG_DEFAULT // NOLINT macro
#endif

// -------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark Version

#define AUSDK_VERSION_MAJOR 1
#define AUSDK_VERSION_MINOR 1
#define AUSDK_VERSION_PATCH 0

// -------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark Error-handling macros

#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; } \
catch (const std::bad_alloc&) { (result) = kAudio_MemFullError; } \
catch (const OSStatus& catch_err) { (result) = catch_err; } \
catch (const std::system_error& exc) { (result) = exc.code().value(); } \
catch (...) { (result) = -1; }

#define AUSDK_Require(expr, error) /* NOLINT(cppcoreguidelines-macro-usage) */ \
do { \
if (!(expr)) { \
return error; \
} \
} while (0) /* NOLINT */

#define AUSDK_Require_noerr(expr) /* NOLINT(cppcoreguidelines-macro-usage) */ \
do { \
if (const auto status_tmp_macro_detail_ = (expr); status_tmp_macro_detail_ != noErr) { \
return status_tmp_macro_detail_; \
} \
} while (0)

#pragma mark -

// -------------------------------------------------------------------------------------------------

namespace ausdk {

// -------------------------------------------------------------------------------------------------

/// A subclass of std::runtime_error that holds an OSStatus error.
class AUException : public std::runtime_error {
public:
explicit AUException(OSStatus err)
: std::runtime_error{ std::string("OSStatus ") + std::to_string(err) }, mError{ err }
{
}

const OSStatus mError;
};

inline void ThrowExceptionIf(bool condition, OSStatus err)
{
if (condition) {
AUSDK_LogError("throwing %d", static_cast<int>(err));
throw AUException{ err };
}
}

[[noreturn]] inline void Throw(OSStatus err)
{
AUSDK_LogError("throwing %d", static_cast<int>(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
/// customization.
class AUMutex {
public:
AUMutex() = default;
virtual ~AUMutex() = default;

AUMutex(const AUMutex&) = delete;
AUMutex(AUMutex&&) = delete;
AUMutex& operator=(const AUMutex&) = delete;
AUMutex& operator=(AUMutex&&) = delete;

virtual void lock() { mImpl.lock(); }
virtual void unlock() { mImpl.unlock(); }
virtual bool try_lock() { return mImpl.try_lock(); }

private:
std::recursive_mutex mImpl;
};

// -------------------------------------------------------------------------------------------------

/// Implement optional locking at AudioUnit non-realtime entry points (required only for a small
/// number of plug-ins which must synchronize against external entry points).
class AUEntryGuard {
public:
explicit AUEntryGuard(AUMutex* maybeMutex) : mMutex{ maybeMutex }
{
if (mMutex != nullptr) {
mMutex->lock();
}
}

~AUEntryGuard()
{
if (mMutex != nullptr) {
mMutex->unlock();
}
}

AUEntryGuard(const AUEntryGuard&) = delete;
AUEntryGuard(AUEntryGuard&&) = delete;
AUEntryGuard& operator=(const AUEntryGuard&) = delete;
AUEntryGuard& operator=(AUEntryGuard&&) = delete;

private:
AUMutex* mMutex;
};

// -------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark ASBD

/// Utility functions relating to AudioStreamBasicDescription.
namespace ASBD {

constexpr bool IsInterleaved(const AudioStreamBasicDescription& format) noexcept
{
return (format.mFormatFlags & kLinearPCMFormatFlagIsNonInterleaved) == 0u;
}

constexpr UInt32 NumberInterleavedChannels(const AudioStreamBasicDescription& format) noexcept
{
return IsInterleaved(format) ? format.mChannelsPerFrame : 1;
}

constexpr UInt32 NumberChannelStreams(const AudioStreamBasicDescription& format) noexcept
{
return IsInterleaved(format) ? 1 : format.mChannelsPerFrame;
}

constexpr bool IsCommonFloat32(const AudioStreamBasicDescription& format) noexcept
{
return (
format.mFormatID == kAudioFormatLinearPCM && format.mFramesPerPacket == 1 &&
format.mBytesPerPacket == format.mBytesPerFrame
// so far, it's a valid PCM format
&& (format.mFormatFlags & kLinearPCMFormatFlagIsFloat) != 0 &&
(format.mChannelsPerFrame == 1 ||
(format.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0) &&
((format.mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian) &&
format.mBitsPerChannel == 32 // NOLINT
&& format.mBytesPerFrame == NumberInterleavedChannels(format) * sizeof(float));
}

constexpr AudioStreamBasicDescription CreateCommonFloat32(
Float64 sampleRate, UInt32 numChannels, bool interleaved = false) noexcept
{
constexpr auto sampleSize = sizeof(Float32);

AudioStreamBasicDescription asbd{};
asbd.mFormatID = kAudioFormatLinearPCM;
asbd.mFormatFlags = kAudioFormatFlagIsFloat |
static_cast<AudioFormatFlags>(kAudioFormatFlagsNativeEndian) |
kAudioFormatFlagIsPacked;
asbd.mBitsPerChannel = 8 * sampleSize; // NOLINT magic number
asbd.mChannelsPerFrame = numChannels;
asbd.mFramesPerPacket = 1;
asbd.mSampleRate = sampleRate;
if (interleaved) {
asbd.mBytesPerPacket = asbd.mBytesPerFrame = numChannels * sampleSize;
} else {
asbd.mBytesPerPacket = asbd.mBytesPerFrame = sampleSize;
asbd.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
return asbd;
}

constexpr bool MinimalSafetyCheck(const AudioStreamBasicDescription& x) noexcept
{
// This function returns false if there are sufficiently unreasonable values in any field.
// It is very conservative so even some very unlikely values will pass.
// This is just meant to catch the case where the data from a file is corrupted.

return (x.mSampleRate >= 0.) && (x.mSampleRate < 3e6) // NOLINT SACD sample rate is 2.8224 MHz
&& (x.mBytesPerPacket < 1000000) // NOLINT
&& (x.mFramesPerPacket < 1000000) // NOLINT
&& (x.mBytesPerFrame < 1000000) // NOLINT
&& (x.mChannelsPerFrame > 0) && (x.mChannelsPerFrame <= 1024) // NOLINT
&& (x.mBitsPerChannel <= 1024) // NOLINT
&& (x.mFormatID != 0) &&
!(x.mFormatID == kAudioFormatLinearPCM &&
(x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
}

inline bool IsEqual(
const AudioStreamBasicDescription& lhs, const AudioStreamBasicDescription& rhs) noexcept
{
return memcmp(&lhs, &rhs, sizeof(AudioStreamBasicDescription)) == 0;
}

} // namespace ASBD

// -------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark ACL

/// Utility functions relating to AudioChannelLayout.
namespace ACL {

constexpr bool operator==(const AudioChannelLayout& lhs, const AudioChannelLayout& rhs) noexcept
{
if (lhs.mChannelLayoutTag != rhs.mChannelLayoutTag) {
return false;
}
if (lhs.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
return lhs.mChannelBitmap == rhs.mChannelBitmap;
}
if (lhs.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
if (lhs.mNumberChannelDescriptions != rhs.mNumberChannelDescriptions) {
return false;
}
for (auto i = 0u; i < lhs.mNumberChannelDescriptions; ++i) {
const auto& lhdesc = lhs.mChannelDescriptions[i]; // NOLINT array subscript
const auto& rhdesc = rhs.mChannelDescriptions[i]; // NOLINT array subscript

if (lhdesc.mChannelLabel != rhdesc.mChannelLabel) {
return false;
}
if (lhdesc.mChannelLabel == kAudioChannelLabel_UseCoordinates) {
if (memcmp(&lhdesc, &rhdesc, sizeof(AudioChannelDescription)) != 0) {
return false;
}
}
}
}
return true;
}

} // namespace ACL

// -------------------------------------------------------------------------------------------------

/// Utility wrapper for the variably-sized AudioChannelLayout struct.
class AUChannelLayout {
public:
AUChannelLayout() : AUChannelLayout(0, kAudioChannelLayoutTag_UseChannelDescriptions, 0) {}

/// Can construct from a layout tag.
explicit AUChannelLayout(AudioChannelLayoutTag inTag) : AUChannelLayout(0, inTag, 0) {}

AUChannelLayout(uint32_t inNumberChannelDescriptions, AudioChannelLayoutTag inChannelLayoutTag,
AudioChannelBitmap inChannelBitMap)
: mStorage(
kHeaderSize + (inNumberChannelDescriptions * sizeof(AudioChannelDescription)), {})
{
auto* const acl = reinterpret_cast<AudioChannelLayout*>(mStorage.data()); // NOLINT

acl->mChannelLayoutTag = inChannelLayoutTag;
acl->mChannelBitmap = inChannelBitMap;
acl->mNumberChannelDescriptions = inNumberChannelDescriptions;
}

/// Implicit conversion from AudioChannelLayout& is allowed.
AUChannelLayout(const AudioChannelLayout& acl) // NOLINT
: mStorage(kHeaderSize + (acl.mNumberChannelDescriptions * sizeof(AudioChannelDescription)))
{
memcpy(mStorage.data(), &acl, mStorage.size());
}

bool operator==(const AUChannelLayout& other) const noexcept
{
return ACL::operator==(Layout(), other.Layout());
}

bool operator!=(const AUChannelLayout& y) const noexcept { return !(*this == y); }

[[nodiscard]] bool IsValid() const noexcept { return NumberChannels() > 0; }

[[nodiscard]] const AudioChannelLayout& Layout() const noexcept { return *LayoutPtr(); }

[[nodiscard]] const AudioChannelLayout* LayoutPtr() const noexcept
{
return reinterpret_cast<const AudioChannelLayout*>(mStorage.data()); // NOLINT
}

/// After default construction, this method will return
/// kAudioChannelLayoutTag_UseChannelDescriptions with 0 channel descriptions.
[[nodiscard]] AudioChannelLayoutTag Tag() const noexcept { return Layout().mChannelLayoutTag; }

[[nodiscard]] uint32_t NumberChannels() const noexcept { return NumberChannels(*LayoutPtr()); }

[[nodiscard]] uint32_t Size() const noexcept { return static_cast<uint32_t>(mStorage.size()); }

static uint32_t NumberChannels(const AudioChannelLayout& inLayout) noexcept
{
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
return inLayout.mNumberChannelDescriptions;
}
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
return static_cast<uint32_t>(
std::bitset<32>(inLayout.mChannelBitmap).count()); // NOLINT magic #
}
return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
}

private:
constexpr static size_t kHeaderSize = offsetof(AudioChannelLayout, mChannelDescriptions[0]);
std::vector<std::byte> mStorage;
};

// -------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark AudioBufferList

/// Utility functions relating to AudioBufferList.
namespace ABL {

// 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<const uint32_t*>(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);
}

} // namespace ABL

// -------------------------------------------------------------------------------------------------
#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(); }

/// Returns the frequency of the host timebase, in ticks per second.
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<double>(timeBaseInfo.denom) / static_cast<double>(timeBaseInfo.numer) *
1.0e9; // NOLINT
}

} // namespace HostTime

// -------------------------------------------------------------------------------------------------

/// Basic RAII wrapper for CoreFoundation types
template <typename T>
class Owned {
explicit Owned(T obj, bool fromget) noexcept : mImpl{ obj }
{
if (fromget) {
retainRef();
}
}

public:
static Owned from_get(T obj) noexcept { return Owned{ obj, true }; }

static Owned from_create(T obj) noexcept { return Owned{ obj, false }; }
static Owned from_copy(T obj) noexcept { return Owned{ obj, false }; }

Owned() noexcept = default;
~Owned() noexcept { releaseRef(); }

Owned(const Owned& other) noexcept : mImpl{ other.mImpl } { retainRef(); }

Owned(Owned&& other) noexcept : mImpl{ std::exchange(other.mImpl, nullptr) } {}

Owned& operator=(const Owned& other) noexcept
{
if (this != &other) {
releaseRef();
mImpl = other.mImpl;
retainRef();
}
return *this;
}

Owned& operator=(Owned&& other) noexcept
{
std::swap(mImpl, other.mImpl);
return *this;
}

T operator*() const noexcept { return get(); }
T get() const noexcept { return mImpl; }

/// As with `unique_ptr<T>::release()`, releases ownership of the reference to the caller (not
/// to be confused with decrementing the reference count as with `CFRelease()`).
T release() noexcept { return std::exchange(mImpl, nullptr); }

/// This is a from_get operation.
Owned& operator=(T cfobj) noexcept
{
if (mImpl != cfobj) {
releaseRef();
mImpl = cfobj;
retainRef();
}
return *this;
}

private:
void retainRef() noexcept
{
if (mImpl != nullptr) {
CFRetain(mImpl);
}
}

void releaseRef() noexcept
{
if (mImpl != nullptr) {
CFRelease(mImpl);
}
}

T mImpl{ nullptr };
};

// -------------------------------------------------------------------------------------------------

constexpr bool safe_isprint(char in_char) noexcept { return (in_char >= ' ') && (in_char <= '~'); }

inline std::string make_string_from_4cc(uint32_t in_4cc) noexcept
{
#if !TARGET_RT_BIG_ENDIAN
in_4cc = OSSwapInt32(in_4cc); // NOLINT
#endif

char* const string = reinterpret_cast<char*>(&in_4cc); // NOLINT
for (size_t i = 0; i < sizeof(in_4cc); ++i) {
if (!safe_isprint(string[i])) { // NOLINT
string[i] = '.'; // NOLINT
}
}
return std::string{ string, sizeof(in_4cc) };
}

} // namespace ausdk

#endif // AudioUnitSDK_AUUtility_h

+ 22
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/AudioUnitSDK.h View File

@@ -0,0 +1,22 @@
/*!
@file AudioUnitSDK/AudioUnitSDK.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_h
#define AudioUnitSDK_h

#include <AudioUnitSDK/AUBase.h>
#include <AudioUnitSDK/AUBuffer.h>
#include <AudioUnitSDK/AUEffectBase.h>
#include <AudioUnitSDK/AUInputElement.h>
#include <AudioUnitSDK/AUMIDIBase.h>
#include <AudioUnitSDK/AUMIDIEffectBase.h>
#include <AudioUnitSDK/AUOutputElement.h>
#include <AudioUnitSDK/AUPlugInDispatch.h>
#include <AudioUnitSDK/AUScopeElement.h>
#include <AudioUnitSDK/AUSilentTimeout.h>
#include <AudioUnitSDK/AUUtility.h>
#include <AudioUnitSDK/ComponentBase.h>
#include <AudioUnitSDK/MusicDeviceBase.h>

#endif /* AudioUnitSDK_h */

+ 98
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.cpp View File

@@ -0,0 +1,98 @@
/*!
@file AudioUnitSDK/ComponentBase.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
// self
#include <AudioUnitSDK/AUUtility.h>
#include <AudioUnitSDK/ComponentBase.h>

// std
#include <mutex>

namespace ausdk {

static OSStatus CB_GetComponentDescription(
AudioComponentInstance inInstance, AudioComponentDescription* outDesc);

std::recursive_mutex& ComponentBase::InitializationMutex()
{
__attribute__((no_destroy)) static std::recursive_mutex global;
return global;
}

ComponentBase::ComponentBase(AudioComponentInstance inInstance) : mComponentInstance(inInstance)
{
(void)GetComponentDescription();
}

void ComponentBase::DoPostConstructor()
{
PostConstructorInternal();
PostConstructor();
}

void ComponentBase::DoPreDestructor()
{
PreDestructor();
PreDestructorInternal();
}

OSStatus ComponentBase::AP_Open(void* self, AudioComponentInstance compInstance)
{
OSStatus result = noErr;
const auto acpi = static_cast<AudioComponentPlugInInstance*>(self);
try {
const std::lock_guard guard{ InitializationMutex() };

auto* const cb =
static_cast<ComponentBase*>((*acpi->mConstruct)(&acpi->mInstanceStorage, compInstance));
cb->DoPostConstructor(); // allows base class to do additional initialization
// once the derived class is fully constructed
result = noErr;
}
AUSDK_Catch(result)
if (result != noErr) {
delete acpi; // NOLINT
}
return result;
}

OSStatus ComponentBase::AP_Close(void* self)
{
OSStatus result = noErr;
try {
const auto acpi = static_cast<AudioComponentPlugInInstance*>(self);
if (const auto acImp =
reinterpret_cast<ComponentBase*>(&acpi->mInstanceStorage)) { // NOLINT
acImp->DoPreDestructor();
(*acpi->mDestruct)(&acpi->mInstanceStorage);
free(self); // NOLINT manual memory management
}
}
AUSDK_Catch(result)
return result;
}

AudioComponentDescription ComponentBase::GetComponentDescription() const
{
AudioComponentDescription desc = {};

if (CB_GetComponentDescription(mComponentInstance, &desc) == noErr) {
return desc;
}

return {};
}

static OSStatus CB_GetComponentDescription(
AudioComponentInstance inInstance, AudioComponentDescription* outDesc)
{
const AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
if (comp != nullptr) {
return AudioComponentGetDescription(comp, outDesc);
}

return kAudio_ParamError;
}

} // namespace ausdk

+ 162
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/ComponentBase.h View File

@@ -0,0 +1,162 @@
/*!
@file AudioUnitSDK/ComponentBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_ComponentBase_h
#define AudioUnitSDK_ComponentBase_h

// module
#include <AudioUnitSDK/AUUtility.h>

// OS
#include <AudioToolbox/AudioUnit.h>

// std
#include <array>
#include <mutex>
#include <new>

namespace ausdk {

/*!
@class ComponentBase
@brief Base class for implementing an `AudioComponentInstance`.
*/
class ComponentBase {
public:
/// Construct given an AudioComponentInstance, typically from APFactory::Constuct.
explicit ComponentBase(AudioComponentInstance inInstance);

virtual ~ComponentBase() = default;

ComponentBase(const ComponentBase&) = delete;
ComponentBase(ComponentBase&&) = delete;
ComponentBase& operator=(const ComponentBase&) = delete;
ComponentBase& operator=(ComponentBase&&) = delete;

/// Called from dispatchers after constructing an instance.
void DoPostConstructor();

/// Called from dispatchers before destroying an instance.
void DoPreDestructor();

/// Obtain the wrapped `AudioComponentInstance` (underlying type of `AudioUnit`, `AudioCodec`,
/// and others).
[[nodiscard]] AudioComponentInstance GetComponentInstance() const noexcept
{
return mComponentInstance;
}

/// Return the instance's `AudioComponentDescription`.
[[nodiscard]] AudioComponentDescription GetComponentDescription() const;

/// Component dispatch method.
static OSStatus AP_Open(void* self, AudioComponentInstance compInstance);

/// Component dispatch method.
static OSStatus AP_Close(void* self);

/// A mutex which is held during `Open`, since some AU's and the Component Manager itself
/// are not thread-safe against globals.
static std::recursive_mutex& InitializationMutex();

protected:
// subclasses are free to to override these methods to add functionality
virtual void PostConstructor() {}
virtual void PreDestructor() {}
// these methods, however, are reserved for override only within this SDK
virtual void PostConstructorInternal() {}
virtual void PreDestructorInternal() {}

private:
AudioComponentInstance mComponentInstance;
};

/*!
@class AudioComponentPlugInInstance
@brief Object which implements an AudioComponentPlugInInterface for the framework, and
which holds the C++ implementation object.
*/
struct AudioComponentPlugInInstance {
// The AudioComponentPlugInInterface must remain first

AudioComponentPlugInInterface mPlugInInterface;

void* (*mConstruct)(void* memory, AudioComponentInstance ci);

void (*mDestruct)(void* memory);

std::array<void*, 2> mPad; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
UInt32
mInstanceStorage; // the ACI implementation object is constructed into this memory
// this member is just a placeholder. it is aligned to a 16byte boundary
};

/*!
@class APFactory
@tparam APMethodLookup A class (e.g. AUBaseLookup) which provides a method selector lookup
function.
@tparam Implementor The class which implements the full plug-in (AudioUnit) interface.
@brief Provides an AudioComponentFactoryFunction and a convenience wrapper for
AudioComponentRegister.
*/
template <class APMethodLookup, class Implementor>
class APFactory {
public:
static void* Construct(void* memory, AudioComponentInstance compInstance)
{
return new (memory) Implementor(compInstance); // NOLINT manual memory management
}

static void Destruct(void* memory) { static_cast<Implementor*>(memory)->~Implementor(); }

// This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
// The actual implementation object is not created until Open().
static AudioComponentPlugInInterface* Factory(const AudioComponentDescription* /* inDesc */)
{
auto* const acpi = // NOLINT owning memory
static_cast<AudioComponentPlugInInstance*>(malloc( // NOLINT manual memory management
offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor)));
acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
acpi->mPlugInInterface.reserved = nullptr;
acpi->mConstruct = Construct;
acpi->mDestruct = Destruct;
acpi->mPad[0] = nullptr;
acpi->mPad[1] = nullptr;
return &acpi->mPlugInInterface;
}

// This is for runtime registration (not for plug-ins loaded from bundles).
static AudioComponent Register(
UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags = 0)
{
const AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
return AudioComponentRegister(&desc, name, vers, Factory);
}
};

#ifndef AUSDK_EXPORT
#if __GNUC__
#define AUSDK_EXPORT __attribute__((visibility("default"))) // NOLINT
#else
#warning export?
#endif
#endif


/// Macro to generate the factory function for the specified Audio Component. Factory is an
/// APFactory such as AUBaseFactory. Class is the name of the final ComponentBase class which
/// implements instances of the class.
#define AUSDK_COMPONENT_ENTRY(FactoryType, Class) /* NOLINT macro */ \
AUSDK_EXPORT \
extern "C" void* Class##Factory(const AudioComponentDescription* inDesc); \
extern "C" void* Class##Factory(const AudioComponentDescription* inDesc) \
{ \
return FactoryType<Class>::Factory(inDesc); /* NOLINT parens */ \
}

} // namespace ausdk

#endif // AudioUnitSDK_ComponentBase_h

+ 202
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt View File

@@ -0,0 +1,202 @@

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

+ 117
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.cpp View File

@@ -0,0 +1,117 @@
/*!
@file AudioUnitSDK/MusicDeviceBase.cpp
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#include <AudioUnitSDK/MusicDeviceBase.h>

namespace ausdk {


MusicDeviceBase::MusicDeviceBase(
AudioComponentInstance inInstance, UInt32 numInputs, UInt32 numOutputs, UInt32 numGroups)
: AUBase(inInstance, numInputs, numOutputs, numGroups), AUMIDIBase(*static_cast<AUBase*>(this))
{
}

OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable)
{
OSStatus result = noErr;

switch (inID) { // NOLINT if/else
case kMusicDeviceProperty_InstrumentCount:
if (inScope != kAudioUnitScope_Global) {
return kAudioUnitErr_InvalidScope;
}
outDataSize = sizeof(UInt32);
outWritable = false;
result = noErr;
break;
default:
result = AUBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);

if (result == kAudioUnitErr_InvalidProperty) {
result = AUMIDIBase::DelegateGetPropertyInfo(
inID, inScope, inElement, outDataSize, outWritable);
}
break;
}
return result;
}

OSStatus MusicDeviceBase::GetProperty(
AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData)
{
OSStatus result = noErr;

switch (inID) { // NOLINT if/else
case kMusicDeviceProperty_InstrumentCount:
if (inScope != kAudioUnitScope_Global) {
return kAudioUnitErr_InvalidScope;
}
return GetInstrumentCount(*static_cast<UInt32*>(outData));
default:
result = AUBase::GetProperty(inID, inScope, inElement, outData);

if (result == kAudioUnitErr_InvalidProperty) {
result = AUMIDIBase::DelegateGetProperty(inID, inScope, inElement, outData);
}
}

return result;
}


OSStatus MusicDeviceBase::SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize)

{

OSStatus result = AUBase::SetProperty(inID, inScope, inElement, inData, inDataSize);

if (result == kAudioUnitErr_InvalidProperty) {
result = AUMIDIBase::DelegateSetProperty(inID, inScope, inElement, inData, inDataSize);
}

return result;
}

// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
// then this call should return an instrument count of zero and noErr
OSStatus MusicDeviceBase::GetInstrumentCount(UInt32& outInstCount) const
{
outInstCount = 0;
return noErr;
}

OSStatus MusicDeviceBase::HandleNoteOn(
UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame)
{
const MusicDeviceNoteParams params{ .argCount = 2,
.mPitch = static_cast<Float32>(inNoteNumber),
.mVelocity = static_cast<Float32>(inVelocity) };
return StartNote(kMusicNoteEvent_UseGroupInstrument, inChannel, nullptr, inStartFrame, params);
}

OSStatus MusicDeviceBase::HandleNoteOff(
UInt8 inChannel, UInt8 inNoteNumber, UInt8 /*inVelocity*/, UInt32 inStartFrame)
{
return StopNote(inChannel, inNoteNumber, inStartFrame);
}

OSStatus MusicDeviceBase::HandleStartNoteMessage(MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID, NoteInstanceID* outNoteInstanceID, UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams* inParams)
{
if (inParams == nullptr || outNoteInstanceID == nullptr) {
return kAudio_ParamError;
}

if (!IsInitialized()) {
return kAudioUnitErr_Uninitialized;
}

return StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}

} // namespace ausdk

+ 64
- 0
modules/juce_audio_plugin_client/AU/AudioUnitSDK/MusicDeviceBase.h View File

@@ -0,0 +1,64 @@
/*!
@file AudioUnitSDK/MusicDeviceBase.h
@copyright © 2000-2021 Apple Inc. All rights reserved.
*/
#ifndef AudioUnitSDK_MusicDeviceBase_h
#define AudioUnitSDK_MusicDeviceBase_h

#include <AudioUnitSDK/AUMIDIBase.h>

namespace ausdk {

// ________________________________________________________________________
// MusicDeviceBase
//

/*!
@class MusicDeviceBase
@brief Deriving from AUBase and AUMIDIBase, an abstract base class for Music Device
subclasses.
*/
class MusicDeviceBase : public AUBase, public AUMIDIBase {
public:
MusicDeviceBase(AudioComponentInstance inInstance, UInt32 numInputs, UInt32 numOutputs,
UInt32 numGroups = 0);

OSStatus MIDIEvent(
UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame) override
{
return AUMIDIBase::MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
OSStatus SysEx(const UInt8* inData, UInt32 inLength) override
{
return AUMIDIBase::SysEx(inData, inLength);
}

#if AUSDK_MIDI2_AVAILABLE
OSStatus MIDIEventList(
UInt32 inOffsetSampleFrame, const struct MIDIEventList* eventList) override
{
return AUMIDIBase::MIDIEventList(inOffsetSampleFrame, eventList);
}
#endif

OSStatus GetPropertyInfo(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, UInt32& outDataSize, bool& outWritable) override;
OSStatus GetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, void* outData) override;
OSStatus SetProperty(AudioUnitPropertyID inID, AudioUnitScope inScope,
AudioUnitElement inElement, const void* inData, UInt32 inDataSize) override;
OSStatus HandleNoteOn(
UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) override;
OSStatus HandleNoteOff(
UInt8 inChannel, UInt8 inNoteNumber, UInt8 inVelocity, UInt32 inStartFrame) override;
virtual OSStatus GetInstrumentCount(UInt32& outInstCount) const;

private:
OSStatus HandleStartNoteMessage(MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID, NoteInstanceID* outNoteInstanceID, UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams* inParams);
};

} // namespace ausdk

#endif // AudioUnitSDK_MusicDeviceBase_h

+ 0
- 2400
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp
File diff suppressed because it is too large
View File


+ 0
- 1054
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.h
File diff suppressed because it is too large
View File


+ 0
- 75
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBaseHelper.h View File

@@ -1,75 +0,0 @@
/*
File: AUBaseHelper.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUBaseHelper_h__
#define __AUBaseHelper_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#include <AudioUnit/AUComponent.h>
#else
#include <CoreFoundation.h>
#include <AUComponent.h>
#endif
#include "AUBase.h"
// helpers for dealing with the file-references dictionary in an AUPreset
OSStatus GetFileRefPath (CFDictionaryRef parent, CFStringRef frKey, CFStringRef * fPath);
// if fileRefDict is NULL, this call creates one
// if not NULL, then the key value is added to it
CFMutableDictionaryRef CreateFileRefDict (CFStringRef fKey, CFStringRef fPath, CFMutableDictionaryRef fileRefDict);
int AccessURLAsset(const CFURLRef inURL, int mode);
#if DEBUG
void PrintAUParamEvent (AudioUnitParameterEvent& event, FILE* f);
#endif
#endif // __AUBaseHelper_h__

+ 0
- 219
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.cpp View File

@@ -1,219 +0,0 @@
/*
File: AUBuffer.cpp
Abstract: AUBuffer.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUBuffer.h"
#include <stdlib.h>
AUBufferList::~AUBufferList()
{
Deallocate();
if (mPtrs)
free(mPtrs);
}
// a * b + c
static UInt32 SafeMultiplyAddUInt32(UInt32 a, UInt32 b, UInt32 c)
{
if (a == 0 || b == 0) return c; // prevent zero divide
if (a > (0xFFFFFFFF - c) / b)
throw std::bad_alloc();
return a * b + c;
}
void AUBufferList::Allocate(const CAStreamBasicDescription &format, UInt32 nFrames)
{
UInt32 nStreams;
if (format.IsInterleaved()) {
nStreams = 1;
} else {
nStreams = format.mChannelsPerFrame;
}
// careful -- the I/O thread could be running!
if (nStreams > mAllocatedStreams) {
size_t theHeaderSize = sizeof(AudioBufferList) - sizeof(AudioBuffer);
mPtrs = (AudioBufferList *)CA_realloc(mPtrs,
SafeMultiplyAddUInt32(nStreams, sizeof(AudioBuffer), theHeaderSize));
mAllocatedStreams = nStreams;
}
UInt32 bytesPerStream = SafeMultiplyAddUInt32(nFrames, format.mBytesPerFrame, 0xF) & ~0xF;
UInt32 nBytes = SafeMultiplyAddUInt32(nStreams, bytesPerStream, 0);
if (nBytes > mAllocatedBytes) {
if (mExternalMemory) {
mExternalMemory = false;
mMemory = NULL;
}
mMemory = (Byte *)CA_realloc(mMemory, nBytes);
mAllocatedBytes = nBytes;
}
mAllocatedFrames = nFrames;
mPtrState = kPtrsInvalid;
}
void AUBufferList::Deallocate()
{
mAllocatedStreams = 0;
mAllocatedFrames = 0;
mAllocatedBytes = 0;
// this causes a world of hurt if someone upstream disconnects during I/O (SysSoundGraph)
/* if (mPtrs) {
printf("deallocating bufferlist %08X\n", int(mPtrs));
free(mPtrs);
mPtrs = NULL;
} */
if (mMemory) {
if (mExternalMemory)
mExternalMemory = false;
else
free(mMemory);
mMemory = NULL;
}
mPtrState = kPtrsInvalid;
}
AudioBufferList & AUBufferList::PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
{
if (nFrames > mAllocatedFrames)
COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
UInt32 nStreams;
UInt32 channelsPerStream;
if (format.IsInterleaved()) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
if (nStreams > mAllocatedStreams)
COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
}
AudioBufferList *abl = mPtrs;
abl->mNumberBuffers = nStreams;
AudioBuffer *buf = abl->mBuffers;
Byte *mem = mMemory;
UInt32 streamInterval = (mAllocatedFrames * format.mBytesPerFrame + 0xF) & ~0xF;
UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
for ( ; nStreams--; ++buf) {
buf->mNumberChannels = channelsPerStream;
buf->mData = mem;
buf->mDataByteSize = bytesPerBuffer;
mem += streamInterval;
}
if (UInt32(mem - mMemory) > mAllocatedBytes)
COMPONENT_THROW(kAudioUnitErr_TooManyFramesToProcess);
mPtrState = kPtrsToMyMemory;
return *mPtrs;
}
AudioBufferList & AUBufferList::PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames)
{
UInt32 nStreams;
UInt32 channelsPerStream;
if (format.IsInterleaved()) {
nStreams = 1;
channelsPerStream = format.mChannelsPerFrame;
} else {
nStreams = format.mChannelsPerFrame;
channelsPerStream = 1;
if (nStreams > mAllocatedStreams)
COMPONENT_THROW(kAudioUnitErr_FormatNotSupported);
}
AudioBufferList *abl = mPtrs;
abl->mNumberBuffers = nStreams;
AudioBuffer *buf = abl->mBuffers;
UInt32 bytesPerBuffer = nFrames * format.mBytesPerFrame;
for ( ; nStreams--; ++buf) {
buf->mNumberChannels = channelsPerStream;
buf->mData = NULL;
buf->mDataByteSize = bytesPerBuffer;
}
mPtrState = kPtrsToExternalMemory;
return *mPtrs;
}
// this should NOT be called while I/O is in process
void AUBufferList::UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf)
{
UInt32 alignedSize = buf.size & ~0xF;
if (mMemory != NULL && alignedSize >= mAllocatedBytes) {
// don't accept the buffer if we already have one and it's big enough
// if we don't already have one, we don't need one
Byte *oldMemory = mMemory;
mMemory = buf.buffer;
mAllocatedBytes = alignedSize;
// from Allocate(): nBytes = nStreams * nFrames * format.mBytesPerFrame;
// thus: nFrames = nBytes / (nStreams * format.mBytesPerFrame)
mAllocatedFrames = mAllocatedBytes / (format.NumberChannelStreams() * format.mBytesPerFrame);
mExternalMemory = true;
free(oldMemory);
}
}
#if DEBUG
void AUBufferList::PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames, bool asFloats)
{
printf(" %s [%d] 0x%08lX:\n", label, subscript, long(&abl));
const AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = 0; i < abl.mNumberBuffers; ++buf, ++i) {
printf(" [%2d] %5dbytes %dch @ %p: ", (int)i, (int)buf->mDataByteSize, (int)buf->mNumberChannels, buf->mData);
if (buf->mData != NULL) {
UInt32 nSamples = nFrames * buf->mNumberChannels;
for (UInt32 j = 0; j < nSamples; ++j) {
if (nSamples > 16 && (j % 16) == 0)
printf("\n\t");
if (asFloats)
printf(" %6.3f", ((float *)buf->mData)[j]);
else
printf(" %08X", (unsigned)((UInt32 *)buf->mData)[j]);
}
}
printf("\n");
}
}
#endif

+ 0
- 267
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBuffer.h View File

@@ -1,267 +0,0 @@
/*
File: AUBuffer.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUBuffer_h__
#define __AUBuffer_h__
#include <TargetConditionals.h>
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioUnit.h>
#else
#include <AudioUnit.h>
#endif
#include <string.h>
#include "CAStreamBasicDescription.h"
#include "CAAutoDisposer.h"
#include "CADebugMacros.h"
// make this usable outside the stricter context of AudiUnits
#ifndef COMPONENT_THROW
#define COMPONENT_THROW(err) \
do { DebugMessage(#err); throw static_cast<OSStatus>(err); } while (0)
#endif
/*! @class AUBufferList */
class AUBufferList {
enum EPtrState {
kPtrsInvalid,
kPtrsToMyMemory,
kPtrsToExternalMemory
};
public:
/*! @ctor AUBufferList */
AUBufferList() : mPtrState(kPtrsInvalid), mExternalMemory(false), mPtrs(NULL), mMemory(NULL),
mAllocatedStreams(0), mAllocatedFrames(0), mAllocatedBytes(0) { }
/*! @dtor ~AUBufferList */
~AUBufferList();
/*! @method PrepareBuffer */
AudioBufferList & PrepareBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
/*! @method PrepareNullBuffer */
AudioBufferList & PrepareNullBuffer(const CAStreamBasicDescription &format, UInt32 nFrames);
/*! @method SetBufferList */
AudioBufferList & SetBufferList(const AudioBufferList &abl) {
if (mAllocatedStreams < abl.mNumberBuffers)
COMPONENT_THROW(-1);
mPtrState = kPtrsToExternalMemory;
memcpy(mPtrs, &abl, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
return *mPtrs;
}
/*! @method SetBuffer */
void SetBuffer(UInt32 index, const AudioBuffer &ab) {
if (mPtrState == kPtrsInvalid || index >= mPtrs->mNumberBuffers)
COMPONENT_THROW(-1);
mPtrState = kPtrsToExternalMemory;
mPtrs->mBuffers[index] = ab;
}
/*! @method InvalidateBufferList */
void InvalidateBufferList() { mPtrState = kPtrsInvalid; }
/*! @method GetBufferList */
AudioBufferList & GetBufferList() const {
if (mPtrState == kPtrsInvalid)
COMPONENT_THROW(-1);
return *mPtrs;
}
/*! @method CopyBufferListTo */
void CopyBufferListTo(AudioBufferList &abl) const {
if (mPtrState == kPtrsInvalid)
COMPONENT_THROW(-1);
memcpy(&abl, mPtrs, (char *)&abl.mBuffers[abl.mNumberBuffers] - (char *)&abl);
}
/*! @method CopyBufferContentsTo */
void CopyBufferContentsTo(AudioBufferList &abl) const {
if (mPtrState == kPtrsInvalid)
COMPONENT_THROW(-1);
const AudioBuffer *srcbuf = mPtrs->mBuffers;
AudioBuffer *destbuf = abl.mBuffers;
for (UInt32 i = 0; i < abl.mNumberBuffers; ++i, ++srcbuf, ++destbuf) {
if (i >= mPtrs->mNumberBuffers) // duplicate last source to additional outputs [4341137]
--srcbuf;
if (destbuf->mData != srcbuf->mData)
memmove(destbuf->mData, srcbuf->mData, srcbuf->mDataByteSize);
destbuf->mDataByteSize = srcbuf->mDataByteSize;
}
}
/*! @method Allocate */
void Allocate(const CAStreamBasicDescription &format, UInt32 nFrames);
/*! @method Deallocate */
void Deallocate();
/*! @method UseExternalBuffer */
void UseExternalBuffer(const CAStreamBasicDescription &format, const AudioUnitExternalBuffer &buf);
// AudioBufferList utilities
/*! @method ZeroBuffer */
static void ZeroBuffer(AudioBufferList &abl) {
AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = abl.mNumberBuffers ; i--; ++buf)
memset(buf->mData, 0, buf->mDataByteSize);
}
#if DEBUG
/*! @method PrintBuffer */
static void PrintBuffer(const char *label, int subscript, const AudioBufferList &abl, UInt32 nFrames = 8, bool asFloats = true);
#endif
/*! @method GetAllocatedFrames */
UInt32 GetAllocatedFrames() const { return mAllocatedFrames; }
private:
/*! @ctor AUBufferList */
AUBufferList(AUBufferList &) { } // prohibit copy constructor
/*! @var mPtrState */
EPtrState mPtrState;
/*! @var mExternalMemory */
bool mExternalMemory;
/*! @var mPtrs */
AudioBufferList * mPtrs;
/*! @var mMemory */
Byte * mMemory;
/*! @var mAllocatedStreams */
UInt32 mAllocatedStreams;
/*! @var mAllocatedFrames */
UInt32 mAllocatedFrames;
/*! @var mAllocatedBytes */
UInt32 mAllocatedBytes;
};
// Allocates an array of samples (type T), to be optimally aligned for the processor
/*! @class TAUBuffer */
template <class T>
class TAUBuffer {
public:
enum {
kAlignInterval = 0x10,
kAlignMask = kAlignInterval - 1
};
/*! @ctor TAUBuffer.0 */
TAUBuffer() : mMemObject(NULL), mAlignedBuffer(NULL), mBufferSizeBytes(0)
{
}
/*! @ctor TAUBuffer.1 */
TAUBuffer(UInt32 numElems, UInt32 numChannels) : mMemObject(NULL), mAlignedBuffer(NULL),
mBufferSizeBytes(0)
{
Allocate(numElems, numChannels);
}
/*! @dtor ~TAUBuffer */
~TAUBuffer()
{
Deallocate();
}
/*! @method Allocate */
void Allocate(UInt32 numElems) // can also re-allocate
{
UInt32 reqSize = numElems * sizeof(T);
if (mMemObject != NULL && reqSize == mBufferSizeBytes)
return; // already allocated
mBufferSizeBytes = reqSize;
mMemObject = CA_realloc(mMemObject, reqSize);
UInt32 misalign = (uintptr_t)mMemObject & kAlignMask;
if (misalign) {
mMemObject = CA_realloc(mMemObject, reqSize + kAlignMask);
mAlignedBuffer = (T *)((char *)mMemObject + kAlignInterval - misalign);
} else
mAlignedBuffer = (T *)mMemObject;
}
/*! @method Deallocate */
void Deallocate()
{
if (mMemObject == NULL) return; // so this method has no effect if we're using
// an external buffer
free(mMemObject);
mMemObject = NULL;
mAlignedBuffer = NULL;
mBufferSizeBytes = 0;
}
/*! @method AllocateClear */
void AllocateClear(UInt32 numElems) // can also re-allocate
{
Allocate(numElems);
Clear();
}
/*! @method Clear */
void Clear()
{
memset(mAlignedBuffer, 0, mBufferSizeBytes);
}
// accessors
/*! @method operator T *()@ */
operator T *() { return mAlignedBuffer; }
private:
/*! @var mMemObject */
void * mMemObject; // null when using an external buffer
/*! @var mAlignedBuffer */
T * mAlignedBuffer; // always valid once allocated
/*! @var mBufferSizeBytes */
UInt32 mBufferSizeBytes;
};
#endif // __AUBuffer_h__

+ 0
- 438
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.cpp View File

@@ -1,438 +0,0 @@
/*
File: AUDispatch.cpp
Abstract: AUDispatch.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUBase.h"
#include "CAXException.h"
#include "AUDispatch.h"
#if TARGET_OS_MAC
#if __LP64__
// comp instance, parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index + 1];
#else
// parameters in reverse order, then comp instance
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
#endif
#elif TARGET_OS_WIN32
// (no comp instance), parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index];
#endif
OSStatus AUBase::ComponentEntryDispatch(ComponentParameters *params, AUBase *This)
{
if (This == NULL) return kAudio_ParamError;
OSStatus result = noErr;
switch (params->what) {
case kComponentCanDoSelect:
switch (GetSelectorForCanDo(params)) {
// any selectors
case kAudioUnitInitializeSelect:
case kAudioUnitUninitializeSelect:
case kAudioUnitGetPropertyInfoSelect:
case kAudioUnitGetPropertySelect:
case kAudioUnitSetPropertySelect:
case kAudioUnitAddPropertyListenerSelect:
#if (!__LP64__)
case kAudioUnitRemovePropertyListenerSelect:
#endif
case kAudioUnitGetParameterSelect:
case kAudioUnitSetParameterSelect:
case kAudioUnitResetSelect:
result = 1;
break;
// v1 selectors
// v2 selectors
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
case kAudioUnitAddRenderNotifySelect:
case kAudioUnitRemoveRenderNotifySelect:
case kAudioUnitScheduleParametersSelect:
case kAudioUnitRenderSelect:
result = (This->AudioUnitAPIVersion() > 1);
break;
default:
return ComponentBase::ComponentEntryDispatch(params, This);
}
break;
case kAudioUnitInitializeSelect:
{
CAMutex::Locker lock2(This->GetMutex());
result = This->DoInitialize();
}
break;
case kAudioUnitUninitializeSelect:
{
CAMutex::Locker lock2(This->GetMutex());
This->DoCleanup();
result = noErr;
}
break;
case kAudioUnitGetPropertyInfoSelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitPropertyID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(UInt32 *, poutDataSize, 3, 5);
PARAM(Boolean *, poutWritable, 4, 5);
// pass our own copies so that we assume responsibility for testing
// the caller's pointers against null and our C++ classes can
// always assume they're non-null
UInt32 dataSize;
Boolean writable;
result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
if (poutDataSize != NULL)
*poutDataSize = dataSize;
if (poutWritable != NULL)
*poutWritable = writable;
}
break;
case kAudioUnitGetPropertySelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitPropertyID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(void *, poutData, 3, 5);
PARAM(UInt32 *, pioDataSize, 4, 5);
UInt32 actualPropertySize, clientBufferSize;
Boolean writable;
char *tempBuffer;
void *destBuffer;
if (pioDataSize == NULL) {
ca_debug_string("AudioUnitGetProperty: null size pointer");
result = kAudio_ParamError;
goto finishGetProperty;
}
if (poutData == NULL) {
UInt32 dataSize;
result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement, dataSize, writable);
*pioDataSize = dataSize;
goto finishGetProperty;
}
clientBufferSize = *pioDataSize;
if (clientBufferSize == 0)
{
ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
// $$$ or should we allow this as a shortcut for finding the size?
result = kAudio_ParamError;
goto finishGetProperty;
}
result = This->DispatchGetPropertyInfo(pinID, pinScope, pinElement,
actualPropertySize, writable);
if (result)
goto finishGetProperty;
if (clientBufferSize < actualPropertySize)
{
tempBuffer = new char[actualPropertySize];
destBuffer = tempBuffer;
} else {
tempBuffer = NULL;
destBuffer = poutData;
}
result = This->DispatchGetProperty(pinID, pinScope, pinElement, destBuffer);
if (result == noErr) {
if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
{
memcpy(poutData, tempBuffer, clientBufferSize);
delete[] tempBuffer;
// pioDataSize remains correct, the number of bytes we wrote
} else
*pioDataSize = actualPropertySize;
} else
*pioDataSize = 0;
finishGetProperty:
;
}
break;
case kAudioUnitSetPropertySelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitPropertyID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(const void *, pinData, 3, 5);
PARAM(UInt32, pinDataSize, 4, 5);
if (pinData && pinDataSize)
result = This->DispatchSetProperty(pinID, pinScope, pinElement, pinData, pinDataSize);
else {
if (pinData == NULL && pinDataSize == 0) {
result = This->DispatchRemovePropertyValue (pinID, pinScope, pinElement);
} else {
if (pinData == NULL) {
ca_debug_string("AudioUnitSetProperty: inData == NULL");
result = kAudio_ParamError;
goto finishSetProperty;
}
if (pinDataSize == 0) {
ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
result = kAudio_ParamError;
goto finishSetProperty;
}
}
}
finishSetProperty:
;
}
break;
case kAudioUnitAddPropertyListenerSelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitPropertyID, pinID, 0, 3);
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
PARAM(void *, pinProcRefCon, 2, 3);
result = This->AddPropertyListener(pinID, pinProc, pinProcRefCon);
}
break;
#if (!__LP64__)
case kAudioUnitRemovePropertyListenerSelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitPropertyID, pinID, 0, 2);
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 2);
result = This->RemovePropertyListener(pinID, pinProc, NULL, false);
}
break;
#endif
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitPropertyID, pinID, 0, 3);
PARAM(AudioUnitPropertyListenerProc, pinProc, 1, 3);
PARAM(void *, pinProcRefCon, 2, 3);
result = This->RemovePropertyListener(pinID, pinProc, pinProcRefCon, true);
}
break;
case kAudioUnitAddRenderNotifySelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AURenderCallback, pinProc, 0, 2);
PARAM(void *, pinProcRefCon, 1, 2);
result = This->SetRenderNotification (pinProc, pinProcRefCon);
}
break;
case kAudioUnitRemoveRenderNotifySelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AURenderCallback, pinProc, 0, 2);
PARAM(void *, pinProcRefCon, 1, 2);
result = This->RemoveRenderNotification (pinProc, pinProcRefCon);
}
break;
case kAudioUnitGetParameterSelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitParameterID, pinID, 0, 4);
PARAM(AudioUnitScope, pinScope, 1, 4);
PARAM(AudioUnitElement, pinElement, 2, 4);
PARAM(AudioUnitParameterValue *, poutValue, 3, 4);
result = (poutValue == NULL ? kAudio_ParamError : This->GetParameter(pinID, pinScope, pinElement, *poutValue));
}
break;
case kAudioUnitSetParameterSelect:
{
CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
PARAM(AudioUnitParameterID, pinID, 0, 5);
PARAM(AudioUnitScope, pinScope, 1, 5);
PARAM(AudioUnitElement, pinElement, 2, 5);
PARAM(AudioUnitParameterValue, pinValue, 3, 5);
PARAM(UInt32, pinBufferOffsetInFrames, 4, 5);
result = This->SetParameter(pinID, pinScope, pinElement, pinValue, pinBufferOffsetInFrames);
}
break;
case kAudioUnitScheduleParametersSelect:
{
CAMutex::Locker lock(This->GetMutex()); // is this realtime or no???
if (This->AudioUnitAPIVersion() > 1)
{
PARAM(AudioUnitParameterEvent *, pinParameterEvent, 0, 2);
PARAM(UInt32, pinNumParamEvents, 1, 2);
result = This->ScheduleParameter (pinParameterEvent, pinNumParamEvents);
} else
result = badComponentSelector;
}
break;
case kAudioUnitRenderSelect:
{
// realtime; no lock
{
PARAM(AudioUnitRenderActionFlags *, pinActionFlags, 0, 5);
PARAM(const AudioTimeStamp *, pinTimeStamp, 1, 5);
PARAM(UInt32, pinOutputBusNumber, 2, 5);
PARAM(UInt32, pinNumberFrames, 3, 5);
PARAM(AudioBufferList *, pioData, 4, 5);
AudioUnitRenderActionFlags tempFlags;
if (pinTimeStamp == NULL || pioData == NULL)
result = kAudio_ParamError;
else {
if (pinActionFlags == NULL) {
tempFlags = 0;
pinActionFlags = &tempFlags;
}
result = This->DoRender(*pinActionFlags, *pinTimeStamp, pinOutputBusNumber, pinNumberFrames, *pioData);
}
}
}
break;
case kAudioUnitResetSelect:
{
CAMutex::Locker lock(This->GetMutex());
PARAM(AudioUnitScope, pinScope, 0, 2);
PARAM(AudioUnitElement, pinElement, 1, 2);
This->ResetRenderTime();
result = This->Reset(pinScope, pinElement);
}
break;
default:
result = ComponentBase::ComponentEntryDispatch(params, This);
break;
}
return result;
}
// Fast dispatch entry points -- these need to replicate all error-checking logic from above
OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float *outValue)
{
OSStatus result = AUBase::noErr;
try {
if (This == NULL || outValue == NULL) return kAudio_ParamError;
result = This->GetParameter(inID, inScope, inElement, *outValue);
}
COMPONENT_CATCH
return result;
}
OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float inValue,
UInt32 inBufferOffset)
{
OSStatus result = AUBase::noErr;
try {
if (This == NULL) return kAudio_ParamError;
result = This->SetParameter(inID, inScope, inElement, inValue, inBufferOffset);
}
COMPONENT_CATCH
return result;
}
OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
if (inTimeStamp == NULL || ioData == NULL) return kAudio_ParamError;
OSStatus result = AUBase::noErr;
AudioUnitRenderActionFlags tempFlags;
try {
if (ioActionFlags == NULL) {
tempFlags = 0;
ioActionFlags = &tempFlags;
}
result = This->DoRender(*ioActionFlags, *inTimeStamp, inBusNumber, inNumberFrames, *ioData);
}
COMPONENT_CATCH
return result;
}

+ 0
- 82
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUDispatch.h View File

@@ -1,82 +0,0 @@
/*
File: AUDispatch.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUDispatch_h__
#define __AUDispatch_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioUnit.h>
#else
#include "AudioUnit.h"
#endif
#if !CA_USE_AUDIO_PLUGIN_ONLY
/*! @function AudioUnitBaseGetParameter */
OSStatus CMgr_AudioUnitBaseGetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float * outValue);
/*! @function AudioUnitBaseSetParameter */
OSStatus CMgr_AudioUnitBaseSetParameter( AUBase * This,
AudioUnitParameterID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
float inValue,
UInt32 inBufferOffset);
/*! @function AudioUnitBaseRender */
OSStatus CMgr_AudioUnitBaseRender( AUBase * This,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);
#endif
#endif // __AUDispatch_h__

+ 0
- 151
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.cpp View File

@@ -1,151 +0,0 @@
/*
File: AUInputElement.cpp
Abstract: AUInputElement.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUBase.h"
inline bool HasGoodBufferPointers(const AudioBufferList &abl, UInt32 nBytes)
{
const AudioBuffer *buf = abl.mBuffers;
for (UInt32 i = abl.mNumberBuffers; i--;++buf) {
if (buf->mData == NULL || buf->mDataByteSize < nBytes)
return false;
}
return true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::AUInputElement
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AUInputElement::AUInputElement(AUBase *audioUnit) :
AUIOElement(audioUnit),
mInputType(kNoInput)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::SetConnection
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AUInputElement::SetConnection(const AudioUnitConnection &conn)
{
if (conn.sourceAudioUnit == 0) {
Disconnect();
return;
}
mInputType = kFromConnection;
mConnection = conn;
AllocateBuffer();
mConnInstanceStorage = NULL;
#if !CA_USE_AUDIO_PLUGIN_ONLY
mConnRenderProc = NULL;
UInt32 size = sizeof(AudioUnitRenderProc);
OSStatus result = AudioUnitGetProperty( conn.sourceAudioUnit,
kAudioUnitProperty_FastDispatch,
kAudioUnitScope_Global,
kAudioUnitRenderSelect,
&mConnRenderProc,
&size);
if (result == noErr)
mConnInstanceStorage = CMgr_GetComponentInstanceStorage (conn.sourceAudioUnit);
else
mConnRenderProc = NULL;
#endif
}
void AUInputElement::Disconnect()
{
mInputType = kNoInput;
mIOBuffer.Deallocate();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUInputElement::SetInputCallback
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void AUInputElement::SetInputCallback(AURenderCallback proc, void *refCon)
{
if (proc == NULL)
Disconnect();
else {
mInputType = kFromCallback;
mInputProc = proc;
mInputProcRefCon = refCon;
AllocateBuffer();
}
}
OSStatus AUInputElement::SetStreamFormat(const CAStreamBasicDescription &fmt)
{
OSStatus err = AUIOElement::SetStreamFormat(fmt);
if (err == AUBase::noErr)
AllocateBuffer();
return err;
}
OSStatus AUInputElement::PullInput( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 nFrames)
{
if (!IsActive())
return kAudioUnitErr_NoConnection;
AudioBufferList *pullBuffer;
if (HasConnection() || !WillAllocateBuffer())
pullBuffer = &mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
else
pullBuffer = &mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
return PullInputWithBufferList (ioActionFlags, inTimeStamp, inElement, nFrames, pullBuffer);
}

+ 0
- 119
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputElement.h View File

@@ -1,119 +0,0 @@
/*
File: AUInputElement.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUInput_h__
#define __AUInput_h__
#include "AUScopeElement.h"
#include "AUBuffer.h"
/*! @class AUInputElement */
class AUInputElement : public AUIOElement {
public:
/*! @ctor AUInputElement */
AUInputElement(AUBase *audioUnit);
/*! @dtor ~AUInputElement */
virtual ~AUInputElement() { }
// AUElement override
/*! @method SetStreamFormat */
virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
/*! @method NeedsBufferSpace */
virtual bool NeedsBufferSpace() const { return IsCallback(); }
/*! @method SetConnection */
void SetConnection(const AudioUnitConnection &conn);
/*! @method SetInputCallback */
void SetInputCallback(AURenderCallback proc, void *refCon);
/*! @method IsActive */
bool IsActive() const { return mInputType != kNoInput; }
/*! @method IsCallback */
bool IsCallback() const { return mInputType == kFromCallback; }
/*! @method HasConnection */
bool HasConnection() const { return mInputType == kFromConnection; }
/*! @method PullInput */
OSStatus PullInput( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 inNumberFrames);
/*! @method PullInputWithBufferList */
OSStatus PullInputWithBufferList( AudioUnitRenderActionFlags & ioActionFlags,
const AudioTimeStamp & inTimeStamp,
AudioUnitElement inElement,
UInt32 nFrames,
AudioBufferList * inBufferList);
protected:
/*! @method Disconnect */
void Disconnect();
enum EInputType { kNoInput, kFromConnection, kFromCallback };
/*! @var mInputType */
EInputType mInputType;
// if from callback:
/*! @var mInputProc */
AURenderCallback mInputProc;
/*! @var mInputProcRefCon */
void * mInputProcRefCon;
// if from connection:
/*! @var mConnection */
AudioUnitConnection mConnection;
#if !CA_USE_AUDIO_PLUGIN_ONLY
/*! @var mConnRenderProc */
AudioUnitRenderProc mConnRenderProc;
#endif
/*! @var mConnInstanceStorage */
void * mConnInstanceStorage; // for the input component
};
#endif // __AUInput_h__

+ 0
- 155
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUInputFormatConverter.h View File

@@ -1,155 +0,0 @@
/*
File: AUInputFormatConverter.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUInputFormatConverter_h__
#define __AUInputFormatConverter_h__
#include "FormatConverterClient.h"
#include "AUTimestampGenerator.h"
// ____________________________________________________________________________
// AUInputFormatConverter
//
// Subclass of FormatConverterClient that applies a format conversion
// to an input of an AudioUnit.
/*! @class AUInputFormatConverter */
class AUInputFormatConverter : public FormatConverterClient {
public:
/*! @ctor AUInputFormatConverter */
AUInputFormatConverter(AUBase *hostAU, int inputBus) :
mHost(hostAU),
mHostBus(inputBus),
mPreviousSilentFrames(0x1000)
{
#if DEBUG
mTimestampGenerator.mVerbosity = 0;
strcpy(mTimestampGenerator.mDebugName, "AUConverter");
#endif
}
// need to subsequently call Initialize, with the desired formats
/*! @dtor ~AUInputFormatConverter */
~AUInputFormatConverter()
{
}
virtual OSStatus Initialize(const AudioStreamBasicDescription &src, const AudioStreamBasicDescription &dest)
{
OSStatus err = FormatConverterClient::Initialize(src, dest);
if (err) return err;
mIsPCMToPCM = (src.mFormatID == kAudioFormatLinearPCM) && (dest.mFormatID == kAudioFormatLinearPCM);
mHasSRC = (fnonzero(src.mSampleRate) && fnonzero(dest.mSampleRate) && fnotequal(src.mSampleRate, dest.mSampleRate));
return ca_noErr;
}
virtual OSStatus Reset()
{
mPreviousSilentFrames = 0x1000;
mTimestampGenerator.Reset();
return FormatConverterClient::Reset();
}
void SetStartInputTimeAtZero(bool b)
{
mTimestampGenerator.SetStartInputAtZero(b);
}
/*! @method FillComplexBuffer */
OSStatus AUFillComplexBuffer(const AudioTimeStamp & inTimeStamp,
UInt32 & ioOutputDataPacketSize,
AudioBufferList & outOutputData,
AudioStreamPacketDescription* outPacketDescription,
bool& outSilence)
{
mTimestampGenerator.AddOutputTime(inTimeStamp, ioOutputDataPacketSize, mOutputFormat.mSampleRate);
mSilentOutput = true;
OSStatus err = FillComplexBuffer(ioOutputDataPacketSize, outOutputData, outPacketDescription);
if (mSilentOutput) {
if (!mIsPCMToPCM || (mHasSRC && mPreviousSilentFrames < 32))
mSilentOutput = false;
mPreviousSilentFrames += ioOutputDataPacketSize;
} else
mPreviousSilentFrames = 0;
outSilence = mSilentOutput;
return err;
}
/*! @method FormatConverterInputProc */
virtual OSStatus FormatConverterInputProc(
UInt32 & ioNumberDataPackets,
AudioBufferList & ioData,
AudioStreamPacketDescription** outDataPacketDescription)
{
OSStatus err = ca_noErr;
AudioUnitRenderActionFlags actionFlags = 0;
AUInputElement *input = mHost->GetInput(mHostBus);
*ioNumberDataPackets = std::min(*ioNumberDataPackets, This->mHost->GetMaxFramesPerSlice());
const AudioTimeStamp &inputTime = mTimestampGenerator.GenerateInputTime(ioNumberDataPackets, mInputFormat.mSampleRate);
err = input->PullInput(actionFlags, inputTime, mHostBus, ioNumberDataPackets);
if (!err) {
input->CopyBufferListTo(ioData);
if (!(actionFlags & kAudioUnitRenderAction_OutputIsSilence))
mSilentOutput = false;
}
return err;
}
protected:
/*! @var mHost */
AUBase * mHost;
/*! @var mHostBus */
int mHostBus;
AUTimestampGenerator mTimestampGenerator;
bool mIsPCMToPCM;
bool mHasSRC;
bool mSilentOutput;
UInt32 mPreviousSilentFrames;
};
#endif // __AUInputFormatConverter_h__

+ 0
- 495
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.cpp View File

@@ -1,495 +0,0 @@
/*
File: AUMIDIBase.cpp
Abstract: AUMIDIBase.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUMIDIBase.h"
#include <CoreMIDI/CoreMIDI.h>
#include "CAXException.h"
//temporary location
enum
{
kMidiMessage_NoteOff = 0x80,
kMidiMessage_NoteOn = 0x90,
kMidiMessage_PolyPressure = 0xA0,
kMidiMessage_ControlChange = 0xB0,
kMidiMessage_ProgramChange = 0xC0,
kMidiMessage_ChannelPressure = 0xD0,
kMidiMessage_PitchWheel = 0xE0,
kMidiController_AllSoundOff = 120,
kMidiController_ResetAllControllers = 121,
kMidiController_AllNotesOff = 123
};
AUMIDIBase::AUMIDIBase(AUBase* inBase)
: mAUBaseInstance (*inBase)
{
#if CA_AUTO_MIDI_MAP
mMapManager = new CAAUMIDIMapManager();
#endif
}
AUMIDIBase::~AUMIDIBase()
{
#if CA_AUTO_MIDI_MAP
if (mMapManager)
delete mMapManager;
#endif
}
#if TARGET_API_MAC_OSX
OSStatus AUMIDIBase::DelegateGetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus result = noErr;
switch (inID) {
#if !TARGET_OS_IPHONE
case kMusicDeviceProperty_MIDIXMLNames:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
if (GetXMLNames(NULL) == noErr) {
outDataSize = sizeof(CFURLRef);
outWritable = false;
} else
result = kAudioUnitErr_InvalidProperty;
break;
#endif
#if CA_AUTO_MIDI_MAP
case kAudioUnitProperty_AllParameterMIDIMappings:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping)*mMapManager->NumMaps();
result = noErr;
break;
case kAudioUnitProperty_HotMapParameterMIDIMapping:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping);
result = noErr;
break;
case kAudioUnitProperty_AddParameterMIDIMapping:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping);
result = noErr;
break;
case kAudioUnitProperty_RemoveParameterMIDIMapping:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
outWritable = true;
outDataSize = sizeof (AUParameterMIDIMapping);
result = noErr;
break;
#endif
default:
result = kAudioUnitErr_InvalidProperty;
break;
}
return result;
#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
InvalidScope:
return kAudioUnitErr_InvalidScope;
InvalidElement:
return kAudioUnitErr_InvalidElement;
#endif
}
OSStatus AUMIDIBase::DelegateGetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus result;
switch (inID) {
#if !TARGET_OS_IPHONE
case kMusicDeviceProperty_MIDIXMLNames:
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
result = GetXMLNames((CFURLRef *)outData);
break;
#endif
#if CA_AUTO_MIDI_MAP
case kAudioUnitProperty_AllParameterMIDIMappings:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping* maps = (static_cast<AUParameterMIDIMapping*>(outData));
mMapManager->GetMaps(maps);
// printf ("GETTING MAPS\n");
// mMapManager->Print();
result = noErr;
break;
}
case kAudioUnitProperty_HotMapParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * map = (static_cast<AUParameterMIDIMapping*>(outData));
mMapManager->GetHotParameterMap (*map);
result = noErr;
break;
}
#endif
default:
result = kAudioUnitErr_InvalidProperty;
break;
}
return result;
#if CA_AUTO_MIDI_MAP || (!TARGET_OS_IPHONE)
InvalidScope:
return kAudioUnitErr_InvalidScope;
InvalidElement:
return kAudioUnitErr_InvalidElement;
#endif
}
OSStatus AUMIDIBase::DelegateSetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
OSStatus result;
switch (inID) {
#if CA_AUTO_MIDI_MAP
case kAudioUnitProperty_AddParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
mMapManager->SortedInsertToParamaterMaps (maps, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
result = noErr;
break;
}
case kAudioUnitProperty_RemoveParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * maps = (AUParameterMIDIMapping*)inData;
bool didChange;
mMapManager->SortedRemoveFromParameterMaps(maps, (inDataSize / sizeof(AUParameterMIDIMapping)), didChange);
if (didChange)
mAUBaseInstance.PropertyChanged (kAudioUnitProperty_AllParameterMIDIMappings, kAudioUnitScope_Global, 0);
result = noErr;
break;
}
case kAudioUnitProperty_HotMapParameterMIDIMapping:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping & map = *((AUParameterMIDIMapping*)inData);
mMapManager->SetHotMapping (map);
result = noErr;
break;
}
case kAudioUnitProperty_AllParameterMIDIMappings:{
ca_require(inScope == kAudioUnitScope_Global, InvalidScope);
ca_require(inElement == 0, InvalidElement);
AUParameterMIDIMapping * mappings = (AUParameterMIDIMapping*)inData;
mMapManager->ReplaceAllMaps (mappings, (inDataSize / sizeof(AUParameterMIDIMapping)), mAUBaseInstance);
result = noErr;
break;
}
#endif
default:
result = kAudioUnitErr_InvalidProperty;
break;
}
return result;
#if CA_AUTO_MIDI_MAP
InvalidScope:
return kAudioUnitErr_InvalidScope;
InvalidElement:
return kAudioUnitErr_InvalidElement;
#endif
}
#endif //TARGET_API_MAC_OSX
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma mark ____MidiDispatch
inline const Byte * NextMIDIEvent(const Byte *event, const Byte *end)
{
Byte c = *event;
switch (c >> 4) {
default: // data byte -- assume in sysex
while ((*++event & 0x80) == 0 && event < end)
;
break;
case 0x8:
case 0x9:
case 0xA:
case 0xB:
case 0xE:
event += 3;
break;
case 0xC:
case 0xD:
event += 2;
break;
case 0xF:
switch (c) {
case 0xF0:
while ((*++event & 0x80) == 0 && event < end)
;
break;
case 0xF1:
case 0xF3:
event += 2;
break;
case 0xF2:
event += 3;
break;
default:
++event;
break;
}
}
return (event >= end) ? end : event;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUMIDIBase::HandleMIDIPacketList
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus AUMIDIBase::HandleMIDIPacketList(const MIDIPacketList *pktlist)
{
if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
int nPackets = pktlist->numPackets;
const MIDIPacket *pkt = pktlist->packet;
while (nPackets-- > 0) {
const Byte *event = pkt->data, *packetEnd = event + pkt->length;
long startFrame = (long)pkt->timeStamp;
while (event < packetEnd) {
Byte status = event[0];
if (status & 0x80) {
// really a status byte (not sysex continuation)
HandleMidiEvent(status & 0xF0, status & 0x0F, event[1], event[2], static_cast<UInt32>(startFrame));
// note that we're generating a bogus channel number for system messages (0xF0-FF)
}
event = NextMIDIEvent(event, packetEnd);
}
pkt = reinterpret_cast<const MIDIPacket *>(packetEnd);
}
return noErr;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUMIDIBase::HandleMidiEvent
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus AUMIDIBase::HandleMidiEvent(UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
{
if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
#if CA_AUTO_MIDI_MAP
// you potentially have a choice to make here - if a param mapping matches, do you still want to process the
// MIDI event or not. The default behaviour is to continue on with the MIDI event.
if (mMapManager->HandleHotMapping (status, channel, data1, mAUBaseInstance)) {
mAUBaseInstance.PropertyChanged (kAudioUnitProperty_HotMapParameterMIDIMapping, kAudioUnitScope_Global, 0);
}
else {
mMapManager->FindParameterMapEventMatch(status, channel, data1, data2, inStartFrame, mAUBaseInstance);
}
#endif
OSStatus result = noErr;
switch(status)
{
case kMidiMessage_NoteOn:
if(data2)
{
result = HandleNoteOn(channel, data1, data2, inStartFrame);
}
else
{
// zero velocity translates to note off
result = HandleNoteOff(channel, data1, data2, inStartFrame);
}
break;
case kMidiMessage_NoteOff:
result = HandleNoteOff(channel, data1, data2, inStartFrame);
break;
default:
result = HandleNonNoteEvent (status, channel, data1, data2, inStartFrame);
break;
}
return result;
}
OSStatus AUMIDIBase::HandleNonNoteEvent (UInt8 status, UInt8 channel, UInt8 data1, UInt8 data2, UInt32 inStartFrame)
{
OSStatus result = noErr;
switch (status)
{
case kMidiMessage_PitchWheel:
result = HandlePitchWheel(channel, data1, data2, inStartFrame);
break;
case kMidiMessage_ProgramChange:
result = HandleProgramChange(channel, data1);
break;
case kMidiMessage_ChannelPressure:
result = HandleChannelPressure(channel, data1, inStartFrame);
break;
case kMidiMessage_ControlChange:
{
switch (data1) {
case kMidiController_AllNotesOff:
result = HandleAllNotesOff(channel);
break;
case kMidiController_ResetAllControllers:
result = HandleResetAllControllers(channel);
break;
case kMidiController_AllSoundOff:
result = HandleAllSoundOff(channel);
break;
default:
result = HandleControlChange(channel, data1, data2, inStartFrame);
break;
}
break;
}
case kMidiMessage_PolyPressure:
result = HandlePolyPressure (channel, data1, data2, inStartFrame);
break;
}
return result;
}
OSStatus AUMIDIBase::SysEx (const UInt8 * inData,
UInt32 inLength)
{
if (!mAUBaseInstance.IsInitialized()) return kAudioUnitErr_Uninitialized;
return HandleSysEx(inData, inLength );
}
#if TARGET_OS_MAC
#if __LP64__
// comp instance, parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index + 1];
#else
// parameters in reverse order, then comp instance
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
#endif
#elif TARGET_OS_WIN32
// (no comp instance), parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index];
#endif
#if !CA_USE_AUDIO_PLUGIN_ONLY
OSStatus AUMIDIBase::ComponentEntryDispatch( ComponentParameters * params,
AUMIDIBase * This)
{
if (This == NULL) return kAudio_ParamError;
OSStatus result;
switch (params->what) {
case kMusicDeviceMIDIEventSelect:
{
PARAM(UInt32, pbinStatus, 0, 4);
PARAM(UInt32, pbinData1, 1, 4);
PARAM(UInt32, pbinData2, 2, 4);
PARAM(UInt32, pbinOffsetSampleFrame, 3, 4);
result = This->MIDIEvent(pbinStatus, pbinData1, pbinData2, pbinOffsetSampleFrame);
}
break;
case kMusicDeviceSysExSelect:
{
PARAM(const UInt8 *, pbinData, 0, 2);
PARAM(UInt32, pbinLength, 1, 2);
result = This->SysEx(pbinData, pbinLength);
}
break;
default:
result = badComponentSelector;
break;
}
return result;
}
#endif

+ 0
- 213
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUMIDIBase.h View File

@@ -1,213 +0,0 @@
/*
File: AUMIDIBase.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUMIDIBase_h__
#define __AUMIDIBase_h__
#include "AUBase.h"
#if CA_AUTO_MIDI_MAP
#include "CAAUMIDIMapManager.h"
#endif
struct MIDIPacketList;
// ________________________________________________________________________
// MusicDeviceBase
//
/*! @class AUMIDIBase */
class AUMIDIBase {
public:
// this is NOT a copy constructor!
/*! @ctor AUMIDIBase */
AUMIDIBase(AUBase* inBase);
/*! @dtor ~AUMIDIBase */
virtual ~AUMIDIBase();
/*! @method MIDIEvent */
virtual OSStatus MIDIEvent( UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame)
{
UInt32 strippedStatus = inStatus & 0xf0;
UInt32 channel = inStatus & 0x0f;
return HandleMidiEvent(strippedStatus, channel, inData1, inData2, inOffsetSampleFrame);
}
/*! @method HandleMIDIPacketList */
OSStatus HandleMIDIPacketList(const MIDIPacketList *pktlist);
/*! @method SysEx */
virtual OSStatus SysEx( const UInt8 * inData,
UInt32 inLength);
#if TARGET_API_MAC_OSX
/*! @method DelegateGetPropertyInfo */
virtual OSStatus DelegateGetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);
/*! @method DelegateGetProperty */
virtual OSStatus DelegateGetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
/*! @method DelegateSetProperty */
virtual OSStatus DelegateSetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
#endif
protected:
// MIDI dispatch
/*! @method HandleMidiEvent */
virtual OSStatus HandleMidiEvent( UInt8 inStatus,
UInt8 inChannel,
UInt8 inData1,
UInt8 inData2,
UInt32 inStartFrame);
/*! @method HandleNonNoteEvent */
virtual OSStatus HandleNonNoteEvent ( UInt8 status,
UInt8 channel,
UInt8 data1,
UInt8 data2,
UInt32 inStartFrame);
#if TARGET_API_MAC_OSX
/*! @method GetXMLNames */
virtual OSStatus GetXMLNames(CFURLRef *outNameDocument)
{ return kAudioUnitErr_InvalidProperty; } // if not overridden, it's unsupported
#endif
// channel messages
/*! @method HandleNoteOn */
virtual OSStatus HandleNoteOn( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleNoteOff */
virtual OSStatus HandleNoteOff( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleControlChange */
virtual OSStatus HandleControlChange( UInt8 inChannel,
UInt8 inController,
UInt8 inValue,
UInt32 inStartFrame) { return noErr; }
/*! @method HandlePitchWheel */
virtual OSStatus HandlePitchWheel( UInt8 inChannel,
UInt8 inPitch1,
UInt8 inPitch2,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleChannelPressure */
virtual OSStatus HandleChannelPressure( UInt8 inChannel,
UInt8 inValue,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleProgramChange */
virtual OSStatus HandleProgramChange( UInt8 inChannel,
UInt8 inValue) { return noErr; }
/*! @method HandlePolyPressure */
virtual OSStatus HandlePolyPressure( UInt8 inChannel,
UInt8 inKey,
UInt8 inValue,
UInt32 inStartFrame) { return noErr; }
/*! @method HandleResetAllControllers */
virtual OSStatus HandleResetAllControllers(UInt8 inChannel) { return noErr; }
/*! @method HandleAllNotesOff */
virtual OSStatus HandleAllNotesOff( UInt8 inChannel) { return noErr; }
/*! @method HandleAllSoundOff */
virtual OSStatus HandleAllSoundOff( UInt8 inChannel) { return noErr; }
//System messages
/*! @method HandleSysEx */
virtual OSStatus HandleSysEx( const UInt8 * inData,
UInt32 inLength ) { return noErr; }
#if CA_AUTO_MIDI_MAP
/* map manager */
CAAUMIDIMapManager *GetMIDIMapManager() {return mMapManager;};
#endif
private:
/*! @var mAUBaseInstance */
AUBase & mAUBaseInstance;
#if CA_AUTO_MIDI_MAP
/* map manager */
CAAUMIDIMapManager * mMapManager;
#endif
public:
#if !CA_USE_AUDIO_PLUGIN_ONLY
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters *params,
AUMIDIBase *This);
#endif
};
#endif // __AUMIDIBase_h__

+ 0
- 76
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.cpp View File

@@ -1,76 +0,0 @@
/*
File: AUOutputBase.cpp
Abstract: AUOutputBase.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !CA_USE_AUDIO_PLUGIN_ONLY
#include "AUOutputBase.h"
OSStatus AUOutputBase::ComponentEntryDispatch(ComponentParameters *params, AUOutputBase *This)
{
if (This == NULL) return paramErr;
OSStatus result;
switch (params->what) {
case kAudioOutputUnitStartSelect:
{
result = This->Start();
}
break;
case kAudioOutputUnitStopSelect:
{
result = This->Stop();
}
break;
default:
result = badComponentSelector;
break;
}
return result;
}
#endif

+ 0
- 82
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputBase.h View File

@@ -1,82 +0,0 @@
/*
File: AUOutputBase.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUOutputBase_h__
#define __AUOutputBase_h__
#include "AUBase.h"
// ________________________________________________________________________
// AUOutputBase
// this is now a mix-in rather than an AUBase subclass
/*! @class AUOutputBase */
class AUOutputBase {
public:
/*! @ctor AUOutputBase */
AUOutputBase(AUBase *inBase) : mAUBaseInstance(*inBase) { }
virtual ~AUOutputBase() { }
// additional component entry points
/*! @method Start */
virtual OSStatus Start() = 0;
/*! @method Stop */
virtual OSStatus Stop() = 0;
#if !CA_USE_AUDIO_PLUGIN_ONLY
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
AUOutputBase * This);
#endif
private:
/*! @var mAUBaseInstance */
AUBase & mAUBaseInstance;
};
#endif // __AUOutputBase_h__

+ 0
- 63
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.cpp View File

@@ -1,63 +0,0 @@
/*
File: AUOutputElement.cpp
Abstract: AUOutputElement.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUOutputElement.h"
#include "AUBase.h"
AUOutputElement::AUOutputElement(AUBase *audioUnit) :
AUIOElement(audioUnit)
{
AllocateBuffer();
}
OSStatus AUOutputElement::SetStreamFormat(const CAStreamBasicDescription &desc)
{
OSStatus result = AUIOElement::SetStreamFormat(desc); // inherited
if (result == AUBase::noErr)
AllocateBuffer();
return result;
}

+ 0
- 66
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUOutputElement.h View File

@@ -1,66 +0,0 @@
/*
File: AUOutputElement.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUOutput_h__
#define __AUOutput_h__
#include "AUScopeElement.h"
#include "AUBuffer.h"
/*! @class AUOutputElement */
class AUOutputElement : public AUIOElement {
public:
/*! @ctor AUOutputElement */
AUOutputElement(AUBase *audioUnit);
// AUElement override
/*! @method SetStreamFormat */
virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
/*! @method NeedsBufferSpace */
virtual bool NeedsBufferSpace() const { return true; }
};
#endif // __AUOutput_h__

+ 0
- 668
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.cpp View File

@@ -1,668 +0,0 @@
/*
File: AUPlugInDispatch.cpp
Abstract: AUPlugInDispatch.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUPlugInDispatch.h"
#include "CAXException.h"
#include "ComponentBase.h"
#include "AUBase.h"
#define ACPI ((AudioComponentPlugInInstance *)self)
#define AUI ((AUBase *)&ACPI->mInstanceStorage)
#define AUI_LOCK CAMutex::Locker auLock(AUI->GetMutex());
// ------------------------------------------------------------------------------------------------
static OSStatus AUMethodInitialize(void *self)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->DoInitialize();
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodUninitialize(void *self)
{
OSStatus result = noErr;
try {
AUI_LOCK
AUI->DoCleanup();
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodGetPropertyInfo(void *self, AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32 *outDataSize, Boolean *outWritable)
{
OSStatus result = noErr;
try {
UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when there is an error. This is a problem for auval.
Boolean writable = false;
AUI_LOCK
result = AUI->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
if (outDataSize != NULL)
*outDataSize = dataSize;
if (outWritable != NULL)
*outWritable = writable;
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodGetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize)
{
OSStatus result = noErr;
try {
UInt32 actualPropertySize, clientBufferSize;
Boolean writable;
char *tempBuffer;
void *destBuffer;
AUI_LOCK
if (ioDataSize == NULL) {
ca_debug_string("AudioUnitGetProperty: null size pointer");
result = kAudio_ParamError;
goto finishGetProperty;
}
if (outData == NULL) {
UInt32 dataSize;
result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, dataSize, writable);
*ioDataSize = dataSize;
goto finishGetProperty;
}
clientBufferSize = *ioDataSize;
if (clientBufferSize == 0)
{
ca_debug_string("AudioUnitGetProperty: *ioDataSize == 0 on entry");
// $$$ or should we allow this as a shortcut for finding the size?
result = kAudio_ParamError;
goto finishGetProperty;
}
result = AUI->DispatchGetPropertyInfo(inID, inScope, inElement, actualPropertySize, writable);
if (result != noErr)
goto finishGetProperty;
if (clientBufferSize < actualPropertySize)
{
tempBuffer = new char[actualPropertySize];
destBuffer = tempBuffer;
} else {
tempBuffer = NULL;
destBuffer = outData;
}
result = AUI->DispatchGetProperty(inID, inScope, inElement, destBuffer);
if (result == noErr) {
if (clientBufferSize < actualPropertySize && tempBuffer != NULL)
{
memcpy(outData, tempBuffer, clientBufferSize);
delete[] tempBuffer;
// ioDataSize remains correct, the number of bytes we wrote
} else
*ioDataSize = actualPropertySize;
} else
*ioDataSize = 0;
}
COMPONENT_CATCH
finishGetProperty:
return result;
}
static OSStatus AUMethodSetProperty(void *self, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize)
{
OSStatus result = noErr;
try {
AUI_LOCK
if (inData && inDataSize)
result = AUI->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
else {
if (inData == NULL && inDataSize == 0) {
result = AUI->DispatchRemovePropertyValue(inID, inScope, inElement);
} else {
if (inData == NULL) {
ca_debug_string("AudioUnitSetProperty: inData == NULL");
result = kAudio_ParamError;
goto finishSetProperty;
}
if (inDataSize == 0) {
ca_debug_string("AudioUnitSetProperty: inDataSize == 0");
result = kAudio_ParamError;
goto finishSetProperty;
}
}
}
}
COMPONENT_CATCH
finishSetProperty:
return result;
}
static OSStatus AUMethodAddPropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->AddPropertyListener(prop, proc, userData);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodRemovePropertyListener(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->RemovePropertyListener(prop, proc, NULL, false);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodRemovePropertyListenerWithUserData(void *self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void *userData)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->RemovePropertyListener(prop, proc, userData, true);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodAddRenderNotify(void *self, AURenderCallback proc, void *userData)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->SetRenderNotification(proc, userData);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodRemoveRenderNotify(void *self, AURenderCallback proc, void *userData)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->RemoveRenderNotification(proc, userData);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodGetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue *value)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = (value == NULL ? kAudio_ParamError : AUI->GetParameter(param, scope, elem, *value));
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodSetParameter(void *self, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
{
OSStatus result = noErr;
try {
// this is a (potentially) realtime method; no lock
result = AUI->SetParameter(param, scope, elem, value, bufferOffset);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodScheduleParameters(void *self, const AudioUnitParameterEvent *events, UInt32 numEvents)
{
OSStatus result = noErr;
try {
// this is a (potentially) realtime method; no lock
result = AUI->ScheduleParameter(events, numEvents);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
OSStatus result = noErr;
#if !TARGET_OS_IPHONE
try {
#endif
// this is a processing method; no lock
AudioUnitRenderActionFlags tempFlags;
if (inTimeStamp == NULL || ioData == NULL)
result = kAudio_ParamError;
else {
if (ioActionFlags == NULL) {
tempFlags = 0;
ioActionFlags = &tempFlags;
}
result = AUI->DoRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
}
#if !TARGET_OS_IPHONE
}
COMPONENT_CATCH
#endif
return result;
}
static OSStatus AUMethodComplexRender(void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets, UInt32 *outNumberOfPackets, AudioStreamPacketDescription *outPacketDescriptions, AudioBufferList *ioData, void *outMetadata, UInt32 *outMetadataByteSize)
{
OSStatus result = noErr;
#if !TARGET_OS_IPHONE
try {
#endif
// this is a processing method; no lock
AudioUnitRenderActionFlags tempFlags;
if (inTimeStamp == NULL || ioData == NULL)
result = kAudio_ParamError;
else {
if (ioActionFlags == NULL) {
tempFlags = 0;
ioActionFlags = &tempFlags;
}
result = AUI->ComplexRender(*ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions, *ioData, outMetadata, outMetadataByteSize);
}
#if !TARGET_OS_IPHONE
}
COMPONENT_CATCH
#endif
return result;
}
static OSStatus AUMethodReset(void *self, AudioUnitScope scope, AudioUnitElement elem)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->Reset(scope, elem);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodProcess (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, AudioBufferList *ioData)
{
OSStatus result = noErr;
#if !TARGET_OS_IPHONE
try {
#endif
// this is a processing method; no lock
bool doParamCheck = true;
AudioUnitRenderActionFlags tempFlags;
if (ioActionFlags == NULL) {
tempFlags = 0;
ioActionFlags = &tempFlags;
} else {
if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
doParamCheck = false;
}
if (doParamCheck && (inTimeStamp == NULL || ioData == NULL))
result = kAudio_ParamError;
else {
result = AUI->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
}
#if !TARGET_OS_IPHONE
}
COMPONENT_CATCH
#endif
return result;
}
static OSStatus AUMethodProcessMultiple (void *self, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists, const AudioBufferList **inInputBufferLists, UInt32 inNumberOutputBufferLists, AudioBufferList **ioOutputBufferLists)
{
OSStatus result = noErr;
#if !TARGET_OS_IPHONE
try {
#endif
// this is a processing method; no lock
bool doParamCheck = true;
AudioUnitRenderActionFlags tempFlags;
if (ioActionFlags == NULL) {
tempFlags = 0;
ioActionFlags = &tempFlags;
} else {
if (*ioActionFlags & (1 << 9)/*kAudioUnitRenderAction_DoNotCheckRenderArgs*/)
doParamCheck = false;
}
if (doParamCheck && (inTimeStamp == NULL || inInputBufferLists == NULL || ioOutputBufferLists == NULL))
result = kAudio_ParamError;
else {
result = AUI->DoProcessMultiple(*ioActionFlags, *inTimeStamp, inNumberFrames, inNumberInputBufferLists, inInputBufferLists, inNumberOutputBufferLists, ioOutputBufferLists);
}
#if !TARGET_OS_IPHONE
}
COMPONENT_CATCH
#endif
return result;
}
// ------------------------------------------------------------------------------------------------
static OSStatus AUMethodStart(void *self)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->Start();
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodStop(void *self)
{
OSStatus result = noErr;
try {
AUI_LOCK
result = AUI->Stop();
}
COMPONENT_CATCH
return result;
}
// ------------------------------------------------------------------------------------------------
#if !CA_BASIC_AU_FEATURES
// I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
static OSStatus AUMethodMIDIEvent(void *self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUI->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodSysEx(void *self, const UInt8 *inData, UInt32 inLength)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUI->SysEx(inData, inLength);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodStartNote(void *self, MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
if (inParams == NULL || outNoteInstanceID == NULL)
result = kAudio_ParamError;
else
result = AUI->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodStopNote(void *self, MusicDeviceGroupID inGroupID, NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUI->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}
#if !TARGET_OS_IPHONE
static OSStatus AUMethodPrepareInstrument (void *self, MusicDeviceInstrumentID inInstrument)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUI->PrepareInstrument(inInstrument);
}
COMPONENT_CATCH
return result;
}
static OSStatus AUMethodReleaseInstrument (void *self, MusicDeviceInstrumentID inInstrument)
{
OSStatus result = noErr;
try {
// this is a potential render-time method; no lock
result = AUI->ReleaseInstrument(inInstrument);
}
COMPONENT_CATCH
return result;
}
#endif // TARGET_OS_IPHONE
#endif // CA_BASIC_AU_FEATURES
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#pragma mark -
#pragma mark Lookup Methods
AudioComponentMethod AUBaseLookup::Lookup (SInt16 selector)
{
switch (selector) {
case kAudioUnitInitializeSelect: return (AudioComponentMethod)AUMethodInitialize;
case kAudioUnitUninitializeSelect: return (AudioComponentMethod)AUMethodUninitialize;
case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
case kAudioUnitAddPropertyListenerSelect:return (AudioComponentMethod)AUMethodAddPropertyListener;
case kAudioUnitRemovePropertyListenerSelect:
return (AudioComponentMethod)AUMethodRemovePropertyListener;
case kAudioUnitRemovePropertyListenerWithUserDataSelect:
return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData;
case kAudioUnitAddRenderNotifySelect: return (AudioComponentMethod)AUMethodAddRenderNotify;
case kAudioUnitRemoveRenderNotifySelect:return (AudioComponentMethod)AUMethodRemoveRenderNotify;
case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
case kAudioUnitScheduleParametersSelect:return (AudioComponentMethod)AUMethodScheduleParameters;
case kAudioUnitRenderSelect: return (AudioComponentMethod)AUMethodRender;
case kAudioUnitResetSelect: return (AudioComponentMethod)AUMethodReset;
default:
break;
}
return NULL;
}
AudioComponentMethod AUOutputLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
switch (selector) {
case kAudioOutputUnitStartSelect: return (AudioComponentMethod)AUMethodStart;
case kAudioOutputUnitStopSelect: return (AudioComponentMethod)AUMethodStop;
default:
break;
}
return NULL;
}
AudioComponentMethod AUComplexOutputLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
method = AUOutputLookup::Lookup(selector);
if (method) return method;
if (selector == kAudioUnitComplexRenderSelect)
return (AudioComponentMethod)AUMethodComplexRender;
return NULL;
}
AudioComponentMethod AUBaseProcessLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
if (selector == kAudioUnitProcessSelect)
return (AudioComponentMethod)AUMethodProcess;
return NULL;
}
AudioComponentMethod AUBaseProcessMultipleLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
if (selector == kAudioUnitProcessMultipleSelect)
return (AudioComponentMethod)AUMethodProcessMultiple;
return NULL;
}
AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
method = AUBaseProcessMultipleLookup::Lookup(selector);
if (method) return method;
method = AUBaseProcessLookup::Lookup(selector);
if (method) return method;
return NULL;
}
#if !CA_BASIC_AU_FEATURES
inline AudioComponentMethod MIDI_Lookup (SInt16 selector)
{
switch (selector) {
case kMusicDeviceMIDIEventSelect: return (AudioComponentMethod)AUMethodMIDIEvent;
case kMusicDeviceSysExSelect: return (AudioComponentMethod)AUMethodSysEx;
default:
break;
}
return NULL;
}
AudioComponentMethod AUMIDILookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
return MIDI_Lookup(selector);
}
AudioComponentMethod AUMIDIProcessLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
if (method) return method;
return MIDI_Lookup(selector);
}
AudioComponentMethod AUMusicLookup::Lookup (SInt16 selector)
{
AudioComponentMethod method = AUBaseLookup::Lookup(selector);
if (method) return method;
switch (selector) {
case kMusicDeviceStartNoteSelect: return (AudioComponentMethod)AUMethodStartNote;
case kMusicDeviceStopNoteSelect: return (AudioComponentMethod)AUMethodStopNote;
#if !TARGET_OS_IPHONE
case kMusicDevicePrepareInstrumentSelect: return (AudioComponentMethod)AUMethodPrepareInstrument;
case kMusicDeviceReleaseInstrumentSelect: return (AudioComponentMethod)AUMethodReleaseInstrument;
#endif
default:
break;
}
return MIDI_Lookup (selector);
}
AudioComponentMethod AUAuxBaseLookup::Lookup (SInt16 selector)
{
switch (selector) {
case kAudioUnitGetPropertyInfoSelect: return (AudioComponentMethod)AUMethodGetPropertyInfo;
case kAudioUnitGetPropertySelect: return (AudioComponentMethod)AUMethodGetProperty;
case kAudioUnitSetPropertySelect: return (AudioComponentMethod)AUMethodSetProperty;
case kAudioUnitGetParameterSelect: return (AudioComponentMethod)AUMethodGetParameter;
case kAudioUnitSetParameterSelect: return (AudioComponentMethod)AUMethodSetParameter;
default:
break;
}
return NULL;
}
#endif

+ 0
- 144
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUPlugInDispatch.h View File

@@ -1,144 +0,0 @@
/*
File: AUPlugInDispatch.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUPlugInBase_h__
#define __AUPlugInBase_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioComponent.h>
#if !CA_BASIC_AU_FEATURES
#include <AudioUnit/MusicDevice.h>
#endif
#else
#include "AudioComponent.h"
#include "MusicDevice.h"
#endif
#include "ComponentBase.h"
struct AUBaseLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUBaseFactory : public APFactory<AUBaseLookup, Implementor>
{
};
struct AUOutputLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUOutputBaseFactory : public APFactory<AUOutputLookup, Implementor>
{
};
struct AUComplexOutputLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUOutputComplexBaseFactory : public APFactory<AUComplexOutputLookup, Implementor>
{
};
struct AUBaseProcessLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUBaseProcessFactory : public APFactory<AUBaseProcessLookup, Implementor>
{
};
struct AUBaseProcessMultipleLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUBaseProcessMultipleFactory : public APFactory<AUBaseProcessMultipleLookup, Implementor>
{
};
struct AUBaseProcessAndMultipleLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUBaseProcessAndMultipleFactory : public APFactory<AUBaseProcessAndMultipleLookup, Implementor>
{
};
#if !CA_BASIC_AU_FEATURES
struct AUMIDILookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUMIDIEffectFactory : public APFactory<AUMIDILookup, Implementor>
{
};
struct AUMIDIProcessLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUMIDIProcessFactory : public APFactory<AUMIDIProcessLookup, Implementor>
{
};
struct AUMusicLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUMusicDeviceFactory : public APFactory<AUMusicLookup, Implementor>
{
};
struct AUAuxBaseLookup {
static AudioComponentMethod Lookup (SInt16 selector);
};
template <class Implementor>
class AUAuxBaseFactory : public APFactory<AUAuxBaseLookup, Implementor>
{
};
#endif // CA_BASIC_AU_FEATURES
#endif // __AUPlugInBase_h__

+ 0
- 566
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.cpp View File

@@ -1,566 +0,0 @@
/*
File: AUScopeElement.cpp
Abstract: AUScopeElement.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "AUScopeElement.h"
#include "AUBase.h"
//_____________________________________________________________________________
//
// By default, parameterIDs may be arbitrarily spaced, and an STL map
// will be used for access. Calling UseIndexedParameters() will
// instead use an STL vector for faster indexed access.
// This assumes the paramIDs are numbered 0.....inNumberOfParameters-1
// Call this before defining/adding any parameters with SetParameter()
//
void AUElement::UseIndexedParameters(int inNumberOfParameters)
{
mIndexedParameters.resize (inNumberOfParameters);
mUseIndexedParameters = true;
}
//_____________________________________________________________________________
//
// Helper method.
// returns the ParameterMapEvent object associated with the paramID
//
inline ParameterMapEvent& AUElement::GetParamEvent(AudioUnitParameterID paramID)
{
ParameterMapEvent *event;
if(mUseIndexedParameters)
{
if(paramID >= mIndexedParameters.size() )
COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
event = &mIndexedParameters[paramID];
}
else
{
ParameterMap::iterator i = mParameters.find(paramID);
if (i == mParameters.end())
COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
event = &(*i).second;
}
return *event;
}
//_____________________________________________________________________________
//
// Helper method.
// returns whether the specified paramID is known to the element
//
bool AUElement::HasParameterID (AudioUnitParameterID paramID) const
{
if(mUseIndexedParameters)
{
if(paramID >= mIndexedParameters.size() )
return false;
return true;
}
ParameterMap::const_iterator i = mParameters.find(paramID);
if (i == mParameters.end())
return false;
return true;
}
//_____________________________________________________________________________
//
// caller assumes that this is actually an immediate parameter
//
AudioUnitParameterValue AUElement::GetParameter(AudioUnitParameterID paramID)
{
ParameterMapEvent &event = GetParamEvent(paramID);
return event.GetValue();
}
//_____________________________________________________________________________
//
void AUElement::GetRampSliceStartEnd( AudioUnitParameterID paramID,
AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue,
AudioUnitParameterValue & outValuePerFrameDelta )
{
ParameterMapEvent &event = GetParamEvent(paramID);
// works even if the value is constant (immediate parameter value)
event.GetRampSliceStartEnd(outStartValue, outEndValue, outValuePerFrameDelta );
}
//_____________________________________________________________________________
//
AudioUnitParameterValue AUElement::GetEndValue( AudioUnitParameterID paramID)
{
ParameterMapEvent &event = GetParamEvent(paramID);
// works even if the value is constant (immediate parameter value)
return event.GetEndValue();
}
//_____________________________________________________________________________
//
void AUElement::SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue inValue, bool okWhenInitialized)
{
if(mUseIndexedParameters)
{
ParameterMapEvent &event = GetParamEvent(paramID);
event.SetValue(inValue);
}
else
{
ParameterMap::iterator i = mParameters.find(paramID);
if (i == mParameters.end())
{
if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
// 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.
// COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
#if DEBUG
fprintf(stderr, "WARNING: %s SetParameter for undefined param ID %d while initialized. Ignoring..\n",
mAudioUnit->GetLoggingString(), (int)paramID);
#endif
} else {
// create new entry in map for the paramID (only happens first time)
ParameterMapEvent event(inValue);
mParameters[paramID] = event;
}
}
else
{
// paramID already exists in map so simply change its value
ParameterMapEvent &event = (*i).second;
event.SetValue(inValue);
}
}
}
//_____________________________________________________________________________
//
void AUElement::SetScheduledEvent( AudioUnitParameterID paramID,
const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames,
bool okWhenInitialized )
{
if(mUseIndexedParameters)
{
ParameterMapEvent &event = GetParamEvent(paramID);
event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
}
else
{
ParameterMap::iterator i = mParameters.find(paramID);
if (i == mParameters.end())
{
if (mAudioUnit->IsInitialized() && !okWhenInitialized) {
// 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.
// COMPONENT_THROW(kAudioUnitErr_InvalidParameter);
#if DEBUG
fprintf(stderr, "WARNING: %s SetScheduledEvent for undefined param ID %d while initialized. Ignoring..\n",
mAudioUnit->GetLoggingString(), (int)paramID);
#endif
} else {
// create new entry in map for the paramID (only happens first time)
ParameterMapEvent event(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames);
mParameters[paramID] = event;
}
}
else
{
// paramID already exists in map so simply change its value
ParameterMapEvent &event = (*i).second;
event.SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
}
}
}
//_____________________________________________________________________________
//
void AUElement::GetParameterList(AudioUnitParameterID *outList)
{
if(mUseIndexedParameters)
{
UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
for (UInt32 i = 0; i < nparams; i++ )
*outList++ = (AudioUnitParameterID)i;
}
else
{
for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i)
*outList++ = (*i).first;
}
}
//_____________________________________________________________________________
//
void AUElement::SaveState(CFMutableDataRef data)
{
if(mUseIndexedParameters)
{
UInt32 nparams = static_cast<UInt32>(mIndexedParameters.size());
UInt32 theData = CFSwapInt32HostToBig(nparams);
CFDataAppendBytes(data, (UInt8 *)&theData, sizeof(nparams));
for (UInt32 i = 0; i < nparams; i++)
{
struct {
UInt32 paramID;
//CFSwappedFloat32 value; crashes gcc3 PFE
UInt32 value; // really a big-endian float
} entry;
entry.paramID = CFSwapInt32HostToBig(i);
AudioUnitParameterValue v = mIndexedParameters[i].GetValue();
entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
}
}
else
{
UInt32 nparams = CFSwapInt32HostToBig(static_cast<uint32_t>(mParameters.size()));
CFDataAppendBytes(data, (UInt8 *)&nparams, sizeof(nparams));
for (ParameterMap::iterator i = mParameters.begin(); i != mParameters.end(); ++i) {
struct {
UInt32 paramID;
//CFSwappedFloat32 value; crashes gcc3 PFE
UInt32 value; // really a big-endian float
} entry;
entry.paramID = CFSwapInt32HostToBig((*i).first);
AudioUnitParameterValue v = (*i).second.GetValue();
entry.value = CFSwapInt32HostToBig(*(UInt32 *)&v );
CFDataAppendBytes(data, (UInt8 *)&entry, sizeof(entry));
}
}
}
//_____________________________________________________________________________
//
const UInt8 * AUElement::RestoreState(const UInt8 *state)
{
union FloatInt32 { UInt32 i; AudioUnitParameterValue f; };
const UInt8 *p = state;
UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
p += sizeof(UInt32);
for (UInt32 i = 0; i < nparams; ++i) {
struct {
AudioUnitParameterID paramID;
AudioUnitParameterValue value;
} entry;
entry.paramID = CFSwapInt32BigToHost(*(UInt32 *)p);
p += sizeof(UInt32);
FloatInt32 temp;
temp.i = CFSwapInt32BigToHost(*(UInt32 *)p);
entry.value = temp.f;
p += sizeof(AudioUnitParameterValue);
SetParameter(entry.paramID, entry.value);
}
return p;
}
//_____________________________________________________________________________
//
void AUElement::SetName (CFStringRef inName)
{
if (mElementName) CFRelease (mElementName);
mElementName = inName;
if (mElementName) CFRetain (mElementName);
}
//_____________________________________________________________________________
//
AUIOElement::AUIOElement(AUBase *audioUnit) :
AUElement(audioUnit),
mWillAllocate (true)
{
mStreamFormat.SetAUCanonical(2, // stereo
audioUnit->AudioUnitAPIVersion() == 1);
// interleaved if API version 1, deinterleaved if version 2
mStreamFormat.mSampleRate = kAUDefaultSampleRate;
}
//_____________________________________________________________________________
//
OSStatus AUIOElement::SetStreamFormat(const CAStreamBasicDescription &desc)
{
mStreamFormat = desc;
return AUBase::noErr;
}
//_____________________________________________________________________________
// inFramesToAllocate == 0 implies the AudioUnit's max-frames-per-slice will be used
void AUIOElement::AllocateBuffer(UInt32 inFramesToAllocate)
{
if (GetAudioUnit()->HasBegunInitializing())
{
UInt32 framesToAllocate = inFramesToAllocate > 0 ? inFramesToAllocate : GetAudioUnit()->GetMaxFramesPerSlice();
// printf ("will allocate: %d\n", (int)((mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0));
mIOBuffer.Allocate(mStreamFormat, (mWillAllocate && NeedsBufferSpace()) ? framesToAllocate : 0);
}
}
//_____________________________________________________________________________
//
void AUIOElement::DeallocateBuffer()
{
mIOBuffer.Deallocate();
}
//_____________________________________________________________________________
//
// AudioChannelLayout support
// outLayoutTagsPtr WILL be NULL if called to find out how many
// layouts that Audio Unit will report
// return 0 (ie. NO channel layouts) if the AU doesn't require channel layout knowledge
UInt32 AUIOElement::GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr)
{
return 0;
}
// As the AudioChannelLayout can be a variable length structure
// (though in most cases it won't be!!!)
// The size of the ACL is always returned by the method
// if outMapPtr is NOT-NULL, then AU should copy into this pointer (outMapPtr) the current ACL that it has in use.
// the AU should also return whether the property is writable (that is the client can provide any arbitrary ACL that the audio unit will then honour)
// or if the property is read only - which is the generally preferred mode.
// If the AU doesn't require an AudioChannelLayout, then just return 0.
UInt32 AUIOElement::GetAudioChannelLayout (AudioChannelLayout *outMapPtr,
Boolean &outWritable)
{
return 0;
}
// the incoming channel map will be at least as big as a basic AudioChannelLayout
// but its contents will determine its actual size
// Subclass should overide if channel map is writable
OSStatus AUIOElement::SetAudioChannelLayout (const AudioChannelLayout &inData)
{
return kAudioUnitErr_InvalidProperty;
}
// Some units support optional usage of channel maps - typically converter units
// that can do channel remapping between different maps. In that optional case
// the user should be able to remove a channel map if that is possible.
// Typically this is NOT the case (e.g., the 3DMixer even in the stereo case
// needs to know if it is rendering to speakers or headphones)
OSStatus AUIOElement::RemoveAudioChannelLayout ()
{
return kAudioUnitErr_InvalidPropertyValue;
}
//_____________________________________________________________________________
//
AUScope::~AUScope()
{
for (ElementVector::iterator it = mElements.begin(); it != mElements.end(); ++it)
delete *it;
}
//_____________________________________________________________________________
//
void AUScope::SetNumberOfElements(UInt32 numElements)
{
if (mDelegate)
return mDelegate->SetNumberOfElements(numElements);
if (numElements > mElements.size()) {
mElements.reserve(numElements);
while (numElements > mElements.size()) {
AUElement *elem = mCreator->CreateElement(GetScope(), static_cast<UInt32>(mElements.size()));
mElements.push_back(elem);
}
} else
while (numElements < mElements.size()) {
AUElement *elem = mElements.back();
mElements.pop_back();
delete elem;
}
}
//_____________________________________________________________________________
//
bool AUScope::HasElementWithName () const
{
for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
AUElement * el = const_cast<AUScope*>(this)->GetElement (i);
if (el && el->HasName()) {
return true;
}
}
return false;
}
//_____________________________________________________________________________
//
void AUScope::AddElementNamesToDict (CFMutableDictionaryRef & inNameDict)
{
if (HasElementWithName())
{
static char string[32];
CFMutableDictionaryRef elementDict = CFDictionaryCreateMutable (NULL, 0,
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFStringRef str;
for (UInt32 i = 0; i < GetNumberOfElements(); ++i) {
AUElement * el = GetElement (i);
if (el && el->HasName()) {
snprintf (string, sizeof(string), "%d", int(i));
str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
CFDictionarySetValue (elementDict, str, el->GetName());
CFRelease (str);
}
}
snprintf (string, sizeof(string), "%d", int(mScope));
str = CFStringCreateWithCString (NULL, string, kCFStringEncodingASCII);
CFDictionarySetValue (inNameDict, str, elementDict);
CFRelease (str);
CFRelease (elementDict);
}
}
//_____________________________________________________________________________
//
bool AUScope::RestoreElementNames (CFDictionaryRef& inNameDict)
{
static char string[32];
//first we have to see if we have enough elements
bool didAddElements = false;
unsigned int maxElNum = GetNumberOfElements();
int dictSize = static_cast<int>(CFDictionaryGetCount(inNameDict));
CFStringRef * keys = (CFStringRef*)CA_malloc (dictSize * sizeof (CFStringRef));
CFDictionaryGetKeysAndValues (inNameDict, reinterpret_cast<const void**>(keys), NULL);
for (int i = 0; i < dictSize; i++)
{
unsigned int intKey = 0;
CFStringGetCString (keys[i], string, 32, kCFStringEncodingASCII);
int result = sscanf (string, "%u", &intKey);
// check if sscanf succeeded and element index is less than max elements.
if (result && UInt32(intKey) < maxElNum)
{
CFStringRef elName = reinterpret_cast<CFStringRef>(CFDictionaryGetValue (inNameDict, keys[i]));
AUElement* element = GetElement (intKey);
if (element)
element->SetName (elName);
}
}
free (keys);
return didAddElements;
}
void AUScope::SaveState(CFMutableDataRef data)
{
AudioUnitElement nElems = GetNumberOfElements();
for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
AUElement *element = GetElement(ielem);
UInt32 nparams = element->GetNumberOfParameters();
if (nparams > 0) {
struct {
UInt32 scope;
UInt32 element;
} hdr;
hdr.scope = CFSwapInt32HostToBig(GetScope());
hdr.element = CFSwapInt32HostToBig(ielem);
CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
element->SaveState(data);
}
}
}
const UInt8 * AUScope::RestoreState(const UInt8 *state)
{
const UInt8 *p = state;
UInt32 elementIdx = CFSwapInt32BigToHost(*(UInt32 *)p); p += sizeof(UInt32);
AUElement *element = GetElement(elementIdx);
if (!element) {
struct {
AudioUnitParameterID paramID;
AudioUnitParameterValue value;
} entry;
UInt32 nparams = CFSwapInt32BigToHost(*(UInt32 *)p);
p += sizeof(UInt32);
p += nparams * sizeof(entry);
} else
p = element->RestoreState(p);
return p;
}

+ 0
- 553
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUScopeElement.h View File

@@ -1,553 +0,0 @@
/*
File: AUScopeElement.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUScopeElement_h__
#define __AUScopeElement_h__
#include <map>
#include <vector>
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <AudioUnit/AudioUnit.h>
#else
#include <AudioUnit.h>
#endif
#include "ComponentBase.h"
#include "AUBuffer.h"
class AUBase;
// ____________________________________________________________________________
//
// represents a parameter's value (either constant or ramped)
/*! @class ParameterMapEvent */
class ParameterMapEvent
{
public:
/*! @ctor ParameterMapEvent */
ParameterMapEvent()
: mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(0.0f), mValue2(0.0f), mSliceDurationFrames(0)
{}
/*! @ctor ParameterMapEvent */
ParameterMapEvent(AudioUnitParameterValue inValue)
: mEventType(kParameterEvent_Immediate), mBufferOffset(0), mDurationInFrames(0), mValue1(inValue), mValue2(inValue), mSliceDurationFrames(0)
{}
// constructor for scheduled event
/*! @ctor ParameterMapEvent */
ParameterMapEvent( const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames )
{
SetScheduledEvent(inEvent, inSliceOffsetInBuffer, inSliceDurationFrames );
};
/*! @method SetScheduledEvent */
void SetScheduledEvent( const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames )
{
mEventType = inEvent.eventType;
mSliceDurationFrames = inSliceDurationFrames;
if(mEventType == kParameterEvent_Immediate )
{
// constant immediate value for the whole slice
mValue1 = inEvent.eventValues.immediate.value;
mValue2 = mValue1;
mDurationInFrames = inSliceDurationFrames;
mBufferOffset = 0;
}
else
{
mDurationInFrames = inEvent.eventValues.ramp.durationInFrames;
mBufferOffset = inEvent.eventValues.ramp.startBufferOffset - inSliceOffsetInBuffer; // shift over for this slice
mValue1 = inEvent.eventValues.ramp.startValue;
mValue2 = inEvent.eventValues.ramp.endValue;
}
};
/*! @method GetEventType */
AUParameterEventType GetEventType() const {return mEventType;};
/*! @method GetValue */
AudioUnitParameterValue GetValue() const {return mValue1;}; // only valid if immediate event type
/*! @method GetEndValue */
AudioUnitParameterValue GetEndValue() const {return mValue2;}; // only valid if immediate event type
/*! @method SetValue */
void SetValue(AudioUnitParameterValue inValue)
{
mEventType = kParameterEvent_Immediate;
mValue1 = inValue;
mValue2 = inValue;
}
// interpolates the start and end values corresponding to the current processing slice
// most ramp parameter implementations will want to use this method
// the start value will correspond to the start of the slice
// the end value will correspond to the end of the slice
/*! @method GetRampSliceStartEnd */
void GetRampSliceStartEnd( AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue,
AudioUnitParameterValue & outValuePerFrameDelta )
{
if (mEventType == kParameterEvent_Ramped) {
outValuePerFrameDelta = (mValue2 - mValue1) / mDurationInFrames;
outStartValue = mValue1 + outValuePerFrameDelta * (-mBufferOffset); // corresponds to frame 0 of this slice
outEndValue = outStartValue + outValuePerFrameDelta * mSliceDurationFrames;
} else {
outValuePerFrameDelta = 0;
outStartValue = outEndValue = mValue1;
}
};
// Some ramp parameter implementations will want to interpret the ramp using their
// own interpolation method (perhaps non-linear)
// This method gives the raw ramp information, relative to this processing slice
// for the client to interpret as desired
/*! @method GetRampInfo */
void GetRampInfo( SInt32 & outBufferOffset,
UInt32 & outDurationInFrames,
AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue )
{
outBufferOffset = mBufferOffset;
outDurationInFrames = mDurationInFrames;
outStartValue = mValue1;
outEndValue = mValue2;
};
#if DEBUG
void Print()
{
printf("ParameterEvent @ %p\n", this);
printf(" mEventType = %d\n", (int)mEventType);
printf(" mBufferOffset = %d\n", (int)mBufferOffset);
printf(" mDurationInFrames = %d\n", (int)mDurationInFrames);
printf(" mSliceDurationFrames = %d\n", (int)mSliceDurationFrames);
printf(" mValue1 = %.5f\n", mValue1);
printf(" mValue2 = %.5f\n", mValue2);
}
#endif
private:
AUParameterEventType mEventType;
SInt32 mBufferOffset; // ramp start offset relative to start of this slice (may be negative)
UInt32 mDurationInFrames; // total duration of ramp parameter
AudioUnitParameterValue mValue1; // value if immediate : startValue if ramp
AudioUnitParameterValue mValue2; // endValue (only used for ramp)
UInt32 mSliceDurationFrames; // duration of this processing slice
};
// ____________________________________________________________________________
//
class AUIOElement;
/*! @class AUElement */
class AUElement {
public:
/*! @ctor AUElement */
AUElement(AUBase *audioUnit) : mAudioUnit(audioUnit),
mUseIndexedParameters(false), mElementName(0) { }
/*! @dtor ~AUElement */
virtual ~AUElement() { if (mElementName) CFRelease (mElementName); }
/*! @method GetNumberOfParameters */
virtual UInt32 GetNumberOfParameters()
{
if(mUseIndexedParameters) return static_cast<UInt32>(mIndexedParameters.size()); else return static_cast<UInt32>(mParameters.size());
}
/*! @method GetParameterList */
virtual void GetParameterList(AudioUnitParameterID *outList);
/*! @method HasParameterID */
bool HasParameterID (AudioUnitParameterID paramID) const;
/*! @method GetParameter */
AudioUnitParameterValue GetParameter(AudioUnitParameterID paramID);
/*! @method SetParameter */
void SetParameter(AudioUnitParameterID paramID, AudioUnitParameterValue value, bool okWhenInitialized = false);
// Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
// interpolates the start and end values corresponding to the current processing slice
// most ramp parameter implementations will want to use this method
/*! @method GetRampSliceStartEnd */
void GetRampSliceStartEnd( AudioUnitParameterID paramID,
AudioUnitParameterValue & outStartValue,
AudioUnitParameterValue & outEndValue,
AudioUnitParameterValue & outValuePerFrameDelta );
/*! @method GetEndValue */
AudioUnitParameterValue GetEndValue( AudioUnitParameterID paramID);
/*! @method SetRampParameter */
void SetScheduledEvent( AudioUnitParameterID paramID,
const AudioUnitParameterEvent &inEvent,
UInt32 inSliceOffsetInBuffer,
UInt32 inSliceDurationFrames,
bool okWhenInitialized = false );
// Only set okWhenInitialized to true when you know the outside world cannot access this element. Otherwise the parameter map could get corrupted.
/*! @method GetAudioUnit */
AUBase * GetAudioUnit() const { return mAudioUnit; };
/*! @method SaveState */
void SaveState(CFMutableDataRef data);
/*! @method RestoreState */
const UInt8 * RestoreState(const UInt8 *state);
/*! @method GetName */
CFStringRef GetName () const { return mElementName; }
/*! @method SetName */
void SetName (CFStringRef inName);
/*! @method HasName */
bool HasName () const { return mElementName != 0; }
/*! @method UseIndexedParameters */
virtual void UseIndexedParameters(int inNumberOfParameters);
/*! @method AsIOElement*/
virtual AUIOElement* AsIOElement () { return NULL; }
protected:
inline ParameterMapEvent& GetParamEvent(AudioUnitParameterID paramID);
private:
typedef std::map<AudioUnitParameterID, ParameterMapEvent, std::less<AudioUnitParameterID>> ParameterMap;
/*! @var mAudioUnit */
AUBase * mAudioUnit;
/*! @var mParameters */
ParameterMap mParameters;
/*! @var mUseIndexedParameters */
bool mUseIndexedParameters;
/*! @var mIndexedParameters */
std::vector<ParameterMapEvent> mIndexedParameters;
/*! @var mElementName */
CFStringRef mElementName;
};
// ____________________________________________________________________________
//
/*! @class AUIOElement */
class AUIOElement : public AUElement {
public:
/*! @ctor AUIOElement */
AUIOElement(AUBase *audioUnit);
/*! @method GetStreamFormat */
const CAStreamBasicDescription &GetStreamFormat() const { return mStreamFormat; }
/*! @method SetStreamFormat */
virtual OSStatus SetStreamFormat(const CAStreamBasicDescription &desc);
/*! @method AllocateBuffer */
virtual void AllocateBuffer(UInt32 inFramesToAllocate = 0);
/*! @method DeallocateBuffer */
void DeallocateBuffer();
/*! @method NeedsBufferSpace */
virtual bool NeedsBufferSpace() const = 0;
/*! @method SetWillAllocateBuffer */
void SetWillAllocateBuffer(bool inFlag) {
mWillAllocate = inFlag;
}
/*! @method WillAllocateBuffer */
bool WillAllocateBuffer() const {
return mWillAllocate;
}
/*! @method UseExternalBuffer */
void UseExternalBuffer(const AudioUnitExternalBuffer &buf) {
mIOBuffer.UseExternalBuffer(mStreamFormat, buf);
}
/*! @method PrepareBuffer */
AudioBufferList & PrepareBuffer(UInt32 nFrames) {
if (mWillAllocate)
return mIOBuffer.PrepareBuffer(mStreamFormat, nFrames);
throw OSStatus(kAudioUnitErr_InvalidPropertyValue);
}
/*! @method PrepareNullBuffer */
AudioBufferList & PrepareNullBuffer(UInt32 nFrames) {
return mIOBuffer.PrepareNullBuffer(mStreamFormat, nFrames);
}
/*! @method SetBufferList */
AudioBufferList & SetBufferList(AudioBufferList &abl) { return mIOBuffer.SetBufferList(abl); }
/*! @method SetBuffer */
void SetBuffer(UInt32 index, AudioBuffer &ab) { mIOBuffer.SetBuffer(index, ab); }
/*! @method InvalidateBufferList */
void InvalidateBufferList() { mIOBuffer.InvalidateBufferList(); }
/*! @method GetBufferList */
AudioBufferList & GetBufferList() const { return mIOBuffer.GetBufferList(); }
/*! @method GetChannelData */
AudioUnitSampleType * GetChannelData(int ch) const {
if (mStreamFormat.IsInterleaved())
return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
else
return static_cast<AudioUnitSampleType *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
}
Float32 * GetFloat32ChannelData(int ch) const {
if (mStreamFormat.IsInterleaved())
return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
else
return static_cast<Float32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
}
SInt32 * GetSInt32ChannelData(int ch) const {
if (mStreamFormat.IsInterleaved())
return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
else
return static_cast<SInt32 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
}
SInt16 * GetInt16ChannelData(int ch) const {
if (mStreamFormat.IsInterleaved())
return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[0].mData) + ch;
else
return static_cast<SInt16 *>(mIOBuffer.GetBufferList().mBuffers[ch].mData);
}
/*! @method CopyBufferListTo */
void CopyBufferListTo(AudioBufferList &abl) const {
mIOBuffer.CopyBufferListTo(abl);
}
/*! @method CopyBufferContentsTo */
void CopyBufferContentsTo(AudioBufferList &abl) const {
mIOBuffer.CopyBufferContentsTo(abl);
}
/* UInt32 BytesToFrames(UInt32 nBytes) { return nBytes / mStreamFormat.mBytesPerFrame; }
UInt32 BytesToFrames(AudioBufferList &abl) {
return BytesToFrames(abl.mBuffers[0].mDataByteSize);
}
UInt32 FramesToBytes(UInt32 nFrames) { return nFrames * mStreamFormat.mBytesPerFrame; }*/
/*! @method IsInterleaved */
bool IsInterleaved() const { return mStreamFormat.IsInterleaved(); }
/*! @method NumberChannels */
UInt32 NumberChannels() const { return mStreamFormat.NumberChannels(); }
/*! @method NumberInterleavedChannels */
UInt32 NumberInterleavedChannels() const { return mStreamFormat.NumberInterleavedChannels(); }
/*! @method GetChannelMapTags */
virtual UInt32 GetChannelLayoutTags (AudioChannelLayoutTag *outLayoutTagsPtr);
/*! @method GetAudioChannelLayout */
virtual UInt32 GetAudioChannelLayout (AudioChannelLayout *outMapPtr, Boolean &outWritable);
/*! @method SetAudioChannelLayout */
virtual OSStatus SetAudioChannelLayout (const AudioChannelLayout &inData);
/*! @method RemoveAudioChannelLayout */
virtual OSStatus RemoveAudioChannelLayout ();
/*! @method AsIOElement*/
virtual AUIOElement* AsIOElement () { return this; }
protected:
/*! @var mStreamFormat */
CAStreamBasicDescription mStreamFormat;
/*! @var mIOBuffer */
AUBufferList mIOBuffer; // for input: input proc buffer, only allocated when needed
// for output: output cache, usually allocated early on
/*! @var mWillAllocate */
bool mWillAllocate;
};
// ____________________________________________________________________________
//
// AUScopeDelegates are a way to get virtual scopes.
/*! @class AUScopeDelegate */
class AUScopeDelegate {
public:
/*! @ctor AUScopeDelegate */
AUScopeDelegate() : mCreator(NULL), mScope(0) { }
/*! @dtor ~AUScopeDelegate */
virtual ~AUScopeDelegate() {}
/*! @method Initialize */
void Initialize( AUBase *creator,
AudioUnitScope scope,
UInt32 numElements)
{
mCreator = creator;
mScope = scope;
SetNumberOfElements(numElements);
}
/*! @method SetNumberOfElements */
virtual void SetNumberOfElements(UInt32 numElements) = 0;
/*! @method GetNumberOfElements */
virtual UInt32 GetNumberOfElements() = 0;
/*! @method GetElement */
virtual AUElement * GetElement(UInt32 elementIndex) = 0;
AUBase * GetCreator() const { return mCreator; }
AudioUnitScope GetScope() const { return mScope; }
private:
/*! @var mCreator */
AUBase * mCreator;
/*! @var mScope */
AudioUnitScope mScope;
};
// ____________________________________________________________________________
//
/*! @class AUScope */
class AUScope {
public:
/*! @ctor AUScope */
AUScope() : mCreator(NULL), mScope(0), mDelegate(0) { }
/*! @dtor ~AUScope */
~AUScope();
/*! @method Initialize */
void Initialize(AUBase *creator,
AudioUnitScope scope,
UInt32 numElements)
{
mCreator = creator;
mScope = scope;
if (mDelegate)
return mDelegate->Initialize(creator, scope, numElements);
SetNumberOfElements(numElements);
}
/*! @method SetNumberOfElements */
void SetNumberOfElements(UInt32 numElements);
/*! @method GetNumberOfElements */
UInt32 GetNumberOfElements() const
{
if (mDelegate)
return mDelegate->GetNumberOfElements();
return static_cast<UInt32>(mElements.size());
}
/*! @method GetElement */
AUElement * GetElement(UInt32 elementIndex) const
{
if (mDelegate)
return mDelegate->GetElement(elementIndex);
ElementVector::const_iterator i = mElements.begin() + elementIndex;
// catch passing -1 in as the elementIndex - causes a wrap around
return (i >= mElements.end() || i < mElements.begin()) ? NULL : *i;
}
/*! @method SafeGetElement */
AUElement * SafeGetElement(UInt32 elementIndex)
{
AUElement *element = GetElement(elementIndex);
if (element == NULL)
COMPONENT_THROW(kAudioUnitErr_InvalidElement);
return element;
}
/*! @method GetIOElement */
AUIOElement * GetIOElement(UInt32 elementIndex) const
{
AUElement *element = GetElement(elementIndex);
AUIOElement *ioel = element ? element->AsIOElement () : NULL;
if (!ioel)
COMPONENT_THROW (kAudioUnitErr_InvalidElement);
return ioel;
}
/*! @method HasElementWithName */
bool HasElementWithName () const;
/*! @method AddElementNamesToDict */
void AddElementNamesToDict (CFMutableDictionaryRef & inNameDict);
bool RestoreElementNames (CFDictionaryRef& inNameDict);
AudioUnitScope GetScope() const { return mScope; }
void SetDelegate(AUScopeDelegate* inDelegate) { mDelegate = inDelegate; }
/*! @method SaveState */
void SaveState(CFMutableDataRef data);
/*! @method RestoreState */
const UInt8 * RestoreState(const UInt8 *state);
private:
typedef std::vector<AUElement *> ElementVector;
/*! @var mCreator */
AUBase * mCreator;
/*! @var mScope */
AudioUnitScope mScope;
/*! @var mElements */
ElementVector mElements;
/*! @var mDelegate */
AUScopeDelegate * mDelegate;
};
#endif // __AUScopeElement_h__

+ 0
- 93
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUSilentTimeout.h View File

@@ -1,93 +0,0 @@
/*
File: AUSilentTimeout.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUSilentTimeout
#define __AUSilentTimeout
class AUSilentTimeout
{
public:
AUSilentTimeout()
: mTimeoutCounter(0),
mResetTimer(true)
{};
void Process(UInt32 inFramesToProcess, UInt32 inTimeoutLimit, bool &ioSilence )
{
if(ioSilence )
{
if(mResetTimer )
{
mTimeoutCounter = inTimeoutLimit;
mResetTimer = false;
}
if(mTimeoutCounter > 0 )
{
mTimeoutCounter -= inFramesToProcess;
ioSilence = false;
}
}
else
{
// signal to reset the next time we receive silence
mResetTimer = true;
}
}
void Reset()
{
mResetTimer = true;
};
private:
SInt32 mTimeoutCounter;
bool mResetTimer;
};
#endif // __AUSilentTimeout

+ 0
- 163
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUTimestampGenerator.h View File

@@ -1,163 +0,0 @@
/*
File: AUTimestampGenerator.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUTimestampGenerator_h__
#define __AUTimestampGenerator_h__
#include <math.h>
#include "CAHostTimeBase.h"
#include <stdio.h>
#define TSGFMT "0x%10qx"
//#define TSGFMT "%10qd"
// This class generates a continuously increasing series of timestamps based
// on a series of potentially discontinuous timestamps (as can be delivered from
// CoreAudio in the event of an overload or major engine change).
// N.B.: "output" = downstream (source) timestamp
// "input" = upstream (derived) timestamp
class AUTimestampGenerator {
public:
AUTimestampGenerator(bool hostTimeDiscontinuityCorrection = false)
{
mState.mStartInputAtZero = true;
mState.mBypassed = false;
mState.mHostTimeDiscontinuityCorrection = hostTimeDiscontinuityCorrection;
#if DEBUG
mVerbosity = 0;
snprintf(mDebugName, sizeof(mDebugName), "tsg @ %p", this);
#endif
// CAHostTimeBase should be used instead of the calls in <CoreAudio/HostTime.h>
// we make this call here to ensure that this is initialized, otherwise the first time
// you do actually call CAHostTimeBase to do work, can be on the render thread, and lead to unwanted VM faults
CAHostTimeBase::GetFrequency();
Reset();
}
void SetStartInputAtZero(bool b) { mState.mStartInputAtZero = b; }
bool GetStartInputAtZero() const { return mState.mStartInputAtZero; }
// bypassing is intended for a narrow special case. the upstream sample time will always be the same as the downstream time.
void SetBypassed(bool b) { mState.mBypassed = b; }
bool GetBypassed() const { return mState.mBypassed; }
// Call this to reset the timeline.
void Reset()
{
mState.mCurrentInputTime.mSampleTime = 0.;
mState.mNextInputSampleTime = 0.;
mState.mCurrentOutputTime.mSampleTime = 0.;
mState.mNextOutputSampleTime = 0.;
mState.mLastOutputTime.mFlags = 0;
mState.mRateScalarAdj = 1.;
mFirstTime = true;
#if DEBUG
if (mVerbosity)
printf("%-20.20s: Reset\n", mDebugName);
#endif
}
// Call this once per render cycle with the downstream timestamp.
// expectedDeltaFrames is the expected difference between the current and NEXT
// downstream timestamps.
// sampleRate is the OUTPUT sample rate.
void AddOutputTime(const AudioTimeStamp &inTimeStamp, Float64 expectedDeltaFrames, double outputSampleRate, double rateScalarAdj=1.0);
// Call this once per render cycle to obtain the upstream timestamp.
// framesToAdvance is the number of frames the input timeline is to be
// advanced during this render cycle.
// sampleRate is the INPUT sample rate.
const AudioTimeStamp & GenerateInputTime(Float64 framesToAdvance, double inputSampleRate, bool advanceHostTime = false);
// this can be called to override the setting of the next input sample time in GenerateInputTime
void Advance(Float64 framesToAdvance)
{
#if DEBUG
if (mVerbosity > 1)
printf("%-20.20s: ADVANCE in = " TSGFMT " advance = " TSGFMT "\n", mDebugName, (SInt64)mState.mCurrentInputTime.mSampleTime, (SInt64)framesToAdvance);
#endif
mState.mNextInputSampleTime = mState.mCurrentInputTime.mSampleTime + framesToAdvance;
}
struct State {
AudioTimeStamp mCurrentInputTime;
Float64 mNextInputSampleTime;
Float64 mNextOutputSampleTime;
Float64 mInputSampleTimeForOutputPull;
AudioTimeStamp mLastOutputTime;
AudioTimeStamp mCurrentOutputTime;
bool mStartInputAtZero; // if true, input timeline starts at 0, else it starts
// synced with the output timeline
bool mDiscontinuous;
bool mBypassed;
Float64 mDiscontinuityDeltaSamples;
double mRateScalarAdj;
bool mHostTimeDiscontinuityCorrection; // If true, propagate timestamp discontinuities using host time.
};
void GetState(State& outState) const { outState = mState; }
void SetState(State const& inState) { mState = inState; mFirstTime = false; }
private:
struct State mState;
bool mFirstTime;
#if DEBUG
public:
int mVerbosity;
char mDebugName[64];
#endif
};
#endif // __AUTimestampGenerator_h__

+ 0
- 88
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUViewLocalizedStringKeys.h View File

@@ -1,88 +0,0 @@
/*
File: AUViewLocalizedStringKeys.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __AUViewLocalizedStringKeys_h__
#define __AUViewLocalizedStringKeys_h__
// ACCESS POINT:
#define kLocalizedStringBundle_AUView CFSTR("com.apple.audio.units.Components")
#define kLocalizedStringTable_AUView CFSTR("CustomUI")
// UNLOCALIZED STRINGS:
#define kAUViewUnlocalizedString_TitleSeparator CFSTR(": ")
// Generic View:
#define kAUViewLocalizedStringKey_AudioUnit CFSTR("Audio Unit")
#define kAUViewLocalizedStringKey_Manufacturer CFSTR("Manufacturer")
#define kAUViewLocalizedStringKey_FactoryPreset CFSTR("Factory Preset")
#define kAUViewLocalizedStringKey_Properties CFSTR("Properties")
#define kAUViewLocalizedStringKey_Parameters CFSTR("Parameters")
#define kAUViewLocalizedStringKey_Standard CFSTR("Standard")
#define kAUViewLocalizedStringKey_Expert CFSTR("Expert")
// AULoadCPU:
#define kAUViewLocalizedStringKey_RestrictCPULoad CFSTR("Restrict CPU Load")
#define kAUViewLocalizedStringKey_PercentSymbol CFSTR("%")
#define kAUViewLocalizedStringKey_NotApplicable CFSTR("n/a")
// AUDiskStreamingCheckbox:
#define kAUViewLocalizedStringKey_StreamFromDisk CFSTR("Stream From Disk")
// AURenderQualityPopup:
#define kAUViewLocalizedStringKey_RenderQuality CFSTR("Render Quality")
#define kAUViewLocalizedStringKey_Maximum CFSTR("Maximum")
#define kAUViewLocalizedStringKey_High CFSTR("High")
#define kAUViewLocalizedStringKey_Medium CFSTR("Medium")
#define kAUViewLocalizedStringKey_Low CFSTR("Low")
#define kAUViewLocalizedStringKey_Minimum CFSTR("Minimum")
// AUChannelLayoutPopUp:
#define kAUViewLocalizedStringKey_AudioChannelLayout CFSTR("Audio Channel Layout")
#endif //__AUViewLocalizedStringKeys_h__

+ 0
- 401
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.cpp View File

@@ -1,401 +0,0 @@
/*
File: CAAUParameter.cpp
Abstract: CAAUParameter.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "CAAUParameter.h"
CAAUParameter::CAAUParameter()
{
memset(this, 0, sizeof(CAAUParameter));
}
CAAUParameter::CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
{
memset(this, 0, sizeof(CAAUParameter));
Init (au, param, scope, element);
}
CAAUParameter::CAAUParameter (AudioUnitParameter &inParam)
{
memset(this, 0, sizeof(CAAUParameter));
Init (inParam.mAudioUnit, inParam.mParameterID, inParam.mScope, inParam.mElement);
}
CAAUParameter::CAAUParameter(const CAAUParameter &a)
{
memset(this, 0, sizeof(CAAUParameter));
*this = a;
}
CAAUParameter & CAAUParameter::operator = (const CAAUParameter &a)
{
if (mParamName) CFRelease(mParamName);
if (mParamTag) CFRelease(mParamTag);
if (mNamedParams) CFRelease(mNamedParams);
memcpy(this, &a, sizeof(CAAUParameter));
if (mParamName) CFRetain(mParamName);
if (mParamTag) CFRetain(mParamTag);
if (mNamedParams) CFRetain(mNamedParams);
return *this;
}
CAAUParameter::~CAAUParameter()
{
if (mParamName) CFRelease(mParamName);
if (mParamTag) CFRelease(mParamTag);
if (mNamedParams) CFRelease (mNamedParams);
}
void CAAUParameter::Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element)
{
mAudioUnit = au;
mParameterID = param;
mScope = scope;
mElement = element;
UInt32 propertySize = sizeof(mParamInfo);
OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
scope, param, &mParamInfo, &propertySize);
if (err)
memset(&mParamInfo, 0, sizeof(mParamInfo));
if (mParamInfo.flags & kAudioUnitParameterFlag_HasCFNameString) {
mParamName = mParamInfo.cfNameString;
if (!(mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease))
CFRetain (mParamName);
} else
mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
const char* str = 0;
switch (mParamInfo.unit)
{
case kAudioUnitParameterUnit_Boolean:
str = "T/F";
break;
case kAudioUnitParameterUnit_Percent:
case kAudioUnitParameterUnit_EqualPowerCrossfade:
str = "%";
break;
case kAudioUnitParameterUnit_Seconds:
str = "Secs";
break;
case kAudioUnitParameterUnit_SampleFrames:
str = "Samps";
break;
case kAudioUnitParameterUnit_Phase:
case kAudioUnitParameterUnit_Degrees:
str = "Degr.";
break;
case kAudioUnitParameterUnit_Hertz:
str = "Hz";
break;
case kAudioUnitParameterUnit_Cents:
case kAudioUnitParameterUnit_AbsoluteCents:
str = "Cents";
break;
case kAudioUnitParameterUnit_RelativeSemiTones:
str = "S-T";
break;
case kAudioUnitParameterUnit_MIDINoteNumber:
case kAudioUnitParameterUnit_MIDIController:
str = "MIDI";
//these are inclusive, so add one value here
mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
break;
case kAudioUnitParameterUnit_Decibels:
str = "dB";
break;
case kAudioUnitParameterUnit_MixerFaderCurve1:
case kAudioUnitParameterUnit_LinearGain:
str = "Gain";
break;
case kAudioUnitParameterUnit_Pan:
str = "L/R";
break;
case kAudioUnitParameterUnit_Meters:
str = "Mtrs";
break;
case kAudioUnitParameterUnit_Octaves:
str = "8ve";
break;
case kAudioUnitParameterUnit_BPM:
str = "BPM";
break;
case kAudioUnitParameterUnit_Beats:
str = "Beats";
break;
case kAudioUnitParameterUnit_Milliseconds:
str = "msecs";
break;
case kAudioUnitParameterUnit_Ratio:
str = "Ratio";
break;
case kAudioUnitParameterUnit_Indexed:
{
propertySize = sizeof(mNamedParams);
err = AudioUnitGetProperty (au,
kAudioUnitProperty_ParameterValueStrings,
scope,
param,
&mNamedParams,
&propertySize);
if (!err && mNamedParams) {
mNumIndexedParams = CFArrayGetCount(mNamedParams);
} else {
//these are inclusive, so add one value here
mNumIndexedParams = short(mParamInfo.maxValue+1 - mParamInfo.minValue);
}
str = NULL;
}
break;
case kAudioUnitParameterUnit_CustomUnit:
{
CFStringRef unitName = mParamInfo.unitName;
static char paramStr[256];
CFStringGetCString (unitName, paramStr, 256, kCFStringEncodingUTF8);
if (mParamInfo.flags & kAudioUnitParameterFlag_CFNameRelease)
CFRelease (unitName);
str = paramStr;
break;
}
case kAudioUnitParameterUnit_Generic:
case kAudioUnitParameterUnit_Rate:
default:
str = NULL;
break;
}
if (str)
mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
else
mParamTag = NULL;
}
Float32 CAAUParameter::GetValue() const
{
Float32 value = 0.;
//OSStatus err =
AudioUnitGetParameter(mAudioUnit, mParameterID, mScope, mElement, &value);
return value;
}
CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
const CAAUParameter * inParameter,
UInt32 inDigits,
UInt32 minDigits) {
if (!inParameter) return nil;
AudioUnitParameterInfo info = inParameter->ParamInfo();
int pow10;
switch (info.unit) {
case kAudioUnitParameterUnit_Hertz:
// number of significant digits based on value
pow10 = int(log10(fmax(inParameterValue, .000001)));
break;
default:
// number of significant digits based on parameter range
pow10 = int(log10(fmax(double(info.maxValue - info.minValue), .000001)));
break;
}
// pow10 range nDigitsAfterDecimal
// -2 .0100-.0999 4
// -1 .100-.999 3
// 0 1.00-9.99 2
// 1 10.0-99.9 1
// 2 100-999 0
// 3 1000-9990 -1
// 4 10000-99900 -2
int nDigitsAfterDecimal = inDigits - (pow10 + 1);
if (nDigitsAfterDecimal < 0)
nDigitsAfterDecimal = 0; // the least number of digits possible is zero
if (info.flags & kAudioUnitParameterFlag_IsHighResolution)
nDigitsAfterDecimal = 4;
CFLocaleRef currentLocale = CFLocaleCopyCurrent();
CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
CFNumberRef maxFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
if (nDigitsAfterDecimal > 0)
nDigitsAfterDecimal = minDigits;
CFNumberRef minFractionDigits = CFNumberCreate (NULL, kCFNumberIntType, &nDigitsAfterDecimal);
CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMinFractionDigits, minFractionDigits);
CFNumberFormatterSetProperty (numberFormatter, kCFNumberFormatterMaxFractionDigits, maxFractionDigits);
CFStringRef formattedNumberString = CFNumberFormatterCreateStringWithValue (NULL, numberFormatter, kCFNumberDoubleType, &inParameterValue);
CFRelease(currentLocale);
CFRelease(numberFormatter);
CFRelease(maxFractionDigits);
CFRelease(minFractionDigits);
return formattedNumberString;
}
CFStringRef CreateLocalizedStringForParameterValue ( double inParameterValue,
const CAAUParameter * inParameter,
UInt32 inDigits) {
return CreateLocalizedStringForParameterValue (inParameterValue, inParameter, inDigits, 1);
}
double ValueForLocalizedParameterString (CFStringRef string, const CAAUParameter * inParameter) {
CFLocaleRef currentLocale = CFLocaleCopyCurrent();
CFNumberFormatterRef numberFormatter = CFNumberFormatterCreate (NULL, currentLocale, kCFNumberFormatterDecimalStyle);
double value = 0;
Boolean worked = CFNumberFormatterGetValueFromString (numberFormatter, string, NULL, kCFNumberDoubleType, &value);
CFRelease(currentLocale);
CFRelease(numberFormatter);
if (worked)
return value;
else {
AudioUnitParameterInfo info = inParameter->ParamInfo();
return info.defaultValue;
}
}
CFStringRef CAAUParameter::GetStringFromValueCopy(const Float32 *value) const
{
if (HasNamedParams())
{
Float32 val = (value == NULL ? GetValue() : *value);
int index = int(mParamInfo.minValue) + int(val);
CFStringRef str = GetParamName (index);
if (str) {
CFRetain (str);
return str;
}
}
else if (ValuesHaveStrings())
{
AudioUnitParameterStringFromValue stringValue;
stringValue.inParamID = mParameterID;
stringValue.inValue = value;
stringValue.outString = NULL;
UInt32 propertySize = sizeof(stringValue);
OSStatus err = AudioUnitGetProperty (mAudioUnit,
kAudioUnitProperty_ParameterStringFromValue,
mScope,
0,
&stringValue,
&propertySize);
if (!err && stringValue.outString != NULL)
return stringValue.outString;
}
Float32 val = (value == NULL ? GetValue() : *value);
AudioUnitParameterUnit unit = this->ParamInfo().unit;
if (unit == kAudioUnitParameterUnit_Cents || unit == kAudioUnitParameterUnit_AbsoluteCents)
return CreateLocalizedStringForParameterValue(val, this, 4, 0);
else
return CreateLocalizedStringForParameterValue(val, this, 4);
}
Float32 CAAUParameter::GetValueFromString(CFStringRef str) const
{
if (ValuesHaveStrings())
{
AudioUnitParameterValueFromString valueString;
valueString.inParamID = mParameterID;
valueString.inString = str;
UInt32 propertySize = sizeof(valueString);
OSStatus err = AudioUnitGetProperty (mAudioUnit,
kAudioUnitProperty_ParameterValueFromString,
mScope,
0,
&valueString,
&propertySize);
if (!err) {
return valueString.outValue;
}
}
return (Float32) ValueForLocalizedParameterString(str, this);
}
void CAAUParameter::SetValue( AUParameterListenerRef inListener,
void * inObject,
Float32 inValue) const
{
// clip inValue as: maxValue >= inValue >= minValue before setting
Float32 valueToSet = inValue;
if (valueToSet > mParamInfo.maxValue)
valueToSet = mParamInfo.maxValue;
if (valueToSet < mParamInfo.minValue)
valueToSet = mParamInfo.minValue;
AUParameterSet(inListener, inObject, this, valueToSet, 0);
}
#if DEBUG
void CAAUParameter::Print() const
{
UInt32 clump = 0;
GetClumpID (clump);
UInt32 len = static_cast<UInt32>(CFStringGetLength(mParamName));
char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
chars[0] = 0;
printf ("ID: %ld, Clump: %u, Name: %s\n", (long unsigned int) mParameterID, (unsigned int) clump, chars);
free (chars);
}
#endif

+ 0
- 191
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAUParameter.h View File

@@ -1,191 +0,0 @@
/*
File: CAAUParameter.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAAUParameter_h__
#define __CAAUParameter_h__
#include <AudioToolbox/AudioUnitUtilities.h>
// ____________________________________________________________________________
// CAAUParameter
// complete parameter specification
/*! @class CAAUParameter */
class CAAUParameter : public AudioUnitParameter {
public:
/*! @ctor CAAUParameter.0 */
CAAUParameter();
/*! @ctor CAAUParameter.1 */
CAAUParameter(AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
/*! @ctor CAAUParameter.2 */
CAAUParameter(AudioUnitParameter &inParam);
/*! @ctor CAAUParameter.3 */
CAAUParameter(const CAAUParameter &a);
/*! @dtor ~CAAUParameter */
~CAAUParameter();
/*! @method operator <@ */
bool operator < (const CAAUParameter &a) const
{
return memcmp(this, &a, sizeof(AudioUnitParameter)) < 0;
}
/*! @method operator ==@ */
bool operator == (const CAAUParameter &a) const
{
return !memcmp(this, &a, sizeof(AudioUnitParameter));
}
/*! @method operator =@ */
CAAUParameter & operator = (const CAAUParameter &a);
/*! @method GetValue */
Float32 GetValue() const;
/*! @method SetValue */
void SetValue( AUParameterListenerRef inListener,
void * inObject,
Float32 inValue) const;
/*! @method GetName */
CFStringRef GetName() const { return mParamName; }
// borrowed reference!
/*! @method GetStringFromValueCopy */
CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
// returns a copy of the name of the current parameter value
// or null if there is no name associated
// caller must release
/*! @method ValuesHaveStrings */
bool ValuesHaveStrings () const
{
return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
}
/*! @method GetValueFromString */
Float32 GetValueFromString (CFStringRef str) const;
// caller must release
/*! @method ParamInfo */
const AudioUnitParameterInfo &
ParamInfo() const { return mParamInfo; }
/*! @method GetParamTag */
CFStringRef GetParamTag() const { return mParamTag; }
// this may return null! -
// in which case there is no descriptive tag for the parameter
/*! @method GetParamName */
CFStringRef GetParamName (int inIndex) const
// this can return null if there is no name for the parameter
{
return (mNamedParams && inIndex < mNumIndexedParams)
? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
: 0;
}
/*! @method GetNumIndexedParams */
int GetNumIndexedParams () const { return mNumIndexedParams; }
/*! @method IsIndexedParam */
bool IsIndexedParam () const { return mNumIndexedParams != 0; }
/*! @method HasNamedParams */
bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
/*! @method GetClumpID */
bool GetClumpID (UInt32 &outClumpID) const
{
if (mParamInfo.flags & kAudioUnitParameterFlag_HasClump) {
outClumpID = mParamInfo.clumpID;
return true;
}
return false;
}
/*! @method HasDisplayTransformation */
bool HasDisplayTransformation () const
{
return GetAudioUnitParameterDisplayType (mParamInfo.flags);
}
/*! @method IsExpert */
bool IsExpert () const
{
return mParamInfo.flags & kAudioUnitParameterFlag_ExpertMode;
}
#if DEBUG
void Print () const;
#endif
// these methods are defined in CAPersistence.cpp
// they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
// however, this is sufficient to be able to save/restore a CAAUParameter object
void Save (CFPropertyListRef &outData) const;
static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam);
protected:
// cached parameter info
/*! @var mParamInfo */
AudioUnitParameterInfo mParamInfo;
/*! @var mParamName */
CFStringRef mParamName;
/*! @var mParamTag */
CFStringRef mParamTag;
/*! @var mNumIndexedParams */
short mNumIndexedParams;
/*! @var mNamedParams */
CFArrayRef mNamedParams;
private:
void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
};
#endif // __CAAUParameter_h__

+ 0
- 305
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomic.h View File

@@ -1,305 +0,0 @@
/*
File: CAAtomic.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
/*
This file implements all Atomic operations using Interlocked functions specified in
Winbase.h
NOTE: According to Microsoft documentation, all Interlocked functions generates a
full barrier.
On Windows:
As the Interlocked functions returns the Old value, Extra checks and operations
are made after the atomic operation to return value consistent with OSX counterparts.
*/
#ifndef __CAAtomic_h__
#define __CAAtomic_h__
#if TARGET_OS_WIN32
#include <windows.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedAnd)
#else
#include <CoreFoundation/CFBase.h>
#include <libkern/OSAtomic.h>
#endif
inline void CAMemoryBarrier()
{
#if TARGET_OS_WIN32
MemoryBarrier();
#else
OSMemoryBarrier();
#endif
}
inline SInt32 CAAtomicAdd32Barrier(SInt32 theAmt, volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
long lRetVal = InterlockedExchangeAdd((volatile long*)theValue, theAmt);
// InterlockedExchangeAdd returns the original value which differs from OSX version.
// At this point the addition would have occured and hence returning the new value
// to keep it sync with OSX.
return lRetVal + theAmt;
#else
return OSAtomicAdd32Barrier(theAmt, (volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicOr32Barrier(UInt32 theMask, volatile UInt32* theValue)
{
#if TARGET_OS_WIN32
// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
// function instead.
long j = _InterlockedOr((volatile long*)theValue, theMask);
// _InterlockedOr returns the original value which differs from OSX version.
// Returning the new value similar to OSX
return (SInt32)(j | theMask);
#else
return OSAtomicOr32Barrier(theMask, (volatile uint32_t *)theValue);
#endif
}
inline SInt32 CAAtomicAnd32Barrier(UInt32 theMask, volatile UInt32* theValue)
{
#if TARGET_OS_WIN32
// InterlockedAnd macro is not defined in x86 platform, and hence using the intrinsic
// function instead.
long j = _InterlockedAnd((volatile long*)theValue, theMask);
// _InterlockedAnd returns the original value which differs from OSX version.
// Returning the new value similar to OSX
return (SInt32)(j & theMask);
#else
return OSAtomicAnd32Barrier(theMask, (volatile uint32_t *)theValue);
#endif
}
inline bool CAAtomicCompareAndSwap32Barrier(SInt32 oldValue, SInt32 newValue, volatile SInt32 *theValue)
{
#if TARGET_OS_WIN32
// InterlockedCompareExchange returns the old value. But we need to return bool value.
long lRetVal = InterlockedCompareExchange((volatile long*)theValue, newValue, oldValue);
// Hence we check if the new value is set and if it is we return true else false.
// If theValue is equal to oldValue then the swap happens. Otherwise swap doesn't happen.
return (oldValue == lRetVal);
#else
return OSAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicIncrement32(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return (SInt32)InterlockedIncrement((volatile long*)theValue);
#else
return OSAtomicIncrement32((volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicDecrement32(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return (SInt32)InterlockedDecrement((volatile long*)theValue);
#else
return OSAtomicDecrement32((volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicIncrement32Barrier(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return CAAtomicIncrement32(theValue);
#else
return OSAtomicIncrement32Barrier((volatile int32_t *)theValue);
#endif
}
inline SInt32 CAAtomicDecrement32Barrier(volatile SInt32* theValue)
{
#if TARGET_OS_WIN32
return CAAtomicDecrement32(theValue);
#else
return OSAtomicDecrement32Barrier((volatile int32_t *)theValue);
#endif
}
inline bool CAAtomicTestAndClearBarrier(int bitToClear, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = InterlockedBitTestAndReset((long*)theAddress, bitToClear);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndClearBarrier(bitToClear, (volatile void *)theAddress);
#endif
}
inline bool CAAtomicTestAndClear(int bitToClear, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = CAAtomicTestAndClearBarrier(bitToClear, (long*)theAddress);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndClear(bitToClear, (volatile void *)theAddress);
#endif
}
inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
{
#if TARGET_OS_WIN32
BOOL bOldVal = InterlockedBitTestAndSet((long*)theAddress, bitToSet);
return (bOldVal ? true : false);
#else
return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
#endif
}
// int32_t flavors -- for C++ only since we can't overload in C
// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
// SInt32 is defined as signed long so this would work there.
// So in order to fix the redefinition errors, we define these functions only if MacTypes.h is included.
#if defined(__cplusplus) && defined(__MACTYPES__) && !__LP64__
inline int32_t CAAtomicAdd32Barrier(int32_t theAmt, volatile int32_t* theValue)
{
return CAAtomicAdd32Barrier(theAmt, (volatile SInt32 *)theValue);
}
inline int32_t CAAtomicOr32Barrier(uint32_t theMask, volatile uint32_t* theValue)
{
return CAAtomicOr32Barrier(theMask, (volatile UInt32 *)theValue);
}
inline int32_t CAAtomicAnd32Barrier(uint32_t theMask, volatile uint32_t* theValue)
{
return CAAtomicAnd32Barrier(theMask, (volatile UInt32 *)theValue);
}
inline bool CAAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue, volatile int32_t *theValue)
{
return CAAtomicCompareAndSwap32Barrier(oldValue, newValue, (volatile SInt32 *)theValue);
}
inline int32_t CAAtomicIncrement32(volatile int32_t* theValue)
{
return CAAtomicIncrement32((volatile SInt32 *)theValue);
}
inline int32_t CAAtomicDecrement32(volatile int32_t* theValue)
{
return CAAtomicDecrement32((volatile SInt32 *)theValue);
}
inline int32_t CAAtomicIncrement32Barrier(volatile int32_t* theValue)
{
return CAAtomicIncrement32Barrier((volatile SInt32 *)theValue);
}
inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
{
return CAAtomicDecrement32Barrier((volatile SInt32 *)theValue);
}
#endif // __cplusplus && !__LP64__
#if __LP64__
inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
{
return OSAtomicCompareAndSwap64Barrier(__oldValue, __newValue, __theValue);
}
#endif
inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue, volatile void ** __theValue)
{
#if __LP64__
return CAAtomicCompareAndSwap64Barrier((int64_t)__oldValue, (int64_t)__newValue, (int64_t *)__theValue);
#else
return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__theValue);
#endif
}
/* Spinlocks. These use memory barriers as required to synchronize access to shared
* memory protected by the lock. The lock operation spins, but employs various strategies
* to back off if the lock is held, making it immune to most priority-inversion livelocks.
* The try operation immediately returns false if the lock was held, true if it took the
* lock. The convention is that unlocked is zero, locked is nonzero.
*/
#define CA_SPINLOCK_INIT 0
typedef int32_t CASpinLock;
bool CASpinLockTry( volatile CASpinLock *__lock );
void CASpinLockLock( volatile CASpinLock *__lock );
void CASpinLockUnlock( volatile CASpinLock *__lock );
inline void CASpinLockLock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
OSSpinLockLock(__lock);
#else
while (CAAtomicTestAndSetBarrier(0, (void*)__lock))
usleep(1000); // ???
#endif
}
inline void CASpinLockUnlock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
OSSpinLockUnlock(__lock);
#else
CAAtomicTestAndClearBarrier(0, (void*)__lock);
#endif
}
inline bool CASpinLockTry( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
return OSSpinLockTry(__lock);
#else
return (CAAtomicTestAndSetBarrier(0, (void*)__lock) == 0);
#endif
}
#endif // __CAAtomic_h__

+ 0
- 239
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAtomicStack.h View File

@@ -1,239 +0,0 @@
/*
File: CAAtomicStack.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAAtomicStack_h__
#define __CAAtomicStack_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <libkern/OSAtomic.h>
#else
#include <CAAtomic.h>
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
#include <CoreServices/CoreServices.h>
#endif
// linked list LIFO or FIFO (pop_all_reversed) stack, elements are pushed and popped atomically
// class T must implement T *& next().
template <class T>
class TAtomicStack {
public:
TAtomicStack() : mHead(NULL) { }
// non-atomic routines, for use when initializing/deinitializing, operate NON-atomically
void push_NA(T *item)
{
item->next() = mHead;
mHead = item;
}
T * pop_NA()
{
T *result = mHead;
if (result)
mHead = result->next();
return result;
}
bool empty() const { return mHead == NULL; }
T * head() { return mHead; }
// atomic routines
void push_atomic(T *item)
{
T *head_;
do {
head_ = mHead;
item->next() = head_;
} while (!compare_and_swap(head_, item, &mHead));
}
void push_multiple_atomic(T *item)
// pushes entire linked list headed by item
{
T *head_, *p = item, *tail;
// find the last one -- when done, it will be linked to head
do {
tail = p;
p = p->next();
} while (p);
do {
head_ = mHead;
tail->next() = head_;
} while (!compare_and_swap(head_, item, &mHead));
}
T * pop_atomic_single_reader()
// this may only be used when only one thread may potentially pop from the stack.
// if multiple threads may pop, this suffers from the ABA problem.
// <rdar://problem/4606346> TAtomicStack suffers from the ABA problem
{
T *result;
do {
if ((result = mHead) == NULL)
break;
} while (!compare_and_swap(result, result->next(), &mHead));
return result;
}
T * pop_atomic()
// This is inefficient for large linked lists.
// prefer pop_all() to a series of calls to pop_atomic.
// push_multiple_atomic has to traverse the entire list.
{
T *result = pop_all();
if (result) {
T *next = result->next();
if (next)
// push all the remaining items back onto the stack
push_multiple_atomic(next);
}
return result;
}
T * pop_all()
{
T *result;
do {
if ((result = mHead) == NULL)
break;
} while (!compare_and_swap(result, NULL, &mHead));
return result;
}
T* pop_all_reversed()
{
TAtomicStack<T> reversed;
T *p = pop_all(), *next;
while (p != NULL) {
next = p->next();
reversed.push_NA(p);
p = next;
}
return reversed.mHead;
}
static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
{
#if TARGET_OS_MAC
#if __LP64__
return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
return ::OSAtomicCompareAndSwap32Barrier(int32_t(oldvalue), int32_t(newvalue), (int32_t *)pvalue);
#else
return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
#endif
#else
//return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
#endif
}
protected:
T * mHead;
};
#if ((MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) && !TARGET_OS_WIN32)
#include <libkern/OSAtomic.h>
class CAAtomicStack {
public:
CAAtomicStack(size_t nextPtrOffset) : mNextPtrOffset(nextPtrOffset) {
/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
mHead.opaque1 = 0; mHead.opaque2 = 0;
}
// a subset of the above
void push_atomic(void *p) { OSAtomicEnqueue(&mHead, p, mNextPtrOffset); }
void push_NA(void *p) { push_atomic(p); }
void * pop_atomic() { return OSAtomicDequeue(&mHead, mNextPtrOffset); }
void * pop_atomic_single_reader() { return pop_atomic(); }
void * pop_NA() { return pop_atomic(); }
private:
OSQueueHead mHead;
size_t mNextPtrOffset;
};
// a more efficient subset of TAtomicStack using OSQueue.
template <class T>
class TAtomicStack2 {
public:
TAtomicStack2() {
/*OSQueueHead h = OS_ATOMIC_QUEUE_INIT; mHead = h;*/
mHead.opaque1 = 0; mHead.opaque2 = 0;
mNextPtrOffset = -1;
}
void push_atomic(T *item) {
if (mNextPtrOffset < 0) {
T **pnext = &item->next(); // hack around offsetof not working with C++
mNextPtrOffset = (Byte *)pnext - (Byte *)item;
}
OSAtomicEnqueue(&mHead, item, mNextPtrOffset);
}
void push_NA(T *item) { push_atomic(item); }
T * pop_atomic() { return (T *)OSAtomicDequeue(&mHead, mNextPtrOffset); }
T * pop_atomic_single_reader() { return pop_atomic(); }
T * pop_NA() { return pop_atomic(); }
// caution: do not try to implement pop_all_reversed here. the writer could add new elements
// while the reader is trying to pop old ones!
private:
OSQueueHead mHead;
ssize_t mNextPtrOffset;
};
#else
#define TAtomicStack2 TAtomicStack
#endif // MAC_OS_X_VERSION_MAX_ALLOWED && !TARGET_OS_WIN32
#endif // __CAAtomicStack_h__

+ 0
- 153
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp View File

@@ -1,153 +0,0 @@
/*
File: CAAudioChannelLayout.cpp
Abstract: CAAudioChannelLayout.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
//=============================================================================
// Includes
//=============================================================================
// Self Include
#include "CAAudioChannelLayout.h"
#include "CAAutoDisposer.h"
#include <stdlib.h>
#include <string.h>
//=============================================================================
// CAAudioChannelLayout
//=============================================================================
AudioChannelLayout* CAAudioChannelLayout::Create(UInt32 inNumberChannelDescriptions)
{
UInt32 theSize = CalculateByteSize(inNumberChannelDescriptions);
AudioChannelLayout* theAnswer = static_cast<AudioChannelLayout*>(CA_calloc(1, theSize));
if(theAnswer != NULL)
{
SetAllToUnknown(*theAnswer, inNumberChannelDescriptions);
}
return theAnswer;
}
void CAAudioChannelLayout::Destroy(AudioChannelLayout* inChannelLayout)
{
free(inChannelLayout);
}
void CAAudioChannelLayout::SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions)
{
outChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
outChannelLayout.mChannelBitmap = 0;
outChannelLayout.mNumberChannelDescriptions = inNumberChannelDescriptions;
for(UInt32 theChannelIndex = 0; theChannelIndex < inNumberChannelDescriptions; ++theChannelIndex)
{
outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelLabel = kAudioChannelLabel_Unknown;
outChannelLayout.mChannelDescriptions[theChannelIndex].mChannelFlags = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[0] = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[1] = 0;
outChannelLayout.mChannelDescriptions[theChannelIndex].mCoordinates[2] = 0;
}
}
bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y)
{
// compare based on the number of channel descriptions present
// (this may be too strict a comparison if all you care about are matching layout tags)
UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
if (theSize1 != theSize2)
return false;
return !memcmp (&x, &y, theSize1);
}
bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y)
{
return !(x == y);
}
// counting the one bits in a word
inline UInt32 CountOnes(UInt32 x)
{
// secret magic algorithm for counting bits in a word.
UInt32 t;
x = x - ((x >> 1) & 0x55555555);
t = ((x >> 2) & 0x33333333);
x = (x & 0x33333333) + t;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x + (x << 8);
x = x + (x << 16);
return x >> 24;
}
UInt32 CAAudioChannelLayout::NumberChannels (const AudioChannelLayout& inLayout)
{
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
return inLayout.mNumberChannelDescriptions;
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
return CountOnes (inLayout.mChannelBitmap);
return AudioChannelLayoutTag_GetNumberOfChannels(inLayout.mChannelLayoutTag);
}
void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout)
{
if (layout == NULL)
{
fprintf (file, "\tNULL layout\n");
return;
}
fprintf (file, "\tTag=0x%X, ", (int)layout->mChannelLayoutTag);
if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
fprintf (file, "Using Bitmap:0x%X\n", (int)layout->mChannelBitmap);
else {
fprintf (file, "Num Chan Descs=%d\n", (int)layout->mNumberChannelDescriptions);
const AudioChannelDescription *desc = layout->mChannelDescriptions;
for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; ++i, ++desc) {
fprintf (file, "\t\tLabel=%d, Flags=0x%X, ", (int)desc->mChannelLabel, (int)desc->mChannelFlags);
fprintf (file, "[az=%f,el=%f,dist=%f]\n", desc->mCoordinates[0], desc->mCoordinates[1], desc->mCoordinates[2]);
}
}
}

+ 0
- 199
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAudioChannelLayout.h View File

@@ -1,199 +0,0 @@
/*
File: CAAudioChannelLayout.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !defined(__CAAudioChannelLayout_h__)
#define __CAAudioChannelLayout_h__
//=============================================================================
// Includes
//=============================================================================
// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#else
#include <CoreAudioTypes.h>
#include <CoreFoundation.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CADebugMacros.h"
#include "CAAutoDisposer.h"
#if !HAL_Build
#include "CAReferenceCounted.h"
#endif
//=============================================================================
// CAAudioChannelLayout
//=============================================================================
bool operator== (const AudioChannelLayout &x, const AudioChannelLayout &y);
bool operator!= (const AudioChannelLayout &x, const AudioChannelLayout &y);
extern "C" void CAShowAudioChannelLayout (FILE* file, const AudioChannelLayout *layout);
class CAAudioChannelLayout
{
// static Construction/Destruction
public:
static AudioChannelLayout* Create(UInt32 inNumberChannelDescriptions);
static void Destroy(AudioChannelLayout* inChannelLayout);
static UInt32 CalculateByteSize(UInt32 inNumberChannelDescriptions) {
return SizeOf32(AudioChannelLayout) - SizeOf32(AudioChannelDescription) + (inNumberChannelDescriptions * SizeOf32(AudioChannelDescription));
}
static void SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
static UInt32 NumberChannels(const AudioChannelLayout& inLayout);
#if !HAL_Build
// object methods
public:
CAAudioChannelLayout ();
CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
// if inChooseSurround is false, then symmetrical speaker arrangements
// are chosen in place of surround layouts if there is a choice
// This call chooses layouts based on the expected defaults in
// AudioUnit usage
CAAudioChannelLayout (AudioChannelLayoutTag inTag);
CAAudioChannelLayout (const CAAudioChannelLayout &c);
CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
~CAAudioChannelLayout();
CAAudioChannelLayout& operator= (const AudioChannelLayout* inChannelLayout);
CAAudioChannelLayout& operator= (const CAAudioChannelLayout& c);
bool operator== (const CAAudioChannelLayout &c) const;
bool operator!= (const CAAudioChannelLayout &c) const;
void SetWithTag(AudioChannelLayoutTag inTag);
bool IsValid() const { return NumberChannels() > 0; }
UInt32 Size() const { return mLayout ? mLayout->Size() : 0; }
UInt32 NumberChannels() const { return mLayout ? mLayout->NumberChannels() : 0; }
AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; }
const AudioChannelLayout& Layout() const { return mLayout->Layout(); }
operator const AudioChannelLayout *() const { return &Layout(); }
void Print () const { Print (stdout); }
void Print (FILE* file) const;
OSStatus Save (CFPropertyListRef *outData) const;
OSStatus Restore (CFPropertyListRef &inData);
private:
class RefCountedLayout : public CAReferenceCounted {
void * operator new(size_t /* size */, size_t aclSize)
{
return CA_malloc(sizeof(RefCountedLayout) - sizeof(AudioChannelLayout) + aclSize);
}
void operator delete(void *mem)
{
free(mem);
}
RefCountedLayout(UInt32 inDataSize) :
mByteSize(inDataSize)
{
memset(&mACL, 0, inDataSize);
}
public:
static RefCountedLayout *CreateWithNumberChannelDescriptions(unsigned nChannels) {
size_t size = CAAudioChannelLayout::CalculateByteSize(nChannels);
return new(size) RefCountedLayout((UInt32)size);
}
static RefCountedLayout *CreateWithLayout(const AudioChannelLayout *layout) {
size_t size = CAAudioChannelLayout::CalculateByteSize(layout->mNumberChannelDescriptions);
RefCountedLayout *acl = new(size) RefCountedLayout((UInt32)size);
memcpy(&acl->mACL, layout, size);
return acl;
}
static RefCountedLayout *CreateWithLayoutTag(AudioChannelLayoutTag layoutTag) {
RefCountedLayout *acl = CreateWithNumberChannelDescriptions(0);
acl->mACL.mChannelLayoutTag = layoutTag;
return acl;
}
const AudioChannelLayout & Layout() const { return mACL; }
UInt32 Size () const { return mByteSize; }
UInt32 NumberChannels() { return CAAudioChannelLayout::NumberChannels(Layout()); }
private:
const UInt32 mByteSize;
AudioChannelLayout mACL;
// * * * mACL is variable length and thus must be last * * *
// only the constructors can change the actual state of the layout
friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
AudioChannelLayout * GetLayout() { return &mACL; }
private:
// prohibited methods: private and unimplemented.
RefCountedLayout();
RefCountedLayout(const RefCountedLayout& c);
RefCountedLayout& operator=(const RefCountedLayout& c);
};
RefCountedLayout *mLayout;
#endif // HAL_Build
};
#endif

+ 0
- 508
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAAutoDisposer.h View File

@@ -1,508 +0,0 @@
/*
File: CAAutoDisposer.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !defined(__CAPtr_h__)
#define __CAPtr_h__
#include <stdlib.h> // for malloc
#include <new> // for bad_alloc
#include <string.h> // for memset
inline void* CA_malloc(size_t size)
{
void* p = malloc(size);
if (!p && size) throw std::bad_alloc();
return p;
}
inline void* CA_realloc(void* old, size_t size)
{
#if TARGET_OS_WIN32
void* p = realloc(old, size);
#else
void* p = reallocf(old, size); // reallocf ensures the old pointer is freed if memory is full (p is NULL).
#endif
if (!p && size) throw std::bad_alloc();
return p;
}
#ifndef UINTPTR_MAX
#if __LP64__
#define UINTPTR_MAX 18446744073709551615ULL
#else
#define UINTPTR_MAX 4294967295U
#endif
#endif
inline void* CA_calloc(size_t n, size_t size)
{
// ensure that multiplication will not overflow
if (n && UINTPTR_MAX / n < size) throw std::bad_alloc();
size_t nsize = n*size;
void* p = malloc(nsize);
if (!p && nsize) throw std::bad_alloc();
memset(p, 0, nsize);
return p;
}
// helper class for automatic conversions
template <typename T>
struct CAPtrRef
{
T* ptr_;
explicit CAPtrRef(T* ptr) : ptr_(ptr) {}
};
template <typename T>
class CAAutoFree
{
private:
T* ptr_;
public:
CAAutoFree() : ptr_(0) {}
explicit CAAutoFree(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoFree(CAAutoFree<U>& that) : ptr_(that.release()) {} // take ownership
// C++ std says: a template constructor is never a copy constructor
CAAutoFree(CAAutoFree<T>& that) : ptr_(that.release()) {} // take ownership
CAAutoFree(size_t n, bool clear = false)
// this becomes an ambiguous call if n == 0
: ptr_(0)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (n > maxItems)
throw std::bad_alloc();
ptr_ = static_cast<T*>(clear ? CA_calloc(n, sizeof(T)) : CA_malloc(n * sizeof(T)));
}
~CAAutoFree() { free(); }
void alloc(size_t numItems, bool clear = false)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (numItems > maxItems) throw std::bad_alloc();
free();
ptr_ = static_cast<T*>(clear ? CA_calloc(numItems, sizeof(T)) : CA_malloc(numItems * sizeof(T)));
}
void allocBytes(size_t numBytes, bool clear = false)
{
free();
ptr_ = static_cast<T*>(clear ? CA_calloc(1, numBytes) : CA_malloc(numBytes));
}
void reallocBytes(size_t numBytes)
{
ptr_ = static_cast<T*>(CA_realloc(ptr_, numBytes));
}
void reallocItems(size_t numItems)
{
size_t maxItems = ~size_t(0) / sizeof(T);
if (numItems > maxItems) throw std::bad_alloc();
ptr_ = static_cast<T*>(CA_realloc(ptr_, numItems * sizeof(T)));
}
template <typename U>
CAAutoFree& operator=(CAAutoFree<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoFree& operator=(CAAutoFree& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoFree& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoFree& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoFree const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoFree const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
::free(ptr_);
ptr_ = ptr;
}
}
void free()
{
set(0);
}
// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoFree(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
CAAutoFree& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}
template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }
template<typename U>
operator CAAutoFree<U>()
{ return CAAutoFree<U>(release()); }
};
template <typename T>
class CAAutoDelete
{
private:
T* ptr_;
public:
CAAutoDelete() : ptr_(0) {}
explicit CAAutoDelete(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoDelete(CAAutoDelete<U>& that) : ptr_(that.release()) {} // take ownership
// C++ std says: a template constructor is never a copy constructor
CAAutoDelete(CAAutoDelete<T>& that) : ptr_(that.release()) {} // take ownership
~CAAutoDelete() { free(); }
template <typename U>
CAAutoDelete& operator=(CAAutoDelete<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoDelete& operator=(CAAutoDelete& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoDelete& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoDelete& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoDelete const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoDelete const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
delete ptr_;
ptr_ = ptr;
}
}
void free()
{
set(0);
}
// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
CAAutoDelete& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}
template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }
template<typename U>
operator CAAutoFree<U>()
{ return CAAutoFree<U>(release()); }
};
template <typename T>
class CAAutoArrayDelete
{
private:
T* ptr_;
public:
CAAutoArrayDelete() : ptr_(0) {}
explicit CAAutoArrayDelete(T* ptr) : ptr_(ptr) {}
template<typename U>
CAAutoArrayDelete(CAAutoArrayDelete<U>& that) : ptr_(that.release()) {} // take ownership
// C++ std says: a template constructor is never a copy constructor
CAAutoArrayDelete(CAAutoArrayDelete<T>& that) : ptr_(that.release()) {} // take ownership
// this becomes an ambiguous call if n == 0
CAAutoArrayDelete(size_t n) : ptr_(new T[n]) {}
~CAAutoArrayDelete() { free(); }
void alloc(size_t numItems)
{
free();
ptr_ = new T [numItems];
}
template <typename U>
CAAutoArrayDelete& operator=(CAAutoArrayDelete<U>& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoArrayDelete& operator=(CAAutoArrayDelete& that)
{
set(that.release()); // take ownership
return *this;
}
CAAutoArrayDelete& operator=(T* ptr)
{
set(ptr);
return *this;
}
template <typename U>
CAAutoArrayDelete& operator=(U* ptr)
{
set(ptr);
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* operator()() const { return ptr_; }
T* get() const { return ptr_; }
operator T*() const { return ptr_; }
bool operator==(CAAutoArrayDelete const& that) const { return ptr_ == that.ptr_; }
bool operator!=(CAAutoArrayDelete const& that) const { return ptr_ != that.ptr_; }
bool operator==(T* ptr) const { return ptr_ == ptr; }
bool operator!=(T* ptr) const { return ptr_ != ptr; }
T* release()
{
// release ownership
T* result = ptr_;
ptr_ = 0;
return result;
}
void set(T* ptr)
{
if (ptr != ptr_)
{
delete [] ptr_;
ptr_ = ptr;
}
}
void free()
{
set(0);
}
// automatic conversions to allow assignment from results of functions.
// hard to explain. see auto_ptr implementation and/or Josuttis' STL book.
CAAutoArrayDelete(CAPtrRef<T> ref) : ptr_(ref.ptr_) { }
CAAutoArrayDelete& operator=(CAPtrRef<T> ref)
{
set(ref.ptr_);
return *this;
}
template<typename U>
operator CAPtrRef<U>()
{ return CAPtrRef<U>(release()); }
template<typename U>
operator CAAutoArrayDelete<U>()
{ return CAAutoFree<U>(release()); }
};
// convenience function
template <typename T>
void free(CAAutoFree<T>& p)
{
p.free();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
#if 0
// example program showing ownership transfer
CAAutoFree<char> source()
{
// source allocates and returns ownership to the caller.
const char* str = "this is a test";
size_t size = strlen(str) + 1;
CAAutoFree<char> captr(size, false);
strlcpy(captr(), str, size);
printf("source %08X %08X '%s'\n", &captr, captr(), captr());
return captr;
}
void user(CAAutoFree<char> const& captr)
{
// passed by const reference. user can access the pointer but does not take ownership.
printf("user: %08X %08X '%s'\n", &captr, captr(), captr());
}
void sink(CAAutoFree<char> captr)
{
// passed by value. sink takes ownership and frees the pointer on return.
printf("sink: %08X %08X '%s'\n", &captr, captr(), captr());
}
int main (int argc, char * const argv[])
{
CAAutoFree<char> captr(source());
printf("main captr A %08X %08X\n", &captr, captr());
user(captr);
sink(captr);
printf("main captr B %08X %08X\n", &captr, captr());
return 0;
}
#endif
#endif

+ 0
- 583
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugMacros.h View File

@@ -1,583 +0,0 @@
/*
File: CADebugMacros.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !defined(__CADebugMacros_h__)
#define __CADebugMacros_h__
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include "CoreAudioTypes.h"
#endif
//=============================================================================
// CADebugMacros
//=============================================================================
//#define CoreAudio_StopOnFailure 1
//#define CoreAudio_TimeStampMessages 1
//#define CoreAudio_ThreadStampMessages 1
//#define CoreAudio_FlushDebugMessages 1
#if TARGET_RT_BIG_ENDIAN
#define CA4CCToCString(the4CC) { ((char*)&the4CC)[0], ((char*)&the4CC)[1], ((char*)&the4CC)[2], ((char*)&the4CC)[3], 0 }
#define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[0]; theCString[1] = ((char*)&the4CC)[1]; theCString[2] = ((char*)&the4CC)[2]; theCString[3] = ((char*)&the4CC)[3]; theCString[4] = 0; }
#else
#define CA4CCToCString(the4CC) { ((char*)&the4CC)[3], ((char*)&the4CC)[2], ((char*)&the4CC)[1], ((char*)&the4CC)[0], 0 }
#define CACopy4CCToCString(theCString, the4CC) { theCString[0] = ((char*)&the4CC)[3]; theCString[1] = ((char*)&the4CC)[2]; theCString[2] = ((char*)&the4CC)[1]; theCString[3] = ((char*)&the4CC)[0]; theCString[4] = 0; }
#endif
// This is a macro that does a sizeof and casts the result to a UInt32. This is useful for all the
// places where -wshorten64-32 catches assigning a sizeof expression to a UInt32.
// For want of a better place to park this, we'll park it here.
#define SizeOf32(X) ((UInt32)sizeof(X))
// This is a macro that does a offsetof and casts the result to a UInt32. This is useful for all the
// places where -wshorten64-32 catches assigning an offsetof expression to a UInt32.
// For want of a better place to park this, we'll park it here.
#define OffsetOf32(X, Y) ((UInt32)offsetof(X, Y))
// This macro casts the expression to a UInt32. It is called out specially to allow us to track casts
// that have been added purely to avert -wshorten64-32 warnings on 64 bit platforms.
// For want of a better place to park this, we'll park it here.
#define ToUInt32(X) ((UInt32)(X))
#define ToSInt32(X) ((SInt32)(X))
#pragma mark Basic Definitions
#if DEBUG || CoreAudio_Debug
// can be used to break into debugger immediately, also see CADebugger
#define BusError() { long* p=NULL; *p=0; }
// basic debugging print routines
#if TARGET_OS_MAC && !TARGET_API_MAC_CARBON
extern void DebugStr(const unsigned char* debuggerMsg);
#define DebugMessage(msg) DebugStr("\p"msg)
#define DebugMessageN1(msg, N1)
#define DebugMessageN2(msg, N1, N2)
#define DebugMessageN3(msg, N1, N2, N3)
#else
#include "CADebugPrintf.h"
#if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
#define FlushRtn ,fflush(DebugPrintfFile)
#else
#define FlushRtn
#endif
#if CoreAudio_ThreadStampMessages
#include <pthread.h>
#include "CAHostTimeBase.h"
#if TARGET_RT_64_BIT
#define DebugPrintfThreadIDFormat "%16p"
#else
#define DebugPrintfThreadIDFormat "%8p"
#endif
#define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " DebugPrintfThreadIDFormat " " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), pthread_self(), ## __VA_ARGS__) FlushRtn
#elif CoreAudio_TimeStampMessages
#include "CAHostTimeBase.h"
#define DebugMsg(inFormat, ...) DebugPrintf("%17qd: " inFormat, CAHostTimeBase::GetCurrentTimeInNanos(), ## __VA_ARGS__) FlushRtn
#else
#define DebugMsg(inFormat, ...) DebugPrintf(inFormat, ## __VA_ARGS__) FlushRtn
#endif
#endif
void DebugPrint(const char *fmt, ...); // can be used like printf
#ifndef DEBUGPRINT
#define DEBUGPRINT(msg) DebugPrint msg // have to double-parenthesize arglist (see Debugging.h)
#endif
#if VERBOSE
#define vprint(msg) DEBUGPRINT(msg)
#else
#define vprint(msg)
#endif
// Original macro keeps its function of turning on and off use of CADebuggerStop() for both asserts and throws.
// For backwards compat, it overrides any setting of the two sub-macros.
#if CoreAudio_StopOnFailure
#include "CADebugger.h"
#undef CoreAudio_StopOnAssert
#define CoreAudio_StopOnAssert 1
#undef CoreAudio_StopOnThrow
#define CoreAudio_StopOnThrow 1
#define STOP CADebuggerStop()
#else
#define STOP
#endif
#if CoreAudio_StopOnAssert
#if !CoreAudio_StopOnFailure
#include "CADebugger.h"
#define STOP
#endif
#define __ASSERT_STOP CADebuggerStop()
#else
#define __ASSERT_STOP
#endif
#if CoreAudio_StopOnThrow
#if !CoreAudio_StopOnFailure
#include "CADebugger.h"
#define STOP
#endif
#define __THROW_STOP CADebuggerStop()
#else
#define __THROW_STOP
#endif
#else
#define DebugMsg(inFormat, ...)
#ifndef DEBUGPRINT
#define DEBUGPRINT(msg)
#endif
#define vprint(msg)
#define STOP
#define __ASSERT_STOP
#define __THROW_STOP
#endif
// Old-style numbered DebugMessage calls are implemented in terms of DebugMsg() now
#define DebugMessage(msg) DebugMsg(msg)
#define DebugMessageN1(msg, N1) DebugMsg(msg, N1)
#define DebugMessageN2(msg, N1, N2) DebugMsg(msg, N1, N2)
#define DebugMessageN3(msg, N1, N2, N3) DebugMsg(msg, N1, N2, N3)
#define DebugMessageN4(msg, N1, N2, N3, N4) DebugMsg(msg, N1, N2, N3, N4)
#define DebugMessageN5(msg, N1, N2, N3, N4, N5) DebugMsg(msg, N1, N2, N3, N4, N5)
#define DebugMessageN6(msg, N1, N2, N3, N4, N5, N6) DebugMsg(msg, N1, N2, N3, N4, N5, N6)
#define DebugMessageN7(msg, N1, N2, N3, N4, N5, N6, N7) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7)
#define DebugMessageN8(msg, N1, N2, N3, N4, N5, N6, N7, N8) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8)
#define DebugMessageN9(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9) DebugMsg(msg, N1, N2, N3, N4, N5, N6, N7, N8, N9)
void LogError(const char *fmt, ...); // writes to syslog (and stderr if debugging)
void LogWarning(const char *fmt, ...); // writes to syslog (and stderr if debugging)
#define NO_ACTION (void)0
#if DEBUG || CoreAudio_Debug
#pragma mark Debug Macros
#define Assert(inCondition, inMessage) \
if(!(inCondition)) \
{ \
DebugMessage(inMessage); \
__ASSERT_STOP; \
}
#define AssertFileLine(inCondition, inMessage) \
if(!(inCondition)) \
{ \
DebugMessageN3("%s, line %d: %s", __FILE__, __LINE__, inMessage); \
__ASSERT_STOP; \
}
#define AssertNoError(inError, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
char __4CC[5] = CA4CCToCString(__Err); \
DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
__ASSERT_STOP; \
} \
}
#define AssertNoKernelError(inError, inMessage) \
{ \
unsigned int __Err = (unsigned int)(inError); \
if(__Err != 0) \
{ \
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
__ASSERT_STOP; \
} \
}
#define AssertNotNULL(inPtr, inMessage) \
{ \
if((inPtr) == NULL) \
{ \
DebugMessage(inMessage); \
__ASSERT_STOP; \
} \
}
#define FailIf(inCondition, inHandler, inMessage) \
if(inCondition) \
{ \
DebugMessage(inMessage); \
STOP; \
goto inHandler; \
}
#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
if(inCondition) \
{ \
DebugMessage(inMessage); \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
if((inPointer) == NULL) \
{ \
DebugMessage(inMessage); \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \
{ \
unsigned int __Err = (inKernelError); \
if(__Err != 0) \
{ \
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#define FailIfError(inError, inAction, inHandler, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
char __4CC[5] = CA4CCToCString(__Err); \
DebugMessageN2(inMessage ", Error: %ld (%s)", (long int)__Err, __4CC); \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#define FailIfNoMessage(inCondition, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
goto inHandler; \
}
#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \
if((inPointer) == NULL) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \
{ \
unsigned int __Err = (inKernelError); \
if(__Err != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#if defined(__cplusplus)
#define Throw(inException) __THROW_STOP; throw (inException)
#define ThrowIf(inCondition, inException, inMessage) \
if(inCondition) \
{ \
DebugMessage(inMessage); \
Throw(inException); \
}
#define ThrowIfNULL(inPointer, inException, inMessage) \
if((inPointer) == NULL) \
{ \
DebugMessage(inMessage); \
Throw(inException); \
}
#define ThrowIfKernelError(inKernelError, inException, inMessage) \
{ \
int __Err = (inKernelError); \
if(__Err != 0) \
{ \
DebugMessageN1(inMessage ", Error: 0x%X", __Err); \
Throw(inException); \
} \
}
#define ThrowIfError(inError, inException, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
char __4CC[5] = CA4CCToCString(__Err); \
DebugMessageN2(inMessage ", Error: %d (%s)", (int)__Err, __4CC); \
Throw(inException); \
} \
}
#if TARGET_OS_WIN32
#define ThrowIfWinError(inError, inException, inMessage) \
{ \
HRESULT __Err = (inError); \
if(FAILED(__Err)) \
{ \
DebugMessageN2(inMessage ", Code: %d, Facility: 0x%X", HRESULT_CODE(__Err), HRESULT_FACILITY(__Err)); \
Throw(inException); \
} \
}
#endif
#define SubclassResponsibility(inMethodName, inException) \
{ \
DebugMessage(inMethodName": Subclasses must implement this method"); \
Throw(inException); \
}
#endif // defined(__cplusplus)
#else
#pragma mark Release Macros
#define Assert(inCondition, inMessage) \
if(!(inCondition)) \
{ \
__ASSERT_STOP; \
}
#define AssertFileLine(inCondition, inMessage) Assert(inCondition, inMessage)
#define AssertNoError(inError, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
__ASSERT_STOP; \
} \
}
#define AssertNoKernelError(inError, inMessage) \
{ \
unsigned int __Err = (unsigned int)(inError); \
if(__Err != 0) \
{ \
__ASSERT_STOP; \
} \
}
#define AssertNotNULL(inPtr, inMessage) \
{ \
if((inPtr) == NULL) \
{ \
__ASSERT_STOP; \
} \
}
#define FailIf(inCondition, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
goto inHandler; \
}
#define FailWithAction(inCondition, inAction, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNULL(inPointer, inAction, inHandler, inMessage) \
if((inPointer) == NULL) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfKernelError(inKernelError, inAction, inHandler, inMessage) \
if((inKernelError) != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfError(inError, inAction, inHandler, inMessage) \
if((inError) != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNoMessage(inCondition, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
goto inHandler; \
}
#define FailWithActionNoMessage(inCondition, inAction, inHandler, inMessage) \
if(inCondition) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfNULLNoMessage(inPointer, inAction, inHandler, inMessage) \
if((inPointer) == NULL) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
}
#define FailIfKernelErrorNoMessage(inKernelError, inAction, inHandler, inMessage) \
{ \
unsigned int __Err = (inKernelError); \
if(__Err != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#define FailIfErrorNoMessage(inError, inAction, inHandler, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
STOP; \
{ inAction; } \
goto inHandler; \
} \
}
#if defined(__cplusplus)
#define Throw(inException) __THROW_STOP; throw (inException)
#define ThrowIf(inCondition, inException, inMessage) \
if(inCondition) \
{ \
Throw(inException); \
}
#define ThrowIfNULL(inPointer, inException, inMessage) \
if((inPointer) == NULL) \
{ \
Throw(inException); \
}
#define ThrowIfKernelError(inKernelError, inException, inMessage) \
{ \
int __Err = (inKernelError); \
if(__Err != 0) \
{ \
Throw(inException); \
} \
}
#define ThrowIfError(inError, inException, inMessage) \
{ \
SInt32 __Err = (inError); \
if(__Err != 0) \
{ \
Throw(inException); \
} \
}
#if TARGET_OS_WIN32
#define ThrowIfWinError(inError, inException, inMessage) \
{ \
HRESULT __Err = (inError); \
if(FAILED(__Err)) \
{ \
Throw(inException); \
} \
}
#endif
#define SubclassResponsibility(inMethodName, inException) \
{ \
Throw(inException); \
}
#endif // defined(__cplusplus)
#endif // DEBUG || CoreAudio_Debug
#endif

+ 0
- 115
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CADebugPrintf.h View File

@@ -1,115 +0,0 @@
/*
File: CADebugPrintf.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !defined(__CADebugPrintf_h__)
#define __CADebugPrintf_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include "CoreAudioTypes.h"
#endif
//=============================================================================
// Macros to redirect debugging output to various logging services
//=============================================================================
//#define CoreAudio_UseSysLog 1
//#define CoreAudio_UseSideFile "/CoreAudio-%d.txt"
#if DEBUG || CoreAudio_Debug
#if TARGET_OS_WIN32
#if defined(__cplusplus)
extern "C"
#endif
extern int CAWin32DebugPrintf(char* inFormat, ...);
#define DebugPrintfRtn CAWin32DebugPrintf
#define DebugPrintfFile
#define DebugPrintfLineEnding "\n"
#define DebugPrintfFileComma
#else
#if CoreAudio_UseSysLog
#include <sys/syslog.h>
#define DebugPrintfRtn syslog
#define DebugPrintfFile LOG_NOTICE
#define DebugPrintfLineEnding ""
#define DebugPrintfFileComma DebugPrintfFile,
#elif defined(CoreAudio_UseSideFile)
#include <stdio.h>
#if defined(__cplusplus)
extern "C"
#endif
void OpenDebugPrintfSideFile();
extern FILE* sDebugPrintfSideFile;
#define DebugPrintfRtn fprintf
#define DebugPrintfFile ((sDebugPrintfSideFile != NULL) ? sDebugPrintfSideFile : stderr)
#define DebugPrintfLineEnding "\n"
#define DebugPrintfFileComma DebugPrintfFile,
#else
#include <stdio.h>
#define DebugPrintfRtn fprintf
#define DebugPrintfFile stderr
#define DebugPrintfLineEnding "\n"
#define DebugPrintfFileComma DebugPrintfFile,
#endif
#endif
#define DebugPrintf(inFormat, ...) DebugPrintfRtn(DebugPrintfFileComma inFormat DebugPrintfLineEnding, ## __VA_ARGS__)
#else
#define DebugPrintfRtn
#define DebugPrintfFile
#define DebugPrintfLineEnding
#define DebugPrintfFileComma
#define DebugPrintf(inFormat, ...)
#endif
#endif

+ 0
- 83
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAException.h View File

@@ -1,83 +0,0 @@
/*
File: CAException.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !defined(__CAException_h__)
#define __CAException_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include "CoreAudioTypes.h"
#endif
//=============================================================================
// CAException
//=============================================================================
class CAException
{
public:
CAException(OSStatus inError) : mError(inError) {}
CAException(const CAException& inException) : mError(inException.mError) {}
CAException& operator=(const CAException& inException) { mError = inException.mError; return *this; }
~CAException() {}
OSStatus GetError() const { return mError; }
protected:
OSStatus mError;
};
#define CATry try{
#define CACatch } catch(...) {}
#define CASwallowException(inExpression) try { inExpression; } catch(...) {}
#endif

+ 0
- 234
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAHostTimeBase.h View File

@@ -1,234 +0,0 @@
/*
File: CAHostTimeBase.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#if !defined(__CAHostTimeBase_h__)
#define __CAHostTimeBase_h__
//=============================================================================
// Includes
//=============================================================================
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
#if TARGET_OS_MAC
#include <mach/mach_time.h>
#include <pthread.h>
#elif TARGET_OS_WIN32
#include <windows.h>
#include "WinPThreadDefs.h"
#else
#error Unsupported operating system
#endif
#include "CADebugPrintf.h"
//=============================================================================
// CAHostTimeBase
//
// This class provides platform independent access to the host's time base.
//=============================================================================
#if CoreAudio_Debug
// #define Log_Host_Time_Base_Parameters 1
// #define Track_Host_TimeBase 1
#endif
class CAHostTimeBase
{
public:
static UInt64 ConvertToNanos(UInt64 inHostTime);
static UInt64 ConvertFromNanos(UInt64 inNanos);
static UInt64 GetTheCurrentTime();
#if TARGET_OS_MAC
static UInt64 GetCurrentTime() { return GetTheCurrentTime(); }
#endif
static UInt64 GetCurrentTimeInNanos();
static Float64 GetFrequency() { pthread_once(&sIsInited, Initialize); return sFrequency; }
static Float64 GetInverseFrequency() { pthread_once(&sIsInited, Initialize); return sInverseFrequency; }
static UInt32 GetMinimumDelta() { pthread_once(&sIsInited, Initialize); return sMinDelta; }
static UInt64 AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
static SInt64 HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime);
static UInt64 MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator);
private:
static void Initialize();
static pthread_once_t sIsInited;
static Float64 sFrequency;
static Float64 sInverseFrequency;
static UInt32 sMinDelta;
static UInt32 sToNanosNumerator;
static UInt32 sToNanosDenominator;
#if Track_Host_TimeBase
static UInt64 sLastTime;
#endif
};
inline UInt64 CAHostTimeBase::GetTheCurrentTime()
{
UInt64 theTime = 0;
#if TARGET_OS_MAC
theTime = mach_absolute_time();
#elif TARGET_OS_WIN32
LARGE_INTEGER theValue;
QueryPerformanceCounter(&theValue);
theTime = *((UInt64*)&theValue);
#endif
#if Track_Host_TimeBase
if(sLastTime != 0)
{
if(theTime <= sLastTime)
{
DebugPrintf("CAHostTimeBase::GetTheCurrentTime: the current time is earlier than the last time, now: %qd, then: %qd", theTime, sLastTime);
}
sLastTime = theTime;
}
else
{
sLastTime = theTime;
}
#endif
return theTime;
}
inline UInt64 CAHostTimeBase::ConvertToNanos(UInt64 inHostTime)
{
pthread_once(&sIsInited, Initialize);
UInt64 theAnswer = MultiplyByRatio(inHostTime, sToNanosNumerator, sToNanosDenominator);
#if CoreAudio_Debug
if(((sToNanosNumerator > sToNanosDenominator) && (theAnswer < inHostTime)) || ((sToNanosDenominator > sToNanosNumerator) && (theAnswer > inHostTime)))
{
DebugPrintf("CAHostTimeBase::ConvertToNanos: The conversion wrapped");
}
#endif
return theAnswer;
}
inline UInt64 CAHostTimeBase::ConvertFromNanos(UInt64 inNanos)
{
pthread_once(&sIsInited, Initialize);
UInt64 theAnswer = MultiplyByRatio(inNanos, sToNanosDenominator, sToNanosNumerator);
#if CoreAudio_Debug
if(((sToNanosDenominator > sToNanosNumerator) && (theAnswer < inNanos)) || ((sToNanosNumerator > sToNanosDenominator) && (theAnswer > inNanos)))
{
DebugPrintf("CAHostTimeBase::ConvertFromNanos: The conversion wrapped");
}
#endif
return theAnswer;
}
inline UInt64 CAHostTimeBase::GetCurrentTimeInNanos()
{
return ConvertToNanos(GetTheCurrentTime());
}
inline UInt64 CAHostTimeBase::AbsoluteHostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
{
UInt64 theAnswer;
if(inStartTime <= inEndTime)
{
theAnswer = inEndTime - inStartTime;
}
else
{
theAnswer = inStartTime - inEndTime;
}
return ConvertToNanos(theAnswer);
}
inline SInt64 CAHostTimeBase::HostDeltaToNanos(UInt64 inStartTime, UInt64 inEndTime)
{
SInt64 theAnswer;
SInt64 theSign = 1;
if(inStartTime <= inEndTime)
{
theAnswer = static_cast<SInt64>(inEndTime - inStartTime);
}
else
{
theAnswer = static_cast<SInt64>(inStartTime - inEndTime);
theSign = -1;
}
return theSign * static_cast<SInt64>(ConvertToNanos(static_cast<UInt64>(theAnswer)));
}
inline UInt64 CAHostTimeBase::MultiplyByRatio(UInt64 inMuliplicand, UInt32 inNumerator, UInt32 inDenominator)
{
#if TARGET_OS_MAC && TARGET_RT_64_BIT
__uint128_t theAnswer = inMuliplicand;
#else
long double theAnswer = inMuliplicand;
#endif
if(inNumerator != inDenominator)
{
theAnswer *= inNumerator;
theAnswer /= inDenominator;
}
return static_cast<UInt64>(theAnswer);
}
#endif

+ 0
- 68
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMath.h View File

@@ -1,68 +0,0 @@
/*
File: CAMath.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAMath_h__
#define __CAMath_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
inline bool fiszero(Float64 f) { return (f == 0.); }
inline bool fiszero(Float32 f) { return (f == 0.f); }
inline bool fnonzero(Float64 f) { return !fiszero(f); }
inline bool fnonzero(Float32 f) { return !fiszero(f); }
inline bool fequal(const Float64 &a, const Float64 &b) { return a == b; }
inline bool fequal(const Float32 &a, const Float32 &b) { return a == b; }
inline bool fnotequal(const Float64 &a, const Float64 &b) { return !fequal(a, b); }
inline bool fnotequal(const Float32 &a, const Float32 &b) { return !fequal(a, b); }
#endif // __CAMath_h__

+ 0
- 345
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.cpp View File

@@ -1,345 +0,0 @@
/*
File: CAMutex.cpp
Abstract: CAMutex.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
//==================================================================================================
// Includes
//==================================================================================================
// Self Include
#include "CAMutex.h"
#if TARGET_OS_MAC
#include <errno.h>
#endif
// PublicUtility Includes
#include "CADebugMacros.h"
#include "CAException.h"
#include "CAHostTimeBase.h"
//==================================================================================================
// Logging
//==================================================================================================
#if CoreAudio_Debug
// #define Log_Ownership 1
// #define Log_Errors 1
// #define Log_LongLatencies 1
// #define LongLatencyThreshholdNS 1000000ULL // nanoseconds
#endif
//==================================================================================================
// CAMutex
//==================================================================================================
CAMutex::CAMutex(const char* inName)
:
mName(inName),
mOwner(0)
{
#if TARGET_OS_MAC
OSStatus theError = pthread_mutex_init(&mMutex, NULL);
ThrowIf(theError != 0, CAException(theError), "CAMutex::CAMutex: Could not init the mutex");
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::CAMutex: creating %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
#elif TARGET_OS_WIN32
mMutex = CreateMutex(NULL, false, NULL);
ThrowIfNULL(mMutex, CAException(GetLastError()), "CAMutex::CAMutex: could not create the mutex.");
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::CAMutex: creating %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
#endif
}
CAMutex::~CAMutex()
{
#if TARGET_OS_MAC
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::~CAMutex: destroying %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
pthread_mutex_destroy(&mMutex);
#elif TARGET_OS_WIN32
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::~CAMutex: destroying %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), mName, mOwner);
#endif
if(mMutex != NULL)
{
CloseHandle(mMutex);
}
#endif
}
bool CAMutex::Lock()
{
bool theAnswer = false;
#if TARGET_OS_MAC
pthread_t theCurrentThread = pthread_self();
if(!pthread_equal(theCurrentThread, mOwner))
{
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p is locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
#if Log_LongLatencies
UInt64 lockTryTime = CAHostTimeBase::GetCurrentTimeInNanos();
#endif
OSStatus theError = pthread_mutex_lock(&mMutex);
ThrowIf(theError != 0, CAException(theError), "CAMutex::Lock: Could not lock the mutex");
mOwner = theCurrentThread;
theAnswer = true;
#if Log_LongLatencies
UInt64 lockAcquireTime = CAHostTimeBase::GetCurrentTimeInNanos();
if (lockAcquireTime - lockTryTime >= LongLatencyThresholdNS)
DebugPrintfRtn(DebugPrintfFileComma "Thread %p took %.6fs to acquire the lock %s\n", theCurrentThread, (lockAcquireTime - lockTryTime) * 1.0e-9 /* nanos to seconds */, mName);
#endif
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Lock: thread %p has locked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
}
#elif TARGET_OS_WIN32
if(mOwner != GetCurrentThreadId())
{
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu is locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
OSStatus theError = WaitForSingleObject(mMutex, INFINITE);
ThrowIfError(theError, CAException(theError), "CAMutex::Lock: could not lock the mutex");
mOwner = GetCurrentThreadId();
theAnswer = true;
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Lock: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
#endif
return theAnswer;
}
void CAMutex::Unlock()
{
#if TARGET_OS_MAC
if(pthread_equal(pthread_self(), mOwner))
{
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p is unlocking %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
mOwner = 0;
OSStatus theError = pthread_mutex_unlock(&mMutex);
ThrowIf(theError != 0, CAException(theError), "CAMutex::Unlock: Could not unlock the mutex");
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Unlock: thread %p has unlocked %s, owner: %p\n", pthread_self(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), pthread_self(), mName, mOwner);
#endif
}
else
{
DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
}
#elif TARGET_OS_WIN32
if(mOwner == GetCurrentThreadId())
{
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu is unlocking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
mOwner = 0;
bool wasReleased = ReleaseMutex(mMutex);
ThrowIf(!wasReleased, CAException(GetLastError()), "CAMutex::Unlock: Could not unlock the mutex");
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Unlock: thread %lu has unlocked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
else
{
DebugMessage("CAMutex::Unlock: A thread is attempting to unlock a Mutex it doesn't own");
}
#endif
}
bool CAMutex::Try(bool& outWasLocked)
{
bool theAnswer = false;
outWasLocked = false;
#if TARGET_OS_MAC
pthread_t theCurrentThread = pthread_self();
if(!pthread_equal(theCurrentThread, mOwner))
{
// this means the current thread doesn't already own the lock
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p is try-locking %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
// go ahead and call trylock to see if we can lock it.
int theError = pthread_mutex_trylock(&mMutex);
if(theError == 0)
{
// return value of 0 means we successfully locked the lock
mOwner = theCurrentThread;
theAnswer = true;
outWasLocked = true;
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p has locked %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
}
else if(theError == EBUSY)
{
// return value of EBUSY means that the lock was already locked by another thread
theAnswer = false;
outWasLocked = false;
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%p %.4f: CAMutex::Try: thread %p failed to lock %s, owner: %p\n", theCurrentThread, ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), theCurrentThread, mName, mOwner);
#endif
}
else
{
// any other return value means something really bad happenned
ThrowIfError(theError, CAException(theError), "CAMutex::Try: call to pthread_mutex_trylock failed");
}
}
else
{
// this means the current thread already owns the lock
theAnswer = true;
outWasLocked = false;
}
#elif TARGET_OS_WIN32
if(mOwner != GetCurrentThreadId())
{
// this means the current thread doesn't own the lock
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu is try-locking %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
// try to acquire the mutex
OSStatus theError = WaitForSingleObject(mMutex, 0);
if(theError == WAIT_OBJECT_0)
{
// this means we successfully locked the lock
mOwner = GetCurrentThreadId();
theAnswer = true;
outWasLocked = true;
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu has locked %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
else if(theError == WAIT_TIMEOUT)
{
// this means that the lock was already locked by another thread
theAnswer = false;
outWasLocked = false;
#if Log_Ownership
DebugPrintfRtn(DebugPrintfFileComma "%lu %.4f: CAMutex::Try: thread %lu failed to lock %s, owner: %lu\n", GetCurrentThreadId(), ((Float64)(CAHostTimeBase::GetCurrentTimeInNanos()) / 1000000.0), GetCurrentThreadId(), mName, mOwner);
#endif
}
else
{
// any other return value means something really bad happenned
ThrowIfError(theError, CAException(GetLastError()), "CAMutex::Try: call to lock the mutex failed");
}
}
else
{
// this means the current thread already owns the lock
theAnswer = true;
outWasLocked = false;
}
#endif
return theAnswer;
}
bool CAMutex::IsFree() const
{
return mOwner == 0;
}
bool CAMutex::IsOwnedByCurrentThread() const
{
bool theAnswer = true;
#if TARGET_OS_MAC
theAnswer = pthread_equal(pthread_self(), mOwner);
#elif TARGET_OS_WIN32
theAnswer = (mOwner == GetCurrentThreadId());
#endif
return theAnswer;
}
CAMutex::Unlocker::Unlocker(CAMutex& inMutex)
: mMutex(inMutex),
mNeedsLock(false)
{
Assert(mMutex.IsOwnedByCurrentThread(), "Major problem: Unlocker attempted to unlock a mutex not owned by the current thread!");
mMutex.Unlock();
mNeedsLock = true;
}
CAMutex::Unlocker::~Unlocker()
{
if(mNeedsLock)
{
mMutex.Lock();
}
}

+ 0
- 163
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAMutex.h View File

@@ -1,163 +0,0 @@
/*
File: CAMutex.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAMutex_h__
#define __CAMutex_h__
//==================================================================================================
// Includes
//==================================================================================================
// System Includes
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#else
#include <CoreAudioTypes.h>
#endif
#if TARGET_OS_MAC
#include <pthread.h>
#elif TARGET_OS_WIN32
#include <windows.h>
#else
#error Unsupported operating system
#endif
//==================================================================================================
// A recursive mutex.
//==================================================================================================
class CAMutex
{
// Construction/Destruction
public:
CAMutex(const char* inName);
virtual ~CAMutex();
// Actions
public:
virtual bool Lock();
virtual void Unlock();
virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not
virtual bool IsFree() const;
virtual bool IsOwnedByCurrentThread() const;
// Implementation
protected:
const char* mName;
#if TARGET_OS_MAC
pthread_t mOwner;
pthread_mutex_t mMutex;
#elif TARGET_OS_WIN32
UInt32 mOwner;
HANDLE mMutex;
#endif
// Helper class to manage taking and releasing recursively
public:
class Locker
{
// Construction/Destruction
public:
Locker(CAMutex& inMutex) : mMutex(&inMutex), mNeedsRelease(false) { mNeedsRelease = mMutex->Lock(); }
Locker(CAMutex* inMutex) : mMutex(inMutex), mNeedsRelease(false) { mNeedsRelease = (mMutex != NULL && mMutex->Lock()); }
// in this case the mutex can be null
~Locker() { if(mNeedsRelease) { mMutex->Unlock(); } }
private:
Locker(const Locker&);
Locker& operator=(const Locker&);
// Implementation
private:
CAMutex* mMutex;
bool mNeedsRelease;
};
// Unlocker
class Unlocker
{
public:
Unlocker(CAMutex& inMutex);
~Unlocker();
private:
CAMutex& mMutex;
bool mNeedsLock;
// Hidden definitions of copy ctor, assignment operator
Unlocker(const Unlocker& copy); // Not implemented
Unlocker& operator=(const Unlocker& copy); // Not implemented
};
// you can use this with Try - if you take the lock in try, pass in the outWasLocked var
class Tryer {
// Construction/Destruction
public:
Tryer (CAMutex &mutex) : mMutex(mutex), mNeedsRelease(false), mHasLock(false) { mHasLock = mMutex.Try (mNeedsRelease); }
~Tryer () { if (mNeedsRelease) mMutex.Unlock(); }
bool HasLock () const { return mHasLock; }
private:
Tryer(const Tryer&);
Tryer& operator=(const Tryer&);
// Implementation
private:
CAMutex & mMutex;
bool mNeedsRelease;
bool mHasLock;
};
};
#endif // __CAMutex_h__

+ 0
- 97
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAReferenceCounted.h View File

@@ -1,97 +0,0 @@
/*
File: CAReferenceCounted.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAReferenceCounted_h__
#define __CAReferenceCounted_h__
#include "CAAtomic.h"
// base class for reference-counted objects
class CAReferenceCounted {
public:
CAReferenceCounted() : mRefCount(1) {}
void retain() { CAAtomicIncrement32(&mRefCount); }
void release()
{
SInt32 rc = CAAtomicDecrement32(&mRefCount);
if (rc == 0) {
releaseObject();
}
}
class Retainer {
public:
Retainer(CAReferenceCounted *obj) : mObject(obj) { mObject->retain(); }
~Retainer() { mObject->release(); }
private:
CAReferenceCounted * mObject;
};
protected:
virtual ~CAReferenceCounted() { }
virtual void releaseObject ()
{
delete this;
}
#if DEBUG
public:
#endif
SInt32 GetReferenceCount() const { return mRefCount; }
private:
SInt32 mRefCount;
CAReferenceCounted(const CAReferenceCounted &a);
CAReferenceCounted &operator=(const CAReferenceCounted &a);
};
#endif // __CAReferenceCounted_h__

+ 0
- 879
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp View File

@@ -1,879 +0,0 @@
/*
File: CAStreamBasicDescription.cpp
Abstract: CAStreamBasicDescription.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "CAStreamBasicDescription.h"
#include "CAMath.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CFByteOrder.h>
#else
#include <CFByteOrder.h>
#endif
#pragma mark This file needs to compile on earlier versions of the OS, so please keep that in mind when editing it
char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize)
{
if (bufsize > 0) {
char *p = writeLocation, *pend = writeLocation + bufsize;
union { UInt32 i; unsigned char str[4]; } u;
unsigned char *q = u.str;
u.i = CFSwapInt32HostToBig(t);
bool hasNonPrint = false;
for (int i = 0; i < 4; ++i) {
if (!(isprint(*q) && *q != '\\')) {
hasNonPrint = true;
break;
}
q++;
}
q = u.str;
if (hasNonPrint)
p += snprintf (p, pend - p, "0x");
else if (p < pend)
*p++ = '\'';
for (int i = 0; i < 4 && p < pend; ++i) {
if (hasNonPrint) {
p += snprintf(p, pend - p, "%02X", *q++);
} else {
*p++ = *q++;
}
}
if (!hasNonPrint && p < pend)
*p++ = '\'';
if (p >= pend) p -= 1;
*p = '\0';
}
return writeLocation;
}
const AudioStreamBasicDescription CAStreamBasicDescription::sEmpty = { 0.0, 0, 0, 0, 0, 0, 0, 0, 0 };
CAStreamBasicDescription::CAStreamBasicDescription()
{
memset (this, 0, sizeof(AudioStreamBasicDescription));
}
CAStreamBasicDescription::CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
{
SetFrom(desc);
}
CAStreamBasicDescription::CAStreamBasicDescription(double inSampleRate, UInt32 inFormatID,
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
UInt32 inBitsPerChannel, UInt32 inFormatFlags)
{
mSampleRate = inSampleRate;
mFormatID = inFormatID;
mBytesPerPacket = inBytesPerPacket;
mFramesPerPacket = inFramesPerPacket;
mBytesPerFrame = inBytesPerFrame;
mChannelsPerFrame = inChannelsPerFrame;
mBitsPerChannel = inBitsPerChannel;
mFormatFlags = inFormatFlags;
mReserved = 0;
}
char *CAStreamBasicDescription::AsString(char *buf, size_t _bufsize, bool brief /*=false*/) const
{
int bufsize = (int)_bufsize; // must be signed to protect against overflow
char *theBuffer = buf;
int nc;
char formatID[24];
CAStringForOSType(mFormatID, formatID, sizeof(formatID));
if (brief) {
CommonPCMFormat com;
bool interleaved;
if (IdentifyCommonPCMFormat(com, &interleaved) && com != kPCMFormatOther) {
const char *desc;
switch (com) {
case kPCMFormatInt16:
desc = "Int16";
break;
case kPCMFormatFixed824:
desc = "Int8.24";
break;
case kPCMFormatFloat32:
desc = "Float32";
break;
case kPCMFormatFloat64:
desc = "Float64";
break;
default:
desc = NULL;
break;
}
if (desc) {
const char *inter ="";
if (mChannelsPerFrame > 1)
inter = !interleaved ? ", non-inter" : ", inter";
snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s%s", (int)mChannelsPerFrame, mSampleRate, desc, inter);
return theBuffer;
}
}
if (mChannelsPerFrame == 0 && mSampleRate == 0.0 && mFormatID == 0) {
snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz", (int)mChannelsPerFrame, mSampleRate);
return theBuffer;
}
}
nc = snprintf(buf, static_cast<size_t>(bufsize), "%2d ch, %6.0f Hz, %s (0x%08X) ", (int)NumberChannels(), mSampleRate, formatID, (int)mFormatFlags);
buf += nc; if ((bufsize -= nc) <= 0) goto exit;
if (mFormatID == kAudioFormatLinearPCM) {
bool isInt = !(mFormatFlags & kLinearPCMFormatFlagIsFloat);
int wordSize = static_cast<int>(SampleWordSize());
const char *endian = (wordSize > 1) ?
((mFormatFlags & kLinearPCMFormatFlagIsBigEndian) ? " big-endian" : " little-endian" ) : "";
const char *sign = isInt ?
((mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) ? " signed" : " unsigned") : "";
const char *floatInt = isInt ? "integer" : "float";
char packed[32];
if (wordSize > 0 && PackednessIsSignificant()) {
if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
snprintf(packed, sizeof(packed), "packed in %d bytes", wordSize);
else
snprintf(packed, sizeof(packed), "unpacked in %d bytes", wordSize);
} else
packed[0] = '\0';
const char *align = (wordSize > 0 && AlignmentIsSignificant()) ?
((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
char bitdepth[20];
int fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
if (fracbits > 0)
snprintf(bitdepth, sizeof(bitdepth), "%d.%d", (int)mBitsPerChannel - fracbits, fracbits);
else
snprintf(bitdepth, sizeof(bitdepth), "%d", (int)mBitsPerChannel);
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%s-bit%s%s %s%s%s%s%s",
bitdepth, endian, sign, floatInt,
commaSpace, packed, align, deinter);
// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
} else if (mFormatID == kAudioFormatAppleLossless) {
int sourceBits = 0;
switch (mFormatFlags)
{
case 1: // kAppleLosslessFormatFlag_16BitSourceData
sourceBits = 16;
break;
case 2: // kAppleLosslessFormatFlag_20BitSourceData
sourceBits = 20;
break;
case 3: // kAppleLosslessFormatFlag_24BitSourceData
sourceBits = 24;
break;
case 4: // kAppleLosslessFormatFlag_32BitSourceData
sourceBits = 32;
break;
}
if (sourceBits)
nc = snprintf(buf, static_cast<size_t>(bufsize), "from %d-bit source, ", sourceBits);
else
nc = snprintf(buf, static_cast<size_t>(bufsize), "from UNKNOWN source bit depth, ");
buf += nc; if ((bufsize -= nc) <= 0) goto exit;
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d frames/packet", (int)mFramesPerPacket);
// buf += nc; if ((bufsize -= nc) <= 0) goto exit;
}
else
/*nc =*/ snprintf(buf, static_cast<size_t>(bufsize), "%d bits/channel, %d bytes/packet, %d frames/packet, %d bytes/frame",
(int)mBitsPerChannel, (int)mBytesPerPacket, (int)mFramesPerPacket, (int)mBytesPerFrame);
exit:
return theBuffer;
}
void CAStreamBasicDescription::NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription)
{
// the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
{
// the canonical linear PCM format
ioDescription.mFormatFlags = kAudioFormatFlagsCanonical;
ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mFramesPerPacket = 1;
ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
}
}
void CAStreamBasicDescription::NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription)
{
// the only thing that changes is to make mixable linear PCM into the canonical linear PCM format
if((ioDescription.mFormatID == kAudioFormatLinearPCM) && ((ioDescription.mFormatFlags & kIsNonMixableFlag) == 0))
{
// the canonical linear PCM format
ioDescription.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
if(inNativeEndian)
{
#if TARGET_RT_BIG_ENDIAN
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
}
else
{
#if TARGET_RT_LITTLE_ENDIAN
ioDescription.mFormatFlags |= kAudioFormatFlagIsBigEndian;
#endif
}
ioDescription.mBytesPerPacket = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mFramesPerPacket = 1;
ioDescription.mBytesPerFrame = SizeOf32(AudioSampleType) * ioDescription.mChannelsPerFrame;
ioDescription.mBitsPerChannel = 8 * SizeOf32(AudioSampleType);
}
}
void CAStreamBasicDescription::ResetFormat(AudioStreamBasicDescription& ioDescription)
{
ioDescription.mSampleRate = 0;
ioDescription.mFormatID = 0;
ioDescription.mBytesPerPacket = 0;
ioDescription.mFramesPerPacket = 0;
ioDescription.mBytesPerFrame = 0;
ioDescription.mChannelsPerFrame = 0;
ioDescription.mBitsPerChannel = 0;
ioDescription.mFormatFlags = 0;
}
void CAStreamBasicDescription::FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription)
{
if(fiszero(ioDescription.mSampleRate))
{
ioDescription.mSampleRate = inTemplateDescription.mSampleRate;
}
if(ioDescription.mFormatID == 0)
{
ioDescription.mFormatID = inTemplateDescription.mFormatID;
}
if(ioDescription.mFormatFlags == 0)
{
ioDescription.mFormatFlags = inTemplateDescription.mFormatFlags;
}
if(ioDescription.mBytesPerPacket == 0)
{
ioDescription.mBytesPerPacket = inTemplateDescription.mBytesPerPacket;
}
if(ioDescription.mFramesPerPacket == 0)
{
ioDescription.mFramesPerPacket = inTemplateDescription.mFramesPerPacket;
}
if(ioDescription.mBytesPerFrame == 0)
{
ioDescription.mBytesPerFrame = inTemplateDescription.mBytesPerFrame;
}
if(ioDescription.mChannelsPerFrame == 0)
{
ioDescription.mChannelsPerFrame = inTemplateDescription.mChannelsPerFrame;
}
if(ioDescription.mBitsPerChannel == 0)
{
ioDescription.mBitsPerChannel = inTemplateDescription.mBitsPerChannel;
}
}
void CAStreamBasicDescription::GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate)
{
if(inIncludeSampleRate)
{
int theCharactersWritten = snprintf(outName, inMaxNameLength, "%.0f ", inDescription.mSampleRate);
outName += theCharactersWritten;
inMaxNameLength -= static_cast<UInt32>(theCharactersWritten);
}
switch(inDescription.mFormatID)
{
case kAudioFormatLinearPCM:
{
const char* theEndianString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
{
#if TARGET_RT_LITTLE_ENDIAN
theEndianString = "Big Endian";
#endif
}
else
{
#if TARGET_RT_BIG_ENDIAN
theEndianString = "Little Endian";
#endif
}
const char* theKindString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
{
theKindString = (inAbbreviate ? "Float" : "Floating Point");
}
else if((inDescription.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
{
theKindString = (inAbbreviate ? "SInt" : "Signed Integer");
}
else
{
theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
}
const char* thePackingString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
{
if((inDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
{
thePackingString = "High";
}
else
{
thePackingString = "Low";
}
}
const char* theMixabilityString = NULL;
if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
{
theMixabilityString = "Mixable";
}
else
{
theMixabilityString = "Unmixable";
}
if(inAbbreviate)
{
if(theEndianString != NULL)
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theEndianString, theKindString, (int)inDescription.mBitsPerChannel);
}
}
else
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s %s%d/%s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, thePackingString, theKindString, (int)inDescription.mBitsPerChannel, theKindString, (int)((inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8));
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Ch %s%d", theMixabilityString, (int)inDescription.mChannelsPerFrame, theKindString, (int)inDescription.mBitsPerChannel);
}
}
}
else
{
if(theEndianString != NULL)
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theEndianString, theKindString);
}
}
else
{
if(thePackingString != NULL)
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s Aligned %s in %d Bits", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString, thePackingString, (int)(inDescription.mBytesPerFrame / inDescription.mChannelsPerFrame) * 8);
}
else
{
snprintf(outName, inMaxNameLength, "%s %d Channel %d Bit %s", theMixabilityString, (int)inDescription.mChannelsPerFrame, (int)inDescription.mBitsPerChannel, theKindString);
}
}
}
}
break;
case kAudioFormatAC3:
strlcpy(outName, "AC-3", sizeof(outName));
break;
case kAudioFormat60958AC3:
strlcpy(outName, "AC-3 for SPDIF", sizeof(outName));
break;
default:
CACopy4CCToCString(outName, inDescription.mFormatID);
break;
};
}
#if CoreAudio_Debug
#include "CALogMacros.h"
void CAStreamBasicDescription::PrintToLog(const AudioStreamBasicDescription& inDesc)
{
PrintFloat (" Sample Rate: ", inDesc.mSampleRate);
Print4CharCode (" Format ID: ", inDesc.mFormatID);
PrintHex (" Format Flags: ", inDesc.mFormatFlags);
PrintInt (" Bytes per Packet: ", inDesc.mBytesPerPacket);
PrintInt (" Frames per Packet: ", inDesc.mFramesPerPacket);
PrintInt (" Bytes per Frame: ", inDesc.mBytesPerFrame);
PrintInt (" Channels per Frame: ", inDesc.mChannelsPerFrame);
PrintInt (" Bits per Channel: ", inDesc.mBitsPerChannel);
}
#endif
bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
{
bool theAnswer = false;
bool isDone = false;
// note that if either side is 0, that field is skipped
// format ID is the first order sort
if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
{
if(x.mFormatID != y.mFormatID)
{
// formats are sorted numerically except that linear
// PCM is always first
if(x.mFormatID == kAudioFormatLinearPCM)
{
theAnswer = true;
}
else if(y.mFormatID == kAudioFormatLinearPCM)
{
theAnswer = false;
}
else
{
theAnswer = x.mFormatID < y.mFormatID;
}
isDone = true;
}
}
// mixable is always better than non-mixable for linear PCM and should be the second order sort item
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
{
if(((x.mFormatFlags & kIsNonMixableFlag) == 0) && ((y.mFormatFlags & kIsNonMixableFlag) != 0))
{
theAnswer = true;
isDone = true;
}
else if(((x.mFormatFlags & kIsNonMixableFlag) != 0) && ((y.mFormatFlags & kIsNonMixableFlag) == 0))
{
theAnswer = false;
isDone = true;
}
}
// floating point vs integer for linear PCM only
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
{
if((x.mFormatFlags & kAudioFormatFlagIsFloat) != (y.mFormatFlags & kAudioFormatFlagIsFloat))
{
// floating point is better than integer
theAnswer = y.mFormatFlags & kAudioFormatFlagIsFloat;
isDone = true;
}
}
// bit depth
if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
{
if(x.mBitsPerChannel != y.mBitsPerChannel)
{
// deeper bit depths are higher quality
theAnswer = x.mBitsPerChannel < y.mBitsPerChannel;
isDone = true;
}
}
// sample rate
if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
{
if(fnotequal(x.mSampleRate, y.mSampleRate))
{
// higher sample rates are higher quality
theAnswer = x.mSampleRate < y.mSampleRate;
isDone = true;
}
}
// number of channels
if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
{
if(x.mChannelsPerFrame != y.mChannelsPerFrame)
{
// more channels is higher quality
theAnswer = x.mChannelsPerFrame < y.mChannelsPerFrame;
//isDone = true;
}
}
return theAnswer;
}
void CAStreamBasicDescription::ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly )
{
// match wildcards
if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0)
{
// Obliterate all flags.
xFlags = yFlags = 0;
return;
}
if (x.mFormatID == kAudioFormatLinearPCM) {
// knock off the all clear flag
xFlags = xFlags & ~kAudioFormatFlagsAreAllClear;
yFlags = yFlags & ~kAudioFormatFlagsAreAllClear;
// if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit.
if (xFlags & yFlags & kAudioFormatFlagIsPacked) {
xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
}
// if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit.
if (xFlags & yFlags & kAudioFormatFlagIsFloat) {
xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
}
// if the bit depth is 8 bits or less and the format is packed, we don't care about endianness
if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
{
xFlags = xFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
}
if((y.mBitsPerChannel <= 8) && ((yFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
{
yFlags = yFlags & ~static_cast<UInt32>(kAudioFormatFlagIsBigEndian);
}
// if the number of channels is 1, we don't care about non-interleavedness
if (x.mChannelsPerFrame == 1 && y.mChannelsPerFrame == 1) {
xFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
yFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsNonInterleaved);
}
if (converterOnly) {
CAStreamBasicDescription cas_x = CAStreamBasicDescription(x);
CAStreamBasicDescription cas_y = CAStreamBasicDescription(y);
if (!cas_x.PackednessIsSignificant() && !cas_y.PackednessIsSignificant()) {
xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsPacked);
}
if (!cas_x.AlignmentIsSignificant() && !cas_y.AlignmentIsSignificant()) {
xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsAlignedHigh);
}
// We don't care about whether the streams are mixable in this case
xFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
yFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonMixable);
}
}
}
static bool MatchFormatFlags(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
{
UInt32 xFlags = x.mFormatFlags;
UInt32 yFlags = y.mFormatFlags;
CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, false);
return xFlags == yFlags;
}
bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y)
{
// the semantics for equality are:
// 1) Values must match exactly -- except for PCM format flags, see above.
// 2) wildcard's are ignored in the comparison
#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
return
// check all but the format flags
CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
// check the format flags
&& MatchFormatFlags(x, y);
}
bool CAStreamBasicDescription::FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
{
return
// check the sample rate
(fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
// check the format ids
&& MATCH(mFormatID)
// check the bytes per packet
&& MATCH(mBytesPerPacket)
// check the frames per packet
&& MATCH(mFramesPerPacket)
// check the bytes per frame
&& MATCH(mBytesPerFrame)
// check the channels per frame
&& MATCH(mChannelsPerFrame)
// check the channels per frame
&& MATCH(mBitsPerChannel) ;
}
bool CAStreamBasicDescription::IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards) const
{
if (interpretingWildcards)
return *this == other;
return memcmp(this, &other, offsetof(AudioStreamBasicDescription, mReserved)) == 0;
}
bool CAStreamBasicDescription::IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y)
{
UInt32 xFlags = x.mFormatFlags, yFlags = y.mFormatFlags;
CAStreamBasicDescription::ModifyFormatFlagsForMatching(x, y, xFlags, yFlags, true);
return
// check all but the format flags
CAStreamBasicDescription::FlagIndependentEquivalence(x, y)
// check the format flags with converter focus
&& (xFlags == yFlags);
}
bool SanityCheck(const AudioStreamBasicDescription& x)
{
// This function returns false if there are sufficiently insane values in any field.
// It is very conservative so even some very unlikely values will pass.
// This is just meant to catch the case where the data from a file is corrupted.
return
(x.mSampleRate >= 0.)
&& (x.mSampleRate < 3e6) // SACD sample rate is 2.8224 MHz
&& (x.mBytesPerPacket < 1000000)
&& (x.mFramesPerPacket < 1000000)
&& (x.mBytesPerFrame < 1000000)
&& (x.mChannelsPerFrame <= 1024)
&& (x.mBitsPerChannel <= 1024)
&& (x.mFormatID != 0)
&& !(x.mFormatID == kAudioFormatLinearPCM && (x.mFramesPerPacket != 1 || x.mBytesPerPacket != x.mBytesPerFrame));
}
bool CAStreamBasicDescription::FromText(const char *inTextDesc, AudioStreamBasicDescription &fmt)
{
const char *p = inTextDesc;
memset(&fmt, 0, sizeof(fmt));
bool isPCM = true; // until proven otherwise
UInt32 pcmFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
if (p[0] == '-') // previously we required a leading dash on PCM formats
++p;
if (p[0] == 'B' && p[1] == 'E') {
pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
p += 2;
} else if (p[0] == 'L' && p[1] == 'E') {
p += 2;
} else {
// default is native-endian
#if TARGET_RT_BIG_ENDIAN
pcmFlags |= kLinearPCMFormatFlagIsBigEndian;
#endif
}
if (p[0] == 'F') {
pcmFlags = (pcmFlags & ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger)) | kAudioFormatFlagIsFloat;
++p;
} else {
if (p[0] == 'U') {
pcmFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsSignedInteger);
++p;
}
if (p[0] == 'I')
++p;
else {
// it's not PCM; presumably some other format (NOT VALIDATED; use AudioFormat for that)
isPCM = false;
p = inTextDesc; // go back to the beginning
char buf[4] = { ' ',' ',' ',' ' };
for (int i = 0; i < 4; ++i) {
if (*p != '\\') {
if ((buf[i] = *p++) == '\0') {
// special-case for 'aac'
if (i != 3) return false;
--p; // keep pointing at the terminating null
buf[i] = ' ';
break;
}
} else {
// "\xNN" is a hex byte
if (*++p != 'x') return false;
int x;
if (sscanf(++p, "%02X", &x) != 1) return false;
buf[i] = static_cast<char>(x);
p += 2;
}
}
if (strchr("-@/#", buf[3])) {
// further special-casing for 'aac'
buf[3] = ' ';
--p;
}
memcpy(&fmt.mFormatID, buf, 4);
fmt.mFormatID = CFSwapInt32BigToHost(fmt.mFormatID);
}
}
if (isPCM) {
fmt.mFormatID = kAudioFormatLinearPCM;
fmt.mFormatFlags = pcmFlags;
fmt.mFramesPerPacket = 1;
fmt.mChannelsPerFrame = 1;
UInt32 bitdepth = 0, fracbits = 0;
while (isdigit(*p))
bitdepth = 10 * bitdepth + static_cast<UInt32>(*p++ - '0');
if (*p == '.') {
++p;
if (!isdigit(*p)) {
fprintf(stderr, "Expected fractional bits following '.'\n");
goto Bail;
}
while (isdigit(*p))
fracbits = 10 * fracbits + static_cast<UInt32>(*p++ - '0');
bitdepth += fracbits;
fmt.mFormatFlags |= (fracbits << kLinearPCMFormatFlagsSampleFractionShift);
}
fmt.mBitsPerChannel = bitdepth;
fmt.mBytesPerPacket = fmt.mBytesPerFrame = (bitdepth + 7) / 8;
if (bitdepth & 7) {
// assume unpacked. (packed odd bit depths are describable but not supported in AudioConverter.)
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
// alignment matters; default to high-aligned. use ':L_' for low.
fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
}
}
if (*p == '@') {
++p;
while (isdigit(*p))
fmt.mSampleRate = 10 * fmt.mSampleRate + (*p++ - '0');
}
if (*p == '/') {
UInt32 flags = 0;
while (true) {
char c = *++p;
if (c >= '0' && c <= '9')
flags = (flags << 4) | static_cast<UInt32>(c - '0');
else if (c >= 'A' && c <= 'F')
flags = (flags << 4) | static_cast<UInt32>(c - 'A' + 10);
else if (c >= 'a' && c <= 'f')
flags = (flags << 4) | static_cast<UInt32>(c - 'a' + 10);
else break;
}
fmt.mFormatFlags = flags;
}
if (*p == '#') {
++p;
while (isdigit(*p))
fmt.mFramesPerPacket = 10 * fmt.mFramesPerPacket + static_cast<UInt32>(*p++ - '0');
}
if (*p == ':') {
++p;
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsPacked);
if (*p == 'L')
fmt.mFormatFlags &= ~static_cast<UInt32>(kLinearPCMFormatFlagIsAlignedHigh);
else if (*p == 'H')
fmt.mFormatFlags |= kLinearPCMFormatFlagIsAlignedHigh;
else
goto Bail;
++p;
UInt32 bytesPerFrame = 0;
while (isdigit(*p))
bytesPerFrame = 10 * bytesPerFrame + static_cast<UInt32>(*p++ - '0');
fmt.mBytesPerFrame = fmt.mBytesPerPacket = bytesPerFrame;
}
if (*p == ',') {
++p;
int ch = 0;
while (isdigit(*p))
ch = 10 * ch + (*p++ - '0');
fmt.mChannelsPerFrame = static_cast<UInt32>(ch);
if (*p == 'D') {
++p;
if (fmt.mFormatID != kAudioFormatLinearPCM) {
fprintf(stderr, "non-interleaved flag invalid for non-PCM formats\n");
goto Bail;
}
fmt.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
} else {
if (*p == 'I') ++p; // default
if (fmt.mFormatID == kAudioFormatLinearPCM)
fmt.mBytesPerPacket = fmt.mBytesPerFrame *= static_cast<UInt32>(ch);
}
}
if (*p != '\0') {
fprintf(stderr, "extra characters at end of format string: %s\n", p);
goto Bail;
}
return true;
Bail:
fprintf(stderr, "Invalid format string: %s\n", inTextDesc);
fprintf(stderr, "Syntax of format strings is: \n");
return false;
}
const char *CAStreamBasicDescription::sTextParsingUsageString =
"format[@sample_rate_hz][/format_flags][#frames_per_packet][:LHbytesPerFrame][,channelsDI].\n"
"Format for PCM is [-][BE|LE]{F|I|UI}{bitdepth}; else a 4-char format code (e.g. aac, alac).\n";

+ 0
- 424
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAStreamBasicDescription.h View File

@@ -1,424 +0,0 @@
/*
File: CAStreamBasicDescription.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAStreamBasicDescription_h__
#define __CAStreamBasicDescription_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreFoundation/CoreFoundation.h>
#else
#include "CoreAudioTypes.h"
#include "CoreFoundation.h"
#endif
#include "CADebugMacros.h"
#include <string.h> // for memset, memcpy
#include <stdio.h> // for FILE *
#pragma mark This file needs to compile on more earlier versions of the OS, so please keep that in mind when editing it
extern char *CAStringForOSType (OSType t, char *writeLocation, size_t bufsize);
// define Leopard specific symbols for backward compatibility if applicable
#if COREAUDIOTYPES_VERSION < 1050
typedef Float32 AudioSampleType;
enum { kAudioFormatFlagsCanonical = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked };
#endif
#if COREAUDIOTYPES_VERSION < 1051
typedef Float32 AudioUnitSampleType;
enum {
kLinearPCMFormatFlagsSampleFractionShift = 7,
kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),
};
#endif
// define the IsMixable format flag for all versions of the system
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
enum { kIsNonMixableFlag = kAudioFormatFlagIsNonMixable };
#else
enum { kIsNonMixableFlag = (1L << 6) };
#endif
//=============================================================================
// CAStreamBasicDescription
//
// This is a wrapper class for the AudioStreamBasicDescription struct.
// It adds a number of convenience routines, but otherwise adds nothing
// to the footprint of the original struct.
//=============================================================================
class CAStreamBasicDescription :
public AudioStreamBasicDescription
{
// Constants
public:
static const AudioStreamBasicDescription sEmpty;
enum CommonPCMFormat {
kPCMFormatOther = 0,
kPCMFormatFloat32 = 1,
kPCMFormatInt16 = 2,
kPCMFormatFixed824 = 3,
kPCMFormatFloat64 = 4
};
// Construction/Destruction
public:
CAStreamBasicDescription();
CAStreamBasicDescription(const AudioStreamBasicDescription &desc);
CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID,
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
UInt32 inBitsPerChannel, UInt32 inFormatFlags);
CAStreamBasicDescription( double inSampleRate, UInt32 inNumChannels, CommonPCMFormat pcmf, bool inIsInterleaved) {
unsigned wordsize;
mSampleRate = inSampleRate;
mFormatID = kAudioFormatLinearPCM;
mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
mFramesPerPacket = 1;
mChannelsPerFrame = inNumChannels;
mBytesPerFrame = mBytesPerPacket = 0;
mReserved = 0;
switch (pcmf) {
default:
return;
case kPCMFormatFloat32:
wordsize = 4;
mFormatFlags |= kAudioFormatFlagIsFloat;
break;
case kPCMFormatFloat64:
wordsize = 8;
mFormatFlags |= kAudioFormatFlagIsFloat;
break;
case kPCMFormatInt16:
wordsize = 2;
mFormatFlags |= kAudioFormatFlagIsSignedInteger;
break;
case kPCMFormatFixed824:
wordsize = 4;
mFormatFlags |= kAudioFormatFlagIsSignedInteger | (24 << kLinearPCMFormatFlagsSampleFractionShift);
break;
}
mBitsPerChannel = wordsize * 8;
if (inIsInterleaved)
mBytesPerFrame = mBytesPerPacket = wordsize * inNumChannels;
else {
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
mBytesPerFrame = mBytesPerPacket = wordsize;
}
}
// Assignment
CAStreamBasicDescription& operator=(const AudioStreamBasicDescription& v) { SetFrom(v); return *this; }
void SetFrom(const AudioStreamBasicDescription &desc)
{
memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
}
bool FromText(const char *inTextDesc) { return FromText(inTextDesc, *this); }
static bool FromText(const char *inTextDesc, AudioStreamBasicDescription &outDesc);
// return true if parsing was successful
static const char *sTextParsingUsageString;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// interrogation
bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
bool PackednessIsSignificant() const
{
Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
return (SampleWordSize() << 3) != mBitsPerChannel;
}
bool AlignmentIsSignificant() const
{
return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
}
bool IsInterleaved() const
{
return !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
}
bool IsSignedInteger() const
{
return IsPCM() && (mFormatFlags & kAudioFormatFlagIsSignedInteger);
}
bool IsFloat() const
{
return IsPCM() && (mFormatFlags & kAudioFormatFlagIsFloat);
}
bool IsNativeEndian() const
{
return (mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian;
}
// for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
UInt32 NumberChannels() const { return mChannelsPerFrame; }
UInt32 SampleWordSize() const {
return (mBytesPerFrame > 0 && NumberInterleavedChannels()) ? mBytesPerFrame / NumberInterleavedChannels() : 0;
}
UInt32 FramesToBytes(UInt32 nframes) const { return nframes * mBytesPerFrame; }
UInt32 BytesToFrames(UInt32 nbytes) const {
Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
return nbytes / mBytesPerFrame;
}
bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
{
return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
}
bool IdentifyCommonPCMFormat(CommonPCMFormat &outFormat, bool *outIsInterleaved=NULL) const
{ // return true if it's a valid PCM format.
outFormat = kPCMFormatOther;
// trap out patently invalid formats.
if (mFormatID != kAudioFormatLinearPCM || mFramesPerPacket != 1 || mBytesPerFrame != mBytesPerPacket || mBitsPerChannel/8 > mBytesPerFrame || mChannelsPerFrame == 0)
return false;
bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
if (outIsInterleaved != NULL) *outIsInterleaved = interleaved;
unsigned wordsize = mBytesPerFrame;
if (interleaved) {
if (wordsize % mChannelsPerFrame != 0) return false;
wordsize /= mChannelsPerFrame;
}
if ((mFormatFlags & kAudioFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian
&& wordsize * 8 == mBitsPerChannel) {
// packed and native endian, good
if (mFormatFlags & kLinearPCMFormatFlagIsFloat) {
// float: reject nonsense bits
if (mFormatFlags & (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagsSampleFractionMask))
return false;
if (wordsize == 4)
outFormat = kPCMFormatFloat32;
if (wordsize == 8)
outFormat = kPCMFormatFloat64;
} else if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) {
// signed int
unsigned fracbits = (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) >> kLinearPCMFormatFlagsSampleFractionShift;
if (wordsize == 4 && fracbits == 24)
outFormat = kPCMFormatFixed824;
else if (wordsize == 2 && fracbits == 0)
outFormat = kPCMFormatInt16;
}
}
return true;
}
bool IsCommonFloat32(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat32;
}
bool IsCommonFloat64(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFloat64;
}
bool IsCommonFixed824(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatFixed824;
}
bool IsCommonInt16(bool *outIsInterleaved=NULL) const {
CommonPCMFormat fmt;
return IdentifyCommonPCMFormat(fmt, outIsInterleaved) && fmt == kPCMFormatInt16;
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// manipulation
void SetCanonical(UInt32 nChannels, bool interleaved)
// note: leaves sample rate untouched
{
mFormatID = kAudioFormatLinearPCM;
UInt32 sampleSize = SizeOf32(AudioSampleType);
mFormatFlags = kAudioFormatFlagsCanonical;
mBitsPerChannel = 8 * sampleSize;
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
if (interleaved)
mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
else {
mBytesPerPacket = mBytesPerFrame = sampleSize;
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
bool IsCanonical() const
{
if (mFormatID != kAudioFormatLinearPCM) return false;
UInt32 reqFormatFlags;
UInt32 flagsMask = (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagsSampleFractionMask);
bool interleaved = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) == 0;
unsigned sampleSize = SizeOf32(AudioSampleType);
reqFormatFlags = kAudioFormatFlagsCanonical;
UInt32 reqFrameSize = interleaved ? (mChannelsPerFrame * sampleSize) : sampleSize;
return ((mFormatFlags & flagsMask) == reqFormatFlags
&& mBitsPerChannel == 8 * sampleSize
&& mFramesPerPacket == 1
&& mBytesPerFrame == reqFrameSize
&& mBytesPerPacket == reqFrameSize);
}
void SetAUCanonical(UInt32 nChannels, bool interleaved)
{
mFormatID = kAudioFormatLinearPCM;
#if CA_PREFER_FIXED_POINT
mFormatFlags = kAudioFormatFlagsCanonical | (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift);
#else
mFormatFlags = kAudioFormatFlagsCanonical;
#endif
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
mBitsPerChannel = 8 * SizeOf32(AudioUnitSampleType);
if (interleaved)
mBytesPerPacket = mBytesPerFrame = nChannels * SizeOf32(AudioUnitSampleType);
else {
mBytesPerPacket = mBytesPerFrame = SizeOf32(AudioUnitSampleType);
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
// alter an existing format
{
Assert(IsPCM(), "ChangeNumberChannels only works for PCM formats");
UInt32 wordSize = SampleWordSize(); // get this before changing ANYTHING
if (wordSize == 0)
wordSize = (mBitsPerChannel + 7) / 8;
mChannelsPerFrame = nChannels;
mFramesPerPacket = 1;
if (interleaved) {
mBytesPerPacket = mBytesPerFrame = nChannels * wordSize;
mFormatFlags &= ~static_cast<UInt32>(kAudioFormatFlagIsNonInterleaved);
} else {
mBytesPerPacket = mBytesPerFrame = wordSize;
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// other
bool IsEqual(const AudioStreamBasicDescription &other, bool interpretingWildcards=true) const;
static bool FlagIndependentEquivalence(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
static bool IsFunctionallyEquivalent(const AudioStreamBasicDescription &x, const AudioStreamBasicDescription &y);
void Print() const {
Print (stdout);
}
void Print(FILE* file) const {
PrintFormat (file, "", "AudioStreamBasicDescription:");
}
void PrintFormat(FILE *f, const char *indent, const char *name) const {
char buf[256];
fprintf(f, "%s%s %s\n", indent, name, AsString(buf, sizeof(buf)));
}
void PrintFormat2(FILE *f, const char *indent, const char *name) const { // no trailing newline
char buf[256];
fprintf(f, "%s%s %s", indent, name, AsString(buf, sizeof(buf)));
}
char * AsString(char *buf, size_t bufsize, bool brief=false) const;
static void Print (const AudioStreamBasicDescription &inDesc)
{
CAStreamBasicDescription desc(inDesc);
desc.Print ();
}
OSStatus Save(CFPropertyListRef *outData) const;
OSStatus Restore(CFPropertyListRef &inData);
// Operations
static bool IsMixable(const AudioStreamBasicDescription& inDescription) { return (inDescription.mFormatID == kAudioFormatLinearPCM) && ((inDescription.mFormatFlags & kIsNonMixableFlag) == 0); }
static void NormalizeLinearPCMFormat(AudioStreamBasicDescription& ioDescription);
static void NormalizeLinearPCMFormat(bool inNativeEndian, AudioStreamBasicDescription& ioDescription);
static void ResetFormat(AudioStreamBasicDescription& ioDescription);
static void FillOutFormat(AudioStreamBasicDescription& ioDescription, const AudioStreamBasicDescription& inTemplateDescription);
static void GetSimpleName(const AudioStreamBasicDescription& inDescription, char* outName, UInt32 inMaxNameLength, bool inAbbreviate, bool inIncludeSampleRate = false);
static void ModifyFormatFlagsForMatching(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y, UInt32& xFlags, UInt32& yFlags, bool converterOnly);
#if CoreAudio_Debug
static void PrintToLog(const AudioStreamBasicDescription& inDesc);
#endif
};
bool operator<(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
bool operator==(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y);
#if TARGET_OS_MAC || (TARGET_OS_WIN32 && (_MSC_VER > 600))
inline bool operator!=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x == y); }
inline bool operator<=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return (x < y) || (x == y); }
inline bool operator>=(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !(x < y); }
inline bool operator>(const AudioStreamBasicDescription& x, const AudioStreamBasicDescription& y) { return !((x < y) || (x == y)); }
#endif
bool SanityCheck(const AudioStreamBasicDescription& x);
#endif // __CAStreamBasicDescription_h__

+ 0
- 233
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAThreadSafeList.h View File

@@ -1,233 +0,0 @@
/*
File: CAThreadSafeList.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAThreadSafeList_h__
#define __CAThreadSafeList_h__
#include "CAAtomicStack.h"
// linked list of T's
// T must define operator ==
template <class T>
class TThreadSafeList {
private:
enum EEventType { kAdd, kRemove, kClear };
class Node {
public:
Node * mNext;
EEventType mEventType;
T mObject;
Node *& next() { return mNext; }
};
public:
class iterator {
public:
iterator() { }
iterator(Node *n) : mNode(n) { }
bool operator == (const iterator &other) const { return this->mNode == other.mNode; }
bool operator != (const iterator &other) const { return this->mNode != other.mNode; }
T & operator * () const { return mNode->mObject; }
iterator & operator ++ () { mNode = mNode->next(); return *this; } // preincrement
iterator operator ++ (int) { iterator tmp = *this; mNode = mNode->next(); return tmp; } // postincrement
private:
Node * mNode;
};
TThreadSafeList() { }
~TThreadSafeList()
{
mActiveList.free_all();
mPendingList.free_all();
mFreeList.free_all();
}
// These may be called on any thread
void deferred_add(const T &obj) // can be called on any thread
{
Node *node = AllocNode();
node->mEventType = kAdd;
node->mObject = obj;
mPendingList.push_atomic(node);
//mPendingList.dump("pending after add");
}
void deferred_remove(const T &obj) // can be called on any thread
{
Node *node = AllocNode();
node->mEventType = kRemove;
node->mObject = obj;
mPendingList.push_atomic(node);
//mPendingList.dump("pending after remove");
}
void deferred_clear() // can be called on any thread
{
Node *node = AllocNode();
node->mEventType = kClear;
mPendingList.push_atomic(node);
}
// These must be called from only one thread
void update() // must only be called from one thread
{
NodeStack reversed;
Node *event, *node, *next;
bool workDone = false;
// reverse the events so they are in order
event = mPendingList.pop_all();
while (event != NULL) {
next = event->mNext;
reversed.push_NA(event);
event = next;
workDone = true;
}
if (workDone) {
//reversed.dump("pending popped");
//mActiveList.dump("active before update");
// now process them
while ((event = reversed.pop_NA()) != NULL) {
switch (event->mEventType) {
case kAdd:
{
Node **pnode;
bool needToInsert = true;
for (pnode = mActiveList.phead(); *pnode != NULL; pnode = &node->mNext) {
node = *pnode;
if (node->mObject == event->mObject) {
//printf("already active!!!\n");
FreeNode(event);
needToInsert = false;
break;
}
}
if (needToInsert) {
// link the new event in at the end of the active list
*pnode = event;
event->mNext = NULL;
}
}
break;
case kRemove:
// find matching node in the active list, remove it
for (Node **pnode = mActiveList.phead(); *pnode != NULL; ) {
node = *pnode;
if (node->mObject == event->mObject) {
*pnode = node->mNext; // remove from linked list
FreeNode(node);
break;
}
pnode = &node->mNext;
}
// dispose the request node
FreeNode(event);
break;
case kClear:
for (node = mActiveList.head(); node != NULL; ) {
next = node->mNext;
FreeNode(node);
node = next;
}
FreeNode(event);
break;
default:
//printf("invalid node type %d!\n", event->mEventType);
break;
}
}
//mActiveList.dump("active after update");
}
}
iterator begin() const {
//mActiveList.dump("active at begin");
return iterator(mActiveList.head());
}
iterator end() const { return iterator(NULL); }
private:
Node * AllocNode()
{
Node *node = mFreeList.pop_atomic();
if (node == NULL)
node = (Node *)CA_malloc(sizeof(Node));
return node;
}
void FreeNode(Node *node)
{
mFreeList.push_atomic(node);
}
private:
class NodeStack : public TAtomicStack<Node> {
public:
void free_all() {
Node *node;
while ((node = this->pop_NA()) != NULL)
free(node);
}
Node ** phead() { return &this->mHead; }
Node * head() const { return this->mHead; }
};
NodeStack mActiveList; // what's actually in the container - only accessed on one thread
NodeStack mPendingList; // add or remove requests - threadsafe
NodeStack mFreeList; // free nodes for reuse - threadsafe
};
#endif // __CAThreadSafeList_h__

+ 0
- 194
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.cpp View File

@@ -1,194 +0,0 @@
/*
File: CAVectorUnit.cpp
Abstract: CAVectorUnit.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "CAVectorUnit.h"
#if !TARGET_OS_WIN32
#include <sys/sysctl.h>
#elif HAS_IPP
#include "ippdefs.h"
#include "ippcore.h"
#endif
int gCAVectorUnitType = kVecUninitialized;
#if TARGET_OS_WIN32
// Use cpuid to check if SSE2 is available.
// Before calling this function make sure cpuid is available
static SInt32 IsSSE2Available()
{
int return_value;
{
int r_edx;
_asm
{
mov eax, 0x01
cpuid
mov r_edx, edx
}
return_value = (r_edx >> 26) & 0x1;
}
return return_value;
}
// Use cpuid to check if SSE3 is available.
// Before calling this function make sure cpuid is available
static SInt32 IsSSE3Available()
{
SInt32 return_value;
{
SInt32 r_ecx;
_asm
{
mov eax, 0x01
cpuid
mov r_ecx, ecx
}
return_value = r_ecx & 0x1;
}
return return_value;
}
// Return true if the cpuid instruction is available.
// The cpuid instruction is available if bit 21 in the EFLAGS register can be changed
// This function may not work on Intel CPUs prior to Pentium (didn't test)
static bool IsCpuidAvailable()
{
SInt32 return_value = 0x0;
_asm{
pushfd ; //push original EFLAGS
pop eax ; //get original EFLAGS
mov ecx, eax ; //save original EFLAGS
xor eax, 200000h ; //flip ID bit in EFLAGS
push eax ; //save new EFLAGS value on stack
popfd ; //replace current EFLAGS value
pushfd ; //get new EFLAGS
pop eax ; //store new EFLAGS in EAX
xor eax, ecx ;
je end_cpuid_identify ; //can't toggle ID bit
mov return_value, 0x1;
end_cpuid_identify:
nop;
}
return return_value;
}
#endif
SInt32 CAVectorUnit_Examine()
{
int result = kVecNone;
#if TARGET_OS_WIN32
#if HAS_IPP
// Initialize the static IPP library! This needs to be done before
// any IPP function calls, otherwise we may have a performance penalty
int status = ippStaticInit();
if ( status == ippStsNonIntelCpu )
{
IppCpuType cpuType = ippGetCpuType();
if ( cpuType >= ippCpuSSE || cpuType <= ippCpuSSE42 )
ippStaticInitCpu( cpuType );
}
#endif
{
// On Windows we use cpuid to detect the vector unit because it works on Intel and AMD.
// The IPP library does not detect SSE on AMD processors.
if (IsCpuidAvailable())
{
if(IsSSE3Available())
{
result = kVecSSE3;
}
else if(IsSSE2Available())
{
result = kVecSSE2;
}
}
}
#elif TARGET_OS_MAC
#if DEBUG
if (getenv("CA_NoVector")) {
fprintf(stderr, "CA_NoVector set; Vector unit optimized routines will be bypassed\n");
return result;
}
else
#endif
{
#if (TARGET_CPU_PPC || TARGET_CPU_PPC64)
int sels[2] = { CTL_HW, HW_VECTORUNIT };
int vType = 0; //0 == scalar only
size_t length = sizeof(vType);
int error = sysctl(sels, 2, &vType, &length, NULL, 0);
if (!error && vType > 0)
result = kVecAltivec;
#elif (TARGET_CPU_X86 || TARGET_CPU_X86_64)
static const struct { const char* kName; const int kVectype; } kStringVectypes[] = {
{ "hw.optional.avx1_0", kVecAVX1 }, { "hw.optional.sse3", kVecSSE3 }, { "hw.optional.sse2", kVecSSE2 }
};
static const size_t kNumStringVectypes = sizeof(kStringVectypes)/sizeof(kStringVectypes[0]);
int i = 0, answer = 0;
while(i != kNumStringVectypes)
{
size_t length = sizeof(answer);
int error = sysctlbyname(kStringVectypes[i].kName, &answer, &length, NULL, 0);
if (!error && answer)
{
result = kStringVectypes[i].kVectype;
break;
}
++i;
};
#elif CA_ARM_NEON
result = kVecNeon;
#endif
}
#endif
gCAVectorUnitType = result;
return result;
}

+ 0
- 101
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnit.h View File

@@ -1,101 +0,0 @@
/*
File: CAVectorUnit.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAVectorUnit_h__
#define __CAVectorUnit_h__
#include <TargetConditionals.h>
#include "CAVectorUnitTypes.h"
#include <stdlib.h>
#include <stdio.h>
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CFBase.h>
#else
#include "CFBase.h"
#endif
// Unify checks for vector units.
// Allow setting an environment variable "CA_NoVector" to turn off vectorized code at runtime (very useful for performance testing).
extern int gCAVectorUnitType;
#ifdef __cplusplus
extern "C" {
#endif
extern SInt32 CAVectorUnit_Examine(); // expensive. use GetType() for lazy initialization and caching.
static inline SInt32 CAVectorUnit_GetType()
{
int x = gCAVectorUnitType;
return (x != kVecUninitialized) ? x : CAVectorUnit_Examine();
}
static inline Boolean CAVectorUnit_HasVectorUnit()
{
return CAVectorUnit_GetType() > kVecNone;
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
class CAVectorUnit {
public:
static SInt32 GetVectorUnitType() { return CAVectorUnit_GetType(); }
static bool HasVectorUnit() { return GetVectorUnitType() > kVecNone; }
static bool HasAltivec() { return GetVectorUnitType() == kVecAltivec; }
static bool HasSSE2() { return GetVectorUnitType() >= kVecSSE2; }
static bool HasSSE3() { return GetVectorUnitType() >= kVecSSE3; }
static bool HasAVX1() { return GetVectorUnitType() >= kVecAVX1; }
static bool HasNeon() { return GetVectorUnitType() == kVecNeon; }
};
#endif
#endif // __CAVectorUnit_h__

+ 0
- 60
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAVectorUnitTypes.h View File

@@ -1,60 +0,0 @@
/*
File: CAVectorUnitTypes.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAVectorUnitTypes_h__
#define __CAVectorUnitTypes_h__
enum {
kVecUninitialized = -1,
kVecNone = 0,
kVecAltivec = 1,
kVecSSE2 = 100,
kVecSSE3 = 101,
kVecAVX1 = 110,
kVecNeon = 200
};
#endif

+ 0
- 361
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/CAXException.h View File

@@ -1,361 +0,0 @@
/*
File: CAXException.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __CAXException_h__
#define __CAXException_h__
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreFoundation/CoreFoundation.h>
#else
#include <ConditionalMacros.h>
#include <CoreFoundation.h>
#endif
#include "CADebugMacros.h"
#include <ctype.h>
//#include <stdio.h>
#include <string.h>
class CAX4CCString {
public:
CAX4CCString(OSStatus error) {
// see if it appears to be a 4-char-code
UInt32 beErr = CFSwapInt32HostToBig(error);
char *str = mStr;
memcpy(str + 1, &beErr, 4);
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) {
str[0] = str[5] = '\'';
str[6] = '\0';
} else if (error > -200000 && error < 200000)
// no, format it as an integer
snprintf(str, sizeof(mStr), "%d", (int)error);
else
snprintf(str, sizeof(mStr), "0x%x", (int)error);
}
const char *get() const { return mStr; }
operator const char *() const { return mStr; }
private:
char mStr[16];
};
class CAX4CCStringNoQuote {
public:
CAX4CCStringNoQuote(OSStatus error) {
// see if it appears to be a 4-char-code
UInt32 beErr = CFSwapInt32HostToBig(error);
char *str = mStr;
memcpy(str, &beErr, 4);
if (isprint(str[0]) && isprint(str[1]) && isprint(str[2]) && isprint(str[3])) {
str[4] = '\0';
} else if (error > -200000 && error < 200000)
// no, format it as an integer
snprintf(str, sizeof(mStr), "%d", (int)error);
else
snprintf(str, sizeof(mStr), "0x%x", (int)error);
}
const char *get() const { return mStr; }
operator const char *() const { return mStr; }
private:
char mStr[16];
};
// An extended exception class that includes the name of the failed operation
class CAXException {
public:
CAXException(const char *operation, OSStatus err) :
mError(err)
{
if (operation == NULL)
mOperation[0] = '\0';
else if (strlen(operation) >= sizeof(mOperation)) {
memcpy(mOperation, operation, sizeof(mOperation) - 1);
mOperation[sizeof(mOperation) - 1] = '\0';
} else
strlcpy(mOperation, operation, sizeof(mOperation));
}
char *FormatError(char *str, size_t strsize) const
{
return FormatError(str, strsize, mError);
}
char mOperation[256];
const OSStatus mError;
// -------------------------------------------------
typedef void (*WarningHandler)(const char *msg, OSStatus err);
static char *FormatError(char *str, size_t strsize, OSStatus error)
{
strlcpy(str, CAX4CCString(error), strsize);
return str;
}
static void Warning(const char *s, OSStatus error)
{
if (sWarningHandler)
(*sWarningHandler)(s, error);
}
static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
private:
static WarningHandler sWarningHandler;
};
#if DEBUG || CoreAudio_Debug
#define XThrowIfError(error, operation) \
do { \
OSStatus __err = error; \
if (__err) { \
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
__THROW_STOP; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XThrowIf(condition, error, operation) \
do { \
if (condition) { \
OSStatus __err = error; \
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), operation);\
__THROW_STOP; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XRequireNoError(error, label) \
do { \
OSStatus __err = error; \
if (__err) { \
DebugMessageN4("%s:%d: about to throw %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
STOP; \
goto label; \
} \
} while (0)
#define XAssert(assertion) \
do { \
if (!(assertion)) { \
DebugMessageN3("%s:%d: error: failed assertion: %s", __FILE__, __LINE__, #assertion); \
__ASSERT_STOP; \
} \
} while (0)
#define XAssertNoError(error) \
do { \
OSStatus __err = error; \
if (__err) { \
DebugMessageN4("%s:%d: error %s: %s", __FILE__, __LINE__, CAX4CCString(__err).get(), #error);\
STOP; \
} \
} while (0)
#define ca_require_noerr(errorCode, exceptionLabel) \
do \
{ \
int evalOnceErrorCode = (errorCode); \
if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
{ \
DebugMessageN5("ca_require_noerr: [%s, %d] (goto %s;) %s:%d", \
#errorCode, evalOnceErrorCode, \
#exceptionLabel, \
__FILE__, \
__LINE__); \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_verify_noerr(errorCode) \
do \
{ \
int evalOnceErrorCode = (errorCode); \
if ( __builtin_expect(0 != evalOnceErrorCode, 0) ) \
{ \
DebugMessageN4("ca_verify_noerr: [%s, %d] %s:%d", \
#errorCode, evalOnceErrorCode, \
__FILE__, \
__LINE__); \
} \
} while ( 0 )
#define ca_debug_string(message) \
do \
{ \
DebugMessageN3("ca_debug_string: %s %s:%d", \
message, \
__FILE__, \
__LINE__); \
} while ( 0 )
#define ca_verify(assertion) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
DebugMessageN3("ca_verify: %s %s:%d", \
#assertion, \
__FILE__, \
__LINE__); \
} \
} while ( 0 )
#define ca_require(assertion, exceptionLabel) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
DebugMessageN4("ca_require: %s %s %s:%d", \
#assertion, \
#exceptionLabel, \
__FILE__, \
__LINE__); \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_check(assertion) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
DebugMessageN3("ca_check: %s %s:%d", \
#assertion, \
__FILE__, \
__LINE__); \
} \
} while ( 0 )
#else
#define XThrowIfError(error, operation) \
do { \
OSStatus __err = error; \
if (__err) { \
throw CAXException(operation, __err); \
} \
} while (0)
#define XThrowIf(condition, error, operation) \
do { \
if (condition) { \
OSStatus __err = error; \
throw CAXException(operation, __err); \
} \
} while (0)
#define XRequireNoError(error, label) \
do { \
OSStatus __err = error; \
if (__err) { \
goto label; \
} \
} while (0)
#define XAssert(assertion) \
do { \
if (!(assertion)) { \
} \
} while (0)
#define XAssertNoError(error) \
do { \
/*OSStatus __err =*/ error; \
} while (0)
#define ca_require_noerr(errorCode, exceptionLabel) \
do \
{ \
if ( __builtin_expect(0 != (errorCode), 0) ) \
{ \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_verify_noerr(errorCode) \
do \
{ \
if ( 0 != (errorCode) ) \
{ \
} \
} while ( 0 )
#define ca_debug_string(message)
#define ca_verify(assertion) \
do \
{ \
if ( !(assertion) ) \
{ \
} \
} while ( 0 )
#define ca_require(assertion, exceptionLabel) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
goto exceptionLabel; \
} \
} while ( 0 )
#define ca_check(assertion) \
do \
{ \
if ( !(assertion) ) \
{ \
} \
} while ( 0 )
#endif
#define XThrow(error, operation) XThrowIf(true, error, operation)
#define XThrowIfErr(error) XThrowIfError(error, #error)
#endif // __CAXException_h__

+ 0
- 369
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.cpp View File

@@ -1,369 +0,0 @@
/*
File: ComponentBase.cpp
Abstract: ComponentBase.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "ComponentBase.h"
#include "CAXException.h"
#if TARGET_OS_MAC
pthread_mutex_t ComponentInitLocker::sComponentOpenMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_once_t ComponentInitLocker::sOnce = PTHREAD_ONCE_INIT;
void ComponentInitLocker::InitComponentInitLocker()
{
// have to do this because OS X lacks PTHREAD_MUTEX_RECURSIVE_INITIALIZER_NP
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&sComponentOpenMutex, &attr);
pthread_mutexattr_destroy(&attr);
}
#elif TARGET_OS_WIN32
CAGuard ComponentInitLocker::sComponentOpenGuard("sComponentOpenGuard");
#endif
ComponentBase::EInstanceType ComponentBase::sNewInstanceType;
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
#if !CA_USE_AUDIO_PLUGIN_ONLY && !TARGET_OS_WIN32
static OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc);
#endif
ComponentBase::ComponentBase(AudioComponentInstance inInstance)
: mComponentInstance(inInstance),
mInstanceType(sNewInstanceType)
{
GetComponentDescription();
}
ComponentBase::~ComponentBase()
{
}
void ComponentBase::PostConstructor()
{
}
void ComponentBase::PreDestructor()
{
}
#define ACPI ((AudioComponentPlugInInstance *)self)
#define ACImp ((ComponentBase *)&ACPI->mInstanceStorage)
OSStatus ComponentBase::AP_Open(void *self, AudioUnit compInstance)
{
OSStatus result = noErr;
try {
ComponentInitLocker lock;
ComponentBase::sNewInstanceType = ComponentBase::kAudioComponentInstance;
ComponentBase *cb = (ComponentBase *)(*ACPI->mConstruct)(&ACPI->mInstanceStorage, compInstance);
cb->PostConstructor(); // allows base class to do additional initialization
// once the derived class is fully constructed
result = noErr;
}
COMPONENT_CATCH
if (result)
delete ACPI;
return result;
}
OSStatus ComponentBase::AP_Close(void *self)
{
OSStatus result = noErr;
try {
if (ACImp) {
ACImp->PreDestructor();
(*ACPI->mDestruct)(&ACPI->mInstanceStorage);
free(self);
}
}
COMPONENT_CATCH
return result;
}
#if !CA_USE_AUDIO_PLUGIN_ONLY
OSStatus ComponentBase::Version()
{
return 0x00000001;
}
OSStatus ComponentBase::ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This)
{
if (This == NULL) return kAudio_ParamError;
OSStatus result = noErr;
switch (p->what) {
case kComponentCloseSelect:
This->PreDestructor();
delete This;
break;
case kComponentVersionSelect:
result = This->Version();
break;
case kComponentCanDoSelect:
switch (GetSelectorForCanDo(p)) {
case kComponentOpenSelect:
case kComponentCloseSelect:
case kComponentVersionSelect:
case kComponentCanDoSelect:
return 1;
default:
return 0;
}
default:
result = badComponentSelector;
break;
}
return result;
}
SInt16 ComponentBase::GetSelectorForCanDo(ComponentParameters *params)
{
if (params->what != kComponentCanDoSelect) return 0;
#if TARGET_CPU_X86
SInt16 sel = params->params[0];
#elif TARGET_CPU_X86_64
SInt16 sel = params->params[1];
#elif TARGET_CPU_PPC
SInt16 sel = (params->params[0] >> 16);
#else
SInt16 sel = params->params[0];
#endif
return sel;
/*
printf ("flags:%d, paramSize: %d, what: %d\n\t", params->flags, params->paramSize, params->what);
for (int i = 0; i < params->paramSize; ++i) {
printf ("[%d]:%d(0x%x), ", i, params->params[i], params->params[i]);
}
printf("\n\tsel:%d\n", sel);
*/
}
#endif
#if CA_DO_NOT_USE_AUDIO_COMPONENT
static OSStatus ComponentBase_GetComponentDescription (const AudioComponentInstance & inInstance, AudioComponentDescription &outDesc);
#endif
AudioComponentDescription ComponentBase::GetComponentDescription() const
{
AudioComponentDescription desc;
OSStatus result = 1;
if (IsPluginObject()) {
ca_require_noerr(result = CB_GetComponentDescription (mComponentInstance, &desc), home);
}
#if !CA_USE_AUDIO_PLUGIN_ONLY
else {
ca_require_noerr(result = CMgr_GetComponentDescription (mComponentInstance, &desc), home);
}
#endif
home:
if (result)
memset (&desc, 0, sizeof(AudioComponentDescription));
return desc;
}
#if CA_USE_AUDIO_PLUGIN_ONLY
// everything we need is there and we should be linking against it
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
{
AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
if (comp)
return AudioComponentGetDescription(comp, outDesc);
return kAudio_ParamError;
}
#elif !TARGET_OS_WIN32
// these are the direct dependencies on ComponentMgr calls that an AU
// that is a component mgr is dependent on
// these are dynamically loaded so that these calls will work on Leopard
#include <dlfcn.h>
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
{
typedef AudioComponent (*AudioComponentInstanceGetComponentProc) (AudioComponentInstance);
static AudioComponentInstanceGetComponentProc aciGCProc = NULL;
typedef OSStatus (*AudioComponentGetDescriptionProc)(AudioComponent, AudioComponentDescription *);
static AudioComponentGetDescriptionProc acGDProc = NULL;
static int doneInit = 0;
if (doneInit == 0) {
doneInit = 1;
void* theImage = dlopen("/System/Library/Frameworks/AudioUnit.framework/AudioUnit", RTLD_LAZY);
if (theImage != NULL)
{
aciGCProc = (AudioComponentInstanceGetComponentProc)dlsym (theImage, "AudioComponentInstanceGetComponent");
if (aciGCProc) {
acGDProc = (AudioComponentGetDescriptionProc)dlsym (theImage, "AudioComponentGetDescription");
}
}
}
OSStatus result = kAudio_UnimplementedError;
if (acGDProc && aciGCProc) {
AudioComponent comp = (*aciGCProc)(inInstance);
if (comp)
result = (*acGDProc)(comp, outDesc);
}
#if !CA_USE_AUDIO_PLUGIN_ONLY
else {
result = CMgr_GetComponentDescription (inInstance, outDesc);
}
#endif
return result;
}
#if !CA_USE_AUDIO_PLUGIN_ONLY
// these are the direct dependencies on ComponentMgr calls that an AU
// that is a component mgr is dependent on
// these are dynamically loaded
#include <CoreServices/CoreServices.h>
#include <AudioUnit/AudioUnit.h>
#include "CAXException.h"
#include "ComponentBase.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Component Manager
// Used for fast dispatch with audio units
typedef Handle (*GetComponentInstanceStorageProc)(ComponentInstance aComponentInstance);
static GetComponentInstanceStorageProc sGetComponentInstanceStorageProc = NULL;
typedef OSErr (*GetComponentInfoProc)(Component, ComponentDescription *, void*, void*, void*);
static GetComponentInfoProc sGetComponentInfoProc = NULL;
typedef void (*SetComponentInstanceStorageProc)(ComponentInstance, Handle);
static SetComponentInstanceStorageProc sSetComponentInstanceStorageProc = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void CSInitOnce(void* /*unused*/)
{
void *theImage = dlopen("/System/Library/Frameworks/CoreServices.framework/CoreServices", RTLD_LAZY);
if (!theImage) return;
sGetComponentInstanceStorageProc = (GetComponentInstanceStorageProc) dlsym(theImage, "GetComponentInstanceStorage");
sGetComponentInfoProc = (GetComponentInfoProc)dlsym (theImage, "GetComponentInfo");
sSetComponentInstanceStorageProc = (SetComponentInstanceStorageProc) dlsym(theImage, "SetComponentInstanceStorage");
}
#if TARGET_OS_MAC
#include <dispatch/dispatch.h>
static dispatch_once_t sCSInitOnce = 0;
static void CSInit ()
{
dispatch_once_f(&sCSInitOnce, NULL, CSInitOnce);
}
#else
static void CSInit ()
{
static int sDoCSLoad = 1;
if (sDoCSLoad) {
sDoCSLoad = 0;
CSInitOnce(NULL);
}
}
#endif
OSStatus CMgr_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
{
CSInit();
if (sGetComponentInfoProc)
return (*sGetComponentInfoProc)((Component)inInstance, (ComponentDescription*)outDesc, NULL, NULL, NULL);
return kAudio_UnimplementedError;
}
Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance)
{
CSInit();
if (sGetComponentInstanceStorageProc)
return (*sGetComponentInstanceStorageProc)(aComponentInstance);
return NULL;
}
void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage)
{
CSInit();
if (sSetComponentInstanceStorageProc)
(*sSetComponentInstanceStorageProc)(aComponentInstance, theStorage);
}
#endif // !CA_USE_AUDIO_PLUGIN_ONLY
#else
//#include "ComponentManagerDependenciesWin.h"
// everything we need is there and we should be linking against it
static OSStatus CB_GetComponentDescription (const AudioComponentInstance inInstance, AudioComponentDescription * outDesc)
{
AudioComponent comp = AudioComponentInstanceGetComponent(inInstance);
if (comp)
return AudioComponentGetDescription(comp, outDesc);
return kAudio_ParamError;
}
#endif

+ 0
- 353
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/ComponentBase.h View File

@@ -1,353 +0,0 @@
/*
File: ComponentBase.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __ComponentBase_h__
#define __ComponentBase_h__
#include <new>
#include "CADebugMacros.h"
#include "CAXException.h"
#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
#include <CoreAudio/CoreAudioTypes.h>
#include <AudioUnit/AudioUnit.h>
#if !CA_USE_AUDIO_PLUGIN_ONLY
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Components.h>
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
#define AudioComponentInstance ComponentInstance
#define AudioComponentDescription ComponentDescription
#define AudioComponent Component
#endif
Handle CMgr_GetComponentInstanceStorage(ComponentInstance aComponentInstance);
void CMgr_SetComponentInstanceStorage(ComponentInstance aComponentInstance, Handle theStorage);
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
typedef Float32 AudioUnitParameterValue;
#endif
#if COREAUDIOTYPES_VERSION < 1051
typedef Float32 AudioUnitSampleType;
#endif
#if !TARGET_OS_WIN32
#include <pthread.h>
#endif
#if TARGET_OS_WIN32
#include "CAGuard.h"
#endif
#else
#include "CoreAudioTypes.h"
#if !CA_USE_AUDIO_PLUGIN_ONLY
#include "ComponentManagerDependenciesWin.h"
#endif
#include "AudioUnit.h"
#include "CAGuard.h"
#endif
#ifndef COMPONENT_THROW
#if VERBOSE_COMPONENT_THROW
#define COMPONENT_THROW(throw_err) \
do { DebugMessage(#throw_err); throw static_cast<OSStatus>(throw_err); } while (0)
#else
#define COMPONENT_THROW(throw_err) \
throw static_cast<OSStatus>(throw_err)
#endif
#endif
#define COMPONENT_CATCH \
catch (const CAXException &ex) { result = ex.mError; } \
catch (std::bad_alloc &) { result = kAudio_MemFullError; } \
catch (OSStatus catch_err) { result = catch_err; } \
catch (OSErr catch_err) { result = catch_err; } \
catch (...) { result = -1; }
/*! @class ComponentBase */
class ComponentBase {
public:
// classic MacErrors
enum { noErr = 0};
/*! @ctor ComponentBase */
ComponentBase(AudioComponentInstance inInstance);
/*! @dtor ~ComponentBase */
virtual ~ComponentBase();
/*! @method PostConstructor */
virtual void PostConstructor();
/*! @method PreDestructor */
virtual void PreDestructor();
#if !CA_USE_AUDIO_PLUGIN_ONLY
/*! @method Version */
virtual OSStatus Version();
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch(ComponentParameters *p, ComponentBase *This);
/*! GetSelectorForCanDo */
static SInt16 GetSelectorForCanDo(ComponentParameters *params);
#endif
/*! @method GetComponentInstance */
AudioComponentInstance GetComponentInstance() const { return mComponentInstance; }
/*! @method GetComponentDescription */
AudioComponentDescription GetComponentDescription() const;
// This global variable is so that new instances know how they were instantiated: via the Component Manager,
// or as AudioComponents. It's ugly, but preferable to altering the constructor of every class in the hierarchy.
// It's safe because construction is protected by ComponentInitLocker.
enum EInstanceType { kComponentMgrInstance, kAudioComponentInstance };
static EInstanceType sNewInstanceType;
/*! @method IsPluginObject */
bool IsPluginObject () const { return mInstanceType == kAudioComponentInstance; }
/*! @method IsCMgrObject */
bool IsCMgrObject () const { return mInstanceType == kComponentMgrInstance; }
/*! @method AP_Open */
static OSStatus AP_Open(void *self, AudioUnit compInstance);
/*! @method AP_Close */
static OSStatus AP_Close(void *self);
protected:
/*! @var mComponentInstance */
AudioComponentInstance mComponentInstance;
EInstanceType mInstanceType;
};
class ComponentInitLocker
{
#if TARGET_OS_MAC
public:
ComponentInitLocker()
{
pthread_once(&sOnce, InitComponentInitLocker);
pthread_mutex_lock(&sComponentOpenMutex);
mPreviousNewInstanceType = ComponentBase::sNewInstanceType;
}
~ComponentInitLocker()
{
ComponentBase::sNewInstanceType = mPreviousNewInstanceType;
pthread_mutex_unlock(&sComponentOpenMutex);
}
// There are situations (11844772) where we need to be able to release the lock early.
class Unlocker {
public:
Unlocker()
{
pthread_mutex_unlock(&sComponentOpenMutex);
}
~Unlocker()
{
pthread_mutex_lock(&sComponentOpenMutex);
}
};
private:
static pthread_mutex_t sComponentOpenMutex;
static pthread_once_t sOnce;
static void InitComponentInitLocker();
#elif TARGET_OS_WIN32
public:
bool sNeedsUnlocking;
ComponentInitLocker() { sNeedsUnlocking = sComponentOpenGuard.Lock(); }
~ComponentInitLocker() { if(sNeedsUnlocking) { sComponentOpenGuard.Unlock(); } }
private:
static CAGuard sComponentOpenGuard;
#endif
private:
ComponentBase::EInstanceType mPreviousNewInstanceType;
};
/*! @class AudioComponentPlugInInstance */
struct AudioComponentPlugInInstance {
AudioComponentPlugInInterface mPlugInInterface;
void * (*mConstruct)(void *memory, AudioComponentInstance ci);
void (*mDestruct)(void *memory);
void * mPad[2]; // pad to a 16-byte boundary (in either 32 or 64 bit mode)
UInt32 mInstanceStorage; // the ACI implementation object is constructed into this memory
// this member is just a placeholder. it is aligned to a 16byte boundary
};
/*! @class APFactory */
template <class APMethodLookup, class Implementor>
class APFactory {
public:
static void *Construct(void *memory, AudioComponentInstance compInstance)
{
return new(memory) Implementor(compInstance);
}
static void Destruct(void *memory)
{
((Implementor *)memory)->~Implementor();
}
// This is the AudioComponentFactoryFunction. It returns an AudioComponentPlugInInstance.
// The actual implementation object is not created until Open().
static AudioComponentPlugInInterface *Factory(const AudioComponentDescription * /* inDesc */)
{
AudioComponentPlugInInstance *acpi =
(AudioComponentPlugInInstance *)malloc( offsetof(AudioComponentPlugInInstance, mInstanceStorage) + sizeof(Implementor) );
acpi->mPlugInInterface.Open = ComponentBase::AP_Open;
acpi->mPlugInInterface.Close = ComponentBase::AP_Close;
acpi->mPlugInInterface.Lookup = APMethodLookup::Lookup;
acpi->mPlugInInterface.reserved = NULL;
acpi->mConstruct = Construct;
acpi->mDestruct = Destruct;
acpi->mPad[0] = NULL;
acpi->mPad[1] = NULL;
return (AudioComponentPlugInInterface*)acpi;
}
// This is for runtime registration (not for plug-ins loaded from bundles).
static AudioComponent Register(UInt32 type, UInt32 subtype, UInt32 manuf, CFStringRef name, UInt32 vers, UInt32 flags=0)
{
AudioComponentDescription desc = { type, subtype, manuf, flags, 0 };
return AudioComponentRegister(&desc, name, vers, Factory);
}
};
#if !CA_USE_AUDIO_PLUGIN_ONLY
/*! @class ComponentEntryPoint
* @discussion This is only used for a component manager version
*/
template <class Class>
class ComponentEntryPoint {
public:
/*! @method Dispatch */
static OSStatus Dispatch(ComponentParameters *params, Class *obj)
{
OSStatus result = noErr;
try {
if (params->what == kComponentOpenSelect) {
// solve a host of initialization thread safety issues.
ComponentInitLocker lock;
ComponentBase::sNewInstanceType = ComponentBase::kComponentMgrInstance;
ComponentInstance ci = (ComponentInstance)(params->params[0]);
Class *This = new Class((AudioComponentInstance)ci);
This->PostConstructor(); // allows base class to do additional initialization
// once the derived class is fully constructed
CMgr_SetComponentInstanceStorage(ci, (Handle)This);
} else
result = Class::ComponentEntryDispatch(params, obj);
}
COMPONENT_CATCH
return result;
}
/*! @method Register */
static Component Register(OSType compType, OSType subType, OSType manufacturer)
{
ComponentDescription description = {compType, subType, manufacturer, 0, 0};
Component component = RegisterComponent(&description, (ComponentRoutineUPP) Dispatch, registerComponentGlobal, NULL, NULL, NULL);
if (component != NULL) {
SetDefaultComponent(component, defaultComponentAnyFlagsAnyManufacturerAnySubType);
}
return component;
}
};
// NOTE: Component Mgr is deprecated in ML.
// this macro should not be used with new audio components
// it is only for backwards compatibility with Lion and SL.
// this macro registers both a plugin and a component mgr version.
#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
return ComponentEntryPoint<Class>::Dispatch(params, obj); \
} \
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
return FactoryType<Class>::Factory(inDesc); \
}
// the only component we still support are the carbon based view components
// you should be using this macro now to exclusively register those types
#define VIEW_COMPONENT_ENTRY(Class) \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj); \
extern "C" OSStatus Class##Entry(ComponentParameters *params, Class *obj) { \
return ComponentEntryPoint<Class>::Dispatch(params, obj); \
}
/*! @class ComponentRegistrar */
template <class Class, OSType Type, OSType Subtype, OSType Manufacturer>
class ComponentRegistrar {
public:
/*! @ctor ComponentRegistrar */
ComponentRegistrar() { ComponentEntryPoint<Class>::Register(Type, Subtype, Manufacturer); }
};
#define COMPONENT_REGISTER(Class,Type,Subtype,Manufacturer) \
static ComponentRegistrar<Class, Type, Subtype, Manufacturer> gRegistrar##Class
#else
#define COMPONENT_ENTRY(Class)
#define COMPONENT_REGISTER(Class)
// this macro is used to generate the Entry Point for a given Audio Plugin
// you should be using this macro now with audio components
#define AUDIOCOMPONENT_ENTRY(FactoryType, Class) \
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc); \
extern "C" void * Class##Factory(const AudioComponentDescription *inDesc) { \
return FactoryType<Class>::Factory(inDesc); \
}
#endif // !CA_USE_AUDIO_PLUGIN_ONLY
#endif // __ComponentBase_h__

+ 0
- 354
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp View File

@@ -1,354 +0,0 @@
/*
File: MusicDeviceBase.cpp
Abstract: MusicDeviceBase.h
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#include "MusicDeviceBase.h"
// compatibility with older OS SDK releases
typedef OSStatus
(*TEMP_MusicDeviceMIDIEventProc)( void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);
typedef OSStatus
(*TEMP_MusicDeviceStartNoteProc)( void * inComponentStorage,
MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams);
typedef OSStatus
(*TEMP_MusicDeviceStopNoteProc)(void * inComponentStorage,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);
#if !CA_USE_AUDIO_PLUGIN_ONLY
static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);
static OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams);
static OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame);
#endif
MusicDeviceBase::MusicDeviceBase(AudioComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups)
: AUBase(inInstance, numInputs, numOutputs, numGroups),
AUMIDIBase(this)
{
}
OSStatus MusicDeviceBase::GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable)
{
OSStatus result;
switch (inID)
{
#if !TARGET_OS_IPHONE
case kMusicDeviceProperty_InstrumentCount:
if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
outDataSize = sizeof(UInt32);
outWritable = false;
result = noErr;
break;
#endif
default:
result = AUBase::GetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateGetPropertyInfo (inID, inScope, inElement, outDataSize, outWritable);
break;
}
return result;
}
OSStatus MusicDeviceBase::GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData)
{
OSStatus result;
switch (inID)
{
#if !CA_USE_AUDIO_PLUGIN_ONLY
case kAudioUnitProperty_FastDispatch:
if (!IsCMgrObject()) return kAudioUnitErr_InvalidProperty;
if (inElement == kMusicDeviceMIDIEventSelect) {
*(TEMP_MusicDeviceMIDIEventProc *)outData = MusicDeviceBaseMIDIEvent;
return noErr;
}
else if (inElement == kMusicDeviceStartNoteSelect) {
*(TEMP_MusicDeviceStartNoteProc *)outData = MusicDeviceBaseStartNote;
return noErr;
}
else if (inElement == kMusicDeviceStopNoteSelect) {
*(TEMP_MusicDeviceStopNoteProc *)outData = MusicDeviceBaseStopNote;
return noErr;
}
return kAudioUnitErr_InvalidElement;
#endif
#if !TARGET_OS_IPHONE
case kMusicDeviceProperty_InstrumentCount:
if (inScope != kAudioUnitScope_Global) return kAudioUnitErr_InvalidScope;
return GetInstrumentCount (*(UInt32*)outData);
#endif
default:
result = AUBase::GetProperty (inID, inScope, inElement, outData);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateGetProperty (inID, inScope, inElement, outData);
}
return result;
}
OSStatus MusicDeviceBase::SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize)
{
OSStatus result = AUBase::SetProperty (inID, inScope, inElement, inData, inDataSize);
if (result == kAudioUnitErr_InvalidProperty)
result = AUMIDIBase::DelegateSetProperty (inID, inScope, inElement, inData, inDataSize);
return result;
}
// For a MusicDevice that doesn't support separate instruments (ie. is mono-timbral)
// then this call should return an instrument count of zero and noErr
OSStatus MusicDeviceBase::GetInstrumentCount (UInt32 &outInstCount) const
{
outInstCount = 0;
return noErr;
}
OSStatus MusicDeviceBase::HandleNoteOn( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame)
{
MusicDeviceNoteParams params;
params.argCount = 2;
params.mPitch = inNoteNumber;
params.mVelocity = inVelocity;
return StartNote (kMusicNoteEvent_UseGroupInstrument, inChannel, NULL, inStartFrame, params);
}
OSStatus MusicDeviceBase::HandleNoteOff( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame)
{
return StopNote (inChannel, inNoteNumber, inStartFrame);
}
OSStatus
MusicDeviceBase::HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams)
{
if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
if (!IsInitialized()) return kAudioUnitErr_Uninitialized;
return StartNote (inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}
#if TARGET_OS_MAC
#if __LP64__
// comp instance, parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index + 1];
#else
// parameters in reverse order, then comp instance
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
#endif
#elif TARGET_OS_WIN32
// (no comp instance), parameters in forward order
#define PARAM(_typ, _name, _index, _nparams) \
_typ _name = *(_typ *)&params->params[_index];
#endif
#if !CA_USE_AUDIO_PLUGIN_ONLY
OSStatus MusicDeviceBase::ComponentEntryDispatch( ComponentParameters * params,
MusicDeviceBase * This)
{
if (This == NULL) return kAudio_ParamError;
OSStatus result;
switch (params->what) {
case kMusicDeviceMIDIEventSelect:
case kMusicDeviceSysExSelect:
{
result = AUMIDIBase::ComponentEntryDispatch (params, This);
}
break;
case kMusicDevicePrepareInstrumentSelect:
{
PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
result = This->PrepareInstrument(inInstrument);
}
break;
case kMusicDeviceReleaseInstrumentSelect:
{
PARAM(MusicDeviceInstrumentID, inInstrument, 0, 1);
result = This->ReleaseInstrument(inInstrument);
}
break;
case kMusicDeviceStartNoteSelect:
{
PARAM(MusicDeviceInstrumentID, pbinInstrument, 0, 5);
PARAM(MusicDeviceGroupID, pbinGroupID, 1, 5);
PARAM(NoteInstanceID *, pboutNoteInstanceID, 2, 5);
PARAM(UInt32, pbinOffsetSampleFrame, 3, 5);
PARAM(const MusicDeviceNoteParams *, pbinParams, 4, 5);
result = This->HandleStartNoteMessage(pbinInstrument, pbinGroupID, pboutNoteInstanceID, pbinOffsetSampleFrame, pbinParams);
}
break;
case kMusicDeviceStopNoteSelect:
{
PARAM(MusicDeviceGroupID, pbinGroupID, 0, 3);
PARAM(NoteInstanceID, pbinNoteInstanceID, 1, 3);
PARAM(UInt32, pbinOffsetSampleFrame, 2, 3);
result = This->StopNote(pbinGroupID, pbinNoteInstanceID, pbinOffsetSampleFrame);
}
break;
default:
result = AUBase::ComponentEntryDispatch(params, This);
break;
}
return result;
}
#endif
#if !CA_USE_AUDIO_PLUGIN_ONLY
// fast dispatch
static OSStatus MusicDeviceBaseMIDIEvent(void * inComponentStorage,
UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
if (This == NULL) return kAudio_ParamError;
result = This->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}
OSStatus MusicDeviceBaseStartNote( void * inComponentStorage,
MusicDeviceInstrumentID inInstrument,
MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
UInt32 inOffsetSampleFrame,
const MusicDeviceNoteParams * inParams)
{
OSStatus result = noErr;
try {
if (inParams == NULL || outNoteInstanceID == NULL) return kAudio_ParamError;
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
if (This == NULL) return kAudio_ParamError;
result = This->StartNote(inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
}
COMPONENT_CATCH
return result;
}
OSStatus MusicDeviceBaseStopNote(void * inComponentStorage,
MusicDeviceGroupID inGroupID,
NoteInstanceID inNoteInstanceID,
UInt32 inOffsetSampleFrame)
{
OSStatus result = noErr;
try {
MusicDeviceBase *This = static_cast<MusicDeviceBase *>(inComponentStorage);
if (This == NULL) return kAudio_ParamError;
result = This->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
}
COMPONENT_CATCH
return result;
}
#endif

+ 0
- 126
modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/MusicDeviceBase.h View File

@@ -1,126 +0,0 @@
/*
File: MusicDeviceBase.h
Abstract: Part of CoreAudio Utility Classes
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#ifndef __MusicDeviceBase_h__
#define __MusicDeviceBase_h__
#include "AUMIDIBase.h"
// ________________________________________________________________________
// MusicDeviceBase
//
/*! @class MusicDeviceBase */
class MusicDeviceBase : public AUBase, public AUMIDIBase {
public:
/*! @ctor MusicDeviceBase */
MusicDeviceBase( AudioComponentInstance inInstance,
UInt32 numInputs,
UInt32 numOutputs,
UInt32 numGroups = 0);
virtual OSStatus MIDIEvent( UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame)
{
return AUMIDIBase::MIDIEvent (inStatus, inData1, inData2, inOffsetSampleFrame);
}
/*! @method SysEx */
virtual OSStatus SysEx( const UInt8 * inData,
UInt32 inLength)
{
return AUMIDIBase::SysEx (inData, inLength);
}
/*! @method GetPropertyInfo */
virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32 & outDataSize,
Boolean & outWritable);
/*! @method GetProperty */
virtual OSStatus GetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
void * outData);
/*! @method SetProperty */
virtual OSStatus SetProperty( AudioUnitPropertyID inID,
AudioUnitScope inScope,
AudioUnitElement inElement,
const void * inData,
UInt32 inDataSize);
/*! @method HandleNoteOn */
virtual OSStatus HandleNoteOn( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame);
/*! @method HandleNoteOff */
virtual OSStatus HandleNoteOff( UInt8 inChannel,
UInt8 inNoteNumber,
UInt8 inVelocity,
UInt32 inStartFrame);
/*! @method GetInstrumentCount */
virtual OSStatus GetInstrumentCount ( UInt32 &outInstCount) const;
#if !CA_USE_AUDIO_PLUGIN_ONLY
// component dispatcher
/*! @method ComponentEntryDispatch */
static OSStatus ComponentEntryDispatch( ComponentParameters * params,
MusicDeviceBase * This);
#endif
private:
OSStatus HandleStartNoteMessage (MusicDeviceInstrumentID inInstrument, MusicDeviceGroupID inGroupID, NoteInstanceID *outNoteInstanceID, UInt32 inOffsetSampleFrame, const MusicDeviceNoteParams *inParams);
};
#endif // __MusicDeviceBase_h__

+ 94
- 155
modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm View File

@@ -52,7 +52,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wshorten-64-to-32",
#include <AudioToolbox/AudioUnitUtilities.h>
#include <CoreMIDI/MIDIServices.h>
#include <QuartzCore/QuartzCore.h>
#include "CoreAudioUtilityClasses/MusicDeviceBase.h"
#include "AudioUnitSDK/MusicDeviceBase.h"
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
@@ -73,6 +73,8 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif
#endif
#include <set>
//==============================================================================
using namespace juce;
@@ -101,7 +103,7 @@ struct AudioProcessorHolder
//==============================================================================
class JuceAU : public AudioProcessorHolder,
public MusicDeviceBase,
public ausdk::MusicDeviceBase,
public AudioProcessorListener,
public AudioProcessorParameter::Listener
{
@@ -239,24 +241,6 @@ public:
}
}
//==============================================================================
static OSStatus ComponentEntryDispatch (ComponentParameters* params, JuceAU* effect)
{
if (effect == nullptr)
return paramErr;
switch (params->what)
{
case kMusicDeviceMIDIEventSelect:
case kMusicDeviceSysExSelect:
return AUMIDIBase::ComponentEntryDispatch (params, effect);
default:
break;
}
return MusicDeviceBase::ComponentEntryDispatch (params, effect);
}
//==============================================================================
bool BusCountWritable (AudioUnitScope scope) override
{
@@ -380,7 +364,7 @@ public:
AudioUnitScope inScope,
AudioUnitElement inElement,
UInt32& outDataSize,
Boolean& outWritable) override
bool& outWritable) override
{
if (inScope == kAudioUnitScope_Global)
{
@@ -813,8 +797,10 @@ public:
#endif
}
UInt32 GetAudioChannelLayout (AudioUnitScope scope, AudioUnitElement element,
AudioChannelLayout* outLayoutPtr, Boolean& outWritable) override
UInt32 GetAudioChannelLayout (AudioUnitScope scope,
AudioUnitElement element,
AudioChannelLayout* outLayoutPtr,
bool& outWritable) override
{
outWritable = false;
@@ -839,22 +825,17 @@ public:
return sizeInBytes;
}
UInt32 GetChannelLayoutTags (AudioUnitScope scope, AudioUnitElement element, AudioChannelLayoutTag* outLayoutTags) override
std::vector<AudioChannelLayoutTag> GetChannelLayoutTags (AudioUnitScope inScope, AudioUnitElement inElement) override
{
const auto info = getElementInfo (scope, element);
const auto info = getElementInfo (inScope, inElement);
if (info.error != noErr)
return 0;
return {};
if (busIgnoresLayout (info.isInput, info.busNr))
return 0;
const Array<AudioChannelLayoutTag>& layouts = getSupportedBusLayouts (info.isInput, info.busNr);
if (outLayoutTags != nullptr)
std::copy (layouts.begin(), layouts.end(), outLayoutTags);
return {};
return (UInt32) layouts.size();
return getSupportedBusLayouts (info.isInput, info.busNr);
}
OSStatus SetAudioChannelLayout (AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override
@@ -870,34 +851,29 @@ public:
if (inLayout == nullptr)
return kAudioUnitErr_InvalidPropertyValue;
if (const AUIOElement* ioElement = GetIOElement (info.isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, element))
{
const AudioChannelSet newChannelSet = CoreAudioLayouts::fromCoreAudio (*inLayout);
const int currentNumChannels = static_cast<int> (ioElement->GetStreamFormat().NumberChannels());
const int newChannelNum = newChannelSet.size();
auto& ioElement = IOElement (info.isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, element);
if (currentNumChannels != newChannelNum)
return kAudioUnitErr_InvalidPropertyValue;
const AudioChannelSet newChannelSet = CoreAudioLayouts::fromCoreAudio (*inLayout);
const int currentNumChannels = static_cast<int> (ioElement.NumberChannels());
const int newChannelNum = newChannelSet.size();
// check if the new layout could be potentially set
#ifdef JucePlugin_PreferredChannelConfigurations
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
if (currentNumChannels != newChannelNum)
return kAudioUnitErr_InvalidPropertyValue;
if (! AudioUnitHelpers::isLayoutSupported (*juceFilter, info.isInput, info.busNr, newChannelNum, configs))
return kAudioUnitErr_FormatNotSupported;
#else
if (! juceFilter->getBus (info.isInput, info.busNr)->isLayoutSupported (newChannelSet))
return kAudioUnitErr_FormatNotSupported;
#endif
// check if the new layout could be potentially set
#ifdef JucePlugin_PreferredChannelConfigurations
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
getCurrentLayout (info.isInput, info.busNr) = CoreAudioLayouts::toCoreAudio (newChannelSet);
if (! AudioUnitHelpers::isLayoutSupported (*juceFilter, info.isInput, info.busNr, newChannelNum, configs))
return kAudioUnitErr_FormatNotSupported;
#else
if (! juceFilter->getBus (info.isInput, info.busNr)->isLayoutSupported (newChannelSet))
return kAudioUnitErr_FormatNotSupported;
#endif
return noErr;
}
else
jassertfalse;
getCurrentLayout (info.isInput, info.busNr) = CoreAudioLayouts::toCoreAudio (newChannelSet);
return kAudioUnitErr_InvalidElement;
return noErr;
}
//==============================================================================
@@ -1063,14 +1039,13 @@ public:
bool CanScheduleParameters() const override { return false; }
//==============================================================================
ComponentResult Version() override { return JucePlugin_VersionCode; }
bool SupportsTail() override { return true; }
Float64 GetTailTime() override { return juceFilter->getTailLengthSeconds(); }
double getSampleRate()
{
if (AudioUnitHelpers::getBusCountForWrapper (*juceFilter, false) > 0)
return GetOutput (0)->GetStreamFormat().mSampleRate;
return Output (0).GetStreamFormat().mSampleRate;
return 44100.0;
}
@@ -1236,14 +1211,16 @@ public:
return ((! IsInitialized()) && (info.error == noErr));
}
bool ValidFormat (AudioUnitScope scope, AudioUnitElement element, const CAStreamBasicDescription& format) override
bool ValidFormat (AudioUnitScope inScope,
AudioUnitElement inElement,
const AudioStreamBasicDescription& inNewFormat) override
{
// DSP Quattro incorrectly uses global scope for the ValidFormat call
if (scope == kAudioUnitScope_Global)
return ValidFormat (kAudioUnitScope_Input, element, format)
|| ValidFormat (kAudioUnitScope_Output, element, format);
if (inScope == kAudioUnitScope_Global)
return ValidFormat (kAudioUnitScope_Input, inElement, inNewFormat)
|| ValidFormat (kAudioUnitScope_Output, inElement, inNewFormat);
const auto info = getElementInfo (scope, element);
const auto info = getElementInfo (inScope, inElement);
if (info.error != noErr)
return false;
@@ -1251,15 +1228,15 @@ public:
if (info.kind == BusKind::wrapperOnly)
return true;
const int newNumChannels = static_cast<int> (format.NumberChannels());
const int oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr);
const auto newNumChannels = static_cast<int> (inNewFormat.mChannelsPerFrame);
const auto oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr);
if (newNumChannels == oldNumChannels)
return true;
if (AudioProcessor::Bus* bus = juceFilter->getBus (info.isInput, info.busNr))
{
if (! MusicDeviceBase::ValidFormat (scope, element, format))
if (! MusicDeviceBase::ValidFormat (inScope, inElement, inNewFormat))
return false;
#ifdef JucePlugin_PreferredChannelConfigurations
@@ -1276,17 +1253,20 @@ public:
}
// AU requires us to override this for the sole reason that we need to find a default layout tag if the number of channels have changed
OSStatus ChangeStreamFormat (AudioUnitScope scope, AudioUnitElement element, const CAStreamBasicDescription& old, const CAStreamBasicDescription& format) override
OSStatus ChangeStreamFormat (AudioUnitScope inScope,
AudioUnitElement inElement,
const AudioStreamBasicDescription& inPrevFormat,
const AudioStreamBasicDescription& inNewFormat) override
{
const auto info = getElementInfo (scope, element);
const auto info = getElementInfo (inScope, inElement);
if (info.error != noErr)
return info.error;
AudioChannelLayoutTag& currentTag = getCurrentLayout (info.isInput, info.busNr);
const int newNumChannels = static_cast<int> (format.NumberChannels());
const int oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr);
const auto newNumChannels = static_cast<int> (inNewFormat.mChannelsPerFrame);
const auto oldNumChannels = juceFilter->getChannelCountOfBus (info.isInput, info.busNr);
#ifdef JucePlugin_PreferredChannelConfigurations
short configs[][2] = {JucePlugin_PreferredChannelConfigurations};
@@ -1310,7 +1290,7 @@ public:
if (set == AudioChannelSet())
return kAudioUnitErr_FormatNotSupported;
const auto err = MusicDeviceBase::ChangeStreamFormat (scope, element, old, format);
const auto err = MusicDeviceBase::ChangeStreamFormat (inScope, inElement, inPrevFormat, inNewFormat);
if (err == noErr)
currentTag = CoreAudioLayouts::toCoreAudio (set);
@@ -1375,7 +1355,7 @@ public:
for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
{
if (pulledSucceeded[busIdx])
audioBuffer.set (busIdx, GetInput ((UInt32) busIdx)->GetBufferList(), mapper.get (true, busIdx));
audioBuffer.set (busIdx, Input ((UInt32) busIdx).GetBufferList(), mapper.get (true, busIdx));
else
audioBuffer.clearInputBus (busIdx, (int) nFrames);
}
@@ -1396,7 +1376,7 @@ public:
// copy back
{
for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
audioBuffer.get (busIdx, GetOutput ((UInt32) busIdx)->GetBufferList(), mapper.get (false, busIdx));
audioBuffer.get (busIdx, Output ((UInt32) busIdx).GetBufferList(), mapper.get (false, busIdx));
}
// process midi output
@@ -1415,10 +1395,10 @@ public:
ComponentResult StopNote (MusicDeviceGroupID, NoteInstanceID, UInt32) override { return noErr; }
//==============================================================================
OSStatus HandleMidiEvent (UInt8 nStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame) override
OSStatus HandleMIDIEvent (UInt8 inStatus, UInt8 inChannel, UInt8 inData1, UInt8 inData2, UInt32 inStartFrame) override
{
#if JucePlugin_WantsMidiInput || JucePlugin_IsMidiEffect
const juce::uint8 data[] = { (juce::uint8) (nStatus | inChannel),
const juce::uint8 data[] = { (juce::uint8) (inStatus | inChannel),
(juce::uint8) inData1,
(juce::uint8) inData2 };
@@ -1426,7 +1406,7 @@ public:
incomingEvents.addEvent (data, 3, (int) inStartFrame);
return noErr;
#else
ignoreUnused (nStatus, inChannel, inData1);
ignoreUnused (inStatus, inChannel, inData1);
ignoreUnused (inData2, inStartFrame);
return kAudioUnitErr_PropertyNotInUse;
#endif
@@ -1877,7 +1857,7 @@ private:
//==============================================================================
Array<AUChannelInfo> channelInfo;
Array<Array<AudioChannelLayoutTag>> supportedInputLayouts, supportedOutputLayouts;
Array<std::vector<AudioChannelLayoutTag>> supportedInputLayouts, supportedOutputLayouts;
Array<AudioChannelLayoutTag> currentInputLayout, currentOutputLayout;
//==============================================================================
@@ -1923,15 +1903,14 @@ private:
for (unsigned int i = 0; i < numInputBuses; ++i)
{
if (AUInputElement* input = GetInput (i))
{
const bool succeeded = (input->PullInput (flags, timestamp, i, nFrames) == noErr);
auto& input = Input (i);
if ((flags & kAudioUnitRenderAction_OutputIsSilence) != 0 && succeeded)
AudioUnitHelpers::clearAudioBuffer (input->GetBufferList());
const bool succeeded = (input.PullInput (flags, timestamp, i, nFrames) == noErr);
pulledSucceeded[i] = succeeded;
}
if ((flags & kAudioUnitRenderAction_OutputIsSilence) != 0 && succeeded)
AudioUnitHelpers::clearAudioBuffer (input.GetBufferList());
pulledSucceeded[i] = succeeded;
}
}
@@ -1942,13 +1921,13 @@ private:
for (UInt32 busIdx = 0; busIdx < numWrapperBuses; ++busIdx)
{
AUOutputElement* output = GetOutput (busIdx);
auto& output = Output (busIdx);
if (output->WillAllocateBuffer())
output->PrepareBuffer (nFrames);
if (output.WillAllocateBuffer())
output.PrepareBuffer (nFrames);
if (busIdx >= (UInt32) numProcessorBuses)
AudioUnitHelpers::clearAudioBuffer (output->GetBufferList());
AudioUnitHelpers::clearAudioBuffer (output.GetBufferList());
}
}
@@ -2026,7 +2005,7 @@ private:
void GetAudioBufferList (bool isInput, int busIdx, AudioBufferList*& bufferList, bool& interleaved, int& numChannels)
{
AUIOElement* element = GetElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, static_cast<UInt32> (busIdx))->AsIOElement();
auto* element = Element (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, static_cast<UInt32> (busIdx)).AsIOElement();
jassert (element != nullptr);
bufferList = &element->GetBufferList();
@@ -2124,7 +2103,7 @@ private:
if (forceUseLegacyParamIDs)
{
Globals()->UseIndexedParameters (numParams);
Globals()->UseIndexedParameters (static_cast<UInt32> (numParams));
}
else
{
@@ -2261,8 +2240,8 @@ private:
const int numInputBuses = AudioUnitHelpers::getBusCount (*juceFilter, true);
const int numOutputBuses = AudioUnitHelpers::getBusCount (*juceFilter, false);
const int numInputElements = static_cast<int> (GetScope(kAudioUnitScope_Input). GetNumberOfElements());
const int numOutputElements = static_cast<int> (GetScope(kAudioUnitScope_Output).GetNumberOfElements());
const int numInputElements = static_cast<int> (GetScope (kAudioUnitScope_Input). GetNumberOfElements());
const int numOutputElements = static_cast<int> (GetScope (kAudioUnitScope_Output).GetNumberOfElements());
AudioProcessor::BusesLayout requestedLayouts;
for (int dir = 0; dir < 2; ++dir)
@@ -2274,8 +2253,8 @@ private:
for (int busIdx = 0; busIdx < n; ++busIdx)
{
const AUIOElement* element = (busIdx < numAUElements ? GetIOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busIdx) : nullptr);
const int numChannels = (element != nullptr ? static_cast<int> (element->GetStreamFormat().NumberChannels()) : 0);
const auto* element = (busIdx < numAUElements ? &IOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busIdx) : nullptr);
const int numChannels = (element != nullptr ? static_cast<int> (element->NumberChannels()) : 0);
AudioChannelLayoutTag currentLayoutTag = isInput ? currentInputLayout[busIdx] : currentOutputLayout[busIdx];
const int tagNumChannels = currentLayoutTag & 0xffff;
@@ -2314,20 +2293,12 @@ private:
if (numChannels == 0)
return noErr;
if (AUIOElement* element = GetIOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busNr))
{
element->SetName ((CFStringRef) juceStringToNS (juceFilter->getBus (isInput, busNr)->getName()));
CAStreamBasicDescription streamDescription;
streamDescription.mSampleRate = getSampleRate();
auto& element = IOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, (UInt32) busNr);
streamDescription.SetCanonical ((UInt32) numChannels, false);
return element->SetStreamFormat (streamDescription);
}
else
jassertfalse;
element.SetName ((CFStringRef) juceStringToNS (juceFilter->getBus (isInput, busNr)->getName()));
return kAudioUnitErr_InvalidElement;
const auto streamDescription = ausdk::ASBD::CreateCommonFloat32 (getSampleRate(), (UInt32) numChannels);
return element.SetStreamFormat (streamDescription);
}
//==============================================================================
@@ -2355,14 +2326,16 @@ private:
}
//==============================================================================
Array<AudioChannelLayoutTag>& getSupportedBusLayouts (bool isInput, int bus) noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); }
const Array<AudioChannelLayoutTag>& getSupportedBusLayouts (bool isInput, int bus) const noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); }
std::vector<AudioChannelLayoutTag>& getSupportedBusLayouts (bool isInput, int bus) noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); }
const std::vector<AudioChannelLayoutTag>& getSupportedBusLayouts (bool isInput, int bus) const noexcept { return (isInput ? supportedInputLayouts : supportedOutputLayouts).getReference (bus); }
AudioChannelLayoutTag& getCurrentLayout (bool isInput, int bus) noexcept { return (isInput ? currentInputLayout : currentOutputLayout).getReference (bus); }
AudioChannelLayoutTag getCurrentLayout (bool isInput, int bus) const noexcept { return (isInput ? currentInputLayout : currentOutputLayout)[bus]; }
//==============================================================================
void addSupportedLayoutTagsForBus (bool isInput, int busNum, Array<AudioChannelLayoutTag>& tags)
std::vector<AudioChannelLayoutTag> getSupportedLayoutTagsForBus (bool isInput, int busNum) const
{
std::set<AudioChannelLayoutTag> tags;
if (AudioProcessor::Bus* bus = juceFilter->getBus (isInput, busNum))
{
#ifndef JucePlugin_PreferredChannelConfigurations
@@ -2370,7 +2343,7 @@ private:
for (auto tag : knownTags)
if (bus->isLayoutSupported (CoreAudioLayouts::fromCoreAudio (tag)))
tags.addIfNotAlreadyThere (tag);
tags.insert (tag);
#endif
// add discrete layout tags
@@ -2384,10 +2357,12 @@ private:
tags.addIfNotAlreadyThere (static_cast<AudioChannelLayoutTag> ((int) kAudioChannelLayoutTag_DiscreteInOrder | ch));
#else
if (bus->isLayoutSupported (AudioChannelSet::discreteChannels (ch)))
tags.addIfNotAlreadyThere (static_cast<AudioChannelLayoutTag> ((int) kAudioChannelLayoutTag_DiscreteInOrder | ch));
tags.insert (static_cast<AudioChannelLayoutTag> ((int) kAudioChannelLayoutTag_DiscreteInOrder | ch));
#endif
}
}
return std::vector<AudioChannelLayoutTag> (tags.begin(), tags.end());
}
void addSupportedLayoutTagsForDirection (bool isInput)
@@ -2397,12 +2372,7 @@ private:
auto numBuses = AudioUnitHelpers::getBusCount (*juceFilter, isInput);
for (int busNr = 0; busNr < numBuses; ++busNr)
{
Array<AudioChannelLayoutTag> busLayouts;
addSupportedLayoutTagsForBus (isInput, busNr, busLayouts);
layouts.add (busLayouts);
}
layouts.add (getSupportedLayoutTagsForBus (isInput, busNr));
}
void addSupportedLayoutTags()
@@ -2425,10 +2395,10 @@ private:
void auPropertyListener (AudioUnitPropertyID propId, AudioUnitScope scope, AudioUnitElement)
{
if (scope == kAudioUnitScope_Global && propId == kAudioUnitProperty_ContextName
&& juceFilter != nullptr && mContextName != nullptr)
&& juceFilter != nullptr && GetContextName() != nullptr)
{
AudioProcessor::TrackProperties props;
props.name = String::fromCFString (mContextName);
props.name = String::fromCFString (GetContextName());
juceFilter->updateTrackProperties (props);
}
@@ -2444,48 +2414,17 @@ private:
};
//==============================================================================
#define JUCE_COMPONENT_ENTRYX(Class, Name, Suffix) \
extern "C" __attribute__((visibility("default"))) ComponentResult Name ## Suffix (ComponentParameters* params, Class* obj); \
extern "C" __attribute__((visibility("default"))) ComponentResult Name ## Suffix (ComponentParameters* params, Class* obj) \
{ \
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnit; \
return ComponentEntryPoint<Class>::Dispatch (params, obj); \
}
#if JucePlugin_ProducesMidiOutput || JucePlugin_WantsMidiInput || JucePlugin_IsMidiEffect
#define FACTORY_BASE_CLASS AUMIDIEffectFactory
#define FACTORY_BASE_CLASS ausdk::AUMusicDeviceFactory
#else
#define FACTORY_BASE_CLASS AUBaseFactory
#endif
#define JUCE_FACTORY_ENTRYX(Class, Name) \
extern "C" __attribute__((visibility("default"))) void* Name ## Factory (const AudioComponentDescription* desc); \
extern "C" __attribute__((visibility("default"))) void* Name ## Factory (const AudioComponentDescription* desc) \
{ \
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AudioUnit; \
return FACTORY_BASE_CLASS<Class>::Factory (desc); \
}
#define JUCE_COMPONENT_ENTRY(Class, Name, Suffix) JUCE_COMPONENT_ENTRYX(Class, Name, Suffix)
#define JUCE_FACTORY_ENTRY(Class, Name) JUCE_FACTORY_ENTRYX(Class, Name)
//==============================================================================
JUCE_COMPONENT_ENTRY (JuceAU, JucePlugin_AUExportPrefix, Entry)
#ifndef AUDIOCOMPONENT_ENTRY
#define JUCE_DISABLE_AU_FACTORY_ENTRY 1
#endif
#if ! JUCE_DISABLE_AU_FACTORY_ENTRY // (You might need to disable this for old Xcode 3 builds)
JUCE_FACTORY_ENTRY (JuceAU, JucePlugin_AUExportPrefix)
#define FACTORY_BASE_CLASS ausdk::AUBaseFactory
#endif
#if ! JUCE_DISABLE_AU_FACTORY_ENTRY
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align", "-Wzero-as-null-pointer-constant")
AUSDK_COMPONENT_ENTRY (FACTORY_BASE_CLASS, JuceAU)
#include "CoreAudioUtilityClasses/AUPlugInDispatch.cpp"
#define JUCE_AU_ENTRY_POINT_NAME JUCE_CONCAT (JucePlugin_AUExportPrefix, Factory)
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
#endif
extern "C" void* JUCE_AU_ENTRY_POINT_NAME (const AudioComponentDescription* inDesc);
AUSDK_EXPORT extern "C" void* JUCE_AU_ENTRY_POINT_NAME (const AudioComponentDescription* inDesc) { return JuceAUFactory (inDesc); }
#endif

+ 0
- 150
modules/juce_audio_plugin_client/AUResources.r View File

@@ -1,150 +0,0 @@
/*
File: AUResources.r
Abstract: AUResources.r
Version: 1.1
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AUResources.r
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* sample macro definitions -- all of these symbols must be defined
#define RES_ID kHALOutputResID
#define COMP_TYPE kAudioUnitComponentType
#define COMP_SUBTYPE kAudioUnitOutputSubType
#define COMP_MANUF kAudioUnitAudioHardwareOutputSubSubType
#define VERSION 0x00010000
#define NAME "AudioHALOutput"
#define DESCRIPTION "Audio hardware output AudioUnit"
#define ENTRY_POINT "AUHALEntry"
*/
#define UseExtendedThingResource 1

#include <CoreServices/CoreServices.r>

// this is a define used to indicate that a component has no static data that would mean
// that no more than one instance could be open at a time - never been true for AUs
#ifndef cmpThreadSafeOnMac
#define cmpThreadSafeOnMac 0x10000000
#endif

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

resource 'STR ' (RES_ID, purgeable) {
NAME
};

resource 'STR ' (RES_ID + 1, purgeable) {
DESCRIPTION
};

resource 'dlle' (RES_ID) {
ENTRY_POINT
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

resource 'thng' (RES_ID, NAME) {
COMP_TYPE,
COMP_SUBTYPE,
COMP_MANUF,
0, 0, 0, 0, // no 68K
'STR ', RES_ID,
'STR ', RES_ID + 1,
0, 0, /* icon */
VERSION,
componentHasMultiplePlatforms | componentDoAutoVersion,
0,
{
#if defined(ppc_YES)
cmpThreadSafeOnMac,
'dlle', RES_ID, platformPowerPCNativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(ppc64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, platformPowerPC64NativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(i386_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, platformIA32NativeEntryPoint
#define NeedLeadingComma 1
#endif
#if defined(x86_64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, 8
#define NeedLeadingComma 1
#endif
// JUCE CHANGE STARTS HERE
#if defined(arm64_YES)
#if defined(NeedLeadingComma)
,
#endif
cmpThreadSafeOnMac,
'dlle', RES_ID, 9
#define NeedLeadingComma 1
#endif
// JUCE CHANGE ENDS HERE
}
};

#undef RES_ID
#undef COMP_TYPE
#undef COMP_SUBTYPE
#undef COMP_MANUF
#undef VERSION
#undef NAME
#undef DESCRIPTION
#undef ENTRY_POINT
#undef NeedLeadingComma

+ 0
- 50
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r View File

@@ -1,50 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
Agreement and JUCE Privacy Policy.
End User License Agreement: www.juce.com/juce-7-licence
Privacy Policy: www.juce.com/juce-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
#define UseExtendedThingResource 1
#include <AudioUnit.r>
//==============================================================================
/* The JucePluginDefines file should be a file in your project, containing info to describe the
plugin's name, type, etc. The Projucer will generate this file automatically for you.
You may need to adjust the include path of your project to make sure it can be
found by this include statement. (Don't hack this file to change the include path)
*/
#include "JucePluginDefines.h"
//==============================================================================
// component resources for Audio Unit
#define RES_ID 1000
#define COMP_TYPE JucePlugin_AUMainType
#define COMP_SUBTYPE JucePlugin_AUSubType
#define COMP_MANUF JucePlugin_AUManufacturerCode
#define VERSION JucePlugin_VersionCode
#define NAME JucePlugin_Manufacturer ": " JucePlugin_Name
#define DESCRIPTION JucePlugin_Desc
#define ENTRY_POINT JucePlugin_AUExportPrefixQuoted "Entry"
#include "AUResources.r"

+ 36
- 15
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm View File

@@ -60,21 +60,42 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wparentheses",
#define verify_noerr(errorCode) __Verify_noErr(errorCode)
#endif
#include "AU/CoreAudioUtilityClasses/AUBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUBuffer.cpp"
#include "AU/CoreAudioUtilityClasses/AUDispatch.cpp"
#include "AU/CoreAudioUtilityClasses/AUInputElement.cpp"
#include "AU/CoreAudioUtilityClasses/AUMIDIBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUOutputBase.cpp"
#include "AU/CoreAudioUtilityClasses/AUOutputElement.cpp"
#include "AU/CoreAudioUtilityClasses/AUScopeElement.cpp"
#include "AU/CoreAudioUtilityClasses/CAAUParameter.cpp"
#include "AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp"
#include "AU/CoreAudioUtilityClasses/CAMutex.cpp"
#include "AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp"
#include "AU/CoreAudioUtilityClasses/CAVectorUnit.cpp"
#include "AU/CoreAudioUtilityClasses/ComponentBase.cpp"
#include "AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp"
#if ! defined (MAC_OS_VERSION_11_0) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_11_0
// These constants are only defined in the macOS 11+ SDKs
enum MIDICVStatus : unsigned int
{
kMIDICVStatusNoteOff = 0x8,
kMIDICVStatusNoteOn = 0x9,
kMIDICVStatusPolyPressure = 0xA,
kMIDICVStatusControlChange = 0xB,
kMIDICVStatusProgramChange = 0xC,
kMIDICVStatusChannelPressure = 0xD,
kMIDICVStatusPitchBend = 0xE,
kMIDICVStatusRegisteredPNC = 0x0,
kMIDICVStatusAssignablePNC = 0x1,
kMIDICVStatusRegisteredControl = 0x2,
kMIDICVStatusAssignableControl = 0x3,
kMIDICVStatusRelRegisteredControl = 0x4,
kMIDICVStatusRelAssignableControl = 0x5,
kMIDICVStatusPerNotePitchBend = 0x6,
kMIDICVStatusPerNoteMgmt = 0xF
};
#endif
#include "AU/AudioUnitSDK/AUBase.cpp"
#include "AU/AudioUnitSDK/AUBuffer.cpp"
#include "AU/AudioUnitSDK/AUBufferAllocator.cpp"
#include "AU/AudioUnitSDK/AUEffectBase.cpp"
#include "AU/AudioUnitSDK/AUInputElement.cpp"
#include "AU/AudioUnitSDK/AUMIDIBase.cpp"
#include "AU/AudioUnitSDK/AUMIDIEffectBase.cpp"
#include "AU/AudioUnitSDK/AUOutputElement.cpp"
#include "AU/AudioUnitSDK/AUPlugInDispatch.cpp"
#include "AU/AudioUnitSDK/AUScopeElement.cpp"
#include "AU/AudioUnitSDK/ComponentBase.cpp"
#include "AU/AudioUnitSDK/MusicDeviceBase.cpp"
#undef verify
#undef verify_noerr


Loading…
Cancel
Save