chenlh
2026-03-20 f761b6198e2e98f02adb84c83dbf59529e51b2ef
新增门控混响算法(基于spring reverb)
已添加31个文件
已删除15个文件
3974 ■■■■■ 文件已修改
cbb_ReverbGate/Reverb_gate.sln 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/Reverb_spring.vcxproj 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/Reverb_spring.vcxproj.filters 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/Reverb_spring.vcxproj.user 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/reverb_gate.cpp 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/reverb_gate.h 633 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/Compressor.cpp 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/Compressor.h 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/DynamicsProcessor.h 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/EffectProcessorBase.h 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/EnvelopeDetector.cpp 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/EnvelopeDetector.h 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/FirstOrderSmoother.h 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/GainUtilities.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/IIRFilter.cpp 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/IIRFilter.h 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/InterpolatedAllPassFilter.cpp 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/InterpolatedAllPassFilter.h 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/InterpolatedCombFilter.cpp 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/InterpolatedCombFilter.h 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/LFO.cpp 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/LFO.h 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/LinearInterpolationCircularBuffer.cpp 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/LinearInterpolationCircularBuffer.h 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/ModulatedAllPassFilter.cpp 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/ModulatedAllPassFilter.h 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/ModulatedCombFilter.cpp 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/ModulatedCombFilter.h 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/ModulationProcessor.h 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/Reverb.cpp 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/utils/Reverb.h 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/CopilotIndices/17.13.439.2385/CodeChunks.db 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/CopilotIndices/17.13.439.2385/SemanticSymbols.db 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/2575945a-65a1-431d-91d3-3d5f980cae5a.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/3a4648d8-dd3f-46ea-993c-503c18760d34.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/46d07015-65cb-4fe7-a056-59362f75721f.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/9e83b5d3-8044-4e57-b6e1-3cc4afe3f3db.vsidx 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/.suo 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/Browse.VC.db 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/DocumentLayout.backup.json 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/DocumentLayout.json 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/Solution.VC.db 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/26c6e6bc21719993/REVERB.ipch 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/60fac65e2eb3380b/REVERBHALLROOM.ipch 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/c6c4be2c6e03fbf/REVERB_WRAPPER.ipch 补丁 | 查看 | 原始文档 | blame | 历史
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/c9606fc76e9a2740/RANDOMBUFFER.ipch 补丁 | 查看 | 原始文档 | blame | 历史
cbb_ReverbGate/Reverb_gate.sln
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35828.75 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Reverb_spring", "Reverb_spring.vcxproj", "{42EA330B-B03E-44F6-9D4C-9C4FD300A78C}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|x64 = Debug|x64
        Debug|x86 = Debug|x86
        Release|x64 = Release|x64
        Release|x86 = Release|x86
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Debug|x64.ActiveCfg = Debug|x64
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Debug|x64.Build.0 = Debug|x64
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Debug|x86.ActiveCfg = Debug|Win32
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Debug|x86.Build.0 = Debug|Win32
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Release|x64.ActiveCfg = Release|x64
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Release|x64.Build.0 = Release|x64
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Release|x86.ActiveCfg = Release|Win32
        {42EA330B-B03E-44F6-9D4C-9C4FD300A78C}.Release|x86.Build.0 = Release|Win32
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {B8775238-3A82-456D-AB61-D88B57B90638}
    EndGlobalSection
EndGlobal
cbb_ReverbGate/Reverb_spring.vcxproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <VCProjectVersion>17.0</VCProjectVersion>
    <Keyword>Win32Proj</Keyword>
    <ProjectGuid>{42ea330b-b03e-44f6-9d4c-9c4fd300a78c}</ProjectGuid>
    <RootNamespace>Reverbspring</RootNamespace>
    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
    <ProjectName>Reverb_gate</ProjectName>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v143</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v143</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v143</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v143</PlatformToolset>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="Shared">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <SDLCheck>true</SDLCheck>
      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ConformanceMode>true</ConformanceMode>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <SDLCheck>true</SDLCheck>
      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ConformanceMode>true</ConformanceMode>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <SDLCheck>true</SDLCheck>
      <PreprocessorDefinitions>_DEBUG;_CRT_SECURE_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ConformanceMode>true</ConformanceMode>
      <AdditionalIncludeDirectories>E:\Algorithm\Effect\MoorerReverb-main\Reverb_spring\Reverb_spring\utils;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <SDLCheck>true</SDLCheck>
      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <ConformanceMode>true</ConformanceMode>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="reverb_gate.cpp" />
    <ClCompile Include="utils\Compressor.cpp" />
    <ClCompile Include="utils\EnvelopeDetector.cpp" />
    <ClCompile Include="utils\IIRFilter.cpp" />
    <ClCompile Include="utils\InterpolatedAllPassFilter.cpp" />
    <ClCompile Include="utils\InterpolatedCombFilter.cpp" />
    <ClCompile Include="utils\LFO.cpp" />
    <ClCompile Include="utils\LinearInterpolationCircularBuffer.cpp" />
    <ClCompile Include="utils\ModulatedAllPassFilter.cpp" />
    <ClCompile Include="utils\ModulatedCombFilter.cpp" />
    <ClCompile Include="utils\Reverb.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="reverb_gate.h" />
    <ClInclude Include="utils\Compressor.h" />
    <ClInclude Include="utils\DynamicsProcessor.h" />
    <ClInclude Include="utils\EffectProcessorBase.h" />
    <ClInclude Include="utils\FirstOrderSmoother.h" />
    <ClInclude Include="utils\GainUtilities.h" />
    <ClInclude Include="utils\IIRFilter.h" />
    <ClInclude Include="utils\InterpolatedAllPassFilter.h" />
    <ClInclude Include="utils\InterpolatedCombFilter.h" />
    <ClInclude Include="utils\LFO.h" />
    <ClInclude Include="utils\LinearInterpolationCircularBuffer.h" />
    <ClInclude Include="utils\ModulatedAllPassFilter.h" />
    <ClInclude Include="utils\ModulatedCombFilter.h" />
    <ClInclude Include="utils\ModulationProcessor.h" />
    <ClInclude Include="utils\Reverb.h" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>
cbb_ReverbGate/Reverb_spring.vcxproj.filters
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="源文件">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
    <Filter Include="头文件">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
    </Filter>
    <Filter Include="资源文件">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="reverb_gate.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\IIRFilter.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\InterpolatedAllPassFilter.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\InterpolatedCombFilter.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\LFO.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\LinearInterpolationCircularBuffer.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\ModulatedAllPassFilter.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\ModulatedCombFilter.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\Reverb.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\Compressor.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="utils\EnvelopeDetector.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="reverb_gate.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\EffectProcessorBase.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\FirstOrderSmoother.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\LFO.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\ModulatedAllPassFilter.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\ModulatedCombFilter.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\ModulationProcessor.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\IIRFilter.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\InterpolatedCombFilter.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\LinearInterpolationCircularBuffer.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\InterpolatedAllPassFilter.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\Reverb.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\Compressor.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\DynamicsProcessor.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="utils\GainUtilities.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
</Project>
cbb_ReverbGate/Reverb_spring.vcxproj.user
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup />
</Project>
cbb_ReverbGate/reverb_gate.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@

