Protoplug

Variable-hardness clipping, de Soras assumes a maximum power value of 100, maximum is 1000 :slight_smile: , try with 0-100 first.

--[[
name: Variable-hardness clipping
author: Laurent de Soras / J.R.
url: http://musicdsp.org/showone.php?id=104
--]]
require "include/protoplug"

local power
local gain
local gain2
local mix

stereoFx.init ()
function stereoFx.Channel:init ()
    -- create per-channel fields (filters)
end

function stereoFx.Channel:processBlock (samples, smax)
    for i = 0, smax do
    	
        local x = samples[i] * (1/gain)
        local neg = 1
        if (x<0) then neg = -1; x = -x; end
              
        x = math.pow (math.atan (math.pow (math.abs (x), power)), (1 / power)) * gain * gain2      
              
        if (x>1) then x=1; end

        samples[i] = x * neg * mix + samples[i] * (1-mix)
  
    end
end

params = plugin.manageParams {
    {
        name = "Strength";
        min = 1;
        max = 1000;
        changed = function (val) power = val; end;
    };
    {
        name = "Threshold";
        min = 0;
        max = 1;
        changed = function (val) gain = (1-(val*0.99)); end;
    };
    {
        name = "Gain";
        min = 0;
        max = 2;
        default = 1;
        changed = function (val) gain2 = val; end;
    };
    {
        name = "Mix";
        min = 0;
        max = 100;
        default = 100;
        changed = function (val) mix = val*0.01; end;
    };
}

Another one, some kind of cheap and aliasing distortion, but sounds quite cool e.g. on hi hats with a pre filter. Or if you think “damn, this sounds too high quality, let’s lofi it”, it is maybe useful.

--[[
name: Crank Distortion
author: J.R.
--]]
require "include/protoplug"

local power
local threshold
local gain
local mix

stereoFx.init ()
function stereoFx.Channel:init ()
    -- create per-channel fields (filters)
end

function stereoFx.Channel:processBlock (samples, smax)
    for i = 0, smax do
        local s = samples[i]
        local neg = 1
        if (s<0) then neg = -1; s = -s; end
        
        if (s < threshold) then s = s^power
        else s = s^(1/power)
        end
        
        samples[i] = s * gain * neg * mix + samples[i] * (1-mix)
    end
end

params = plugin.manageParams {
    {
        name = "Power";
        min = 1;
        max = 0.01;
        changed = function (val) power = val end;
    };
    {
        name = "Character";
        min = 0;
        max = 1;
        changed = function (val) val = 1-val;threshold = (val*val*val*val) end;
    };
    {
        name = "Gain";
        min = 0;
        max = 1;
        changed = function (val) gain = val end;
    };
    {
        name = "Mix";
        min = 0;
        max = 100;
        default = 100;
        changed = function (val) mix = val*0.01; end;
    };
}

im pretty impressed, there was something i was trying to do in puredata and max before but i couldnt work out how to do it, maybe one of you will be able to fathom it out,

its a type of compressor/maximiser sort of weird thing whereby you set a volume level and the plugin matches the incoming sound volume to that, whether this works on a per sample basis or is averaged over time i dont know, or maybe that could be a feature :slight_smile: would allow for weird sustain inducing tricks…

just found this, might try it again…http://designingsound.org/2013/06/tutorial-a-compressor-in-pure-data/

You know, reajs has been available for a very long time and unlike protoplug it has loads of scripts (plenty build in already) :c

Just for testing, regarding discussion of Renoise’s allpass filter device, see here: https://forum.renoise.com/t/new-tool-3-0-insert-hidden-legacy-renoise-dsp-effect/43441

Algorithm taken from here:http://denniscronin.net/dsp/vst.html

This seems to be the algorithm of the allpass filter dsp device:

--[[
name: Allpass filter
author: Dennis Cronin, j.r.
--]]

