Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTOR] Tone stack abstraction #444

Merged
merged 5 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 14 additions & 34 deletions NeuralAmpModeler/NeuralAmpModeler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ EMsgBoxResult _ShowMessageBox(iplug::igraphics::IGraphics* pGraphics, const char
NeuralAmpModeler::NeuralAmpModeler(const InstanceInfo& info)
: Plugin(info, MakeConfig(kNumParams, kNumPresets))
{
_InitToneStack();
nam::activations::Activation::enable_fast_tanh();
GetParam(kInputLevel)->InitGain("Input", 0.0, -20.0, 20.0, 0.1);
GetParam(kToneBass)->InitDouble("Bass", 5.0, 0.0, 10.0, 0.1);
Expand Down Expand Up @@ -323,14 +324,8 @@ void NeuralAmpModeler::ProcessBlock(iplug::sample** inputs, iplug::sample** outp
sample** gateGainOutput =
noiseGateActive ? mNoiseGateGain.Process(mOutputPointers, numChannelsInternal, numFrames) : mOutputPointers;

sample** toneStackOutPointers = gateGainOutput;
if (toneStackActive)
{
sample** bassPointers = mToneBass.Process(gateGainOutput, numChannelsInternal, numFrames);
sample** midPointers = mToneMid.Process(bassPointers, numChannelsInternal, numFrames);
sample** treblePointers = mToneTreble.Process(midPointers, numChannelsInternal, numFrames);
toneStackOutPointers = treblePointers;
}
sample** toneStackOutPointers = (toneStackActive && mToneStack != nullptr) ? mToneStack->Process(gateGainOutput, numChannelsInternal, numFrames)
: gateGainOutput;

sample** irPointers = toneStackOutPointers;
if (mIR != nullptr && GetParam(kIRToggle)->Value())
Expand Down Expand Up @@ -361,6 +356,8 @@ void NeuralAmpModeler::ProcessBlock(iplug::sample** inputs, iplug::sample** outp
void NeuralAmpModeler::OnReset()
{
const auto sampleRate = GetSampleRate();
const int maxBlockSize = GetBlockSize();

// Tail is because the HPF DC blocker has a decay.
// 10 cycles should be enough to pass the VST3 tests checking tail behavior.
// I'm ignoring the model & IR, but it's not the end of the world.
Expand All @@ -371,6 +368,7 @@ void NeuralAmpModeler::OnReset()
mCheckSampleRateWarning = true;
// If there is a model or IR loaded, they need to be checked for resampling.
_ResetModelAndIR(sampleRate, GetBlockSize());
mToneStack->Reset(sampleRate, maxBlockSize);
}

void NeuralAmpModeler::OnIdle()
Expand Down Expand Up @@ -443,36 +441,13 @@ void NeuralAmpModeler::OnParamChange(int paramIdx)
switch (paramIdx)
{
case kToneBass:
{
const double sampleRate = GetSampleRate();
const double bassGainDB = 4.0 * (GetParam(kToneBass)->Value() - 5.0); // +/- 20
const double bassFrequency = 150.0;
const double bassQuality = 0.707;
recursive_linear_filter::BiquadParams bassParams(sampleRate, bassFrequency, bassQuality, bassGainDB);
mToneBass.SetParams(bassParams);
}

mToneStack->SetParam("bass", GetParam(paramIdx)->Value());
break;
case kToneMid:
{
const double sampleRate = GetSampleRate();
const double midGainDB = 3.0 * (GetParam(kToneMid)->Value() - 5.0); // +/- 15
const double midFrequency = 425.0;
// Wider EQ on mid bump up to sound less honky.
const double midQuality = midGainDB < 0.0 ? 1.5 : 0.7;
recursive_linear_filter::BiquadParams midParams(sampleRate, midFrequency, midQuality, midGainDB);
mToneMid.SetParams(midParams);
}
mToneStack->SetParam("middle", GetParam(paramIdx)->Value());
break;
case kToneTreble:
{
const double sampleRate = GetSampleRate();
const double trebleGainDB = 2.0 * (GetParam(kToneTreble)->Value() - 5.0); // +/- 10
const double trebleFrequency = 1800.0;
const double trebleQuality = 0.707;
recursive_linear_filter::BiquadParams trebleParams(sampleRate, trebleFrequency, trebleQuality, trebleGainDB);
mToneTreble.SetParams(trebleParams);
}
mToneStack->SetParam("treble", GetParam(paramIdx)->Value());
break;
default: break;
}
Expand Down Expand Up @@ -751,6 +726,11 @@ size_t NeuralAmpModeler::_GetBufferNumFrames() const
return mInputArray[0].size();
}

void NeuralAmpModeler::_InitToneStack()
{
// If you want to customize the tone stack, then put it here!
mToneStack = std::make_unique<dsp::tone_stack::BasicNamToneStack>();
}
void NeuralAmpModeler::_PrepareBuffers(const size_t numChannels, const size_t numFrames)
{
const bool updateChannels = numChannels != _GetBufferNumChannels();
Expand Down
8 changes: 4 additions & 4 deletions NeuralAmpModeler/NeuralAmpModeler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
#include "NeuralAmpModelerCore/NAM/dsp.h"
#include "AudioDSPTools/dsp/ImpulseResponse.h"
#include "AudioDSPTools/dsp/NoiseGate.h"
#include "AudioDSPTools/dsp/RecursiveLinearFilter.h"
#include "AudioDSPTools/dsp/dsp.h"
#include "AudioDSPTools/dsp/wav.h"
#include "AudioDSPTools/dsp/ResamplingContainer/ResamplingContainer.h"

#include "ToneStack.h"

#include "IPlug_include_in_plug_hdr.h"
#include "ISender.h"

Expand Down Expand Up @@ -238,6 +239,7 @@ class NeuralAmpModeler final : public iplug::Plugin
// Sizes based on mInputArray
size_t _GetBufferNumChannels() const;
size_t _GetBufferNumFrames() const;
void _InitToneStack();
// Apply the normalization for the model output (if possible)
void _NormalizeModelOutput(iplug::sample** buffer, const size_t numChannels, const size_t numFrames);
// Loads a NAM model and stores it to mStagedNAM
Expand Down Expand Up @@ -300,9 +302,7 @@ class NeuralAmpModeler final : public iplug::Plugin
std::atomic<bool> mCheckSampleRateWarning = true;

// Tone stack modules
recursive_linear_filter::LowShelf mToneBass;
recursive_linear_filter::Peaking mToneMid;
recursive_linear_filter::HighShelf mToneTreble;
std::unique_ptr<dsp::tone_stack::AbstractToneStack> mToneStack;

// Post-IR filters
recursive_linear_filter::HighPass mHighPass;
Expand Down
58 changes: 58 additions & 0 deletions NeuralAmpModeler/ToneStack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "ToneStack.h"

DSP_SAMPLE** dsp::tone_stack::BasicNamToneStack::Process(DSP_SAMPLE** inputs, const int numChannels,
const int numFrames)
{
DSP_SAMPLE** bassPointers = mToneBass.Process(inputs, numChannels, numFrames);
DSP_SAMPLE** midPointers = mToneMid.Process(bassPointers, numChannels, numFrames);
DSP_SAMPLE** treblePointers = mToneTreble.Process(midPointers, numChannels, numFrames);
return treblePointers;
}

void dsp::tone_stack::BasicNamToneStack::Reset(const double sampleRate, const int maxBlockSize)
{
dsp::tone_stack::AbstractToneStack::Reset(sampleRate, maxBlockSize);

// Refresh the params!
SetParam("bass", mBassVal);
SetParam("middle", mMiddleVal);
SetParam("treble", mTrebleVal);
}

void dsp::tone_stack::BasicNamToneStack::SetParam(const std::string name, const double val)
{
if (name == "bass")
{
// HACK: Store for refresh
mBassVal = val;
const double sampleRate = GetSampleRate();
const double bassGainDB = 4.0 * (val - 5.0); // +/- 20
const double bassFrequency = 150.0;
const double bassQuality = 0.707;
recursive_linear_filter::BiquadParams bassParams(sampleRate, bassFrequency, bassQuality, bassGainDB);
mToneBass.SetParams(bassParams);
}
else if (name == "middle")
{
// HACK: Store for refresh
mMiddleVal = val;
const double sampleRate = GetSampleRate();
const double midGainDB = 3.0 * (val - 5.0); // +/- 15
const double midFrequency = 425.0;
// Wider EQ on mid bump up to sound less honky.
const double midQuality = midGainDB < 0.0 ? 1.5 : 0.7;
recursive_linear_filter::BiquadParams midParams(sampleRate, midFrequency, midQuality, midGainDB);
mToneMid.SetParams(midParams);
}
else if (name == "treble")
{
// HACK: Store for refresh
mTrebleVal = val;
const double sampleRate = GetSampleRate();
const double trebleGainDB = 2.0 * (val - 5.0); // +/- 10
const double trebleFrequency = 1800.0;
const double trebleQuality = 0.707;
recursive_linear_filter::BiquadParams trebleParams(sampleRate, trebleFrequency, trebleQuality, trebleGainDB);
mToneTreble.SetParams(trebleParams);
}
}
60 changes: 60 additions & 0 deletions NeuralAmpModeler/ToneStack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

#include <string>
#include "AudioDSPTools/dsp/dsp.h"
#include "AudioDSPTools/dsp/RecursiveLinearFilter.h"

namespace dsp
{
namespace tone_stack
{
class AbstractToneStack
{
public:
// Compute in the real-time loop
virtual DSP_SAMPLE** Process(DSP_SAMPLE** inputs, const int numChannels, const int numFrames) = 0;
// Any preparation. Call from Reset() in the plugin
virtual void Reset(const double sampleRate, const int maxBlockSize)
{
mSampleRate = sampleRate;
mMaxBlockSize = maxBlockSize;
};
// Set the various parameters of your tone stack by name.
// Call this during OnParamChange()
virtual void SetParam(const std::string name, const double val) = 0;

protected:
double GetSampleRate() const { return mSampleRate; };
double mSampleRate = 0.0;
int mMaxBlockSize = 0;
};

class BasicNamToneStack : public AbstractToneStack
{
public:
BasicNamToneStack()
{
SetParam("bass", 5.0);
SetParam("middle", 5.0);
SetParam("treble", 5.0);
};
~BasicNamToneStack() = default;

DSP_SAMPLE** Process(DSP_SAMPLE** inputs, const int numChannels, const int numFrames);
virtual void Reset(const double sampleRate, const int maxBlockSize) override;
// :param val: Assumed to be between 0 and 10, 5 is "noon"
void SetParam(const std::string name, const double val);


protected:
recursive_linear_filter::LowShelf mToneBass;
recursive_linear_filter::Peaking mToneMid;
recursive_linear_filter::HighShelf mToneTreble;

// HACK not DRY w knob defs
double mBassVal = 5.0;
double mMiddleVal = 5.0;
double mTrebleVal = 5.0;
};
}; // namespace tone_stack
}; // namespace dsp
2 changes: 2 additions & 0 deletions NeuralAmpModeler/projects/NeuralAmpModeler-aax.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@
<ClCompile Include="..\NeuralAmpModelerCore\NAM\lstm.cpp" />
<ClCompile Include="..\NeuralAmpModelerCore\NAM\util.cpp" />
<ClCompile Include="..\NeuralAmpModelerCore\NAM\wavenet.cpp" />
<ClCompile Include="..\ToneStack.cpp" />
</ItemGroup>
<ItemGroup>
<CustomBuildStep Include="..\..\AAX_SDK\Libs\Release\AAXLibrary.lib">
Expand Down Expand Up @@ -534,6 +535,7 @@
<ClInclude Include="..\NeuralAmpModelerCore\NAM\version.h" />
<ClInclude Include="..\NeuralAmpModelerCore\NAM\wavenet.h" />
<ClInclude Include="..\resources\resource.h" />
<ClInclude Include="..\ToneStack.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\resources\main.rc" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
<ClCompile Include="..\AudioDSPTools\dsp\wav.cpp">
<Filter>dsp</Filter>
</ClCompile>
<ClCompile Include="..\ToneStack.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\resources\resource.h">
Expand Down Expand Up @@ -311,6 +312,7 @@
<ClInclude Include="..\AudioDSPTools\dsp\ResamplingContainer\Dependencies\WDL\wdltypes.h">
<Filter>dsp\ResamplingContainer\Dependencies\WDL</Filter>
</ClInclude>
<ClInclude Include="..\ToneStack.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="resources">
Expand Down
2 changes: 2 additions & 0 deletions NeuralAmpModeler/projects/NeuralAmpModeler-app.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@
<ClInclude Include="..\NeuralAmpModelerCore\NAM\version.h" />
<ClInclude Include="..\NeuralAmpModelerCore\NAM\wavenet.h" />
<ClInclude Include="..\resources\resource.h" />
<ClInclude Include="..\ToneStack.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\iPlug2\Dependencies\IPlug\RTAudio\include\asio.cpp" />
Expand Down Expand Up @@ -403,6 +404,7 @@
<ClCompile Include="..\NeuralAmpModelerCore\NAM\lstm.cpp" />
<ClCompile Include="..\NeuralAmpModelerCore\NAM\util.cpp" />
<ClCompile Include="..\NeuralAmpModelerCore\NAM\wavenet.cpp" />
<ClCompile Include="..\ToneStack.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\resources\main.rc" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<ClCompile Include="..\AudioDSPTools\dsp\wav.cpp">
<Filter>dsp</Filter>
</ClCompile>
<ClCompile Include="..\ToneStack.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\NeuralAmpModeler.h" />
Expand Down Expand Up @@ -359,6 +360,7 @@
<ClInclude Include="..\AudioDSPTools\dsp\ResamplingContainer\Dependencies\WDL\wdltypes.h">
<Filter>dsp\ResamplingContainer\Dependencies\WDL</Filter>
</ClInclude>
<ClInclude Include="..\ToneStack.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="resources">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
4FE0DEE829A183B700DDBCC8 /* NeuralAmpModelerAU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4FC6982F293BA47F0076EC33 /* NeuralAmpModelerAU.framework */; };
4FE0DEF029A2E0F100DDBCC8 /* IPlugAUViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4FFF105A20A0E57100D3092F /* IPlugAUViewController.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
91236D811B08F59300734C5E /* NeuralAmpModelerAppExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 91236D771B08F59300734C5E /* NeuralAmpModelerAppExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
AA341E2B2B9E5A650069C260 /* ToneStack.h in Headers */ = {isa = PBXBuildFile; fileRef = AA341E292B9E5A650069C260 /* ToneStack.h */; };
AA341E2C2B9E5A650069C260 /* ToneStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA341E2A2B9E5A650069C260 /* ToneStack.cpp */; };
AA341E2D2B9E5A650069C260 /* ToneStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA341E2A2B9E5A650069C260 /* ToneStack.cpp */; };
AA341E2E2B9E5A650069C260 /* ToneStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA341E2A2B9E5A650069C260 /* ToneStack.cpp */; };
AA7C860B2B43A42F00B5FB3A /* ResamplingContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7C86042B43A42E00B5FB3A /* ResamplingContainer.h */; };
AA7C860C2B43A42F00B5FB3A /* LanczosResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7C86062B43A42E00B5FB3A /* LanczosResampler.h */; };
AA7C860D2B43A42F00B5FB3A /* wdltypes.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7C86082B43A42E00B5FB3A /* wdltypes.h */; };
Expand Down Expand Up @@ -341,6 +345,8 @@
4FFF108820A1036200D3092F /* NeuralAmpModeler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NeuralAmpModeler.h; path = ../NeuralAmpModeler.h; sourceTree = "<group>"; };
91236D0D1B08F42B00734C5E /* NeuralAmpModeler.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NeuralAmpModeler.app; sourceTree = BUILT_PRODUCTS_DIR; };
91236D771B08F59300734C5E /* NeuralAmpModelerAppExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NeuralAmpModelerAppExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
AA341E292B9E5A650069C260 /* ToneStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToneStack.h; path = ../ToneStack.h; sourceTree = "<group>"; };
AA341E2A2B9E5A650069C260 /* ToneStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToneStack.cpp; path = ../ToneStack.cpp; sourceTree = "<group>"; };
AA7C86042B43A42E00B5FB3A /* ResamplingContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResamplingContainer.h; sourceTree = "<group>"; };
AA7C86062B43A42E00B5FB3A /* LanczosResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LanczosResampler.h; sourceTree = "<group>"; };
AA7C86082B43A42E00B5FB3A /* wdltypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wdltypes.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -753,6 +759,8 @@
4FFF108820A1036200D3092F /* NeuralAmpModeler.h */,
4FFF108720A1036200D3092F /* NeuralAmpModeler.cpp */,
4F9979242A066F960066545C /* NeuralAmpModelerControls.h */,
AA341E2A2B9E5A650069C260 /* ToneStack.cpp */,
AA341E292B9E5A650069C260 /* ToneStack.h */,
4F8D8BD82316701900EFA1FB /* README.md */,
4F8BF48D20A12D2E0081DF0A /* Resources */,
4F67D51620A121F60061FB8E /* Other Sources */,
Expand Down Expand Up @@ -824,6 +832,7 @@
4FBDC95E29FFF143004FF203 /* wavenet.h in Headers */,
4FC6983B293BA5020076EC33 /* IPlugAUAudioUnit.h in Headers */,
AA7C860B2B43A42F00B5FB3A /* ResamplingContainer.h in Headers */,
AA341E2B2B9E5A650069C260 /* ToneStack.h in Headers */,
4FBDC95B29FFF143004FF203 /* convnet.h in Headers */,
4FBDC95929FFF143004FF203 /* version.h in Headers */,
AA7C860C2B43A42F00B5FB3A /* LanczosResampler.h in Headers */,
Expand Down Expand Up @@ -1052,6 +1061,7 @@
4FC69840293BA5C40076EC33 /* IPlugPluginBase.cpp in Sources */,
4FC6984A293BA5F90076EC33 /* IGraphics.cpp in Sources */,
4FBDC95229FFF143004FF203 /* NoiseGate.cpp in Sources */,
AA341E2E2B9E5A650069C260 /* ToneStack.cpp in Sources */,
4FC69841293BA5C40076EC33 /* IPlugAPIBase.cpp in Sources */,
4FC69842293BA5C50076EC33 /* IPlugProcessor.cpp in Sources */,
4FC69846293BA5F90076EC33 /* IGraphicsEditorDelegate.cpp in Sources */,
Expand All @@ -1071,6 +1081,7 @@
buildActionMask = 2147483647;
files = (
4FDF6D7F2267CEBA0007B686 /* IPlugAUPlayer.mm in Sources */,
AA341E2C2B9E5A650069C260 /* ToneStack.cpp in Sources */,
4FDF6D7B2267CE540007B686 /* AppDelegate.m in Sources */,
4FDF6D772267CE540007B686 /* AppViewController.mm in Sources */,
4FDF6D792267CE540007B686 /* main.m in Sources */,
Expand All @@ -1082,6 +1093,7 @@
buildActionMask = 2147483647;
files = (
4FCBE769293CDFB7005D913D /* IPlugAUViewController.mm in Sources */,
AA341E2D2B9E5A650069C260 /* ToneStack.cpp in Sources */,
4F4856842773BD77005BCF8E /* NeuralAmpModelerAUv3Appex.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Loading
Loading