Delta Thing  It Came From the Swamp of Billstei's Mind

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
Here is an alpha version of Delta Thing, as inspired by this thread: http://www.kvraudio.com/forum/viewtopic.php?t=252010 . The only parameter that I attempt to randomize here is OSC1 Tune, but the point is not to do anything incredibly useful, but to do a proof of concept. Patches can now (in theory) be built up which deal with any group of parameters, dealing with them (somewhat) intelligently. For example, a patch that makes attack times shorter, let's call it the MorePunchyPatch, could be built by adding attack time parameters from modules that have attack times, using a negative bias setting so that the randomization tends to decrease their values. You begin with a patch that sounds reasonably good, and you "morph" it towards more punchiness by clicking the MorePunchyPatch (repeatedly) until you get something you like, or until it sounds so bad it makes you want to quit the music business and get a real job.
In the prototype Delta Thing patch below the key line (and the only one that you should need to change/add to) is this:
Oscillator[1].Tune = delta(Oscillator[1].Tune, Oscillator[1].Tune.min, Oscillator[1].Tune.max, DELTA_FROM_RANGE, 1.0, 0.5, 1.0, 12.0);
This is what it is trying to do:
Oscillator[1].Tune  the parameter being changed
Oscillator[1].Tune.min, & max  the min/max of the range of the parameter
DELTA_FROM_RANGE  the random value is taken from (a subrange of) the min/max range (see also DELTA_FROM_VALUE), can just put a 1 or 2 here
1.0  there is a 100% chance that this value will (try to) be changed
0.5  a negative bias, where one half of the allowable value increases are not possible
1.0  scale the value change by this amount
12.0  round the new value to this multiple, i.e. in the case of Tune, an octave.
There are many things I could say about the code in this patch  many of the "bad" things were due to 1) Zebraspeak limitations/bugs, and 2) my sanity with respect to debugging it, and 3) my ignorance. All of which I expect to improve as time goes on. Except my ignorance, which is already a finely tuned machine.
billstei
P.S. It would obviously be if there was a graphical front end to build patches.

#defaults=no
#patchname=no
<?
// Delta Thing  Version 2
int DELTA_FROM_RANGE = 1;
int DELTA_FROM_VALUE = 2;
// delta()  returns the changed parameter value
// v  the parameter's current value
// vmin  the minimum of the range of v
// vmax  the maximum of the range of v
// dt  type of delta, either from a value chosen from the range,
// or a value which is a percentage of the current value
// cp  probability of there being a change, from 0.0 to 1.0
// cb  change bias is from 1.0 to 1.0
// sc  scaling applied to the random value/percentage
// cm  change multiple to round to. Use 0.0 for no rounding
float delta( float v, float vmin, float vmax, int dt, float cp, float cb, float sc, float cm) {
float lo;
float hi;
float x;
float h;
float r;
float delta_out;
// Assume no change to the current value
delta_out = v;
r = rand(0.0, 1.0);
// If random r is less than the change percentage then we do the change
if (cp > 0.0) { if (r <= cp) {
if (dt == DELTA_FROM_RANGE) {
if (cb > 0.0) {
// Positive bias
lo = (vmin  v)  ((vmin  v) * cb);
hi = vmax  v;
} else {
// Negative bias
lo = vmin  v;
hi = (vmax  v) + ((vmax  v) * cb);
}
// Else use percentages
} else {
if (cb > 0.0) {
// Positive bias
lo = 1.0 + cb;
hi = 1.0;
} else {
// Negative bias
lo = 1.0;
hi = 1.0 + cb;
}
}
if (dp_osc1_tune_delta_type == DELTA_FROM_RANGE) {
if (cm > 0.0) {
r = rand(lo, hi) * sc;
x = v + r;
if (x < 0.0) { h = 0.5; } else { h = 0.5; };
int c = ((x / cm) + h);
delta_out = c * cm;
} else {
r = rand(lo, hi) * sc;
delta_out = v + r;
}
// Else do the delta from percentage of current value
} else {
if (cm > 0.0) {
r = rand(lo, hi) * sc;
x = v + (v * r);
if (x < 0.0) { h = 0.5; } else { h = 0.5; };
int c = ((x / cm) + h);
delta_out = c * cm;
} else {
r = rand(lo, hi) * sc;
delta_out = v + (v * r);
}
}
if (delta_out < vmin) delta_out = vmin;
if (delta_out > vmax) delta_out = vmax;
}}
return delta_out;
}
Oscillator[1].Tune = delta(Oscillator[1].Tune, Oscillator[1].Tune.min, Oscillator[1].Tune.max, DELTA_FROM_RANGE, 1.0, 0.5, 1.0, 12.0);
?>
In the prototype Delta Thing patch below the key line (and the only one that you should need to change/add to) is this:
Oscillator[1].Tune = delta(Oscillator[1].Tune, Oscillator[1].Tune.min, Oscillator[1].Tune.max, DELTA_FROM_RANGE, 1.0, 0.5, 1.0, 12.0);
This is what it is trying to do:
Oscillator[1].Tune  the parameter being changed
Oscillator[1].Tune.min, & max  the min/max of the range of the parameter
DELTA_FROM_RANGE  the random value is taken from (a subrange of) the min/max range (see also DELTA_FROM_VALUE), can just put a 1 or 2 here
1.0  there is a 100% chance that this value will (try to) be changed
0.5  a negative bias, where one half of the allowable value increases are not possible
1.0  scale the value change by this amount
12.0  round the new value to this multiple, i.e. in the case of Tune, an octave.
There are many things I could say about the code in this patch  many of the "bad" things were due to 1) Zebraspeak limitations/bugs, and 2) my sanity with respect to debugging it, and 3) my ignorance. All of which I expect to improve as time goes on. Except my ignorance, which is already a finely tuned machine.
billstei
P.S. It would obviously be if there was a graphical front end to build patches.

