The Zebra Scripting Thread
-
- KVRAF
- 4229 posts since 9 Apr, 2003 from Right here, in front of my computer...
I guess as Urs is planning to be doing some scripting docs at this point in time, I'll put in a request for a little pre-documentation scripting help for when he gets back...
Basically, I want to do a script that will randomise select parameters for Osc1 each time you run it, as a quick way of generating random different tone ideas. Including stuff like waveforms, wave knob, osc FX, phase, sync settings that kind of stuff. The few scripts already out there don't really contain enough info to reverse engineer this stuff yet.
So you could say load a 2-osc pad sound from the presets, you could flip through random osc scripts which would give you the same pad sound but just modify the osc parameters for some quick different tone settings.
Obviously, in time we're going to get some more sophisticated randomiser scripts and so on (I'm not too keen on *random* randomisers, but more intelligent ones can be very cool) but for now, this would be fun.
So if Urs can get us started on how to access some of the Osc1 parameters from a script, and maybe the names of how they are referenced, that'd be appreciated. If not, I'll wait for the docs, no probs.
Is there a way to get Z2 to dump out all the internal parameter names and data structures to a text file already?
Other scripts that would be cool include (some of these might not be possible from scripting alone, but I'll mention them anyway):
- "Lock" all parameters except certain modules so you could browse the presets but only be loading in the unlocked modules - so for example, you could lock all parameters except the FX so you could select the different presets and only load their effects settings into the current patch.
- Randomise All Oscillators
- Randomise Filters
- Randomise Grid Order
- "Evolve" patches
- Crossbreed two different patches (I know these things are a bit more tricky because of differences in patch architecture)
- "Pad-ify" (set all EG's to pad-type settings)
- "Percussify" (set all EG's to drum-type envelope settings)
- Mod wheel->Flter (quickly set up mod wheel mod routings to all filter modules)
- DX-ify (Add FMO's in a random config, and set random ratios/FM amounts/scaling settings and so on)
- Analogify (Add random small amounts of filter drives, saturation, detuning and so on)
These are a few I can think of off the top of my head that would be cool, I'm sure other people can think of plenty more ideas...
Basically, I want to do a script that will randomise select parameters for Osc1 each time you run it, as a quick way of generating random different tone ideas. Including stuff like waveforms, wave knob, osc FX, phase, sync settings that kind of stuff. The few scripts already out there don't really contain enough info to reverse engineer this stuff yet.
So you could say load a 2-osc pad sound from the presets, you could flip through random osc scripts which would give you the same pad sound but just modify the osc parameters for some quick different tone settings.
Obviously, in time we're going to get some more sophisticated randomiser scripts and so on (I'm not too keen on *random* randomisers, but more intelligent ones can be very cool) but for now, this would be fun.
So if Urs can get us started on how to access some of the Osc1 parameters from a script, and maybe the names of how they are referenced, that'd be appreciated. If not, I'll wait for the docs, no probs.
Is there a way to get Z2 to dump out all the internal parameter names and data structures to a text file already?
Other scripts that would be cool include (some of these might not be possible from scripting alone, but I'll mention them anyway):
- "Lock" all parameters except certain modules so you could browse the presets but only be loading in the unlocked modules - so for example, you could lock all parameters except the FX so you could select the different presets and only load their effects settings into the current patch.
- Randomise All Oscillators
- Randomise Filters
- Randomise Grid Order
- "Evolve" patches
- Crossbreed two different patches (I know these things are a bit more tricky because of differences in patch architecture)
- "Pad-ify" (set all EG's to pad-type settings)
- "Percussify" (set all EG's to drum-type envelope settings)
- Mod wheel->Flter (quickly set up mod wheel mod routings to all filter modules)
- DX-ify (Add FMO's in a random config, and set random ratios/FM amounts/scaling settings and so on)
- Analogify (Add random small amounts of filter drives, saturation, detuning and so on)
These are a few I can think of off the top of my head that would be cool, I'm sure other people can think of plenty more ideas...
- KVRAF
- 4197 posts since 23 May, 2004 from Bad Vilbel, Germany
Yes, that would be great. I'm looking forward to getting my teeth into "ZScript" (does it already have a name?)beej wrote:I guess as Urs is planning to be doing some scripting docs at this point in time, I'll put in a request for a little pre-documentation scripting help for when he gets back...So if Urs can get us started on how to access some of the Osc1 parameters from a script, and maybe the names of how they are referenced, that'd be appreciated.
See Virus Control - works very well, BTW."Lock" all parameters except certain modules...
Which grid do you mean? Wave order?- Randomise Grid Order
I think such functions might take more time and effort to get right than they are worth.- "Evolve" patches
- Crossbreed two different patches
- "Pad-ify" (set all EG's to pad-type settings)
- "Percussify" (set all EG's to drum-type envelope settings)
- Mod wheel->Flter (quickly set up mod wheel mod routings to all filter modules)
- DX-ify (Add FMO's in a random config, and set random ratios/FM amounts/scaling settings and so on)
But if 3rd parties want to go there...
Yes, please. Do you already know whether ZScript is suitable for the following extra functionality? :- Analogify (Add random small amounts of filter drives, saturation, detuning and so on)
* Copy/paste module parameters. Entire oscillators/noise generators, individual osc waves, filters/combs, envelopes, arpeggios, complete effects, individual effects, pad assignments...
* Convert waves from one mode to another
* Change the root path of the patch library.
* "Compactify" the patching grids
-
- KVRAF
- Topic Starter
- 4229 posts since 9 Apr, 2003 from Right here, in front of my computer...
Yeah, I've just seen that, it's the kind of thing I had in mind. These kinds of functions are a nice easy way to get new sound ideas quickly without much effort, so I support them wholeheartedly!Howard wrote:See Virus Control - works very well, BTW."Lock" all parameters except certain modules...
The main module grid where you insert modules and wire them up. Randomising the positions and orders of the modules and envelope assignments (with certain limitations) might be interesting,Howard wrote:Which grid do you mean? Wave order?- Randomise Grid Order
Yeah, that's an important one, but is probably more in need of a standard way of handling it in the gui - maybe for a new Zebra version...Howard wrote: * Copy/paste module parameters. Entire oscillators/noise generators, individual osc waves, filters/combs, envelopes, arpeggios, complete effects, individual effects, pad assignments...
Nice idea!Howard wrote: * Convert waves from one mode to another
- u-he
- 30213 posts since 8 Aug, 2002 from Berlin
All of these ideas might work, except for crossbreeding patches... the scripting will not have access to actual files, it only has access to data that's already loaded into Zebra...
Adding support for filesystem functions (open, read, write...) would indeed open pandora's box, as this could be abused to create Zebra patches that install malware...
However, one thing to think about is this:
The u-he engine that drives all recent plugins is based on the concept of absolute modularity. This has the advantage that stuff is easy to maintain and it's easy to create a clear design. The disadvantage though is, the modules don't know about each other and there's no entity that could offer functions that work on multiple modules at once.
Now comes the scripting part. A script (like a normal preset) can have access to every parameter in every module at once. So the idea here is, one can add editing functions that can not be done (with reasonable effort) within normal coding.
You could
- grab the last note that was played on the keyboard, i.e. an A, and set up a microtuning table that "quantizes" the whole keyboard to match A minor - like the arpeggiator in Live
- Rotate the Arpeggiator Sequence left or right, so that the first step jumps into the last used slot and vice versa
- For those who want to be able to audition patches without effects, I have planned to add a customizable "standard script" that will always be executed when a preset is loaded. It could just move effects mix/levels to XY4 and set XY4 fully down...
Stuff like that...
... before it goes to next generation where i.e. oscillator waveforms could be calculated in realtime or scripts could be executed upon midi events...
Urs
Adding support for filesystem functions (open, read, write...) would indeed open pandora's box, as this could be abused to create Zebra patches that install malware...
However, one thing to think about is this:
The u-he engine that drives all recent plugins is based on the concept of absolute modularity. This has the advantage that stuff is easy to maintain and it's easy to create a clear design. The disadvantage though is, the modules don't know about each other and there's no entity that could offer functions that work on multiple modules at once.
Now comes the scripting part. A script (like a normal preset) can have access to every parameter in every module at once. So the idea here is, one can add editing functions that can not be done (with reasonable effort) within normal coding.
You could
- grab the last note that was played on the keyboard, i.e. an A, and set up a microtuning table that "quantizes" the whole keyboard to match A minor - like the arpeggiator in Live
- Rotate the Arpeggiator Sequence left or right, so that the first step jumps into the last used slot and vice versa
- For those who want to be able to audition patches without effects, I have planned to add a customizable "standard script" that will always be executed when a preset is loaded. It could just move effects mix/levels to XY4 and set XY4 fully down...
Stuff like that...
... before it goes to next generation where i.e. oscillator waveforms could be calculated in realtime or scripts could be executed upon midi events...
-
- KVRAF
- 1927 posts since 30 Oct, 2003 from Frolicking in Dirac's Ocean
- KVRian
- 581 posts since 21 Feb, 2005 from Upper Left USA
Would it be possible to randomize patches with a script then?
-
- KVRian
- 864 posts since 4 Apr, 2001 from Finland
In case you didn't know, Tarekith, Zebra already comes with a preset that maps random things onto the X/Y controls and you can play with them. It's "UH Random XY" in the "Zebra Scripts" folder.
- KVRian
- 581 posts since 21 Feb, 2005 from Upper Left USA
Thanks I didn't know that, nor see it mentioned in the online manual!
-
- KVRAF
- Topic Starter
- 4229 posts since 9 Apr, 2003 from Right here, in front of my computer...
- KVRian
- 581 posts since 21 Feb, 2005 from Upper Left USA
-
- KVRist
- 114 posts since 3 Apr, 2005
Tarekith wrote:Is that on the u-he site?
I dont think he has posted it on the web site yet. But it would be nice with a link to different scripts that users can try out.Urs wrote:Hehehe...
here's another one... and it changes slightly each time you load it!
I call it "SawRand.h2p"
Code: Select all
#defaults=no #cm=OSC Wave=2 <? float Wave[ 128 ]; float filter = 0.2f; for ( int table = 1; table <= 16; table++ ) { float saw = 1.0f; float saw_inc = -2.0f/127.0f; float out = 1.0f; for ( int i = 0; i < 64; i++ ) { out *= (1.f - filter); out += saw * filter * rand(filter * -0.25f, filter * 2.f); Wave[ i ] = out; Wave[ 127 - i ] = -out; saw += saw_inc; } filter *= 1.12f; Selected.WaveTable.set( table, Wave ); } ?>
Regards
Replicator
- u-he
- 30213 posts since 8 Aug, 2002 from Berlin
Yo, I think I'll start on the scripting docs soonishly... this will include a lot of sample scripts, naturally.
But I think there's also need for improvement on the implementation side, such as an output facility that reports errors and debug messages... we'll see...
Later,
Urs
But I think there's also need for improvement on the implementation side, such as an output facility that reports errors and debug messages... we'll see...
Later,
-
- KVRAF
- Topic Starter
- 4229 posts since 9 Apr, 2003 from Right here, in front of my computer...
- u-he
- 30213 posts since 8 Aug, 2002 from Berlin
Depends...beej wrote:Ooh, I've just remembered that you can save patches in h2p extended format, which might give me some scripting clues to access those parameters...
Actually a parameter should always have the name that's shown on the big display when you turn a knob.
And then there are complex parameters... hmmm... some of these can only be set at the moment, such as MSEGs...
However, here are some findings in my test script folder:
Code: Select all
#defaults=no
<?
Grid.clear();
Grid.setCell( 0, 5, Filter[ 2 ].id, 0, 0 );
?>
- getting the ID of a module
- using that ID to put something in a grid
Parameters for setCell: column, row, ModuleID, input channel, side chain
Take care though... dunno if this could be used in malicious ways...
Code: Select all
#defaults=no
<?
float stepDuration = 1.0;
float fade = 0.5;
float levels[ 16 ] = { 1.0, 0.1, 0.5, 0.0,
1.0, 0.0, 0.5, 0.0,
1.0, 0.0, 0.5, 0.0,
1.0, 0.0, 0.5, 0.0
};
float value = 0.f;
float fadeIn = stepDuration * fade;
float levelTime = stepDuration - fadeIn;
MSEG1.setSegment( 1, value, fadeIn, -1.0, 0 );
for ( int i = 1; i <= 16; i++ )
{
value = levels[ i - 1 ];
MSEG1.setSegment( i * 2, value, levelTime, 0.0, 0 );
MSEG1.setSegment( i * 2 + 1, value, fadeIn, -1.0, 0 );
}
?>
Code: Select all
#defaults=no
<?
float a = 0;
float b = 1;
int count = 0;
float testFunc( int inOne, float inTwo, int inPotenz )
{
if( inOne >= inPotenz ) return (inTwo);
count++;
inTwo *= 2.f;
float out = testFunc( inOne + 1, inTwo, inPotenz );
return (out);
}
a = testFunc( 0, b, 16 );
?>
There are still some dead spots though:
- Microtuning table is not yet accessible
- Key/Velocity Zones are dark yet
- Parameters that still have a space in their names...
- spline based oscillator waveforms
Most importantly, there is still no support for literals. Thus parameters that take text as input (i.e. xy-labels) can not be scripted. I'll be working out a simple way for this though...
Later,

