Example Scripts

Amplifier

amp.lua
--- Stereo Amplifier in Lua.
--
-- The code contained implements a simple stereo amplifier plugin. It does not
-- try to smooth the volume parameter and could cause zipper noise.
--
-- @script      amp
-- @type        DSP
-- @license     GPL v3
-- @author      Michael Fisher

local audio  = require ('el.audio')

--- Gain parameters.
-- Used for fading between changes in volume
local gain1 = 1.0
local gain2 = 1.0

--- Return a table of audio/midi inputs and outputs.
-- This plugin supports stereo in/out with no MIDI
local function amp_layout()
    return {
        audio   = { 2, 2 },
        midi    = { 0, 0 },
        control = {{
            {
                name        = "Volume",
                symbol      = "volume",
                label       = "dB",
                min         = -90.0,
                max         = 24.0,
                default     = 0.0
            }
        }}
    }
end

--- Render audio and midi.
-- Use the provided audio and midi objects to process your plugin
-- @param a The source el.AudioBuffer
-- @param m The source el.MidiPipe
-- @param p Parameters
-- @param c Controls
-- @param t Time info
local function amp_process (a, m, p, c, t)
    gain2 = audio.togain (p [1])
    a:fade (gain1, gain2)
    gain1 = gain2
end

return {
    type        = 'DSP',
    layout      = amp_layout,
    parameters  = amp_parameters,
    process     = amp_process
}

Amplifier UI

ampui.lua
--- Editor for `amp` DSP script.
-- @script ampui
-- @type DSPUI amp

local Widget        = require ('el.Widget')
local Slider        = require ('el.Slider')
local object        = require ('el.object')
local script        = require ('el.script')

local bgcolor       = 0xff545454
local fgcolor       = 0xffffffff

-- Derive a new widget type for the amp editor.
local Editor = object (Widget)

function Editor:init (ctx)
    -- Invoke the parent class' init method
    Widget.init (self)

    local volume = ctx.params [1]

    self.knob = self:add (object.new (Slider))
    self.knob.style = Slider.Rotary
    self.knob:setTextBoxStyle (Slider.TextBoxBelow, true, 52, 26)
    self.knob:setRange (-90, 24, 0.01)
    self.knob:setValue (volume:get(), false)
    self.knob.dragging  = false
    self.knob.dragStart = function() self.knob.dragging = true end
    self.knob.dragEnd   = function() self.knob.dragging = false end
    self.knob.changed   = function()
        if not self.knob.dragging then return end
        volume:set (self.knob:value(), false)
    end

    volume.changed = function()
        self.knob:setValue (volume:get(), false)
    end

    self:resize (180, 170)
end

function Editor:paint (g)
    g:fillAll (bgcolor)
    g:setColor (fgcolor)
    g:drawText ("AMP", 0, 0, self.width, 30)
end

function Editor:resized()
    local r = self:localBounds()
    self.knob:setBounds (r:reduced (20))
end

-- Editor factory function.
local function instantiate (ctx)
    return object.new (Editor, ctx)
end

return {
    type        = 'DSPUI',
    instantiate = instantiate
}

MIDI Filter

channelize.lua
--- MIDI Channelizer.
--
-- This is a MIDI filter which forces a specified channel on all messages. Set
-- the channel parameter to '0' to bypass the filter.
--
-- @script      channelize
-- @type        DSP
-- @license     GPL v3
-- @author      Michael Fisher

local MidiBuffer    = require ('el.MidiBuffer')
local script        = require ('el.script')
local round         = require ('el.round')

-- Buffer to render filtered output
local output        = MidiBuffer.new()

local function layout()
    return {
        audio       = { 0, 0 },
        midi        = { 1, 1 },
        control     = {{
            {
                name        = "Channel",
                symbol      = "channel",
                min         = 0,
                max         = 16,
                default     = 0
            }
        }}
    }
end

-- prepare for rendering
local function prepare()
    -- reserve 128 bytes of memory and clear the output buffer
    output:reserve (128)
    output:clear()
end

local function process (_, m, p)
    -- Get MIDI input buffer fromt the MidiPipe
    local input = m:get (1)

    -- Get the channel number from the parameter array, and round to integer
    local channel = round.integer (p[1])

    -- For each input message, set the specified channel
    output:clear()
    for msg, frame in input:messages() do
        if channel > 0 and msg:channel() > 0 then
            msg:setChannel (channel)
        end
        output:insert (msg, frame)
    end

    -- DSP scripts use replace processing, so swap in the rendered output
    input:swap (output)
end

return {
    type        = 'DSP',
    layout      = layout,
    parameters  = parameters,
    prepare     = prepare,
    process     = process,
    release     = release
}