Plugin Development
12 min readIntermediateJanuary 5, 2026

The Beautiful Mess
What We Learned Building Plugins That Don't Suck

Or: How I learned to stop worrying and love the segfault

Plugin DevelopmentThread SafetyADAAPerformanceWar Stories

Look, I'm not going to sugarcoat this: Building audio plugins that actual professionals want to use is like trying to juggle chainsaws while riding a unicycle. On fire. In the dark.

But here's the thing: it's also one of the most rewarding things you can do as a, you know, founder/designer/developer type person. And our community? You folks are simultaneously the best and worst thing about this job.

The Thread Safety Rabbit Hole

Remember when we thought "just slap a mutex on it" was a valid threading strategy? Yeah, good times. Turns out, locking in an audio callback is like bringing a kazoo to a symphony orchestra—technically music, but everyone's going to hate you.

We learned this the hard way with AlterOne's pitch shifter. Version 0.1 had this beautiful, elegant design where the UI thread could update DSP parameters whenever it felt like it. Worked great... until it didn't. Users started reporting random clicks and pops that we couldn't reproduce. Classic heisenbug territory.

Turns out, when you're processing audio at 48kHz with a 512-sample buffer, you've got about 10 milliseconds to do your thing. That's it. Any lock contention, any memory allocation, any "I'll just quickly check this one thing" moment—and boom, you're staring at an XRUN. The DAW glitches. The engineer screams. The cat jumps off the desk.

The Fix: Atomic Operations

// Before: "It'll be fine"

void processBlock(AudioBuffer& buffer) {
    mutex.lock();  // <- narrator: it was not fine
    float gain = parameters.gain;
    mutex.unlock();
    // ... process ...
}

// After: Actually fine

void processBlock(AudioBuffer& buffer) {
    ScopedNoDenormals noDenormals;
    float gain = gainParam->load();  // atomic read, no locks
    // ... process ...
}

Everything between threads happens through std::atomic parameters. The audio thread reads, never writes to shared state (except meters). The UI thread writes, never blocks. Zero locks. Zero blocking. Zero drama.

Zero locks. Zero blocking. Zero drama.

The Aliasing Wars

You know what nobody tells you about DSP? That beautiful, mathematically pure std::tanh() saturation you're so proud of? It's spewing aliasing artifacts all over your frequency spectrum like a sprinkler at a fancy garden party.

We discovered this during LihisSplattener development. The plugin sounded "okay" on 808 kicks and vocal stems, but run it on high-frequency content like hi-hats or cymbals, and it was like listening through a cheese grater.

The Oversampling Trap

Our first instinct? "Let's just oversample everything!" 4x oversampling, problem solved, ship it.

Except now the CPU usage was through the roof. Turns out, oversampling the entire signal chain—including linear processes like input gain and EQ—is like hiring a Formula 1 pit crew to change the batteries in your TV remote. Technically effective, hilariously wasteful.

Enter ADAA

The real breakthrough came when we discovered Antiderivative Anti-Aliasing (ADAA). Instead of brute-force oversampling, you analytically solve for the antiderivative of your nonlinear function and use calculus to get alias-free output.

ADAA in Action

// F(x) is the antiderivative of your nonlinearity
// For tanh(x), F(x) = log(cosh(x))
float process(float x) {
    if (abs(x - x1) < tolerance) {
        return tanh(0.5f * (x + x1));
    }
    // ADAA: (F(x) - F(x1)) / (x - x1)
    float y = (logCosh(x) - logCosh(x1)) / (x - x1);
    x1 = x;
    return y;
}

The result? Clean saturation at any sample rate, with CPU usage lower than oversampling. Our plugins now sound great at 44.1kHz and sublime at 192kHz, without requiring a NASA supercomputer.

Smart Oversampling Architecture

Oversample only what needs it. Save CPU. Sound better.

The "It Works On My Machine" Syndrome

Here's a fun game: build a plugin on your Mac, test it in Logic Pro, think you're golden. Then watch it crash three different ways in Ableton Live, behave weirdly in Reaper, and refuse to load in FL Studio.

Welcome to plugin development, where every DAW is its own special snowflake with its own interpretations of the VST3 spec.

The pluginval Savior

The turning point was when we started treating pluginval not as an optional suggestion but as a gate that must be passed. Level 10. No exceptions.

This tool stress-tests your plugin in ways you'd never think of:

  • Loads and unloads it 100 times in a row
  • Randomizes parameters at audio rate
  • Changes sample rates and buffer sizes mid-stream
  • Tests state save/restore with every permutation

The first time we ran it on AlterOne, it found 14 issues. Things we'd never have caught in manual testing.

Quality Gates Pipeline

No shortcuts. No exceptions. No regressions.

The Performance Obsession

"Your plugin uses 1.2% CPU at 48kHz."

That sentence might sound meaningless to a web developer, but in audio plugin land, it's the difference between a tool that ships and one that collects dust.

Why? Because professional producers don't use one instance of your plugin. They use ten. Fifteen. Thirty-seven. If each one used even 3% CPU, that project would be unplayable.

Our Target

< 1% CPU per instance at 48kHz on an M1 MacBook Air

Not Pro. Not Max. The Air—because if it runs well there, it'll run anywhere.

• No allocations in the audio thread. Period. Everything pre-allocated in prepareToPlay().

• SIMD where it matters. Not everywhere, just the hot paths that actually show up in profiling.

• Smart oversampling. Only the nonlinear stages, not the whole chain.

• Efficient algorithms. Sometimes the mathematically elegant solution isn't the performant one.

Performance Optimization Strategy

Profile. Optimize. Benchmark. Repeat.

Why We Do This (The Mushy Bit)

So why put ourselves through this? Why spend months chasing down sub-1% CPU targets and hunting denormal numbers at 3am?

Because when it works—when a user loads your plugin and immediately gets the sound they heard in their head—there's nothing quite like it.

We get messages like:

"AlterOne saved my vocal stem. I was about to scrap the whole track."

"LihisSplattener made my 808s hit harder than they ever have."

"Your plugins just... work. I don't think about them. They're invisible tools that do exactly what I need."

That last one might be the highest compliment. When your plugin becomes invisible—when it's not the thing the user thinks about, but the tool that lets them think about their music—you've won.

What's Next

We're not done. Not even close.

There are aliasing artifacts still lurking in corner cases. Performance optimizations waiting to be discovered. UI improvements that'll make workflows faster. New DSP algorithms we're dying to implement.

And honestly? That's the fun part. Each plugin is a puzzle. Each optimization is a challenge. Each user request is a hint at what's possible.

So yeah, building industry-leading plugins is hard. It's frustrating. It's occasionally soul-crushing.

But when you nail it? When you ship something that just works, that sounds beautiful, that becomes an invisible tool in someone's creative process?

Worth every segfault.

Related Articles

Written by The KnobSmith Audio Team · January 5, 2026

We use optional analytics cookies to understand site usage. You can accept or reject. See our Privacy Policy.