Random numbers without seed

As a way to use random numbers without seed,

use_random_seed Time.new.usec
or
use_random_seed Random.new_seed

but what is the best recommended method?

1 Like

Hi @H_Tachibana did you also try?

use_random_seed Time.now.to_i
live_loop :boom do
  play rrand(30, 110), amp: 0.4
  sleep 0.25
end

2 Likes

Thanks.
I did not know about Time.now.to_i.

1 Like

Time.now.to_i is a 10-digit integer.
Random.new_seed is a 38-digit integer. (Seedless random number in Ruby)
Time.new.usec is a 5-digit integer.

Would you all say that 38 digits is the best?

If by ā€œbestā€ you mean most random, then Random.new_seed is the best option here.

I believe the way that random numbers work in Sonic Pi is that it has a predetermined list of ā€œrandomā€ numbers, and the seed just chooses the starting point in that list. This is to ensure reproducibility, so that running the same code with the same seed will generate the same sounds even if it uses randomness.

One effect of this is that if you use a similar seed (e.g. increment it by 1), you will get the same sequence of numbers, just offset a bit (in this case by 1), like this:

define :random_list do |seed|
  use_random_seed seed
  list = []
  10.times { list.push(rand_i(100)) }
  list
end

puts random_list(123)
puts random_list(123)
puts random_list(124)

# {run: 45, time: 0.0}
# ā”œā”€ [77, 8, 53, 70, 0, 19, 99, 24, 89, 46]
# ā”œā”€ [77, 8, 53, 70, 0, 19, 99, 24, 89, 46]
# ā””ā”€ [8, 53, 70, 0, 19, 99, 24, 89, 46, 9]

If you use Time.now.to_i, it only changes once a second, so if not much time has passed since the last run, you will get a similar sequence.
Similarly for Time.new.usec, this is the microseconds part of the time, which repeats every second, so you are likely to get a similar sequence when you rerun the code if it happens to be a similar fractional part of a second as the last time.
In contrast, Random.new_seed returns a very large number that changes completely every time you call it, so you will start in a completely different part of the random sequence each time.

5 Likes

Thanks @emlyn for this interesting explanation! Do you mean that for Random.new_seed, each call to it, it will generate different numbers with no reproducibility possible? And how do you use it, like this f.i?:

Random.new_seed

live_loop :seed do
play rrand(40, 90)
sleep 0.5
end
1 Like

SP program is

use_random_seed Random.new_seed
live_loop :seed do
  play rrand(40, 90)
  sleep 0.5
end

But this programme keeps producing the same sound, doesnā€™t it?

Oh, thatā€™s very weird, Iā€™m not sure whatā€™s happening there, but it seems when the random seed is too big things break.
You can get around this by restricting the random seed to a lower range:

use_random_seed Random.new_seed % 1e9
1 Like

Hi @beryann, itā€™s almost like that, you just have to pass the new seed into Sonic Piā€™s use_random_seed, but as @H_Tachibana found out it still doesnā€™t quite work because the numbers it generates are too big and Sonic Pi canā€™t handle them, so something like this should do the trick:

use_random_seed Random.new_seed % 1e9

live_loop :seed do
    play rrand(40, 90)
    sleep 0.5
end
1 Like

ok Emelyn, thanks! @emlyn But then, are the sequences of notes predictable or not if I transmit my code to someone? Is there reproducibility? :thinking:

If you use Random.new_seed it will give you a new sequence each time.
If you want it to be random-sounding but reproducible, you can just not call use_random_seed at all, or give it a fixed number. E.g. you could do something like:

use_random_seed 123456

live_loop :seed do
    play rrand(40, 90)
    sleep 0.5
end

And change the random seed until you get a ā€œrandomā€ sequence that you like. Then if you send the code to someone else they will get the same sequence.

2 Likes

Thanks a lot Emlyn @emlyn so, random is a question of choice in Sonic Pi, if I can say so! :grin:
Supplementary question: Doing this sounds logical but is it redundant compared to ā€œuse_random_seed 123456ā€ ?

use_random_seed rrand(1, 123456)

live_loop :seed do
    play rrand(40, 90)
    sleep 0.5
end

Hi
your code produces one random seed upon execution

myrand = rrand(1, 123456)

use_random_seed myrand

live_loop :seed do
  play rrand(40, 90)
  sleep 0.5
  puts myrand
end

This helped me understand use_random_seed

Random.new_seed is entirely random every time, anything else is pseudo-random, i.e. random repeatedly. Built in to Sonic Pi for reproducability.

1 Like

Thatā€™s right, the above (even if it initially looks more random) is redundant. When rrand is called at the start of the run, it will always generate the same number, so you might as well just type a ā€˜randomā€™ number yourself, no need to call rrand.

2 Likes

Iā€™ve been needing this.

You are are right Emelyn! @emlyn I forgot that my rrand generates the same numberā€¦These concepts are subtle and we have to pay attention to each of these terms! :face_with_monocle: