Mutable Instruments UGens

All of this is very exciting. I am happy to help out. Are we thinking of putting this as a Stack Package?

Verb as global effect:

(1..SuperDirt.maxSampleNumChannels).do { |numChannels|
  SynthDef("global_mi_verb" ++ numChannels, { |dryBus, effectBus, verbwet=0, verbtime=0, verbdamp=0, verbhp=0, verbfreeze=0, verbdiff=0|
    var signal = In.ar(dryBus, ~dirt.numChannels);
    signal = MiVerb.ar(signal, verbwet, verbtime, verbdamp, verbhp, verbfreeze, verbdiff);
    Out.ar(effectBus, signal)
  }, [\ir, \ir]).add;
};

then

  ~dirt.orbits.do { |x|
    x.globalEffects = ~dirt.orbits[0].globalEffects.addFirst(
      GlobalDirtEffect(\global_mi_verb, [\verbwet, \verbtime, \verbdamp, \verbhp, \verbfreeze, \verbdiff])
  	)
  };

  ~dirt.orbits[0].initNodeTree;

and parameters:

verbwet = pF "verbwet"
verbtime = pF "verbtime"
verbdamp = pF "verbdamp"
verbhp = pF "verbhp"
verbfreeze = pI "verbfreeze"
verbdiff = pF "verbdiff"

the only issue is that also without verb* parameters set, the effect is inserted and it change the sound (it raises the level)

2 Likes

That sounds like a great idea. It seems that most of the code will be SuperCollider code (wraping the mi-ugens). Perhaps a thing to aim for would be a quark package with some supporting documentation about what to add to your BootTidal.hs on the tidal side?

I'm happy to set up a github repo to keep all the code above in the same place, if that would help?

In the first instance having some code to cut-and-paste into the startup.scd and BootTidal.hs files would probably be a step in the right direction.

4 Likes

About the Braids/Plaits modules: Is it better to produce a global synth definitions and a bunch of other specialized ones for each oscillator engine? I guess that switching engine on the fly should remain a possibility but it would be nice to give quick access to a specific engine if the musician feels the need to do that. Something like : Braids, BFold, BSyn, BRing, etc... That's what SuperDirt is doing already by giving access to different waveforms and filters or other raw sound generators.

These modules are huge and packed with different sound possibilities. I'm not sure what is the best "code interface" for them.

EDIT: Some modules can't be used in a straightforward way from Tidal. For instance, Warps is made for blending audio signals together in creative ways. It might be cool to experiment a bit and add some extras synthdefs with "general" and "usable" instrument-patches made with the modules only.

These sound phenomenal... thanks everyone who's digging into this !

PS it's also way over my head for the most part, but some of it may be sinking in - thanks for keeping the discussion open :slight_smile:

As I was playing around in supercollider (rings into clouds, of course) I was wondering whether tidal could have a syntax for chaining together "modules". But perhaps this is out of scope for the Tidal language? We can do that kind of thing in supercollider ultimately.

global effects cloud: really great!
setting #cloudsfreeze 1 it starts to granulate some seconds of audio recorded when freeze was 1.

  SynthDef("global_mi_clouds" ++ numChannels, { |dryBus, effectBus, cloudspitch=0, cloudspos=0, cloudssize=0, cloudsdens=0, cloudstex=0, cloudswet=0, cloudsgain=0, cloudsspread=0, cloudsrvb=0, cloudsfb=0, cloudsfreeze=0, cloudsmode=0, cloudslofi=0|
    var signal = In.ar(dryBus, ~dirt.numChannels);
    Out.ar(effectBus, MiClouds.ar(
      inputArray: signal,
      pit: cloudspitch,
      pos: cloudspos,
      size: cloudssize,
      dens: cloudsdens,
      tex: cloudstex,
      drywet: cloudswet,
      in_gain: cloudsgain,
      spread: cloudsspread,
      rvb: cloudsrvb,
      fb: cloudsfb,
      freeze: cloudsfreeze,
      mode: cloudsmode,
      lofi: cloudslofi
    ));
  }, [\ir, \ir]).add;
    cloudspitch = pF "cloudspitch"
    cloudspos = pF "cloudspos"
    cloudssize = pF "cloudssize"
    cloudsdens = pF "cloudsdens"
    cloudstex = pF "cloudstex"
    cloudswet = pF "cloudswet"
    cloudsgain = pF "cloudsgain"
    cloudsspread = pF "cloudsspread"
    cloudsrvb = pF "cloudsrvb"
    cloudsfb = pF "cloudsfb"
    cloudsfreeze = pF "cloudsfreeze"
    cloudsmode = pF "cloudsmode"
    cloudslofi = pF "cloudslofi"
    -- utility to group the 4 "blend parameters"
    cloudsblend w s f r = cloudswet w # cloudsspread s # cloudsfb f # cloudsrvb r

tides is an lfo, but is also nice as oscillator:

(
  SynthDef(\tides, {|out=0,freq=440,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0,tidesshape=0.5,slope=0.5,tidessmooth=0.5,shift=0.5,mode=2|
    var envLength = sustain*(end-begin)/speed;
    var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf);
    var env = Env.asr;
    var volume = IEnvGen.ar(env, line);
    var sig;

    freq = max(0, freq * speed * (1 + (accelerate * line)));
    sig = MiTides.ar(
      freq: freq,
      shape: tidesshape,
      slope: slope,
      smooth: tidessmooth,
      shift: shift,
      output_mode: mode,
      ramp_mode: 1,
      rate: 1
    );

    Out.ar(out, DirtPan.ar(sig * volume, ~dirt.numChannels, pan));
  }).add;
);

