Mutable Instruments UGens

Hi folks. I've been trying to regularly create something for Jamuary and today I decided to play with the various ports of the Mutable Instruments eurorack modules to SuperCollider. I installed the UGens on my OS X machine (the pre-compiled binaries were not signed so I couldn't use them as-is, so I decided to compile them myself. The compilation instructions worked fine for me). Following @eris excellent tutorial I created a very basic wrapper for the Plaits UGen

(
SynthDef(\plaits, {|out, sustain=1, pan, accelerate, freq, harm=0.5, timbre=0.5, morph=0.5, engine=0|
    var env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01, 1,-3), timeScale:sustain, doneAction:2);
	var sound = MiPlaits.ar(pitch: freq.cpsmidi, engine: engine, harm: harm, timbre: timbre, morph: morph);
	Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env));
}).add
);

I'm using a simple envelope here just to get something working, but I think that could be improved (or I could rely on the envelope generator in Plaits instead).

And here's an example of how I used it in Tidalcycles:

let harm = pF "harm"
let timbre = pF "timbre"
let morph = pF "morph"
let engine = pI "engine"

d1 $ slow 2 $ n "{0, 3 7 3 <0 7>}(5,8)" |-24 # sustain 0.1 # s "plaits" # engine (irand 15) # room 0.4 # gain 0.75

I recorded some of my jam, here I'm randomly modulating the synthesis "engine" that Plaits uses to create some glitchy effects. I recorded directly from SuperCollider.

Has anyone else played with these UGens in Tidal? I had a lot of fun running the various examples from the documentation in SuperCollider, and connecting different modules together. I might spend some time creating some wrappers for these UGens to use in Tidal. I think some of them, like rings might work as both "synths" and "effects" and I'm not quite sure what the best interface would be to allow them to be chained together.

28 Likes

I wasn't aware that there is a SuperCollider port of these modules! I'm really happy that you posted about it because these modules are excellent and more people might be encouraged to play with them. For those of you who haven't seen Mutable modules in action, I encourage you to take a look (Plaits Module Demo) ! It's really great to see that Émilie Gillet is open-sourcing all this.

I’ll try to follow your steps and compile them.

1 Like

Thanks for the reference!

I'm currently trying it, I was a bit confused by the installation instructions, so I'm putting more detailed steps here to save time for further noobs.

Collect the UGen files from the build folders of the projects and put them together with the sc folder into your SC extensions folder.

For reference, on my Linux computer, the UGen files were the .sc files in the mi-UGens/sc/Classes folder, and the SC extensions folder was ~/.local/share/SuperCollider/Extensions/.

5 Likes

Heeyyy this are awesomee.
Having so much fun with plaits and rings.
The reverb also is super luuushh

That's really exciting - I'd love to hear what you all come up with and any ideas you have for interfaces between tidal and these ugens.

Have you tried to use the clouds Ugen? I've tried it as a globalEffect and as an Insert type effect. The first method produced some results, but noting interesting, always sounds to low and rumbly. With the insert fx approach I won't get anything and SuperDirts prints "MiClouds > numAudioIns: 2", which I don't know what it means (maybe clouds expects a signal array bigger? or smaller? I dunno...)

what does your directory structure look like?

(on Linux) after plenty of folder rearranging I keep getting:

exception in GraphDef_Recv: UGen 'MiPlaits' not installed.

after messing around with the MI clones on VCV Rack in the past, it would be really fun to use these in Tidal!

however I'm pretty clueless when it comes to SuperCollider and I'm evidently doing something wrong...

thanks!

I don't understand which other informations about directory structure you need beside the paths I gave.

Here are the precise commands I typed to install the UGens:

