title::Random Seed
summary:: Random generator seed
categories::Core>Kernel, Random
related:: Guides/Randomness, Classes/RandSeed, Classes/Pseed, Classes/Thread

section:: Introduction

Every link::Classes/Thread:: in sclang has a (pseudo-) random number generator that is responsible for all randomization within this thread. Each random number generator has its own seed (starting point) from which the series of values is generated. This seed can be set and after that, the randgen (being strictly deterministic) produces exactly the same numbers again.

In order to save disk space, you can reproduce any sequence of randomized data just by one Integer number that you can write down in your notebook.

method:: randSeed

code::
// every thread, also a Routine, has a random generator seed:
(
r = Routine({
	loop({#[1,2,3,4,5].choose.yield })
});
r.randSeed = 1923;
)

// using the routine to fill an array
Array.fill(7, r);

// setting the random generator seed back to our initial seed
r.randSeed = 1923;

// causes this array to be identical
Array.fill(7, r);
::

subsection::Inheriting Seeds

When a routine is created, it inherits its random number generator from the parent thread (link::Classes/Thread#.thisThread#thisThread::). If no particular randSeed is set (the normal case), then the same random number generator object provides numbers to both the parent and the child (one stream of random numbers, distributed between both).

The parent thread is whichever Routine is in force at the moment of creating a new Routine. If no Routine is evaluating at that moment, then the parent is the sclang process main link::Classes/Thread::. By default, all Routines inherit the random number generator from the main thread.

To set the main random seed for the entire application, then, evaluate code::thisThread.randSeed = yourSeed:: outside of the context of any Routine, as in the example below.

code::
thisThread.randSeed = 1923;

// create a function that returns a Routine

r = { Routine({
	loop({#[1,2,3,4,5].choose.yield })
}) };

Array.fill(7, r.value);

// reset the seed
thisThread.randSeed = 1923;

Array.fill(7, r.value);
::

When you set code::randSeed:: on a Routine, the Routine switches to its own random number generator, independent of any other. Subsequently, Routines created within this Routine will inherit its unique random number generator.

code::
(
thisThread.randSeed = 1000;
TempoClock.sched(0, { 1000.rand.debug("main RNG"); 1 });

fork {
	2.1.wait;
	thisThread.randSeed = 1000;
	loop { 1000.rand.debug("routine RNG"); 1.wait }
};
)

main RNG: 592 // sequence is 592, 876, 614, 236...
main RNG: 876
main RNG: 614
routine RNG: 592 // sequence is 592, 876...
main RNG: 236
routine RNG: 876
::

Note that this inheritance takes place only at the moment of creating a new Routine. Calling code::next:: or code::play:: on the child Routine does not override that Routine's random number generator.

subsection:: Audio example

code::
// use the seed to completely reproduce a sound:
(
SynthDef(\help_randomSeed, { arg out=0, freq=440;
	Out.ar(out,
		Line.kr(1, 0, 0.3, doneAction: Done.freeSelf) *
		Resonz.ar(
			Dust2.ar([10, 10], 270) + WhiteNoise.ar(4),
		freq, 0.01)
	)
}).send(s);

SynthDef(\help_setRandomSeed, { arg seed=1956, tbus=0.0;
		RandSeed.kr(tbus, seed);
}).send(s);
)

// run a patch
(
x = Synth(\help_setRandomSeed);
r = Routine({
	loop({
		Synth(\help_randomSeed, [\freq, rrand(440, 700)]);
		0.25.wait;
	})
}).play;
)


// make a reset task

(
d = 1250;// seed
t = Task({
	loop({
		x.set(\seed, d, \tbus, 1.0); r.randSeed = d;
		0.1.wait;
		x.set(\tbus, 0.0);
		1.9.wait;
	})
});
)

// sound starts to loop
t.start;

d = 1251; // different loop
d = 1925;


// sound is just like random again, not interested in anything.
t.stop;
::
