Skip to content
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
32 changes: 32 additions & 0 deletions scripts/dial.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--- Value.
--
-- A single control output that emits a normalized value (0.0 - 1.0). The value
-- is intended to be driven externally (host automation, MIDI mapping, etc.).
--
-- @script value
-- @type DSP
-- @license GPL v3
-- @author Michael Fisher

local function layout()
return {
audio = { 0, 0 },
midi = { 0, 0 },
control = { {}, {
{ name = "Value", symbol = "value", min = 0.0, max = 1.0, default = 0.5 }
} }
}
end

local function process (_, _, _, _)
-- Output value is driven externally; nothing to compute here.
end

return {
type = 'DSP',
layout = layout,
process = process
}

-- SPDX-FileCopyrightText: Copyright (C) Kushview, LLC.
-- SPDX-License-Identifier: GPL-3.0-or-later
66 changes: 66 additions & 0 deletions scripts/midicc.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--- MIDI CC.
--
-- Converts a normalized value (0.0 - 1.0) into a 0-127 MIDI Continuous Controller
-- value. Emits a MIDI CC message on MIDI-out and exposes the scaled value as a
-- control output. A message is only sent when the scaled value changes.
--
-- @script midicc
-- @type DSP
-- @license GPL v3
-- @author Michael Fisher

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

local output = MidiBuffer.new()
local lastValue = -1

local function layout()
return {
audio = { 0, 0 },
midi = { 0, 1 },
control = { {
{ name = "Value", symbol = "value", min = 0.0, max = 1.0, default = 0.0 },
{ name = "CC", symbol = "cc", min = 0, max = 127, default = 1 },
{ name = "Channel", symbol = "channel", min = 1, max = 16, default = 1 }
}, {
{ name = "Value", symbol = "value", min = 0, max = 127, default = 0 }
} }
}
end

local function prepare()
output:reserve (128)
output:clear()
end

local function process (_, m, p, c)
local out = m:get (1)
output:clear()

local value = round.integer (p[1] * 127)
local cc = round.integer (p[2])
local channel = round.integer (p[3])

-- Expose the scaled value as a control output.
c[1] = value

-- Only emit a message when the scaled value changes.
if value ~= lastValue then
output:insertPacked (midi.controller (channel, cc, value), 0)
lastValue = value
end

out:swap (output)
end

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

-- SPDX-FileCopyrightText: Copyright (C) Kushview, LLC.
-- SPDX-License-Identifier: GPL-3.0-or-later
72 changes: 72 additions & 0 deletions scripts/testtone.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
--- Test Tone.
-- A simple sine wave generator, handy as a signal source for checking routing,
-- levels and metering. Frequency is in Hz and Level scales the output amplitude.
--
-- @script testtone
-- @type DSP
-- @license GPL v3
-- @author Michael Fisher

-- Oscillator phase (radians) and current sample rate, kept across process blocks.
local phase = 0.0
local srate = 44100.0

local function layout()
return {
audio = { 0, 2 },
midi = { 0, 0 },
control = {{
{
name = "Frequency",
symbol = "freq",
label = "Hz",
min = 20.0,
max = 20000.0,
default = 440.0
},
{
name = "Level",
symbol = "level",
min = 0.0,
max = 1.0,
default = 0.5
}
}}
}
end

local function prepare (sampleRate, block)
srate = sampleRate
phase = 0.0
end

local function process (a, m, p)
local freq = p[1]
local level = p[2]
local nframes = a:length()
local nchans = a:channels()
local inc = (2.0 * math.pi * freq) / srate

for f = 1, nframes do
local s = level * math.sin (phase)

for c = 1, nchans do
a:set (c, f, s)
end

phase = phase + inc
if phase >= 2.0 * math.pi then
phase = phase - 2.0 * math.pi
end
end
end

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

-- SPDX-FileCopyrightText: Copyright (C) Kushview, LLC.
-- SPDX-License-Identifier: GPL-3.0-or-later
74 changes: 74 additions & 0 deletions scripts/tremolo.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
--- Tremolo.
-- Amplitude modulation driven by a sine LFO. Rate sets the modulation speed in
-- Hz and Depth controls how far the level drops at the trough of the wave.
--
-- @script tremolo
-- @type DSP
-- @license GPL v3
-- @author Michael Fisher