git clone --recurse-submodules https://github.com/v7b1/mi-UGens.git
git clone https://github.com/supercollider/supercollider
cd mi-UGens/
./linux-build.sh /tmp/supercollider/
cp sc/Classes/* ~/.local/share/SuperCollider/Extensions/

If your issue is with locating the equivalent of ~/.local/share/SuperCollider/Extensions, try starting an instance of SuperCollider and looking up which directories appear at the very beginning of the log. For me it's:

compiling class library...
	Found 862 primitives.
	Compiling directory '/usr/share/SuperCollider/SCClassLibrary'
	Compiling directory '/usr/share/SuperCollider/Extensions'
	Compiling directory '~/.local/share/SuperCollider/Extensions'
	Compiling directory '~/.local/share/SuperCollider/downloaded-quarks/Vowel'
	Compiling directory '~/.local/share/SuperCollider/downloaded-quarks/Dirt-Samples'
	Compiling directory '~/.local/share/SuperCollider/downloaded-quarks/SuperDirt'
	numentries = 1223511 / 19201236 = 0.064
	5919 method selectors, 3244 classes
	method table size 20136680 bytes, big table size 153609888
	Number of Symbols 15060
	Byte Code Size 431257
	compiled 485 files in 1.59 seconds
1 Like

interesting - I thought maybe the .sc files had to be in their own folder in Extensions (hence why I was asking about directory structure) however I've already tried the steps that you've described (twice to be sure!) and I still get the same error.

thank you anyway @th4

:slight_smile:

I had the same issue... I resolved copying the .so files as reported in the guide:

Collect the UGen files from the build folders of the projects and put them together with the sc folder into your SC extensions folder.

I did it with this command:
cp **/build/*.so ~/.local/share/SuperCollider/Extensions

this was it! apparently I am incapable of following instructions.

thanks both of you

1 Like

Hey, I'm not able to define an effect with any of those (tried with clouds and verb).

I define the effect this way:

(
~dirt.addModule('verb', { |dirtEvent|
	dirtEvent.sendSynth('verb' ++ ~dirt.numChannels,
		[
      vwet: ~vwet,
			vtime: ~vtime,
			vdamp: ~vdamp,
			vhp: ~vhp,
			vfreeze: ~vfreeze,
			vdiff: ~vdiff,
		]
	)
}, {~vwet.notNil});

SynthDef("verb" ++ ~dirt.numChannels, { |out, vwet=0.5, vtime=0.7, vdamp=0.5, vhp=0.05, vfreeze=0, vdiff=0.625|
	var signal = In.ar(out, ~dirt.numChannels);
	signal = MiVerb.ar(signal, vwet, vtime, vdamp, vhp, vfreeze, vdiff);
  ReplaceOut.ar(out, signal)
}).add;

);

I also configured the parameters on tidal like:

let vwet = pF "vwet"
    vtime = pF "vtime"
    vdamp = pF "vdamp"
    vhp = pF "vhp"
    vfreeze = pI "vfreeze"
    vdiff = pF "vdiff"

there's something I'm missing?

I had actually copied the .so files before, which didn't work for me, so I'm postulating that both the .scd and the .so are needed.

Looks like you forgot to add "out" when adding the module to dirt (right after vdiff: ~vdiff). This works for me:

(
~dirt.addModule('verb', { |dirtEvent|
	dirtEvent.sendSynth('verb' ++ ~dirt.numChannels,
		[
			vwet: ~vwet,
			vtime: ~vtime,
			vdamp: ~vdamp,
			vhp: ~vhp,
			vfreeze: ~vfreeze,
			vdiff: ~vdiff,
			out: ~out
		]
	)
}, {~vwet.notNil});
)

~dirt.modules;

(
SynthDef("verb" ++ ~dirt.numChannels, { |out, vwet=0.5, vtime=0.7, vdamp=0.5, vhp=0.05, vfreeze=0, vdiff=0.625|
	var signal = In.ar(out, ~dirt.numChannels);
	signal = MiVerb.ar(signal, vwet, vtime, vdamp, vhp, vfreeze, vdiff);
  ReplaceOut.ar(out, signal)
}).add;

);
2 Likes

thank you, it works! but I think they'll work better as global effects, will try that soon

Great! Share with us your results.

Does anyone want to start a collective effort for writing SuperDirt bindings for Mutable UGens? I believe that it would be a great addition to Tidal, some as instruments and others as Global Effects. It would be nice to have an efficient and easy way to install them and connect them to Tidal.

6 Likes

Rings is working nicely!

In Tidal:

let ringsfreq = pF "rfreq"
let ringsstruct = pF "rstruct"
let ringsbright = pF "rbright"
let ringsdamp = pF "rdamp"
let ringspos = pF "rpos"
let ringsmodel = pI "rmodel"
let ringsintern_exciter = pI "rintern_exciter"
let ringstrig = pI "rtrig"
let ringseasteregg = pI "reasteregg"
let ringsbypass= pI "rbypass"

Then is SC:

(
~dirt.addModule('rings', { |dirtEvent|
	dirtEvent.sendSynth('rings' ++ ~dirt.numChannels,
		[
			rtrig: ~rtrig,
			rfreq: ~rfreq,
			rstruct: ~rstruct,
			rbright: ~rbright,
			rdamp: ~rdamp,
			rpos: ~rpos,
			rmodel: ~rmodel,
			rpoly: ~rpoly,
			rintern_exciter: ~rintern_exciter,
			reasteregg: ~reasteregg,
			rbypass: ~rbypass,
			out: ~out
		]
	)
}, {~rbright.notNil});
)

(
SynthDef("rings" ++ ~dirt.numChannels, { |out, rtrig=0, rfreq=60.0, rstruct=0.75, rbright=0.75, rdamp=0.4, rpos=0.9, rmodel=0, rpoly=1,rintern_exciter=0, reasteregg=0, rbypass=0|
	var signal = In.ar(out, ~dirt.numChannels);
	signal = MiRings.ar(signal, rtrig, rfreq, rstruct, rbright, rdamp, rpos, rmodel, rpoly,rintern_exciter, reasteregg, rbypass);
  ReplaceOut.ar(out, signal)
}).add;

);

Use in Tidal:

d1 $ s "sn*16" # ringsbright tri # ringsfreq 30 # slow 2 (ringspos saw) # ringsmodel 0 # ringsstruct 0.75 # ringsdamp 0.4
3 Likes

Sure, I'm in for being part of the collective.

Set both the ringstrig and ringsinternal_exciter to 1 to use the internal exciter. It will combine with whatever sample sound is being sent in:

d2 $ s "hh*16" # ringsbright perlin # ringsfreq 30 # slow 2 (ringspos saw) # ringsmodel (irand 4) # ringsstruct 0.75 # ringsdamp 0.4 # ringseasteregg 0 # ringstrig 1 # ringsintern_exciter 1 # ringsbypass 0 # gain (range 0.9 1.5 rand) 

Having too much fun with this. Plaits and rings:

--plaits
d1 $ slow 0.5 $ n "[0*8, 0(3,8)]" |-18 
# sustain 0.1 
# s "plaits" 
# engine 6 
# room 0.7 
# gain 0.75 
# harm (range 0.8 1.0 $ perlin) 
# timbre (range 0.45 0.5 $ perlin) 
# slow 8 (morph (range 1.0 0.9 $ square)) 

-- rings
d2 $ sometimesBy 0.4 (# ringseasteregg 1) 
$ sometimesBy 0.7 (# ringsbypass 1) 
$ s "hh*16" 
# ringsbright perlin 
# ringsfreq 30 
# slow 2 (ringspos saw) 
# slow 2 (ringsmodel (run 4)) 
# ringsstruct 0.75 
# ringsdamp 0.4 
# ringstrig 1 
# gain (range 0.9 1.5 rand)

3 Likes