Jump to content

Scripted LFO instead of using "Modulator" MIDI FX?


DGB111

Recommended Posts

I love using the modulator to warp sounds, but the only problem I find is that the LFO is set to some internal clock, instead of being aligned to a beat. Even if you have the "Rate" set at 1/4, the timing is a quarter note, but when you hit the transport it starts wherever the LFO is in its waveform, so one time it may be all the way at the top, then the next time it may be all the way at the bottom, so if you want the loud part of the modulation always to be on the beat it's impossible. In Kontakt it's easy because you can always set what part of the wave it should start on (not sure why that's not an option in LPX, or am I missing it?!?!)

 

Anyway, is there a way to script this so you can get LFOs that can be set to the beat and always start where you want?

 

Thanks!

Link to comment
Share on other sites

Thanks Eric! The only thing that's missing is that always starts you in the middle of the waveform, so its impossible (as far as I can tell) to start at the top or bottom of a sine wave LFO (without tweaking the shape until it's not a sine anymore). Do you know if there's a way to set where it starts in the waveform, or are we just locked into the beat = the middle? And if there isn't a way, is there a way to script it?

 

Thanks!!!!

Link to comment
Share on other sites

Yes you can write a script to do it, but I don't have time to work out the math for you. In order to plot a sine wave in Scripter use the Math.sin() function. You'll have to figure out the rest of the math so that it has the amplitude you want, the frequency you want and starts 90 degrees into the cycle... then just generate a CC event that is scaled appropriately. If I were going to write it I would just plot a CC event for every call to ProcessMIDI(), using the start beat number.
Link to comment
Share on other sites

Yes you can write a script to do it, but I don't have time to work out the math for you. In order to plot a sine wave in Scripter use the Math.sin() function. You'll have to figure out the rest of the math so that it has the amplitude you want, the frequency you want and starts 90 degrees into the cycle... then just generate a CC event that is scaled appropriately. If I were going to write it I would just plot a CC event for every call to ProcessMIDI(), using the start beat number.

 

Thanks! I'll take a stab at it when I get a chance!!!

Link to comment
Share on other sites

  • 4 years later...

I don't have any time to customize any of this for you, but this can get you started.  

var NeedsTimingInfo = true;

var CYCLE_LENGTH = 4;  // cycle length in beats      

var cc = new ControlChange;
cc.number = 1;
cc.channel = 1;


function HandleMIDI(event) {
    event.send();
}

var lastVal = 0;

function ProcessMIDI() {
    
    var timing = GetTimingInfo();
    
    if(timing.playing) {
        lastSendBeat = timing.blockStartBeat;
        cc.value = modulator(timing.blockStartBeat);
        if(cc.value != lastVal) {
            cc.send();
            lastVal = cc.value;
        }
    }    
}

// produce modulation value based on Beat
function modulator(beat) {
    let radians = radsFromBeat(beat);
    let plot = (Math.sin(radians)+1)/2;  // convert to 0-1 range
    return Math.round(plot*127);

}

// convert beat value to radians
function radsFromBeat(beat) {
    let percent = (beat-1)/CYCLE_LENGTH;
    let frac = percent - Math.floor(percent);
    return frac * (2 * Math.PI);
}

 

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...

Thank you!

I want to keep this thread and idea alive and customised the script so that it modifies the velocity of the notes played, so you can have an LFO that will trigger different velocities.

It produces hanging notes when stopping Logic, I haven't figured out why, but perhaps whoever is interested in growing this little script finds out why.

/*
With Scripter, you can use JavaScript to create your own custom MIDI processing 
effects, including slider controls for real-time interaction.

For detailed information about using Scripter, including code samples, 
see the MIDI plug-ins chapter of the Logic Pro X Effects or 
MainStage 3 Effects manual.
*/

var NeedsTimingInfo = true;
var CYCLE_LENGTH = 3;  // cycle length in beats      
// var PluginParameters = [{name:"Cycle Length", type:"lin", minValue:1, maxValue:16, numberOfSteps:15, defaultValue:4}];  // cycle length in beats      