require "include/protoplug"
local mFreq
local z1 = {}
local z2 = {}

z1[0] = 0
z1[1] = 0
z2[0] = 0
z2[1] = 0

function plugin.processBlock(s, smax)
	for cn = 0,1 do
		for i = 0,smax do
			local input = s[cn][i]
			
			
			local wp = (math.pi * mFreq) / plugin.getSampleRate()
			local coef = (1 - wp) / (1 + wp)
			
			z2[cn] = coef * (z2[cn] + input) - z1[cn]
			z1[cn] = input
			
			s[cn][i] = z2[cn]
		
		end
	end
end

params = plugin.manageParams {
	{
		name = "Frequency";
		min = 10;
		max = 20000;
		default = 440;
		changed = function(val) mFreq=val end;
	};
}

just found this, might try it again…http://designingsound.org/2013/06/tutorial-a-compressor-in-pure-data/

You know, reajs has been available for a very long time and unlike protoplug it has loads of scripts (plenty build in already) :c

Well, ReaJS doesn’t seem to be available for Mac OSX. Pure-Data seems to complicate things. Protoplug is maybe only at beginning state, but is 1. cross platform, 2. LUA like there stuff in Renoise 3. very simple and fast in producing results

Funny little trick… default instance of Protoplug Gen vsti can act like a quick midi-thru if you want to midi-chain multiple instruments in series in R3.1.

require "include/protoplug"

Simply compile this line.

Cool trick. Are renoise users still using this plug? Is it still being developed? I’ve had it for a while but still don’t get how to use it at all bc I’ve never delved into lua. Imo, this is the short term answer to tool-development of the audio engine (a much needed feature).

1 Like

Protoplug is quite nice. I began playing around with it recently, to try one or another silly demolition of sound. Maybe I will try to use it in future to “prototype” some more useful plugins that are later implemented in more efficient languages like c - what protoplug was thought for judging by its name.

Maybe it is some interesting tool for people with programming background and some dsp knowledge, as playground to experiment with dsp methods in a rapid development environment, while not caring too much about performance. People without a certain level of programming experience will very soon be frustrated, maybe use one or another precoded snippet like those above, here and there, but not really use themselves as creative music production tool. Real DSP is quite different from just coding some simple modulator with the formula device. You’re directly generating or manipulating audio buffers with this beast, and lua being built up in simple ways won’t mean it’s easier to code quality dsp with.

I don’t think it would make a nice object to learn coding with - dsp is too delicate for beginners imho, after trying some crappy sounding naive methods there’ll be a long way through a thirsty desert until you’re able to come up with something sounding real good. Also the results seem to soak quite a lot of cpu power compared to pure (and probably hand-optimised) c code, but maybe I just have to get into the ffi modules and the implications of using c types with luajit some more. This thing has its beaty as a development tool - not as a musician’s bread-and-butter tool for music production.

As I think of it now, having the new renoise 3.1 feature in mind, this thing can also make midi processors. Maybe it might have potential for musicians with moderate coding background, enabling them to make their own chord-generators or arpeggiators or stuff in that line? Shuffling around midi notes in creative ways is not as bitter and hard as developing good sounding dsp. A trip on the procedural music line granted, but realtime controlled.

I dont want to hijack, but does anyone know of an environment that acts as a vst which uses a language that’s more popular/efficient/documented for dsp? I really like the concept that protoplug puts forth. The whole idea of a VST IDE makes learning to code really attractive to those who are experienced with daw production, but in terms of developing skills for dsp coding, it doesn’t seem scalable to me personally.

You can get jesussonic as a part of reaplugs vst pack herehttp://www.reaper.fm/reaplugs/#reajs it also comes wth reaper and there is a ton of presets online all over the place.

#edit# sorry i forgot to mention that it is a vst and that the coding is quite simple …depending on what you wan t to code…:slight_smile:

There’s Blue Cat’s Plug’n Script, but no common language (forgot what it is, the demo took too much cpu I never look closer.)