#include "reverb.h"
#include "compressor.h"
#include "reverb_gate.h"
int main(void)
{
    Reverb<float> rvb;
    rvb.prepare(48000);
    rvb.setRoomSize(1.0);
    rvb.setDecay(1.0);
    rvb.setCutoff(5000);
    rvb.setMix(1.0);
    Compressor<float> comp;
    comp.prepare(48000);
    comp.setThreshold(-20.0);
    comp.setRatio(5.0);
    comp.setAttack(0.001);
    comp.setRelease(0.1);
    comp.setGain(1.0);
    std::string output_file = "output.wav";
    Wave w;
    w.read_wav("E:\\music\\Voice_print\\GaoWeiDong.wav");
    w.init_channels_maxmin();
    w.update_channel_maxmin();
    float gate_gain;
    for (int i = 0; i < w.num_channels; ++i)
    {
        for (int j = 0; j < w.num_samples; ++j) {
            gate_gain = comp.processSample(w.samples[i][j]);
            w.samples[i][j] = rvb.processSample(w.samples[i][j]) * gate_gain;
        }
    }
    // normalizing to db
    LOG_INFO("normalized_volume : " << db_to_vol(-1.5f));
    LOG_INFO("normalized_volume_db: " << -1.5f);
    w.update_channel_maxmin();
    w.normalize(-db_to_vol(-1.5f), db_to_vol(-1.5f));
    w.write_wav(output_file);
    LOG_INFO("output_file : " << output_file);
    w.info_summary();
    return 0;
}
cbb_ReverbGate/reverb_gate.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,633 @@
#pragma once
#include <iostream>
#define NUM_COMBS 4
#define NUM_ALLPASS 2
#define LOG_INFO(msg) std::cout<<"[INFO] "<<msg<<std::endl;
#define LOG_WARN(msg) std::cout<<"[WARN] "<<msg<<std::endl;
#define LOG_ERROR(msg) std::cout<<"[ERROR] "<<msg<<std::endl;
float db_to_vol(float db) {
    return pow(10, db / 20);
}
class Header {
public:
    uint8_t riff_label[4]; // (00) = {'R','I','F','F'}
    uint32_t riff_size; // (04) = 36 + data_size
    uint8_t file_tag[4]; // (08) = {'W','A','V','E'}
    uint8_t fmt_label[4]; // (12) = {'f','m','t',' '}
    uint32_t fmt_size; // (16) = 16
    uint16_t audio_format; // (20) = 1
    uint16_t channel_count; // (22) = 1 or 2
    uint32_t sampling_rate; // (24) = (anything)
    uint32_t bytes_per_second; // (28) = (see above)
    uint16_t bytes_per_sample; // (32) = (see above)
    uint16_t bits_per_sample; // (34) = 8 or 16
    uint8_t data_label[4]; // (36) = {'d','a','t','a'}
    uint32_t data_size; // (40) = # bytes of data
};
class Wave {
public:
    Header header;
    std::vector<std::vector<float>> samples;
    std::vector<float> max_amplitude;
    std::vector<float> min_amplitude;
    int num_samples = 0;
    int num_channels = 0;
    void read_header(std::string file_path) {
        FILE* in = fopen(file_path.c_str(), "rb");
        if (!in) {
            LOG_ERROR("read : file does not exsit");
            exit(-1);
        }
        fread(&header, sizeof(Header), 1, in);
        fclose(in);
        if (header.channel_count > 1) {
            LOG_ERROR("read : only mono tracks supported for now");
            exit(-1);
        }
    }
    void write_header(std::string file_path) {
        if (header.channel_count > 1) {
            LOG_ERROR("write : only mono tracks supported for now");
            exit(-1);
        }
        FILE* out = fopen(file_path.c_str(), "wb");
        if (!out) {
            LOG_ERROR("write : file does not exsit");
            exit(-1);
        }
        fseek(out, 0, SEEK_SET);
        fwrite(&header, sizeof(header), 1, out);
        fclose(out);
    }
    void print_header(int i) {
        printf("\n[HEADER]\n");
        if (i) printf("riff_label:       %c%c%c%c.\n", header.riff_label[0], header.riff_label[1], header.riff_label[2], header.riff_label[3]);
        printf("riff_size:        %u.\n", header.riff_size);
        if (i) printf("file_tag:         %c%c%c%c.\n", header.file_tag[0], header.file_tag[1], header.file_tag[2], header.file_tag[3]);
        if (i) printf("fmt_label:        %c%c%c%c.\n", header.fmt_label[0], header.fmt_label[1], header.fmt_label[2], header.fmt_label[3]);
        printf("fmt_size:         %u.\n", header.fmt_size);
        printf("audio_format:     %u.\n", header.audio_format);
        printf("channel_count:    %u.\n", header.channel_count);
        printf("sampling_rate:    %u.\n", header.sampling_rate);
        printf("bytes_per_second: %u.\n", header.bytes_per_second);
        printf("bytes_per_sample: %u.\n", header.bytes_per_sample);
        printf("bits_per_sample:  %u.\n", header.bits_per_sample);
        if (i) printf("data_label:       %c%c%c%c.\n", header.data_label[0], header.data_label[1], header.data_label[2], header.data_label[3]);
        printf("data_size:        %u.\n", header.data_size);
    }
    void read_data(std::string file_path) {
        FILE* in = fopen(file_path.c_str(), "rb");
        num_samples = header.data_size / (header.channel_count * header.bits_per_sample / 8);
        num_channels = header.channel_count;
        fseek(in, sizeof(Header), SEEK_SET);
        uint8_t* data = new uint8_t[header.data_size];
        fread(data, header.data_size, 1, in);
        int16_t* data16 = (int16_t*)(data);
        // clear all channels
        for (int channel = 0;channel < (int)samples.size();++channel) {
            samples[channel].clear();
        }
        samples.clear();
        // resize buffer and reserve samples
        samples.resize(num_channels);
        for (int channel = 0;channel < (int)samples.size();++channel) {
            samples[channel].reserve(num_samples);
        }
        // convert PCM data to float samples
        for (int i = 0;i < num_samples;++i) {
            for (int c = 0;c < num_channels;++c) {
                if (header.bits_per_sample == 16) {
                    float sample = data16[i * num_channels + c] / (float)((1 << 15));
                    samples[c].push_back(sample);
                }
                else {
                    LOG_ERROR("read : only 16 bit signed pcm supported");
                    exit(-1);
                }
            }
        }
        delete[] data;
        fclose(in);
    }
    void write_data(std::string file_path) {
        FILE* out = fopen(file_path.c_str(), "ab");
        fseek(out, sizeof(Header), SEEK_SET);
        for (int i = 0;i < num_samples;++i) {
            for (int c = 0;c < num_channels;++c) {
                float sample = samples[c][i];
                if (header.bits_per_sample == 16) {
                    int16_t bytes_2 = (sample * ((1 << 15)));
                    fwrite(&bytes_2, 2, 1, out);
                }
                else {
                    LOG_ERROR("write : only 16 bit signed pcm supported");
                    exit(-1);
                }
            }
        }
        fclose(out);
    }
    void read_wav(std::string file_path) {
        read_header(file_path);
        read_data(file_path);
    }
    void write_wav(std::string file_path) {
        write_header(file_path.c_str());
        write_data(file_path.c_str());
    }
    void init_channels_maxmin() {
        // clear it
        max_amplitude.clear();
        min_amplitude.clear();
        // initialize
        for (int i = 0;i < num_channels;++i) {
            max_amplitude.push_back(std::numeric_limits<float>::min());
            min_amplitude.push_back(std::numeric_limits<float>::max());
        }
    }
    void update_channel_maxmin() {
        for (int i = 0;i < num_samples;++i) {
            for (int c = 0;c < num_channels;++c) {
                float sample = samples[c][i];
                //track max min
                if (sample > max_amplitude[c]) {
                    max_amplitude[c] = sample;
                }
                if (sample < min_amplitude[c]) {
                    min_amplitude[c] = sample;
                }
            }
        }
    }
    void normalize(float min, float max) {
        std::vector<float> sum;
        sum.resize(2, 0.0f);
        for (int i = 0; i < num_samples; i++) {
            for (int c = 0; c < num_channels; c++) {
                float x = samples[c][i];
                sum[c] += x;
            }
        }
        for (int i = 0; i < num_samples; i++) {
            for (int c = 0; c < num_channels; c++) {
                samples[c][i] += sum[c] / num_samples;
                float x = samples[c][i];
                x = ((max - min) * (x - min_amplitude[c]) / (max_amplitude[c] - min_amplitude[c])) - (max - min) / 2;
                samples[c][i] = x;
            }
        }
    }
    void info_summary() {
        LOG_INFO("sample_rate : " << header.sampling_rate);
        LOG_INFO("bit_depth : " << header.bits_per_sample);
        LOG_INFO("num_channels : " << num_channels);
        LOG_INFO("num_samples : " << num_samples);
        LOG_INFO("num_seconds : " << num_samples / header.sampling_rate);
    }
};
/*
#include "iostream"
#include "fstream"
#include "vector"
#include "limits"
#include "math.h"
#define PI 3.14159265358979323846
#define LOG_INFO(msg) std::cout<<"[INFO] "<<msg<<std::endl;
#define LOG_WARN(msg) std::cout<<"[WARN] "<<msg<<std::endl;
#define LOG_ERROR(msg) std::cout<<"[ERROR] "<<msg<<std::endl;
float min(float a, float b){
    if(a<b){
        return a;
    }
    else{
        return b;
    }
}
float max(float a, float b){
    if(a>b){
        return a;
    }
    else{
        return b;
    }
}
float lerp(float l, float r, float t, float lo=0.0f, float hi=1.0f){
    if(hi == lo){
        return l;
    }
    t = (t-lo)/(hi-lo);
    // interpolate
    return l*(1-t) + r*(t);
}
class GainFilter{
public:
    float gain=1.0f;
public:
    void init(float g=1.0f){
        gain = g;
    }
    void set_gain(float g){
        gain = g;
    }
    float process(float n){
        return n*gain;
    }
};
class DelayFilter{
public:
    std::vector<float> delay_pipe;
    float delay_samples;
    float delay_ms;
    float delay_frac;
    float max_delay_ms;
    int max_delay_samples;
    int w_index;
    int r_index;
public:
    void init(float ms, float delay_ms_max, int sample_rate=48000){
        delay_samples = 0.0f;
        delay_ms = ms;
        max_delay_samples = ceil(sample_rate * delay_ms_max / 1000.0f);
        max_delay_ms = max_delay_samples * 1000.0f / sample_rate;
        // get the delay in sammples and separate out fractional parts
        float delay_raw = sample_rate * ms / 1000.0f;
        delay_samples = floor(delay_raw);
        delay_frac = delay_raw - delay_samples;
        // initialize the delay pipe with 0.0f data and set read write indexes
        r_index = 0;
        w_index = 0;
        delay_pipe.resize(max_delay_samples,0.0f);
    }
    float process(float n){
        float out=0.0f;
        if(delay_samples == 0){
            out = n;
        }
        else{
            out = read_delay();
        }
        write_delay(n);
        return out;
    }
    void set_delay_ms(float ms,int sample_rate=48000){
        if(ms > max_delay_ms){
            LOG_ERROR("Delay Filter : exceeded max_delay_ms");
            return;
        }
        // delay
        delay_ms = ms;
        // get the delay in sammples and separate out fractional parts
        float delay_raw = sample_rate * ms / 1000.0f;
        delay_samples = floor(delay_raw);
        delay_frac = delay_raw - delay_samples;
        // read position and wrap around the buffer max size
        r_index = w_index - delay_samples;
        r_index = r_index<0?r_index+max_delay_samples:r_index;
    }
    float read_delay(){
        float out = 0.0f;
        out = delay_pipe[r_index];
        int n_minus_one_r_index = r_index - 1;
        n_minus_one_r_index = n_minus_one_r_index < 0? max_delay_samples - 1: n_minus_one_r_index;
        float out_n_minus_one = delay_pipe[n_minus_one_r_index];
        return lerp(out,out_n_minus_one,delay_frac);
    }
    void write_delay(float n){
        delay_pipe[w_index++] = n;
        w_index = w_index >= max_delay_samples ? 0 : w_index;
        ++r_index;
        r_index = r_index >= max_delay_samples ? 0 : r_index;
    }
    void reset(){
        delay_pipe.clear();
        delay_pipe.resize(max_delay_samples,0.0f);
        r_index = 0;
        w_index = 0;
        set_delay_ms(delay_ms,48000);
    }
};
class LowPassFilter{
public:
    float coeff=0.0f;
    float n_minus_one=0.0f;
public:
    void init(float lp_coeff,int sample_rate=48000){
        set_coeff(lp_coeff);
    }
    float process(float n){
        n_minus_one = n * (1 - coeff) + (coeff * n_minus_one); // this was the correct one
        return n_minus_one;
    }
    void set_coeff(float c){
        coeff = c;
    }
};
class CombFilter{
public:
    GainFilter gain_filter;
    DelayFilter delay_filter;
    LowPassFilter low_pass_filter;
public:
    void init(float ms, float delay_ms_max, float g, float lp_coeff, int sample_rate=48000){
        delay_filter.init(ms,delay_ms_max,sample_rate);
        low_pass_filter.init(lp_coeff,sample_rate);
        gain_filter.init(g);
    }
    float process(float n){
        // delay -> gain -> low pass -> feedback -> output
        float delayed_n = delay_filter.read_delay();
        float delayed_n_gain = gain_filter.process(delayed_n);
        float delayed_n_gain_low_pass = low_pass_filter.process(delayed_n_gain);
        float delayed_n_gain_low_pass_feedback = n + delayed_n_gain_low_pass;
        delay_filter.write_delay(delayed_n_gain_low_pass_feedback);
        float out = delayed_n;
        return out;
    }
};
class AllPassFilter{
public:
    float wet_dry_ratio=1.0f;
    DelayFilter delay_filter;
    GainFilter gain_filter;
public:
    void init(float ms, float delay_ms_max, float g, int sample_rate=48000){
        delay_filter.init(ms,delay_ms_max,sample_rate);
        gain_filter.init(g);
    }
    float process(float n){
        float delayed_n = delay_filter.read_delay();
        float delayed_n_gain = gain_filter.process(delayed_n);
        float delayed_n_gain_feedback = n + delayed_n_gain;
        float out = delayed_n + (-1.0f)*(gain_filter.process(delayed_n_gain_feedback));
        delay_filter.write_delay(delayed_n_gain_feedback);
        return out;
    }
};
class Header{
public:
    uint8_t riff_label[4]; // (00) = {'R','I','F','F'}
    uint32_t riff_size; // (04) = 36 + data_size
    uint8_t file_tag[4]; // (08) = {'W','A','V','E'}
    uint8_t fmt_label[4]; // (12) = {'f','m','t',' '}
    uint32_t fmt_size; // (16) = 16
    uint16_t audio_format; // (20) = 1
    uint16_t channel_count; // (22) = 1 or 2
    uint32_t sampling_rate; // (24) = (anything)
    uint32_t bytes_per_second; // (28) = (see above)
    uint16_t bytes_per_sample; // (32) = (see above)
    uint16_t bits_per_sample; // (34) = 8 or 16
    uint8_t data_label[4]; // (36) = {'d','a','t','a'}
    uint32_t data_size; // (40) = # bytes of data
};
class Wave{
public:
    Header header;
    std::vector<std::vector<float>> samples;
    std::vector<float> max_amplitude;
    std::vector<float> min_amplitude;
    int num_samples=0;
    int num_channels=0;
    void read_header(std::string file_path){
        FILE* in = fopen(file_path.c_str(),"rb");
        if(!in){
            LOG_ERROR("read : file does not exsit");
            exit(-1);
        }
        fread(&header,sizeof(Header),1,in);
        fclose(in);
        if(header.channel_count > 1){
            LOG_ERROR("read : only mono tracks supported for now");
            exit(-1);
        }
    }
    void write_header(std::string file_path){
        if(header.channel_count > 1){
            LOG_ERROR("write : only mono tracks supported for now");
            exit(-1);
        }
        FILE* out = fopen(file_path.c_str(),"wb");
        if(!out){
            LOG_ERROR("write : file does not exsit");
            exit(-1);
        }
        fseek(out,0,SEEK_SET);
        fwrite(&header,sizeof(header),1,out);
        fclose(out);
    }
    void print_header(int i){
               printf("\n[HEADER]\n");
        if(i) printf("riff_label:       %c%c%c%c.\n",header.riff_label[0],header.riff_label[1],header.riff_label[2],header.riff_label[3]);
              printf("riff_size:        %u.\n",header.riff_size);
        if(i) printf("file_tag:         %c%c%c%c.\n",header.file_tag[0],header.file_tag[1],header.file_tag[2],header.file_tag[3]);
        if(i) printf("fmt_label:        %c%c%c%c.\n",header.fmt_label[0],header.fmt_label[1],header.fmt_label[2],header.fmt_label[3]);
              printf("fmt_size:         %u.\n",header.fmt_size);
              printf("audio_format:     %u.\n",header.audio_format);
              printf("channel_count:    %u.\n",header.channel_count);
              printf("sampling_rate:    %u.\n",header.sampling_rate);
              printf("bytes_per_second: %u.\n",header.bytes_per_second);
              printf("bytes_per_sample: %u.\n",header.bytes_per_sample);
              printf("bits_per_sample:  %u.\n",header.bits_per_sample);
        if(i) printf("data_label:       %c%c%c%c.\n",header.data_label[0],header.data_label[1],header.data_label[2],header.data_label[3]);
              printf("data_size:        %u.\n",header.data_size);
    }
    void read_data(std::string file_path){
        FILE* in = fopen(file_path.c_str(),"rb");
        num_samples = header.data_size/(header.channel_count*header.bits_per_sample/8);
        num_channels = header.channel_count;
        fseek(in,sizeof(Header),SEEK_SET);
        uint8_t* data = new uint8_t[header.data_size];
        fread(data,header.data_size,1,in);
        int16_t* data16 = (int16_t*)(data);
        // clear all channels
        for(int channel=0;channel<(int)samples.size();++channel){
            samples[channel].clear();
        }
        samples.clear();
        // resize buffer and reserve samples
        samples.resize(num_channels);
        for(int channel=0;channel<(int)samples.size();++channel){
            samples[channel].reserve(num_samples);
        }
        // convert PCM data to float samples
        for(int i=0;i<num_samples;++i){
            for(int c=0;c<num_channels;++c){
                if(header.bits_per_sample == 16){
                    float sample = data16[i*num_channels + c]/(float)((1<<15));
                    samples[c].push_back(sample);
                }
                else{
                    LOG_ERROR("read : only 16 bit signed pcm supported");
                    exit(-1);
                }
            }
        }
        delete[] data;
        fclose(in);
    }
    void write_data(std::string file_path){
        FILE* out = fopen(file_path.c_str(),"ab");
        fseek(out,sizeof(Header),SEEK_SET);
        for(int i=0;i<num_samples;++i){
            for(int c=0;c<num_channels;++c){
                float sample = samples[c][i];
                if(header.bits_per_sample == 16){
                    int16_t bytes_2 = (sample * ((1<<15)));
                    fwrite(&bytes_2,2,1,out);
                }
                else{
                    LOG_ERROR("write : only 16 bit signed pcm supported");
                    exit(-1);
                }
            }
        }
        fclose(out);
    }
    void read_wav(std::string file_path){
        read_header(file_path);
        read_data(file_path);
    }
    void write_wav(std::string file_path){
        write_header(file_path.c_str());
        write_data(file_path.c_str());
    }
    void init_channels_maxmin(){
        // clear it
        max_amplitude.clear();
        min_amplitude.clear();
        // initialize
        for(int i=0;i<num_channels;++i){
            max_amplitude.push_back(std::numeric_limits<float>::min());
            min_amplitude.push_back(std::numeric_limits<float>::max());
        }
    }
    void update_channel_maxmin(){
        for(int i=0;i<num_samples;++i){
            for(int c=0;c<num_channels;++c){
                float sample = samples[c][i];
                //track max min
                if(sample > max_amplitude[c]){
                    max_amplitude[c] = sample;
                }
                if(sample < min_amplitude[c]){
                    min_amplitude[c] = sample;
                }
            }
        }
    }
    void normalize(float min, float max){
        std::vector<float> sum;
        sum.resize(2,0.0f);
        for (int i = 0; i < num_samples; i++){
            for (int c = 0; c < num_channels; c++){
                float x = samples[c][i];
                sum[c] += x;
            }
        }
        for (int i = 0; i < num_samples; i++){
            for (int c = 0; c < num_channels; c++){
                samples[c][i] += sum[c]/num_samples;
                float x = samples[c][i];
                x = ((max-min) * (x - min_amplitude[c]) / (max_amplitude[c] - min_amplitude[c])) - (max-min)/2;
                samples[c][i] = x;
            }
        }
    }
    void info_summary(){
        LOG_INFO("sample_rate : "<<header.sampling_rate);
        LOG_INFO("bit_depth : "<<header.bits_per_sample);
        LOG_INFO("num_channels : "<<num_channels);
        LOG_INFO("num_samples : "<<num_samples);
        LOG_INFO("num_seconds : "<<num_samples/header.sampling_rate);
    }
};
*/
cbb_ReverbGate/utils/Compressor.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,205 @@
#include "Compressor.h"
template <typename SampleType>
Compressor<SampleType>::Compressor()
{
}
template <typename SampleType>
Compressor<SampleType>::~Compressor()
{
}
template <typename SampleType>
void Compressor<SampleType>::prepare(SampleType sampleRate)
{
    this->detector.prepare(sampleRate);
    this->detector.setOutputIndB(true);
}
template <typename SampleType>
SampleType Compressor<SampleType>::processSample(SampleType sample)
{
    SampleType xn = sample;
    SampleType detect_input = 0.0;
    detect_input = this->detector.processSample(xn);
    //Gain Reduction Calculation
    SampleType gainReduction = calaculateGain(detect_input);
    //Make-up Gain
    //SampleType muGain = GainUtilities<SampleType>::decibelsToGain(makeupGain);
    //return xn * gainReduction * muGain;
    return gainReduction;
}
template <typename SampleType>
void Compressor<SampleType>::process(SampleType* data, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        data[sample] = processSample(data[sample]);
}
template <typename SampleType>
void Compressor<SampleType>::setThreshold(SampleType newThreshold)
{
    threshold = newThreshold;
    //Bounds Check
    if (threshold > 0.0)
        threshold = 0.0;
    if (threshold < -80.0)
        threshold = -80.0;
}
template <typename SampleType>
void Compressor<SampleType>::setRatio(SampleType newRatio)
{
    ratio = newRatio;
    //Bounds Check
    if (ratio > 100.0)
        ratio = 100.0;
    if (ratio < 1.0)
        ratio = 1.0;
}
template <typename SampleType>
void Compressor<SampleType>::setAttack(SampleType newAttack)
{
    attack = newAttack;
    //Bounds Check
    if (attack > 100.0)
        attack = 100.0;
    if (attack < 1.0)
        attack = 1.0;
    this->detector.setAttackTime(attack);
}
template <typename SampleType>
void Compressor<SampleType>::setRelease(SampleType newRelease)
{
    release = newRelease;
    //Bounds Check
    if (release > 1000.0)
        release = 1000.0;
    if (release < 10.0)
        release = 10.0;
    this->detector.setReleaseTime(release);
}
template <typename SampleType>
void Compressor<SampleType>::setGain(SampleType newGain)
{
    makeupGain = newGain;
}
template <typename SampleType>
void Compressor<SampleType>::setParameter(int index, SampleType newValue)
{
    switch (index)
    {
    case Parameters::Threshold:
        setThreshold(newValue);
        break;
    case Parameters::Ratio:
        setRatio(newValue);
        break;
    case Parameters::Attack:
        setAttack(newValue);
        break;
    case Parameters::Release:
        setRelease(newValue);
        break;
    case Parameters::MakeupGain:
        setGain(newValue);
        break;
    }
}
template <typename SampleType>
SampleType Compressor<SampleType>::getParameter(int index)
{
    switch (index)
    {
    case Parameters::Threshold:
        return threshold;
        break;
    case Parameters::Ratio:
        return ratio;
        break;
    case Parameters::Attack:
        return attack;
        break;
    case Parameters::Release:
        return release;
        break;
    case Parameters::MakeupGain:
        return makeupGain;
        break;
    }
}
template <typename SampleType>
void Compressor<SampleType>::setKneeType(int index)
{
    switch (index)
    {
    case KneeTypes::Soft:
        kneeType = KneeTypes::Soft;
        break;
    case KneeTypes::Hard:
        kneeType = KneeTypes::Hard;
        break;
    }
}
template <typename SampleType>
int Compressor<SampleType>::getKneeType()
{
    return kneeType;
}
template <typename SampleType>
SampleType Compressor<SampleType>::calaculateGain(SampleType input)
{
    SampleType output = 0.0;
    switch (kneeType)
    {
    case KneeTypes::Soft:
        if (2.0 * (input - threshold) < -(kneeWidth))
            output = input;
        else if (2.0 * (std::fabs(input - threshold)) <= kneeWidth)
            output = input + (((1.0 / ratio) - 1.0) * std::pow((input - threshold + (kneeWidth/ 2.0)), 2.0)) / (2.0 * kneeWidth);
        else if (2.0 * (input - threshold) > kneeWidth)
            output = threshold + (input - threshold) / ratio;
        break;
    case KneeTypes::Hard:
        if (input <= threshold)
            output = input;
        else
            output = threshold + (input - threshold) / ratio;
        break;
    }
    SampleType gainReduction_dB = output - input;
    SampleType gainReduction_Linear = std::pow(10.0, (gainReduction_dB) / 20.0);
    return gainReduction_Linear;
}
template class Compressor<float>;
template class Compressor<double>;
cbb_ReverbGate/utils/Compressor.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,143 @@
#pragma once
#include <DynamicsProcessor.h>
#include <GainUtilities.h>
/**
 * Basic Compressor Effect
 */
