Welcome to %s forums

BrainModular Users Forum

Login Register

new script midi transpose with wrap function ( for creating voice leading chords)

Discussions about add-ons, announcements
Post Reply
joffo78
Member
Posts: 1033
Contact:

new script midi transpose with wrap function ( for creating voice leading chords)

Unread post by joffo78 » 30 Jan 2026, 09:44

Enhanced MIDI Transpose with Smart Voice Leading
Overview

This script is an advanced evolution of the standard MIDI Transpose module. While it retains the core functionality of pitch shifting, it introduces an intelligent Auto-Wrap system. This feature ensures that transposed notes stay within a specific musical range (octave), effectively creating automatic inversions and smoother voice leading for generative patches and chords.

Core Functionalities

Standard Transposition: Functions exactly like the original script, shifting incoming MIDI notes by a user-defined interval (+/- 24 semitones).

Polyphonic Support: Handles multiple MIDI messages (chords) simultaneously, maintaining the integrity of Note-On, Note-Off, and Velocity data.

New Advanced Features

Dynamic Root Control: A new Root Note input allows you to define the start of your "active window." All harmonized notes will be mathematically forced to stay relative to this reference.

Intelligent Auto-Wrap: When active, the script monitors the output pitch. If a transposed note exceeds the Root + 12 boundary, it is automatically shifted down by octaves until it fits the window. Conversely, if it falls below the Root, it is shifted up.

Switchable Inversions: A dedicated Wrap Active switch allows you to toggle between "Block Chords" (standard parallel movement) and "Smart Voicing" (inversions within a single octave).
//////////////////////////
// transpose midi with optional auto-wrap
// Window defined by Root and Root+12
/////////////////////////
var input : Tparameter;
var output : Tparameter;
var transpo : TParameter;
var active : TParameter;
var root : TParameter;

procedure init;
begin
Input := CreateParam('midi in', ptMidi, pioInput);
Output := CreateParam('midi out', ptMidi, pioOutput);

transpo := CreateParam('transpo', ptDataFader, pioInput);
transpo.Format('%.0f');
transpo.Min(-24);
transpo.Max(24);

root := CreateParam('root note', ptDataFader, pioInput);
root.Format('%.0f');
root.Min(0);
root.Max(115);
// On ne met pas de .Value() ici pour éviter l'erreur

active := CreateParam('wrap active', ptSwitch, pioInput);

SetModuleColor($FF3298DB);
end;

procedure Process;
var i : integer;
var nbOfMidi : integer;
var ReceivedMidi : TMidi;
var TranspoVal : integer;
var RootVal : integer;
var HighLimit : integer;
begin

nbOfMidi := input.Length;
output.length(nbOfMidi);

if (nbOfMidi > 0) then
begin
TranspoVal := transpo.asInteger;
RootVal := root.asInteger;
HighLimit := RootVal + 12;

for i := 0 to nbOfMidi-1 do
begin
ReceivedMidi := input.asMidi(i);

ReceivedMidi.data1 := ReceivedMidi.data1 + TranspoVal;

if (active.asInteger > 0) then
begin
while (ReceivedMidi.data1 > HighLimit) do
begin
ReceivedMidi.data1 := ReceivedMidi.data1 - 12;
end;

while (ReceivedMidi.data1 < RootVal) do
begin
ReceivedMidi.data1 := ReceivedMidi.data1 + 12;
end;
end;

output.asMidi(i, ReceivedMidi);
end;
end;
end;

Who is online

Users browsing this forum: No registered users and 80 guests