-- LFO phase (radians) and current sample rate, kept across process blocks.
local phase = 0.0
local srate = 44100.0

local function layout()
return {
audio = { 2, 2 },
midi = { 0, 0 },
control = {{
{
name = "Rate",
symbol = "rate",
label = "Hz",
min = 0.1,
max = 20.0,
default = 4.0
},
{
name = "Depth",
symbol = "depth",
min = 0.0,
max = 1.0,
default = 0.5
}
}}
}
end

local function prepare (sampleRate, block)
srate = sampleRate
phase = 0.0
end

local function process (a, m, p)
local freq = p[1]
local depth = p[2]
local nframes = a:length()
local nchans = a:channels()
local inc = (2.0 * math.pi * freq) / srate

for f = 1, nframes do
-- LFO ranges 0..1; gain ranges (1 - depth)..1
local lfo = 0.5 + 0.5 * math.sin (phase)
local gain = 1.0 - depth * (1.0 - lfo)

for c = 1, nchans do
a:set (c, f, a:get (c, f) * gain)
end

phase = phase + inc
if phase >= 2.0 * math.pi then
phase = phase - 2.0 * math.pi
end
end
end

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

-- SPDX-FileCopyrightText: Copyright (C) Kushview, LLC.
-- SPDX-License-Identifier: GPL-3.0-or-later
33 changes: 29 additions & 4 deletions src/nodes/scriptnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,11 @@

#include "luascripts.hpp"

#include "sol/sol.hpp"
#include "element/element.h"
#include "el/factories.hpp"
#include "engine/graphnode.hpp"
#include "nodes/scriptnode.hpp"
#include "scripting/bindings.hpp"
#include "scripting/dspscript.hpp"
#include "scripting/scriptloader.hpp"
#include "scripting/scriptmanager.hpp"

#define EL_LUA_DBG(x)
// #define EL_LUA_DBG(x) DBG(x)
Expand Down Expand Up @@ -260,6 +256,18 @@ const String ScriptNode::getProgramName (int index) const
case 3:
return "MIDI Timecode (MTC) Generator";
break;
case 4:
return "Value";
break;
case 5:
return "MIDI CC";
break;
case 6:
return "Tremolo";
break;
case 7:
return "Test Tone";
break;
}

String name = TRANS ("Program");
Expand Down Expand Up @@ -292,6 +300,23 @@ void ScriptNode::setCurrentProgram (int index)
case 3:
newDspCode = String::fromUTF8 (scripts::mtc_generator_lua, scripts::mtc_generator_luaSize);
newUiCode.clear();
break;
case 4:
newDspCode = String::fromUTF8 (scripts::dial_lua, scripts::dial_luaSize);
newUiCode.clear();
break;
case 5:
newDspCode = String::fromUTF8 (scripts::midicc_lua, scripts::midicc_luaSize);
newUiCode.clear();
break;
case 6:
newDspCode = String::fromUTF8 (scripts::tremolo_lua, scripts::tremolo_luaSize);
newUiCode.clear();
break;
case 7:
newDspCode = String::fromUTF8 (scripts::testtone_lua, scripts::testtone_luaSize);
newUiCode.clear();
break;
}

dspCode.replaceAllContent (newDspCode);
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/scriptnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ScriptNode : public Processor,
void setPlayHead (juce::AudioPlayHead*) override;

//==========================================================================
int getNumPrograms() const override { return 4; }
int getNumPrograms() const override { return 8; }
int getCurrentProgram() const override { return _program; }
const String getProgramName (int index) const override;
void setCurrentProgram (int index) override;
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_test(NAME "NodeTests" COMMAND test_element --run_test=NodeTests)
add_test(NAME "OversamplerTests" COMMAND test_element --run_test=OversamplerTests)
add_test(NAME "PluginManagerTests" COMMAND test_element --run_test=PluginManagerTests)
add_test(NAME "PortListTests" COMMAND test_element --run_test=PortListTests)
add_test(NAME "PresetScriptsTest" COMMAND test_element --run_test=PresetScriptsTest)
add_test(NAME "PortTypeTests" COMMAND test_element --run_test=PortTypeTests)
add_test(NAME "RootGraphTests" COMMAND test_element --run_test=RootGraphTests)
add_test(NAME "ScriptInfoTest" COMMAND test_element --run_test=ScriptInfoTest)
Expand Down
Loading
Loading