|
|
|
03-15-2015, 12:03 PM
|
#1
|
Human being with feelings
Join Date: Feb 2007
Posts: 3,221
|
"midi legato by range" bug help?
i've always used this plugin useful plugin by user "dumant" as part of larger bidule based midi programs or on monophonic synth lines, so i never realized that it has a bug with notes never receiving their noteoff.
the plugin delays noteoffs as specified, by ms or tick.
i found that if you trigger multiple notes near simultaneously while applying a delayed noteoff, the last couple notes never receive their noteoffs.
does anyone have a spare moment to show me what is wrong here, if anything? my hunch is that it has to do with "leastfreeindex"
Code:
/*
Midi Legato for a Note Range
----------------------------
This effect lets you increase the length of all notes in a given range.
Usage
-----
- Input Channel Filter: select the channel of the notes you wish to modify.
- Note min: lowest note that will be altered by the effect.
- Note max: highest note that will be altered by the effect.
- Delay: value of the delay for the currently selected range.
- Delay unit: the unit in which the delay is expressed (ms or ticks: there
are 960 ticks per beat.)
- Deviation: some randomness may be added (or subtracted) from the delay.
The effective delay will be comprised between delay*(1 - deviation)
and delay*(1+ deviation).
Presets may be saved using the standard preset mechanism.
Version History
---------------
1.1.2a: defined deviation as a maximum deviation, removed average correction
1.1.1a: bug corrections, normal randomization
1.1.0a: delay by tick, preset management
1.0.0a: Delay note off in ms
Thanks to IXix for delivering very inspiring js midi effects.
----------------------------
Copyright 2008, Bruno Dumant
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.
The name of Bruno Dumant may not be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
////////////////////////////////////////////////////////////////////////////////////////////
desc:Midi Legato for a Note Range - Press edit for documentation.
// Filters
slider1:0<0,16,1{All,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>Input channel filter
slider2:0<0,127,1>Note min
slider3:127<0,127,1>Note max
// Delay
slider4:0<0,1920,120>Delay (in ms or ticks)
slider5:0<0,1,1{ms,tick}>Delay unit (double it!)
slider6:0<0,100,1>Deviation in %
//slider7:0<0,1000,1>LFI
//slider8:0<0,1000,1>MFI
//------------------
@init
ext_noinit = 1;
version = 1; // storage version
// store events that will be released
events = 0;
leastFreeIndex = 0;
maxFreeIndex = 0;
// delay, msg1, msg23
eventSize = 3;
statNoteOn = $x90;
statNoteOff = $x80;
statController = $xB0;
noteMax = 127;
// generate a pseudo normal data set
normalData = 128;
i = 0;
loop (
128,
while ( a = rand(1); a != 0 ? (v = sqrt(-2*log(a))*cos(6.28318530717959*rand(1))); a == 0 || abs(v) > 3);
normalData[i] = v;
i += 1;
);
i = 0;
// make sure values are contained between -1 and 1
loop ( 128, normalData[i] /= 3; i += 1; );
//------------------
@slider
inChannel != slider1 - 1 ? (
slider1 = min(16,max(0,floor(slider1)));
inChannel = slider1 - 1;
);
noteMin != slider2 ? (
slider2 = noteMin = min(noteMax,max(0,floor(slider2)));
);
noteMax != slider3 ? (
slider3 = noteMax = min(127,max(noteMin,floor(slider3)));
);
delay != slider4 ? (
delay = slider4;
);
delayUnit != slider5 ? (
slider5 = delayUnit = min(1,max(0,floor(slider5)));
);
// variance is global
variance != slider6 / 100 ? (
variance = slider6 / 100;
);
//------------------
@serialize
file_var(0,version);
file_var(0,inChannel);
file_var(0,noteMin);
file_var(0,noteMax);
file_var(0,delay);
file_var(0,delayUnit);
file_var(0,variance);
//------------------
@block
delay != 0 || maxFreeIndex > 0 ? (
// send delayed events that expire within this block
i = 0;
while (
evtDelay = events[i];
evtDelay != 0 ? (
evtDelay < samplesblock ? (
// send the event
midisend(max(0, evtDelay), events[i + 1], events[i + 2]);
leastFreeIndex == maxFreeIndex ? (
// update maxFreeIndex
while (
maxFreeIndex -= eventSize;
events[maxFreeIndex] == 0 && maxFreeIndex >= 0;
);
);
leastFreeIndex = min(i, leastFreeIndex);
events[i] = 0; // disable the event
//slider7 = leastFreeIndex; sliderchange(slider7);
//slider8 = maxFreeIndex; sliderchange(slider8);
) : (
events[i] -= samplesblock;
)
);
i += eventSize;
i < maxFreeIndex;
);
while (
midirecv(offset, msg1, msg23) ? (
channel = msg1 & $xF; // Low four bits is channel number
//Is it on our channel
inChannel == -1 || channel == inChannel ? (
//Check status byte
status = msg1 & $xF0; // High four bits is message type (240 == 11110000)
//Is it a note event
status == statNoteOn || status == statNoteOff ?
(
note = msg23 & $x7F;
// is the note managed ?
note >= noteMin && note <= noteMax ? (
status == statNoteOff || ((msg23/$x100) & $x7F) == 0 ? (
realDelay = 0;
delay != 0 ? (
// compute the delay in samples
delayUnit == 0 ? (
realDelay = delay / 1000 * srate;
) : (
realDelay = delay / 16 / tempo * srate; // 1/16 = 60/960
);
variance != 0 ? realDelay *= (1 + normalData[floor(rand(128.99))] * variance);
);
// offset of event % beginning of block
date = offset + realDelay;
// this is a noteOff or 0 velocity message
date < samplesblock ? (
// the event can be immediately sent
midisend(max(0, date), msg1, msg23);
) : (
// otherwise store in the events (offset % beginning of next block)
events[leastFreeIndex] = date - samplesblock;
events[leastFreeIndex + 1] = msg1;
events[leastFreeIndex + 2] = msg23;
// update leastFreeIndex
leastFreeIndex == maxFreeIndex ? (
leastFreeIndex = maxFreeIndex += eventSize;
) : (
while(
leastFreeIndex += eventSize;
events[leastFreeIndex] != 0 || leastFreeIndex < maxFreeIndex;
);
leastFreeIndex == maxFreeIndex ? (
leastFreeIndex = maxFreeIndex += eventSize;
)
);
//slider7 = leastFreeIndex; sliderchange(slider7);
//slider8 = maxFreeIndex; sliderchange(slider8);
);
) : (
// not a noteOff
midisend(offset,msg1,msg23);
);
) : (
// not a managed note
midisend(offset,msg1,msg23);
)
) : (
// Not a note
status == statController ? (
ccId = msg23 & $x7F;
ccId == 123 || ccId == 120 ? (
// all sounds off or all notes off
leastFreeIndex = 0;
maxFreeIndex = 0;
//slider7 = leastFreeIndex; sliderchange(slider7);
//slider8 = maxFreeIndex; sliderchange(slider8);
);
);
// pass thru
midisend(offset,msg1,msg23);
);
) : (
// pass thru
midisend(offset,msg1,msg23);
);
)
);
);
|
|
|
04-09-2016, 02:32 PM
|
#2
|
Human being with feelings
Join Date: Feb 2016
Posts: 232
|
HUGE BUMP!!! I'm running into the same issue and I really need this to work... Although I suppose an infinite note is technically "legato"
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 01:45 AM.
|