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

Official support for: u-he.com
RELATED
PRODUCTS

Post

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 sub-range 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 8) 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);

?>

Post

I see the evil silicon-based forum lifeform has mangled all my code indentations. Here is the original file: DeltaThing2

Post

I tried this and it sounds kinda FUNCy.

Please rate this pun on a scale from '1-horrible' to '5-so 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 real-time script execution, like if it'd work without interrupting audio and in the MIDI Program folder), and part daunting. This is really cleverly done.

Post

Here is the latest from my Delta Thing project, and it is beginning to show signs of being useful :shock: 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 for-loop, 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 pad-like.

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);
  }
}

?>

Post

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 :hihi: 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).

Post

:zzz: :!: 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 delta-delta-patch that changes delta-patches that change patches. :)

Post

nice, very cool.

or instead of delta-delta, 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

Post

mattmitch wrote:nice, very cool.

or instead of delta-delta, 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
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).

Edit: Uploaded a set of patches like this (old revs moved to Archive sub-folder). http://www.hbci.com/~billstei/pub/zebra2/DeltaPatches

Post

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

Post

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 Low-to-High, or High-to-Low (easier to see it than to explain it, so just scribble a Blend wave and try each patch).

Post

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.

Post

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 (?).

Post

billstei wrote:fixed in a newer version coming to your neighborhood (I think).
I hope tomorrow :-o

Return to “u-he”