template <typename SampleType>
class Compressor : public DynamicsProcessor<SampleType>
{
public:
    /**
     * @brief Constructor
     */
    Compressor();
    /**
     * @brief Destructor
     */
    ~Compressor();
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate) override;
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input) override;
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param data Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* data, int startSample, int endSample) override;
    /**
     * @brief Sets the compressor threshold
     *
     * @param newThreshold New threshold value in decibels
     */
    void setThreshold(SampleType newThreshold) override;
    /**
     * @brief Sets the compression ratio
     *
     * @param newRatio New ratio value
     */
    void setRatio(SampleType newRatio);
    /**
     * @brief Sets the compressor attack time
     *
     * @param newAttack New attack time value in milliseconds
     */
    void setAttack(SampleType newAttack) override;
    /**
     * @brief Sets the compressor release time
     *
     * @param newRelease New release time value in milliseconds
     */
    void setRelease(SampleType newRelease) override;
    /**
     * @brief Sets the compressor make-up gain
     *
     * @param newGain New gain value in decibels
     */
    void setGain(SampleType newGain) override;
    /**
     * @brief Sets one of the compressor's parameters
     *
     * @param index Parameter index
     * @param newValue New parameter value
     */
    void setParameter(int index, SampleType newValue);
    /**
     * @brief Returns one of the compressor's parameters
     *
     * @param index Parameter index
     */
    SampleType getParameter(int index);
    /**
     * @brief Sets the compressor knee type
     *
     * @param index Knee type index
     */
    void setKneeType(int index);
    /**
     * @brief Returns the compressor knee type index
     */
    int getKneeType();
    enum Parameters
    {
        Threshold = 0,    //-80 | 0 dB
        Ratio,            //
        Attack,            //1ms | 100ms
        Release,        //10ms | 1000ms
        MakeupGain
    };
    enum KneeTypes
    {
        Soft = 0,
        Hard
    };
