AnalogTapeModel

Physical modelling signal processing for analog tape recording
Log | Files | Refs | Submodules | README | LICENSE

commit dabe5925b335daec05cdbcdfaaf684f1dbfaf371
parent 5f50d0c85d48faa0efd75698e3b89afe5e008f45
Author: jatinchowdhury18 <[email protected]>
Date:   Sun, 21 Feb 2021 23:13:57 -0800

Fix filter stability issue in tone filters (#139)

* Fix filter stability issue in tone filters

* Fix add_subdirectory(JUCE) for case-sensitive file systems

* Debug Linux build

* Adjust GitHub Actions build command

* Don't debug gh-actions build

Co-authored-by: jatinchowdhury18 <[email protected]>
Diffstat:
M.github/workflows/cmake.yml | 3++-
M.gitmodules | 7+++++--
MCHANGELOG.md | 6+++++-
MPlugin/CMakeLists.txt | 49+------------------------------------------------
DPlugin/Juce | 1-
DPlugin/Source/Processors/BilinearUtils.h | 55-------------------------------------------------------
MPlugin/Source/Processors/Hysteresis/DCBlocker.h | 1-
MPlugin/Source/Processors/Hysteresis/ToneControl.h | 5+++--
DPlugin/Source/Processors/Hysteresis/ToneFilter.h | 46----------------------------------------------
DPlugin/Source/Processors/IIRFilter.h | 83-------------------------------------------------------------------------------
DPlugin/foleys_gui_magic | 1-
APlugin/modules/CMakeLists.txt | 50++++++++++++++++++++++++++++++++++++++++++++++++++
APlugin/modules/JUCE | 1+
APlugin/modules/chowdsp_utils | 1+
APlugin/modules/foleys_gui_magic | 1+
15 files changed, 69 insertions(+), 241 deletions(-)

diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml @@ -44,6 +44,7 @@ jobs: submodules: true # - name: Setup debug session + # if: runner.os == 'Linux' # uses: mxschmitt/action-tmate@v3 - name: Configure @@ -54,7 +55,7 @@ jobs: - name: Build shell: bash working-directory: ${{github.workspace}}/Plugin - run: cmake --build build --config Release --parallel + run: cmake --build build --config Release --parallel 4 - name: Pluginval if: runner.os == 'Windows' || runner.os == 'MacOS' diff --git a/.gitmodules b/.gitmodules @@ -1,6 +1,9 @@ [submodule "Plugin/Juce"] - path = Plugin/Juce + path = Plugin/modules/JUCE url = https://github.com/Chowdhury-DSP/DISTRHO-JUCE.git [submodule "Plugin/foleys_gui_magic"] - path = Plugin/foleys_gui_magic + path = Plugin/modules/foleys_gui_magic url = https://github.com/jatinchowdhury18/foleys_gui_magic.git +[submodule "Plugin/modules/chowdsp_utils"] + path = Plugin/modules/chowdsp_utils + url = https://github.com/Chowdhury-DSP/chowdsp_utils diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -4,8 +4,12 @@ this file. ## [Unreleased] -- Migrated build pipeline to CMake. +- Fixed stability issue in tone filters. +- Improved parameter names for automation menus. +- Fixed GUI freezing bug in Cakewalk. - Fixed gain staging bug in Renoise. +- Migrated build pipeline to CMake. + ## [2.7.0] - 2020-11-25 - Added new hysteresis mode: State Transition Network (STN) - Updated Loss Filters to improve frequency response and phase response. diff --git a/Plugin/CMakeLists.txt b/Plugin/CMakeLists.txt @@ -3,54 +3,7 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "Minimum OS X deployment ta set(CMAKE_CXX_STANDARD 17) project(CHOWTapeModel VERSION 2.7.0) -# set up JUCE and modules -add_subdirectory(Juce) -juce_add_modules(foleys_gui_magic) - -add_library(juce_plugin_modules STATIC) -target_link_libraries(juce_plugin_modules - PRIVATE - BinaryData - juce::juce_audio_utils - juce::juce_audio_plugin_client - foleys_gui_magic - PUBLIC - juce::juce_recommended_config_flags - juce::juce_recommended_lto_flags - juce::juce_recommended_warning_flags -) - -target_compile_definitions(juce_plugin_modules - PUBLIC - JUCE_DISPLAY_SPLASH_SCREEN=0 - JUCE_REPORT_APP_USAGE=0 - JUCE_WEB_BROWSER=0 - JUCE_USE_CURL=0 - JUCE_VST3_CAN_REPLACE_VST2=0 - FOLEYS_SHOW_GUI_EDITOR_PALLETTE=0 - FOLEYS_ENABLE_BINARY_DATA=1 - JucePlugin_Manufacturer="chowdsp" - JucePlugin_VersionString="${CMAKE_PROJECT_VERSION}" - JucePlugin_Name="${CMAKE_PROJECT_NAME}" - INTERFACE - $<TARGET_PROPERTY:juce_plugin_modules,COMPILE_DEFINITIONS> -) - -if(MSVC) - target_compile_options(juce_plugin_modules PRIVATE /wd4458) # supress "declaration hides class member" for Foley's -endif() - -target_include_directories(juce_plugin_modules - INTERFACE - $<TARGET_PROPERTY:juce_plugin_modules,INCLUDE_DIRECTORIES> -) - -set_target_properties(juce_plugin_modules PROPERTIES - POSITION_INDEPENDENT_CODE TRUE - VISIBILITY_INLINES_HIDDEN TRUE - C_VISBILITY_PRESET hidden - CXX_VISIBILITY_PRESET hidden -) +add_subdirectory(modules) # set up plugin project # juce_set_vst2_sdk_path(C:/SDKs/VST_SDK/VST2_SDK/) diff --git a/Plugin/Juce b/Plugin/Juce @@ -1 +0,0 @@ -Subproject commit 5d503f334ddb849b3e13f5d7d28e553686f44f9e diff --git a/Plugin/Source/Processors/BilinearUtils.h b/Plugin/Source/Processors/BilinearUtils.h @@ -1,55 +0,0 @@ -#pragma once - -#include <cmath> - -namespace Bilinear -{ -/** Dummy generic bilinear transform (@TODO: actually implement this) */ -template <typename T, size_t N> -struct BilinearTransform -{ - static inline void call (T (&b)[N], T (&a)[N], T (&bs)[N], T (&as)[N], T K); -}; - -/** Bilinear transform for a first-order filter */ -template <typename T> -struct BilinearTransform<T, 2> -{ - static inline void call (T (&b)[2], T (&a)[2], T (&bs)[2], T (&as)[2], T K) - { - const auto a0 = as[0] * K + as[1]; - b[0] = (bs[0] * K + bs[1]) / a0; - b[1] = (-bs[0] * K + bs[1]) / a0; - a[0] = 1.0f; - a[1] = (-as[0] * K + as[1]) / a0; - } -}; - -/** Bilinear transform for a second-order filter */ -template <typename T> -struct BilinearTransform<T, 3> -{ - static inline void call (T (&b)[3], T (&a)[3], T (&bs)[3], T (&as)[3], T K) - { - const auto KSq = K * K; - const float a0 = as[0] * KSq + as[1] * K + as[2]; - - a[0] = 1.0f; - a[1] = 2.0f * (as[2] - as[0] * KSq) / a0; - a[2] = (as[0] * KSq - as[1] * K + as[2]) / a0; - b[0] = (bs[0] * KSq + bs[1] * K + bs[2]) / a0; - b[1] = 2.0f * (bs[2] - bs[0] * KSq) / a0; - b[2] = (bs[0] * KSq - bs[1] * K + bs[2]) / a0; - } -}; - -inline float calcPoleFreq (float a, float b, float c) -{ - auto radicand = b * b - 4.0f * a * c; - if (radicand >= 0.0f) - return 0.0f; - - return std::sqrt (-radicand) / (2.0f * a); -} - -} // namespace Bilinear diff --git a/Plugin/Source/Processors/Hysteresis/DCBlocker.h b/Plugin/Source/Processors/Hysteresis/DCBlocker.h @@ -1,7 +1,6 @@ #ifndef DCBLOCKER_H_INCLUDED #define DCBLOCKER_H_INCLUDED -#include "../IIRFilter.h" #include <JuceHeader.h> /** DC blocking filter */ diff --git a/Plugin/Source/Processors/Hysteresis/ToneControl.h b/Plugin/Source/Processors/Hysteresis/ToneControl.h @@ -1,13 +1,14 @@ #ifndef TONECONTROL_H_INCLUDED #define TONECONTROL_H_INCLUDED -#include "ToneFilter.h" +#include <JuceHeader.h> using SmoothGain = SmoothedValue<float, ValueSmoothingTypes::Multiplicative>; struct ToneStage { - ToneFilter tone[2]; + // ToneFilter tone[2]; + chowdsp::ShelfFilter<float> tone[2]; SmoothGain lowGain[2], highGain[2], tFreq[2]; float fs = 44100.0f; diff --git a/Plugin/Source/Processors/Hysteresis/ToneFilter.h b/Plugin/Source/Processors/Hysteresis/ToneFilter.h @@ -1,46 +0,0 @@ -#ifndef TONEFILTER_H_INCLUDED -#define TONEFILTER_H_INCLUDED - -#include "../BilinearUtils.h" -#include "../IIRFilter.h" - -/** A first order shelving filter, with a set gain at DC, -* a set gain at high frequencies, and a transition frequency. -*/ -class ToneFilter : public chowdsp::IIRFilter<1> -{ -public: - ToneFilter() = default; - - /** Calculates the coefficients for the filter. - * @param lowGain: the gain of the filter at low frequencies - * @param highGain: the gain of the filter at high frequencies - * @param fc: the transition frequency of the filter - * @param fs: the sample rate for the filter - */ - void calcCoefs (float lowGain, float highGain, float fc, float fs) - { - // reduce to simple gain element - if (lowGain == highGain) - { - this->b[0] = lowGain; - this->b[1] = 0.0f; - this->a[0] = 1.0f; - this->a[1] = 0.0f; - return; - } - - auto wc = MathConstants<float>::twoPi * fc; - auto p = std::sqrt (wc * wc * (highGain * highGain - lowGain * highGain) / (lowGain * highGain - lowGain * lowGain)); - auto K = p / std::tan (p / (2.0f * fs)); - - float bs[2] { highGain / p, lowGain }; - float as[2] { 1.0f / p, 1.0f }; - Bilinear::BilinearTransform<float, 2>::call (this->b, this->a, bs, as, K); - } - -private: - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToneFilter) -}; - -#endif // TONEFILTER_H_INCLUDED diff --git a/Plugin/Source/Processors/IIRFilter.h b/Plugin/Source/Processors/IIRFilter.h @@ -1,83 +0,0 @@ -#pragma once - -#include <JuceHeader.h> - -namespace chowdsp -{ -/** IIR filter of arbirtary order. - * Uses Transposed Direct Form II: - * https://ccrma.stanford.edu/~jos/fp/Transposed_Direct_Forms.html - */ -template <int order, typename FloatType = float> -class IIRFilter -{ -public: - IIRFilter() = default; - virtual ~IIRFilter() {} - - /** Reset filter state */ - virtual void reset() - { - std::fill (z, &z[order + 1], 0.0f); - } - - /** Set coefficients to new values */ - virtual void setCoefs (const FloatType (&newB)[order + 1], const FloatType (&newA)[order + 1]) - { - std::copy (newB, &newB[order + 1], b); - std::copy (newA, &newA[order + 1], a); - } - - /** Optimized processing call for first-order filter */ - template <int N = order> - inline typename std::enable_if<N == 1, FloatType>::type - processSample (FloatType x) noexcept - { - FloatType y = z[1] + x * b[0]; - z[order] = x * b[order] - y * a[order]; - return y; - } - - /** Optimized processing call for second-order filter */ - template <int N = order> - inline typename std::enable_if<N == 2, FloatType>::type - processSample (FloatType x) noexcept - { - FloatType y = z[1] + x * b[0]; - z[1] = z[2] + x * b[1] - y * a[1]; - z[order] = x * b[order] - y * a[order]; - return y; - } - - /** Optimized processing call for Nth-order filter */ - template <int N = order> - inline typename std::enable_if<(N > 2), FloatType>::type - processSample (FloatType x) noexcept - { - FloatType y = z[1] + x * b[0]; - - for (int i = 1; i < order; ++i) - z[i] = z[i + 1] + x * b[i] - y * a[i]; - - z[order] = x * b[order] - y * a[order]; - - return y; - } - - /** Process block of samples */ - virtual void processBlock (FloatType* block, const int numSamples) noexcept - { - for (int n = 0; n < numSamples; ++n) - block[n] = processSample (block[n]); - } - -protected: - FloatType a[order + 1]; - FloatType b[order + 1]; - FloatType z[order + 1]; - -private: - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IIRFilter) -}; - -} // namespace chowdsp diff --git a/Plugin/foleys_gui_magic b/Plugin/foleys_gui_magic @@ -1 +0,0 @@ -Subproject commit 49c87190bcf3bd3fe1dcc281faff0793afaeb775 diff --git a/Plugin/modules/CMakeLists.txt b/Plugin/modules/CMakeLists.txt @@ -0,0 +1,50 @@ +# set up JUCE and modules +add_subdirectory(JUCE) +juce_add_modules(foleys_gui_magic) +juce_add_modules(chowdsp_utils) + +add_library(juce_plugin_modules STATIC) +target_link_libraries(juce_plugin_modules + PRIVATE + BinaryData + juce::juce_audio_utils + juce::juce_audio_plugin_client + foleys_gui_magic + chowdsp_utils + PUBLIC + juce::juce_recommended_config_flags + juce::juce_recommended_lto_flags + juce::juce_recommended_warning_flags +) + +target_compile_definitions(juce_plugin_modules + PUBLIC + JUCE_DISPLAY_SPLASH_SCREEN=0 + JUCE_REPORT_APP_USAGE=0 + JUCE_WEB_BROWSER=0 + JUCE_USE_CURL=0 + JUCE_VST3_CAN_REPLACE_VST2=0 + FOLEYS_SHOW_GUI_EDITOR_PALLETTE=0 + FOLEYS_ENABLE_BINARY_DATA=1 + JucePlugin_Manufacturer="chowdsp" + JucePlugin_VersionString="${CMAKE_PROJECT_VERSION}" + JucePlugin_Name="${CMAKE_PROJECT_NAME}" + INTERFACE + $<TARGET_PROPERTY:juce_plugin_modules,COMPILE_DEFINITIONS> +) + +if(MSVC) + target_compile_options(juce_plugin_modules PRIVATE /wd4458) # supress "declaration hides class member" for Foley's +endif() + +target_include_directories(juce_plugin_modules + INTERFACE + $<TARGET_PROPERTY:juce_plugin_modules,INCLUDE_DIRECTORIES> +) + +set_target_properties(juce_plugin_modules PROPERTIES + POSITION_INDEPENDENT_CODE TRUE + VISIBILITY_INLINES_HIDDEN TRUE + C_VISBILITY_PRESET hidden + CXX_VISIBILITY_PRESET hidden +) diff --git a/Plugin/modules/JUCE b/Plugin/modules/JUCE @@ -0,0 +1 @@ +Subproject commit 5d503f334ddb849b3e13f5d7d28e553686f44f9e diff --git a/Plugin/modules/chowdsp_utils b/Plugin/modules/chowdsp_utils @@ -0,0 +1 @@ +Subproject commit 4fef4b854c1cda03526ef54dc9d56e31fdea3cfa diff --git a/Plugin/modules/foleys_gui_magic b/Plugin/modules/foleys_gui_magic @@ -0,0 +1 @@ +Subproject commit 49c87190bcf3bd3fe1dcc281faff0793afaeb775