#defaults=no
#patchname=no
<?
// Delta Thing  Version 2
int DELTA_FROM_RANGE = 1;
int DELTA_FROM_VALUE = 2;
// delta()  returns the changed parameter value
// v  the parameter's current value
// vmin  the minimum of the range of v
// vmax  the maximum of the range of v
// dt  type of delta, either from a value chosen from the range,
// or a value which is a percentage of the current value
// cp  probability of there being a change, from 0.0 to 1.0
// cb  change bias is from 1.0 to 1.0
// sc  scaling applied to the random value/percentage
// cm  change multiple to round to. Use 0.0 for no rounding
float delta( float v, float vmin, float vmax, int dt, float cp, float cb, float sc, float cm) {
float lo;
float hi;
float x;
float h;
float r;
float delta_out;
// Assume no change to the current value
delta_out = v;
r = rand(0.0, 1.0);
// If random r is less than the change percentage then we do the change
if (cp > 0.0) { if (r <= cp) {
if (dt == DELTA_FROM_RANGE) {
if (cb > 0.0) {
// Positive bias
lo = (vmin  v)  ((vmin  v) * cb);
hi = vmax  v;
} else {
// Negative bias
lo = vmin  v;
hi = (vmax  v) + ((vmax  v) * cb);
}
// Else use percentages
} else {
if (cb > 0.0) {
// Positive bias
lo = 1.0 + cb;
hi = 1.0;
} else {
// Negative bias
lo = 1.0;
hi = 1.0 + cb;
}
}
if (dp_osc1_tune_delta_type == DELTA_FROM_RANGE) {
if (cm > 0.0) {
r = rand(lo, hi) * sc;
x = v + r;
if (x < 0.0) { h = 0.5; } else { h = 0.5; };
int c = ((x / cm) + h);
delta_out = c * cm;
} else {
r = rand(lo, hi) * sc;
delta_out = v + r;
}
// Else do the delta from percentage of current value
} else {
if (cm > 0.0) {
r = rand(lo, hi) * sc;
x = v + (v * r);
if (x < 0.0) { h = 0.5; } else { h = 0.5; };
int c = ((x / cm) + h);
delta_out = c * cm;
} else {
r = rand(lo, hi) * sc;
delta_out = v + (v * r);
}
}
if (delta_out < vmin) delta_out = vmin;
if (delta_out > vmax) delta_out = vmax;
}}
return delta_out;
}
Oscillator[1].Tune = delta(Oscillator[1].Tune, Oscillator[1].Tune.min, Oscillator[1].Tune.max, DELTA_FROM_RANGE, 1.0, 0.5, 1.0, 12.0);
?>

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
I see the evil siliconbased forum lifeform has mangled all my code indentations. Here is the original file: DeltaThing2
 KVRAF
 1617 posts since 11 Dec, 2008 from Minneapolis