private:
    SampleType sampleRate;
    // User Parameters
    SampleType threshold{ -10.0 }; //in dB
    SampleType ratio{ 50.0 };
    SampleType makeupGain{ 0.0 }; //in dB
    SampleType attack{ 10.0 }; //in ms
    SampleType release{ 100.0 }; //in ms
    int kneeType{ KneeTypes::Soft };
    //=============================================
    SampleType kneeWidth{ 30.0 }; //in dB
    //============================================
    SampleType calaculateGain(SampleType input);
};
cbb_ReverbGate/utils/DynamicsProcessor.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
#pragma once
#include <EffectProcessorBase.h>
#include <EnvelopeDetector.h>
/**
 * Base Class for Dynamics Effects Processors
 */
template <typename SampleType>
class DynamicsProcessor : public EffectProcessorBase<SampleType>
{
public:
    /**
     * @brief Sets the detection threshold
     *
     * @param newThreshold New threshold value in decibels
     */
    virtual void setThreshold(SampleType newThreshold) = 0;
    /**
     * @brief Sets the detector attack time
     *
     * @param newRatio New ratio value
     */
    virtual void setAttack(SampleType newAttack) = 0;
    /**
     * @brief Sets the detector release time
     *
     * @param newRelease New release time value in milliseconds
     */
    virtual void setRelease(SampleType newRelease) = 0;
    /**
     * @brief Sets the processor make-up gain
     *
     * @param newGain New gain value in decibels
     */
    virtual void setGain(SampleType newGain) = 0;
protected:
    EnvelopeDetector<SampleType> detector;
};
cbb_ReverbGate/utils/EffectProcessorBase.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
#pragma once
/**
 * Base Class for Audio Effect Processors
 *
 */
template <typename SampleType>
class EffectProcessorBase
{
public:
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    virtual void prepare(SampleType sampleRate) = 0;
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    virtual SampleType processSample(SampleType input) = 0;
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param data Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    virtual void process(SampleType* channelData, int startSample, int endSample) = 0;
protected:
    SampleType sampleRate;
};
cbb_ReverbGate/utils/EnvelopeDetector.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
#include "EnvelopeDetector.h"
template <typename SampleType>
EnvelopeDetector<SampleType>::EnvelopeDetector()
{
}
template <typename SampleType>
void EnvelopeDetector<SampleType>::prepare(SampleType sampleRate)
{
    setSampleRate(sampleRate);
    previousValue = 0.0;
}
template <typename SampleType>
SampleType EnvelopeDetector<SampleType>::processSample(SampleType input)
{
    SampleType xn = std::fabs(input);
    SampleType currentValue = 0.0; //Envelope value for the current sample
    if(detectionMode == DetectionModes::MS || detectionMode == DetectionModes::RMS)
        xn = xn*xn;
    if(xn > previousValue)
        currentValue = attackTimeCoeff * (previousValue - xn) + xn;
    else
        currentValue = releaseTimeCoeff * (previousValue  - xn) + xn;
    if (currentValue > 0.0 && currentValue < 1.175494351e-38)
    {
        currentValue = 0;
    }
    else if (currentValue < 0.0 && currentValue > -1.175494351e-38)
    {
        currentValue = 0;
    }
    currentValue = std::fmax(currentValue, 0.0);
    previousValue = currentValue;
    //Check if RMS Mode is selected
    if(getDetectionMode() == DetectionModes::RMS)
        currentValue = std::pow(currentValue, 0.5);
    //Check if output is linear
    if(!output_In_dB)
        return currentValue;
    if (currentValue <= 0)
        return -96.0;
    //If output is in dB...
    return 20*(std::log10(currentValue));
}
template <typename SampleType>
void EnvelopeDetector<SampleType>::setAttackTime(SampleType newValue)
{
    attackTimeCoeff = std::exp(rc_atc / (newValue * sampleRate * 0.001));
}
template <typename SampleType>
SampleType EnvelopeDetector<SampleType>::getAttackTime()
{
    return attackTime;
}
template <typename SampleType>
void EnvelopeDetector<SampleType>::setReleaseTime(SampleType newValue)
{
    releaseTimeCoeff = std::exp(rc_atc / (newValue * sampleRate * 0.001));
}
template <typename SampleType>
SampleType EnvelopeDetector<SampleType>::getReleaseTime()
{
    return releaseTimeCoeff;
}
template <typename SampleType>
void EnvelopeDetector<SampleType>::setDetectionMode(int index)
{
    switch(index)
    {
        case DetectionModes::Peak:
            detectionMode = DetectionModes::Peak;
            break;
        case DetectionModes::MS:
            detectionMode = DetectionModes::MS;
            break;
        case DetectionModes::RMS:
            detectionMode = DetectionModes::RMS;
            break;
        default:
            detectionMode = DetectionModes::Peak;
    }
}
template <typename SampleType>
int EnvelopeDetector<SampleType>::getDetectionMode()
{
    return detectionMode;
}
template <typename SampleType>
void EnvelopeDetector<SampleType>::setOutputIndB(bool outputIndB)
{
    output_In_dB = outputIndB;
}
template <typename SampleType>
bool EnvelopeDetector<SampleType>::isOutputIndB()
{
    return output_In_dB;
}
template <typename SampleType>
void EnvelopeDetector<SampleType>::setSampleRate(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    setAttackTime(attackTime);
    setReleaseTime(releaseTime);
}
template class EnvelopeDetector<float>;
template class EnvelopeDetector<double>;
cbb_ReverbGate/utils/EnvelopeDetector.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
#pragma once
#include <cmath>
/**
 * Envelope Detector Class
 */
template <typename SampleType>
class EnvelopeDetector
{
public:
    /**
     * @brief Constructor
     *
     */
    EnvelopeDetector();
    /**
     * @brief Prepares object for processing
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate);
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input);
    /**
     * @brief Sets the attack time of the Envelope Detector object
     *
     * @param newValue New attack time in milliseconds
     */
    void setAttackTime(SampleType newValue);
    /**
     * @brief Returns the attack time parameter value of the Envelope Detector object
     */
    SampleType getAttackTime();
    /**
     * @brief Sets the release time of the Envelope Detector object
     *
     * @param newValue New Release time in milliseconds
     */
    void setReleaseTime(SampleType newValue);
    /**
     * @brief Returns the release time parameter value of the Envelope Detector object
     *
     * @return SampleType
     */
    SampleType getReleaseTime();
    /**
     * @brief Sets the detection mode of the Envelope Detector object
     *
     * @param index Detection mode index
     */
    void setDetectionMode(int index);
    /**
     * @brief Returns the detection mode index of the Envelope Detector object
     */
    int getDetectionMode();
    /**
     * @brief Sets the envelope detector in dB or linear output mode
     *
     * @param outputIndB Should output be in dB boolean.
     * True = db Output, False = Linear Output
     */
    void setOutputIndB(bool outputIndB);
    /**
     * @brief Returns Envelope Detector detection mode
     *
     * @return true dB output
     * @return false Linear output
     */
    bool isOutputIndB();
    enum DetectionModes
    {
        Peak = 0,
        MS,        //Mean Square
        RMS        //Root Mean Square
    };
private:
    SampleType sampleRate{ 44100.0 };
    //User Parameters
    SampleType attackTime{ 0.0 };   //In ms
    SampleType releaseTime{ 0.0 };  //In ms
    int detectionMode{DetectionModes::Peak};
    SampleType attackTimeCoeff{ 0.0 };
    SampleType releaseTimeCoeff{ 0.0 };
    bool output_In_dB{false};
    const double rc_atc = -0.99967234081320612357829304641019; //RC filter analog time constant
    SampleType previousValue{0.0}; //Envelope value for the previous sample
    void setSampleRate(SampleType sampleRate);
};
cbb_ReverbGate/utils/FirstOrderSmoother.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
#pragma once
#include <cmath>
/**
 * First order filter for smoothing parameter changes
 *
 */
class FirstOrderSmoother
{
public:
    FirstOrderSmoother()
    {
    }
    ~FirstOrderSmoother()
    {
    }
    /**
     * @brief Prepares filter for playback
     *
     * @param smoothingTimeInMs Amount of time to reach target value in milliseconds
     * @param samplingRate Current sampling rate
     */
    void prepare(float smoothingTimeInMs, float samplingRate)
    {
        const float c_twoPi = 6.283185307179586476925286766559f;
        a = exp(-c_twoPi / (smoothingTimeInMs * 0.001f * samplingRate));
        b = 1.0f - a;
        z = 0.0f;
    };
    /**
     * @brief Processes a single sample
     *
     * @param in Target value to reach
     */
    inline float process(float in)
    {
        z = (in * b) + (z * a);
        return z;
    }
private:
    float a;
    float b;
    float z;
};
cbb_ReverbGate/utils/GainUtilities.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
#pragma once
#include <cmath>
/**
 * Struct wrapping inline functions for manipulating Audio Buffer sample levels.
 */
