Is there a Way to do a Action after Play-Synth

Hello Community,
I have a Question of Possibility in SuperCollider
I working of a greater Complex Application in Supercollider
There will been a System of Processes,
each of this Process is started by another of this Processes and will Start self other of this Processes.
So each Process has a Speed / Tuning and a Duration.
So each Process starts and finished in Time.
The Problem is to Manage the just Running Processes.
And this is in the Beginning easy.
I have a Global Dictionary who each Process check in by his Start
The Problem is Step 2:
And this is each Process should checkout by his Finish.

So I think what I need is a Function which automatically will be called by the Done-Action of each Synth which represents the Processes.

So I hope there will been an Angle which tells me the right way to do this

CreCo
Thomas Lahme

Synths have a onFree method that executes a function when the synth is freed:

x = Synth(\default);
x.onFree({ "the synth was freed".postln });
x.free
// -> "the synth was freed"
1 Like

Thanks to elgaino,
Exactly this was I looking for.

With verry much Thanks.

CreCo Thomas Lahme

1 Like

Ok,
I was happy too early
The next / The reminder Problem is this:

The x.onFree calls at the End of the Synth the as Paramater to him given Function. But I known’t not the Circumstances of this Execution.
So the Problem is, I can only delete the Right Position in the Dictionary, when I know the Name of the Responded Synth.

So the Question is, is there any way to customize this Function automticaly for each started Synth. At least can it have any Parameter who tells him his connected Synt Names.

In because of there can been any Number Synths between 1 and 120 paralel tp 12000 in a whole Performance, it is important to do this Automatically.

In Honorary
CreCo Thomas Lahme

In fact, it does have access to that. This is unfortunately not documented in the help file, but the onFree function receives the Node (Synth or Group) object as argument:

(
SynthDef(\beep, { |out, freq = 440, time = 0.1, amp = 0.1|
	var sig = SinOsc.ar(freq);
	var eg = EnvGen.ar(Env.perc(0.01, time), doneAction: 2);
	Out.ar(out, (sig * amp * eg).dup);
}).add;
)

a = Synth(\default).onFree({ |synth| synth.defName.debug("synth ended") });
-> Synth('default' : 1002)

a.release;
synth ended: default

b = Synth(\beep, [time: 0.5]).onFree({ |synth| synth.defName.debug("synth ended") });
-> Synth('beep' : 1003)
synth ended: beep

Alternately, the onFree function could use variables outside of its own scope – just make sure the variable is defined within the loop, e.g.:

// the good way
(
r = fork {
	20.do { |i|
		var freq = (i+1) * 100;  // **this** variable
		"Starting synth with frequency %\n".postf(freq);
		Synth(\beep, [freq: freq, time: 1]).onFree({
			// 'freq' here refers to the i*100.
			// because it's declared within the loop,
			// it's bound to the current cycle,
			// no matter how much time passed before release.
			"\tSynth with frequency % was just released\n".postf(freq);
		});
		0.2.wait;
	};
};
)

// the bad way
(
r = fork {
	var freq;  // nope, don't do this
	20.do { |i|
		freq = (i+1) * 100;
		"Starting synth with frequency %\n".postf(freq);
		Synth(\beep, [freq: freq, time: 1]).onFree({
			// now 'freq' is declared outside the loop,
			// so it only refers to the last played frequency.
			// the link between this synth and its frequency is broken
			"\tSynth with frequency % was just released\n".postf(freq);
		});
		0.2.wait;
	};
};
)

hjh

1 Like

Ok,
That I understand.
But I need not the Name of the Type of the Synth.
Rather I need anything to see which as one Played Synth.

Beep in the above Examples rather the Type - The Name of my Synthdef - as a Tip which of the played Synths plays

Excuse me for my broken Explaination.

But here a better Examples
I would like do something like that:

(
SynthDef(\beep, { |out, gate = 1, freq = 440, time = 0.1, amp = 0.1|
	var sig = SinOsc.ar(freq);
	var eg = EnvGen.ar(Env.perc(0.01, time), doneAction: 2);
	Out.ar(out, (sig * amp * eg).dup);
}).add;
)
b = Synth(\beep, [time: 0.5]).onFree({ |synth| synth.get.debug("synth played by ... Hz") });
-> Synth('beep' : 1003)
synth played by ... Hz 440

When there is a Way to do something like this …
… It would bee woundeful and Great.

Because it would do all what I need

A hopeful

CreCo :: Thomas Lahme

My second example does that.

hjh

Execuse me please,

but:

synth played by ... Hz 440

Is not the Same as:

synth ended: beep

The First is looking at a Argument given to the single Synth Instance / Node
The Second is looking for the Name of the Synthdef / The Synth Template.

So I understand the Second,
and my Question is, can I have too the First Point

A little stupid

CreCo :: Thomas Lahme

James’ example here does what you want! - try it - you pass the frequency into the .onFree function.

Ok,
I sily :laughing:
But just I understand

A very happy
CreCo Thomas Lahme

:joy: :joy: :joy:

Here I’m back,
And Juston We have a Problem.
I have tryed all,
but the freq is only received from the Loop in Which it was definied
But My Synth must have a little bit Garbage Collection.
The Problem is,
he must remove his Values from a Table.
And when this is going on, the freq Value in the Loop has nothing to do with
The Freq once the Synth Instance was created.
So my Problem is the self as before.
Are there any Technique to pass the DoneAction to Send a Message to the IDE that this and only this Instance of the Synth was died

That is… exactly my first example.

The synth instance is passed in as an argument.

hjh

Ok,
Try we another Way.
This is my call:

x = Synth(“Zerro-Processing”, [“dur”, 11, “speed”, 1, “tempo”, 11, “masterAmp”, 1, “center”, 1, “question”, index ]).onFree({question.postln});

You see I need the Parameter Question to see which Instance of the Synth-Type Zerro-Processing is over.

I tryed it in two Ways:

  1. First was question-postln which says that question was not found.

.onFree({ question.postln});

ERROR: Variable ‘question’ not defined.

  1. .onFree({ index.postln});
    Which gives only the Index of the last Synth-Instance but no way back to the Instances before. But I must remove - as an Example - The first Entry with Name Question when two other Instances are started

But actually you don’t.

x = Synth(“Zerro-Processing”, [“dur”, 11, “speed”, 1, “tempo”, 11, “masterAmp”, 1, “center”, 1, “question”, index ])
.onFree({ |synth|
    synth.postln
});

Did you try declaring an argument in the onFree function, for the synth?

This argument will be the exact instance that was freed.

Seems you’ve tried many things except this.

hjh

Ok,
This gives me a hint which Nodes Operates.
It’s like:

Synth(‘Zerro-Processing’ : 1002)

The Problem now is, in which way can I have the same Mark by Starting
My Synth Instance.

In the End it will been for me like:

if( synth = Synth(‘Zerro-Processing’ : 1002) ) then delete synth

Why/from where do you want to delete the synth?
When it’s ended, it’s automatically deleted from the server.

I’m guessing now, but maybe you wanted to remember the synths you started, maybe in an array, and then delete them from the array when they are ended?

Then you could do something like this:

(
~myRememberedSynths = ~myRememberedSynths.add(
	Synth(\beep, [freq: 44.rand + 40, time: 4.0.rand + 0.2])
	.onFree({ |synth|
		var index = ~myRememberedSynths.indexOf(synth);
		~myRememberedSynths.removeAt(index);
		"// removed synth at index % because it ended. ".postf(index);
		"there are now % synths left in ~myRememberedSynths.\n".postf(~myRememberedSynths.size);
	}
	)
)
)

cheers,
eddi

Yes nearly this is.
I have a little Directory
with 3 Elements.

1.) A Reference to the synth // X = synth(/beep)
2…) Two Reference Places

I need a Way to remove this Entry when the Synth Instance freed
One of my Problems is to Store a Reference to the Synth in this Directory
In special must the Entry refresched in little Time-Cycles,
and there I become Problems to Work with the above x for Synth
and the Put and at Methods

CrecO
Thomas Lahme

You can apply the same principle to a dictionary, as i have demonstrated with an array above.
The trick is to do the removal inside the onFree function, then you don’t have to manage any “little time cycles” – the cleanup happens automatically and almost instantaneously.

Try it out, post some code, then we can help.

Cheers,
eddi
https://alln4tural.bandcamp.com

Ok,
there I am:

Ok, I have tried to Code a simple Function for my onFree Function.

So this called new onFree:

x = Synth(“Zerro-Processing”, [“dur”, 5, “speed”, 1, “tempo”, 11, “masterAmp”, 1, “center”, 1, “question”, index ]).onFree({ |synth| ~freeSynth.value(synth)});
~memory = ~memory.put(index, [x, 1.3, 2.2]); // Seting in Free Chanell

And this is the ~freeSynth Function:

(~freeSynth = { arg x;
var i, // Helper Index
notFound, // Found Helper
temp; // Temporary Locoker
i = 0;
notFound = True;
while ((notFound == True),
{“Test”.postln;
temp = ~memory.at(i);
if ( { temp.at(0) == x },
{
notFound = False;
~memory.put(i, Nil);
})});}; )

So new I have 3 Questions:

  1. When - as showed - the x contains the Synth Instance is it right to Test
    x == somethingLikeX or is a other Equality Test Function needed
  2. Are there other Things I should have in Mind but not actuality in this Code
  3. Oh Sorry: I have Problems with the While and IF Function, can anybody give me a hint whats going wrong.

Oh Dear,
Today is not my Day:

A Little bit Refactoring and the Code of the Function is:

// Locks for Processing-Node in Process-Directory
(~freeMySynth = { arg x;
var sb, // Size of Banch
temp; // Temporary Locoker

sb = ~memory.size;
sb = sb -1;
for(0, sb, 
	{
		arg i;
		temp = ~memory.at(i);
		if( temp.size > 0,{
			if( temp.at(0) == x,
			{
					~memory.put(i, Nil);
			}
			);
		});
	}
	);

};
)
Which runs correctly.

At this Point I can say this Thread has here his Solution.
So I mark this Thread as Solution.

CreCo
Thomas Lahme