parameters

    mode = pI "mode"
    tidesshape = pF "tidesshape"
    tidessmooth = pF "tidessmooth"
    slope = pF "slope"
    shift = pF "shift"

Don't know... but, the effects order can be defined on superdirt.
E.g. rings can be defined as local effect, and clouds as global effect: boom :slight_smile:

After playing with plaits in tidal, I think I prefer having the access to the different engines all there just by changing a parameter, rather than breaking them out into different definitions. Meta mode on my braids is always fun to play with. I think if we make it easy within the one synth definition to know which engine you're choosing that would be helpful. If each of the different oscillator engine names were ints (i.e., BFold could be 0, BSyn could be 1, etc.), then it would be easy to select the engine by name but would allow for nice # engine (irand 20), or similar.

2 Likes

What's the advantage of having the effects be global? It seems like we can't turn them off as @ndr_brt mentioned.

Based on my little knowledge, a "local" effect works only on single event (eg, a note of a synt or a sample), while a global event works on all the sounds played on a orbit.
So, the effects that modulate the time in my opinon works better as global effects (e.g. reverb/delay/leslie of superdirt), while other kind of modulations (distortion, waveshaping, filters, tremolo, phaser, etc...) are good as local effects.

I'm trying clouds as local effect, but it's not good as when it's a global one.
Rings works well as local.

(ps: to turn them off, when there's a gain (like for clouds) I set it at 0, if there's no gain in the ugen, I add a * <effectname>gain)

Thanks for the explanation. If I do this: d1 $ "bd bd sd ~" # delay 0.5 # delayfb 0.7 # delaytime 0.9 and then do hush i still hear echos afterwards which makes me think time based effects still work locally. Is what you meant something different? Sorry if I'm not understanding exactly the difference still (in terms of the end resulting sound). Or is delay a global effect and that's why it works? And each d1, d2, etc. has a different orbit?

In superdirt delay is a global effect, that's why you hear echoes after an hush. If it were a local one, it would shut off together with the sound generated by the event.

Tidal defines an orbit for each "connection" (d1, d2, etc..).
Every orbit has its set of global effects.
Local effects are instantiated for every event.

Said that, I'm porting all that MI synths/effects into superdirt, for those who are interested here's the code:

(The code to load the global effects is in the superdirt startup file: https://github.com/ndr-brt/sc-adente/blob/master/superdirt_startup.scd#L31)

6 Likes

Got it, thanks!

This should be placed in the docs (for "effects") more prominently. What is the best place?

The "local/global" distinction is mentioned here: https://tidalcycles.org/orbit but to find that, I already have to know about the "orbit" concept. (When I search for "effect" I get too many results. Can the search engine make a difference between: definition and use of a concept (name)?)

After finding the "orbits" page I still don't know whether any given effect is local/global. Is it possible to tag or group the effects description in https://tidalcycles.org/All_effects_and_synths accordingly?

Or is there another way to find out? So instead of tagging each effect (too much work), we can put a description "Each effect is either local or global (link to explanation of concept). To find out which, look for property ?? in (link to effect definitions in Superdirt??)".

[EDIT] Ah you already answered this? "the code for loading global effects ..." (sc-adente/superdirt_startup.scd at master · ndr-brt/sc-adente · GitHub) Or is this specific to your setup?

Sorry for going on a tangent here. Feel free to move to Innards (?). What is the current process to contribute documentation? I recall there was a recent discussion, also leading to some changes, but I did not follow closely.

1 Like

Yep, there's another discussion about documentation (Updating the Tidal website and documentation - #47 by yaxu), there's a plan to move everything on a markdown based static site (https://doc.tidalcycles.org), at the moment the documentation is the wiki on tidalcycles.org, everyone signed in can modify it.

The code I linked is specific to my setup, I did some trial/error to load those synths/effects.
Not particulary complicated, I admit that I had to look at the superdirt code to understand the signature of some functions, but it worked well enough.

1 Like

What are you guys using as documentation for these ugens?

Just the code, or their own website, or?

The .schelp files in the repository:

2 Likes

The manuals on the MI site (e.g this one for plaits) are also very useful.

2 Likes

I'm having a hard time getting clouds to work. I used your mutable.scd file and afterwards did:

 ~dirt.orbits.do { |x|
    var clouds = GlobalDirtEffect(\global_mi_clouds, [\cloudspitch, \cloudspos, \cloudssize, \cloudsdens, \cloudstex, \cloudswet, \cloudsgain, \cloudsspread, \cloudsrvb, \cloudsfb, \cloudsfreeze, \cloudsmode, \cloudslofi]);
    var verb = GlobalDirtEffect(\global_mi_verb, [\verbwet, \verbtime, \verbdamp, \verbhp, \verbfreeze, \verbdiff, \verbgain]);
    x.globalEffects = x.globalEffects
      .addFirst(clouds)
      .addFirst(verb);

    x.initNodeTree;
  };

In Tidal I'm doing:

d1 $ s "bd bd sd ~" # cloudspitch "1" # cloudspos "0.5" # cloudswet "0.5" # cloudssize "0.5" # cloudsdens "0.5" # cloudstex "0.5" # cloudsgain "5.5" # cloudsspread "0.5"# cloudsrvb "0.5" # cloudsfb "0.5" # cloudsfreeze "0" # cloudsmode "0" # cloudslofi "0"

Any thoughts? What am I missing?