template <typename SampleType>
struct GainUtilities
{
    /**
     * @brief Converts linear gain values to decibels
     *
     * @param gainValue Linear gain value
     */
    static inline SampleType gainToDecibels(SampleType gainValue)
    {
        return 20.0 * log10(gainValue);
    };
    /**
     * @brief Converts decibel values to linear gain
     *
     * @param dbValue Decibel value
     */
    static inline SampleType decibelsToGain(SampleType dbValue)
    {
        return pow(10.0, dbValue / 20.0);
    };
};
cbb_ReverbGate/utils/IIRFilter.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
#include "IIRFilter.h"
template <typename SampleType>
IIRFilter<SampleType>::IIRFilter()
{
}
template <typename SampleType>
IIRFilter<SampleType>::~IIRFilter()
{
}
template <typename SampleType>
void IIRFilter<SampleType>::prepare(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    calculateCoeffs();
}
template <typename SampleType>
SampleType IIRFilter<SampleType>::processSample(SampleType input)
{
    auto yn = d0*input + c0*(a0 * input + a1 * xn_1 + a2 * xn_2 - b1 * yn_1 - b2 * yn_2);
    xn_2 = xn_1;
    xn_1 = input;
    yn_2 = yn_1;
    yn_1 = yn;
    return yn;
}
template <typename SampleType>
void IIRFilter<SampleType>::process(SampleType* data, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        data[sample] = processSample(data[sample]);
}
template <typename SampleType>
void IIRFilter<SampleType>::setCutoff(SampleType newValue)
{
    if (newValue < 20.0f)
        fc = 20.0f;
    else if (newValue > 20000.0f)
        fc = 20000.0f;
    else
        fc = newValue;
    calculateCoeffs();
}
template <typename SampleType>
SampleType IIRFilter<SampleType>::getCutoff()
{
    return fc;
}
template <typename SampleType>
void IIRFilter<SampleType>::setFilterType(int type)
{
    if (type < 0)
        type = 0;
    else if (type > 4)
        type = 4;
    filterType = type;
    calculateCoeffs();
}
template <typename SampleType>
int IIRFilter<SampleType>::getFilterType()
{
    return filterType;
}
template <typename SampleType>
void IIRFilter<SampleType>::setQ(SampleType newValue)
{
    SampleType this_q = newValue;
    if (this_q > 20.0)
        this_q = 20.0;
    else if (this_q < 0.2)
        this_q = 0.2;
    Q = this_q;
    calculateCoeffs();
}
template <typename SampleType>
SampleType IIRFilter<SampleType>::getQ()
{
    return Q;
}
template <typename SampleType>
void IIRFilter<SampleType>::setGain(SampleType newValue)
{
    notchGain = newValue;
    calculateCoeffs();
}
template <typename SampleType>
SampleType IIRFilter<SampleType>::getGain()
{
    return notchGain;
}
template <typename SampleType>
void IIRFilter<SampleType>::calculateCoeffs()
{
    switch (filterType)
    {
        case FilterTypes::LPF : //2nd Order Butterworth LPF
            r = std::sqrt(2);
            C = SampleType(1.0f / tan(PI * fc / (SampleType)this->sampleRate));
            a0 = 1.0f / (1.0f + r * C + C * C);
            a1 = 2 * a0;
            a2 = a0;
            b1 = 2.0f * a0 * (1.0f - C * C);
            b2 = a0 * (1.0f - r * C + C * C);
            c0 = 1.0f;
            d0 = 0.0;
            break;
        case FilterTypes::HPF : //2nd Order Butterworth HPF
            r = std::sqrt(2);
            C = SampleType(tan(PI * fc / (SampleType)this->sampleRate));
            a0 = 1.0f / (1.0f + r * C + C * C);
            a1 = -2 * a0;
            a2 = a0;
            b1 = 2.0f * a0 * (C * C - 1.0f);
            b2 = a0 * (1.0f - r * C + C * C);
            c0 = 1.0f;
            d0 = 0.0;
            break;
        case FilterTypes::Parametric :
            K = tan(PI*fc/SampleType(this->sampleRate));
            V0 = std::pow(10, notchGain / 20);
            D0 = 1 + (K/Q)+K*K;
            e0 = 1 + (K/(V0*Q)) + K*K;
            alpha = 1 + ((V0*K) / Q) + K*K;
            beta = 2*(K*K - 1);
            gamma = 1 - ((V0*K) / Q) + K*K;
            delta = 1 - (K / Q) + K*K;
            heta = 1 - (K / V0*Q) + K*K;
            if(notchGain >= 0)
            {
                //Calcualte boost coefficients
                a0 = alpha/D0;
                a1 = beta/D0;
                a2 = gamma/D0;
                b1 = beta/D0;
                b2 = delta/D0;
                c0 = 1.0f;
                d0 = 0.0f;
            }else
            {
                //Calculate cut coefficients
                a0 = D0/e0;
                a1 = beta/e0;
                a2 = delta/e0;
                b1 = beta/e0;
                b2 = heta/e0;
                c0 = 1.0f;
                d0 = 0.0f;
            }
            /*theta_c = (2 * PI * fc) / SampleType(this->sampleRate);
            u = std::pow(10, notchGain / 20);
            zeta = 4.0 / (1.0 + u);
            beta = 0.5 * (1.0f - (zeta * tan(theta_c / (2.0 * Q)))) / (1.0f + (zeta * tan(theta_c / (2.0 * Q))));
            gamma = (0.5 + beta) * cos(theta_c);
            a0 = 0.5 - beta;
            a1 = 0.0;
            a2 = beta - 0.5;
            b1 = -2.0 * gamma;
            b2 = 2.0 * beta;
            c0 = u - 1.0f;
            d0 = 1.0f;*/
            break;
    }
}
template class IIRFilter<float>;
template class IIRFilter<double>;
cbb_ReverbGate/utils/IIRFilter.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,125 @@
#pragma once
#include <cmath>
#include <EffectProcessorBase.h>
#define PI 3.14159265358979323846
/**
 * IIR Filter Class
 *
 */
template <typename SampleType>
class IIRFilter : public EffectProcessorBase<SampleType>
{
public:
    /**
     * @brief Constructor
     */
    IIRFilter();
    /**
     * @brief Destructor
     */
    ~IIRFilter();
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate) override;
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input) override;
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param data Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* data, int startSample, int endSample) override;
    /**
     * @brief Sets filter cutoff frequency
     *
     * @param newValue New cutoff frequency value
     *
     * When the filter mode is set to Parametric it sets the center frequency instead.
     */
    void setCutoff(SampleType newValue);
    /**
     * @brief Sets the filter type
     *
     * @param filterType Filter type index
     */
    void setFilterType(int filterType);
    /**
     * @brief Sets the filter quality factor
     *
     * @param newValue New filter quality factor
     */
    void setQ(SampleType newValue);
    /**
     * @brief Sets the amount of boost/attenuation of the parametric mode
     *
     * @param newValue New boost/attention value in decibels
     */
    void setGain(SampleType newValue);
    /**
     * @brief Returns the cutoff/center frequency of the filter
     */
    SampleType getCutoff();
    /**
     * @brief Returns the quality factor of the filter
     */
    SampleType getQ();
    /**
     * @brief Returns the boost/cut value of the parametric filter mode
     */
    SampleType getGain();
    /**
     * @brief Returns the filter type index
     */
    int getFilterType();
    enum FilterTypes
    {
        LPF = 0,    // Low Pass Fitler
        HPF,        // High Pass Filter
        Parametric,
    };
private:
    SampleType a0, a1, a2, b1, b2, c0, d0, r, C;
    // Paremetric EQ Filter Variables
    SampleType K, V0, e0, D0, alpha, beta, gamma, delta, heta;
    SampleType theta_c, u, zeta;
    // Previous in/out values
    SampleType xn_1 = 0, xn_2 = 0, yn_1 = 0, yn_2 = 0;
    // User Parameters
    SampleType fc {500.0}, Q {1.0}, notchGain {0.0};
    int filterType {FilterTypes::LPF};
    void calculateCoeffs();
};
cbb_ReverbGate/utils/InterpolatedAllPassFilter.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
#include "InterpolatedAllPassFilter.h"
template <typename SampleType>
InterpolatedAllPassFilter<SampleType>::InterpolatedAllPassFilter()
{
}
template <typename SampleType>
InterpolatedAllPassFilter<SampleType>::~InterpolatedAllPassFilter()
{
}
template <typename SampleType>
void InterpolatedAllPassFilter<SampleType>::prepare(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    circularBuffer.prepare(sampleRate);
    circularBuffer.setSize(2*sampleRate);
    circularBuffer.setDelayInMs(delayTime);
}
template <typename SampleType>
void InterpolatedAllPassFilter<SampleType>::setDelayMs(SampleType delayInMs)
{
    circularBuffer.setDelayInMs(delayInMs);
}
template <typename SampleType>
void InterpolatedAllPassFilter<SampleType>::setDelaySamples(SampleType delayInSamples)
{
    circularBuffer.setDelayInSamples(delayInSamples);
}
template <typename SampleType>
void InterpolatedAllPassFilter<SampleType>::setFeedback(SampleType newFeedback)
{
    newFeedback >= FEEDBACK_LIMIT ? newFeedback = FEEDBACK_LIMIT : newFeedback = newFeedback;
    newFeedback <= 0.0 ? newFeedback = 0.0 : newFeedback = newFeedback;
    this->feedback = newFeedback;
}
template <typename SampleType>
SampleType InterpolatedAllPassFilter<SampleType>::processSample(SampleType input)
{
    lastOutput = circularBuffer.popSample();
    circularBuffer.pushSample(input + (feedback * lastOutput));
    lastInput = input * -feedback;
    return (lastOutput + lastInput);
}
template <typename SampleType>
void InterpolatedAllPassFilter<SampleType>::process(SampleType* channelData, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        channelData[sample] = processSample(channelData[sample]);
}
template class InterpolatedAllPassFilter<float>;
template class InterpolatedAllPassFilter<double>;
cbb_ReverbGate/utils/InterpolatedAllPassFilter.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
#pragma once
#include <LinearInterpolationCircularBuffer.h>
#define FEEDBACK_LIMIT 0.99
/**
 * First Order All-Pass Filter that utilizes linear interpolation when poping samples.
 *
 * Allows for smoother delay time changes and modulation.
 *
 */
