├── .gitignore ├── .gitmodules ├── .vs └── launch.vs.json ├── CMakeLists.txt ├── CMakeSettings.json ├── ChangeLog.txt ├── ExamplesCommon ├── Archives │ ├── Archives.cpp │ └── Archives.h ├── AudioFiles │ ├── AudioFiles.cpp │ └── AudioFiles.h ├── PlugInHosting │ ├── AudioUnitLoader.h │ ├── AudioUnitLoader.m │ ├── CLAPLoader.c │ ├── CLAPLoader.h │ ├── VST3Loader.cpp │ └── VST3Loader.h ├── SignalProcessing │ ├── PulsedSineSignal.c │ └── PulsedSineSignal.h ├── Utilities │ └── StdUniquePtrUtilities.h ├── Windows │ ├── ARAExamples.ico │ ├── ARAExamples.rc │ └── desktop.ini └── macOS │ ├── ARAExamples-FolderIcon │ ├── ARAExamples.entitlements │ ├── ARAExamples.icns │ └── AddFolderIcon.sh ├── LICENSE.txt ├── MiniHost └── MiniHost.c ├── NOTICE.txt ├── README.md ├── TestHost ├── ARADocumentController.cpp ├── ARADocumentController.h ├── ARAHostInterfaces │ ├── ARAArchivingController.cpp │ ├── ARAArchivingController.h │ ├── ARAAudioAccessController.cpp │ ├── ARAAudioAccessController.h │ ├── ARAContentAccessController.cpp │ ├── ARAContentAccessController.h │ ├── ARAModelUpdateController.cpp │ ├── ARAModelUpdateController.h │ ├── ARAPlaybackController.cpp │ └── ARAPlaybackController.h ├── CompanionAPIs.cpp ├── CompanionAPIs.h ├── IPC │ ├── IPCMessageChannel.cpp │ ├── IPCMessageChannel.h │ ├── IPCXMLEncoding.cpp │ └── IPCXMLEncoding.h ├── ModelObjects.cpp ├── ModelObjects.h ├── TestCases.cpp ├── TestCases.h ├── TestHost.cpp ├── TestHost.h └── main.cpp └── TestPlugIn ├── ARATestAudioSource.cpp ├── ARATestAudioSource.h ├── ARATestDocumentController.cpp ├── ARATestDocumentController.h ├── ARATestPlaybackRenderer.cpp ├── ARATestPlaybackRenderer.h ├── AudioFileChunkWriter └── ARATestChunkWriter.cpp ├── AudioUnit ├── TestAudioUnit.cpp ├── TestAudioUnit.h ├── TestAudioUnitInfo.plist └── mangle-plugin-version.sh ├── AudioUnit_v3 ├── App │ ├── TestAUv3App.entitlements │ ├── TestAUv3App.m │ ├── TestAUv3App.xib │ └── TestAUv3AppInfo.plist ├── Extension │ ├── TestAUv3Extension.entitlements │ ├── TestAUv3Extension.m │ └── TestAUv3ExtensionInfo.plist └── Framework │ ├── BufferedAudioBus.hpp │ ├── TestAUv3AudioUnit.h │ ├── TestAUv3AudioUnit.mm │ ├── TestAUv3DSPKernel.hpp │ ├── TestAUv3Factory.h │ ├── TestAUv3Factory.m │ └── TestAUv3FrameworkInfo.plist ├── CLAP ├── TestCLAPInfo.plist └── TestCLAPPlugIn.cpp ├── TestAnalysis.cpp ├── TestAnalysis.h ├── TestPersistency.cpp ├── TestPersistency.h ├── TestPlugInConfig.h └── VST3 ├── ARATestMainFactory.h ├── TestVST3Entry.cpp ├── TestVST3Info.plist ├── TestVST3Processor.cpp └── TestVST3Processor.h /.gitignore: -------------------------------------------------------------------------------- 1 | $RECYCLE.BIN 2 | .fseventsd 3 | .Trashes 4 | .DS_Store 5 | .vscode 6 | .vs 7 | *.ncb 8 | *.suo 9 | *.sdf 10 | *.opensdf 11 | *.pbxuser 12 | *.perspectivev3 13 | *.user 14 | *.xcworkspacedata 15 | *.VC.db* 16 | *.VC.opendb* 17 | *.ipch 18 | version.properties 19 | xcuserdata 20 | ARTIFACTS 21 | build 22 | out 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rdParty/cpp-base64"] 2 | path = 3rdParty/cpp-base64 3 | url = https://github.com/ReneNyffenegger/cpp-base64 4 | shallow = true 5 | [submodule "3rdParty/pugixml"] 6 | path = 3rdParty/pugixml 7 | url = https://github.com/zeux/pugixml 8 | shallow = true 9 | [submodule "3rdParty/ICST_AudioFile"] 10 | path = 3rdParty/ICST_AudioFile 11 | url = https://github.com/Celemony/ICST_AudioFile 12 | shallow = true 13 | -------------------------------------------------------------------------------- /.vs/launch.vs.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.1", 3 | "defaults": {}, 4 | "configurations": [ 5 | { 6 | "type": "default", 7 | "project": "CMakeLists.txt", 8 | "projectTarget": "ARATestHost.exe (bin\\ARATestHost.exe)", 9 | "name": "ARATestHost.exe w/ ARATestPlugIn.vst3", 10 | "args": [ 11 | "-vst3 ARATestPlugIn.vst3" 12 | ] 13 | }, 14 | { 15 | "type": "default", 16 | "project": "CMakeLists.txt", 17 | "projectTarget": "validator.exe (bin\\validator.exe)", 18 | "name": "validator.exe w/ ARATestPlugIn.vst3", 19 | "args": [ 20 | "ARATestPlugIn.vst3" 21 | ] 22 | }, 23 | { 24 | "type": "default", 25 | "project": "CMakeLists.txt", 26 | "projectTarget": "ARAMiniHost.exe (bin\\ARAMiniHost.exe)", 27 | "name": "ARAMiniHost.exe w/ ARATestPlugIn.vst3" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "x64-Debug", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ "msvc_x64_x64" ], 8 | "buildRoot": "${projectDir}\\out\\build\\${name}", 9 | "installRoot": "${projectDir}\\out\\install\\${name}", 10 | "cmakeCommandArgs": "", 11 | "buildCommandArgs": "", 12 | "ctestCommandArgs": "", 13 | "variables": [] 14 | }, 15 | { 16 | "name": "x64-Release", 17 | "generator": "Ninja", 18 | "configurationType": "Release", 19 | "buildRoot": "${projectDir}\\out\\build\\${name}", 20 | "installRoot": "${projectDir}\\out\\install\\${name}", 21 | "cmakeCommandArgs": "", 22 | "buildCommandArgs": "", 23 | "ctestCommandArgs": "", 24 | "inheritEnvironments": [ "msvc_x64_x64" ], 25 | "variables": [] 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /ExamplesCommon/Archives/Archives.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file Archives.cpp 3 | //! archive classes used by e.g. ARATestHost to save/restore plug-in state 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "Archives.h" 27 | 28 | #include "ARA_Library/Debug/ARADebug.h" 29 | 30 | #include 31 | 32 | /*******************************************************************************/ 33 | 34 | std::streamsize ArchiveBase::getArchiveSize () noexcept 35 | { 36 | try 37 | { 38 | if (!_dataStream.good ()) 39 | return 0; 40 | 41 | const auto initialPos { _dataStream.tellg () }; 42 | _dataStream.seekg (0, _dataStream.end); 43 | const auto fileSize { _dataStream.tellg () }; 44 | _dataStream.seekg (initialPos, _dataStream.beg); 45 | 46 | return fileSize; 47 | } 48 | catch (const std::exception& e) 49 | { 50 | ARA_WARN ("%s", e.what ()); 51 | ARA_INTERNAL_ASSERT (false); 52 | return 0; 53 | } 54 | } 55 | 56 | bool ArchiveBase::readBytes (std::streamoff position, std::streamsize length, char buffer[]) noexcept 57 | { 58 | try 59 | { 60 | if (!_dataStream.good ()) 61 | return false; 62 | 63 | _dataStream.seekg (position); 64 | ARA_INTERNAL_ASSERT (_dataStream.good ()); 65 | 66 | _dataStream.read (buffer, length); 67 | return _dataStream.good (); 68 | } 69 | catch (const std::exception& e) 70 | { 71 | ARA_WARN ("%s", e.what ()); 72 | ARA_INTERNAL_ASSERT (false); 73 | return false; 74 | } 75 | } 76 | 77 | bool ArchiveBase::writeBytes (std::streamoff position, std::streamsize length, const char buffer[]) noexcept 78 | { 79 | try 80 | { 81 | if (!_dataStream.good ()) 82 | return false; 83 | 84 | _dataStream.seekg (position, std::ios::beg); 85 | ARA_INTERNAL_ASSERT (_dataStream.good ()); 86 | 87 | _dataStream.write (buffer, length); 88 | return _dataStream.good (); 89 | } 90 | catch (const std::exception& e) 91 | { 92 | ARA_WARN ("%s", e.what ()); 93 | ARA_INTERNAL_ASSERT (false); 94 | return false; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ExamplesCommon/Archives/Archives.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file Archives.h 3 | //! archive classes used by e.g. ARATestHost to save/restore plug-in state 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | class ArchiveBase 33 | { 34 | protected: 35 | ArchiveBase (std::iostream& dataStream, const std::string& documentArchiveID) : _dataStream { dataStream }, _documentArchiveID { documentArchiveID } {} 36 | 37 | public: 38 | std::streamsize getArchiveSize () noexcept; 39 | bool readBytes (std::streamoff position, std::streamsize length, char buffer[]) noexcept; 40 | bool writeBytes (std::streamoff position, std::streamsize length, const char buffer[]) noexcept; 41 | 42 | const std::string& getDocumentArchiveID () const noexcept { return _documentArchiveID; } 43 | 44 | private: 45 | std::iostream& _dataStream; 46 | const std::string _documentArchiveID; 47 | }; 48 | 49 | /*******************************************************************************/ 50 | 51 | // In-memory archive, using the optional provided std::string as initial data. 52 | // \todo With C++20, this could be optimized: 53 | // an external string would always be required and it would be directly used 54 | // as backing for the stream, preventing all the current temporary copies. 55 | class MemoryArchive : public ArchiveBase 56 | { 57 | public: 58 | // create empty 59 | MemoryArchive (const std::string& documentArchiveID) : ArchiveBase { _stream, documentArchiveID } {} 60 | // create with copy of existing data 61 | MemoryArchive (const std::string& data, const std::string& documentArchiveID) : ArchiveBase { _stream, documentArchiveID }, _stream { data } {} 62 | 63 | // copy current data 64 | operator std::string () const noexcept { return _stream.str (); } 65 | 66 | private: 67 | std::stringstream _stream; 68 | }; 69 | -------------------------------------------------------------------------------- /ExamplesCommon/AudioFiles/AudioFiles.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file AudioFiles.h 3 | //! classes representing audio files 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include "3rdParty/ICST_AudioFile/AudioFile.h" 23 | 24 | #include 25 | #include 26 | 27 | class ARAiXMLChunk; 28 | 29 | /*******************************************************************************/ 30 | 31 | // Abstract interface for audio files. 32 | class AudioFileBase 33 | { 34 | public: 35 | AudioFileBase (const std::string& name) : _name { name } {} 36 | virtual ~AudioFileBase () { setiXMLChunk (nullptr); } 37 | 38 | virtual int64_t getSampleCount () const noexcept = 0; 39 | virtual double getSampleRate () const noexcept = 0; 40 | virtual int getChannelCount () const noexcept = 0; 41 | virtual bool merits64BitSamples () const noexcept = 0; 42 | 43 | virtual bool readSamples (int64_t samplePosition, int64_t samplesPerChannel, 44 | void* const buffers[], bool use64BitSamples) noexcept = 0; 45 | 46 | std::string getiXMLARAAudioSourceData (const std::string& documentArchiveID, bool& openAutomatically, 47 | std::string& plugInName, std::string& plugInVersion, 48 | std::string& manufacturer, std::string& informationURL, 49 | std::string& persistentID); 50 | void setiXMLARAAudioSourceData (const std::string& documentArchiveID, bool openAutomatically, 51 | const std::string& plugInName, const std::string& plugInVersion, 52 | const std::string& manufacturer, const std::string& informationURL, 53 | const std::string& persistentID, const std::string& data); 54 | 55 | virtual bool saveToFile (const std::string& path) = 0; 56 | 57 | const std::string& getName () const noexcept { return _name; } 58 | void setName (const std::string& name) noexcept { _name = name; } 59 | 60 | protected: 61 | const ARAiXMLChunk* getiXMLChunk () const noexcept { return _iXMLChunk; } 62 | void setiXMLChunk (ARAiXMLChunk* chunk) noexcept; 63 | 64 | private: 65 | std::string _name; 66 | ARAiXMLChunk* _iXMLChunk { nullptr }; 67 | }; 68 | 69 | /*******************************************************************************/ 70 | 71 | // Dummy in-memory audio file based on a generated pulsed sine wave. 72 | class SineAudioFile : public AudioFileBase 73 | { 74 | public: 75 | SineAudioFile (const std::string& name, double duration, double sampleRate, int channelCount); 76 | SineAudioFile (const std::string& name, int64_t sampleCount, double sampleRate, int channelCount); 77 | 78 | int64_t getSampleCount () const noexcept override { return _sampleCount; } 79 | double getSampleRate () const noexcept override { return _sampleRate; } 80 | int getChannelCount () const noexcept override { return _channelCount; } 81 | bool merits64BitSamples () const noexcept override { return true; } 82 | 83 | bool readSamples (int64_t samplePosition, int64_t samplesPerChannel, 84 | void* const buffers[], bool use64BitSamples) noexcept override; 85 | 86 | bool saveToFile (const std::string& path) override; 87 | 88 | private: 89 | int64_t _sampleCount; 90 | double _sampleRate; 91 | int _channelCount; 92 | }; 93 | 94 | /*******************************************************************************/ 95 | 96 | // Encapsulation of a WAVE or AIFF audio file. 97 | class AudioDataFile : public AudioFileBase 98 | { 99 | public: 100 | AudioDataFile (const std::string& name, icstdsp::AudioFile&& audioFile); 101 | 102 | int64_t getSampleCount () const noexcept override { return _audioFile.GetSize (); } 103 | double getSampleRate () const noexcept override { return _audioFile.GetRate (); } 104 | int getChannelCount () const noexcept override { return static_cast (_audioFile.GetChannels ()); } 105 | bool merits64BitSamples () const noexcept override { return false; } 106 | 107 | bool readSamples (int64_t samplePosition, int64_t samplesPerChannel, 108 | void* const buffers[], bool use64BitSamples) noexcept override; 109 | 110 | bool saveToFile (const std::string& path) override; 111 | 112 | private: 113 | icstdsp::AudioFile _audioFile; 114 | }; 115 | -------------------------------------------------------------------------------- /ExamplesCommon/PlugInHosting/AudioUnitLoader.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file AudioUnitLoader.h 3 | //! Audio Unit specific ARA implementation for the SDK's hosting examples 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #include "ARA_API/ARAInterface.h" 22 | #include "ARA_Library/Debug/ARADebug.h" 23 | #include "ARA_Library/IPC/ARAIPC.h" 24 | 25 | #include 26 | 27 | #if defined(__cplusplus) 28 | extern "C" 29 | { 30 | #endif 31 | 32 | typedef struct _AudioUnitComponent * AudioUnitComponent; 33 | typedef struct _AudioUnitInstance * AudioUnitInstance; 34 | 35 | AudioUnitComponent AudioUnitPrepareComponentWithIDs(OSType type, OSType subtype, OSType manufacturer); 36 | bool AudioUnitIsV2(AudioUnitComponent audioUnitComponent); 37 | AudioUnitInstance AudioUnitOpenInstance(AudioUnitComponent audioUnitComponent, bool useIPC); 38 | // On return, *connection will be NULL if Audio Unit does not use IPC, otherwise it will point to 39 | // a valid message channel for all factory-related calls until AudioUnitCleanupComponent() is called. 40 | const ARA_NAMESPACE ARAFactory * AudioUnitGetARAFactory(AudioUnitInstance audioUnit, ARA_IPC_NAMESPACE ARAIPCConnectionRef * connectionRef); 41 | const ARA_NAMESPACE ARAPlugInExtensionInstance * AudioUnitBindToARADocumentController(AudioUnitInstance audioUnit, ARA_NAMESPACE ARADocumentControllerRef controllerRef, ARA_NAMESPACE ARAPlugInInstanceRoleFlags assignedRoles); 42 | void AudioUnitStartRendering(AudioUnitInstance audioUnit, UInt32 maxBlockSize, double sampleRate); 43 | void AudioUnitRenderBuffer(AudioUnitInstance audioUnit, UInt32 blockSize, SInt64 samplePosition, float * buffer); 44 | void AudioUnitStopRendering(AudioUnitInstance audioUnit); 45 | void AudioUnitCloseInstance(AudioUnitInstance audioUnit); 46 | void AudioUnitCleanupComponent(AudioUnitComponent audioUnitComponent); 47 | 48 | #if defined(__cplusplus) 49 | } // extern "C" 50 | #endif 51 | -------------------------------------------------------------------------------- /ExamplesCommon/PlugInHosting/CLAPLoader.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file CLAPLoader.h 3 | //! CLAP specific ARA implementation for the SDK's hosting examples 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2022-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! Developed in cooperation with Timo Kaluza (defiantnerd) 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #pragma once 21 | 22 | #include "ARA_API/ARAInterface.h" 23 | #include "ARA_Library/Debug/ARADebug.h" 24 | 25 | #if defined(__cplusplus) 26 | extern "C" 27 | { 28 | #endif 29 | 30 | struct _CLAPBinary; 31 | struct _CLAPPlugIn; 32 | typedef struct _CLAPBinary * CLAPBinary; 33 | typedef struct _CLAPPlugIn * CLAPPlugIn; 34 | 35 | CLAPBinary CLAPLoadBinary(const char * binaryName); 36 | const ARA_NAMESPACE ARAFactory * CLAPGetARAFactory(CLAPBinary clapBinary, const char * optionalPlugInName); 37 | CLAPPlugIn CLAPCreatePlugIn(CLAPBinary clapBinary, const char * optionalPlugInName); 38 | const ARA_NAMESPACE ARAPlugInExtensionInstance * CLAPBindToARADocumentController(CLAPPlugIn clapPlugIn, ARA_NAMESPACE ARADocumentControllerRef controllerRef, ARA_NAMESPACE ARAPlugInInstanceRoleFlags assignedRoles); 39 | void CLAPStartRendering(CLAPPlugIn clapPlugIn, uint32_t maxBlockSize, double sampleRate); 40 | void CLAPRenderBuffer(CLAPPlugIn clapPlugIn, uint32_t blockSize, int64_t samplePosition, float * buffer); 41 | void CLAPStopRendering(CLAPPlugIn clapPlugIn); 42 | void CLAPDestroyPlugIn(CLAPPlugIn clapPlugIn); 43 | void CLAPUnloadBinary(CLAPBinary clapBinary); 44 | 45 | #if defined(__cplusplus) 46 | } // extern "C" 47 | #endif 48 | -------------------------------------------------------------------------------- /ExamplesCommon/PlugInHosting/VST3Loader.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file VST3Loader.h 3 | //! VST3 specific ARA implementation for the SDK's hosting examples 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #include "ARA_API/ARAInterface.h" 22 | #include "ARA_Library/Debug/ARADebug.h" 23 | 24 | #if defined(__cplusplus) 25 | extern "C" 26 | { 27 | #endif 28 | 29 | struct _VST3Binary; 30 | struct _VST3Effect; 31 | typedef struct _VST3Binary * VST3Binary; 32 | typedef struct _VST3Effect * VST3Effect; 33 | 34 | VST3Binary VST3LoadBinary(const char * binaryName); 35 | const ARA_NAMESPACE ARAFactory * VST3GetARAFactory(VST3Binary vst3Binary, const char * optionalPlugInName); 36 | VST3Effect VST3CreateEffect(VST3Binary vst3Effect, const char * optionalPlugInName); 37 | const ARA_NAMESPACE ARAPlugInExtensionInstance * VST3BindToARADocumentController(VST3Effect vst3Effect, ARA_NAMESPACE ARADocumentControllerRef controllerRef, ARA_NAMESPACE ARAPlugInInstanceRoleFlags assignedRoles); 38 | void VST3StartRendering(VST3Effect vst3Effect, int32_t maxBlockSize, double sampleRate); 39 | void VST3RenderBuffer(VST3Effect vst3Effect, int32_t blockSize, double sampleRate, int64_t samplePosition, float * buffer); 40 | void VST3StopRendering(VST3Effect vst3Effect); 41 | void VST3DestroyEffect(VST3Effect vst3Effect); 42 | void VST3UnloadBinary(VST3Binary vst3Binary); 43 | 44 | #if defined(__cplusplus) 45 | } // extern "C" 46 | #endif 47 | -------------------------------------------------------------------------------- /ExamplesCommon/SignalProcessing/PulsedSineSignal.c: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file PulsedSineSignal.c 3 | //! creating a pulsed sine test signal for ARA examples 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #include "PulsedSineSignal.h" 20 | 21 | #include 22 | #if !defined(M_PI) 23 | #define M_PI 3.14159265358979323846264338327950288 /* taken from the macOS variant of math.h - M_PI is a custom extension of C11 */ 24 | #endif 25 | 26 | void RenderPulsedSineSignal (int64_t samplePosition, double sampleRate, int64_t sampleCount, 27 | int32_t channelCount, int64_t samplesPerChannel, 28 | void* const buffers[], bool use64BitSamples) 29 | { 30 | int64_t index = 0; 31 | while (samplesPerChannel--) 32 | { 33 | double value = 0.0; 34 | if ((0 <= samplePosition) && (samplePosition < sampleCount)) 35 | { 36 | const double normalizedTime = ((double)samplePosition) * 440.0 / sampleRate; 37 | value = (fmod (normalizedTime, 440.0) <= 220.0) ? sin (normalizedTime * M_PI * 2.0) : 0.0; 38 | value *= (fmod (normalizedTime, 880.0) <= 440.0) ? 1.0 : 0.125; 39 | } 40 | 41 | for (int32_t c = 0; c < channelCount; ++c) 42 | { 43 | if (use64BitSamples != false) 44 | ((double*) buffers[c])[index] = value; 45 | else 46 | ((float*) buffers[c])[index] = (float)value; 47 | } 48 | ++samplePosition; 49 | ++index; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ExamplesCommon/SignalProcessing/PulsedSineSignal.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file PulsedSineSignal.h 3 | //! creating a pulsed sine test signal for ARA examples 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include 23 | 24 | #if defined(__cplusplus) 25 | extern "C" 26 | { 27 | #endif 28 | 29 | // Creates a pulsed sine: half a second sine with 440 Hz, half a second silence. 30 | // Amplitude varies each other second between full scale and 1/8 scale. 31 | // Samples before 0 or at or after sampleCount are set to zero. 32 | void RenderPulsedSineSignal (int64_t samplePosition, double sampleRate, int64_t sampleCount, 33 | int32_t channelCount, int64_t samplesPerChannel, 34 | void* const buffers[], bool use64BitSamples); 35 | 36 | #if defined(__cplusplus) 37 | } // extern "C" 38 | #endif 39 | -------------------------------------------------------------------------------- /ExamplesCommon/Utilities/StdUniquePtrUtilities.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAStdUniquePtrUtilities.h 3 | //! convenience functions to assist with operations related 4 | //! to std::unique_ptr (comparison, searching in vectors) 5 | //! Also provides an implementation of std::make_unique for older compilers. 6 | //! \project ARA SDK Examples 7 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 8 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 9 | //! you may not use this file except in compliance with the License. 10 | //! You may obtain a copy of the License at 11 | //! 12 | //! http://www.apache.org/licenses/LICENSE-2.0 13 | //! 14 | //! Unless required by applicable law or agreed to in writing, software 15 | //! distributed under the License is distributed on an "AS IS" BASIS, 16 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | //! See the License for the specific language governing permissions and 18 | //! limitations under the License. 19 | //------------------------------------------------------------------------------ 20 | 21 | #ifndef StdUniquePtrUtilities_h 22 | #define StdUniquePtrUtilities_h 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace ARA { 32 | 33 | /*******************************************************************************/ 34 | // helper: std::unique_ptr comparison predicate 35 | 36 | template 37 | struct unique_ptr_compare 38 | { 39 | const T* ptr; 40 | bool operator () (const std::unique_ptr& uPtr) noexcept 41 | { 42 | return uPtr.get () == ptr; 43 | } 44 | }; 45 | 46 | /*******************************************************************************/ 47 | // Find an a raw pointer inside a vector of std::unique_ptrs in the vector and, 48 | // if found, erase it from the vector. Returns true if found & erased, otherwise false 49 | template ::value || std::is_convertible::value, bool>::type = true> 50 | inline bool find_erase (std::vector>& container, const U& ptr) 51 | { 52 | auto it = std::find_if (container.begin (), container.end (), unique_ptr_compare{ ptr }); 53 | if (it == container.end ()) 54 | return false; 55 | 56 | container.erase (it); 57 | return true; 58 | } 59 | 60 | /*******************************************************************************/ 61 | // Determine if a raw pointer exists in a vector as a std::unique_ptr 62 | 63 | template ::value || std::is_convertible::value, bool>::type = true> 64 | inline bool contains (std::vector> const& container, const U& ptr) 65 | { 66 | return std::any_of (container.begin (), container.end (), unique_ptr_compare{ ptr }); 67 | } 68 | 69 | /*******************************************************************************/ 70 | // Find position of a raw pointer inside a vector of std::unique_ptrs. 71 | template ::value || std::is_convertible::value, bool>::type = true> 72 | inline intptr_t index_of (std::vector> const& container, const U& ptr) 73 | { 74 | auto it = std::find_if (container.begin (), container.end (), unique_ptr_compare{ ptr }); 75 | if (it == container.end ()) 76 | return -1; 77 | 78 | return std::distance (container.begin (), it); 79 | } 80 | 81 | } // namespace ARA 82 | 83 | /*******************************************************************************/ 84 | // Implement std::make_unique for pre-C++14 compilers, as published by ISO here: 85 | // https://isocpp.org/files/papers/N3656.txt 86 | #if !defined (_MSC_VER) && (__cplusplus < 201402L) 87 | namespace std 88 | { 89 | template 90 | struct _Unique_if 91 | { 92 | typedef unique_ptr _Single_object; 93 | }; 94 | template 95 | struct _Unique_if 96 | { 97 | typedef unique_ptr _Unknown_bound; 98 | }; 99 | template 100 | struct _Unique_if 101 | { 102 | typedef void _Known_bound; 103 | }; 104 | 105 | template 106 | typename _Unique_if::_Single_object make_unique (Args&&... args) 107 | { 108 | return unique_ptr (new T (std::forward (args)...)); 109 | } 110 | template 111 | typename _Unique_if::_Unknown_bound make_unique (size_t n) 112 | { 113 | typedef typename remove_extent::type U; 114 | return unique_ptr (new U[n] ()); 115 | } 116 | template 117 | typename _Unique_if::_Known_bound make_unique (Args&&...) = delete; 118 | } // namespace std 119 | #endif // !defined (_MSC_VER) && (__cplusplus < 201402L) 120 | 121 | #endif // StdUniquePtrUtilities_h 122 | -------------------------------------------------------------------------------- /ExamplesCommon/Windows/ARAExamples.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Celemony/ARA_Examples/d06a2351c3a86e5455e839a8146bbc45b7c9a482/ExamplesCommon/Windows/ARAExamples.ico -------------------------------------------------------------------------------- /ExamplesCommon/Windows/ARAExamples.rc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAExamples.rc 3 | //! Windows resource fork implementation for the ARA examples. 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #include 20 | 21 | #define APSTUDIO_READONLY_SYMBOLS 22 | 23 | #pragma code_page(65001) 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | // Converting macro values to strings 27 | 28 | #define _IN_QUOTES_HELPER(x) #x 29 | #define IN_QUOTES(x) _IN_QUOTES_HELPER(x) 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | // Version 33 | 34 | #define COMPANY_NAME "ARA SDK Examples" 35 | #define COPYRIGHT_YEAR "2012-2025" 36 | #define LEGAL_TRADEMARKS "ARA Audio Random Access is a trademark of Celemony Software GmbH. VST is a trademark of Steinberg Media Technologies GmbH." 37 | 38 | // \todo we're currently only building either .exe or .vst3, so checking ARA_TARGET_TYPE_... this way is sufficient for now 39 | // A clean solution would be to provide a distinct executable type as argument to ara_add_default_settings() instead of relying 40 | // on $ (which would also allow to integrate ara_configure_binary_package() there entirely). 41 | #ifdef ARA_TARGET_TYPE_EXECUTABLE 42 | #define FILE_TYPE VFT_APP 43 | #define FILE_EXTENSION ".exe" 44 | #define FILE_DESCRIPTION "application" 45 | #define ICON_PATH "ARAExamples.ico" 46 | #else 47 | #define FILE_TYPE VFT_DLL 48 | #define FILE_EXTENSION ".vst3" 49 | #define FILE_DESCRIPTION "VST3 plug-in" 50 | #endif 51 | 52 | 53 | VS_VERSION_INFO VERSIONINFO 54 | FILEVERSION ARA_MAJOR_VERSION,ARA_MINOR_VERSION,ARA_PATCH_VERSION,ARA_BUILD_VERSION 55 | PRODUCTVERSION ARA_MAJOR_VERSION,ARA_MINOR_VERSION,ARA_PATCH_VERSION,ARA_BUILD_VERSION 56 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 57 | #ifdef _DEBUG 58 | FILEFLAGS VS_FF_DEBUG 59 | #else 60 | FILEFLAGS 0 61 | #endif 62 | FILEOS VOS_NT_WINDOWS32 63 | FILETYPE FILE_TYPE 64 | FILESUBTYPE VFT2_UNKNOWN 65 | BEGIN 66 | BLOCK "StringFileInfo" 67 | BEGIN 68 | BLOCK "000004B0" 69 | BEGIN 70 | VALUE "CompanyName", COMPANY_NAME "\0" 71 | VALUE "FileVersion", IN_QUOTES(ARA_MAJOR_VERSION) "." IN_QUOTES(ARA_MINOR_VERSION) "." IN_QUOTES(ARA_PATCH_VERSION) "." IN_QUOTES(ARA_BUILD_VERSION) "\0" 72 | VALUE "FileDescription", ARA_TARGET_NAME " " FILE_DESCRIPTION "\0" 73 | VALUE "InternalName", ARA_TARGET_NAME "\0" 74 | VALUE "LegalCopyright", "© " COPYRIGHT_YEAR " " COMPANY_NAME "\0" 75 | VALUE "LegalTrademarks", LEGAL_TRADEMARKS "\0" 76 | VALUE "OriginalFilename", ARA_TARGET_NAME FILE_EXTENSION "\0" 77 | VALUE "ProductName", ARA_TARGET_NAME "\0" 78 | VALUE "ProductVersion", IN_QUOTES(ARA_MAJOR_VERSION) "." IN_QUOTES(ARA_MINOR_VERSION) "." IN_QUOTES(ARA_PATCH_VERSION) "\0" 79 | END 80 | END 81 | BLOCK "VarFileInfo" 82 | BEGIN 83 | VALUE "Translation", 0x0000, 0x04B0 84 | END 85 | END 86 | 87 | ///////////////////////////////////////////////////////////////////////////// 88 | // Icon 89 | 90 | #ifdef ICON_PATH 91 | // Icon with lowest ID value placed first to ensure application icon 92 | // remains consistent on all systems. 93 | IDI_ICON1 ICON ICON_PATH 94 | #endif 95 | -------------------------------------------------------------------------------- /ExamplesCommon/Windows/desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | IconResource=BundleIcon.ico,0 3 | ;For compatibility with Windows XP 4 | IconFile=BundleIcon.ico 5 | IconIndex=0 6 | -------------------------------------------------------------------------------- /ExamplesCommon/macOS/ARAExamples-FolderIcon: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Celemony/ARA_Examples/d06a2351c3a86e5455e839a8146bbc45b7c9a482/ExamplesCommon/macOS/ARAExamples-FolderIcon -------------------------------------------------------------------------------- /ExamplesCommon/macOS/ARAExamples.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-unsigned-executable-memory 6 | 7 | com.apple.security.cs.disable-library-validation 8 | 9 | com.apple.security.get-task-allow 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ExamplesCommon/macOS/ARAExamples.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Celemony/ARA_Examples/d06a2351c3a86e5455e839a8146bbc45b7c9a482/ExamplesCommon/macOS/ARAExamples.icns -------------------------------------------------------------------------------- /ExamplesCommon/macOS/AddFolderIcon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cp "${0%/*}"'/ARAExamples-FolderIcon' "$1"$'/Icon\r' 3 | setfile -a V "$1"$'/Icon\r' 4 | setfile -a C "$1" 5 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | ARA Audio Random Access Examples 2 | Copyright 2012-2025, Celemony Software GmbH, All Rights Reserved. 3 | 4 | This product is published under the Apache 2.0 license. 5 | 6 | This product bundles cpp-base64, developed by René Nyffenegger, 7 | which is available under the "zlib" license. 8 | For details, see 3rdParty/cpp-base64. 9 | 10 | This product bundles pugixml, developed by Arseny Kapoulkine, 11 | which is available under the "MIT" license. 12 | For details, see 3rdParty/pugixml. 13 | 14 | This product bundles the AudioFile component of the ICST DSP library, 15 | extended to read and write iXML data chunks, developed by 16 | Celemony Software GmbH, which is available under the "2-clause BSD" license. 17 | For details, see 3rdParty/ICST_AudioFile. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ARA Audio Random Access: Examples 2 | 3 | Copyright (c) 2012-2025, [Celemony Software GmbH](https://www.celemony.com), All Rights Reserved. 4 | Published under the Apache 2.0 license. 5 | 6 | The ARA_Examples Git repository contains various sample code demonstrating how to both implement 7 | and host ARA enabled plug-ins. They are provided both as a mean to debug your implementation and 8 | as a blueprint for building your own ARA applications. 9 | 10 | Developers should use the [full ARA_SDK installer](https://github.com/Celemony/ARA_SDK) which 11 | includes this repository along with the core ARA API specification, an extensive C++ library to ease 12 | ARA development, and full documentation. 13 | 14 | Any public release of ARA-enabled software should be based on a tagged public release of the ARA API. 15 | If temporarily using HEAD to study current work-in-progress, keep in mind that in order to achieve a 16 | concise long-term change history, any changes since the last tagged release may eventually be rebased. 17 | 18 | 19 | ## Companion APIs 20 | 21 | Creating ARA-enabled products relies on using at least one of the various established audio plug-in 22 | formats as "companion APIs". The CMake code allows for setting path variables to your local copies 23 | of these SDKs: `ARA_VST3_SDK_DIR` and `ARA_AUDIO_UNIT_SDK_DIR`. If needed, installing the SDKs 24 | can be done using the [ARA SDK Installer](https://github.com/Celemony/ARA_SDK). 25 | 26 | 27 | ## 3rd party submodules 28 | 29 | For generic tasks such as reading .wav files or applying Base64 encodings, some examples rely on 30 | external dependencies, see separate [3rd party README](3rdParty/README.md). These dependencies 31 | have separate licensing conditions as laid out in each project, but they should be fully compatible 32 | with ARA's terms and conditions for typical use cases. 33 | 34 | The external projects are integrated as shallow Git submodules. When using CMake these will be 35 | automatically be fetched, otherwise this can be triggered explicitly with this Git command: 36 | 37 | git submodule update --init --recursive 38 | 39 | 40 | ## Examples overview 41 | 42 | - Mini Host 43 | The ARAMiniHost example is a very minimal ARA host application written using the pure C ARA API 44 | that demonstrates the basic ARA plug-in life cycle in a host. 45 | 46 | - Test Plug-In 47 | This Audio Unit and VST3 plug-in utilizes the `ARAPlug` classes from the ARA library and can be 48 | used as a template for creating ARA-enabled plug-ins. It executes a (fake) analysis of the audio 49 | material including proper export of the resulting ARA content data and provides pass-through 50 | ARA rendering and proper persistency. 51 | It also features extensive validation and logging capabilities that make it very useful when 52 | developing ARA host applications. 53 | The actual plug-in is accompanied by a standalone ARATestChunkWriter tool for creating 54 | ARA audio file chunks for the plug-in. 55 | 56 | - Test Host 57 | The ARATestHost is a command line utility that can be used to load and debug ARA plug-ins. 58 | It implements many test scenarios that relate to real-life use cases. 59 | Please see `main.cpp` for a description of its command line arguments and `TestCases.h` 60 | for a list of tests that can be executed. 61 | The ARATestHost also serves as a demonstration for how to implement the various 62 | ARA hosting interfaces, and for how to load ARA enabled plug-ins using the VST3 or AudioUnit 63 | companion APIs. 64 | It also implements optionally running the plug-in in a separate address space, controlled via IPC. 65 | 66 | 67 | ## Building and running the examples 68 | 69 | Building the ARA examples relies on CMake 3.12 or newer. Using CMake 3.19 or newer is highly 70 | recommended, debugger support requires at least 3.13 for Visual Studio and 3.15 for Xcode. 71 | To create a project for your development environment of choice, from within the ARA_Examples folder 72 | execute this CMake command line (in older CMake versions, omit the whitespace after -B/-G/-A): 73 | 74 | cmake -B -G -A 75 | 76 | This assume you've installed the companion API SDKs using the optional install scripts from the 77 | ARA SDK installer. If you want to instead provide local copies of those SDKs, specify them like so: 78 | 79 | cmake -D ARA_VST3_SDK_DIR=/path/to/vst3sdk/ -D ARA_AUDIO_UNIT_SDK_DIR=/path/to/AudioUnit_SDK/ 80 | 81 | Note that while it is possible to directly open the ARA_Examples folder in Visual Studio 2017 or 82 | newer utilizing its integrated CMake support, we still recommend creating an explicit solution due 83 | to its superior project layout and debugger support, e.g. for VS2019: 84 | 85 | cmake -B build -G "Visual Studio 16 2019" -A x64 86 | 87 | To properly handle signing and packaging on macOS, the CMake support is currently explicitly 88 | limited to creating an Xcode project. Further, in order to run in sandbox environments such as 89 | Audio Unit v3 via XPC, you need to specify your development team and code sign identity: 90 | 91 | cmake -B build -G "Xcode" -D CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=1234567890 -D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY="Apple Development" 92 | 93 | On Linux, the examples in general are still in an experimental state, but have been successfully 94 | tested on Ubuntu 18.04 with GCC 8.3.0 and clang 7.0 using make as build system: 95 | 96 | cd ARA_SDK/ARA_Examples # Enter the ARA_Examples directory 97 | mkdir build # Create a CMake 'out of source' build directory 98 | cd build # Enter the build directory 99 | cmake .. # Execute cmake command to generate a GNU Makefile 100 | make # Compile the examples 101 | 102 | To run the VST3 mini host (which automatically loads `ARATestPlugIn.vst3`), from within your build 103 | directory execute: 104 | 105 | ./bin/Debug/ARAMiniHost 106 | 107 | To run the test host example e.g. using the VST3 variant of the ARATestPlugIn: 108 | 109 | ./bin/Debug/TestHost -vst3 ARATestPlugIn.vst3 110 | 111 | Or for the Audio Unit version on macOS: 112 | 113 | ./bin/Debug/TestHost -au aufx AraT ADeC 114 | 115 | Or use the optional CLAP variant: 116 | 117 | ./bin/Debug/TestHost -clap ARATestPlugIn.clap 118 | 119 | To to run the plug-in in a separate process connected via IPC, use -ipc_vst3 or -ipc_au or 120 | -ipc_clap instead of -vst3 or -au or -clap. 121 | 122 | Where applicable (Visual Studio solution, Xcode project), debugging a plug-in target will per 123 | default launch the validator application provided by the companion API. Debugging with the 124 | ARATestHost will per default launch the SDK's ARATestPlugIn example in its VST3 incarnation. 125 | Note that on macOS, debugging an Audio Unit with Apple's `auvaltool` might not be possible on your 126 | machine due to System Integrity Protection. You will need to run `auvaltool` without attaching the 127 | debugger in that case (by unchecking "Debug executable" in the scheme's "Run" tab). 128 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAArchivingController.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAArchivingController.cpp 3 | //! implementation of the host ARAArchivingControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "ARAArchivingController.h" 27 | 28 | // A reference to the TestArchive instance will be passed to this function, 29 | // which we can use to query the size of the archive's file stream 30 | ARA::ARASize ARAArchivingController::getArchiveSize (ARA::ARAArchiveReaderHostRef archiveReaderHostRef) noexcept 31 | { 32 | const auto archive = fromHostRef (archiveReaderHostRef); 33 | ARA_VALIDATE_API_ARGUMENT (archiveReaderHostRef, archive != nullptr); 34 | ARA_VALIDATE_API_STATE (_araDocumentController->isUsingArchive (archive)); 35 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 36 | 37 | return static_cast (archive->getArchiveSize ()); 38 | } 39 | 40 | // A reference to the TestArchive instance will be passed to this function, 41 | // and we can use it to read from the test archive into the supplied output buffer 42 | bool ARAArchivingController::readBytesFromArchive (ARA::ARAArchiveReaderHostRef archiveReaderHostRef, ARA::ARASize position, ARA::ARASize length, ARA::ARAByte buffer[]) noexcept 43 | { 44 | const auto archive = fromHostRef (archiveReaderHostRef); 45 | ARA_VALIDATE_API_ARGUMENT (archiveReaderHostRef, archive != nullptr); 46 | ARA_VALIDATE_API_STATE (_araDocumentController->isUsingArchive (archive)); 47 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 48 | ARA_VALIDATE_API_ARGUMENT (nullptr, 0 < length); 49 | ARA_VALIDATE_API_ARGUMENT (nullptr, position + length <= getArchiveSize (archiveReaderHostRef)); 50 | 51 | return archive->readBytes (static_cast (position), static_cast (length), reinterpret_cast (buffer)); 52 | } 53 | 54 | // Like the above function, but instead of streaming bytes into a data buffer we'll 55 | // write data into our TestArchive instance. 56 | bool ARAArchivingController::writeBytesToArchive (ARA::ARAArchiveWriterHostRef archiveWriterHostRef, ARA::ARASize position, ARA::ARASize length, const ARA::ARAByte buffer[]) noexcept 57 | { 58 | auto archive = fromHostRef (archiveWriterHostRef); 59 | ARA_VALIDATE_API_ARGUMENT (archiveWriterHostRef, archive != nullptr); 60 | ARA_VALIDATE_API_STATE (_araDocumentController->isUsingArchive (archive)); 61 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 62 | ARA_VALIDATE_API_ARGUMENT (nullptr, 0 < length); 63 | 64 | return archive->writeBytes (static_cast (position), static_cast (length), reinterpret_cast (buffer)); 65 | } 66 | 67 | // The plug-in will call these progress notification functions, which we can 68 | // use to keep track of its archiving/unarchiving progress 69 | void ARAArchivingController::notifyDocumentArchivingProgress (float value) noexcept 70 | { 71 | ARA_VALIDATE_API_STATE (_araDocumentController->isUsingArchive ()); 72 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 73 | ARA_LOG ("document archiving progress is %.f%%.", 100.0 * value); 74 | } 75 | 76 | void ARAArchivingController::notifyDocumentUnarchivingProgress (float value) noexcept 77 | { 78 | ARA_VALIDATE_API_STATE (_araDocumentController->isUsingArchive ()); 79 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 80 | ARA_LOG ("document unarchiving progress is %.f%%.", 100.0 * value); 81 | } 82 | 83 | ARA::ARAPersistentID ARAArchivingController::getDocumentArchiveID (ARA::ARAArchiveReaderHostRef archiveReaderHostRef) noexcept 84 | { 85 | const auto archive = fromHostRef (archiveReaderHostRef); 86 | ARA_VALIDATE_API_STATE (_araDocumentController->isUsingArchive (archive)); 87 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 88 | return archive->getDocumentArchiveID ().c_str (); 89 | } 90 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAArchivingController.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAArchivingController.h 3 | //! implementation of the host ARAArchivingControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include "ARADocumentController.h" 29 | 30 | /*******************************************************************************/ 31 | // Implementation of our test host's archiving controller interface 32 | // The plug-in will call these functions when reading and writing its document archive 33 | // and to notify the host of archiving progress notifications while reading / writing 34 | class ARAArchivingController : public ARA::Host::ArchivingControllerInterface 35 | { 36 | public: 37 | ARAArchivingController (ARADocumentController* araDocumentController) noexcept 38 | : _araDocumentController { araDocumentController } 39 | {} 40 | 41 | ARA::ARASize getArchiveSize (ARA::ARAArchiveReaderHostRef archiveReaderHostRef) noexcept override; 42 | bool readBytesFromArchive (ARA::ARAArchiveReaderHostRef archiveReaderHostRef, ARA::ARASize position, ARA::ARASize length, ARA::ARAByte buffer[]) noexcept override; 43 | bool writeBytesToArchive (ARA::ARAArchiveWriterHostRef archiveWriterHostRef, ARA::ARASize position, ARA::ARASize length, const ARA::ARAByte buffer[]) noexcept override; 44 | void notifyDocumentArchivingProgress (float value) noexcept override; 45 | void notifyDocumentUnarchivingProgress (float value) noexcept override; 46 | ARA::ARAPersistentID getDocumentArchiveID (ARA::ARAArchiveReaderHostRef archiveReaderHostRef) noexcept override; 47 | 48 | private: 49 | ARADocumentController* _araDocumentController; 50 | }; 51 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAAudioAccessController.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAAudioAccessController.cpp 3 | //! implementation of the host ARAAudioAccessControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "ARAAudioAccessController.h" 27 | 28 | #include 29 | 30 | /*******************************************************************************/ 31 | 32 | bool AudioSourceReader::readSamples (ARA::ARASamplePosition samplePosition, ARA::ARASampleCount samplesPerChannel, void* const buffers[]) const noexcept 33 | { 34 | return _audioSource->getAudioFile ()->readSamples (samplePosition, samplesPerChannel, buffers, _use64BitSamples); 35 | } 36 | 37 | /*******************************************************************************/ 38 | 39 | #if ARA_VALIDATE_API_CALLS 40 | std::mutex _renderThreadMutex; 41 | std::vector _renderThreadIDs; 42 | 43 | void ARAAudioAccessController::registerRenderThread () 44 | { 45 | std::lock_guard guard (_renderThreadMutex); 46 | _renderThreadIDs.push_back (std::this_thread::get_id ()); 47 | } 48 | 49 | void ARAAudioAccessController::unregisterRenderThread () 50 | { 51 | std::lock_guard guard (_renderThreadMutex); 52 | const bool success { ARA::find_erase (_renderThreadIDs, std::this_thread::get_id ()) }; 53 | ARA_INTERNAL_ASSERT (success); 54 | } 55 | #endif 56 | 57 | // Create an audio reader for the given audio source - because we have no real audio reader object, we instead 58 | // treat the reference this function returns as a "key" that we'll use when reading this audio source 59 | ARA::ARAAudioReaderHostRef ARAAudioAccessController::createAudioReaderForSource (ARA::ARAAudioSourceHostRef audioSourceHostRef, bool use64BitSamples) noexcept 60 | { 61 | const auto audioSource = fromHostRef (audioSourceHostRef); 62 | ARA_VALIDATE_API_ARGUMENT (audioSourceHostRef, ARA::contains (getDocument ()->getAudioSources (), audioSource)); 63 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 64 | #if ARA_VALIDATE_API_CALLS 65 | std::lock_guard guard (_audioSourceReadersMutex); 66 | #endif 67 | _audioSourceReaders.emplace_back (std::make_unique (audioSource, use64BitSamples)); 68 | return toHostRef (_audioSourceReaders.back ().get ()); 69 | } 70 | 71 | // If this function gets passed the "key" reference returned by the function above then we can use it 72 | // to render audio samples into to the supplied buffers - the audio samples will form a pulsed sine wave at 440 Hz 73 | bool ARAAudioAccessController::readAudioSamples (ARA::ARAAudioReaderHostRef audioReaderHostRef, ARA::ARASamplePosition samplePosition, ARA::ARASampleCount samplesPerChannel, void* const buffers[]) noexcept 74 | { 75 | const auto audioSourceReader = fromHostRef (audioReaderHostRef); 76 | #if ARA_VALIDATE_API_CALLS 77 | { 78 | std::lock_guard guard (_renderThreadMutex); 79 | ARA_VALIDATE_API_THREAD (!ARA::contains (_renderThreadIDs, std::this_thread::get_id ())); 80 | } 81 | { 82 | std::lock_guard guard (_audioSourceReadersMutex); 83 | ARA_VALIDATE_API_ARGUMENT (audioReaderHostRef, ARA::contains (_audioSourceReaders, audioSourceReader)); 84 | } 85 | #endif 86 | ARA_VALIDATE_API_ARGUMENT (nullptr, samplesPerChannel >= 0); 87 | ARA_VALIDATE_API_ARGUMENT (buffers, buffers != nullptr); 88 | for (int i = 0; i < audioSourceReader->getAudioSource ()->getChannelCount (); ++i) 89 | ARA_VALIDATE_API_ARGUMENT (buffers, buffers[i] != nullptr); 90 | return audioSourceReader->readSamples (samplePosition, samplesPerChannel, buffers); 91 | } 92 | 93 | // We don't need to actually destroy anything here, but it's worth validating that 94 | // the reference we're meant to destroy is our original "key" reference 95 | void ARAAudioAccessController::destroyAudioReader (ARA::ARAAudioReaderHostRef audioReaderHostRef) noexcept 96 | { 97 | const auto audioSourceReader = fromHostRef (audioReaderHostRef); 98 | #if ARA_VALIDATE_API_CALLS 99 | std::lock_guard guard (_audioSourceReadersMutex); 100 | #endif 101 | ARA_VALIDATE_API_ARGUMENT (audioReaderHostRef, ARA::contains (_audioSourceReaders, audioSourceReader)); 102 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 103 | ARA::find_erase (_audioSourceReaders, audioSourceReader); 104 | } 105 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAAudioAccessController.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAAudioAccessController.h 3 | //! implementation of the host ARAAudioAccessControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include "ARADocumentController.h" 29 | 30 | #include 31 | 32 | /*******************************************************************************/ 33 | // Simple audio source reader class that will be passed to readAudioSamples 34 | // as the 'ARAAudioReaderHostRef audioReaderHostRef' parameter. 35 | class AudioSourceReader 36 | { 37 | public: 38 | explicit AudioSourceReader (const AudioSource* audioSource, bool use64BitSamples) noexcept 39 | : _audioSource { audioSource }, 40 | _use64BitSamples { use64BitSamples } 41 | {} 42 | 43 | const AudioSource* getAudioSource () const noexcept { return _audioSource; } 44 | 45 | bool readSamples (ARA::ARASamplePosition samplePosition, ARA::ARASampleCount samplesPerChannel, void* const buffers[]) const noexcept; 46 | 47 | private: 48 | const AudioSource* _audioSource; 49 | const bool _use64BitSamples; 50 | 51 | ARA_PLUGIN_MANAGED_OBJECT (AudioSourceReader) 52 | }; 53 | ARA_MAP_HOST_REF (AudioSourceReader, ARA::ARAAudioReaderHostRef) 54 | 55 | /*******************************************************************************/ 56 | // Implementation of our test host's audio access controller interface 57 | // The plug-in will call these functions when reading audio samples 58 | class ARAAudioAccessController : public ARA::Host::AudioAccessControllerInterface 59 | { 60 | public: 61 | ARAAudioAccessController (ARADocumentController* araDocumentController) noexcept 62 | : _araDocumentController { araDocumentController } 63 | {} 64 | 65 | // Create an audio reader for the given audio source - because we have no real audio reader object, we instead 66 | // treat the reference this function returns as a "key" that we'll use when reading this audio source 67 | ARA::ARAAudioReaderHostRef createAudioReaderForSource (ARA::ARAAudioSourceHostRef audioSourceHostRef, bool use64BitSamples) noexcept override; 68 | 69 | // If this function gets passed the "key" reference returned by the function above then we can use it 70 | // to render audio samples into to the supplied buffers - the audio samples will form a pulsed sine wave at 440 Hz 71 | bool readAudioSamples (ARA::ARAAudioReaderHostRef audioReaderHostRef, ARA::ARASamplePosition samplePosition, ARA::ARASampleCount samplesPerChannel, void* const buffers[]) noexcept override; 72 | 73 | // We don't need to actually destroy anything here, but it's worth validating that 74 | // the reference we're meant to destroy is our original "key" reference 75 | void destroyAudioReader (ARA::ARAAudioReaderHostRef audioReaderHostRef) noexcept override; 76 | 77 | Document* getDocument () const noexcept { return _araDocumentController->getDocument (); } 78 | 79 | #if ARA_VALIDATE_API_CALLS 80 | static void registerRenderThread (); 81 | static void unregisterRenderThread (); 82 | #endif 83 | 84 | private: 85 | ARADocumentController* _araDocumentController; 86 | std::vector> _audioSourceReaders; 87 | #if ARA_VALIDATE_API_CALLS 88 | std::mutex _audioSourceReadersMutex; 89 | #endif 90 | }; 91 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAContentAccessController.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAContentAccessController.h 3 | //! implementation of the host ARAContentAccessControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include "ARADocumentController.h" 29 | 30 | /*******************************************************************************/ 31 | // Simple content reader class that will be passed as ARAContentReaderHostRef 32 | class HostDataContentReader 33 | { 34 | public: 35 | virtual ~HostDataContentReader () = default; 36 | 37 | virtual bool hasData () const noexcept = 0; 38 | virtual const void* getDataForEvent (ARA::ARAInt32 eventIndex) const noexcept = 0; 39 | virtual ARA::ARAInt32 getEventCount () const noexcept = 0; 40 | 41 | protected: 42 | HostDataContentReader () = default; 43 | ARA_PLUGIN_MANAGED_OBJECT (HostDataContentReader) 44 | }; 45 | ARA_MAP_HOST_REF (HostDataContentReader, ARA::ARAContentReaderHostRef) 46 | 47 | 48 | /*******************************************************************************/ 49 | // Implementation of our test host's content access controller interface 50 | // We'll use it here to give the plug-in information about the content of our musical context or audio sources 51 | class ARAContentAccessController : public ARA::Host::ContentAccessControllerInterface 52 | { 53 | public: 54 | ARAContentAccessController (ARADocumentController* araDocumentController) noexcept 55 | : _araDocumentController { araDocumentController } 56 | {} 57 | 58 | bool isMusicalContextContentAvailable (ARA::ARAMusicalContextHostRef musicalContextHostRef, ARA::ARAContentType type) noexcept override; 59 | ARA::ARAContentGrade getMusicalContextContentGrade (ARA::ARAMusicalContextHostRef musicalContextHostRef, ARA::ARAContentType type) noexcept override; 60 | ARA::ARAContentReaderHostRef createMusicalContextContentReader (ARA::ARAMusicalContextHostRef musicalContextHostRef, ARA::ARAContentType type, const ARA::ARAContentTimeRange* range) noexcept override; 61 | 62 | bool isAudioSourceContentAvailable (ARA::ARAAudioSourceHostRef audioSourceHostRef, ARA::ARAContentType type) noexcept override; 63 | ARA::ARAContentGrade getAudioSourceContentGrade (ARA::ARAAudioSourceHostRef audioSourceHostRef, ARA::ARAContentType type) noexcept override; 64 | ARA::ARAContentReaderHostRef createAudioSourceContentReader (ARA::ARAAudioSourceHostRef audioSourceHostRef, ARA::ARAContentType type, const ARA::ARAContentTimeRange* range) noexcept override; 65 | 66 | ARA::ARAInt32 getContentReaderEventCount (ARA::ARAContentReaderHostRef contentReaderHostRef) noexcept override; 67 | const void* getContentReaderDataForEvent (ARA::ARAContentReaderHostRef contentReaderHostRef, ARA::ARAInt32 eventIndex) noexcept override; 68 | void destroyContentReader (ARA::ARAContentReaderHostRef contentReaderHostRef) noexcept override; 69 | 70 | private: 71 | static std::unique_ptr createContentReader (const ContentContainer* contentContainer, const ARA::ARAContentType type); 72 | static bool isContentAvailable (const ContentContainer* contentContainer, const ARA::ARAContentType type); 73 | static ARA::ARAContentGrade getContentGrade (const ContentContainer* contentContainer, const ARA::ARAContentType type); 74 | 75 | Document* getDocument () const noexcept { return _araDocumentController->getDocument (); } 76 | 77 | private: 78 | std::vector> _hostDataContentReaders; 79 | ARADocumentController* _araDocumentController; 80 | }; 81 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAModelUpdateController.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAModelUpdateController.cpp 3 | //! implementation of the host ARAModelUpdateControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "ARAModelUpdateController.h" 27 | #include "ARA_Library/Debug/ARAContentLogger.h" 28 | 29 | // The plug-in will call this function to notify us of audio source analysis progress 30 | // In this case we make sure that it's one of our known audio source "key" references 31 | // and, if so, log a message indicating its analysis progress 32 | void ARAModelUpdateController::notifyAudioSourceAnalysisProgress (ARA::ARAAudioSourceHostRef audioSourceHostRef, ARA::ARAAnalysisProgressState state, float value) noexcept 33 | { 34 | const auto audioSource = fromHostRef (audioSourceHostRef); 35 | const auto audioSourceRef = _araDocumentController->getRef (audioSource); 36 | ARA_VALIDATE_API_ARGUMENT (audioSource, ARA::contains (getDocument ()->getAudioSources (), audioSource)); 37 | ARA_VALIDATE_API_ARGUMENT (nullptr, 0.0f <= value); 38 | ARA_VALIDATE_API_ARGUMENT (nullptr, value <= 1.0f); 39 | ARA_VALIDATE_API_STATE (_araDocumentController->isPollingModelUpdates ()); 40 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 41 | 42 | switch (state) 43 | { 44 | case ARA::kARAAnalysisProgressStarted: 45 | { 46 | ARA_VALIDATE_API_STATE (_audioSourceAnalysisProgressValues.count (audioSource) == 0); 47 | ARA_LOG ("audio source %p (ARAAudioSourceRef %p) analysis started with progress %.f%%.", audioSource, audioSourceRef, 100.0 * value); 48 | _audioSourceAnalysisProgressValues[audioSource] = value; 49 | break; 50 | } 51 | case ARA::kARAAnalysisProgressUpdated: 52 | { 53 | ARA_VALIDATE_API_STATE (_audioSourceAnalysisProgressValues.count (audioSource) != 0); 54 | ARA_VALIDATE_API_STATE (_audioSourceAnalysisProgressValues[audioSource] <= value); 55 | ARA_LOG ("audio source %p (ARAAudioSourceRef %p) analysis progress is %.f%%.", audioSource, audioSourceRef, 100.0 * value); 56 | _audioSourceAnalysisProgressValues[audioSource] = value; 57 | break; 58 | } 59 | case ARA::kARAAnalysisProgressCompleted: 60 | { 61 | ARA_VALIDATE_API_STATE (_audioSourceAnalysisProgressValues.count (audioSource) != 0); 62 | ARA_VALIDATE_API_STATE (_audioSourceAnalysisProgressValues[audioSource] <= value); 63 | ARA_LOG ("audio source %p (ARAAudioSourceRef %p) analysis finished with progress %.f%%.", audioSource, audioSourceRef, 100.0 * value); 64 | _audioSourceAnalysisProgressValues.erase (audioSource); 65 | break; 66 | } 67 | default: 68 | { 69 | ARA_VALIDATE_API_ARGUMENT (nullptr, false && "invalid progress state"); 70 | break; 71 | } 72 | } 73 | } 74 | 75 | // The plug-in will call this function to let us know that it has some sort of new content for an audio source 76 | // This could happen if, say, the plug-in detects notes within an audio source 77 | void ARAModelUpdateController::notifyAudioSourceContentChanged (ARA::ARAAudioSourceHostRef audioSourceHostRef, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes scopeFlags) noexcept 78 | { 79 | const auto audioSource = fromHostRef (audioSourceHostRef); 80 | ARA_VALIDATE_API_ARGUMENT (audioSource, ARA::contains (getDocument ()->getAudioSources (), audioSource)); 81 | ARA_VALIDATE_API_ARGUMENT (range, (range == nullptr) || (0.0 <= range->duration)); 82 | ARA_VALIDATE_API_ARGUMENT (nullptr, scopeFlags.affectEverything () || !scopeFlags.affectSamples ()); 83 | ARA_VALIDATE_API_STATE (_araDocumentController->isPollingModelUpdates ()); 84 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 85 | 86 | if (_minimalContentUpdateLogging) 87 | ARA_LOG ("content of audio source %p (ARAAudioSource ref %p) was updated from %.3f to %.3f, flags 0x%X", audioSource, _araDocumentController->getRef (audioSource), ARA::ContentLogger::getStartOfRange (range), ARA::ContentLogger::getEndOfRange (range), scopeFlags); 88 | else 89 | ARA::ContentLogger::logUpdatedContent (*_araDocumentController->getDocumentController (), _araDocumentController->getRef (audioSource), range, scopeFlags); 90 | } 91 | 92 | // Similar to notifyAudioSourceContentChanged but with a change in scope - now it's limited to a change in an audio modification 93 | // (many ARA 2 hosts don't need to concern themselves with this) 94 | void ARAModelUpdateController::notifyAudioModificationContentChanged (ARA::ARAAudioModificationHostRef audioModificationHostRef, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes scopeFlags) noexcept 95 | { 96 | const auto audioModification = fromHostRef (audioModificationHostRef); 97 | ARA_VALIDATE_API_ARGUMENT (audioModification, ARA::contains (getDocument ()->getAudioSources (), audioModification->getAudioSource ())); 98 | ARA_VALIDATE_API_ARGUMENT (audioModification, ARA::contains (audioModification->getAudioSource ()->getAudioModifications (), audioModification)); 99 | ARA_VALIDATE_API_ARGUMENT (range, (range == nullptr) || (0.0 <= range->duration)); 100 | ARA_VALIDATE_API_STATE (_araDocumentController->isPollingModelUpdates ()); 101 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 102 | 103 | if (_minimalContentUpdateLogging) 104 | ARA_LOG ("content of audio modification %p (ARAAudioModificationRef ref %p) was updated from %.3f to %.3f, flags 0x%X", audioModification, _araDocumentController->getRef (audioModification), ARA::ContentLogger::getStartOfRange (range), ARA::ContentLogger::getEndOfRange (range), scopeFlags); 105 | else 106 | ARA::ContentLogger::logUpdatedContent (*_araDocumentController->getDocumentController (), _araDocumentController->getRef (audioModification), range, scopeFlags); 107 | } 108 | 109 | // Similar to notifyAudioSourceContentChanged but with a change in scope - now it's limited to a change with a playback region 110 | void ARAModelUpdateController::notifyPlaybackRegionContentChanged (ARA::ARAPlaybackRegionHostRef playbackRegionHostRef, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes scopeFlags) noexcept 111 | { 112 | const auto playbackRegion = fromHostRef (playbackRegionHostRef); 113 | ARA_VALIDATE_API_ARGUMENT (playbackRegion, ARA::contains (getDocument ()->getRegionSequences (), playbackRegion->getRegionSequence ())); 114 | ARA_VALIDATE_API_ARGUMENT (playbackRegion, ARA::contains (playbackRegion->getRegionSequence ()->getPlaybackRegions (), playbackRegion)); 115 | ARA_VALIDATE_API_ARGUMENT (range, (range == nullptr) || (0.0 <= range->duration)); 116 | ARA_VALIDATE_API_STATE (_araDocumentController->isPollingModelUpdates ()); 117 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 118 | 119 | if (_minimalContentUpdateLogging) 120 | ARA_LOG ("content of playback region %p (ARAPlaybackRegionRef ref %p) was updated from %.3f to %.3f, flags 0x%X", playbackRegion, _araDocumentController->getRef (playbackRegion), ARA::ContentLogger::getStartOfRange (range), ARA::ContentLogger::getEndOfRange (range), scopeFlags); 121 | else 122 | ARA::ContentLogger::logUpdatedContent (*_araDocumentController->getDocumentController (), _araDocumentController->getRef (playbackRegion), range, scopeFlags); 123 | } 124 | 125 | void ARAModelUpdateController::notifyDocumentDataChanged () noexcept 126 | { 127 | ARA_VALIDATE_API_STATE (_araDocumentController->isPollingModelUpdates ()); 128 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 129 | 130 | ARA_LOG ("document data was updated"); 131 | } 132 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAModelUpdateController.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAModelUpdateController.h 3 | //! implementation of the host ARAModelUpdateControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include "ARADocumentController.h" 29 | 30 | /*******************************************************************************/ 31 | // Implementation of our test host's model update controller interface 32 | // The plug-in will call these functions to notify the host of changes 33 | // in audio or musical content and post analysis progress notifications 34 | class ARAModelUpdateController : public ARA::Host::ModelUpdateControllerInterface 35 | { 36 | public: 37 | ARAModelUpdateController (ARADocumentController* araDocumentController) noexcept 38 | : _araDocumentController { araDocumentController } 39 | {} 40 | 41 | // The plug-in will call this function to notify us of audio source analysis progress 42 | // In this case we make sure that it's one of our known audio source "key" references 43 | // and, if so, log a message indicating its analysis progress 44 | void notifyAudioSourceAnalysisProgress (ARA::ARAAudioSourceHostRef audioSourceHostRef, ARA::ARAAnalysisProgressState state, float value) noexcept override; 45 | 46 | // The plug-in will call this function to let us know that it has some sort of new content for an audio source 47 | // This could happen if, say, the plug-in detects notes within an audio source 48 | void notifyAudioSourceContentChanged (ARA::ARAAudioSourceHostRef audioSourceHostRef, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes scopeFlags) noexcept override; 49 | 50 | // Similar to notifyAudioSourceContentChanged but with a change in scope - now it's limited to a change in an audio modification 51 | // (note that since ARA 2, in many situations it is preferable to instead read the newly added playback region content) 52 | void notifyAudioModificationContentChanged (ARA::ARAAudioModificationHostRef audioModificationHostRef, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes scopeFlags) noexcept override; 53 | 54 | // Similar to notifyAudioSourceContentChanged but with a change in scope - now it's limited to a change with a playback region 55 | void notifyPlaybackRegionContentChanged (ARA::ARAPlaybackRegionHostRef playbackRegionHostRef, const ARA::ARAContentTimeRange* range, ARA::ContentUpdateScopes scopeFlags) noexcept override; 56 | 57 | void notifyDocumentDataChanged () noexcept override; 58 | 59 | void setMinimalContentUpdateLogging (bool flag) { _minimalContentUpdateLogging = flag; } 60 | 61 | private: 62 | Document* getDocument () const noexcept { return _araDocumentController->getDocument (); } 63 | 64 | ARADocumentController* _araDocumentController; 65 | std::map _audioSourceAnalysisProgressValues; 66 | 67 | bool _minimalContentUpdateLogging { false }; 68 | }; 69 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAPlaybackController.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAPlaybackController.cpp 3 | //! implementation of the host ARAPlaybackControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "ARAPlaybackController.h" 27 | 28 | void ARAPlaybackController::requestStartPlayback () noexcept 29 | { 30 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 31 | ARA_WARN ("requestStartPlayback () not implemented."); 32 | } 33 | 34 | void ARAPlaybackController::requestStopPlayback () noexcept 35 | { 36 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 37 | ARA_WARN ("requestStopPlayback () not implemented"); 38 | } 39 | 40 | void ARAPlaybackController::requestSetPlaybackPosition (ARA::ARATimePosition timePosition) noexcept 41 | { 42 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 43 | ARA_WARN ("requestSetPlaybackPosition () not implemented, requested time is %.2f", timePosition); 44 | } 45 | 46 | void ARAPlaybackController::requestSetCycleRange (ARA::ARATimePosition startTime, ARA::ARATimeDuration duration) noexcept 47 | { 48 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 49 | ARA_WARN ("requestSetCycleRange () not implemented, requested range is %.2f to %.2f", startTime, startTime + duration); 50 | } 51 | 52 | void ARAPlaybackController::requestEnableCycle (bool enable) noexcept 53 | { 54 | ARA_VALIDATE_API_THREAD (_araDocumentController->wasCreatedOnCurrentThread ()); 55 | ARA_WARN ("requestEnableCycle () not implemented, requested to turn %s.", enable ? "on" : "off"); 56 | } 57 | -------------------------------------------------------------------------------- /TestHost/ARAHostInterfaces/ARAPlaybackController.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARAPlaybackController.h 3 | //! implementation of the host ARAPlaybackControllerInterface 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include "ARA_Library/Dispatch/ARAHostDispatch.h" 29 | 30 | #include "ARADocumentController.h" 31 | 32 | /*******************************************************************************/ 33 | // Implementation of our test host's playback controller interface 34 | // Since we aren't a real host this doesn't do anything, but it's the 35 | // plug-in's means of controller the host transport 36 | class ARAPlaybackController : public ARA::Host::PlaybackControllerInterface 37 | { 38 | public: 39 | ARAPlaybackController (ARADocumentController* araDocumentController) noexcept 40 | : _araDocumentController { araDocumentController } 41 | {} 42 | 43 | void requestStartPlayback () noexcept override; 44 | void requestStopPlayback () noexcept override; 45 | void requestSetPlaybackPosition (ARA::ARATimePosition timePosition) noexcept override; 46 | void requestSetCycleRange (ARA::ARATimePosition startTime, ARA::ARATimeDuration duration) noexcept override; 47 | void requestEnableCycle (bool enable) noexcept override; 48 | 49 | private: 50 | ARADocumentController* const _araDocumentController; 51 | }; 52 | -------------------------------------------------------------------------------- /TestHost/CompanionAPIs.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file CompanionAPIs.h 3 | //! used by the test host to load a companion API plug-in binary 4 | //! and create / destroy plug-in instances with ARA2 roles 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 20 | // of several companion APIs, creates a small model, performs various tests and 21 | // sanity checks and shuts everything down again. 22 | // This educational example is not suitable for production code - for the sake 23 | // of readability of the code, proper error handling or dealing with optional 24 | // ARA API elements is left out. 25 | //------------------------------------------------------------------------------ 26 | 27 | #pragma once 28 | 29 | #include "ARA_Library/Debug/ARADebug.h" 30 | #include "ARA_Library/Dispatch/ARAHostDispatch.h" 31 | 32 | #include "ARA_Library/IPC/ARAIPC.h" 33 | 34 | #include 35 | #include 36 | 37 | 38 | /*******************************************************************************/ 39 | // Wrapper class for a companion API plug-in instance 40 | class PlugInInstance 41 | { 42 | protected: 43 | PlugInInstance () {} 44 | 45 | public: 46 | // Instances will be created through the factory PlugInEntry::createPlugInInstance() 47 | virtual ~PlugInInstance () = default; 48 | 49 | // Execute the ARA binding 50 | virtual void bindToDocumentControllerWithRoles (ARA::ARADocumentControllerRef documentControllerRef, ARA::ARAPlugInInstanceRoleFlags assignedRoles) = 0; 51 | 52 | // Companion API specific implementations 53 | virtual void startRendering (int maxBlockSize, double sampleRate) = 0; 54 | virtual void renderSamples (int blockSize, int64_t samplePosition, float* buffer) = 0; 55 | virtual void stopRendering () = 0; 56 | 57 | // Getters for ARA specific plug-in role interfaces 58 | ARA::Host::PlaybackRenderer getPlaybackRenderer () { return ARA::Host::PlaybackRenderer { _instance }; } 59 | ARA::Host::EditorRenderer getEditorRenderer () { return ARA::Host::EditorRenderer { _instance }; } 60 | ARA::Host::EditorView getEditorView () { return ARA::Host::EditorView { _instance }; } 61 | 62 | #if ARA_ENABLE_IPC 63 | const ARA::ARAPlugInExtensionInstance* getARAPlugInExtensionInstance () { return _instance; } 64 | #endif 65 | 66 | protected: 67 | void validateAndSetPlugInExtensionInstance (const ARA::ARAPlugInExtensionInstance* instance, ARA::ARAPlugInInstanceRoleFlags assignedRoles); 68 | 69 | private: 70 | const ARA::ARAPlugInExtensionInstance* _instance {}; 71 | }; 72 | 73 | /*******************************************************************************/ 74 | // Wrapper class for the entry into the individual companion API plug-in classes. 75 | class PlugInEntry 76 | { 77 | protected: 78 | PlugInEntry (const std::string& description) 79 | : _description { description } {} 80 | 81 | public: 82 | // Static factory function for parsing companion API plug-in binaries from command line args. 83 | // If the plug-in supports ARA, the API will be initialized using the provided assert function 84 | // and uninitialized when the resulting binary is deleted. 85 | static std::unique_ptr parsePlugInEntry (const std::vector& args); 86 | 87 | virtual ~PlugInEntry () = default; 88 | 89 | // String describing the selected plug-in 90 | const std::string& getDescription () const { return _description; } 91 | 92 | // Return pointer to factory describing the ARA plug-in (nullptr if plug-in does not support ARA) 93 | const ARA::SizedStructPtr getARAFactory () const { return _factory; } 94 | 95 | // Test if IPC is used 96 | virtual bool usesIPC () const { return false; } 97 | 98 | // If IPC is used, and the main thread is spinning in some loop for a prolonged time, 99 | // this call may be necessary to allow handling IPC in time. 100 | virtual void idleThreadForDuration (int32_t milliseconds); 101 | 102 | // Initialize ARA before creating any document controllers 103 | virtual void initializeARA (ARA::ARAAssertFunction* assertFunctionAddress); 104 | 105 | // Factory function for new ARA document controller instances 106 | virtual const ARA::ARADocumentControllerInstance* createDocumentControllerWithDocument (const ARA::ARADocumentControllerHostInstance* hostInstance, 107 | const ARA::ARADocumentProperties* properties); 108 | 109 | // Initialize ARA before after destroying all document controllers 110 | virtual void uninitializeARA (); 111 | 112 | // Factory function for new plug-in instances 113 | virtual std::unique_ptr createPlugInInstance () = 0; 114 | 115 | protected: 116 | // Implementation helper for derived classes - to be called from the c'tor, 117 | // but implemented as separate functions due to call order requirements 118 | void validateAndSetFactory (const ARA::ARAFactory* factory); 119 | 120 | // Implementation helper for initializeARA () and its overrides 121 | ARA::ARAAPIGeneration getDesiredAPIGeneration (const ARA::ARAFactory* const factory); 122 | 123 | private: 124 | const std::string _description; 125 | const ARA::ARAFactory* _factory { nullptr }; 126 | }; 127 | 128 | #if ARA_ENABLE_IPC 129 | /*******************************************************************************/ 130 | // Wrapper class for the remote process main(). 131 | namespace RemoteHost 132 | { 133 | int main (std::unique_ptr plugInEntry, const std::string& channelID); 134 | } 135 | #endif 136 | -------------------------------------------------------------------------------- /TestHost/IPC/IPCMessageChannel.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file IPCMessageChannel.h 3 | //! Proof-of-concept implementation of MessageChannel 4 | //! for the ARA SDK TestHost (error handling is limited to assertions). 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #pragma once 21 | 22 | 23 | #include "ARA_Library/IPC/ARAIPCConnection.h" 24 | 25 | #if ARA_ENABLE_IPC 26 | 27 | 28 | #if defined (_WIN32) 29 | #include 30 | #include 31 | #elif defined (__APPLE__) 32 | #include 33 | #include 34 | #else 35 | #error "IPC not yet implemented for this platform" 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | 42 | // select underlying implementation: Apple CFDictionary or a generic pugixml-based 43 | // Note that the pugixml version is much less efficient because it base64-encodes bytes 44 | // (used for large sample data) which adds encoding overhead and requires additional copies. 45 | #ifndef USE_ARA_CF_ENCODING 46 | #if defined (__APPLE__) 47 | #define USE_ARA_CF_ENCODING 1 48 | #else 49 | #define USE_ARA_CF_ENCODING 0 50 | #endif 51 | #endif 52 | 53 | 54 | // run IPC either on main thread or on background thread 55 | #ifndef USE_ARA_BACKGROUND_IPC 56 | #define USE_ARA_BACKGROUND_IPC 1 57 | #endif 58 | 59 | 60 | class IPCSendPort; 61 | class IPCReceivePort; 62 | 63 | 64 | class IPCMessageChannel : public ARA::IPC::MessageChannel 65 | { 66 | public: 67 | ~IPCMessageChannel () override; 68 | 69 | // factory functions for send and receive channels 70 | static IPCMessageChannel* createPublishingID (const std::string& channelID); 71 | static IPCMessageChannel* createConnectedToID (const std::string& channelID); 72 | 73 | // message receiving 74 | // waits up to the specified amount of milliseconds for an incoming event and processes it 75 | // returns true if some event was processed during that time 76 | bool runReceiveLoop (int32_t milliseconds); 77 | 78 | void sendMessage (ARA::IPC::MessageID messageID, ARA::IPC::MessageEncoder* encoder) override; 79 | 80 | #if !USE_ARA_BACKGROUND_IPC 81 | bool runsReceiveLoopOnCurrentThread () override; 82 | void loopUntilMessageReceived () override; 83 | #endif 84 | 85 | protected: 86 | using ARA::IPC::MessageChannel::MessageChannel; 87 | 88 | private: 89 | friend class IPCReceivePort; 90 | 91 | #if !USE_ARA_BACKGROUND_IPC 92 | std::thread::id _receiveThread { std::this_thread::get_id () }; 93 | #endif 94 | 95 | IPCSendPort* _sendPort {}; 96 | IPCReceivePort* _receivePort {}; 97 | }; 98 | 99 | #endif // ARA_ENABLE_IPC 100 | -------------------------------------------------------------------------------- /TestHost/IPC/IPCXMLEncoding.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file IPCXMLEncoding.h 3 | //! Proof-of-concept pugixml-based implementation of ARAIPCMessageEn-/Decoder 4 | //! for the ARA SDK TestHost (error handling is limited to assertions). 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #pragma once 21 | 22 | 23 | #include "ARA_Library/IPC/ARAIPCMessage.h" 24 | 25 | #if ARA_ENABLE_IPC 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #if defined (__APPLE__) 33 | #include 34 | #endif 35 | 36 | #include "3rdParty/pugixml/src/pugixml.hpp" 37 | 38 | 39 | class IPCXMLMessage 40 | { 41 | public: 42 | using MessageArgumentKey = ARA::IPC::MessageArgumentKey; 43 | 44 | protected: 45 | IPCXMLMessage (); 46 | IPCXMLMessage (std::shared_ptr dictionary, pugi::xml_node root); 47 | IPCXMLMessage (const char* data, const size_t dataSize); 48 | 49 | static const char* _getEncodedKey (const MessageArgumentKey argKey); 50 | 51 | protected: 52 | std::shared_ptr _dictionary {}; 53 | pugi::xml_node _root {}; 54 | }; 55 | 56 | 57 | class IPCXMLMessageEncoder : public IPCXMLMessage, public ARA::IPC::MessageEncoder 58 | { 59 | public: 60 | IPCXMLMessageEncoder () = default; 61 | 62 | void appendInt32 (MessageArgumentKey argKey, int32_t argValue) override; 63 | void appendInt64 (MessageArgumentKey argKey, int64_t argValue) override; 64 | void appendSize (MessageArgumentKey argKey, size_t argValue) override; 65 | void appendFloat (MessageArgumentKey argKey, float argValue) override; 66 | void appendDouble (MessageArgumentKey argKey, double argValue) override; 67 | void appendString (MessageArgumentKey argKey, const char * argValue) override; 68 | void appendBytes (MessageArgumentKey argKey, const uint8_t * argValue, size_t argSize, bool copy) override; 69 | ARA::IPC::MessageEncoder* appendSubMessage (MessageArgumentKey argKey) override; 70 | 71 | // to be used by IPCMessageChannel only: encoding to channel-internal datas format 72 | #if defined (__APPLE__) 73 | __attribute__((cf_returns_retained)) CFDataRef createEncodedMessage () const; 74 | #else 75 | std::string createEncodedMessage () const; 76 | #endif 77 | 78 | private: 79 | using IPCXMLMessage::IPCXMLMessage; 80 | 81 | pugi::xml_attribute _appendAttribute (const MessageArgumentKey argKey); 82 | }; 83 | 84 | class IPCXMLMessageDecoder : public IPCXMLMessage, public ARA::IPC::MessageDecoder 85 | { 86 | public: 87 | // to be used by IPCMessageChannel only: encoding from channel-internal datas format 88 | #if defined (__APPLE__) 89 | static IPCXMLMessageDecoder* createWithMessageData(CFDataRef data); 90 | #else 91 | static IPCXMLMessageDecoder* createWithMessageData(const char* data, const size_t dataSize); 92 | #endif 93 | 94 | bool readInt32 (MessageArgumentKey argKey, int32_t* argValue) const override; 95 | bool readInt64 (MessageArgumentKey argKey, int64_t* argValue) const override; 96 | bool readSize (MessageArgumentKey argKey, size_t* argValue) const override; 97 | bool readFloat (MessageArgumentKey argKey, float* argValue) const override; 98 | bool readDouble (MessageArgumentKey argKey, double* argValue) const override; 99 | bool readString (MessageArgumentKey argKey, const char** argValue) const override; 100 | bool readBytesSize (MessageArgumentKey argKey, size_t* argSize) const override; 101 | void readBytes (MessageArgumentKey argKey, uint8_t* argValue) const override; 102 | MessageDecoder* readSubMessage (const MessageArgumentKey argKey) const override; 103 | bool hasDataForKey (MessageArgumentKey argKey) const override; 104 | 105 | private: 106 | using IPCXMLMessage::IPCXMLMessage; 107 | 108 | mutable std::string _bytesCacheData {}; 109 | mutable MessageArgumentKey _bytesCacheKey { std::numeric_limits::max () }; 110 | }; 111 | 112 | #endif // ARA_ENABLE_IPC 113 | -------------------------------------------------------------------------------- /TestHost/ModelObjects.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ModelObjects.cpp 3 | //! classes used to build the host model graph 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "ModelObjects.h" 27 | #include "ARA_Library/Debug/ARADebug.h" 28 | 29 | /*******************************************************************************/ 30 | 31 | Document::Document (std::string name) 32 | : _name { name } 33 | {} 34 | 35 | /*******************************************************************************/ 36 | 37 | MusicalContext::MusicalContext (Document * document, std::string name, ARA::ARAColor color) 38 | : _document { document }, 39 | _name { name }, 40 | _color { color } 41 | {} 42 | 43 | int MusicalContext::getOrderIndex () const noexcept 44 | { 45 | return static_cast (ARA::index_of (_document->getMusicalContexts (), this)); 46 | } 47 | 48 | /*******************************************************************************/ 49 | 50 | RegionSequence::RegionSequence (Document * document, std::string name, MusicalContext * musicalContext, ARA::ARAColor color) 51 | : _document { document }, 52 | _name { name }, 53 | _musicalContext { musicalContext }, 54 | _color { color } 55 | { 56 | _musicalContext->_addRegionSequence (this); 57 | } 58 | 59 | RegionSequence::~RegionSequence () 60 | { 61 | _musicalContext->_removeRegionSequence (this); 62 | } 63 | 64 | int RegionSequence::getOrderIndex () const noexcept 65 | { 66 | return static_cast (ARA::index_of (_document->getRegionSequences (), this)); 67 | } 68 | 69 | void RegionSequence::setMusicalContext (MusicalContext* musicalContext) 70 | { 71 | if (musicalContext == _musicalContext) 72 | return; 73 | 74 | _musicalContext->_removeRegionSequence (this); 75 | _musicalContext = musicalContext; 76 | _musicalContext->_addRegionSequence (this); 77 | } 78 | 79 | /*******************************************************************************/ 80 | 81 | AudioSource::AudioSource (Document* document, AudioFileBase* audioFile, std::string persistentID) 82 | : _document { document }, 83 | _audioFile { audioFile }, 84 | _persistentID { persistentID } 85 | { 86 | // at this point, only up to stereo formats are supported because the test code 87 | // doesn't handle surround channel arrangements yet. 88 | ARA_INTERNAL_ASSERT (_audioFile->getChannelCount () <= 2); 89 | } 90 | 91 | /*******************************************************************************/ 92 | 93 | AudioModification::AudioModification (AudioSource * audioSource, std::string name, std::string persistentID) 94 | : _audioSource { audioSource }, 95 | _name { name }, 96 | _persistentID { persistentID } 97 | {} 98 | 99 | /*******************************************************************************/ 100 | 101 | PlaybackRegion::PlaybackRegion (AudioModification* audioModification, ARA::ARAPlaybackTransformationFlags transformationFlags, double startInModificationTime, double durationInModificationTime, double startInPlaybackTime, double durationInPlaybackTime, RegionSequence * regionSequence, std::string name, ARA::ARAColor color) 102 | : _audioModification { audioModification }, 103 | _transformationFlags { transformationFlags }, 104 | _startInModificationTime { startInModificationTime }, 105 | _durationInModificationTime { durationInModificationTime }, 106 | _startInPlaybackTime { startInPlaybackTime }, 107 | _durationInPlaybackTime { durationInPlaybackTime }, 108 | _regionSequence { regionSequence }, 109 | _name { name }, 110 | _color { color } 111 | { 112 | _regionSequence->_addPlaybackRegion (this); 113 | } 114 | 115 | PlaybackRegion::~PlaybackRegion () 116 | { 117 | _regionSequence->_removePlaybackRegion (this); 118 | } 119 | 120 | // Note that setRegionsequence handles removing this from the old 121 | // region sequence and adding this to the new region sequence 122 | void PlaybackRegion::setRegionSequence (RegionSequence* regionSequence) 123 | { 124 | if (regionSequence == _regionSequence) 125 | return; 126 | 127 | _regionSequence->_removePlaybackRegion (this); 128 | _regionSequence = regionSequence; 129 | _regionSequence->_addPlaybackRegion (this); 130 | } 131 | -------------------------------------------------------------------------------- /TestHost/TestCases.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestCases.h 3 | //! various tests simulating user interaction with the TestHost 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include "ExamplesCommon/AudioFiles/AudioFiles.h" 27 | #include "CompanionAPIs.h" 28 | 29 | using AudioFileList = std::vector>; 30 | 31 | // Helper function to create dummy audio file representations that play back a pulsed sine signal 32 | AudioFileList createDummyAudioFiles (size_t numFiles); 33 | 34 | // Demonstrates updating several properties of ARA model graph objects within an edit cycle 35 | // (note: in an actual application, these updates would likely be spread across individual cycles) 36 | void testPropertyUpdates (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 37 | 38 | // Demonstrates how to update content information if changed in the host 39 | // The plug-in will call back into the host's ARAContentAccessController implementation 40 | // to read the updated data - see ARAContentAccessController 41 | void testContentUpdates (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 42 | 43 | // Demonstrates how to read ARAContentTypes from a plug-in - 44 | // see ContentLogger::log () for implementation of the actual content reading 45 | void testContentReading (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 46 | 47 | // Demonstrates how to clone an audio modification to enable two separate edits of the same audio source 48 | void testModificationCloning (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 49 | 50 | // Demonstrates how to store and restore plug-in document archives 51 | void testArchiving (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 52 | 53 | // For ARA 2 plug-ins, instead of a monolithic archive for the entire document this test uses 54 | // multiple smaller archives, each containing specific parts of the graph. 55 | void testSplitArchives (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 56 | 57 | // Simulates a "drag & drop" operation by archiving one source and its modification in a 58 | // two source/modification document with a StoreObjectsFilter, and restoring them in another document 59 | void testDragAndDrop (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 60 | 61 | // Demonstrates using a plug-in playback renderer instance to process audio for a playback region, 62 | // using the companion API rendering methods 63 | // Can optionally use an ARA plug-in's time stretching capabilities to stretch a playback region - 64 | // try loading Melodyne to see this feature in action 65 | void testPlaybackRendering (PlugInEntry* plugInEntry, bool enableTimeStretchingIfSupported, const AudioFileList& audioFiles); 66 | 67 | // Demonstrates how to communicate view selection and region sequence hiding 68 | // (albeit this is of rather limited use in a non-UI application) 69 | void testEditorView (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 70 | 71 | // Requests plug-in analysis, using every processing algorithm published by the plug-in. 72 | void testProcessingAlgorithms (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 73 | 74 | // Loads an `iXML` ARA audio file chunk from a supplied .WAV or .AIFF file 75 | void testAudioFileChunkLoading (PlugInEntry* plugInEntry, const AudioFileList& audioFiles); 76 | 77 | // Requests plug-in analysis and saves audio source state into an `iXML` data chunk in each audio file 78 | // (if chunk authoring is supported by the plug-in) - 79 | // overwrites any current iXML chunk in the files (but only in-memory) 80 | void testAudioFileChunkSaving (PlugInEntry* plugInEntry, AudioFileList& audioFiles); 81 | -------------------------------------------------------------------------------- /TestHost/TestHost.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestHost.h 3 | //! class that maintains the model graph and ARA document controller 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // This is a brief test app that hooks up an ARA capable plug-in using a choice 19 | // of several companion APIs, creates a small model, performs various tests and 20 | // sanity checks and shuts everything down again. 21 | // This educational example is not suitable for production code - for the sake 22 | // of readability of the code, proper error handling or dealing with optional 23 | // ARA API elements is left out. 24 | //------------------------------------------------------------------------------ 25 | 26 | #pragma once 27 | 28 | #include "ModelObjects.h" 29 | #include "ARADocumentController.h" 30 | #include "CompanionAPIs.h" 31 | 32 | /*******************************************************************************/ 33 | // TestHost 34 | // This class represents our ARA host and manages a single document. 35 | // To share this document with an ARA plug-in the host constructs an 36 | // ARA document controller and uses it from the document control APIs. 37 | class TestHost 38 | { 39 | public: 40 | 41 | TestHost () {} 42 | ~TestHost (); 43 | 44 | // document control 45 | Document* addDocument (std::string documentName, PlugInEntry* plugInEntry); 46 | void destroyDocument (Document* document); 47 | 48 | MusicalContext* addMusicalContext (Document* document, std::string name, ARA::ARAColor color); 49 | void removeMusicalContext (Document* document, MusicalContext* musicalContext); 50 | 51 | RegionSequence* addRegionSequence (Document* document, std::string name, MusicalContext* musicalContext, ARA::ARAColor color); 52 | void removeRegionSequence (Document* document, RegionSequence* regionSequence); 53 | 54 | AudioSource* addAudioSource (Document* document, AudioFileBase* audioFile, std::string persistentID); 55 | void removeAudioSource (Document* document, AudioSource* audioSource); 56 | 57 | AudioModification* addAudioModification (Document* document, AudioSource* audioSource, std::string name, std::string persistentID); 58 | void removeAudioModification (Document* document, AudioModification* audioModification); 59 | AudioModification* cloneAudioModification (Document* document, AudioModification* audioModification, std::string name, std::string persistentID); 60 | 61 | PlaybackRegion* addPlaybackRegion (Document* document, AudioModification* audioModification, 62 | ARA::ARAPlaybackTransformationFlags transformationFlags, 63 | double startInModificationTime, double durationInModificationTime, 64 | double startInPlaybackTime, double durationInPlaybackTime, 65 | RegionSequence* regionSequence, 66 | std::string name, ARA::ARAColor color); 67 | void removePlaybackRegion (Document* document, PlaybackRegion* playbackRegion); 68 | 69 | // document and ARA document controller access 70 | ARADocumentController* getDocumentController (Document* document); 71 | 72 | private: 73 | std::map _documents; 74 | }; 75 | -------------------------------------------------------------------------------- /TestPlugIn/ARATestAudioSource.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARATestAudioSource.cpp 3 | //! audio source implementation for the ARA test plug-in, 4 | //! customizing the audio source base class of the ARA library 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #include "ARATestAudioSource.h" 21 | 22 | #include 23 | 24 | void ARATestAudioSource::setNoteContent (std::unique_ptr&& analysisResult, ARA::ARAContentGrade grade, bool fromHost) noexcept 25 | { 26 | _noteContent = std::move (analysisResult); 27 | _noteContentGrade = grade; 28 | _noteContentWasReadFromHost = fromHost; 29 | } 30 | 31 | void ARATestAudioSource::updateRenderSampleCache () 32 | { 33 | ARA_INTERNAL_ASSERT (isSampleAccessEnabled ()); 34 | 35 | // set up cache (this is a hack, so we're ignoring potential overflow of 32 bit with long files here...) 36 | const auto channelCount { static_cast (getChannelCount ()) }; 37 | const auto sampleCount { static_cast (getSampleCount ()) }; 38 | _sampleCache.resize (channelCount * sampleCount); 39 | 40 | // create temporary host audio reader and let it fill the cache 41 | // (we can safely ignore any errors while reading since host must clear buffers in that case, 42 | // as well as report the error to the user) 43 | ARA::PlugIn::HostAudioReader audioReader { this }; 44 | std::vector dataPointers { channelCount }; 45 | for (auto c { 0U }; c < channelCount; ++c) 46 | dataPointers[c] = _sampleCache.data () + c * sampleCount; 47 | audioReader.readAudioSamples (0, static_cast (sampleCount), dataPointers.data ()); 48 | } 49 | 50 | const float* ARATestAudioSource::getRenderSampleCacheForChannel (ARA::ARAChannelCount channel) const 51 | { 52 | return _sampleCache.data () + static_cast (channel * getSampleCount ()); 53 | } 54 | 55 | void ARATestAudioSource::destroyRenderSampleCache () 56 | { 57 | _sampleCache.clear (); 58 | _sampleCache.resize (0); 59 | } 60 | -------------------------------------------------------------------------------- /TestPlugIn/ARATestAudioSource.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARATestAudioSource.h 3 | //! audio source implementation for the ARA test plug-in, 4 | //! customizing the audio source base class of the ARA library 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #pragma once 21 | 22 | #include "ARA_Library/PlugIn/ARAPlug.h" 23 | 24 | #include "TestAnalysis.h" 25 | 26 | /*******************************************************************************/ 27 | class ARATestAudioSource : public ARA::PlugIn::AudioSource 28 | { 29 | public: 30 | ARATestAudioSource (ARA::PlugIn::Document* document, ARA::ARAAudioSourceHostRef hostRef, const TestProcessingAlgorithm* processingAlgorithm = TestProcessingAlgorithm::getDefaultAlgorithm ()) 31 | : AudioSource { document, hostRef }, 32 | _processingAlgorithm { processingAlgorithm } 33 | {} 34 | 35 | void setProcessingAlgorithm (const TestProcessingAlgorithm* processingAlgorithm) noexcept { _processingAlgorithm = processingAlgorithm; } 36 | const TestProcessingAlgorithm* getProcessingAlgorithm () const noexcept { return _processingAlgorithm; } 37 | 38 | // may return nullptr if analysis has not completed yet 39 | const TestNoteContent* getNoteContent () const noexcept { return _noteContent.get (); } 40 | ARA::ARAContentGrade getNoteContentGrade () const noexcept { return _noteContentGrade; } 41 | bool getNoteContentWasReadFromHost () const noexcept { return _noteContentWasReadFromHost; } 42 | void setNoteContent (std::unique_ptr&& analysisResult, ARA::ARAContentGrade grade, bool fromHost) noexcept; 43 | void clearNoteContent () noexcept { return setNoteContent ({}, ARA::kARAContentGradeInitial, false); } 44 | 45 | // render thread sample access: 46 | // in order to keep this test code as simple as possible, our test audio source uses brute 47 | // force and caches all samples in-memory so that renderers can access it without threading issues 48 | // the document controller triggers filling this cache on the main thread, immediately after access is enabled. 49 | // actual plug-ins will use a multi-threaded setup to only cache sections of the audio source on demand - 50 | // a sophisticated file I/O threading implementation is needed for file-based processing regardless of ARA. 51 | void updateRenderSampleCache (); 52 | const float* getRenderSampleCacheForChannel (ARA::ARAChannelCount channel) const; 53 | void destroyRenderSampleCache (); 54 | 55 | protected: 56 | const TestProcessingAlgorithm* _processingAlgorithm; 57 | std::unique_ptr _noteContent; 58 | ARA::ARAContentGrade _noteContentGrade { ARA::kARAContentGradeInitial }; 59 | bool _noteContentWasReadFromHost { false }; 60 | 61 | std::vector _sampleCache; 62 | }; 63 | -------------------------------------------------------------------------------- /TestPlugIn/ARATestPlaybackRenderer.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARATestPlaybackRenderer.cpp 3 | //! playback renderer implementation for the ARA test plug-in, 4 | //! customizing the playback renderer base class of the ARA library 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #include "ARATestPlaybackRenderer.h" 21 | #include "ARATestDocumentController.h" 22 | #include "ARATestAudioSource.h" 23 | 24 | void ARATestPlaybackRenderer::renderPlaybackRegions (float* const* ppOutput, ARA::ARASamplePosition samplePosition, 25 | ARA::ARASampleCount samplesToRender, bool isPlayingBack) 26 | { 27 | // initialize output buffers with silence, in case no viable playback region intersects with the 28 | // current buffer, or if the model is currently not accessible due to being edited. 29 | for (auto c { 0 }; c < _channelCount; ++c) 30 | std::memset (ppOutput[c], 0, sizeof (float) * static_cast (samplesToRender)); 31 | 32 | // only output samples while host is playing back 33 | if (!isPlayingBack) 34 | return; 35 | 36 | // flag that we've started rendering to prevent the document from being edited while in this callback 37 | // see TestDocumentController for details. 38 | auto docController { getDocumentController () }; 39 | if (docController->rendererWillAccessModelGraph (this)) 40 | { 41 | const auto sampleEnd { samplePosition + samplesToRender }; 42 | for (const auto& playbackRegion : getPlaybackRegions ()) 43 | { 44 | const auto audioModification { playbackRegion->getAudioModification () }; 45 | ARA_VALIDATE_API_STATE (!audioModification->isDeactivatedForUndoHistory ()); 46 | const auto audioSource { audioModification->getAudioSource () }; 47 | ARA_VALIDATE_API_STATE (!audioSource->isDeactivatedForUndoHistory ()); 48 | 49 | // render silence if access is currently disabled 50 | // (this is done here only to ease host debugging - actual plug-ins would have at least 51 | // some samples cached for realtime access and would continue unless there's a cache miss.) 52 | if (!audioSource->isSampleAccessEnabled ()) 53 | continue; 54 | 55 | // this simplified test code "rendering" only produces audio if the sample rate matches 56 | if (audioSource->getSampleRate () != _sampleRate) 57 | continue; 58 | 59 | // evaluate region borders in song time, calculate sample range to copy in song time 60 | // (if a plug-in uses playback region head/tail time, it will also need to reflect these values here) 61 | const auto regionStartSample { playbackRegion->getStartInPlaybackSamples (_sampleRate) }; 62 | if (sampleEnd <= regionStartSample) 63 | continue; 64 | 65 | const auto regionEndSample { playbackRegion->getEndInPlaybackSamples (_sampleRate) }; 66 | if (regionEndSample <= samplePosition) 67 | continue; 68 | 69 | auto startSongSample { std::max (regionStartSample, samplePosition) }; 70 | auto endSongSample { std::min (regionEndSample, sampleEnd) }; 71 | 72 | // calculate offset between song and audio source samples, clip at region borders in audio source samples 73 | // (if a plug-in supports time stretching, it will also need to reflect the stretch factor here) 74 | const auto offsetToPlaybackRegion { playbackRegion->getStartInAudioModificationSamples () - regionStartSample }; 75 | 76 | const auto startAvailableSourceSamples { std::max (ARA::ARASamplePosition { 0 }, playbackRegion->getStartInAudioModificationSamples ()) }; 77 | const auto endAvailableSourceSamples { std::min (audioSource->getSampleCount (), playbackRegion->getEndInAudioModificationSamples ()) }; 78 | 79 | startSongSample = std::max (startSongSample, startAvailableSourceSamples - offsetToPlaybackRegion); 80 | endSongSample = std::min (endSongSample, endAvailableSourceSamples - offsetToPlaybackRegion); 81 | if (endSongSample <= startSongSample) 82 | continue; 83 | 84 | // add samples from audio source 85 | const auto sourceChannelCount { audioSource->getChannelCount () }; 86 | for (auto posInSong { startSongSample }; posInSong < endSongSample; ++posInSong) 87 | { 88 | const auto posInBuffer { posInSong - samplePosition }; 89 | const auto posInSource { posInSong + offsetToPlaybackRegion }; 90 | if (sourceChannelCount == _channelCount) 91 | { 92 | for (auto c { 0 }; c < sourceChannelCount; ++c) 93 | ppOutput[c][posInBuffer] += audioSource->getRenderSampleCacheForChannel (c)[posInSource]; 94 | } 95 | else 96 | { 97 | // crude channel format conversion: 98 | // mix down to mono, then distribute the mono signal evenly to all channels. 99 | // note that when down-mixing to mono, the result is scaled by channel count, 100 | // whereas upon up-mixing it is just copied to all channels. 101 | // \todo ambisonic formats should just stick with the mono sum on channel 0, 102 | // but in this simple test code we currently do not distinguish ambisonics 103 | float monoSum { 0.0f }; 104 | for (auto c { 0 }; c < sourceChannelCount; ++c) 105 | monoSum += audioSource->getRenderSampleCacheForChannel (c)[posInSource]; 106 | if (sourceChannelCount > 1) 107 | monoSum /= static_cast (sourceChannelCount); 108 | for (auto c { 0 }; c < _channelCount; ++c) 109 | ppOutput[c][posInBuffer] = monoSum; 110 | } 111 | } 112 | } 113 | 114 | // let the document controller know we're done 115 | docController->rendererDidAccessModelGraph (this); 116 | } 117 | } 118 | 119 | void ARATestPlaybackRenderer::enableRendering (ARA::ARASampleRate sampleRate, ARA::ARAChannelCount channelCount, ARA::ARASampleCount maxSamplesToRender, bool apiSupportsToggleRendering) noexcept 120 | { 121 | // proper plug-ins would use this call to manage the resources which they need for rendering, 122 | // but our test plug-in caches everything it needs in-memory anyways, so this method is near-empty 123 | _sampleRate = sampleRate; 124 | _channelCount = channelCount; 125 | _maxSamplesToRender = maxSamplesToRender; 126 | #if ARA_VALIDATE_API_CALLS 127 | _isRenderingEnabled = true; 128 | _apiSupportsToggleRendering = apiSupportsToggleRendering; 129 | #endif 130 | } 131 | 132 | void ARATestPlaybackRenderer::disableRendering () noexcept 133 | { 134 | #if ARA_VALIDATE_API_CALLS 135 | _isRenderingEnabled = false; 136 | #endif 137 | } 138 | 139 | #if ARA_VALIDATE_API_CALLS 140 | void ARATestPlaybackRenderer::willAddPlaybackRegion (ARA::PlugIn::PlaybackRegion* /*playbackRegion*/) noexcept 141 | { 142 | if (_apiSupportsToggleRendering) 143 | ARA_VALIDATE_API_STATE (!_isRenderingEnabled); 144 | // else 145 | // proper plug-ins would check _isRenderingEnabled here and toggle it off on demand, toggling it back on in didAddPlaybackRegion() 146 | // this works because hosts using such APIs implicitly guarantee that they do not concurrently render the plug-in while making this call 147 | } 148 | 149 | void ARATestPlaybackRenderer::willRemovePlaybackRegion (ARA::PlugIn::PlaybackRegion* /*playbackRegion*/) noexcept 150 | { 151 | if (_apiSupportsToggleRendering) 152 | ARA_VALIDATE_API_STATE (!_isRenderingEnabled); 153 | // else 154 | // see willAddPlaybackRegion(), same pattern applies here 155 | } 156 | #endif 157 | -------------------------------------------------------------------------------- /TestPlugIn/ARATestPlaybackRenderer.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARATestPlaybackRenderer.h 3 | //! playback renderer implementation for the ARA test plug-in, 4 | //! customizing the playback renderer base class of the ARA library 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #pragma once 21 | 22 | #include "ARA_Library/PlugIn/ARAPlug.h" 23 | 24 | /*******************************************************************************/ 25 | class ARATestPlaybackRenderer : public ARA::PlugIn::PlaybackRenderer 26 | { 27 | public: 28 | using PlaybackRenderer::PlaybackRenderer; 29 | 30 | void renderPlaybackRegions (float* const* ppOutput, ARA::ARASamplePosition samplePosition, ARA::ARASampleCount samplesToRender, bool isPlayingBack); 31 | 32 | void enableRendering (ARA::ARASampleRate sampleRate, ARA::ARAChannelCount channelCount, ARA::ARASampleCount maxSamplesToRender, bool apiSupportsToggleRendering) noexcept; 33 | void disableRendering () noexcept; 34 | 35 | protected: 36 | #if ARA_VALIDATE_API_CALLS 37 | void willAddPlaybackRegion (ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override; 38 | void willRemovePlaybackRegion (ARA::PlugIn::PlaybackRegion* playbackRegion) noexcept override; 39 | #endif 40 | 41 | private: 42 | ARA::ARASampleRate _sampleRate { 44100.0f }; 43 | ARA::ARASampleCount _maxSamplesToRender { 4096 }; 44 | ARA::ARAChannelCount _channelCount { 1 }; 45 | #if ARA_VALIDATE_API_CALLS 46 | bool _isRenderingEnabled { false }; 47 | bool _apiSupportsToggleRendering { true }; // AAX enables rendering only once upon init, but does not allow to toggle it later like VST3, AU, CLAP etc. 48 | #endif 49 | }; 50 | -------------------------------------------------------------------------------- /TestPlugIn/AudioFileChunkWriter/ARATestChunkWriter.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARATestChunkWriter.cpp 3 | //! ARA audio file chunk authoring tool for the ARA test plug-in 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | // Command line arguments format for creating ARA audio file chunks for the ARA test plug-in: 19 | // ./ARATestChunkWriter [-openAutomatically] [AudioFile(s)] 20 | // The tool will add a chunk to each of the specified audio files. Existing data for other 21 | // plug-ins will be preserved. 22 | // If a specified file does not exist, it will be created and contain a dummy pulsed sine signal. 23 | // openAutomatically defaults to false unless the option -openAutomatically is specified. 24 | //------------------------------------------------------------------------------ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "ARA_Library/Debug/ARADebug.h" 31 | 32 | #include "ExamplesCommon/Archives/Archives.h" 33 | #include "ExamplesCommon/AudioFiles/AudioFiles.h" 34 | 35 | #include "TestAnalysis.h" 36 | #include "TestPersistency.h" 37 | #include "TestPlugInConfig.h" 38 | 39 | 40 | ARA_SETUP_DEBUG_MESSAGE_PREFIX ("ARATestChunkWriter"); 41 | 42 | 43 | class SynchronousTestAnalysis : public TestAnalysisCallbacks 44 | { 45 | public: 46 | explicit SynchronousTestAnalysis (AudioFileBase& audioFile) : _audioFile { audioFile } {} 47 | 48 | bool readAudioSamples (int64_t samplePosition, int64_t samplesPerChannel, void* const buffers[]) noexcept override 49 | { 50 | return _audioFile.readSamples (samplePosition, samplesPerChannel, buffers, false); 51 | } 52 | 53 | private: 54 | AudioFileBase& _audioFile; 55 | }; 56 | 57 | 58 | void addChunk (AudioFileBase&& audioFile, bool openAutomatically) 59 | { 60 | const auto persistentID { "audioSource1" }; 61 | const auto documentArchiveID { TEST_FILECHUNK_ARCHIVE_ID }; 62 | 63 | // perform analysis 64 | SynchronousTestAnalysis callbacks { audioFile }; 65 | const auto algorithm { TestProcessingAlgorithm::getDefaultAlgorithm () }; 66 | const auto analysisResult { algorithm->analyzeNoteContent (&callbacks, audioFile.getSampleCount (), audioFile.getSampleRate (), 67 | static_cast (audioFile.getChannelCount ())) }; 68 | 69 | // create archive 70 | MemoryArchive archive { documentArchiveID }; 71 | TestArchiver archiver {[&archive] (size_t position, size_t length, const uint8_t buffer[]) noexcept -> bool 72 | { 73 | return archive.writeBytes (static_cast (position), static_cast (length), reinterpret_cast (buffer)); 74 | }}; 75 | archiver.writeString (persistentID); 76 | archiver.writeString (algorithm->getIdentifier ()); 77 | encodeTestNoteContent (analysisResult.get (), archiver); 78 | ARA_INTERNAL_ASSERT (archiver.didSucceed ()); 79 | 80 | // store ARA audio file XML chunk 81 | audioFile.setiXMLARAAudioSourceData (documentArchiveID, openAutomatically, 82 | TEST_PLUGIN_NAME, TEST_VERSION_STRING, TEST_MANUFACTURER_NAME, TEST_INFORMATION_URL, 83 | persistentID, archive); 84 | 85 | // store audio file 86 | auto wavFileName { audioFile.getName () }; 87 | auto success { audioFile.saveToFile (audioFile.getName ()) }; 88 | ARA_INTERNAL_ASSERT (success); 89 | } 90 | 91 | 92 | // see start of this file for detailed description of the command line arguments 93 | int main (int argc, const char* argv[]) 94 | { 95 | const std::vector args (argv + 1, argv + argc); 96 | bool openAutomatically { false }; 97 | for (const auto& it : args) 98 | { 99 | if (it == "-openAutomatically") 100 | { 101 | openAutomatically = true; 102 | continue; 103 | } 104 | 105 | icstdsp::AudioFile audioFile; 106 | int ARA_MAYBE_UNUSED_VAR (err); 107 | err = audioFile.Load (it.c_str ()); 108 | if (err == icstdsp::NOFILE) 109 | { 110 | ARA_LOG ("Audio File '%s' not found, will be created.", it.c_str ()); 111 | addChunk (SineAudioFile { it, 5.0, 44100.0, 1 }, openAutomatically); 112 | } 113 | else 114 | { 115 | ARA_INTERNAL_ASSERT (err == 0); 116 | addChunk (AudioDataFile { it, std::move (audioFile) }, openAutomatically); 117 | } 118 | } 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit/TestAudioUnit.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAudioUnit.h 3 | //! Audio Unit effect class for the ARA test plug-in, 4 | //! created via the Xcode 3 project template for Audio Unit effects. 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #ifndef __TestAudioUnit_h__ 21 | #define __TestAudioUnit_h__ 22 | 23 | _Pragma("GCC diagnostic push") 24 | _Pragma("GCC diagnostic ignored \"-Wimport-preprocessor-directive-pedantic\"") 25 | 26 | #include "AUEffectBase.h" 27 | 28 | _Pragma("GCC diagnostic pop") 29 | 30 | #if !CA_USE_AUDIO_PLUGIN_ONLY 31 | #error "Audio Unit v1 is no longer supported." 32 | #endif 33 | 34 | #include "ARA_Library/PlugIn/ARAPlug.h" 35 | 36 | class TestAudioUnit : public ausdk::AUEffectBase 37 | { 38 | public: 39 | TestAudioUnit(AudioUnit component); 40 | 41 | virtual OSStatus Initialize(); 42 | virtual void Cleanup(); 43 | 44 | virtual UInt32 SupportedNumChannels(const AUChannelInfo** outInfo); 45 | virtual CFURLRef CopyIconLocation (); 46 | 47 | virtual OSStatus GetPropertyInfo(AudioUnitPropertyID inID, 48 | AudioUnitScope inScope, 49 | AudioUnitElement inElement, 50 | UInt32 & outDataSize, 51 | bool & outWritable ); 52 | virtual OSStatus GetProperty(AudioUnitPropertyID inID, 53 | AudioUnitScope inScope, 54 | AudioUnitElement inElement, 55 | void * outData); 56 | 57 | virtual OSStatus ProcessBufferLists( 58 | AudioUnitRenderActionFlags & ioActionFlags, 59 | const AudioBufferList & inBuffer, 60 | AudioBufferList & outBuffer, 61 | UInt32 inFramesToProcess ); 62 | virtual OSStatus Render(AudioUnitRenderActionFlags & ioActionFlags, 63 | const AudioTimeStamp & inTimeStamp, 64 | UInt32 inNumberFrames); 65 | private: 66 | ARA::PlugIn::PlugInExtension _araPlugInExtension; 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit/TestAudioUnitInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AudioComponents 6 | 7 | 8 | description 9 | ARATestPlugIn 10 | factoryFunction 11 | TestAudioUnitFactory 12 | manufacturer 13 | ADeC 14 | name 15 | ARA SDK Examples: ARATestPlugIn 16 | sandboxSafe 17 | 18 | subtype 19 | AraT 20 | tags 21 | 22 | Effect 23 | ARA 24 | 25 | type 26 | aufx 27 | version 28 | 131073 29 | 30 | 31 | CFBundleDevelopmentRegion 32 | $(DEVELOPMENT_LANGUAGE) 33 | CFBundleExecutable 34 | $(EXECUTABLE_NAME) 35 | CFBundleIconFile 36 | ARAExamples.icns 37 | CFBundleIdentifier 38 | $(PRODUCT_BUNDLE_IDENTIFIER) 39 | CFBundleInfoDictionaryVersion 40 | 6.0 41 | CFBundleName 42 | $(PRODUCT_NAME) 43 | CFBundlePackageType 44 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 45 | CFBundleShortVersionString 46 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} 47 | CFBundleVersion 48 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION}.${ARA_BUILD_VERSION} 49 | LSMinimumSystemVersion 50 | $(MACOSX_DEPLOYMENT_TARGET) 51 | 52 | 53 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit/mangle-plugin-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TMP_ENV_FILE=/tmp/mangle-plugin-version-$$.sh 4 | 5 | CMAKE_VERSION_FILE="$1" 6 | INFOPLIST_FILE="$2" 7 | 8 | echo "${CMAKE_VERSION_FILE} -> ${INFOPLIST_FILE}" 9 | 10 | # generate shell-compatible env file 11 | cat "${CMAKE_VERSION_FILE}" | grep '^set' | sed -e 's;set(;;g' -e 's;);;g' -e 's; ;=;g' > "${TMP_ENV_FILE}" 12 | # source variables 13 | . "${TMP_ENV_FILE}" 14 | rm -f "${TMP_ENV_FILE}" 15 | 16 | VERSION_NUMBER=$((${ARA_MAJOR_VERSION} * 65536 + ${ARA_MINOR_VERSION} * 256 + ${ARA_PATCH_VERSION})) 17 | echo "${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} => ${VERSION_NUMBER}" 18 | 19 | # AudioComponent array index is omitted here to allow replacement to work across multiple plug-ins in the same plist 20 | plutil -replace AudioComponents.version -integer ${VERSION_NUMBER} "${INFOPLIST_FILE}" 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/App/TestAUv3App.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/App/TestAUv3App.m: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAUv3App.m 3 | //! Empty dummy container app for the Audio Unit v3 App Extension, 4 | //! based on Apple's AUv3FilterDemo found at: 5 | //! https://developer.apple.com/documentation/audiotoolbox/audio_unit_v3_plug-ins/creating_custom_audio_effects 6 | //! \project ARA SDK Examples 7 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 8 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 9 | //! you may not use this file except in compliance with the License. 10 | //! You may obtain a copy of the License at 11 | //! 12 | //! http://www.apache.org/licenses/LICENSE-2.0 13 | //! 14 | //! Unless required by applicable law or agreed to in writing, software 15 | //! distributed under the License is distributed on an "AS IS" BASIS, 16 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | //! See the License for the specific language governing permissions and 18 | //! limitations under the License. 19 | //------------------------------------------------------------------------------ 20 | 21 | #import 22 | 23 | @interface AppDelegate : NSObject 24 | @end 25 | 26 | @implementation AppDelegate 27 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 28 | { 29 | [[NSApplication sharedApplication] orderFrontStandardAboutPanel:self]; 30 | } 31 | @end 32 | 33 | 34 | int main(int argc, const char * argv[]) 35 | { 36 | AppDelegate * appDelegate = [[AppDelegate alloc] init]; 37 | [[NSApplication sharedApplication] setDelegate:appDelegate]; 38 | return NSApplicationMain(argc, argv); 39 | } 40 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/App/TestAUv3App.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/App/TestAUv3AppInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | ARAExamples.icns 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} 21 | CFBundleVersion 22 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION}.${ARA_BUILD_VERSION} 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSMainNibFile 26 | TestAUv3App 27 | NSPrincipalClass 28 | NSApplication 29 | NSSupportsAutomaticTermination 30 | 31 | NSSupportsSuddenTermination 32 | 33 | NSHumanReadableCopyright 34 | Copyright © 2021-2025 ARA SDK Examples. All rights reserved. 35 | 36 | 37 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Extension/TestAUv3Extension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Extension/TestAUv3Extension.m: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAUv3App.m 3 | //! App Extension placeholder function for the Audio Unit v3 App Extension, 4 | //! based on Apple's AUv3FilterDemo found at: 5 | //! https://developer.apple.com/documentation/audiotoolbox/audio_unit_v3_plug-ins/creating_custom_audio_effects 6 | //! \project ARA SDK Examples 7 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 8 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 9 | //! you may not use this file except in compliance with the License. 10 | //! You may obtain a copy of the License at 11 | //! 12 | //! http://www.apache.org/licenses/LICENSE-2.0 13 | //! 14 | //! Unless required by applicable law or agreed to in writing, software 15 | //! distributed under the License is distributed on an "AS IS" BASIS, 16 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | //! See the License for the specific language governing permissions and 18 | //! limitations under the License. 19 | //------------------------------------------------------------------------------ 20 | 21 | __attribute__ ((used)) void placeholder(void) 22 | { 23 | // This placeholder function ensures the extension correctly loads. 24 | } 25 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Extension/TestAUv3ExtensionInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | ARATestPlugInAUv3 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIconFile 12 | ARAExamples.icns 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 21 | CFBundleShortVersionString 22 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} 23 | CFBundleVersion 24 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION}.${ARA_BUILD_VERSION} 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSExtension 28 | 29 | NSExtensionAttributes 30 | 31 | AudioComponentBundle 32 | org.ara-audio.examples.ARATestPlugInAUv3Framework 33 | AudioComponents 34 | 35 | 36 | description 37 | ARATestPlugInAUv3 38 | manufacturer 39 | ADeC 40 | name 41 | ARA SDK Examples: ARATestPlugInAUv3 42 | sandboxSafe 43 | 44 | subtype 45 | Ara3 46 | tags 47 | 48 | Effects 49 | ARA 50 | 51 | type 52 | aufx 53 | version 54 | 131585 55 | 56 | 57 | 58 | NSExtensionPointIdentifier 59 | com.apple.AudioUnit 60 | NSExtensionPrincipalClass 61 | TestAUv3Factory 62 | 63 | NSHumanReadableCopyright 64 | Copyright © 2021-2025 ARA SDK Examples. All rights reserved. 65 | 66 | 67 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Framework/BufferedAudioBus.hpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file BufferedAudioBus.hpp 3 | //! Audio Unit App Extension helper class, 4 | //! created via the Xcode 11 project template for Audio Unit App Extensions. 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #import 21 | #import 22 | #import 23 | 24 | //MARK:- BufferedAudioBus Utility Class 25 | // Utility classes to manage audio formats and buffers for an audio unit implementation's input and output audio busses. 26 | 27 | // Reusable non-ObjC class, accessible from render thread. 28 | struct BufferedAudioBus { 29 | AUAudioUnitBus* bus = nullptr; 30 | AUAudioFrameCount maxFrames = 0; 31 | 32 | AVAudioPCMBuffer* pcmBuffer = nullptr; 33 | 34 | AudioBufferList const* originalAudioBufferList = nullptr; 35 | AudioBufferList* mutableAudioBufferList = nullptr; 36 | 37 | void init(AVAudioFormat* defaultFormat, AVAudioChannelCount maxChannels) { 38 | maxFrames = 0; 39 | pcmBuffer = nullptr; 40 | originalAudioBufferList = nullptr; 41 | mutableAudioBufferList = nullptr; 42 | 43 | bus = [[AUAudioUnitBus alloc] initWithFormat:defaultFormat error:nil]; 44 | 45 | bus.maximumChannelCount = maxChannels; 46 | } 47 | 48 | void allocateRenderResources(AUAudioFrameCount inMaxFrames) { 49 | maxFrames = inMaxFrames; 50 | 51 | pcmBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:bus.format frameCapacity: maxFrames]; 52 | 53 | originalAudioBufferList = pcmBuffer.audioBufferList; 54 | mutableAudioBufferList = pcmBuffer.mutableAudioBufferList; 55 | } 56 | 57 | void deallocateRenderResources() { 58 | pcmBuffer = nullptr; 59 | originalAudioBufferList = nullptr; 60 | mutableAudioBufferList = nullptr; 61 | } 62 | }; 63 | 64 | // MARK:- BufferedOutputBus: BufferedAudioBus 65 | // MARK: prepareOutputBufferList() 66 | /* 67 | BufferedOutputBus 68 | 69 | This class provides a prepareOutputBufferList method to copy the internal buffer pointers 70 | to the output buffer list in case the client passed in null buffer pointers. 71 | */ 72 | struct BufferedOutputBus: BufferedAudioBus { 73 | void prepareOutputBufferList(AudioBufferList* outBufferList, AVAudioFrameCount frameCount, bool zeroFill) { 74 | UInt32 byteSize = frameCount * sizeof(float); 75 | for (UInt32 i = 0; i < outBufferList->mNumberBuffers; ++i) { 76 | outBufferList->mBuffers[i].mNumberChannels = originalAudioBufferList->mBuffers[i].mNumberChannels; 77 | outBufferList->mBuffers[i].mDataByteSize = byteSize; 78 | if (outBufferList->mBuffers[i].mData == nullptr) { 79 | outBufferList->mBuffers[i].mData = originalAudioBufferList->mBuffers[i].mData; 80 | } 81 | if (zeroFill) { 82 | memset(outBufferList->mBuffers[i].mData, 0, byteSize); 83 | } 84 | } 85 | } 86 | }; 87 | 88 | // MARK: - BufferedInputBus: BufferedAudioBus 89 | // MARK: pullInput() 90 | // MARK: prepareInputBufferList() 91 | /* 92 | BufferedInputBus 93 | 94 | This class manages a buffer into which an audio unit with input busses can 95 | pull its input data. 96 | */ 97 | struct BufferedInputBus : BufferedAudioBus { 98 | /* 99 | Gets input data for this input by preparing the input buffer list and pulling 100 | the pullInputBlock. 101 | */ 102 | AUAudioUnitStatus pullInput(AudioUnitRenderActionFlags *actionFlags, 103 | AudioTimeStamp const* timestamp, 104 | AVAudioFrameCount frameCount, 105 | NSInteger inputBusNumber, 106 | AURenderPullInputBlock pullInputBlock) { 107 | if (pullInputBlock == nullptr) { 108 | return kAudioUnitErr_NoConnection; 109 | } 110 | 111 | /* 112 | Important: 113 | The Audio Unit must supply valid buffers in (inputData->mBuffers[x].mData) and mDataByteSize. 114 | mDataByteSize must be consistent with frameCount. 115 | 116 | The AURenderPullInputBlock may provide input in those specified buffers, or it may replace 117 | the mData pointers with pointers to memory which it owns and guarantees will remain valid 118 | until the next render cycle. 119 | 120 | See prepareInputBufferList() 121 | */ 122 | 123 | prepareInputBufferList(frameCount); 124 | 125 | return pullInputBlock(actionFlags, timestamp, frameCount, inputBusNumber, mutableAudioBufferList); 126 | } 127 | 128 | /* 129 | prepareInputBufferList populates the mutableAudioBufferList with the data 130 | pointers from the originalAudioBufferList. 131 | 132 | The upstream audio unit may overwrite these with its own pointers, so each 133 | render cycle this function needs to be called to reset them. 134 | */ 135 | void prepareInputBufferList(UInt32 frameCount) { 136 | UInt32 byteSize = std::min(frameCount, maxFrames) * sizeof(float); 137 | mutableAudioBufferList->mNumberBuffers = originalAudioBufferList->mNumberBuffers; 138 | 139 | for (UInt32 i = 0; i < originalAudioBufferList->mNumberBuffers; ++i) { 140 | mutableAudioBufferList->mBuffers[i].mNumberChannels = originalAudioBufferList->mBuffers[i].mNumberChannels; 141 | mutableAudioBufferList->mBuffers[i].mData = originalAudioBufferList->mBuffers[i].mData; 142 | mutableAudioBufferList->mBuffers[i].mDataByteSize = byteSize; 143 | } 144 | } 145 | }; 146 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Framework/TestAUv3AudioUnit.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAUv3AudioUnit.h 3 | //! Audio Unit App Extension implementation, 4 | //! created via the Xcode 11 project template for Audio Unit App Extensions. 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #import 21 | 22 | #import "ARA_API/ARAAudioUnit_v3.h" 23 | 24 | @interface TestAUv3AudioUnit : AUAudioUnit 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Framework/TestAUv3DSPKernel.hpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAUv3DSPKernel.hpp 3 | //! Audio Unit App Extension DSP implementation, 4 | //! created via the Xcode 11 project template for Audio Unit App Extensions. 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #ifndef TestAUv3DSPKernel_hpp 21 | #define TestAUv3DSPKernel_hpp 22 | 23 | #include "ARA_Library/PlugIn/ARAPlug.h" 24 | #include "ARATestPlaybackRenderer.h" 25 | 26 | /* 27 | TestAUv3DSPKernel 28 | Performs simple copying of the input signal to the output. 29 | As a non-ObjC class, this is safe to use from render thread. 30 | */ 31 | class TestAUv3DSPKernel { 32 | public: 33 | 34 | // MARK: Member Functions 35 | 36 | TestAUv3DSPKernel() {} 37 | 38 | void init(int channelCount, double inSampleRate) { 39 | chanCount = channelCount; 40 | sampleRate = float(inSampleRate); 41 | } 42 | 43 | AUAudioFrameCount maximumFramesToRender() const { 44 | return maxFramesToRender; 45 | } 46 | 47 | void setMaximumFramesToRender(const AUAudioFrameCount &maxFrames) { 48 | maxFramesToRender = maxFrames; 49 | } 50 | 51 | void setTransportStateBlock(AUHostTransportStateBlock transportState) { 52 | transportStateBlock = transportState; 53 | } 54 | 55 | void setARAPlugInExtension(ARA::PlugIn::PlugInExtension* extension) { 56 | araPlugInExtension = extension; 57 | } 58 | 59 | void setBuffers(AudioBufferList* inBufferList, AudioBufferList* outBufferList) { 60 | inBufferListPtr = inBufferList; 61 | outBufferListPtr = outBufferList; 62 | } 63 | 64 | void enableRendering() { 65 | if (auto playbackRenderer = (araPlugInExtension) ? araPlugInExtension->getPlaybackRenderer() : nullptr) 66 | playbackRenderer->enableRendering(sampleRate, chanCount, maxFramesToRender, true); 67 | } 68 | 69 | void disableRendering() { 70 | if (auto playbackRenderer = (araPlugInExtension) ? araPlugInExtension->getPlaybackRenderer() : nullptr) 71 | playbackRenderer->disableRendering(); 72 | } 73 | 74 | /** 75 | This function handles the event list processing and rendering loop for you. 76 | Call it inside your internalRenderBlock. 77 | */ 78 | void processWithEvents(AudioTimeStamp const *timestamp, AUAudioFrameCount frameCount, AURenderEvent const *events, AUMIDIOutputEventBlock midiOut) { 79 | AUEventSampleTime now = AUEventSampleTime(timestamp->mSampleTime); 80 | AUAudioFrameCount framesRemaining = frameCount; 81 | AURenderEvent const *event = events; 82 | 83 | while (framesRemaining > 0) { 84 | // If there are no more events, we can process the entire remaining segment and exit. 85 | if (event == nullptr) { 86 | AUAudioFrameCount const bufferOffset = frameCount - framesRemaining; 87 | process(framesRemaining, bufferOffset); 88 | return; 89 | } 90 | 91 | // **** start late events late. 92 | auto timeZero = AUEventSampleTime(0); 93 | auto headEventTime = event->head.eventSampleTime; 94 | AUAudioFrameCount const framesThisSegment = AUAudioFrameCount(std::max(timeZero, headEventTime - now)); 95 | 96 | // Compute everything before the next event. 97 | if (framesThisSegment > 0) { 98 | AUAudioFrameCount const bufferOffset = frameCount - framesRemaining; 99 | process(framesThisSegment, bufferOffset); 100 | 101 | // Advance frames. 102 | framesRemaining -= framesThisSegment; 103 | 104 | // Advance time. 105 | now += AUEventSampleTime(framesThisSegment); 106 | } 107 | } 108 | } 109 | 110 | private: 111 | void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) { 112 | float * channels[chanCount]; 113 | for (int i = 0; i < chanCount; ++i) 114 | channels[i] = (float*)outBufferListPtr->mBuffers[i].mData + bufferOffset; 115 | 116 | AUHostTransportStateFlags transportStateFlags = 0; 117 | double currentSamplePosition = 0.0; 118 | if (transportStateBlock) 119 | transportStateBlock(&transportStateFlags, ¤tSamplePosition, nullptr, nullptr); 120 | bool isPlaying = (transportStateFlags & AUHostTransportStateMoving) != 0; 121 | 122 | if (auto playbackRenderer = (araPlugInExtension) ? araPlugInExtension->getPlaybackRenderer() : nullptr) { 123 | // if we're an ARA playback renderer, calculate ARA playback output 124 | playbackRenderer->renderPlaybackRegions(channels, ARA::roundSamplePosition(currentSamplePosition), frameCount, isPlaying); 125 | } 126 | else { 127 | // if we're no ARA playback renderer, we're just copying the inputs to the outputs, which is 128 | // appropriate both when being only an ARA editor renderer, or when being used in non-ARA mode. 129 | for (int i = 0; i < chanCount; ++i) { 130 | const float* in = (const float*)inBufferListPtr->mBuffers[i].mData + bufferOffset; 131 | if (in != channels[i]) // check in-place processing 132 | std::memcpy(channels[i] + bufferOffset, in, sizeof(float) * frameCount); 133 | } 134 | } 135 | } 136 | 137 | // MARK: Member Variables 138 | 139 | private: 140 | int chanCount = 0; 141 | float sampleRate = 44100.0; 142 | AUAudioFrameCount maxFramesToRender = 512; 143 | AudioBufferList* inBufferListPtr = nullptr; 144 | AudioBufferList* outBufferListPtr = nullptr; 145 | AUHostTransportStateBlock transportStateBlock = nullptr; 146 | ARA::PlugIn::PlugInExtension* araPlugInExtension = nullptr; 147 | }; 148 | 149 | #endif /* TestAUv3DSPKernel_hpp */ 150 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Framework/TestAUv3Factory.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAUv3Factory.h 3 | //! Audio Unit App Extension factory, 4 | //! created via the Xcode 11 project template for Audio Unit App Extensions. 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #import 21 | #import 22 | 23 | 24 | @interface TestAUv3Factory : NSObject 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Framework/TestAUv3Factory.m: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAUv3Factory.m 3 | //! Audio Unit App Extension factory, 4 | //! created via the Xcode 11 project template for Audio Unit App Extensions. 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2021-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #import "TestAUv3AudioUnit.h" 21 | #import "TestAUv3Factory.h" 22 | 23 | 24 | @implementation TestAUv3Factory 25 | 26 | - (void)beginRequestWithExtensionContext:(NSExtensionContext *)context { 27 | 28 | } 29 | 30 | - (AUAudioUnit *)createAudioUnitWithComponentDescription:(AudioComponentDescription)desc error:(NSError **)error { 31 | return [[TestAUv3AudioUnit alloc] initWithComponentDescription:desc error:error]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /TestPlugIn/AudioUnit_v3/Framework/TestAUv3FrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} 19 | CFBundleVersion 20 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION}.${ARA_BUILD_VERSION} 21 | NSHumanReadableCopyright 22 | Copyright © 2021-2025 ARA SDK Examples. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /TestPlugIn/CLAP/TestCLAPInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | ARAExamples.icns 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} 21 | CFBundleVersion 22 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION}.${ARA_BUILD_VERSION} 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | 26 | 27 | -------------------------------------------------------------------------------- /TestPlugIn/TestAnalysis.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestAnalysis.h 3 | //! dummy implementation of audio source analysis for the ARA test plug-in 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | class TestArchiver; 26 | class TestUnarchiver; 27 | 28 | /*******************************************************************************/ 29 | struct TestNote 30 | { 31 | float _frequency; 32 | float _volume; 33 | double _startTime; 34 | double _duration; 35 | }; 36 | 37 | /*******************************************************************************/ 38 | using TestNoteContent = std::vector; 39 | 40 | void encodeTestNoteContent (const TestNoteContent* content, TestArchiver& archiver); 41 | std::unique_ptr decodeTestNoteContent (TestUnarchiver& unarchiver); 42 | 43 | /*******************************************************************************/ 44 | class TestAnalysisCallbacks 45 | { 46 | public: 47 | virtual ~TestAnalysisCallbacks () = default; 48 | virtual void notifyAnalysisProgressStarted () noexcept {} 49 | virtual void notifyAnalysisProgressUpdated (float /*progress*/) noexcept {} 50 | virtual void notifyAnalysisProgressCompleted () noexcept {} 51 | virtual bool readAudioSamples (int64_t samplePosition, int64_t samplesPerChannel, void* const buffers[]) noexcept = 0; 52 | virtual bool shouldCancel () const noexcept { return false; } 53 | }; 54 | 55 | /*******************************************************************************/ 56 | class TestProcessingAlgorithm 57 | { 58 | protected: 59 | TestProcessingAlgorithm (const char* name, const char* identifier) 60 | : _name { name }, 61 | _identifier { identifier } 62 | {} 63 | 64 | public: 65 | virtual ~TestProcessingAlgorithm () = default; 66 | 67 | static std::vector const& getAlgorithms (); 68 | static const TestProcessingAlgorithm* getDefaultAlgorithm (); 69 | static const TestProcessingAlgorithm* getAlgorithmWithIdentifier (const char* identifier); 70 | 71 | const char* getName () const { return _name; } 72 | const char* getIdentifier () const { return _identifier; } 73 | 74 | virtual std::unique_ptr analyzeNoteContent (TestAnalysisCallbacks* analysisCallbacks, int64_t sampleCount, double sampleRate, uint32_t channelCount) const = 0; 75 | 76 | private: 77 | const char* _name; 78 | const char* _identifier; 79 | }; 80 | -------------------------------------------------------------------------------- /TestPlugIn/TestPersistency.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestPersistency.cpp 3 | //! archiver/unarchiver implementation for the ARA test plug-in 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #include "TestPersistency.h" 20 | 21 | #include 22 | #include 23 | 24 | // host-network byte ordering include 25 | #if defined (_WIN32) 26 | #include 27 | #elif defined (__APPLE__) 28 | #include 29 | #elif defined (__linux__) 30 | #include 31 | #ifndef htonll 32 | #define htonll(x) ((1==htonl (1)) ? (x) : (static_cast (htonl (static_cast ((x) & 0xFFFFFFFF))) << 32) | htonl (static_cast ((x) >> 32))) 33 | #endif 34 | #ifndef ntohll 35 | #define ntohll(x) ((1==ntohl (1)) ? (x) : (static_cast (ntohl (static_cast ((x) & 0xFFFFFFFF))) << 32) | ntohl (static_cast ((x) >> 32))) 36 | #endif 37 | #endif 38 | 39 | enum { archiveVersion = 1 }; 40 | 41 | union ConversionHelper8Byte 42 | { 43 | explicit ConversionHelper8Byte (double value) : _doubleValue (value) {} 44 | explicit ConversionHelper8Byte (int64_t value) : _intValue (value) {} 45 | explicit ConversionHelper8Byte (uint64_t bytes) : _bytes (bytes) {} 46 | operator double () const { return _doubleValue; } 47 | operator int64_t () const { return _intValue; } 48 | operator uint64_t () const { return _bytes; } 49 | private: 50 | double _doubleValue; 51 | int64_t _intValue; 52 | uint64_t _bytes; 53 | }; 54 | 55 | /*******************************************************************************/ 56 | 57 | TestArchiver::TestArchiver (const ArchivingFunction& writeFunction) noexcept 58 | : _writeFunction { writeFunction } 59 | { 60 | writeInt64 (archiveVersion); 61 | } 62 | 63 | void TestArchiver::writeBool (bool data) noexcept 64 | { 65 | write8ByteData ((data) ? 1U : 0U); 66 | } 67 | 68 | void TestArchiver::writeDouble (double data) noexcept 69 | { 70 | static_assert (sizeof (double) == sizeof (uint64_t), "only implemented for architectures where double uses 64 bit"); 71 | write8ByteData (ConversionHelper8Byte { data }); 72 | } 73 | 74 | void TestArchiver::writeInt64 (int64_t data) noexcept 75 | { 76 | write8ByteData (ConversionHelper8Byte { data }); 77 | } 78 | 79 | void TestArchiver::writeSize (size_t data) noexcept 80 | { 81 | static_assert (sizeof (size_t) <= sizeof (uint64_t), "only implemented for architectures where size_t can be mapped to uint64_t without losing precision"); 82 | write8ByteData (static_cast (data)); 83 | } 84 | 85 | void TestArchiver::writeString (std::string data) noexcept 86 | { 87 | const size_t numBytes { data.size () }; 88 | writeSize (numBytes); 89 | if (didSucceed () && !_writeFunction (_location, numBytes, reinterpret_cast (data.c_str ()))) 90 | _state = TestArchiveState::iOError; 91 | _location += numBytes; 92 | } 93 | 94 | void TestArchiver::write8ByteData (uint64_t data) noexcept 95 | { 96 | const uint64_t encodedData { htonll (data) }; 97 | if (didSucceed () && !_writeFunction (_location, sizeof (data), reinterpret_cast (&encodedData))) 98 | _state = TestArchiveState::iOError; 99 | _location += sizeof (data); 100 | } 101 | 102 | /*******************************************************************************/ 103 | 104 | TestUnarchiver::TestUnarchiver (const UnarchivingFunction& readFunction) noexcept 105 | : _readFunction { readFunction } 106 | { 107 | const int64_t version { readInt64 () }; 108 | if (didSucceed () && (version != archiveVersion)) 109 | _state = TestArchiveState::unknownFormatError; 110 | } 111 | 112 | bool TestUnarchiver::readBool () noexcept 113 | { 114 | const uint64_t encodedData { read8ByteData () }; 115 | return encodedData != 0; 116 | } 117 | 118 | double TestUnarchiver::readDouble () noexcept 119 | { 120 | return ConversionHelper8Byte { read8ByteData () }; 121 | } 122 | 123 | int64_t TestUnarchiver::readInt64 () noexcept 124 | { 125 | return ConversionHelper8Byte { read8ByteData () }; 126 | } 127 | 128 | size_t TestUnarchiver::readSize () noexcept 129 | { 130 | uint64_t data { read8ByteData () }; 131 | 132 | #if __cplusplus >= 201703L 133 | if constexpr (sizeof (size_t) < sizeof (uint64_t)) 134 | #else 135 | #if defined (_MSC_VER) 136 | __pragma (warning(push)) 137 | __pragma (warning(disable : 4127)) 138 | #endif 139 | if (sizeof (size_t) < sizeof (uint64_t)) 140 | #if defined (_MSC_VER) 141 | __pragma (warning(pop)) 142 | #endif 143 | #endif 144 | { 145 | if (data > std::numeric_limits::max ()) 146 | { 147 | _state = TestArchiveState::incompatibleDataError; 148 | data = 0; 149 | } 150 | } 151 | 152 | return static_cast (data); 153 | } 154 | 155 | std::string TestUnarchiver::readString () 156 | { 157 | std::string data; 158 | const size_t numBytes { readSize () }; 159 | if (didSucceed () && numBytes) 160 | { 161 | std::vector stringBuffer (numBytes + 1); 162 | if (_readFunction (_location, numBytes, reinterpret_cast (stringBuffer.data ()))) 163 | data = stringBuffer.data (); 164 | else 165 | _state = TestArchiveState::iOError; 166 | _location += numBytes; 167 | } 168 | return data; 169 | } 170 | 171 | uint64_t TestUnarchiver::read8ByteData () noexcept 172 | { 173 | uint64_t encodedData { 0 }; 174 | if (didSucceed () && !_readFunction (_location, sizeof (encodedData), reinterpret_cast (&encodedData))) 175 | _state = TestArchiveState::iOError; 176 | if (!didSucceed ()) 177 | encodedData = 0; 178 | _location += sizeof (encodedData); 179 | return ntohll (encodedData); 180 | } 181 | -------------------------------------------------------------------------------- /TestPlugIn/TestPersistency.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestPersistency.h 3 | //! archiver/unarchiver implementation for the ARA test plug-in 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2018-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | // Archiver/Unarchiver 26 | // Actual plug-ins will already feature some persistency implementation which is independent of ARA - 27 | // the following code merely drafts such an implementation, it cannot be used in actual products! 28 | 29 | enum class TestArchiveState 30 | { 31 | noError = 0, 32 | iOError, // could not read or write bytes 33 | // in ARA, the host handles I/O and will display a proper error message in this case 34 | unknownFormatError, // archive was written by future version of the program 35 | // in ARA, hosts should handle the version matching based on documentArchiveIDs - 36 | // but some hosts behave incorrect here, so actual plug-ins should handle this 37 | // as safety measure and will display a proper error message in this case 38 | incompatibleDataError // archive contains numbers that cannot be represented on the current architecture 39 | // (e.g. 64 bit archive with size_t that exceeds 32 bit architecture) 40 | // in ARA, actual plug-ins will display a proper error message in this case 41 | }; 42 | 43 | /*******************************************************************************/ 44 | // encoder class 45 | class TestArchiver 46 | { 47 | public: 48 | // \todo this should be noexcept but recent clang/stl versions fail with this. 49 | using ArchivingFunction = std::function; 50 | TestArchiver (const ArchivingFunction& writeFunction) noexcept; 51 | 52 | void writeBool (bool data) noexcept; 53 | void writeDouble (double data) noexcept; 54 | void writeInt64 (int64_t data) noexcept; 55 | void writeSize (size_t data) noexcept; 56 | void writeString (std::string data) noexcept; 57 | 58 | TestArchiveState getState () const noexcept { return _state; } 59 | bool didSucceed () const noexcept { return (_state == TestArchiveState::noError); } 60 | 61 | private: 62 | void write8ByteData (uint64_t data) noexcept; 63 | 64 | private: 65 | const ArchivingFunction _writeFunction; 66 | size_t _location { 0 }; 67 | TestArchiveState _state { TestArchiveState::noError }; 68 | }; 69 | 70 | /*******************************************************************************/ 71 | // decoder class 72 | class TestUnarchiver 73 | { 74 | public: 75 | // \todo this should be noexcept but recent clang/stl versions fail with this. 76 | using UnarchivingFunction = std::function; 77 | TestUnarchiver (const UnarchivingFunction& readFunction) noexcept; 78 | 79 | bool readBool () noexcept; 80 | double readDouble () noexcept; 81 | int64_t readInt64 () noexcept; 82 | size_t readSize () noexcept; 83 | std::string readString (); 84 | 85 | TestArchiveState getState () const noexcept { return _state; } 86 | bool didSucceed () const noexcept { return (_state == TestArchiveState::noError); } 87 | 88 | private: 89 | uint64_t read8ByteData () noexcept; 90 | 91 | private: 92 | const UnarchivingFunction _readFunction; 93 | size_t _location { 0 }; 94 | TestArchiveState _state { TestArchiveState::noError }; 95 | }; 96 | -------------------------------------------------------------------------------- /TestPlugIn/TestPlugInConfig.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestPlugInConfig.h 3 | //! IDs and other shared definitions for the ARATestPlugIn 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #pragma once 20 | 21 | #define _IN_QUOTES_HELPER(x) #x 22 | #define IN_QUOTES(x) _IN_QUOTES_HELPER(x) 23 | 24 | #if (!defined(ARA_MAJOR_VERSION)) || (!defined(ARA_MINOR_VERSION)) || (!defined(ARA_PATCH_VERSION)) 25 | #error "ARA version macros not set up properly!" 26 | #endif 27 | 28 | #define TEST_PLUGIN_NAME "ARATestPlugIn" 29 | #define TEST_MANUFACTURER_NAME "ARA SDK Examples" 30 | #define TEST_INFORMATION_URL "https://www.ara-audio.org/examples" 31 | #define TEST_MAILTO_URL "mailto:info@ara-audio.org?subject=ARATestPlugIn" 32 | #define TEST_VERSION_STRING IN_QUOTES(ARA_MAJOR_VERSION) "." IN_QUOTES(ARA_MINOR_VERSION) "." IN_QUOTES(ARA_PATCH_VERSION) 33 | 34 | #define TEST_FACTORY_ID "org.ara-audio.examples.testplugin.arafactory" 35 | #define TEST_DOCUMENT_ARCHIVE_ID "org.ara-audio.examples.testplugin.aradocumentarchive.version1" 36 | #define TEST_FILECHUNK_ARCHIVE_ID "org.ara-audio.examples.testplugin.arafilechunkarchive.version1" 37 | -------------------------------------------------------------------------------- /TestPlugIn/VST3/ARATestMainFactory.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file ARATestMainFactory.h 3 | //! VST3 ARA Main Factory implementation for the ARA test plug-in. 4 | //! \project ARA SDK Examples 5 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 6 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 7 | //! you may not use this file except in compliance with the License. 8 | //! You may obtain a copy of the License at 9 | //! 10 | //! http://www.apache.org/licenses/LICENSE-2.0 11 | //! 12 | //! Unless required by applicable law or agreed to in writing, software 13 | //! distributed under the License is distributed on an "AS IS" BASIS, 14 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | //! See the License for the specific language governing permissions and 16 | //! limitations under the License. 17 | //------------------------------------------------------------------------------ 18 | 19 | #include "ARA_API/ARAVST3.h" 20 | #include "ARATestDocumentController.h" 21 | 22 | ARA_DISABLE_VST3_WARNINGS_BEGIN 23 | 24 | class ARATestMainFactory : public ARA::IMainFactory 25 | { 26 | public: 27 | ARATestMainFactory () { FUNKNOWN_CTOR } 28 | virtual ~ARATestMainFactory () { FUNKNOWN_DTOR } 29 | 30 | // Class ID 31 | static const Steinberg::FUID getClassFUID () 32 | { 33 | return Steinberg::FUID (0xB761364A, 0x035149BF, 0xA580C576, 0xECD186FB); 34 | } 35 | 36 | // Create function 37 | static Steinberg::FUnknown* createInstance (void* /*context*/) 38 | { 39 | return (ARA::IMainFactory*) new ARATestMainFactory (); 40 | } 41 | 42 | DECLARE_FUNKNOWN_METHODS 43 | 44 | //------------------------------------------------------------------------ 45 | // ARA::IMainFactory overrides: 46 | //------------------------------------------------------------------------ 47 | const ARA::ARAFactory* PLUGIN_API getFactory () SMTG_OVERRIDE 48 | { 49 | return ARATestDocumentController::getARAFactory (); 50 | } 51 | }; 52 | 53 | IMPLEMENT_FUNKNOWN_METHODS (ARATestMainFactory, ARA::IMainFactory, ARA::IMainFactory::iid) 54 | 55 | ARA_DISABLE_VST3_WARNINGS_END 56 | -------------------------------------------------------------------------------- /TestPlugIn/VST3/TestVST3Entry.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestVST3Entry.cpp 3 | //! VST3 factory functions for the ARA test plug-in, 4 | //! originally created using the VST project generator from the Steinberg VST3 SDK 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #include "TestVST3Processor.h" 21 | #include "ARATestMainFactory.h" 22 | #include "TestPlugInConfig.h" 23 | 24 | ARA_DISABLE_VST3_WARNINGS_BEGIN 25 | 26 | #if VST_VERSION >= 0x03060D /* 3.6.13 */ 27 | #include "public.sdk/source/main/pluginfactory.h" 28 | #else 29 | #include "public.sdk/source/main/pluginfactoryvst3.h" 30 | #endif 31 | 32 | 33 | //------------------------------------------------------------------------ 34 | // Module init/exit 35 | //------------------------------------------------------------------------ 36 | 37 | //------------------------------------------------------------------------ 38 | // called after library was loaded 39 | bool InitModule () 40 | { 41 | return true; 42 | } 43 | 44 | //------------------------------------------------------------------------ 45 | // called after library is unloaded 46 | bool DeinitModule () 47 | { 48 | return true; 49 | } 50 | 51 | //------------------------------------------------------------------------ 52 | // VST Class IIDs 53 | //------------------------------------------------------------------------ 54 | 55 | DEF_CLASS_IID (ARA::IMainFactory) 56 | DEF_CLASS_IID (ARA::IPlugInEntryPoint) 57 | DEF_CLASS_IID (ARA::IPlugInEntryPoint2) 58 | 59 | 60 | //------------------------------------------------------------------------ 61 | // VST Plug-in Entry 62 | //------------------------------------------------------------------------ 63 | 64 | #define FULL_VERSION_STR TEST_VERSION_STRING "." IN_QUOTES(TEST_BUILD_VERSION) 65 | 66 | BEGIN_FACTORY_DEF (TEST_MANUFACTURER_NAME, 67 | TEST_INFORMATION_URL, 68 | TEST_MAILTO_URL) 69 | 70 | //---First Plug-in included in this factory------- 71 | // its kVstAudioEffectClass component 72 | DEF_CLASS2 (INLINE_UID_FROM_FUID (TestVST3Processor::getClassFUID ()), 73 | PClassInfo::kManyInstances, // cardinality 74 | kVstAudioEffectClass, // the IAudioProcessor component category (do not changed this) 75 | TEST_PLUGIN_NAME, // here the Plug-in name 76 | Vst::kDistributable, // means that component and controller could be distributed on different computers 77 | "Fx|OnlyARA", // Subcategory for this Plug-in (see Steinberg::Vst::PlugType) 78 | FULL_VERSION_STR, // Plug-in version 79 | kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define) 80 | TestVST3Processor::createInstance) // function pointer called when this component should be instantiated 81 | 82 | // its kVstComponentControllerClass component 83 | DEF_CLASS2 (INLINE_UID_FROM_FUID (TestVST3Processor::getEditControllerClassFUID ()), 84 | PClassInfo::kManyInstances, // cardinality 85 | kVstComponentControllerClass, // the Controller category (do not changed this) 86 | TEST_PLUGIN_NAME, // controller name (could be the same as component name) 87 | 0, // not used here 88 | "", // not used here 89 | FULL_VERSION_STR, // Plug-in version 90 | kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define) 91 | TestVST3Processor::createEditControllerInstance) // function pointer called when this component should be instantiated 92 | 93 | // its kARAMainFactoryClass component 94 | DEF_CLASS2 (INLINE_UID_FROM_FUID (ARATestMainFactory::getClassFUID ()), 95 | PClassInfo::kManyInstances, // cardinality 96 | kARAMainFactoryClass, // the ARA Main Factory category (do not changed this) 97 | TEST_PLUGIN_NAME, // here the Plug-in name (MUST be the same as component name if multiple kVstAudioEffectClass components are used!) 98 | 0, // not used here 99 | "", // not used here 100 | FULL_VERSION_STR, // Plug-in version (to be changed) 101 | kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define) 102 | ARATestMainFactory::createInstance) // function pointer called when this component should be instantiated 103 | 104 | END_FACTORY 105 | 106 | ARA_DISABLE_VST3_WARNINGS_END 107 | -------------------------------------------------------------------------------- /TestPlugIn/VST3/TestVST3Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | ARAExamples.icns 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION} 21 | CFBundleVersion 22 | ${ARA_MAJOR_VERSION}.${ARA_MINOR_VERSION}.${ARA_PATCH_VERSION}.${ARA_BUILD_VERSION} 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | 26 | 27 | -------------------------------------------------------------------------------- /TestPlugIn/VST3/TestVST3Processor.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestVST3Processor.cpp 3 | //! VST3 audio effect class for the ARA test plug-in, 4 | //! originally created using the VST project generator from the Steinberg VST3 SDK 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #include "TestVST3Processor.h" 21 | #include "ARATestPlaybackRenderer.h" 22 | #include "ARATestDocumentController.h" 23 | 24 | #include "ARA_Library/PlugIn/ARAPlug.h" 25 | #include "ARA_Library/Debug/ARADebug.h" 26 | 27 | ARA_DISABLE_VST3_WARNINGS_BEGIN 28 | #include "pluginterfaces/vst/ivstprocesscontext.h" 29 | ARA_DISABLE_VST3_WARNINGS_END 30 | 31 | using namespace Steinberg; 32 | 33 | // helper to improve readability 34 | int32 getAudioBusChannelCount (const IPtr& bus) 35 | { 36 | return Vst::SpeakerArr::getChannelCount (FCast (bus.get ())->getArrangement ()); 37 | } 38 | 39 | //----------------------------------------------------------------------------- 40 | TestVST3Processor::TestVST3Processor () 41 | { 42 | setControllerClass (getEditControllerClassFUID ()); 43 | 44 | #if VST_VERSION >= 0x030700 /* 3.7.0 */ 45 | processContextRequirements.needTransportState (); 46 | #endif 47 | } 48 | 49 | //------------------------------------------------------------------------ 50 | TestVST3Processor::~TestVST3Processor () 51 | {} 52 | 53 | //------------------------------------------------------------------------ 54 | tresult PLUGIN_API TestVST3Processor::initialize (FUnknown* context) 55 | { 56 | // Here the Plug-in will be instantiated 57 | 58 | //---always initialize the parent------- 59 | tresult result = AudioEffect::initialize (context); 60 | // if everything Ok, continue 61 | if (result != kResultOk) 62 | { 63 | return result; 64 | } 65 | 66 | //--- create Audio IO ------ 67 | addAudioInput (STR16 ("Stereo In"), Steinberg::Vst::SpeakerArr::kStereo); 68 | addAudioOutput (STR16 ("Stereo Out"), Steinberg::Vst::SpeakerArr::kStereo); 69 | 70 | return kResultOk; 71 | } 72 | 73 | //------------------------------------------------------------------------ 74 | tresult PLUGIN_API TestVST3Processor::terminate () 75 | { 76 | // Here the Plug-in will be de-instantiated, last possibility to remove some memory! 77 | 78 | //---do not forget to call parent ------ 79 | return AudioEffect::terminate (); 80 | } 81 | 82 | //----------------------------------------------------------------------------- 83 | tresult PLUGIN_API TestVST3Processor::setBusArrangements (Vst::SpeakerArrangement* inputs, int32 numIns, Vst::SpeakerArrangement* outputs, int32 numOuts) 84 | { 85 | // we only support one in and output bus and these buses must have the same number of non-zero channels 86 | if ((numIns == 1) && (numOuts == 1) && 87 | (inputs[0] == outputs[0]) && 88 | (Vst::SpeakerArr::getChannelCount (outputs[0]) != 0)) 89 | { 90 | return AudioEffect::setBusArrangements (inputs, numIns, outputs, numOuts); 91 | } 92 | 93 | return kResultFalse; 94 | } 95 | 96 | //----------------------------------------------------------------------------- 97 | tresult PLUGIN_API TestVST3Processor::setActive (TBool state) 98 | { 99 | //--- called when the Plug-in is enable/disable (On/Off) ----- 100 | 101 | if (ARATestPlaybackRenderer* playbackRenderer = _araPlugInExtension.getPlaybackRenderer ()) 102 | { 103 | if (state) 104 | playbackRenderer->enableRendering (processSetup.sampleRate, getAudioBusChannelCount (audioOutputs[0]), processSetup.maxSamplesPerBlock, true); 105 | else 106 | playbackRenderer->disableRendering (); 107 | } 108 | 109 | return AudioEffect::setActive (state); 110 | } 111 | 112 | //----------------------------------------------------------------------------- 113 | tresult PLUGIN_API TestVST3Processor::process (Vst::ProcessData& data) 114 | { 115 | //--- Here you have to implement your processing 116 | 117 | if (!data.outputs || !data.outputs[0].numChannels) 118 | return kResultTrue; 119 | 120 | ARA_VALIDATE_API_CONDITION (data.outputs[0].numChannels == getAudioBusChannelCount (audioOutputs[0])); 121 | ARA_VALIDATE_API_CONDITION (data.numSamples <= processSetup.maxSamplesPerBlock); 122 | 123 | if (auto playbackRenderer = _araPlugInExtension.getPlaybackRenderer ()) 124 | { 125 | // if we're an ARA playback renderer, calculate ARA playback output 126 | playbackRenderer->renderPlaybackRegions (data.outputs[0].channelBuffers32, data.processContext->projectTimeSamples, 127 | data.numSamples, (data.processContext->state & Vst::ProcessContext::kPlaying) != 0); 128 | } 129 | else 130 | { 131 | // if we're no ARA playback renderer, we're just copying the inputs to the outputs, which is 132 | // appropriate both when being only an ARA editor renderer, or when being used in non-ARA mode. 133 | for (int32 c = 0; c < data.outputs[0].numChannels; ++c) 134 | std::memcpy (data.outputs[0].channelBuffers32[c], data.inputs[0].channelBuffers32[c], sizeof (float) * static_cast (data.numSamples)); 135 | } 136 | 137 | // if we are an ARA editor renderer, we now would add out preview signal to the output, but 138 | // our test implementation does not support editing and thus never generates any preview signal. 139 | // if (auto editorRenderer = _araPlugInExtension.getEditorRenderer ()) 140 | // editorRenderer->addEditorSignal (...); 141 | 142 | return kResultTrue; 143 | } 144 | 145 | //------------------------------------------------------------------------ 146 | tresult PLUGIN_API TestVST3Processor::setupProcessing (Vst::ProcessSetup& newSetup) 147 | { 148 | //--- called before any processing ---- 149 | return AudioEffect::setupProcessing (newSetup); 150 | } 151 | 152 | //------------------------------------------------------------------------ 153 | tresult PLUGIN_API TestVST3Processor::canProcessSampleSize (int32 symbolicSampleSize) 154 | { 155 | // by default kSample32 is supported 156 | if (symbolicSampleSize == Vst::kSample32) 157 | return kResultTrue; 158 | 159 | // disable the following comment if your processing support kSample64 160 | /* if (symbolicSampleSize == Vst::kSample64) 161 | return kResultTrue; */ 162 | 163 | return kResultFalse; 164 | } 165 | 166 | //----------------------------------------------------------------------------- 167 | const ARA::ARAFactory* PLUGIN_API TestVST3Processor::getFactory () 168 | { 169 | return ARATestDocumentController::getARAFactory (); 170 | } 171 | 172 | //----------------------------------------------------------------------------- 173 | #if ARA_SUPPORT_VERSION_1 174 | const ARA::ARAPlugInExtensionInstance* PLUGIN_API TestVST3Processor::bindToDocumentController (ARA::ARADocumentControllerRef documentControllerRef) 175 | { 176 | ARA_VALIDATE_API_STATE (ARA::PlugIn::DocumentController::getUsedApiGeneration () < ARA::kARAAPIGeneration_2_0_Draft); 177 | constexpr auto allRoles = ARA::kARAPlaybackRendererRole | ARA::kARAEditorRendererRole | ARA::kARAEditorViewRole; 178 | return _araPlugInExtension.bindToDocumentController (documentControllerRef, allRoles, allRoles); 179 | } 180 | #else 181 | const ARA::ARAPlugInExtensionInstance* PLUGIN_API TestVST3Processor::bindToDocumentController (ARA::ARADocumentControllerRef /*documentControllerRef*/) 182 | { 183 | ARA_VALIDATE_API_STATE (false && "call is deprecated in ARA 2, host must not call this"); 184 | return nullptr; 185 | } 186 | #endif 187 | 188 | //----------------------------------------------------------------------------- 189 | const ARA::ARAPlugInExtensionInstance* PLUGIN_API TestVST3Processor::bindToDocumentControllerWithRoles (ARA::ARADocumentControllerRef documentControllerRef, 190 | ARA::ARAPlugInInstanceRoleFlags knownRoles, ARA::ARAPlugInInstanceRoleFlags assignedRoles) 191 | { 192 | return _araPlugInExtension.bindToARA (documentControllerRef, knownRoles, assignedRoles); 193 | } 194 | -------------------------------------------------------------------------------- /TestPlugIn/VST3/TestVST3Processor.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | //! \file TestVST3Processor.h 3 | //! VST3 audio effect class for the ARA test plug-in, 4 | //! originally created using the VST project generator from the Steinberg VST3 SDK 5 | //! \project ARA SDK Examples 6 | //! \copyright Copyright (c) 2012-2025, Celemony Software GmbH, All Rights Reserved. 7 | //! \license Licensed under the Apache License, Version 2.0 (the "License"); 8 | //! you may not use this file except in compliance with the License. 9 | //! You may obtain a copy of the License at 10 | //! 11 | //! http://www.apache.org/licenses/LICENSE-2.0 12 | //! 13 | //! Unless required by applicable law or agreed to in writing, software 14 | //! distributed under the License is distributed on an "AS IS" BASIS, 15 | //! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | //! See the License for the specific language governing permissions and 17 | //! limitations under the License. 18 | //------------------------------------------------------------------------------ 19 | 20 | #pragma once 21 | 22 | #include "ARA_API/ARAVST3.h" 23 | 24 | ARA_DISABLE_VST3_WARNINGS_BEGIN 25 | 26 | #include "public.sdk/source/vst/vstaudioeffect.h" 27 | #include "public.sdk/source/vst/vsteditcontroller.h" 28 | 29 | #include "ARA_Library/PlugIn/ARAPlug.h" 30 | 31 | //------------------------------------------------------------------------ 32 | // TestVST3Processor 33 | //------------------------------------------------------------------------ 34 | class TestVST3Processor : public Steinberg::Vst::AudioEffect, public ARA::IPlugInEntryPoint, public ARA::IPlugInEntryPoint2 35 | { 36 | public: 37 | TestVST3Processor (); 38 | ~TestVST3Processor () SMTG_OVERRIDE; 39 | 40 | // Class IDs 41 | static const Steinberg::FUID getClassFUID () 42 | { 43 | return Steinberg::FUID (0xA8497651, 0x8C994E9C, 0xA5030D11, 0x3617C309); 44 | } 45 | 46 | static const Steinberg::FUID getEditControllerClassFUID () 47 | { 48 | return Steinberg::FUID (0x005F4AB1, 0x67CE4E31, 0x9ED45F1D, 0x3F5DC889); 49 | } 50 | 51 | // Create functions 52 | static Steinberg::FUnknown* createInstance (void* /*context*/) 53 | { 54 | return static_cast (new TestVST3Processor); 55 | } 56 | 57 | static Steinberg::FUnknown* createEditControllerInstance (void* /*context*/) 58 | { 59 | return static_cast (new Steinberg::Vst::EditController); 60 | } 61 | 62 | //------------------------------------------------------------------------ 63 | // AudioEffect overrides: 64 | //------------------------------------------------------------------------ 65 | /** Called at first after constructor */ 66 | Steinberg::tresult PLUGIN_API initialize (Steinberg::FUnknown* context) SMTG_OVERRIDE; 67 | 68 | /** Called at the end before destructor */ 69 | Steinberg::tresult PLUGIN_API terminate () SMTG_OVERRIDE; 70 | 71 | /** Switch the Plug-in on/off */ 72 | Steinberg::tresult PLUGIN_API setActive (Steinberg::TBool state) SMTG_OVERRIDE; 73 | 74 | /** Will be called before any process call */ 75 | Steinberg::tresult PLUGIN_API setupProcessing (Steinberg::Vst::ProcessSetup& newSetup) SMTG_OVERRIDE; 76 | 77 | /** Try to set (host => plug-in) a wanted arrangement for inputs and outputs. */ 78 | Steinberg::tresult PLUGIN_API setBusArrangements (Steinberg::Vst::SpeakerArrangement* inputs, Steinberg::int32 numIns, 79 | Steinberg::Vst::SpeakerArrangement* outputs, Steinberg::int32 numOuts) SMTG_OVERRIDE; 80 | 81 | /** Asks if a given sample size is supported see SymbolicSampleSizes. */ 82 | Steinberg::tresult PLUGIN_API canProcessSampleSize (Steinberg::int32 symbolicSampleSize) SMTG_OVERRIDE; 83 | 84 | /** Here we go...the process call */ 85 | Steinberg::tresult PLUGIN_API process (Steinberg::Vst::ProcessData& data) SMTG_OVERRIDE; 86 | 87 | 88 | //------------------------------------------------------------------------ 89 | // ARA::IPlugInEntryPoint2 overrides: 90 | //------------------------------------------------------------------------ 91 | 92 | /** Get associated ARA factory */ 93 | const ARA::ARAFactory* PLUGIN_API getFactory () SMTG_OVERRIDE; 94 | 95 | /** Bind to ARA document controller instance */ 96 | const ARA::ARAPlugInExtensionInstance* PLUGIN_API bindToDocumentController (ARA::ARADocumentControllerRef documentControllerRef) SMTG_OVERRIDE; 97 | const ARA::ARAPlugInExtensionInstance* PLUGIN_API bindToDocumentControllerWithRoles (ARA::ARADocumentControllerRef documentControllerRef, 98 | ARA::ARAPlugInInstanceRoleFlags knownRoles, ARA::ARAPlugInInstanceRoleFlags assignedRoles) SMTG_OVERRIDE; 99 | 100 | //------------------------------------------------------------------------ 101 | // Interface 102 | //------------------------------------------------------------------------ 103 | OBJ_METHODS (TestVST3Processor, AudioEffect) 104 | DEFINE_INTERFACES 105 | DEF_INTERFACE (IPlugInEntryPoint) 106 | DEF_INTERFACE (IPlugInEntryPoint2) 107 | END_DEFINE_INTERFACES (AudioEffect) 108 | REFCOUNT_METHODS (AudioEffect) 109 | 110 | //------------------------------------------------------------------------ 111 | protected: 112 | ARA::PlugIn::PlugInExtension _araPlugInExtension; 113 | }; 114 | 115 | ARA_DISABLE_VST3_WARNINGS_END 116 | --------------------------------------------------------------------------------