General > General Discussion

AZ Lua MFX plug-in

(1/2) > >>

azslow3:
AZ Lua MFX
Current version can be downloaded here
Installation video: https://www.youtube.com/watch?v=oTddpaGxpBA

While the program is still alpha quality, I have tested it under Sonar X2 32bit and Sonar Platinum 64bit. So far I have not observed any problems. Window resizing is still not perfect, but that does not influence the plug-in functionality.

About
AZ Lua is Sonar MIDI Effect (MFX) plug-in in DXi format (the only supported by Sonar for MIDI plug-ins).

To just use this plug-in with existing presets, no programming knowledge required. In this case you can ignore everything written in this thread, except the next post with installations instruction and the last post with existing presets description and the preset file.

It allows to write MFXes in Lua programming language. While MFX API is published by Cakewalk long time ago, at least average experience in C++ programming is required to create own effects. Programming MFXes is Lua has following advantages:

* Lua is a simple language, easy to learn: www.lua.org
* tiny footprint. The plug-in size is way under 1MB, no external dependencies (except MS Windows Runtime, included in all currently deployed Windows versions)
* scripting language, no compilation step
* reasonably fast
AZ Lua plug-in also provides the following advantages:

* Modified toward simplicity API.  Everyone with basic programming experience should be able to create own MIDI filters. Everyone with basic calculations experience (for example calculations in spreadsheet) should be able to modify filters created by other
* The API created for unexperienced audience, several protections are implemented to avoid your "first program" crash/lock Sonar. The plug-in disallow dangerous Lua functionality, detect (big) memory leaks and too slow for MIDI processing code (including endless loops). Like with normal plug-ins, users should not worry about Sonar integrity when creating programs/presets
* You can program without leaving Sonar, AZ Lua User Interface has simple text editor and can (test) run your Lua code. All errors and "print" output are displayed. Unlike most MFXes, the interface can be resized
* Several instances of the plug-in run completely independently, the code is multi-thread and RealTime nature of MIDI processing inside DAW aware and seamless give the same properties to the Lua code
Important differences between CAL and AZ Lua
While both can be used to process MIDI in Sonar, there are more differences then the language used:
CALAZ LuaNot MIDI functionalityYESNOMulti-track  functionalityYESNO"Look back" and "multi-pass" MIDI processingYESNOOffline MIDI processingYESYESLive MIDI processingNOYESNon destructive MIDI processingNOYES

To give you an idea how MFX can look like, the following is a COMPLETE WORKING example for filtering out all "C" Notes:

--- Code: ---function OnInput(pqIn, pqOut)
  for i = 1, #pqIn do
    e = pqIn[i]
    if e.Key and (e.Key % 12 == 0) then
      e = nil
    end
    pqOut.add(e)
  end
end

OnEvents = function ( From, To, pqIn, pqOut)
 OnInput(pqIn, pqOut)
end

--- End code ---
For Lua experts: I know there is better way for looping, "e" should be local and the condition can be reversed to make the code shorter  ;)

If that example looks like a newspaper from the Mars for you, probably you can just use some presets without going into details. If you understand that is "a program" (probably you do not understand WHAT it is doing and HOW it is working, that is ok), I think you can create your own FXes till you finish reading this thread.

Note 1: AZ Lua has different from Lua license. AZ Lua is closed source project (at least for now) but it is free to use (and I have no plans to change that).
Note 2: I do not pretend to be the first in writing such kind of plug-in. I have found several projects which are using Lua is VST(i) plug-ins. But I have not found any in DX(i) format. If you know such project and you think I am violating something or simply "cross the road" for someone, please let me know.

Changelog:
1.3.16 - b2, Different Note event types (API change)
1.3.16 - b3, MfxKey and MfxOffNotes helpers
4.3.16 - b4, User Interface
6.3.16 - b5, UI Resize should work a bit better
19.3.16 - b6, TempoMap functions exposed
14.06.16 - b7, Fixed incorrect CC processing in life mode, could produce rather strange effects...

azslow3:
Installation