Another one is Faust, seems to be able to export C++/java/VST/AU/Max/PD all by a same Faust code, but has its own language and no existing VST IDE (there’s something in the work though, search Faustlive and “pmix v2”).

I’m learning dsp stuff too, planning to implement Protoplug into Bidule. I think Lua is close enough to C++ that it won’t hurt much just doing separate segments or fast prototyping. After that I might convert critical parts to Bidule’s sdk (it’s C-based). But my goal isn’t large projects but to make funny sounds here and there.

btw I think both Max and PD let you import C-based objects too.

I know of Faust but I had no clue it was that versatile in terms of exporting. I’ll definitely have to give it another look over. I know for sure you can code external max objects in C, and Gen will spit out C source if I’m not mistaken. My main hesitation with Max is its lack of DAW integration. But I LOVE the visual language element. A renoise canvas for modular coding and patching would be a dream. Something that you can pull up and patch like Max, but then spits out Renoise xml to control the back end is basically exactly what I’m looking for. But as far as I understand, Renoise’s lua implementation wouldn’t allow for any kind of free form patching window at the moment.

It’s possible also to turn JS plugs into VST. It’s not fully developed yet but there’s a program called Geep Jeez. Guy who’s developing it is taking a break, but he got really far and I’ve successfully exported some JS synth controllers I made as VST. Really you usually won’t need to, you can just load the script in ReaJS in any VST host.

Major drawback of JS is doing the GUI stuff, it’s truly a bitch, but if you don’t all you get is a long list of sliders that can run off the screen if there are too many, but there are tools out there for GUI stuff too (and Geep Jeez makes it possible to use VSTGUI and such). And you can just lift stuff from other JS scripts with good GUI elements (that’s what I do).

There’s also a graphical “modular” JS editor here: http://jsfxgen.googlecode.com/svn/trunk/bin/index.html (and a standalone application of the same). It’s been pretty reliable when I’ve used it, but you may need to vet the code it outputs a little bit. It’s aging and the guy who made it hasn’t updated it for more recent versions of JS.

JS is really pretty capable and will likely get better. I recommend it, there are some bloody good FX written in it and the beauty is you can totally customize them.

Edit: forgot to mention, even better (well, easier) than VSTGUI is SWIPE GUI, which is also usable with Geep and is very effective.

I think you could use the luajit “ffi” module in protoplug to draft code and data types as pure C code wrapped inside lua. “FFI” seems to be a luajit speciality. In the expamples that come with proto you’ll see quite some use of it for defining data objects. This way you can not only access C-style-buffers and floats (lua will have every number as double, and every structured data types as huge dynamic table…) but can also have code snippets written directly in C. I think it works this way, haven’t delved deeper into it yet. The beauty is of course to have relevant algorithms fixed down in C while pushing the framework and gui around in rad style in lua, or draft and tune algos in lua and then later fix them down to C for speed reasons or to transfer them to a C project.

It doesn’t sound that bad to me after all. And: this tool is for experimenting or quickly doing unusual stuff, not for building professional grade plugins. To me Lua plus ffi seems to fit just in when it comes to a simple scripting language with enough power. And lua is really simple - if you know how to program in another language, you’ll be supprised after a while, there’s nothing fancy to it and syntax is minimalistic instead of complex.

Hm, but protoplug is surprisingly fast here! Almost like a normal fx. And somehow you can extend with lua libs (no clue about it), that assumingly can be compiled c++?

Yes, as I’ve written, with luajit you can “ffi” plain c code directly into your work (dunno how well the luajit compiler will do ob it), and you can also interface binary libraries for outsourced routines. You can see how its done (libraries) in the examples using the fftw3 library for calculating fft’s. Protoplug has its own one-liner syntax extension to loading libraries, presumably to allow the same code working on mac/win/linux without too much extra stuff. Of course you can load your own binary libraries this way.

