5 |
6 | # ZLWarm
7 | ![pluginval]()
8 |
9 | ZLWarm is a distortion/saturation plugin.
10 |
11 |
12 |
13 | ## Usage
14 |
15 | See the wiki for details.
16 |
17 | ## Download
18 |
19 | See the releases for the latest version.
20 |
21 | **Please NOTICE**:
22 | - the installer has **NOT** been notarized/EV certificated on macOS/Windows
23 | - the plugin has **NOT** been fully tested on DAWs
24 |
25 | ## Build from Source
26 |
27 | 0. `git clone` this repo
28 |
29 | 1. [Download CMAKE](https://cmake.org/download/) if you do not have it.
30 |
31 | 2. Populate the latest JUCE by running `git submodule update --init` in your repository directory.
32 |
33 | 3. Follow the [JUCE CMake API](https://github.com/juce-framework/JUCE/blob/master/docs/CMake%20API.md) to build the source.
34 |
35 | ## License
36 |
37 | ZLWarm is licensed under GPLv3, as found in the [LICENSE.md](LICENSE.md) file.
38 |
39 | Copyright (c) 2023 - [zsliu98](https://github.com/zsliu98)
40 |
41 | JUCE framework from [JUCE](https://github.com/juce-framework/JUCE)
42 |
43 | JUCE template from [pamplejuce](https://github.com/sudara/pamplejuce)
44 |
45 | [Friz](https://github.com/bgporter/animator) by [bgporter](https://github.com/bgporter)
46 |
47 | [RemixIcon](https://github.com/Remix-Design/RemixIcon) by [Remix-Design](https://github.com/Remix-Design)
48 |
49 | Font from CMU Open Sans, Font Awesome and MiSans.
--------------------------------------------------------------------------------
/assets/font/MiSansLatin-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZL-Audio/ZLWarm/48093f38c079551924679c5b86bd02d348885f3a/assets/font/MiSansLatin-Medium.ttf
--------------------------------------------------------------------------------
/assets/icon/shut-down-line.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/icon/split-cells-horizontal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/cmake-includes/Assets.cmake:
--------------------------------------------------------------------------------
1 | # HEADS UP: Pamplejuce assumes anything you stick in the assets folder you want to included in your binary!
2 | # This makes life easy, but will bloat your binary needlessly if you include unused files
3 | file(GLOB_RECURSE AssetFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/assets/*")
4 |
5 | # Setup our binary data as a target called Assets
6 | juce_add_binary_data(Assets SOURCES ${AssetFiles})
7 |
8 | # Required for Linux happiness:
9 | # See https://forum.juce.com/t/loading-pytorch-model-using-binarydata/39997/2
10 | set_target_properties(Assets PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
11 |
--------------------------------------------------------------------------------
/cmake-includes/Benchmarks.cmake:
--------------------------------------------------------------------------------
1 | file(GLOB_RECURSE BenchmarkFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/benchmarks/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Benchmarks/*.h")
2 |
3 | # Organize the test source in the Tests/ folder in the IDE
4 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/benchmarks PREFIX "" FILES ${BenchmarkFiles})
5 |
6 | add_executable(Benchmarks ${BenchmarkFiles})
7 | target_compile_features(Benchmarks PRIVATE cxx_std_20)
8 | catch_discover_tests(Benchmarks)
9 |
10 | # Our benchmark executable also wants to know about our plugin code...
11 | target_include_directories(Benchmarks PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/source)
12 |
13 | # Copy over compile definitions from our plugin target so it has all the JUCEy goodness
14 | target_compile_definitions(Benchmarks PRIVATE $)
15 |
16 | # And give tests access to our shared code
17 | target_link_libraries(Benchmarks PRIVATE SharedCode Catch2::Catch2WithMain)
18 |
19 | # Make an Xcode Scheme for the test executable so we can run tests in the IDE
20 | set_target_properties(Benchmarks PROPERTIES XCODE_GENERATE_SCHEME ON)
21 |
22 | # When running Tests we have specific needs
23 | target_compile_definitions(Benchmarks PUBLIC
24 | JUCE_MODAL_LOOPS_PERMITTED=1 # let us run Message Manager in tests
25 | RUN_PAMPLEJUCE_TESTS=1 # also run tests in module .cpp files guarded by RUN_PAMPLEJUCE_TESTS
26 | )
27 |
--------------------------------------------------------------------------------
/cmake-includes/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 2023-09-04
2 |
3 | * Added `SharedCodeDefaults.cmake` which handles setting C++20 and fast math on the `SharedCode` Target.
4 | * Modified CTest to report on failure
5 |
6 | ## 2023-09-04
7 |
8 | Initial commit. Added this CHANGELOG.
9 |
--------------------------------------------------------------------------------
/cmake-includes/GitHubENV.cmake:
--------------------------------------------------------------------------------
1 | # Write some temp files to make GitHub Actions / packaging easy
2 |
3 | if ((DEFINED ENV{CI}))
4 | set (env_file "${PROJECT_SOURCE_DIR}/.env")
5 | message ("Writing ENV file for CI: ${env_file}")
6 |
7 | # the first call truncates, the rest append
8 | file(WRITE "${env_file}" "PROJECT_NAME=${PROJECT_NAME}\n")
9 | file(APPEND "${env_file}" "PRODUCT_NAME=${PRODUCT_NAME}\n")
10 | file(APPEND "${env_file}" "VERSION=${CURRENT_VERSION}\n")
11 | file(APPEND "${env_file}" "BUNDLE_ID=${BUNDLE_ID}\n")
12 | file(APPEND "${env_file}" "COMPANY_NAME=${COMPANY_NAME}\n")
13 | endif ()
14 |
--------------------------------------------------------------------------------
/cmake-includes/GitVersion.cmake:
--------------------------------------------------------------------------------
1 | # Read version from git tag and write it to VERSION file
2 | find_package(Git)
3 |
4 | if(GIT_EXECUTABLE)
5 | # Generate a git-describe version string from Git repository tags
6 | execute_process(
7 | COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
8 | OUTPUT_VARIABLE GIT_DESCRIBE_VERSION
9 | RESULT_VARIABLE GIT_DESCRIBE_ERROR_CODE
10 | OUTPUT_STRIP_TRAILING_WHITESPACE
11 | )
12 | if(NOT GIT_DESCRIBE_ERROR_CODE)
13 | set(FOOBAR_VERSION ${GIT_DESCRIBE_VERSION})
14 | endif()
15 | endif()
16 |
17 | if(NOT DEFINED FOOBAR_VERSION)
18 | set(FOOBAR_VERSION 0.0.0)
19 | message(WARNING "Failed to determine VERSION from Git tags. Using default version \"${FOOBAR_VERSION}\".")
20 | endif()
21 |
22 | string(REPLACE "v" "" FOOBAR_VERSION_WITHOUT_V "${FOOBAR_VERSION}")
23 |
24 | file(WRITE VERSION "${FOOBAR_VERSION_WITHOUT_V}")
--------------------------------------------------------------------------------
/cmake-includes/JUCEDefaults.cmake:
--------------------------------------------------------------------------------
1 | # Adds all the module sources so they appear correctly in the IDE
2 | # Must be set before JUCE is added as a sub-dir (or any targets are made)
3 | # https://github.com/juce-framework/JUCE/commit/6b1b4cf7f6b1008db44411f2c8887d71a3348889
4 | set_property(GLOBAL PROPERTY USE_FOLDERS YES)
5 |
6 | # Creates a /Modules directory in the IDE with the JUCE Module code
7 | option(JUCE_ENABLE_MODULE_SOURCE_GROUPS "Show all module sources in IDE projects" ON)
8 |
9 | # Color our warnings and errors
10 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
11 | add_compile_options(-fdiagnostics-color=always)
12 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
13 | add_compile_options(-fcolor-diagnostics)
14 | endif ()
15 |
--------------------------------------------------------------------------------
/cmake-includes/PamplejuceIPP.cmake:
--------------------------------------------------------------------------------
1 | # When present, use Intel IPP for performance on Windows
2 | if (WIN32) # Can't use MSVC here, as it won't catch Clang on Windows
3 | find_package(IPP)
4 | if (IPP_FOUND)
5 | target_link_libraries(SharedCode INTERFACE IPP::ipps IPP::ippcore IPP::ippi IPP::ippcv)
6 | message("IPP LIBRARIES FOUND")
7 | target_compile_definitions(SharedCode INTERFACE PAMPLEJUCE_IPP=1)
8 | else ()
9 | message("IPP LIBRARIES *NOT* FOUND")
10 | endif ()
11 | endif ()
12 |
--------------------------------------------------------------------------------
/cmake-includes/PamplejuceMacOS.cmake:
--------------------------------------------------------------------------------
1 |
2 | # This must be set before the project() call
3 | # see: https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_DEPLOYMENT_TARGET.html
4 | set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Support macOS down to High Sierra")
5 |
6 | # Building universal binaries on macOS increases build time
7 | # This is set on CI but not during local dev
8 | if ((DEFINED ENV{CI}) AND (CMAKE_BUILD_TYPE STREQUAL "Release"))
9 | message("Building for Apple Silicon and x86_64")
10 | set(CMAKE_OSX_ARCHITECTURES arm64 x86_64)
11 | endif ()
12 |
13 | # By default we don't want Xcode schemes to be made for modules, etc
14 | set(CMAKE_XCODE_GENERATE_SCHEME OFF)
15 |
--------------------------------------------------------------------------------
/cmake-includes/PamplejuceVersion.cmake:
--------------------------------------------------------------------------------
1 | # Reads in our VERSION file and sticks in it CURRENT_VERSION variable
2 | # Be sure the file has no newlines!
3 | # This exposes CURRENT_VERSION to the build system
4 | # And it's later fed to JUCE so it shows up as VERSION in your IDE
5 | file(STRINGS VERSION CURRENT_VERSION)
6 |
7 | # Figure out the major version to append to our PROJECT_NAME
8 | string(REGEX MATCH "([0-9]+)" MAJOR_VERSION ${CURRENT_VERSION})
9 | message(STATUS "Major version: ${MAJOR_VERSION}")
10 |
--------------------------------------------------------------------------------
/cmake-includes/README.md:
--------------------------------------------------------------------------------
1 | # CMake Includes for Pamplejuce
2 |
3 | Hi there!
4 |
5 | ## What is this?
6 |
7 | It's most of the actual CMake functionality used by [Pamplejuce](https://github.com/sudara/pamplejuce), my template repository for plugins in the JUCE framework.
8 |
9 | ## Why is this its own git submodule?
10 |
11 | It's to help projects built by the template pull in the lastest changes.
12 |
13 | [Pamplejuce](https://github.com/sudara/pamplejuce) is a template repository. Unlike most "dependencies," when you hit "Create Template" you are literally copying and pasting the code. Which sorta sucks, as people can't get fixes or updates.
14 |
15 | ## Why would I want updates?
16 |
17 | For at least the gritty CMake details, there are fixes, improvements and additional functionality being added.
18 |
19 | In the best case, as a submodule, you can pull in the fixes and improvements.
20 |
21 | In the worst case, this seperate repo will help you see what exactly changed in Pamplejuce.
22 |
23 | ## Is it risky?
24 |
25 | It could be!
26 |
27 | As of 2023, Pamplejuce is still being changed around a bunch, with the goal of being a better and better ecosystem for developers.
28 |
29 | That means there could be breakage when you pull.
30 |
31 | ## What changed recently tho?
32 |
33 | See [CHANGELOG.md](CHANGELOG.md).
34 |
--------------------------------------------------------------------------------
/cmake-includes/SharedCodeDefaults.cmake:
--------------------------------------------------------------------------------
1 | # fast math and better simd support in RELEASE and RELWITHDEBINFO
2 | if (MSVC)
3 | # https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior?view=msvc-170#fast
4 | target_compile_options(SharedCode INTERFACE $<$:/fp:fast>)
5 | else ()
6 | # See the implications here:
7 | # https://stackoverflow.com/q/45685487
8 | target_compile_options(SharedCode INTERFACE $<$:-Ofast>)
9 | target_compile_options(SharedCode INTERFACE $<$:-Ofast>)
10 | endif ()
11 |
12 | # Tell MSVC to properly report what c++ version is being used
13 | if (MSVC)
14 | target_compile_options(SharedCode INTERFACE /Zc:__cplusplus)
15 | endif ()
16 |
17 | # C++20, please
18 | # Use cxx_std_23 for C++23 (as of CMake v 3.20)
19 | target_compile_features(SharedCode INTERFACE cxx_std_20)
20 |
--------------------------------------------------------------------------------
/cmake-includes/Tests.cmake:
--------------------------------------------------------------------------------
1 | # Required for ctest (which is just an easier way to run in cross-platform CI)
2 | # include(CTest) could be used too, but adds additional targets we don't care about
3 | # See: https://github.com/catchorg/Catch2/issues/2026
4 | # You can also forgo ctest entirely and call ./Tests directly from the build dir
5 | enable_testing()
6 |
7 | # Go into detail when there's a CTest failure
8 | set(CTEST_OUTPUT_ON_FAILURE ON)
9 | set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1)
10 |
11 | # "GLOBS ARE BAD" is brittle and silly dev UX, sorry CMake!
12 | file(GLOB_RECURSE TestFiles CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.h")
13 |
14 | # Organize the test source in the Tests/ folder in Xcode
15 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/tests PREFIX "" FILES ${TestFiles})
16 |
17 | # Use Catch2 v3 on the devel branch
18 | Include(FetchContent)
19 | FetchContent_Declare(
20 | Catch2
21 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git
22 | GIT_PROGRESS TRUE
23 | GIT_SHALLOW TRUE
24 | GIT_TAG v3.4.0)
25 | FetchContent_MakeAvailable(Catch2) # find_package equivalent
26 |
27 | # Setup the test executable, again C++20 please
28 | add_executable(Tests ${TestFiles})
29 | target_compile_features(Tests PRIVATE cxx_std_20)
30 |
31 | # Our test executable also wants to know about our plugin code...
32 | target_include_directories(Tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/source)
33 |
34 | # Copy over compile definitions from our plugin target so it has all the JUCEy goodness
35 | target_compile_definitions(Tests PRIVATE $)
36 |
37 | # And give tests access to our shared code
38 | target_link_libraries(Tests PRIVATE SharedCode Catch2::Catch2WithMain)
39 |
40 | # Make an Xcode Scheme for the test executable so we can run tests in the IDE
41 | set_target_properties(Tests PROPERTIES XCODE_GENERATE_SCHEME ON)
42 |
43 | # When running Tests we have specific needs
44 | target_compile_definitions(Tests PUBLIC
45 | JUCE_MODAL_LOOPS_PERMITTED=1 # let us run Message Manager in tests
46 | RUN_PAMPLEJUCE_TESTS=1 # also run tests in other module .cpp files guarded by RUN_PAMPLEJUCE_TESTS
47 | )
48 |
49 | # Load and use the .cmake file provided by Catch2
50 | # https://github.com/catchorg/Catch2/blob/devel/docs/cmake-integration.md
51 | # We have to manually provide the source directory here for now
52 | include(${Catch2_SOURCE_DIR}/extras/Catch.cmake)
53 | catch_discover_tests(Tests)
54 |
--------------------------------------------------------------------------------
/cmake-includes/XcodePrettify.cmake:
--------------------------------------------------------------------------------
1 | # No, we don't want our source buried in extra nested folders
2 | set_target_properties(SharedCode PROPERTIES FOLDER "")
3 |
4 | # The Xcode source tree should uhhh, still look like the source tree, yo
5 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/source PREFIX "" FILES ${SourceFiles})
6 |
7 | # It tucks the Plugin varieties into a "Targets" folder and generate an Xcode Scheme manually
8 | # Xcode scheme generation is turned off globally to limit noise from other targets
9 | # The non-hacky way of doing this is via the global PREDEFINED_TARGETS_FOLDER property
10 | # However that doesn't seem to be working in Xcode
11 | # Not all plugin types (au, vst) available on each build type (win, macos, linux)
12 | foreach (target ${FORMATS} "All")
13 | if (TARGET ${PROJECT_NAME}_${target})
14 | set_target_properties(${PROJECT_NAME}_${target} PROPERTIES
15 | # Tuck the actual plugin targets into a folder where they won't bother us
16 | FOLDER "Targets"
17 | # Let us build the target in Xcode
18 | XCODE_GENERATE_SCHEME ON)
19 |
20 | # Set the default executable that Xcode will open on build
21 | # Note: you must manually build the AudioPluginHost.xcodeproj in the JUCE subdir
22 | if ((NOT target STREQUAL "All") AND (NOT target STREQUAL "Standalone"))
23 | set_target_properties(${PROJECT_NAME}_${target} PROPERTIES
24 | XCODE_SCHEME_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/JUCE/extras/AudioPluginHost/Builds/MacOSX/build/Debug/AudioPluginHost.app")
25 | endif ()
26 | endif ()
27 | endforeach ()
28 |
29 | if (TARGET Assets)
30 | set_target_properties(Assets PROPERTIES FOLDER "Targets")
31 | endif ()
32 |
--------------------------------------------------------------------------------
/docs/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
--------------------------------------------------------------------------------
/docs/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZL-Audio/ZLWarm/48093f38c079551924679c5b86bd02d348885f3a/docs/screenshot.png
--------------------------------------------------------------------------------
/licenses/Friz_LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019-2023 Brett g Porter
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/licenses/pamplejuce_LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Sudara Williams
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/modules/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZL-Audio/ZLWarm/48093f38c079551924679c5b86bd02d348885f3a/modules/.gitkeep
--------------------------------------------------------------------------------
/packaging/dmg.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "ZL Warm",
3 | "window": {
4 | "position": {
5 | "x": 100,
6 | "y": 100
7 | },
8 | "size": {
9 | "width": 730,
10 | "height": 520
11 | }
12 | },
13 | "format": "UDZO",
14 | "contents": [
15 | { "x": 250, "y": 245, "type": "file", "path": "dmg/ZL Warm.component" },
16 | { "x": 480, "y": 245, "type": "file", "path": "dmg/Your Mac's Component Folder" },
17 | { "x": 250, "y": 405, "type": "file", "path": "dmg/ZL Warm.vst3" },
18 | { "x": 480, "y": 405, "type": "file", "path": "dmg/Your Mac's VST3 Folder" }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/packaging/installer.iss:
--------------------------------------------------------------------------------
1 | #define Version Trim(FileRead(FileOpen("..\VERSION")))
2 | #define ProjectName GetEnv('PROJECT_NAME')
3 | #define ProductName GetEnv('PRODUCT_NAME')
4 | #define Publisher GetEnv('COMPANY_NAME')
5 | #define Year GetDateTimeString("yyyy","","")
6 |
7 | [Setup]
8 | ArchitecturesInstallIn64BitMode=x64
9 | ArchitecturesAllowed=x64
10 | AppName={#ProductName}
11 | OutputBaseFilename={#ProductName}-{#Version}
12 | AppCopyright=Copyright (C) {#Year} {#Publisher}
13 | AppPublisher={#Publisher}
14 | AppVersion={#Version}
15 | DefaultDirName="{commoncf64}\VST3\{#ProductName}.vst3"
16 | DisableDirPage=yes
17 |
18 | ; MAKE SURE YOU READ THE FOLLOWING!
19 | LicenseFile="EULA"
20 | UninstallFilesDir="{commonappdata}\{#ProductName}\uninstall"
21 |
22 | [UninstallDelete]
23 | Type: filesandordirs; Name: "{commoncf64}\VST3\{#ProductName}Data"
24 |
25 | ; MSVC adds a .ilk when building the plugin. Let's not include that.
26 | [Files]
27 | Source: "..\Builds\{#ProjectName}_artefacts\Release\VST3\{#ProductName}.vst3\*"; DestDir: "{commoncf64}\VST3\{#ProductName}.vst3\"; Excludes: *.ilk; Flags: ignoreversion recursesubdirs;
28 |
29 | [Run]
30 | Filename: "{cmd}"; \
31 | WorkingDir: "{commoncf64}\VST3"; \
32 | Parameters: "/C mklink /D ""{commoncf64}\VST3\{#ProductName}Data"" ""{commonappdata}\{#ProductName}"""; \
33 | Flags: runascurrentuser;
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base"
5 | ],
6 | "git-submodules": {
7 | "enabled": true
8 | },
9 | "schedule": "after 5am on Friday"
10 | }
--------------------------------------------------------------------------------
/source/PluginEditor.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #include "PluginEditor.h"
14 | #include
15 |
16 | //==============================================================================
17 | PluginEditor::PluginEditor(PluginProcessor &p) :
18 | AudioProcessorEditor(&p), processorRef(p),
19 | property(p.states),
20 | mainPanel(p) {
21 |
22 | for (auto &ID: IDs) {
23 | processorRef.states.addParameterListener(ID, this);
24 | }
25 | // set font
26 | auto sourceCodePro = juce::Typeface::createSystemTypefaceFor(BinaryData::MiSansLatinMedium_ttf,
27 | BinaryData::MiSansLatinMedium_ttfSize);
28 | juce::LookAndFeel::getDefaultLookAndFeel().setDefaultSansSerifTypeface(sourceCodePro);
29 |
30 | // add main panel
31 | addAndMakeVisible(mainPanel);
32 |
33 | // set size & size listener
34 | setResizeLimits(zlstate::windowW::minV, zlstate::windowH::minV, zlstate::windowW::maxV, zlstate::windowH::maxV);
35 | getConstrainer()->setFixedAspectRatio(
36 | static_cast(zlstate::windowW::defaultV) / static_cast(zlstate::windowH::defaultV));
37 | setResizable(true, p.wrapperType != PluginProcessor::wrapperType_AudioUnitv3);
38 | lastUIWidth.referTo(p.states.getParameterAsValue(zlstate::windowW::ID));
39 | lastUIHeight.referTo(p.states.getParameterAsValue(zlstate::windowH::ID));
40 | setSize(lastUIWidth.getValue(), lastUIHeight.getValue());
41 | lastUIWidth.addListener(this);
42 | lastUIHeight.addListener(this);
43 | }
44 |
45 | PluginEditor::~PluginEditor() {
46 | for (auto &ID: IDs) {
47 | processorRef.states.removeParameterListener(ID, this);
48 | }
49 | }
50 |
51 | //==============================================================================
52 | void PluginEditor::paint(juce::Graphics &g) {
53 | juce::ignoreUnused(g);
54 | }
55 |
56 | void PluginEditor::resized() {
57 | mainPanel.setBounds(getLocalBounds());
58 | lastUIWidth = getWidth();
59 | lastUIHeight = getHeight();
60 | }
61 |
62 | void PluginEditor::valueChanged(juce::Value &) {
63 | setSize(lastUIWidth.getValue(), lastUIHeight.getValue());
64 | }
65 |
66 | void PluginEditor::parameterChanged(const juce::String ¶meterID, float newValue) {
67 | juce::ignoreUnused(parameterID, newValue);
68 | triggerAsyncUpdate();
69 | }
70 |
71 | void PluginEditor::handleAsyncUpdate() {
72 | property.saveAPVTS(processorRef.states);
73 | sendLookAndFeelChange();
74 | }
--------------------------------------------------------------------------------
/source/PluginEditor.h:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #pragma once
14 |
15 | #include "panel/main_panel.h"
16 | #include "state/state_definitions.h"
17 | #include "state/property.h"
18 | #include "PluginProcessor.h"
19 |
20 | //==============================================================================
21 | /**
22 | */
23 | class PluginEditor : public juce::AudioProcessorEditor,
24 | private juce::Value::Listener,
25 | private juce::AudioProcessorValueTreeState::Listener,
26 | private juce::AsyncUpdater {
27 | public:
28 | explicit PluginEditor(PluginProcessor &);
29 |
30 | ~PluginEditor() override;
31 |
32 | //==============================================================================
33 | void paint(juce::Graphics &) override;
34 |
35 | void resized() override;
36 |
37 | private:
38 | PluginProcessor &processorRef;
39 | zlstate::Property property;
40 | MainPanel mainPanel;
41 | juce::Value lastUIWidth, lastUIHeight;
42 | constexpr const static std::array IDs{zlstate::uiStyle::ID,
43 | zlstate::windowW::ID, zlstate::windowH::ID};
44 |
45 | void valueChanged(juce::Value &) override;
46 |
47 | void parameterChanged(const juce::String ¶meterID, float newValue) override;
48 |
49 | void handleAsyncUpdate() override;
50 |
51 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginEditor)
52 | };
53 |
--------------------------------------------------------------------------------
/source/PluginProcessor.h:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #pragma once
14 |
15 | #include
16 | #include
17 |
18 | #include "dsp/dsp.hpp"
19 | #include "state/dummy_processor.h"
20 | #include "state/state_definitions.h"
21 |
22 | //==============================================================================
23 | /**
24 | */
25 | class PluginProcessor : public juce::AudioProcessor
26 | #if JucePlugin_Enable_ARA
27 | ,
28 | public juce::AudioProcessorARAExtension
29 | #endif
30 | {
31 | public:
32 | DummyProcessor dummyProcessor;
33 | juce::AudioProcessorValueTreeState parameters;
34 | juce::AudioProcessorValueTreeState states;
35 |
36 | //==============================================================================
37 | PluginProcessor();
38 |
39 | ~PluginProcessor() override;
40 |
41 | //==============================================================================
42 | void prepareToPlay(double sampleRate, int samplesPerBlock) override;
43 |
44 | void releaseResources() override;
45 |
46 | #ifndef JucePlugin_PreferredChannelConfigurations
47 |
48 | bool isBusesLayoutSupported(const BusesLayout &layouts) const override;
49 |
50 | #endif
51 |
52 | void process(juce::dsp::ProcessContextReplacing context);
53 |
54 | void processBlock(juce::AudioBuffer &, juce::MidiBuffer &) override;
55 |
56 | void reset() override;
57 |
58 | //==============================================================================
59 | juce::AudioProcessorEditor *createEditor() override;
60 |
61 | bool hasEditor() const override;
62 |
63 | //==============================================================================
64 | const juce::String getName() const override;
65 |
66 | bool acceptsMidi() const override;
67 |
68 | bool producesMidi() const override;
69 |
70 | bool isMidiEffect() const override;
71 |
72 | double getTailLengthSeconds() const override;
73 |
74 | //==============================================================================
75 | int getNumPrograms() override;
76 |
77 | int getCurrentProgram() override;
78 |
79 | void setCurrentProgram(int index) override;
80 |
81 | const juce::String getProgramName(int index) override;
82 |
83 | void changeProgramName(int index, const juce::String &newName) override;
84 |
85 | //==============================================================================
86 | void getStateInformation(juce::MemoryBlock &destData) override;
87 |
88 | void setStateInformation(const void *data, int sizeInBytes) override;
89 |
90 | inline zlDSP::Controller &getController() { return controller; }
91 |
92 | private:
93 | //==============================================================================
94 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginProcessor)
95 |
96 | zlDSP::Controller controller;
97 | zlDSP::ControllerAttach controllerAttach;
98 | };
99 |
--------------------------------------------------------------------------------
/source/dsp/controller.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #include "controller.hpp"
14 |
15 | namespace zlDSP {
16 | template
17 | void Controller::prepare(const juce::dsp::ProcessSpec &spec) {
18 | inMeter.prepare(spec);
19 | outMeter.prepare(spec);
20 | inGain.prepare(spec);
21 | outGain.prepare(spec);
22 | {
23 | juce::ScopedLock lock(oversampleLock);
24 | for (size_t i = 0; i < overSamplers.size(); ++i) {
25 | overSamplers[i] = std::make_unique>(
26 | spec.numChannels, i,
27 | juce::dsp::Oversampling::filterHalfBandFIREquiripple, true,
28 | true);
29 | overSamplers[i]->initProcessing(spec.maximumBlockSize);
30 | }
31 | }
32 | mainSpec = spec;
33 | setOverSampleID(oversampleID);
34 | }
35 |
36 | template
37 | void Controller::reset() {
38 |
39 | }
40 |
41 | template
42 | void Controller::process(juce::AudioBuffer &buffer) {
43 | juce::dsp::AudioBlock block(buffer);
44 | juce::dsp::ProcessContextReplacing context(block);
45 | inGain.process(block);
46 | inMeter.process(block);
47 | {
48 | juce::ScopedLock lock1(oversampleLock);
49 | auto oversampled_block =
50 | overSamplers[oversampleID]->processSamplesUp(context.getInputBlock());
51 |
52 | if (isSplitterON.load()) {
53 | splitter.split(oversampled_block);
54 |
55 | auto lBlock = juce::dsp::AudioBlock(splitter.getLBuffer());
56 | auto mBlock = juce::dsp::AudioBlock(splitter.getMBuffer());
57 | auto hBlock = juce::dsp::AudioBlock(splitter.getHBuffer());
58 |
59 | if (isShaperON.load()) {
60 | shaper.process(lBlock);
61 | shaper.process(mBlock);
62 | shaper.process(hBlock);
63 | }
64 |
65 | splitter.combine(oversampled_block);
66 | } else {
67 | if (isShaperON.load()) {
68 | shaper.process(oversampled_block);
69 | }
70 | }
71 | overSamplers[oversampleID]->processSamplesDown(block);
72 | }
73 | outGain.process(block);
74 | outMeter.process(block);
75 | }
76 |
77 | template
78 | void Controller::setOverSampleID(const size_t idx) {
79 | juce::ScopedLock lock(oversampleLock);
80 | oversampleID = idx;
81 | juce::dsp::ProcessSpec overSampleSpec{
82 | mainSpec.sampleRate * static_cast(overSampleRate[idx]),
83 | mainSpec.maximumBlockSize * static_cast(overSampleRate[idx]),
84 | mainSpec.numChannels
85 | };
86 | shaper.prepare(overSampleSpec);
87 | splitter.prepare(overSampleSpec);
88 | if (overSamplers[oversampleID] != nullptr) {
89 | latency.store(static_cast(overSamplers[oversampleID]->getLatencyInSamples()));
90 | }
91 | }
92 |
93 | template
94 | class Controller;
95 |
96 | template
97 | class Controller;
98 | } // zlDSP
99 |
--------------------------------------------------------------------------------
/source/dsp/controller.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZLWarm_CONTROLLER_HPP
14 | #define ZLWarm_CONTROLLER_HPP
15 |
16 | #include "waveshaper/waveshaper.hpp"
17 | #include "meter/meter.hpp"
18 | #include "splitter/splitter.hpp"
19 | #include "gain/gain.hpp"
20 |
21 | namespace zlDSP {
22 | template
23 | class Controller {
24 | public:
25 | Controller() = default;
26 |
27 | void prepare(const juce::dsp::ProcessSpec &spec);
28 |
29 | void reset();
30 |
31 | void process(juce::AudioBuffer &buffer);
32 |
33 | zlMeter::SingleMeter &getInMeter() { return inMeter; }
34 |
35 | zlMeter::SingleMeter &getOutMeter() { return outMeter; }
36 |
37 | zlSplitter::IIRSplitter &getSplitter() { return splitter; }
38 |
39 | zlWaveShaper::WarmInflator &getShaper() { return shaper; }
40 |
41 | inline void setInGain(const FloatType x) {
42 | inGain.setGainDecibels(x);
43 | }
44 |
45 | inline void setOutGain(const FloatType x) {
46 | outGain.setGainDecibels(x);
47 | }
48 |
49 | void setOverSampleID(size_t idx);
50 |
51 | inline void enableSplitter(const bool x) { isSplitterON.store(x); }
52 |
53 | inline void enableShaper(const bool x) { isShaperON.store(x); }
54 |
55 | inline int getLatency() const { return latency.load(); }
56 |
57 | private:
58 | zlMeter::SingleMeter inMeter, outMeter;
59 | zlSplitter::IIRSplitter splitter;
60 | std::atomic isSplitterON;
61 | zlWaveShaper::WarmInflator shaper;
62 | std::atomic isShaperON;
63 |
64 | zlGain::Gain inGain{}, outGain{};
65 |
66 | std::array >, 5> overSamplers{};
67 | std::array overSampleRate = {1, 2, 4, 8, 16};
68 | size_t oversampleID{0};
69 | std::atomic latency{0};
70 | juce::CriticalSection oversampleLock;
71 | juce::dsp::ProcessSpec mainSpec{44100, 512, 2};
72 | };
73 | } // zlDSP
74 |
75 | #endif //ZLWarm_CONTROLLER_HPP
76 |
--------------------------------------------------------------------------------
/source/dsp/controller_attach.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #include "controller_attach.hpp"
14 |
15 | namespace zlDSP {
16 | template
17 | ControllerAttach::ControllerAttach(juce::AudioProcessor &processor,
18 | juce::AudioProcessorValueTreeState ¶meters,
19 | Controller &controller)
20 | : processorRef(processor),
21 | parametersRef(parameters),
22 | controllerRef(controller) {
23 | for (size_t i = 0; i < defaultVs.size(); ++i) {
24 | handleParameterChange(IDs[i], defaultVs[i]);
25 | }
26 | for (auto &ID: IDs) {
27 | parametersRef.addParameterListener(ID, this);
28 | }
29 | }
30 |
31 | template
32 | ControllerAttach::~ControllerAttach() {
33 | for (auto &ID: IDs) {
34 | parametersRef.removeParameterListener(ID, this);
35 | }
36 | }
37 |
38 |
39 | template
40 | void ControllerAttach::parameterChanged(const juce::String ¶meterID, float newValue) {
41 | handleParameterChange(parameterID, newValue);
42 | }
43 |
44 | template
45 | void ControllerAttach::handleParameterChange(const juce::String ¶meterID, float newValue) {
46 | auto value = static_cast(newValue);
47 | if (parameterID == inputGain::ID) {
48 | controllerRef.setInGain(value);
49 | } else if (parameterID == outputGain::ID) {
50 | controllerRef.setOutGain(value);
51 | } else if (parameterID == wet::ID) {
52 | controllerRef.getShaper().setWet(wet::formatV(value));
53 | } else if (parameterID == warm::ID) {
54 | controllerRef.getShaper().setWarm(warm::formatV(value));
55 | } else if (parameterID == curve::ID) {
56 | controllerRef.getShaper().setCurve(curve::formatV(value));
57 | } else if (parameterID == lowSplit::ID) {
58 | controllerRef.getSplitter().setLowFreq(value);
59 | } else if (parameterID == highSplit::ID) {
60 | controllerRef.getSplitter().setHighFreq(value);
61 | } else if (parameterID == effectOff::ID) {
62 | controllerRef.enableShaper(!static_cast(value));
63 | } else if (parameterID == bandSplit::ID) {
64 | controllerRef.enableSplitter(static_cast(value));
65 | } else if (parameterID == overSample::ID) {
66 | controllerRef.setOverSampleID(static_cast(value));
67 | triggerAsyncUpdate();
68 | }
69 | }
70 |
71 | template
72 | void ControllerAttach::handleAsyncUpdate() {
73 | processorRef.setLatencySamples(controllerRef.getLatency());
74 | }
75 |
76 | template
77 | class ControllerAttach;
78 |
79 | template
80 | class ControllerAttach;
81 | } // zlDSP
82 |
--------------------------------------------------------------------------------
/source/dsp/controller_attach.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZLWarm_CONTROLLER_ATTACH_HPP
14 | #define ZLWarm_CONTROLLER_ATTACH_HPP
15 |
16 | #include "controller.hpp"
17 | #include "dsp_definitions.hpp"
18 |
19 | namespace zlDSP {
20 | template
21 | class ControllerAttach : private juce::AudioProcessorValueTreeState::Listener,
22 | private juce::AsyncUpdater {
23 | public:
24 | explicit ControllerAttach(juce::AudioProcessor &processor,
25 | juce::AudioProcessorValueTreeState ¶meters,
26 | Controller &controller);
27 |
28 | ~ControllerAttach() override;
29 |
30 | private:
31 | juce::AudioProcessor &processorRef;
32 | juce::AudioProcessorValueTreeState ¶metersRef;
33 | Controller &controllerRef;
34 |
35 | constexpr static std::array IDs{
36 | inputGain::ID, outputGain::ID, wet::ID,
37 | warm::ID, curve::ID,
38 | lowSplit::ID, highSplit::ID,
39 | effectOff::ID, bandSplit::ID, overSample::ID
40 | };
41 |
42 | inline static std::array defaultVs {
43 | static_cast(inputGain::defaultV), static_cast(outputGain::defaultV),
44 | static_cast(wet::defaultV),
45 | static_cast(warm::defaultV), static_cast(curve::defaultV),
46 | static_cast(lowSplit::defaultV), static_cast(highSplit::defaultV),
47 | static_cast(effectOff::defaultV), static_cast(bandSplit::defaultV),
48 | static_cast(overSample::defaultI)
49 | };
50 |
51 | void parameterChanged(const juce::String ¶meterID, float newValue) override;
52 |
53 | void handleParameterChange(const juce::String ¶meterID, float newValue);
54 |
55 | void handleAsyncUpdate() override;
56 | };
57 | } // zlDSP
58 |
59 | #endif //ZLWarm_CONTROLLER_ATTACH_HPP
60 |
--------------------------------------------------------------------------------
/source/dsp/dsp.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZLWarm_DSP_HPP
14 | #define ZLWarm_DSP_HPP
15 |
16 | #include "controller.hpp"
17 | #include "controller_attach.hpp"
18 | #include "meter/meter.hpp"
19 | #include "waveshaper/waveshaper.hpp"
20 | #include "splitter/splitter.hpp"
21 | #include "gain/gain.hpp"
22 | #include "oversample/over_sampler.hpp"
23 | #include "dsp_definitions.hpp"
24 |
25 | #endif //ZLWarm_DSP_HPP
26 |
--------------------------------------------------------------------------------
/source/dsp/gain/auto_gain.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #include "auto_gain.hpp"
11 |
12 | namespace zlGain {
13 | template
14 | void AutoGain::prepare(const juce::dsp::ProcessSpec &spec) {
15 | gainDSP.prepare(spec);
16 | gainDSP.setRampDurationSeconds(1.0);
17 | }
18 | template
19 | void AutoGain::processPre(juce::AudioBuffer &buffer) {
20 | auto block = juce::dsp::AudioBlock(buffer);
21 | processPre(block);
22 | }
23 |
24 | template
25 | void AutoGain::processPre(juce::dsp::AudioBlock block) {
26 | if (isON.load()) {
27 | if (toReset.load()) {
28 | gainDSP.setGainLinear(1);
29 | gainDSP.reset();
30 | toReset.store(false);
31 | }
32 | preRMS = juce::Decibels::gainToDecibels(calculateRMS(block), FloatType(-240));
33 | isPreProcessed.store(true);
34 | }
35 | }
36 |
37 | template
38 | void AutoGain::processPost(juce::AudioBuffer &buffer) {
39 | auto block = juce::dsp::AudioBlock(buffer);
40 | processPost(block);
41 | }
42 |
43 | template
44 | void AutoGain::processPost(juce::dsp::AudioBlock block) {
45 | if (isON.load() && isPreProcessed.load()) {
46 | postRMS = juce::Decibels::gainToDecibels(calculateRMS(block), FloatType(-240));
47 | gainDSP.setGainDecibels(preRMS - postRMS);
48 | juce::dsp::ProcessContextReplacing context(block);
49 | gainDSP.process(context);
50 | }
51 | isPreProcessed.store(false);
52 | }
53 |
54 | template
55 | FloatType AutoGain::calculateRMS(juce::dsp::AudioBlock block) {
56 | FloatType _ms = 0;
57 | for (size_t channel = 0; channel < block.getNumChannels(); channel++) {
58 | auto data = block.getChannelPointer(channel);
59 | for (size_t i = 0; i < block.getNumSamples(); i++) {
60 | _ms += data[i] * data[i];
61 | }
62 | }
63 | return std::sqrt(_ms / static_cast(block.getNumChannels()));
64 | }
65 |
66 | template
67 | void AutoGain::setRampDurationSeconds(double newDurationSeconds) {
68 | gainDSP.setRampDurationSeconds(newDurationSeconds);
69 | }
70 |
71 | template
72 | void AutoGain::enable(const bool f) {
73 | if (f) {
74 | toReset.store(true);
75 | isON.store(true);
76 | } else {
77 | isON.store(false);
78 | }
79 | }
80 |
81 | template
82 | class AutoGain;
83 |
84 | template
85 | class AutoGain;
86 | } // zlGain
--------------------------------------------------------------------------------
/source/dsp/gain/auto_gain.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #ifndef ZLEqualizer_AUTO_GAIN_HPP
11 | #define ZLEqualizer_AUTO_GAIN_HPP
12 |
13 | #include
14 |
15 | namespace zlGain {
16 | /**
17 | * a lock free, thread safe auto-gain class
18 | * @tparam FloatType
19 | */
20 | template
21 | class AutoGain {
22 | public:
23 | AutoGain() = default;
24 |
25 | void prepare(const juce::dsp::ProcessSpec &spec);
26 |
27 | void processPre(juce::AudioBuffer &buffer);
28 |
29 | void processPre(juce::dsp::AudioBlock block);
30 |
31 | void processPost(juce::AudioBuffer &buffer);
32 |
33 | void processPost(juce::dsp::AudioBlock block);
34 |
35 | void setRampDurationSeconds(double newDurationSeconds);
36 |
37 | void enable(bool f);
38 |
39 | private:
40 | std::atomic isON{false}, toReset{false}, isPreProcessed{false};
41 | FloatType preRMS, postRMS;
42 | juce::dsp::Gain gainDSP;
43 |
44 | FloatType calculateRMS(juce::dsp::AudioBlock block);
45 | };
46 | } // zlGain
47 |
48 | #endif //ZLEqualizer_AUTO_GAIN_HPP
49 |
--------------------------------------------------------------------------------
/source/dsp/gain/gain.hpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Zishu Liu on 3/12/24.
3 | //
4 |
5 | #ifndef ZLEqualizer_GAIN_HPP
6 | #define ZLEqualizer_GAIN_HPP
7 |
8 | #include "simple_gain.hpp"
9 | #include "auto_gain.hpp"
10 |
11 | #endif //ZLEqualizer_GAIN_HPP
12 |
--------------------------------------------------------------------------------
/source/dsp/gain/simple_gain.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #include "simple_gain.hpp"
11 |
12 | namespace zlGain {
13 | template
14 | void Gain::prepare(const juce::dsp::ProcessSpec &spec) {
15 | gainDSP.prepare(spec);
16 | }
17 |
18 | template
19 | void Gain::process(juce::AudioBuffer &buffer) {
20 | auto block = juce::dsp::AudioBlock(buffer);
21 | process(block);
22 | }
23 |
24 | template
25 | void Gain::process(juce::dsp::AudioBlock block) {
26 | if (std::abs(gain.load() - 1) <= FloatType(1e-6)) { return; }
27 | gainDSP.setGainLinear(gain.load());
28 | juce::dsp::ProcessContextReplacing context(block);
29 | gainDSP.process(context);
30 | }
31 |
32 | template
33 | class Gain;
34 |
35 | template
36 | class Gain;
37 | } // zlGain
38 |
--------------------------------------------------------------------------------
/source/dsp/gain/simple_gain.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #ifndef ZLEqualizer_SIMPLE_GAIN_HPP
11 | #define ZLEqualizer_SIMPLE_GAIN_HPP
12 |
13 | #include
14 |
15 | namespace zlGain {
16 | /**
17 | * a lock free, thread safe gain class
18 | * it will not process the signal if the gain is equal to 1
19 | * @tparam FloatType
20 | */
21 | template
22 | class Gain {
23 | public:
24 | Gain() = default;
25 |
26 | void prepare(const juce::dsp::ProcessSpec &spec);
27 |
28 | void process(juce::AudioBuffer &buffer);
29 |
30 | void process(juce::dsp::AudioBlock block);
31 |
32 | void setGainLinear(const FloatType x) { gain.store(x); }
33 |
34 | void setGainDecibels(const FloatType x) {
35 | gain.store(juce::Decibels::decibelsToGain(x, FloatType(-240)));
36 | }
37 |
38 | private:
39 | std::atomic gain{FloatType(1)};
40 | juce::dsp::Gain gainDSP;
41 | };
42 | } // zlGain
43 |
44 | #endif //ZLEqualizer_SIMPLE_GAIN_HPP
--------------------------------------------------------------------------------
/source/dsp/meter/meter.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZLWarm_METER_HPP
14 | #define ZLWarm_METER_HPP
15 |
16 | #include "single_meter.hpp"
17 |
18 | #endif //ZLWarm_METER_HPP
19 |
--------------------------------------------------------------------------------
/source/dsp/meter/single_meter.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #include "single_meter.hpp"
14 |
15 | namespace zlMeter {
16 | template
17 | void SingleMeter::reset() {
18 | for (size_t idx = 0; idx < maxPeak.size(); ++idx) {
19 | maxPeak[idx].store(-160.f);
20 | bufferPeak[idx].store(-160.f);
21 | }
22 | }
23 |
24 | template
25 | void SingleMeter::prepare(const juce::dsp::ProcessSpec &spec) {
26 | sampleRate.store(static_cast(spec.sampleRate));
27 | juce::ScopedLock lock(resizeLock);
28 | maxPeak.resize(static_cast(spec.numChannels));
29 | bufferPeak.resize(static_cast(spec.numChannels));
30 | tempPeak.resize(static_cast(spec.numChannels));
31 | currentDecay.resize(static_cast(spec.numChannels));
32 | reset();
33 | }
34 |
35 | template
36 | void SingleMeter::process(juce::dsp::AudioBlock block) {
37 | auto outputBlock = block;
38 | if (!isON.load()) return;
39 | const auto decay = decayRate.load() * static_cast(outputBlock.getNumSamples()) / sampleRate.load();
40 |
41 | std::fill(tempPeak.begin(), tempPeak.end(), FloatType(0));
42 | for (size_t channel = 0; channel < maxPeak.size(); ++channel) {
43 | for (size_t idx = 0; idx < outputBlock.getNumSamples(); ++idx) {
44 | tempPeak[channel] = std::max(tempPeak[channel],
45 | std::abs(outputBlock.getSample(
46 | static_cast(channel), static_cast(idx))));
47 | }
48 | }
49 |
50 | for (size_t channel = 0; channel < maxPeak.size(); ++channel) {
51 | tempPeak[channel] = juce::Decibels::gainToDecibels(tempPeak[channel]);
52 | const auto currentPeak = bufferPeak[channel].load() - currentDecay[channel];
53 | if (currentPeak <= tempPeak[channel]) {
54 | bufferPeak[channel].store(tempPeak[channel]);
55 | currentDecay[channel] = 0;
56 | } else {
57 | bufferPeak[channel].store(currentPeak);
58 | currentDecay[channel] += decay;
59 | }
60 | maxPeak[channel].store(std::max(maxPeak[channel].load(), tempPeak[channel]));
61 | }
62 | }
63 |
64 | template
65 | class SingleMeter;
66 |
67 | template
68 | class SingleMeter;
69 | } // zlMeter
70 |
--------------------------------------------------------------------------------
/source/dsp/meter/single_meter.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2023 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZL_SINGLE_METER_HPP
14 | #define ZL_SINGLE_METER_HPP
15 |
16 | // #include "juce_audio_processors/juce_audio_processors.h"
17 | #include "juce_dsp/juce_dsp.h"
18 |
19 | namespace zlMeter {
20 | template
21 | class SingleMeter {
22 | public:
23 | SingleMeter() = default;
24 |
25 | void reset();
26 |
27 | void prepare(const juce::dsp::ProcessSpec &spec);
28 |
29 | void process(juce::dsp::AudioBlock block);
30 |
31 | std::deque > &getmaxPeak() { return maxPeak; }
32 |
33 | std::deque > &getBufferPeak() { return bufferPeak; }
34 |
35 | void enable(const bool x) { isON.store(x); }
36 |
37 | juce::CriticalSection &getLock() { return resizeLock; }
38 |
39 | private:
40 | std::deque > maxPeak, bufferPeak;
41 | std::vector tempPeak;
42 | std::atomic decayRate{2}, sampleRate;
43 | std::vector currentDecay;
44 | std::atomic isON = false;
45 |
46 | juce::CriticalSection resizeLock;
47 | };
48 | } // zlMeter
49 |
50 | #endif //ZL_SINGLE_METER_HPP
51 |
--------------------------------------------------------------------------------
/source/dsp/oversample/over_sampler.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLWarm
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #include "over_sampler.hpp"
14 |
15 | namespace zlOverSample {
16 | } // zlOverSample
--------------------------------------------------------------------------------
/source/dsp/oversample/over_sampler.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLWarm
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZLWarm_OVER_SAMPLER_HPP
14 | #define ZLWarm_OVER_SAMPLER_HPP
15 |
16 | namespace zlOverSample {
17 |
18 | class OverSampler {
19 |
20 | };
21 |
22 | } // zlOverSample
23 |
24 | #endif //ZLWarm_OVER_SAMPLER_HPP
25 |
--------------------------------------------------------------------------------
/source/dsp/splitter/iir_splitter.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #include "iir_splitter.hpp"
14 |
15 | namespace zlSplitter {
16 | template
17 | void IIRSplitter::reset() {
18 | for (auto &f: {&low1, &low2, &high1, &high2, &all1, &all2}) {
19 | f->reset();
20 | }
21 | }
22 |
23 | template
24 | void IIRSplitter::prepare(const juce::dsp::ProcessSpec &spec) {
25 | lBuffer.setSize(static_cast(spec.numChannels), static_cast(spec.maximumBlockSize));
26 | mBuffer.setSize(static_cast(spec.numChannels), static_cast(spec.maximumBlockSize));
27 | hBuffer.setSize(static_cast(spec.numChannels), static_cast(spec.maximumBlockSize));
28 | for (auto &f: {&low1, &low2, &high1, &high2, &all1, &all2}) {
29 | f->prepare(spec);
30 | }
31 | low1.setType(juce::dsp::LinkwitzRileyFilterType::lowpass);
32 | low2.setType(juce::dsp::LinkwitzRileyFilterType::lowpass);
33 | high1.setType(juce::dsp::LinkwitzRileyFilterType::highpass);
34 | high2.setType(juce::dsp::LinkwitzRileyFilterType::highpass);
35 | all1.setType(juce::dsp::LinkwitzRileyFilterType::allpass);
36 | all2.setType(juce::dsp::LinkwitzRileyFilterType::allpass);
37 | }
38 |
39 | template
40 | void IIRSplitter::split(juce::dsp::AudioBlock block) {
41 | auto inputBlock = block;
42 | lBuffer.setSize(static_cast(block.getNumChannels()), static_cast(block.getNumSamples()),
43 | true, false, true);
44 | mBuffer.setSize(static_cast(block.getNumChannels()), static_cast(block.getNumSamples()),
45 | true, false, true);
46 | hBuffer.setSize(static_cast(block.getNumChannels()), static_cast(block.getNumSamples()),
47 | true, false, true);
48 | auto lBlock = juce::dsp::AudioBlock(lBuffer);
49 | auto mBlock = juce::dsp::AudioBlock(mBuffer);
50 | auto hBlock = juce::dsp::AudioBlock(hBuffer);
51 |
52 | lBlock.copyFrom(inputBlock);
53 | mBlock.copyFrom(inputBlock);
54 |
55 | auto lContext = juce::dsp::ProcessContextReplacing(lBlock);
56 | auto mContext = juce::dsp::ProcessContextReplacing(mBlock);
57 | auto hContext = juce::dsp::ProcessContextReplacing(hBlock);
58 |
59 | juce::ScopedLock lock(paraLock);
60 | low1.process(lContext);
61 | all2.process(lContext);
62 |
63 | high1.process(mContext);
64 | hBlock.copyFrom(mBlock);
65 |
66 | low2.process(mContext);
67 | high2.process(hContext);
68 | }
69 |
70 | template
71 | void IIRSplitter::combine(juce::dsp::AudioBlock block) {
72 | auto outputBlock = block;
73 |
74 | auto lBlock = juce::dsp::AudioBlock(lBuffer);
75 | auto mBlock = juce::dsp::AudioBlock(mBuffer);
76 | auto hBlock = juce::dsp::AudioBlock(hBuffer);
77 |
78 | outputBlock.copyFrom(lBlock);
79 | outputBlock.add(mBlock);
80 | outputBlock.add(hBlock);
81 | }
82 |
83 | template
84 | void IIRSplitter::setLowFreq(FloatType freq) {
85 | juce::ScopedLock lock(paraLock);
86 | for (auto &f: {&low1, &high1, &all1}) {
87 | f->setCutoffFrequency(freq);
88 | }
89 | }
90 |
91 | template
92 | void IIRSplitter::setHighFreq(FloatType freq) {
93 | juce::ScopedLock lock(paraLock);
94 | for (auto &f: {&low2, &high2, &all2}) {
95 | f->setCutoffFrequency(freq);
96 | }
97 | }
98 |
99 | template
100 | class IIRSplitter;
101 |
102 | template
103 | class IIRSplitter;
104 | } // zlSplitter
105 |
--------------------------------------------------------------------------------
/source/dsp/splitter/iir_splitter.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | ==============================================================================
3 | Copyright (C) 2024 - zsliu98
4 | This file is part of ZLInflator
5 |
6 | ZLInflator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7 | ZLInflator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8 |
9 | You should have received a copy of the GNU General Public License along with ZLInflator. If not, see .
10 | ==============================================================================
11 | */
12 |
13 | #ifndef ZLWarm_IIR_SPLITTER_HPP
14 | #define ZLWarm_IIR_SPLITTER_HPP
15 |
16 | #include
17 | #include
18 |
19 | namespace zlSplitter {
20 | /**
21 | * a three-band Linkwitz-Riley filter
22 | * @tparam FloatType
23 | */
24 | template
25 | class IIRSplitter {
26 | public:
27 | IIRSplitter() = default;
28 |
29 | void reset();
30 |
31 | void prepare(const juce::dsp::ProcessSpec &spec);
32 |
33 | /**
34 | * split the audio buffer into internal low, mid and high buffers
35 | * @param block
36 | */
37 | void split(juce::dsp::AudioBlock block);
38 |
39 | /**
40 | * combine the internal low, mid and high buffers into the audio buffer
41 | * @param block
42 | */
43 | void combine(juce::dsp::AudioBlock block);
44 |
45 | void setLowFreq(FloatType freq);
46 |
47 | void setHighFreq(FloatType freq);
48 |
49 | inline juce::AudioBuffer &getLBuffer() { return lBuffer; }
50 |
51 | inline juce::AudioBuffer &getMBuffer() { return mBuffer; }
52 |
53 | inline juce::AudioBuffer &getHBuffer() { return hBuffer; }
54 |
55 | private:
56 | juce::AudioBuffer lBuffer, mBuffer, hBuffer;
57 | juce::dsp::LinkwitzRileyFilter low1, high1, all1;
58 | juce::dsp::LinkwitzRileyFilter low2, high2, all2;
59 |
60 | juce::CriticalSection paraLock;
61 | };
62 | } // zlSplitter
63 |
64 | #endif //ZLWarm_IIR_SPLITTER_HPP
65 |
--------------------------------------------------------------------------------
/source/dsp/splitter/lr_splitter.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #include "lr_splitter.hpp"
11 |
12 | namespace zlSplitter {
13 | template
14 | void LRSplitter::reset() {
15 | lBuffer.clear();
16 | rBuffer.clear();
17 | }
18 |
19 | template
20 | void LRSplitter::prepare(const juce::dsp::ProcessSpec &spec) {
21 | lBuffer.setSize(1, static_cast(spec.maximumBlockSize));
22 | rBuffer.setSize(1, static_cast(spec.maximumBlockSize));
23 | }
24 |
25 | template
26 | void LRSplitter::split(juce::AudioBuffer &buffer) {
27 | lBuffer.copyFrom(0, 0, buffer, 0, 0, buffer.getNumSamples());
28 | rBuffer.copyFrom(0, 0, buffer, 1, 0, buffer.getNumSamples());
29 | lBuffer.setSize(1, buffer.getNumSamples(), true, false, true);
30 | rBuffer.setSize(1, buffer.getNumSamples(), true, false, true);
31 | }
32 |
33 | template
34 | void LRSplitter::combine(juce::AudioBuffer &buffer) {
35 | buffer.copyFrom(0, 0, lBuffer, 0, 0, buffer.getNumSamples());
36 | buffer.copyFrom(1, 0, rBuffer, 0, 0, buffer.getNumSamples());
37 | }
38 |
39 | template
40 | class LRSplitter;
41 |
42 | template
43 | class LRSplitter;
44 | }
--------------------------------------------------------------------------------
/source/dsp/splitter/lr_splitter.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #ifndef ZLEQUALIZER_LRSPLITER_H
11 | #define ZLEQUALIZER_LRSPLITER_H
12 |
13 | #include
14 | #include
15 |
16 | namespace zlSplitter {
17 | /**
18 | * a splitter that splits the stereo audio signal input left signal and right signal
19 | * @tparam FloatType
20 | */
21 | template
22 | class LRSplitter {
23 | public:
24 | LRSplitter() = default;
25 |
26 | void reset();
27 |
28 | void prepare(const juce::dsp::ProcessSpec &spec);
29 |
30 | /**
31 | * split the audio buffer into internal left buffer and right buffer
32 | * @param buffer
33 | */
34 | void split(juce::AudioBuffer &buffer);
35 |
36 | /**
37 | * combine the internal left buffer and right buffer into the audio buffer
38 | * @param buffer
39 | */
40 | void combine(juce::AudioBuffer &buffer);
41 |
42 | inline juce::AudioBuffer &getLBuffer() { return lBuffer; }
43 |
44 | inline juce::AudioBuffer &getRBuffer() { return rBuffer; }
45 |
46 | private:
47 | juce::AudioBuffer lBuffer, rBuffer;
48 | };
49 | }
50 |
51 | #endif //ZLEQUALIZER_LRSPLITER_H
52 |
--------------------------------------------------------------------------------
/source/dsp/splitter/ms_splitter.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #include "ms_splitter.hpp"
11 | namespace zlSplitter {
12 | template
13 | void MSSplitter::reset() {
14 | mBuffer.clear();
15 | sBuffer.clear();
16 | }
17 |
18 | template
19 | void MSSplitter::prepare(const juce::dsp::ProcessSpec &spec) {
20 | mBuffer.setSize(1, static_cast(spec.maximumBlockSize));
21 | sBuffer.setSize(1, static_cast(spec.maximumBlockSize));
22 | }
23 |
24 | template
25 | void MSSplitter::split(juce::AudioBuffer &buffer) {
26 | auto lBuffer = buffer.getReadPointer(0);
27 | auto rBuffer = buffer.getReadPointer(1);
28 | auto _mBuffer = mBuffer.getWritePointer(0);
29 | auto _sBuffer = sBuffer.getWritePointer(0);
30 | for (size_t i = 0; i < static_cast(buffer.getNumSamples()); ++i) {
31 | _mBuffer[i] = FloatType(0.5) * (lBuffer[i] + rBuffer[i]);
32 | _sBuffer[i] = FloatType(0.5) * (lBuffer[i] - rBuffer[i]);
33 | }
34 | mBuffer.setSize(1, buffer.getNumSamples(), true, false, true);
35 | sBuffer.setSize(1, buffer.getNumSamples(), true, false, true);
36 | }
37 |
38 | template
39 | void MSSplitter::combine(juce::AudioBuffer &buffer) {
40 | auto lBuffer = buffer.getWritePointer(0);
41 | auto rBuffer = buffer.getWritePointer(1);
42 | auto _mBuffer = mBuffer.getReadPointer(0);
43 | auto _sBuffer = sBuffer.getReadPointer(0);
44 | for (size_t i = 0; i < static_cast(buffer.getNumSamples()); ++i) {
45 | lBuffer[i] = _mBuffer[i] + _sBuffer[i];
46 | rBuffer[i] = _mBuffer[i] - _sBuffer[i];
47 | }
48 | }
49 |
50 | template
51 | class MSSplitter;
52 |
53 | template
54 | class MSSplitter;
55 | }
--------------------------------------------------------------------------------
/source/dsp/splitter/ms_splitter.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2023 - zsliu98
2 | // This file is part of ZLEqualizer
3 | //
4 | // ZLEqualizer is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
5 | //
6 | // ZLEqualizer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7 | //
8 | // You should have received a copy of the GNU General Public License along with ZLEqualizer. If not, see .
9 |
10 | #ifndef ZLEQUALIZER_MS_SPLITTER_HPP
11 | #define ZLEQUALIZER_MS_SPLITTER_HPP
12 |
13 | #include
14 | #include
15 |
16 | namespace zlSplitter {
17 | /**
18 | * a splitter that splits the stereo audio signal input mid signal and side signal
19 | * @tparam FloatType
20 | */
21 | template
22 | class MSSplitter {
23 | public:
24 | MSSplitter() = default;
25 |
26 | void reset();
27 |
28 | void prepare(const juce::dsp::ProcessSpec &spec);
29 |
30 | /**
31 | * split the audio buffer into internal mid buffer and side buffer
32 | * @param buffer
33 | */
34 | void split(juce::AudioBuffer &buffer);
35 |
36 | /**
37 | * combine the internal mid buffer and side buffer into the audio buffer
38 | * @param buffer
39 | */
40 | void combine(juce::AudioBuffer &buffer);
41 |
42 | inline juce::AudioBuffer &getMBuffer() { return mBuffer; }
43 |
44 | inline juce::AudioBuffer &getSBuffer() { return sBuffer; }
45 |
46 | private:
47 | juce::AudioBuffer