Skip to content
Open
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
19 changes: 15 additions & 4 deletions NeuralAmpModeler/NeuralAmpModeler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,14 +409,24 @@ void NeuralAmpModeler::OnReset()
SetTailSize(tailCycles * (int)(sampleRate / kDCBlockerFrequency));
mInputSender.Reset(sampleRate);
mOutputSender.Reset(sampleRate);
// If there is a model or IR loaded, they need to be checked for resampling.
_ResetModelAndIR(sampleRate, GetBlockSize());
// Only reset the model when the format actually changed. iPlug2 also calls OnReset() in
// response to kAudioUnitProperty_BypassEffect (the AU bypass / power-button toggle), which
// would trigger prewarm() on the audio thread and cause an audible dropout. Sample rate and
// block size are unchanged on a bypass toggle, so skipping _ResetModelAndIR() is safe there.
if (sampleRate != mLastResetSampleRate || maxBlockSize != mLastResetBlockSize)
{
_ResetModelAndIR(sampleRate, maxBlockSize);
mLastResetSampleRate = sampleRate;
mLastResetBlockSize = maxBlockSize;
}
mToneStack->Reset(sampleRate, maxBlockSize);
_UpdateLatency();
}

void NeuralAmpModeler::OnIdle()
{
delete mModelPendingDeletion.exchange(nullptr, std::memory_order_acquire);

mInputSender.TransmitData(*this);
mOutputSender.TransmitData(*this);

Expand Down Expand Up @@ -597,7 +607,7 @@ void NeuralAmpModeler::_ApplyDSPStaging()
// Remove marked modules
if (mShouldRemoveModel)
{
mModel = nullptr;
mModelPendingDeletion.store(mModel.release(), std::memory_order_release);
mNAMPath.Set("");
mShouldRemoveModel = false;
mModelCleared = true;
Expand All @@ -614,8 +624,9 @@ void NeuralAmpModeler::_ApplyDSPStaging()
// Move things from staged to live
if (mStagedModel != nullptr)
{
ResamplingNAM* old = mModel.release();
mModel = std::move(mStagedModel);
mStagedModel = nullptr;
mModelPendingDeletion.store(old, std::memory_order_release);
mNewModelLoadedInDSP = true;
_UpdateLatency();
_SetInputGain();
Expand Down
8 changes: 8 additions & 0 deletions NeuralAmpModeler/NeuralAmpModeler.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ class NeuralAmpModeler final : public iplug::Plugin

std::atomic<bool> mNewModelLoadedInDSP = false;
std::atomic<bool> mModelCleared = false;
// Holds a model evicted from mModel that must be deleted on the UI thread (OnIdle) rather
// than the audio thread, to avoid freeing large Eigen weight matrices inside ProcessBlock
// and causing a buffer-deadline miss.
std::atomic<ResamplingNAM*> mModelPendingDeletion{nullptr};

// Last format seen by OnReset(). Used to guard _ResetModelAndIR() — see OnReset() for rationale.
double mLastResetSampleRate{0.0};
int mLastResetBlockSize{0};

// Tone stack modules
std::unique_ptr<dsp::tone_stack::AbstractToneStack> mToneStack;
Expand Down