But I don’t know how you define performance, yea, it is quite fast, but not even close to what a good c/c++ compiler can do inlining stuff together massively, using sse accelleration, unrolling vectorization and shit. Well - fast enough for prototyping and having quick fun with ideas. When a simple effect uses 4%cpu instead of 1% it is still very usable, that is.

WOW! This is PERFECT!

THANKS!!!

Split midi input / one track notes to multiple instruments using protoplug VSTi / Panning by note -> VSTi instance

Hi, since Renoise 3.1 doesn’t seem to be capable to split midi to multiple tracks/instruments, I made a little script with protoplug. You can split one midi input / the notes of one track to multiple instruments with it, see example song below. It will transpose each n note to n*split_range (e.g. 24).

Very helpful for me, maybe for you, too. I can do this marvelous note auto panning for example, even with VSTis that do not support panning.

midi split by notes followup

[SPOILER]

--[[
name: midi split followup v0.1
author: J.R.
--]]

require "include/protoplug"

-- what kind of chord ?
local noteoffs = {}
local blockEvents = {}
local cNotes = 0
local numInstrs = 2
local splitRange = 24

function plugin.processBlock(samples, smax, midiBuf)
	blockEvents = {}
	-- analyse midi buffer and prepare a chord for each note
	for ev in midiBuf:eachEvent() do
		if ev:isNoteOn() then
			noteOff(ev)
			noteOn(ev)
			cNotes = (cNotes + 1) % (numInstrs)
		elseif ev:isNoteOff() then
			noteOff(ev)
		elseif ev:isPitchBend() then
			table.insert(blockEvents, midi.Event.pitchBend(ev:getChannel(), ev:getPitchBendValue()))
		elseif ev:isControl() then
			table.insert(blockEvents, midi.Event.control(ev:getChannel(), ev:getControlNumber(), ev:getControlValue()))
		end	
	end
	-- fill midi buffer with prepared notes
	midiBuf:clear() 
	if #blockEvents>0 then
		for _,e in ipairs(blockEvents) do
			midiBuf:addEvent(e)
		end
	end
end

function noteOn(root)
	noteoffs[root:getNote()] = root:getNote() + cNotes*splitRange
	local newEv = midi.Event.noteOn(
			root:getChannel(), 
			noteoffs[root:getNote()], 
			root:getVel())
	table.insert(blockEvents, newEv)
end 

function noteOff(root)
	if not noteoffs[root:getNote()] then return end
	local newEv = midi.Event.noteOff(
			root:getChannel(), 
			noteoffs[root:getNote()])
	table.insert(blockEvents, newEv)
	noteoffs[root:getNote()] = nil
end

params = plugin.manageParams {
    {
        name = "Num of instr.";
		type = "list";
		values = {2,3,4,5,6,7,8};
		default = 3;
        changed = function (val) numInstrs = val end;
    };
    {
        name = "Split range";
		type = "list";
		values = {12,24,36,48};
		default = 24;
        changed = function (val) splitRange = val end;
    };
}

[/SPOILER]

Example song:

http://tstlab.virtualcreations.de/renoise_forum/multiple_instr_note_followup.xrns

You needsynth1 VSTiand luaprotoplug VSTi. Also you need to setup a loopback driver in midi OSX settings or some loopback driver for windows:

post-5192-0-74303200-1446055958.png

Routing in example should be (could be not set, because of loopback driver device name):

instr 0: midi input your midi keyboard, midi routing to instrument 1

instr 1: midi input none, output midi loopback/iac driver

instr 2: midi input loopack/iac, midi ch.1, key c3-b4

instr 3: midi input loopack/iac, midi ch.1, key c5-b6

instr 3: midi input loopack/iac, midi ch.1, key c7++

Play on instr. 0, using the key range c-3 to b-4.

EDIT: fixed song link

EDIT 2: Added pitch bend and control data support!

1 Like