Making mono lua plugin stereo, with a.i

A discussion on linuxmusicians led to the script pasted on this page SWH-LV2 for Windows? which is a lua version of barry satan’s maximiser.

This is a mono plugin (as is the original). It only affects the left side on a stereo track. To use on the right side as well, it’s needed to add another instance of the plugin and bypass with the pin connections. I don’t know lua scripting, so I asked a.i. to make me a stereo version and it gave me this:

ardour {
    ["type"] = "dsp",
    name = "Beelzebub Maximizer (Stereo)",
    category = "Dynamics",
    license = "MIT",
    author = "Ardour Team",
    description = [[Barry's Satan Maximizer — Stereo version]]
}

-- I/O configuration: 2 inputs, 2 outputs
function dsp_ioconfig ()
    return { { audio_in = 2, audio_out = 2 } }
end

-- Parameters
function dsp_params ()
    return {
        { ["type"] = "input", name = "Decay time (samples)", min = 2, max = 30, default = 30 },
        { ["type"] = "input", name = "Knee Point (dB)", min = -90, max = 0, default = 0, logarithmic = true },
    }
end

-- Initialization
function dsp_init (rate)
    self:shmem ():allocate (32)  -- 16 samples buffer per channel
end

-- State variables for each channel
local env = { 0, 0 }
local pos = { 0, 0 }

function dsp_run (ins, outs, n_samples)
    local ctrl = CtrlPorts:array ()
    local env_time = ctrl[1]
    local knee = ARDOUR.DSP.dB_to_coefficient(ctrl[2])

    local delay = math.floor(0.5 + env_time * 0.5)
    local env_tr = 1.0 / env_time

    local b = self:shmem():to_float(0):array()

    -- process each channel separately
    for ch = 1, 2 do
        local i = ins[ch]:array()
        local o = outs[ch]:array()
        local env_ch = env[ch]
        local pos_ch = pos[ch]
        local base = (ch - 1) * 16  -- channel offset in shared memory buffer

        for s = 1, n_samples do
            local f = math.abs(i[s])
            if f > env_ch then
                env_ch = f
            else
                env_ch = f * env_tr + env_ch * (1 - env_tr)
            end

            local env_sc
            if env_ch <= knee then
                env_sc = 1 / knee
            else
                env_sc = 1 / env_ch
            end

            -- store sample in per-channel circular buffer
            b[1 + base + pos_ch] = i[s]
            local idx = (16 + pos_ch - delay) & 15
            o[s] = b[1 + base + idx] * env_sc

            pos_ch = (pos_ch + 1) & 15
        end

        env[ch] = env_ch
        pos[ch] = pos_ch
    end
end

I tested it and it nulls with the original plugin. Is there anything in this code that shouldn’t be there, could cause a problem or is in any other way bad?

Great stuff @Largos!!

@x42 Could these be added to the ACE or Ardour Team collection? I know you want Plugins that are immutable and don’t need maintaining but the SWH Barry’s Satan Maximizer DSP goes all the way back to the infancy of Linux Audio, it wouldn’t need maintaining and to this day this is one of the most useful percussion Plugins in Linuxdom IMHO, almost every project I’ve ever done has at least one instance of it… It’s also magical for waking up acoustic pianos… Forget pitch correction… comically crude compression is where it’s at!!

The AI gave you a dual mono version of the plugin.

For a dynamics plugin you’ usually use the same gain factor for both channels. This maximizer is really a compressor/limiter on steroids (super fast attack, infinite ratio), so ideally it should also behave like a stereo version.

Lua scripts can have dynamic I/O, so one could generalize it for any number of channels (not just two).

The original C version is significantly faster (needs much less CPU). Doing per-sample processing directly in Lua isn’t very efficient, so It’d rather not ship it with the official binary.

Could the original version be added ?

You can get it from swh.

Ideally we ship as little plugins as possible with Ardour itself (just basic bread/butter), and not tie plugin release cycles with Ardour releases. Besides, “Barry’s Satan Maximiser” is also a rather obscure thing to include…

The reason the lua version came up in conversation was because there are a lot of crappy speaker shredders in SWH collection.

1 Like

FWIW…

I requested this Plugin in a falkTX collection that I don’t think was ever released:

I believe the Devil’s Distortion is the BSM DSP, I could be wrong tho…

The reason I did this was because @GMaq included swh plugins in the beta release of AV Linux. I tested them and (as he just typed whilst I was typing this) found that some of them create a massive audio spike when moving the parameters. I thought I’d try and get him one plugin back since he’s removed both that and the calf plugins. :smile:

Hopefully in the long term, someone can make a standalone version of the maximiser and have it stereo, it may sound even better.

1 Like

PS. you can find a multi-channel version:

No AI resources were used to create this.

7 Likes

I probably couldn’t see a case for LuaJIT to be used either, despite it being way faster than any other compiler so I’ve heard. Maybe I’m wrong, though.

For DSP you want to vectorize the inner loop, and ideally use SSE, AVX, FMA or similar floating point instructions. LuaJIT isn’t any help there.

Most of the other Lua DSP scripts call Ardour provided C/C++ functions to do the heavy lifting, and Lua is only used as glue.