template <typename SampleType>
class InterpolatedAllPassFilter
{
public:
    /**
     * @brief Constructor
     */
    InterpolatedAllPassFilter();
    /**
     * @brief Destructor
     */
    ~InterpolatedAllPassFilter();
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate);
    /**
     * @brief Sets the delay time in milliseconds
     *
     * @param delayInMs Delay time in milliseconds
     */
    void setDelayMs(SampleType delayInMs);
    /**
     * @brief Sets the delay time in samples
     *
     * @param delayInMs Delay time in samples
     */
    void setDelaySamples(SampleType delayInSamples);
    /**
     * @brief Sets the amount of feedback.
     *
     * Values must range between 0 and 1
     *
     * @param newFeedback Feedback amount
     */
    void setFeedback(SampleType newFeedback);
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input);
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param channelData Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* channelData, int startSample, int endSample);
private:
    SampleType sampleRate;
    LinearInterpolationCircularBuffer<SampleType> circularBuffer;
    SampleType delayTime {0.0};
    SampleType feedback {0.0};
    SampleType lastOutput {0.0};
    SampleType lastInput {0.0};
};
cbb_ReverbGate/utils/InterpolatedCombFilter.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
#include "InterpolatedCombFilter.h"
template <typename SampleType>
InterpolatedCombFilter<SampleType>::InterpolatedCombFilter()
{
}
template <typename SampleType>
InterpolatedCombFilter<SampleType>::~InterpolatedCombFilter()
{
}
template <typename SampleType>
void InterpolatedCombFilter<SampleType>::prepare(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    circularBuffer.prepare(sampleRate);
    circularBuffer.setSize(2*sampleRate);
    circularBuffer.setDelayInSamples(delaySamples);
}
template <typename SampleType>
void InterpolatedCombFilter<SampleType>::setDelayMs(SampleType delayInMs)
{
    this->delaySamples = (delayInMs / 1000) * sampleRate;
    circularBuffer.setDelayInSamples(this->delaySamples);
}
template <typename SampleType>
void InterpolatedCombFilter<SampleType>::setDelaySamples(SampleType delayInSamples)
{
    this->delaySamples = delayInSamples;
    circularBuffer.setDelayInSamples(delaySamples);
}
template <typename SampleType>
void InterpolatedCombFilter<SampleType>::setFeedback(SampleType newFeedback)
{
    newFeedback >= FEEDBACK_LIMIT ? newFeedback = FEEDBACK_LIMIT : newFeedback = newFeedback;
    //newFeedback <= 0.0 ? newFeedback = 0.0 : newFeedback = newFeedback;
    this->feedback = newFeedback;
}
template <typename SampleType>
SampleType InterpolatedCombFilter<SampleType>::processSample(SampleType input)
{
    SampleType in = input + feedback*lastOutput;
    SampleType out = circularBuffer.popSample();
    circularBuffer.pushSample(in);
    lastOutput = out;
    return out;
}
template <typename SampleType>
void InterpolatedCombFilter<SampleType>::process(SampleType* channelData, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        channelData[sample] = processSample(channelData[sample]);
}
template class InterpolatedCombFilter<float>;
template class InterpolatedCombFilter<double>;
cbb_ReverbGate/utils/InterpolatedCombFilter.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
#pragma once
#include <LinearInterpolationCircularBuffer.h>
#define FEEDBACK_LIMIT 0.99
/**
 * Comb Filter that utilizes linear interpolation when poping samples.
 *
 * Allows for smoother delay time changes and modulation.
 *
 */
template <typename SampleType>
class InterpolatedCombFilter
{
public:
    /**
     * @brief Constructor
     */
    InterpolatedCombFilter();
    /**
     * @brief Destructor
     */
    ~InterpolatedCombFilter();
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate);
    /**
     * @brief Sets the delay time in milliseconds
     *
     * @param delayInMs Delay time in milliseconds
     */
    void setDelayMs(SampleType delayInMs);
    /**
     * @brief Sets the delay time in samples
     *
     * @param delayInSamples Delay time in samples
     */
    void setDelaySamples(SampleType delayInSamples);
    /**
     * @brief Sets the amount of feedback.
     *
     * Values must range between 0 and 1
     *
     * @param newFeedback Feedback amount
     */
    void setFeedback(SampleType newFeedback);
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input);
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param channelData Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* channelData, int startSample, int endSample);
private:
    SampleType sampleRate;
    LinearInterpolationCircularBuffer<SampleType> circularBuffer;
    SampleType delaySamples {0.0};
    SampleType feedback {0.0};
    SampleType lastOutput {0.0};
};
cbb_ReverbGate/utils/LFO.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,199 @@
#include "LFO.h"
LFO::LFO()
{
}
LFO::LFO(int waveformType)
{
    setWaveformType(waveformType);
}
void LFO::prepare(double sampleRate)
{
    setSampleRate(sampleRate);
    modCounter = 0.0;
    modCounter90 = 0.25;
    setFrequency(frequency);
}
double LFO::getNextOutputSample(int phaseType)
{
    generateNextOutputSample();
    switch(phaseType)
    {
        case LFOPhase::Normal:
            return outNormal;
            break;
        case LFOPhase::Inverted:
            return outInverted;
            break;
        case LFOPhase::QuadPhase:
            return outQuadPhase;
            break;
        case LFOPhase::QuadPhaseInverted:
            return outQuadPhaseInverted;
            break;
        default:
            return outNormal;
            break;
    }
}
void LFO::setWaveformType(int waveformType)
{
    switch(waveformType)
    {
        case Waveforms::Triangle:
            waveformType = Waveforms::Triangle;
            break;
        case Waveforms::Sine:
            waveformType = Waveforms::Sine;
            break;
        case Waveforms::Saw:
            waveformType = Waveforms::Saw;
            break;
    }
}
int LFO::getWaveformType()
{
    return waveformType;
}
void LFO::setFrequency(double freq)
{
    frequency = freq;
    phaseInc = frequency / sampleRate;
}
double LFO::getFrequency()
{
    return frequency;
}
void LFO::setSampleRate(double sampleRate)
{
    this->sampleRate = sampleRate;
}
double LFO::getSampleRate()
{
    return sampleRate;
}
double LFO::unipolarToBipolar(double value)
{
    return 2.0*value - 1.0;
}
void LFO::generateNextOutputSample()
{
    moduloWrap(modCounter, phaseInc);
    modCounter90 = modCounter;
    moduloAdvanceAndWrap(modCounter90, 0.25);
    outNormal = 0.0;
    outInverted = 0.0;
    outQuadPhase = 0.0;
    outQuadPhaseInverted = 0.0;
    switch(waveformType)
    {
        case Waveforms::Triangle:
            // Normal Output
            outNormal = unipolarToBipolar(modCounter);
            outNormal = 2.0*fabs(outNormal) - 1.0;
            // 90 Degree phase shift
            outQuadPhase = unipolarToBipolar(modCounter90);
            outQuadPhase = 2.0*fabs(outQuadPhase) - 1.0;
            break;
        case Waveforms::Sine:
            double angle;
            // Angle Calculation
            angle = modCounter*2.0*PI - PI;
            // Normal Output
            outNormal = parabolicSine(-angle);
            // 90 Degree shift angle calculation
            angle = modCounter90*2.0*PI - PI;
            // 90 Degree phase shift
            outQuadPhase = parabolicSine(-angle);
            break;
        case Waveforms::Saw:
            // Normal Output
            outNormal = unipolarToBipolar(modCounter);
            // 90 Degree Shift
            outQuadPhase = unipolarToBipolar(modCounter90);
            break;
    }
    // Inverted Outputs
    // Inverted Normal Output
    outInverted = -outNormal;
    // Inverted 90 Degree
    outQuadPhaseInverted = -outQuadPhase;
    moduloAdvance(modCounter, phaseInc);
}
void LFO::moduloAdvance(double& modCounter, double phaseInc)
{
    modCounter += phaseInc;
}
void LFO::moduloWrap(double& modCounter, double phaseInc)
{
    // Positive Frequencies
    if(phaseInc > 0 && modCounter >= 1.0)
        modCounter -= 1.0;
    // Negative Frequencies
    if(phaseInc < 0 && modCounter <= 0.0)
        modCounter += 1.0;
}
void LFO::moduloAdvanceAndWrap(double& modCounter, double phaseInc)
{
    // Advance
    modCounter += phaseInc;
    // Check if Wrap is needed
    // Positive Frequencies
    if(phaseInc > 0 && modCounter >= 1.0)
        modCounter -= 1.0;
    // Negative Frequencies
    if(phaseInc < 0 && modCounter <= 0.0)
        modCounter += 1.0;
}
double LFO::parabolicSine(double angle)
{
    const double B = 4.0 / PI;
    const double C = -4.0 / (PI* PI);
    const double P = 0.225;
    double y = B * angle + C * angle * fabs(angle);
    return (P * (y * fabs(y) - y) + y);
}
cbb_ReverbGate/utils/LFO.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,127 @@
#pragma once
#include <iostream>
#include <cmath>
#define PI 3.14159265358979323846
/**
 * Low Frequency Oscillator Class
 *
 */