var cc = new ControlChange;
cc.number = 1;
cc.channel = 1;

function HandleMIDI(event) {
	var note = new NoteOn;
	var noteOff = new NoteOff
	note.pitch = event.pitch;
	note.velocity = event.velocity - cc.value; // have to get the values inside 1-127 velocity
	
	if(note.velocity < 0) {
		note.velocity = 0;
		}
	
	if(note.velocity > 127) {
		note.velocity = 127;
		}
		
	
	// note.trace();
	cc.trace();
	note.send();
	noteOff.send()
}
	
var lastVal = 0;
function ProcessMIDI() {
    
    var timing = GetTimingInfo();
    
    if(timing.playing) {
        lastSendBeat = timing.blockStartBeat;
        cc.value = modulator(timing.blockStartBeat);
        if(cc.value != lastVal) {
            //cc.send();
            lastVal = cc.value;
        }
    }    
}

// example: simple pass through and MIDI monitor
// function HandleMIDI(event)
// {
//	event.trace();
//	event.send();
//}

// produce modulation value based on Beat
function modulator(beat) {
    let radians = radsFromBeat(beat);
    let plot = (Math.sin(radians)+1)/2;  // convert to 0-1 range
    return Math.round(plot*127);
}
// convert beat value to radians
function radsFromBeat(beat) {
    let percent = (beat-1)/CYCLE_LENGTH;
    let frac = percent - Math.floor(percent);
    return frac * (2 * Math.PI);
}

 

Link to comment
Share on other sites

Thank you!

Yes, next time I will think of removing all the unnecessary comments from the code...

Yes, I've tried that, but I was doing it wrong somehow and was getting syntax errors left and right, so I decided to do it another wrong way that at least produced the result I wanted.

I don't understand how to modify the velocity of the event directly and from the tutorial scripts it was easier for me to learn how to do it this way.

I would be very happy if you could share that one line of how to subtract a variable from the velocity of the current event.

Link to comment
Share on other sites

remove the ProcessMIDI function and change the HandleMIDI function like this:

function HandleMIDI(event) {
    
    var timing = GetTimingInfo();
    
    if(timing.playing) {
        lastSendBeat = timing.blockStartBeat;
        event.velocity = modulator(timing.blockStartBeat);
    }
    event.send();    
}

 

 

Link to comment
Share on other sites

  • 8 months later...
On 5/28/2022 at 8:35 AM, Dewdman42 said:

remove the ProcessMIDI function and change the HandleMIDI function like this:

function HandleMIDI(event) {
    
    var timing = GetTimingInfo();
    
    if(timing.playing) {
        lastSendBeat = timing.blockStartBeat;
        event.velocity = modulator(timing.blockStartBeat);
    }
    event.send();    
}

 

var NeedsTimingInfo = true;
var CYCLE_LENGTH = 3;

function HandleMIDI(event) {
    var timing = GetTimingInfo();
    if (timing.playing) {
        event.velocity = modulator(timing.blockStartBeat);
    }
    event.send();
}

function modulator(beat) {
    let radians = radsFromBeat(beat);
    let plot = (Math.sin(radians) + 1) / 2;
    return Math.round(plot * 127);
}

function radsFromBeat(beat) {
    let percent = (beat - 1) / CYCLE_LENGTH;
    let frac = percent - Math.floor(percent);
    return frac * (2 * Math.PI);
}
   

 

Link to comment
Share on other sites

  • 2 months later...

This works really great, thank you all! Is there an easy way to edit this script so that we can choose between sine/saw/square/etc? I know you can do this with Modulator but having this Scripter "print" these patterns directly saves quite a bit of time and steps!

Edited by anp27
Link to comment
Share on other sites

modify the modulator function math for whatever waveform you want.  Unfortunately I don't have access to my mac or time really to help you work out the math required for different kinds of waveforms, but some google searches should get you there pretty easily.

Another way to approach this would be to fill an array with the desired waveform points...rather then calculating math on the fly, but again, I don't have access to my mac at the moment to give you an example...sorry.

 

Edited by Dewdman42
  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...