I tried this and it sounds kinda FUNCy.
Please rate this pun on a scale from '1horrible' to '5so bad I unplugged the computer, set it on fire, shot it, then lobbied the CIA to implement the pun as a secret interrogation technique'.
Thanks for the script. It's equally part exciting to think about scripting (esp. if Urs goes with realtime script execution, like if it'd work without interrupting audio and in the MIDI Program folder), and part daunting. This is really cleverly done.
Please rate this pun on a scale from '1horrible' to '5so bad I unplugged the computer, set it on fire, shot it, then lobbied the CIA to implement the pun as a secret interrogation technique'.
Thanks for the script. It's equally part exciting to think about scripting (esp. if Urs goes with realtime script execution, like if it'd work without interrupting audio and in the MIDI Program folder), and part daunting. This is really cleverly done.

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
Here is the latest from my Delta Thing project, and it is beginning to show signs of being useful The delta function has changed a bit from my first post (including bug fixes), and I figured out most of the potential parameter names and documented them here: http://www.kvraudio.com/forum/viewtopic.php?t=252473 Again the key lines are the last ones, which I now have in a forloop, which checks to see if the module is active rather than changing them all even if they aren't being used. The idea of this delta patch was to make the currently loaded patch in Zebra more "punchy" by decreasing, for example, Attack parameters. If we analyze one of the lines below:
Env.Attack = delta(Env.Attack, Env.Attack.min, Env.Attack.max, DELTA_FROM_RANGE, 1.0, 0.85, 1.0, 0.0, 0.0);
Env.Attack : the index i will go from 1 to 4, processing ENV1, ENV2, ENV3, ENV4
delta() : calls the delta function, which returns a new value (could be the same value)
Env.Attack, Env.Attack.min, Env.Attack.max : passes the current value, min, and max to the delta function
DELTA_FROM_RANGE  use the full range of min to max to randomly select a value from
1.0 : there is a 100% chance that this variable will be randomized
0.85 : a strong negative bias, only 15% of the positive potential new values will be available
1.0 : the randomly chosen value is scaled by 1, i.e. not scaled
0.0 : the change is not rounded to any multiple
0.0 : the final result is not rounded to any multiple
So from all this we see there is a fairly strong tendency that the Attack values for ENV1 through ENV4 will be decreased, thereby making it "more punchy". There is also a small chance it will go the other way, but that's okay too. Note that I also processed MSEG values, and these need to increase to get the same effect.
To use the patch, I loaded up a typical slow moving pad sound, clicked this delta patch several times, and there were several voices that sounded pretty good, being not very padlike.
So the idea would be to have a library of "patches that change patches", each with a specific change characteristic, so that the end user guides the morphing process. Guess we'll see, but it looks doable.
Env.Attack = delta(Env.Attack, Env.Attack.min, Env.Attack.max, DELTA_FROM_RANGE, 1.0, 0.85, 1.0, 0.0, 0.0);
Env.Attack : the index i will go from 1 to 4, processing ENV1, ENV2, ENV3, ENV4
delta() : calls the delta function, which returns a new value (could be the same value)
Env.Attack, Env.Attack.min, Env.Attack.max : passes the current value, min, and max to the delta function
DELTA_FROM_RANGE  use the full range of min to max to randomly select a value from
1.0 : there is a 100% chance that this variable will be randomized
0.85 : a strong negative bias, only 15% of the positive potential new values will be available
1.0 : the randomly chosen value is scaled by 1, i.e. not scaled
0.0 : the change is not rounded to any multiple
0.0 : the final result is not rounded to any multiple
So from all this we see there is a fairly strong tendency that the Attack values for ENV1 through ENV4 will be decreased, thereby making it "more punchy". There is also a small chance it will go the other way, but that's okay too. Note that I also processed MSEG values, and these need to increase to get the same effect.
To use the patch, I loaded up a typical slow moving pad sound, clicked this delta patch several times, and there were several voices that sounded pretty good, being not very padlike.
So the idea would be to have a library of "patches that change patches", each with a specific change characteristic, so that the end user guides the morphing process. Guess we'll see, but it looks doable.
Code: Select all
#defaults=no
#patchname=no
<?
// Delta Thing  Version 3.4
int DELTA_FROM_RANGE = 1;
int DELTA_FROM_VALUE = 2;
// delta()  returns the changed parameter value
// v  the parameter's current value
// vmin  the minimum of the range of v
// vmax  the maximum of the range of v
// dt  type of delta, either from a value chosen from the range,
// or a value which is a percentage of the current value
// cp  probability of there being a change, from 0.0 to 1.0
// cb  change bias is from 1.0 to 1.0
// sc  scaling applied to the random value/percentage
// cm  multiple to round the change to. Use 0.0 for no rounding
// fm  multiple to round the final result to. Use 0.0 for no rounding
float delta( float v, float vmin, float vmax, int dt, float cp, float cb, float sc, float cm, float fm)
{
float r;
float lo;
float hi;
float x;
float h;
int yi;
float yf;
// Assume no change to the current value
x = v;
// Generate a random to determine if a change will occur or not
r = rand(0.0, 1.0);
// If cp exists (i.e. not 0) AND random r is less than the change probability then we do the change
if (cp > 0.0)
{
if (r <= cp)
{
// If delta is to be taken from value's min/max range...
if (dt == DELTA_FROM_RANGE)
{
// Calculate the lo/hi values using the change bias
if (cb > 0.0)
{
// Positive bias
lo = (vmin  v)  ((vmin  v) * cb);
hi = vmax  v;
}
else
{
// Negative bias
lo = vmin  v;
hi = (vmax  v) + ((vmax  v) * cb);
}
// Else the delta is based on lo/hi percentages
}
else
{
// Calculate the lo/hi values using the change bias
if (cb > 0.0)
{
// Positive bias
lo = 1.0 + cb;
hi = 1.0;
}
else
{
// Negative bias
lo = 1.0;
hi = 1.0 + cb;
}
}
// Generate a random scaled change amount
r = rand(lo, hi) * sc;
// If the change amount should be rounded to a multiple
if (cm > 0.0)
{
if (r < 0.0)
{
h = 0.5;
}
else
{
h = 0.5;
}
// Scale by cm, round, and type cast to int
yi = ((r / cm) + h);
// Type cast back to float
yf = yi;
// Unscale back by cm
r = yf * cm;
}
// If delta is from value's min/max range
if (dt == DELTA_FROM_RANGE)
{
// Add change amount to v
x = v + r;
// Else delta is a percentage of current value
}
else
{
// Add change amount percentage of current value
x = v + (v * r);
}
// If the final result should be rounded to a multiple
if (fm > 0.0)
{
if (x < 0.0)
{
h = 0.5;
}
else
{
h = 0.5;
}
// Scale by fm, round, and type cast to int
yi = ((x / fm) + h);
// Type cast back to float
yf = yi;
// Unscale back by fm
x = yf * fm;
}
// Although Zebra will attempt to do limits, sometimes it gets wonky, so do it here too
if (x < vmin)
{
x = vmin;
}
if (x > vmax)
{
x = vmax;
}
}
}
return x;
}
int i;
for ( i = 1; i <= 4; i++ )
{
if (Env[i].active)
{
Env[i].Attack = delta(Env[i].Attack, Env[i].Attack.min, Env[i].Attack.max, DELTA_FROM_RANGE, 1.0, 0.85, 1.0, 0.0, 0.0);
Env[i].Decay = delta(Env[i].Decay, Env[i].Decay.min, Env[i].Decay.max, DELTA_FROM_RANGE, 0.5, 0.75, 0.5, 0.0, 0.0);
Env[i].Release = delta(Env[i].Release, Env[i].Release.min, Env[i].Release.max, DELTA_FROM_RANGE, 0.5, 0.5, 1.0, 0.0, 0.0);
}
}
for ( i = 1; i <= 4; i++ )
{
if (MSEG[i].active)
{
MSEG[i].Attack = delta(MSEG[i].Attack, MSEG[i].Attack.min, MSEG[i].Attack.max, DELTA_FROM_RANGE, 0.5, 0.75, 1.0, 0.0, 0.0);
MSEG[i].Release = delta(MSEG[i].Release, MSEG[i].Release.min, MSEG[i].Release.max, DELTA_FROM_RANGE, 0.5, 0.75, 1.0, 0.0, 0.0);
}
}
?>

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
I whipped together 4 delta patches, LessPunchy1.h2p, MorePunchy1.h2p, MellowFilters1.h2p, and UppityFilters1.h2p, and I've been playing around with them  I'm pretty sure having this much fun is illegal somewhere, but not here in billstei's lab, bwahahahha I will probably start dumping patches here http://www.hbci.com/~billstei/pub/zebra2/DeltaPatches so you can grab them if you want to try it (and they will probably change with bug fixes/improvements).

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
It occurs to me this morning that given a small probability of a large change, versus a large probability of a small change, that we humans turn knobs slowly, and my first experiment/improvement might be to change my delta patches to be more "human". Either that or I need to invent a deltadeltapatch that changes deltapatches that change patches.

 KVRist
 31 posts since 19 May, 2008