class LFO
{
public:
    /**
     * @brief Contructor
     *
     */
    LFO();
    /**
     * @brief Constructor
     *
     * Sets waveform type during object declaration
     *
     * @param waveformType Waveform type index
     */
    LFO(int waveformType);
    /**
     * @brief Prepares object for processing
     *
     * @param sampleRate Current sample rate
     */
    void prepare(double sampleRate);
    /**
     * @brief Generates and returns the next oscillator sample
     *
     * @param phaseType Oscillator phase
     */
    double getNextOutputSample(int phaseType);
    /**
     * @brief Sets oscillator waveform type
     *
     * @param waveformType Waveform type index
     */
    void setWaveformType(int waveformType);
    /**
     * @brief Returns waveform type index
     */
    int getWaveformType();
    /**
     * @brief Sets oscillation rate
     *
     * @param freq New Rate
     */
    void setFrequency(double freq);
    /**
     * @brief Returns oscillation rate
     */
    double getFrequency();
    /**
     * @brief Sets the Sample Rate
     *
     * @param sampleRate New sample rate
     */
    void setSampleRate(double sampleRate);
    /**
     * @brief Returns the current sample rate the object is operating on
     */
    double getSampleRate();
    /**
     * @brief Converts unipolar oscilation type to bipolar
     *
     * @param value Value to convert
     */
    double unipolarToBipolar(double value);
    enum Waveforms
    {
        Triangle = 0,
        Sine,
        Saw
    };
    enum LFOPhase
    {
        Normal = 0,
        Inverted,
        QuadPhase,
        QuadPhaseInverted
    };
private:
    void generateNextOutputSample();
    // Advabce the mod counter
    void moduloAdvance(double& modCounter, double phaceInc);
    // Check the mod counter and wrap
    void moduloWrap(double& modCounter, double phaceInc);
    // Advance the mod counter and wrap
    void moduloAdvanceAndWrap(double& modCounter, double phaceInc);
    // Parabolic Sine Calculation Function (Angle ragnes from -pi to pi)
    double parabolicSine(double angle);
    // Oscillator Parameters
    double modCounter, modCounter90, phaseInc;
    double frequency {1.0}, sampleRate;
    int waveformType {Waveforms::Sine};
    // Output Values
    double outNormal, outInverted, outQuadPhase, outQuadPhaseInverted;
};
cbb_ReverbGate/utils/LinearInterpolationCircularBuffer.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,127 @@
#include "LinearInterpolationCircularBuffer.h"
template <typename SampleType>
LinearInterpolationCircularBuffer<SampleType>::LinearInterpolationCircularBuffer()
{
    buffer.reset(new std::vector<SampleType>);
}
template <typename SampleType>
LinearInterpolationCircularBuffer<SampleType>::~LinearInterpolationCircularBuffer()
{
    buffer->clear();
    buffer.reset(nullptr);
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::prepare(int sampleRate)
{
    this->sampleRate = sampleRate;
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::clear()
{
    buffer->clear();
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::setSize(int newBufferSize)
{
    clear();
    buffer->resize(newBufferSize);
    this->bufferSize = newBufferSize;
    writePointer = 0;
    readPointer = 0;
}
template <typename SampleType>
int LinearInterpolationCircularBuffer<SampleType>::getNumSamples()
{
    return buffer->size();
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::setDelayInSamples(SampleType delayInSamples)
{
    delay = limitWithinRange(SampleType(0), SampleType(bufferSize - 1), delayInSamples);
    delayInt  = static_cast<int> (std::floor (delay));
    delayFrac = delay - (SampleType) delayInt;
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::setDelayInMs(SampleType delayInMs)
{
    setDelayInSamples((delayInMs / 1000) * sampleRate);
}
template <typename SampleType>
SampleType LinearInterpolationCircularBuffer<SampleType>::processSample(SampleType input)
{
    pushSample(input);
    return popSample();
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::process(SampleType* channelData, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        channelData[sample] = processSample(channelData[sample]);
}
template <typename SampleType>
void LinearInterpolationCircularBuffer<SampleType>::pushSample(SampleType sample)
{
    (*buffer)[writePointer] = sample;
    writePointer = (writePointer + bufferSize - 1) % bufferSize;
}
template <typename SampleType>
SampleType LinearInterpolationCircularBuffer<SampleType>::popSample()
{
    SampleType returnValue = interpolateSample();
    readPointer = (readPointer + bufferSize - 1) % bufferSize;
    return returnValue;
}
template <typename SampleType>
SampleType LinearInterpolationCircularBuffer<SampleType>::interpolateSample()
{
    auto index1 = readPointer + delayInt;
    auto index2 = index1 + 1;
    if(index2 >= bufferSize)
    {
        index1 %= bufferSize;
        index2 %= bufferSize;
    }
    SampleType value1 = (*buffer)[index1];
    SampleType value2 = (*buffer)[index2];
    return value1 + delayFrac * (value2 - value1);
}
template <typename SampleType>
int LinearInterpolationCircularBuffer<SampleType>::getReadPointerIndex()
{
    return readPointer;
}
template <typename SampleType>
int LinearInterpolationCircularBuffer<SampleType>::getWritePointerIndex()
{
    return writePointer;
}
template <typename SampleType>
SampleType LinearInterpolationCircularBuffer<SampleType>::limitWithinRange(SampleType lowerLimit, SampleType upperLimit, SampleType value)
{
    return value < lowerLimit ? lowerLimit : (upperLimit < value ? upperLimit : value);
}
template class LinearInterpolationCircularBuffer<float>;
template class LinearInterpolationCircularBuffer<double>;
cbb_ReverbGate/utils/LinearInterpolationCircularBuffer.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,124 @@
#pragma once
#include <iostream>
#include <vector>
#include <memory>
#include <cmath>
/**
 * Circular buffer that utilizes linear interpolation when reading samples, allowing for fractional delay lines.
 */
template <typename SampleType>
class LinearInterpolationCircularBuffer
{
public:
    /**
     * @brief Constructor
     */
    LinearInterpolationCircularBuffer();
    /**
     * @brief Destructor
     */
    ~LinearInterpolationCircularBuffer();
    /**
     * @brief Prepares buffer for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(int sampleRate);
    void reset();
    /**
     * @brief Clears the buffer
     *
     */
    void clear();
    /**
     * @brief Sets buffer size
     *
     * @param newBufferSize New buffer size in samples
     */
    void setSize(int newBufferSize);
    /**
     * @brief Returns buffer size
     */
    int getNumSamples();
    /**
     * @brief Sets delay time in samples
     *
     * @param delayInSamples New delay time in samples
     */
    void setDelayInSamples(SampleType delayInSamples);
    /**
     * @brief Sets delay time in milliseconds
     *
     * @param delayInMs New delay time in milliseconds
     */
    void setDelayInMs(SampleType delayInMs);
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input);
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param channelData Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* channelData, int startSample, int endSample);
    /**
     * @brief Returns read pointer index
     */
    int getReadPointerIndex();
    /**
     * @brief Returns write pointer index
     */
    int getWritePointerIndex();
    /**
     * @brief Pushes a sample to the buffer and advances the write pointer by an index of 1
     *
     * @warning Meant to be used in a sample by sample processing context
     *
     * @param sample input sample
     */
    void pushSample(SampleType sample);
    /**
     * @brief Returns a sample from the buffer read position and advances the read pointer by an index of 1
     *
     * The return value is linearly interpolated
     *
     * @warning Meant to be used in a sample by sample processing context
     */
    SampleType popSample();
private:
    SampleType interpolateSample();
    SampleType limitWithinRange(SampleType lowerLimit, SampleType upperLimit, SampleType value);
private:
    SampleType sampleRate;
    std::unique_ptr<std::vector<SampleType>> buffer;
    SampleType delayFrac {0.0}, delay {0.0};
    int readPointer, writePointer, delayInt, bufferSize;
};
cbb_ReverbGate/utils/ModulatedAllPassFilter.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,107 @@
#include "ModulatedAllPassFilter.h"
template <typename SampleType>
ModulatedAllPassFilter<SampleType>::ModulatedAllPassFilter()
{
}
template <typename SampleType>
ModulatedAllPassFilter<SampleType>::~ModulatedAllPassFilter()
{
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::prepare(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    allPassFilter.prepare(sampleRate);
    allPassFilter.setDelayMs(delayTime);
    allPassFilter.setFeedback(feedback);
    lfo.prepare(sampleRate);
    lfo.setWaveformType(LFO::Waveforms::Sine);
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::setDelayMs(SampleType delayInMs)
{
    this->delayTime = delayInMs;
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::setDelayInSamples(SampleType delayInSamples)
{
    this->delayTime = (delayInSamples / sampleRate) * 1000.0;
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::setFeedback(SampleType newFeedback)
{
    this->feedback = newFeedback;
    allPassFilter.setFeedback(this->feedback);
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::setRate(SampleType newRate)
{
    this->rate = newRate;
    lfo.setFrequency(this->rate);
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::setDepth(SampleType newDepth)
{
    this->depth = newDepth;
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::setWidth(SampleType newWidth)
{
    this->width = newWidth;
}
template <typename SampleType>
SampleType ModulatedAllPassFilter<SampleType>::processSample(SampleType input)
{
    SampleType minDelay = ((this->delayTime / 1000) * sampleRate) - width;
    SampleType maxDelay = ((this->delayTime / 1000) * sampleRate) + width;
    SampleType modMin = minDelay;
    SampleType modMax = maxDelay;
    SampleType newDelTime = (doUnipolarModulationFromMin(bipolarToUnipolar(depth * lfo.getNextOutputSample(LFO::LFOPhase::Normal)), modMin, modMax));
    allPassFilter.setDelaySamples(newDelTime);
    SampleType output = allPassFilter.processSample(input);
    return output;
}
template <typename SampleType>
void ModulatedAllPassFilter<SampleType>::process(SampleType* data, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        data[sample] = processSample(data[sample]);
}
template <typename SampleType>
SampleType ModulatedAllPassFilter<SampleType>::doUnipolarModulationFromMin(SampleType unipolarModulatorValue, SampleType minValue, SampleType maxValue)
{
    // --- UNIPOLAR bound
    unipolarModulatorValue = fmin(unipolarModulatorValue, 1.0f);
    unipolarModulatorValue = fmax(unipolarModulatorValue, 0.0f);
    // --- modulate from minimum value upwards
    return unipolarModulatorValue * (maxValue - minValue) + minValue;
}
template <typename SampleType>
SampleType ModulatedAllPassFilter<SampleType>::bipolarToUnipolar(SampleType value)
{
    return 0.5 * value + 0.5;
}
template class ModulatedAllPassFilter<float>;
template class ModulatedAllPassFilter<double>;
cbb_ReverbGate/utils/ModulatedAllPassFilter.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
#pragma once
#include <InterpolatedAllPassFilter.h>
#include <LFO.h>
/**
 * First Order All-Pass Filter with modulating delay time
 *
 */
template <typename SampleType>
class ModulatedAllPassFilter
{
public:
    /**
     * @brief Constructor
     */
    ModulatedAllPassFilter();
    /**
     * @brief Destructor
     */
    ~ModulatedAllPassFilter();
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate);
    /**
     * @brief Sets the delay time in milliseconds
     *
     * @param delayInMs Delay time in milliseconds
     */
    void setDelayMs(SampleType delayInMs);
    /**
     * @brief Sets the delay time in samples
     *
     * @param delayInSamples Delay time in samples
     */
    void setDelayInSamples(SampleType delayInSamples);
    /**
     * @brief Sets the amount of feedback.
     *
     * Values must range between 0 and 1
     *
     * @param newFeedback Feedback amount
     */
    void setFeedback(SampleType newFeedback);
    /**
     * @brief Sets the delay time modulation rate
     *
     * @param newRate New modulation rate value in Hz
     */
    void setRate(SampleType newRate);
    /**
     * @brief Sets the delay time modulation depth
     *
     * @param newDepth New modulation depth value
     *
     * Values must range between 0.0 to 1.0
     */
    void setDepth(SampleType newDepth);
    /**
     * @brief Sets the bounds the delay time values can modulate between
     *
     * @param newWidth New modulation width in samples
     */
    void setWidth(SampleType newWidth);
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input);
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param data Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* data, int startSample, int endSample);
private:
    SampleType doUnipolarModulationFromMin(SampleType unipolarModulatorValue, SampleType minValue, SampleType maxValue);
    SampleType bipolarToUnipolar(SampleType value);
private:
    SampleType sampleRate;
    InterpolatedAllPassFilter<SampleType> allPassFilter;
    LFO lfo;
    SampleType delayTime {0.0}, feedback {0.0}, rate {0.0}, depth {0.0}, width {0.0};
};
cbb_ReverbGate/utils/ModulatedCombFilter.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,107 @@
#include "ModulatedCombFilter.h"
template <typename SampleType>
ModulatedCombFilter<SampleType>::ModulatedCombFilter()
{
}
template <typename SampleType>
ModulatedCombFilter<SampleType>::~ModulatedCombFilter()
{
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::prepare(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    combFilter.prepare(sampleRate);
    combFilter.setDelayMs(delayTime);
    combFilter.setFeedback(feedback);
    lfo.prepare(sampleRate);
    lfo.setWaveformType(LFO::Waveforms::Sine);
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::setDelayMs(SampleType delayInMs)
{
    this->delayTime = delayInMs;
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::setDelayInSamples(SampleType delayInSamples)
{
    this->delayTime = (delayInSamples / sampleRate) * 1000.0;
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::setFeedback(SampleType newFeedback)
{
    this->feedback = newFeedback;
    combFilter.setFeedback(this->feedback);
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::setRate(SampleType newRate)
{
    this->rate = newRate;
    lfo.setFrequency(this->rate);
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::setDepth(SampleType newDepth)
{
    this->depth = newDepth;
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::setWidth(SampleType newWidth)
{
    this->width = newWidth;
}
template <typename SampleType>
SampleType ModulatedCombFilter<SampleType>::processSample(SampleType input)
{
    SampleType minDelay = ((this->delayTime / 1000) * sampleRate) - width;
    SampleType maxDelay = ((this->delayTime / 1000) * sampleRate) + width;
    SampleType modMin = minDelay;
    SampleType modMax = maxDelay;
    SampleType newDelTime = (doUnipolarModulationFromMin(bipolarToUnipolar(depth * lfo.getNextOutputSample(LFO::LFOPhase::Normal)), modMin, modMax));
    combFilter.setDelaySamples(newDelTime);
    SampleType output = combFilter.processSample(input);
    return output;
}
template <typename SampleType>
void ModulatedCombFilter<SampleType>::process(SampleType* data, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        data[sample] = processSample(data[sample]);
}
template <typename SampleType>
SampleType ModulatedCombFilter<SampleType>::doUnipolarModulationFromMin(SampleType unipolarModulatorValue, SampleType minValue, SampleType maxValue)
{
    // --- UNIPOLAR bound
    unipolarModulatorValue = fmin(unipolarModulatorValue, 1.0f);
    unipolarModulatorValue = fmax(unipolarModulatorValue, 0.0f);
    // --- modulate from minimum value upwards
    return unipolarModulatorValue * (maxValue - minValue) + minValue;
}
template <typename SampleType>
SampleType ModulatedCombFilter<SampleType>::bipolarToUnipolar(SampleType value)
{
    return 0.5 * value + 0.5;
}
template class ModulatedCombFilter<float>;
template class ModulatedCombFilter<double>;
cbb_ReverbGate/utils/ModulatedCombFilter.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
#pragma once
#include <InterpolatedCombFilter.h>
#include <LFO.h>
/**
 * Comb Filter with modulating delay time
 *
 */
template <typename SampleType>
class ModulatedCombFilter
{
public:
    /**
     * @brief Constructor
     */
    ModulatedCombFilter();
    /**
     * @brief Destructor
     */
    ~ModulatedCombFilter();
    /**
     * @brief Prepares object for playback
     *
     * @param sampleRate Current sampling rate
     */
    void prepare(SampleType sampleRate);
    /**
     * @brief Sets the delay time in milliseconds
     *
     * @param delayInMs Delay time in milliseconds
     */
    void setDelayMs(SampleType delayInMs);
    /**
     * @brief Sets the delay time in samples
     *
     * @param delayInSamples Delay time in samples
     */
    void setDelayInSamples(SampleType delayInSamples);
    /**
     * @brief Sets the amount of feedback.
     *
     * Values must range between 0 and 1
     *
     * @param newFeedback Feedback amount
     */
    void setFeedback(SampleType newFeedback);
    /**
     * @brief Sets the delay time modulation rate
     *
     * @param newRate New modulation rate value in Hz
     */
    void setRate(SampleType newRate);
    /**
     * @brief Sets the delay time modulation depth
     *
     * @param newDepth New modulation depth value
     *
     * Values must range between 0.0 to 1.0
     */
    void setDepth(SampleType newDepth);
    /**
     * @brief Sets the bounds the delay time values can modulate between
     *
     * @param newWidth New modulation width in samples
     */
    void setWidth(SampleType newWidth);
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input);
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param data Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* data, int startSample, int endSample);
private:
    SampleType doUnipolarModulationFromMin(SampleType unipolarModulatorValue, SampleType minValue, SampleType maxValue);
    SampleType bipolarToUnipolar(SampleType value);
private:
    SampleType sampleRate;
    InterpolatedCombFilter<SampleType> combFilter;
    LFO lfo;
    SampleType delayTime {0.0}, feedback {0.0}, rate {0.0}, depth {0.0}, width {0.0};
};
cbb_ReverbGate/utils/ModulationProcessor.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
#pragma once
#include <EffectProcessorBase.h>
#include <LinearInterpolationCircularBuffer.h>
#include <LFO.h>
/**
 * Base Class for Modulation Effect Processors
 *
 */
template <typename SampleType>
class ModulationProcessor : public EffectProcessorBase<SampleType>
{
public:
    /**
     * @brief Sets modulation rate
     *
     * @param newRate New rate value
     */
    virtual void setRate(SampleType newRate) = 0;
    /**
     * @brief Sets modulation depth
     *
     * @param newDepth New depth value
     */
    virtual void setDepth(SampleType newDepth) = 0;
protected:
    SampleType doUnipolarModulationFromMin(SampleType unipolarModulatorValue, SampleType minValue, SampleType maxValue)
    {
        // --- UNIPOLAR bound
        unipolarModulatorValue = fmin(unipolarModulatorValue, 1.0f);
        unipolarModulatorValue = fmax(unipolarModulatorValue, 0.0f);
        // --- modulate from minimum value upwards
        return unipolarModulatorValue * (maxValue - minValue) + minValue;
    };
    SampleType bipolarToUnipolar(SampleType value)
    {
        return 0.5 * value + 0.5;
    };
protected:
    SampleType sampleRate;
    LinearInterpolationCircularBuffer<SampleType> delayLine;
    LFO lfo;
};
cbb_ReverbGate/utils/Reverb.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,108 @@
#include "Reverb.h"
template <typename SampleType>
Reverb<SampleType>::Reverb()
{
}
template <typename SampleType>
Reverb<SampleType>::~Reverb()
{
}
template <typename SampleType>
void Reverb<SampleType>::prepare(SampleType sampleRate)
{
    this->sampleRate = sampleRate;
    for(int comb = 0; comb < NUM_COMBS; ++comb)
    {
        combFilters[comb].prepare(sampleRate);
        combFilters[comb].setDelayMs(combDelayTimeValues[comb]);
        combFilters[comb].setFeedback(combFeedbackValues[comb]);
        combFilters[comb].setWidth(8);
        combFilters[comb].setRate(combModRates[comb]);
        combFilters[comb].setDepth(1.0);
        valueSmoothers[comb].prepare(450.0, sampleRate);
    }
    for(int allpass = 0; allpass < NUM_ALLPASS; ++allpass)
    {
        allPassFilters[allpass].prepare(sampleRate);
        allPassFilters[allpass].setDelayMs(allPassDelayTimeValues[allpass]);
        allPassFilters[allpass].setFeedback(allPassFeedbackValues[allpass]);
        allPassFilters[allpass].setWidth(8);
        allPassFilters[allpass].setRate(allPassModRates[allpass]);
        allPassFilters[allpass].setDepth(0.4);
    }
    filter.prepare(sampleRate);
    filter.setFilterType(IIRFilter<SampleType>::FilterTypes::LPF);
    filter.setCutoff(this->filterCutoff);
}
template <typename SampleType>
SampleType Reverb<SampleType>::processSample(SampleType input)
{
    SampleType combOutput = 0.0;
    SampleType output = 0.0;
    // Comb Filters
    for(int comb = 0; comb < NUM_COMBS; ++comb)
    {
        combFilters[comb].setDelayMs(valueSmoothers[comb].process(roomSize) * combDelayTimeValues[comb]);
        combOutput += combFilters[comb].processSample(input);
    }
    combOutput = combOutput / NUM_COMBS;
    // All-Pass Filters
    output = allPassFilters[0].processSample(combOutput);
    output = allPassFilters[1].processSample(output);
    // Low-Pass Filter
    output = filter.processSample(output);
    return (mix * output) + ((1.0 - mix) * input);
}
template <typename SampleType>
void Reverb<SampleType>::process(SampleType* data, int startSample, int endSample)
{
    for(int sample = startSample; sample < endSample; ++sample)
        data[sample] = processSample(data[sample]);
}
template <typename SampleType>
void Reverb<SampleType>::setRoomSize(SampleType newRoomSize)
{
    this->roomSize = newRoomSize;
}
template <typename SampleType>
void Reverb<SampleType>::setDecay(SampleType newDecay)
{
    this->decay = newDecay;
    for(int comb = 0; comb < NUM_COMBS; ++comb)
        combFilters[comb].setFeedback(decay * combFeedbackValues[comb]);
}
template <typename SampleType>
void Reverb<SampleType>::setCutoff(SampleType newCutoff)
{
    this->filterCutoff = newCutoff;
    filter.setCutoff(this->filterCutoff);
}
template <typename SampleType>
void Reverb<SampleType>::setMix(SampleType newMix)
{
    this->mix = newMix;
}
template class Reverb<float>;
template class Reverb<double>;
cbb_ReverbGate/utils/Reverb.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
#pragma once
#include <EffectProcessorBase.h>
#include <ModulatedCombFilter.h>
#include <ModulatedAllPassFilter.h>
#include <LFO.h>
#include <IIRFilter.h>
#include <FirstOrderSmoother.h>
#define NUM_COMBS 4
#define NUM_ALLPASS 2
template <typename SampleType>
class Reverb : public EffectProcessorBase<SampleType>
{
public:
    Reverb();
    ~Reverb();
    void prepare(SampleType sampleRate) override;
    /**
     * @brief Processes a single sample
     *
     * @param input Input sample
     */
    SampleType processSample(SampleType input) override;
    /**
     * @brief Processes a memory block that holds audio samples
     *
     * @param data Memory block start pointer
     * @param startSample Sample index to start processing from
     * @param endSample Number of samples to process
     */
    void process(SampleType* data, int startSample, int endSample) override;
    void setRoomSize(SampleType newRoomSize);
    void setDecay(SampleType newDecay);
    void setCutoff(SampleType newCutoff);
    void setMix(SampleType newMix);
private:
    ModulatedCombFilter<SampleType> combFilters[NUM_COMBS];
    ModulatedAllPassFilter<SampleType> allPassFilters[NUM_ALLPASS];
    LFO combLFO[NUM_COMBS];
    LFO allPassLFO[NUM_ALLPASS];
    SampleType combDelayTimeValues[NUM_COMBS] {43.7, 41.1, 37.1, 29.7}; // CombFilter Delay times in ms
    SampleType combFeedbackValues[NUM_COMBS] {0.9, -0.9, 0.9, -0.9};
    SampleType combModRates[NUM_COMBS] {0.6, 0.71, 0.83, 0.95};
    SampleType allPassDelayTimeValues[NUM_ALLPASS] {5.0, 1.7}; // AllPass Delay times in ms
    SampleType allPassFeedbackValues[NUM_ALLPASS] {0.7, 0.7};
    SampleType allPassModRates[NUM_ALLPASS] {0.6, 0.83};
    FirstOrderSmoother valueSmoothers[NUM_COMBS];
    IIRFilter<SampleType> filter;
    // User Parameters
    SampleType roomSize {1.0}, decay {0.5}, filterCutoff {20000.0}, mix {0.5};
};
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/CopilotIndices/17.13.439.2385/CodeChunks.db
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/CopilotIndices/17.13.439.2385/SemanticSymbols.db
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/2575945a-65a1-431d-91d3-3d5f980cae5a.vsidx
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/3a4648d8-dd3f-46ea-993c-503c18760d34.vsidx
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/46d07015-65cb-4fe7-a056-59362f75721f.vsidx
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/FileContentIndex/9e83b5d3-8044-4e57-b6e1-3cc4afe3f3db.vsidx
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/.suo
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/Browse.VC.db
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/DocumentLayout.backup.json
ÎļþÒÑɾ³ý
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/DocumentLayout.json
ÎļþÒÑɾ³ý
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/Solution.VC.db
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/26c6e6bc21719993/REVERB.ipch
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/60fac65e2eb3380b/REVERBHALLROOM.ipch
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/c6c4be2c6e03fbf/REVERB_WRAPPER.ipch
Binary files differ
cbb_RoomReverb/ReverbHallRoom/.vs/ReverbHallRoom/v17/ipch/AutoPCH/c9606fc76e9a2740/RANDOMBUFFER.ipch
Binary files differ