Automatical Gui for SynthDef Midikeyboard

Hey, I’ve realized here is now a Forum after the Mailinglist got removed. Amazing!

I’ve been wondering if there is an easy way or method for my midi keyboard SynthDef - to have its arguments controlled by a prewritten GUI. Similar to Ndef.gui.
I want to be able to change just all parameter with a fader or anything, except velocity/amp or frequency which is defined by the controller.

Anything in this direction? I really don’t want to take care of lots of code and thought someone already did something like this.

Thank you very much!

Hi, yes the forum is amazing, welcome :slight_smile:

The answer to your question depend a lot of how you manage your MIDI binding with you SynthDef

I am currently writing a quark whose goal is auto GUI and easy control. This is still in alpha stage but you might find it useful.

Here is the pattern approach: you define a Pdef, and there is already an auto GUI for it with PdefEditor. You can then use SeqPlayerGroup to bind your MIDI controller the pattern. There is lot of flexibility, let me know if you have something different in mind.

// init quark prototypes. Needed because SeqPlayerGroup and PdefEditor are not class code
ParamProto.init; 

// define a pattern
(
Pdef(\mysynth, 
	Pbind(
		\instrument, \default,
	)
);
);

// edit it with the PdefEditor
WindowDef(\PdefEditor).front(Pdef(\mysynth))

// control it with MIDI
(
~pgroup = ProtoTemplateDef(\SeqPlayerGroup).new(Pdef(\mysynth));
MIDIdef.noteOn(\piano, { arg velocity, noteNum, channel, deviceId;
	[ velocity, noteNum, channel, deviceId ].debug;
	~pgroup.elAt(noteNum).play;
});
MIDIdef.noteOff(\piano_off, { arg velocity, noteNum, channel, deviceId;
	[ velocity, noteNum, channel, deviceId ].debug;
	~pgroup.elAt(noteNum).stop;
});
)

I guess you want to put parameters in bus mode to be able to control the value while the note is playing

Pdef(\mysynth).setBusMode(\cutoff); // set \cutoff parameter of your synth in bus mode

You can also easily write you custom auto GUI

You can download the quark here

Hi and welcome,

you can check VarGui from miSCellaneous_lib quark. Many possibilities to use it with or without patterns. VarGui’s help file is quite large, the chapter ‘Tour 1’ of ‘Introduction to miSCellaneous’ might be a better starting point.
Independant from this, a principal decision would be if you want a monophonic synth (Pmono style, resp. Pbind with event type ‘set’) or a sequence of synths (‘normal’ Pbind of type ‘note’).

Daniel

Mh, when i download the quarks I get a bunch of nonexistent class errors and syntax errors in the files :S

Am I missing something maybe?

EDIT: i mean the param quarks.

Hello Daniel, thanks for responding, but I dont see how VarGui can be used for my purpose. Since i want to create a new synth with every note pressed on the keyboard.
But VarGui does create the synth pattern itself, no?

I don’t see how this solves my problem.

Sorry, I forgot that this quark have dependencies to other quarks that also need to be installed.

I think the easiest way to install them all at once is by running this code:

Quarks.install(“https://github.com/grirgz/param”);

You may get “duplicate class” error once you restart Supercollider:
This is because you already installed the Param quark previously, so you need to remove your old copy

Also it is possible that you get “duplicate class” error with UnitTesting quark. You have to remove it from your downloaded-quarks folder (if you are on linux, it is in ~/.local/share/SuperCollider/, else I don’t know sorry :confused: )

Thanks you for responding but this was the way I’ve been installing it. Also I’m using Linux. I’ve had to manually also install some other additional Quarks.
Some problems still continue.
Let me copy paste some of the errors:

ERROR: Class extension for nonexistent class ‘MKtlElement’

ERROR: Class extension for nonexistent class ‘MKtlElementGroup’

ERROR: Message ‘newHex’ not understood.

WARNING: SCDoc: Classes/Builder has no categories!
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/ClipTimeline.schelp
Property setter isPlaying_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/ClipTimeline.schelp
Property setter isRecording_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/ClipTimeline.schelp
Property setter outBus_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/ClipTimeline.schelp
Property setter label_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/ClipTimeline.schelp
Property setter quant_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/NoteTimeline.schelp
Property setter isPlaying_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/NoteTimeline.schelp
Property setter isRecording_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/NoteTimeline.schelp
Property setter outBus_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/NoteTimeline.schelp
Property setter label_ should be documented without underscore.
WARNING: SCDoc: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/NoteTimeline.schelp
Property setter quant_ should be documented without underscore.
ERROR: In /home/leafcat/.local/share/SuperCollider/downloaded-quarks/param/HelpSource/Classes/ParamEnvSpec.schelp:
At line 5: syntax error, unexpected newline, expecting text or URL
WARNING: SCDoc: Guides/Param_modifications has no categories!

Ok, I see, I didn’t read that from your first post, so I suggested the two variants. Anyway I’m posting these different approaches below, indeed examples of this kind are not contained in the VarGui help. Nothing complicated but different things have to be put together.

It can generate a Stream from a given Pattern (or take over a passed Stream) but there’s no need to do so.

// 1) Generating new synths with each MIDI trigger

// the newly generated synths can take over values from buses

(
~bus = Bus.control(s, 2);

// helper synth, playing to buses

SynthDef(\setBus, { |width = 0.5, pan = 0|
	Out.kr(~bus, [width, pan])
}).add;

// sound synth, needs envelope

SynthDef(\synth_with_env, {|out = 0, freq = 440, width = 0.5, amp = 0.1, pan = 0,
	att = 0.01, rel = 1, curveAtt = -5, curveRel = 5|
	Out.ar(out, Pan2.ar(Pulse.ar(freq, width.lag(0.1), amp), pan)
		* EnvGen.ar(Env.perc(), doneAction: 2)
	)
}).add;
)

// generate gui and start helper synth playing to buses by pushing green button
(
v = VarGui(
	synthCtr: [
		\width, [0.01, 0.99, \lin, 0, 0.5],
		\pan, [-1, 1, \lin, 0, 0]
	],
	synth: \setBus
).gui
)

// connect MIDI and define MIDIFunc


(
MIDIIn.connectAll;

m = MIDIFunc.noteOn({ |...args|
	var midi = args[0];
	var amp = args[1] / 127;
	// with every MIDI trigger one Event is played
	(
	 	instrument: \synth_with_env,
	 	midinote: midi,
	 	amp: amp,
		// mapping mechanism used in Event/Pbind
	 	width: ~bus.subBus(0).asMap,
	 	pan: ~bus.subBus(1).asMap,
	 	latency: 0
	).play;
}); // match any noteOn
)


// spoof a note on, or play with your MIDI device
// check changing params with gui (also applies during Event as mapped)

MIDIIn.doNoteOnAction(1, 1, 64, 63);

MIDIIn.doNoteOnAction(1, 1, 20, 70);

MIDIIn.doNoteOnAction(1, 1, 40, 74);


// free resources: stop synth in gui and free MIDIFunc (also happens with Cmd-.)

m.free


// 2) Monophonic approach, only one synth


// sound synth

(
SynthDef(\synth_without_env, { |out = 0, freq = 440, width = 0.5, amp = 0.1, pan = 0,
	att = 0.01, rel = 1, curveAtt = -5, curveRel = 5|
	Out.ar(out, Pan2.ar(Pulse.ar(freq, width.lag(0.1), amp), pan))
}).add;
)

// start synth silently

x = Synth(\synth_without_env, args: [amp: 0]).register;

// start gui taking over above already running Synth
(
v = VarGui(
	synthCtr: [
		\width, [0.01, 0.99, \lin, 0, 0.5],
		\pan, [-1, 1, \lin, 0, 0]
	],
	synth: x
).gui
)

// connect MIDI and define MIDIFunc that sets the running Synth
(
MIDIIn.connectAll;

n = MIDIFunc.noteOn({ |...args|
	var midi = args[0];
	var amp = args[1] / 127;
	x.set(\freq, midi.midicps, \amp, amp)
}); // match any noteOn
)


// spoof a note on, or play with your MIDI device
// check changing params with gui

MIDIIn.doNoteOnAction(1, 1, 64, 63);

MIDIIn.doNoteOnAction(1, 1, 20, 70);

MIDIIn.doNoteOnAction(1, 1, 40, 74);


// free resources

x.free;
n.free;
1 Like

You can ignore errors for Class extension, it will not block compilation. It is some optional useful methods to use Param with the Modality-toolkit quark (a quark to manage your controllers)

My bad, I thought i had removed any reference to wslib quark but it seems not. I have now fixed it and pushed to git if you still want to try Param quark.

I forgot to check the last help file I added, I will fix theses. Anyway they are not errors so should not prevent you from booting the language or using help.

Thank for reporting the errors and warnings, it’s always useful to have some feedback :slight_smile: