From e9eb3ee4f251d2784bceaf55c72137f5fae99409 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Sun, 19 Jun 2022 11:37:32 -0400 Subject: [PATCH] Initial Idea --- .gitignore | 59 ++++++++++++ .gitmodules | 9 ++ CMakeLists.txt | 160 ++++++++++++++++++++++++++++++++ LICENSE.md | 9 ++ cmake/claudio-effect-x.plist.in | 34 +++++++ include/audioeffectx.h | 64 +++++++++++++ libs/airwindows | 1 + libs/clap | 1 + libs/clap-helpers | 1 + src/claudio.cpp | 17 ++++ src/claudio_configured.cpp | 44 +++++++++ src/individual_claudio.in.cpp | 18 ++++ src/individual_claudio.in.h | 14 +++ 13 files changed, 431 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 LICENSE.md create mode 100644 cmake/claudio-effect-x.plist.in create mode 100644 include/audioeffectx.h create mode 160000 libs/airwindows create mode 160000 libs/clap create mode 160000 libs/clap-helpers create mode 100644 src/claudio.cpp create mode 100644 src/claudio_configured.cpp create mode 100644 src/individual_claudio.in.cpp create mode 100644 src/individual_claudio.in.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..134115f --- /dev/null +++ b/.gitignore @@ -0,0 +1,59 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Visual Studio +obj/ +*.sln +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +.vs/ +packages/ +target/ +*.pdb +packages.config +CMakeSettings.json +.vscode +.cache + + +# IntelliJ IDEA +.idea + +# CMake common patterns +build/ +cmake-build-*/ + + +# A place to store stuff and get it git ignored +ignore/* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d60e621 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "libs/clap"] + path = libs/clap + url = https://github.com/free-audio/clap +[submodule "libs/clap-helpers"] + path = libs/clap-helpers + url = https://github.com/free-audio/clap-helpers +[submodule "libs/airwindows"] + path = libs/airwindows + url = https://github.com/airwindows/airwindows diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f2f3a1e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,160 @@ +cmake_minimum_required(VERSION 3.15) + +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.11 CACHE STRING "Build for 10.1") +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +if(NOT CMAKE_BUILD_TYPE) + message(STATUS "CMAKE_BUILD_TYPE Type Unspecified; picking Release") + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) +endif() + +project(claudio-effect-x VERSION 0.9.0 LANGUAGES C CXX) + + +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD 17) + + +# use asan as an option (currently mac only) +option(USE_SANITIZER "Build and link with ASAN" FALSE) + +# Copy on mac (could expand to other platforms) +option(COPY_AFTER_BUILD "Copy the clap to ~/Library on MACOS, ~/.clap on linux" FALSE) + +add_subdirectory(libs/clap EXCLUDE_FROM_ALL) +add_subdirectory(libs/clap-helpers EXCLUDE_FROM_ALL) + +if(NOT EXISTS "${CMAKE_BINARY_DIR}/individuals") + message(STATUS "Creating individuals directory") + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/individuals") +endif() + +add_library(${PROJECT_NAME} MODULE + src/claudio.cpp + src/claudio_configured.cpp + ) +target_include_directories(${PROJECT_NAME} PRIVATE include ${CMAKE_BINARY_DIR}/individuals) +target_link_libraries(${PROJECT_NAME} clap-core clap-helpers) +set_property(TARGET ${PROJECT_NAME} PROPERTY AIRWIN_INCLUDES "") +set_property(TARGET ${PROJECT_NAME} PROPERTY AIRWIN_COUNT 0) + +function (addAirwin airwin) + set(awt claudio_${airwin}) + set(aw_src libs/airwindows/plugins/MacVST/${airwin}/source) + add_library(${awt} STATIC ${aw_src}/${airwin}.cpp ${aw_src}/${airwin}Proc.cpp) + target_include_directories(${awt} PRIVATE include) + if (APPLE) + target_compile_options(${PROJECT_NAME} PRIVATE + -Werror -Wno-unused-value + ) + endif() + + set(CREATE_FN "${awt}CreateEffectInstance") + set(AIRWIN_NAME "${airwin}") + configure_file(src/individual_claudio.in.h individuals/${awt}.h) + configure_file(src/individual_claudio.in.cpp individuals/${awt}.cpp) + + target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR}/individuals/${awt}.cpp) + + target_compile_definitions(${awt} PRIVATE -DcreateEffectInstance=${CREATE_FN}) + target_link_libraries(${PROJECT_NAME} ${awt}) + + get_target_property(AW ${PROJECT_NAME} AIRWIN_INCLUDES) + list(APPEND AW ${airwin}) + set_property(TARGET ${PROJECT_NAME} PROPERTY AIRWIN_INCLUDES ${AW}) + + get_target_property(AWC ${PROJECT_NAME} AIRWIN_COUNT) + math(EXPR AWC "${AWC} + 1") + set_property(TARGET ${PROJECT_NAME} PROPERTY AIRWIN_COUNT ${AWC}) +endfunction() + +addAirwin(Chamber) +addAirwin(Galactic) +addAirwin(ZLowpass) +addAirwin(DeBess) + + +get_target_property(AWC ${PROJECT_NAME} AIRWIN_COUNT) +message(STATUS "Generating ${AWC} plugins" ) + +set(sumfn "${CMAKE_BINARY_DIR}/individuals/claudio_configured.hxx") +file(WRITE ${sumfn} "// machine generated. Include once\n") + +get_target_property(AW ${PROJECT_NAME} AIRWIN_INCLUDES) +foreach(awt ${AW}) + message(STATUS "Airwindow: ${awt}") + file(APPEND ${sumfn} "#include \"claudio_${awt}.h\"\n") +endforeach() + +file(APPEND ${sumfn} "uint32_t claudio_get_plugin_count(const clap_plugin_factory *f) { return ${AWC}; }\n") +file(APPEND ${sumfn} "const clap_plugin_descriptor *claudio_get_plugin_descriptor(const clap_plugin_factory *f, uint32_t w)\n") +file(APPEND ${sumfn} "{ switch(w) {\n") +set(CASEW 0) +foreach(awt ${AW}) + + file(APPEND ${sumfn} "case ${CASEW}:\n") + file(APPEND ${sumfn} " return &claudio_${awt}_desc;\n") + file(APPEND ${sumfn} " break;\n") + math(EXPR CASEW "${CASEW} + 1") +endforeach() +file(APPEND ${sumfn} "} return nullptr; } \n") + +file(APPEND ${sumfn} "AudioEffect *claudio_get_aeffInstance(audioMasterCallback c, const char* plugin_id)\n") +file(APPEND ${sumfn} "{") +set(CASEW 0) +foreach(awt ${AW}) + + file(APPEND ${sumfn} "if (strcmp(plugin_id, \"unofficial.com.airwindows.${awt}\") == 0) return claudio_${awt}CreateEffectInstance(c);\n") +endforeach() +file(APPEND ${sumfn} "return nullptr; } \n") + + +if(APPLE) + set_target_properties(${PROJECT_NAME} PROPERTIES + BUNDLE True + BUNDLE_EXTENSION clap + MACOSX_BUNDLE_GUI_IDENTIFIER org.surge-synth-team.${PROJECT_NAME} + MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME} + MACOSX_BUNDLE_BUNDLE_VERSION "0.1" + MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1" + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/${PROJECT_NAME}.plist.in + ) + + target_compile_definitions(${PROJECT_NAME} PRIVATE IS_MAC=1) + target_compile_options(${PROJECT_NAME} PRIVATE + -Werror -Wno-unused-value + $<$:-fsanitize=address> + $<$:-fsanitize=undefined> + ) + target_link_options(${PROJECT_NAME} PRIVATE + $<$:-fsanitize=address> + $<$:-fsanitize=undefined> + ) + + if (${COPY_AFTER_BUILD}) + message(STATUS "Will copy plugin after every build" ) + set(products_folder ${CMAKE_BINARY_DIR}) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "Installing ${products_folder}/${PROJECT_NAME}.clap to ~/Library/Audio/Plug-Ins/CLAP/" + COMMAND ${CMAKE_COMMAND} -E make_directory "~/Library/Audio/Plug-Ins/CLAP" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${products_folder}/${PROJECT_NAME}.clap" "~/Library/Audio/Plug-Ins/CLAP/${PROJECT_NAME}.clap" + ) + endif() +elseif(UNIX) + target_compile_definitions(${PROJECT_NAME} PRIVATE IS_LINUX=1) + set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".clap" PREFIX "") + if (${COPY_AFTER_BUILD}) + message(STATUS "Will copy plugin after every build" ) + set(products_folder ${CMAKE_BINARY_DIR}) + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "Installing ${products_folder}/${PROJECT_NAME}.clap to ~/.clap" + COMMAND ${CMAKE_COMMAND} -E make_directory "~/.clap" + COMMAND ${CMAKE_COMMAND} -E copy "${products_folder}/${PROJECT_NAME}.clap" "~/.clap" + ) + endif() + +else() + target_compile_definitions(${PROJECT_NAME} PRIVATE IS_WIN=1) + set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".clap" PREFIX "") +endif() diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..b2c7d2e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,9 @@ +Copyright 2022, Paul Walker and others as listed in the git history + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + diff --git a/cmake/claudio-effect-x.plist.in b/cmake/claudio-effect-x.plist.in new file mode 100644 index 0000000..f61f8fa --- /dev/null +++ b/cmake/claudio-effect-x.plist.in @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CSResourcesFileMapped + + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + + diff --git a/include/audioeffectx.h b/include/audioeffectx.h new file mode 100644 index 0000000..e62a6bb --- /dev/null +++ b/include/audioeffectx.h @@ -0,0 +1,64 @@ +// +// Created by Paul Walker on 6/18/22. +// + +#ifndef CLAUDIO_EFFECT_X_AUDIOEFFECTX_H +#define CLAUDIO_EFFECT_X_AUDIOEFFECTX_H + +#include +#include + +struct clap_host; +typedef const clap_host * audioMasterCallback; +typedef int VstPlugCategory; +typedef int32_t VstInt32; +#define vst_strncpy strncpy + +static constexpr uint32_t kVstMaxProgNameLen = 32; +static constexpr uint32_t kVstMaxParamStrLen = 64; +static constexpr uint32_t kVstMaxProductStrLen = 64; +static constexpr uint32_t kVstMaxVendorStrLen = 64; + +static constexpr uint32_t kPlugCategEffect = 1; + +inline void float2string(float, const char*, uint32_t) {} + +struct AudioEffect +{ + virtual ~AudioEffect() = default; + + + double getSampleRate() { return 48000.0; } + + void setNumInputs(uint32_t kNumInputs) {} + void setNumOutputs(uint32_t kNumOutputs) {} + void setUniqueID(uint32_t kUniqueId) {} + + bool canProcessReplacing() { return false; } + bool canDoubleReplacing() { return false; } + + void programsAreChunks(bool b) {} + + virtual bool getEffectName(char* name) = 0; // The plug-in name + virtual VstPlugCategory getPlugCategory() = 0; // The general category for the plug-in + virtual bool getProductString(char* text) = 0; // This is a unique plug-in string provided by Steinberg + virtual bool getVendorString(char* text) = 0 ; // Vendor info + virtual VstInt32 getVendorVersion() = 0; // Version number + virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) = 0; + virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames) = 0; + virtual VstInt32 getChunk (void** data, bool isPreset) = 0; + virtual VstInt32 setChunk (void* data, VstInt32 byteSize, bool isPreset) = 0; + virtual float getParameter(VstInt32 index) = 0; // get the parameter value at the specified index + virtual void setParameter(VstInt32 index, float value) = 0; // set the parameter at index to value + virtual void getParameterLabel(VstInt32 index, char *text) = 0; // label for the parameter (eg dB) + virtual void getParameterName(VstInt32 index, char *text) = 0; // name of the parameter + virtual void getParameterDisplay(VstInt32 index, char *text) = 0; // text description of the current value + virtual VstInt32 canDo(char *text) = 0; +}; + +struct AudioEffectX : public AudioEffect +{ + AudioEffectX(audioMasterCallback audioMaster, uint32_t kNumPrograms, uint32_t kNumParameters) {} +}; + +#endif //CLAUDIO_EFFECT_X_AUDIOEFFECTX_H diff --git a/libs/airwindows b/libs/airwindows new file mode 160000 index 0000000..adb0bdc --- /dev/null +++ b/libs/airwindows @@ -0,0 +1 @@ +Subproject commit adb0bdc2f72f080159f67101d1c84bd94269bfe1 diff --git a/libs/clap b/libs/clap new file mode 160000 index 0000000..55ee06f --- /dev/null +++ b/libs/clap @@ -0,0 +1 @@ +Subproject commit 55ee06f776669b94d63247a9c1dcb7dfa6056587 diff --git a/libs/clap-helpers b/libs/clap-helpers new file mode 160000 index 0000000..716cdf4 --- /dev/null +++ b/libs/clap-helpers @@ -0,0 +1 @@ +Subproject commit 716cdf49cc6eb7999bad44c084b363bbde907937 diff --git a/src/claudio.cpp b/src/claudio.cpp new file mode 100644 index 0000000..731dcf4 --- /dev/null +++ b/src/claudio.cpp @@ -0,0 +1,17 @@ +// +// Created by Paul Walker on 6/18/22. +// + +#include "audioeffectx.h" + +#include "claudio_Galactic.h" + +#include "clap/clap.h" + + + +int foo() +{ + claudio_GalacticCreateEffectInstance(nullptr); + return 0; +} \ No newline at end of file diff --git a/src/claudio_configured.cpp b/src/claudio_configured.cpp new file mode 100644 index 0000000..e7b56e6 --- /dev/null +++ b/src/claudio_configured.cpp @@ -0,0 +1,44 @@ +// +// Created by Paul Walker on 6/19/22. +// + +#include "claudio_configured.hxx" + +#include +#include +#include + + +static const clap_plugin *clap_create_plugin(const clap_plugin_factory *f, const clap_host *host, + const char *plugin_id) +{ + auto fx = claudio_get_aeffInstance(host, plugin_id); + std::cout << "FX = " << fx << " plugin_id = " << plugin_id << std::endl; + + return nullptr; +} + +const CLAP_EXPORT struct clap_plugin_factory claudio_factory = { + claudio_get_plugin_count, + claudio_get_plugin_descriptor, + clap_create_plugin, +}; + +static const void *get_factory(const char *factory_id) { return &claudio_factory; } + +// clap_init and clap_deinit are required to be fast, but we have nothing we need to do here +bool clap_init(const char *p) { return true; } + +void clap_deinit() {} + +extern "C" +{ +// clang-format off +const CLAP_EXPORT struct clap_plugin_entry clap_entry = { + CLAP_VERSION, + clap_init, + clap_deinit, + get_factory +}; +// clang-format on +} \ No newline at end of file diff --git a/src/individual_claudio.in.cpp b/src/individual_claudio.in.cpp new file mode 100644 index 0000000..9557b50 --- /dev/null +++ b/src/individual_claudio.in.cpp @@ -0,0 +1,18 @@ +// +// Created by Paul Walker on 6/19/22. +// + +#include "audioeffectx.h" +#include "claudio_@AIRWIN_NAME@.h" + +const char *@AIRWIN_NAME@_features[] = {CLAP_PLUGIN_FEATURE_AUDIO_EFFECT, nullptr}; +clap_plugin_descriptor claudio_@AIRWIN_NAME@_desc = {CLAP_VERSION, + "unofficial.com.airwindows.@AIRWIN_NAME@", // change this change the cmake generatortoo + "Airwindows @AIRWIN_NAME@ (Unofficial)", + "Unsupported", + "https://airwindows.com", + "", + "", + "1.0.0", + "The airwindows effect @AIRWIN_NAME@.", + @AIRWIN_NAME@_features}; \ No newline at end of file diff --git a/src/individual_claudio.in.h b/src/individual_claudio.in.h new file mode 100644 index 0000000..0afec62 --- /dev/null +++ b/src/individual_claudio.in.h @@ -0,0 +1,14 @@ +// +// Created by Paul Walker on 6/19/22. +// + +#ifndef CLAUDIO_EFFECT_@AIRWIN_NAME@_X_INDIVIDUAL_CLAUDIO_IN_H +#define CLAUDIO_EFFECT_@AIRWIN_NAME@_X_INDIVIDUAL_CLAUDIO_IN_H + +#include "audioeffectx.h" +#include + +extern AudioEffect * @CREATE_FN@ (audioMasterCallback audioMaster); +extern clap_plugin_descriptor claudio_@AIRWIN_NAME@_desc; + +#endif //CLAUDIO_EFFECT_X_INDIVIDUAL_CLAUDIO_IN_H