Controlling the random seed?


So, I’m trying to add to my random sequencer a way to optionally fix the random seed via CV.

I’ve been taking a look at the features in random.hpp & random.cpp, naïvely thinking I could figure out how it’s seeded, and I must say I have zero clue how any of all that machinery ticks.

I also looked at how Frozen-Wasteland’s Seeds of Change does it - it has its own PRNG, way too complex for me to follow.

I gave a try using std::mt19937 in a test module and it seems to work. I tried seeding it a fixed seed and flipping a coin every sample to see what happens, the CPU cost is obviously very high, but doing it only 1000x per second the cpu cost is negligible, and in practice I’ll call it 10 times per second at most.

I guess I have two questions:

  • Am I missing a simple way to force Rack’s PRNG seed?
  • Any non-obvious drawback to using the standard library’s in my case? I don’t need the random distribution to pick numbers more than a few times per second, or the randomness to be of high quality, but I need it to be deterministic when used on the same machine.

how do you flip a coin before you have a random seed?

The rack one looks like it uses time of day as a seed. Should be good enough, yes?

void init() {
	struct timeval tv;
	gettimeofday(&tv, NULL);
	xoroshiro128plus_state[0] = tv.tv_sec;
	xoroshiro128plus_state[1] = tv.tv_usec;
	// Generate a few times to fix the fact that the time is not a uniform u64
	for (int i = 0; i < 10; i++) {

That’s not really what I’m asking! I don’t really understand the implications of monkeying around with this, I’d like a sanity check on how to best proceed.

If I do something dangerous/expensive etc. and submit it to the library, I can’t change it without breaking people’s patches.

If you need a deterministic pseudorandom number generator, either write your own or use one from the C++ standard.

1 Like

oh, sorry. You are quite right.

Thanks! Means my test implementation was a safe way to go about it. Since controlling the random seed controls the melody, people would be seriously annoyed if I changed implementations later.

1 Like

For the reference of anyone who might find it useful:

I found it easier to just use the xoroshiro128+ alogrithm that VCV also uses.

Trying to seed the std::mt19937 Mersenne Twister PRNG each run gave me very poor results, with noticeably poor randomness, and skewed results.

Since my random seed is a single CV signal and an a small integer, I found I obtained the best results by salting the seed a bit:

s[0] = seed1 * 52852712; // Keyboard smash
s[1] = seed2 * 60348921;

And also doing a bunch of dry runs to warm it up, cf. how VCV does it.

I left it to run (without an external seed) on my Darius sequencer overnight, and it follows the expected normal distribution, unlike mt19937, which would skew to a side.