nice, very cool.
or instead of deltadelta, maybe different versions of each patch so the end user can select the degree of change he wants to try. Kind of like somewhere earlier in the scripting thread there are randomizers for 25, 50, and 75 percent as well as 100 percent random.
mm
or instead of deltadelta, maybe different versions of each patch so the end user can select the degree of change he wants to try. Kind of like somewhere earlier in the scripting thread there are randomizers for 25, 50, and 75 percent as well as 100 percent random.
mm

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
Exactly. In fact I already put together a set of MorePunchy's for 1/1, 1/10, and 1/100 scalings of the change. Seems to work nicely to vary the desired change (or maybe I should say chaos).mattmitch wrote:nice, very cool.
or instead of deltadelta, maybe different versions of each patch so the end user can select the degree of change he wants to try. Kind of like somewhere earlier in the scripting thread there are randomizers for 25, 50, and 75 percent as well as 100 percent random.
mm
Edit: Uploaded a set of patches like this (old revs moved to Archive subfolder). http://www.hbci.com/~billstei/pub/zebra2/DeltaPatches

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
Although it doesn't use the delta function from the Delta Thing project, I made a fun patch called ScrambledEGs that generates random MSEG envelopes. The MSEG must be active in order for it to change, meaning that particular MSEGx has to be assigned to a knob/parameter in Zebra somewhere. It's in the DeltaPatches folder here: http://www.hbci.com/~billstei/pub/zebra2/DeltaPatches

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
Still more delta things with extra deltaness and deltabilities  the patches SpectroBlendClear, SpectroBlendEvenDown10Percent, SpectroBlendEvenUp10Percent, SpectroBlendOddDown10Percent, and SpectroBlendOddUp10Percent (in my website folder), work on the presently selected Wave[x] (via the Wave knob) of active OSCs. They change all/odd/even harmonics as their names imply.
There are lots of possibilities here for graphical changes to SpectroBlend (and GeoBlend for that matter) wavetables, so if anyone thinks something makes sense (i.e. is actually useful) please make suggestions. Again the idea is not to make a particular waveform, but to change an existing one.
Edit: Added SpectroBlendAllDown10Percent, SpectroBlendAllUp10Percent, SpectroBlendLowDown10Percent, SpectroBlendLowUp10Percent, SpectroBlendHighDown10Percent, SpectroBlendHighUp10Percent. "All" changes all the harmonics. "Low" and "High" scales the change linearly from 10% to >0% across the range of harmonics from LowtoHigh, or HightoLow (easier to see it than to explain it, so just scribble a Blend wave and try each patch).
There are lots of possibilities here for graphical changes to SpectroBlend (and GeoBlend for that matter) wavetables, so if anyone thinks something makes sense (i.e. is actually useful) please make suggestions. Again the idea is not to make a particular waveform, but to change an existing one.
Edit: Added SpectroBlendAllDown10Percent, SpectroBlendAllUp10Percent, SpectroBlendLowDown10Percent, SpectroBlendLowUp10Percent, SpectroBlendHighDown10Percent, SpectroBlendHighUp10Percent. "All" changes all the harmonics. "Low" and "High" scales the change linearly from 10% to >0% across the range of harmonics from LowtoHigh, or HightoLow (easier to see it than to explain it, so just scribble a Blend wave and try each patch).

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
Today's delta stuff:
SBlendLowP3Up10Pct  scaled towards low end, every 3rd harmonic up by 10% (3,6,9,12,...)
SBlendLowP3Down10Pct  scaled towards low end, every 3rd harmonic down by 10%
SBlendLowP4Up10Pct  scaled towards low end, every 4th harmonic up by 10% (4,8,12,16,...)
SBlendLowP4Down10Pct  scaled towards low end, every 4th harmonic down by 10%
The "1Tenth" patches add 0.1 (i.e. they do not use a percentage of the current value):
SBlendAllUp1Tenth  all harmonics up 0.1
SBlendAllDown1Tenth  all harmonics down 0.1
SBlendLowUp1Tenth  scaled towards low end, all harmonics up 0.1
SBlendLowDown1Tenth  scaled towards low end, all harmonics down 0.1
SBlendEvenUp1Tenth  even harmonics up 0.1
SBlendEvenDown1Tenth  even harmonics down 0.1
SBlendOddUp1Tenth  odd harmonics up 0.1
SBlendOddDown1Tenth  odd harmonics down 0.1
Also note that I did some renaming because the file names were a bit long.
Most of these patches don't affect the fundamental, but they could, I just can't make up my mind... easy enough to edit that one manually anyway.
SBlendLowP3Up10Pct  scaled towards low end, every 3rd harmonic up by 10% (3,6,9,12,...)
SBlendLowP3Down10Pct  scaled towards low end, every 3rd harmonic down by 10%
SBlendLowP4Up10Pct  scaled towards low end, every 4th harmonic up by 10% (4,8,12,16,...)
SBlendLowP4Down10Pct  scaled towards low end, every 4th harmonic down by 10%
The "1Tenth" patches add 0.1 (i.e. they do not use a percentage of the current value):
SBlendAllUp1Tenth  all harmonics up 0.1
SBlendAllDown1Tenth  all harmonics down 0.1
SBlendLowUp1Tenth  scaled towards low end, all harmonics up 0.1
SBlendLowDown1Tenth  scaled towards low end, all harmonics down 0.1
SBlendEvenUp1Tenth  even harmonics up 0.1
SBlendEvenDown1Tenth  even harmonics down 0.1
SBlendOddUp1Tenth  odd harmonics up 0.1
SBlendOddDown1Tenth  odd harmonics down 0.1
Also note that I did some renaming because the file names were a bit long.
Most of these patches don't affect the fundamental, but they could, I just can't make up my mind... easy enough to edit that one manually anyway.

 KVRian
 Topic Starter
 595 posts since 20 Jan, 2006
For those of you going crazy wondering why the SpectroBlend patches don't result in the sound changing even though the waveform does... Zebra 2.3.2 apparently has a bug, but this will be fixed in a newer version coming to your neighborhood (I think). In the meantime, wiggling the Normalize knob "fixes" it, which I seem to recall this being mentioned in another thread somewhere (?).