* Exit Sonar
* Download the installer
* Run installation, modern OS will warn you it is not signed. If you trust me, do not worry. The only "safety" which signed executable gives you is some information about the author and prevention some virus which already exist on your computer to modify the executable. You can find more information about me then you can find in any certificate using DNS of my site. If I start to sign my installators, I will be forced to collect money just for the certificate. And if you already have a virus on your computer, preventing it is too late (also you can compare the size of your local file with the information in the Download section, most modern "viruses" are bigger then my whole package...)
* Several files will be installed and registered for Sonar use. The path is not configurable, but that will not fill your disk. You can uninstall any time, from my knowledge uninstallation is restless
* Start Sonar. "AZ Lua" should appear as possible MFX plug-in (in MIDI tracks FX Bin and Processing menu)
Unlike any other MFX plug-ins you have, this plug-in does absolutely nothing till you load Lua program into it. These programs are saved as normal Cakewalk presets and into your project file.
To load preset published by other in SPP format (my examples are attached to the later post in this thread, the file AZLua_Examples_v4.spp):

* Open Cakewalk Plug-in Manager from Sonar Utilities menu
* Select "MIDI Effects", "AZ Lua".
* Press "Import..." buttons, select SPP file and the preset(s) is it, press "Ok"
* Normally imported presets appear is the plug-in presets list without Sonar restart. But sometimes the restart is required

azslow3:
AZ Lua Interface
AZ Lua interface has 2 modes: "User" and "Developer"

User mode
When some preset is already loaded and valid, AZ Lua is switched to this mode when the interface is opened. What is shown here is defined by the Lua program. By default, there will be no controls. When preset developer has followed simple rules, you should see at least some description of what that preset is doing. In addition, there can be some parameters exposed. These parameters are saves within preset/project, so can be recalled.

You can switch into Developer mode any time by pressing "Modify" button.

Note: in case the preset code is change and applied, all parameters are reset to values specified in the code.

Developer mode has:

* Lower "Output" section. It display error messages (which something went wrong with Lua program) and the results of Lua "print" function
* The editor. Current cursor position is displayed above it, next to the buttons (useful when error message includes line information). When you modify Lua code it is not automatically applied.
* "GUI" button to switch into User mode
* "Apply" button. Set Lua program in the editor as FX processor.
* "Test" button. Execute Lua program in the editor. The program is run independent from currently active FX Lua program and so it does not effect MIDI processing. Useful to check you have no bugs in Lua syntax or as general Lua interpreter
* "Revert"/"Clear" button. If you have modified Lua code, you can revert it to currently running one, even in case you have "Test"ed it.
Important: While Sonar disable "Maximize" button, you can resize the window using borders. Sometimes that can be required to see all available parameters in the User mode. In the Developer mode, you can change the hight of output section but dragging the line between it and the editor.

Note: note that changing parameters in the User more does not have immediate effect. Sonar "prepare" MIDI data in advance (there is a setting to change the size of the buffer). MFX plug-in can not "undo" what was already prepared.

Tip: in case you have feeling the preset is no longer working, switch to the Developer mode and check output section. Most probably you will see some "error" there. The problem indicated is NOT with plug-in (you will get Sonar crash then) but with the preset! Presets in AZ Lua are programs, and so they can have bugs.

azslow3:
MFX basics
Please note that API and logic of MFX is significantly different from MIDI processing inside VST.

MFX host (Sonar) call 2 different methods (functions) provided by MFX:

* "OnInput" is called when live MIDI message is received from the track MIDI input. There can be several simultaneous messages (for example chords played with sufficient precision). Please note that in "Record" mode these events are recording BEFORE any MFX processing (the same as with Audio recording)
* "OnEvents" is called in two cases. When you "Play" the track and when you "Process" MIDI clip using the plug-in. In the first case, the processing is not destructive (till you "Apply effects"), it is just sent to the next MFX or the track output. In the second case the result of processing replace original clip. Sonar call "OnEvents" once for "MIDI buffer" specified time period (in advance during playback). Note that that buffer is usually "big" compare to the Audio buffer size, it has order of 0.5 second (audio buffer is normally several milliseconds)
There is important different between Events received by these two functions. "OnInput" receives MIDI messages only, while "OnEvents" receives compound "Events" which can be a combination of several MIDI messages. For example, already recorded MIDI clip knows when there was corresponding to "Note pressed" "Note released" message and so instead of 2 distinct MIDI messages, there is one "Event": "Note with duration". On live input it is impossible to predict when the Note ends, and so there is not way to combine them. The same is true for RPN and NRPN (you should get a sequence of  corresponding "Control" events instead).

So, to create an MFX, you need to define 2 functions: one for live processing and one for recorded/offline processing. In both you can:

* forward incoming MIDI Event "as is"
* modify incoming MIDI Event before forwarding
* generate new MIDI Events
Original API really deliver just MIDI messages to the OnInput function, without "converting" anything to Events. Since that involves some hex arithmetic, there are only "Events" in AZ Lua. Because of already explained difference, "OnInput" get NoteOn/NoteOff events (without duration) while "OnEvents" get Note (with duration). As you will see, for simple filtering/mapping that is not important. But we should be careful during more advanced processing

azslow3:
AZ Lua API
I recommend at least read some chapters from the book about Lua programming language. You can find the link at www.lua.org. In case you have already installed AZ Lua and want try to reproduce some examples - you have Lua interpreter already! AZ Lua has Lua 5.3.2 interpreter build-in. You do not event forced to leave Sonar  ;)

It is very good idea to start each your preset with Lua multi-line style comment, like:

--- Code: -----[[ The is my dummy preset ]]--

--- End code ---
The text will be displayed in the User mode, so everyone can get an idea what that preset is doing without looking into the "code".

When Lua program is loaded from preset/project or "Appliy"ed in UI, it is executed once. During that execution it should define 2 global function:

* OnInput
* OnEvents
In addition, the program can define 3 additional functions to be called on corresponding transport changes:

* OnStart
* OnStop
* OnLoopThe last one can be important in case of dynamic functionality change, for example attempting to restore default/previous state.

Also you program can define (global) table "GUI" (see later).

ANY error (you can see then in the Output section of UI) during initial execution or these functions calls immediately disable your FX. And the plug-in start to work as disabled (everything goes throw unchanged). The same happens in case you have some valid Lua program but you have not defined these functions.

Notice Till you have pressed "Apply" button (so set the program as MFX), your code exists in UI only. If you close UI (or close the project) your changes WILL NOT be saved. Also till "Apply" is pressed, there is no "Project is modified" indication in Sonar. The MFX code currently working is still the same when you have just modified something in the editor, so logically there is no changed is the MIDI processing and so there is no changes in the project.

Till you start to do some "advanced" programming, OnEvents can stay (verbatim) as:

--- Code: ---OnEvents = function ( From, To, pqIn, pqOut)
  OnInput(pqIn, pqOut)
end

--- End code ---
and then you need only one function, OnInput.

Just to finish with "OnEvents": "To" and "From" parameters define the time period in MIDI Ticks for which this function is called.

pqIn and pqOut
There are called such way to mimic original API, with the meaning "the pointer to the Input Queue" and "the pointer to the Output Queue". Pointers make no big sense in Lua, but I have decided to keep the prefix "p". Note that you can rename both, there are just "the first" and "the second" parameters.

Both parameters are Lua Tables. But with a helper method "add". You can create your own queues by calling "MfxQueue.new()" method defined by AZ Lua API. More formal:

There is global object (table) MfxQueue with one single method new which returns an empty table with one defined method add(event,....). This method add a COPY of arguments into the table IF AND ONLY IF they are of type "MfxEvent". So, if you call "pqOut.add(x)" with anything except MfxEvent, nothing will happened (without errors, that is handy for filtering).

pqIn is the Input table. It contains MfxEvent(s) provided by Sonar on input, with numeric indexes (in Lua counting is done from "1").

pqOut is the Output table. You should add (again with numeric indexes started from "1") all MfxEvent(s) you need. Note that in case you do not add anything there, all events will be blocked by your MFX. While you can add events with other methods (for example "table.insert(ev)"), specialized "add" simplify the task (you do not need to bother making the event copy when needed and you do not need the conditional execution when filtering out events).

So, the general structure is:

--- Code: ---function OnInput(pqIn, pqOut)
  for i = 1, #pqIn do
    local e = pqIn[i]
    -- Do something with "e"
    pqOut.add(e)
  end
end

--- End code ---

More "Lua" style (better) definition for the same:

--- Code: ---function OnInput(pqIn, pqOut)
  for i,e in ipairs(pqIn) do
    -- Do something with "e"
    pqOut.add(e)
  end
end

--- End code ---
In that exact form, your MFX will just copy all events from the input table into the output table. Effectively the same "functionality" as not existing or disabled MFX plug-in. As I have already mentioned, defining the function but leaving it empty will BLOCK all MIDI events. So, you already know 2 "extreme" MFX plug-in definitions  :o

Local in "local e = ..." is not required but optimize the speed. We are working close to the Sonar "RealTime engine", so you should care (when that does not severe disturb readability, Lue experts will probable write "must without 'when'").

Navigation

[0] Message Index

[#] Next page

Go to full version