Unique random seeds for each instance of a plugin?

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

The bog-standard time() updates only once per second. As far as I know, multiple instances of the same plugin in a DAW session get initialized faster than that.

How could you make sure they each get a unique seed for a pseudorandom number generator that's part of the signal processing? Is there a cross-platform C/C++ way of accomplishing it?

(I have a hunch that it could be something incredibly trivial, but for some reason I didn't have a lot of success with Google.)

Post

You could use the adress of your main object for this?
You should also store the value somewhere so that your processing is reproducible.

Post

http://en.cppreference.com/w/cpp/chrono ... tion_clock in <chrono> gives something like nano-second resolution.

Post

i leave it up to the user and use phase or similar param to seed. the user may want two identical instances with some other variation, setting the seed themselves allows that discretion.
you come and go, you come and go. amitabha neither a follower nor a leader be tagore "where roads are made i lose my way" where there is certainty, consideration is absent.

Post

nonnaci wrote:http://en.cppreference.com/w/cpp/chrono ... tion_clock in <chrono> gives something like nano-second resolution.
It may not be enough if the platform doesn't provide such a resolution. Even steady clock (which is monotonous increasing) may return several time the same value.

Post

Miles1981 wrote:
nonnaci wrote:http://en.cppreference.com/w/cpp/chrono ... tion_clock in <chrono> gives something like nano-second resolution.
It may not be enough if the platform doesn't provide such a resolution. Even steady clock (which is monotonous increasing) may return several time the same value.
Hrmm, pray that resolution is higher than the thread-process scheduler ;)

Also, I take it that OP wants independence between plugins so maybe have each plugin use its own thread/process ID as the seed if such a query could be made.

Post

You can probably use the address of any object that is unique to your plugin instance. It may need a bit of massaging though. Maybe grab two and use the LSBs of each?
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

With a high quality hash function used to generate the seed, the address of the object actually _is_ the instance in VST. The remaining problem is then that c/c++ don't allow conversion of a pointer to an integer in a compatible way... we never let that stop us before though now did we?

seed = hash(uint32_t(this));

This could be foreseen to fail where the object is allocated into a virtual space with addresses aligned to 2^32, which is entirely possible within the next ten years!

In those cases you might want to go with an instance counter implemented via a singleton/factory pattern. The entry-point function (vstmain, etc) would then possibly (if factory) request the interface be constructed by the factory which would apply a mutex lock and assign a unique identifier to each instance during construction.

This unique identifier (1, 2, 3, ...) could then be mixed with a salt (low precision time?) and hashed to generate a seed value.

Image
Image

'shits making me hungry.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Another option might be to take inspiration from the way which GUIDs/UUIDs are generated - they try hard to be unique. http://graemehill.ca/minimalist-cross-p ... ation-in-c++/

Post

On Windows, you could use

Code: Select all

unsigned int seed = (unsigned int)(__rdtsc());
On OS X, you can define this first

Code: Select all

 //from http://stackoverflow.com/questions/9887839/clock-cycle-count-wth-gcc
#if defined(__i386__)
static __inline__ uint64_t __rdtsc(void){
  uint64_t x;
  __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
  return x; }
#elif defined(__x86_64__)
static __inline__ uint64_t __rdtsc(void) {
  uint16_t hi, lo;
  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
  return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 ); }
#endif
There should be a couple of ticks between each plugin initialization, so it should be unique (I think). There is probably something fancier in C++11, but I am still stuck in the dark ages.

Post

rdtsc is only useful when measuring a delta on a single core. The time between ticks may change with power-saving and various other features of the processor during execution. The absolute value returned by rdtsc is otherwise arbitrary and unpredictable.

What you're doing is not what rdtsc is for.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

aciddose wrote:rdtsc is only useful when measuring a delta on a single core. The time between ticks may change with power-saving and various other features of the processor during execution. The absolute value returned by rdtsc is otherwise arbitrary and unpredictable.

What you're doing is not what rdtsc is for.
I guess there is a chance that different plugin instances on different cores may return the same rdtsc. I haven't had to worry about it. It really depends on how sure you want to be that every instance has a different seed in every different scenario.

Post

If you do want to be sure: the method I described with a locked factory that assigns incremental IDs and generates seeds by hashing these IDs and a salt is the only reliable method to achieve that.

Actually the main issue with rdtsc is correlation (not as good as a hash(id+salt)) as well as the fact it may not run at all, or may not provide any greater precision than a low resolution time function.

The biggest issue (correlation) is the fact that only a few (if any) bits may differ in two samples taken. Samples taken during the construction of many instances of a plug-in could yes return identical bits for those sampled.

Now the real kicker: you have no way to tell how many bits are present in the value, nor can you know the rate (if any) at which these bits change.

For example the most important bits in your seed may be 5,6,7,8,9, while these bits may be static in the rdtsc value with only bits 48,49,50,51,52 providing a good result.
Free plug-ins for Windows, MacOS and Linux. Xhip Synthesizer v8.0 and Xhip Effects Bundle v6.7.
The coder's credo: We believe our work is neither clever nor difficult; it is done because we thought it would be easy.
Work less; get more done.

Post

Have you considered combining the date, hour, minute, second, millisecond, and guid? And if the seed number required is smaller than that, run it through a hash function.. hash collisions are rare, but you can always cross-check for collisions via memory, system calls, or even config files if all collisions must be avoided.
SLH - Yes, I am a woman, deal with it.

Post

aciddose wrote:With a high quality hash function used to generate the seed, the address of the object actually _is_ the instance in VST. The remaining problem is then that c/c++ don't allow conversion of a pointer to an integer in a compatible way... we never let that stop us before though now did we?

seed = hash(uint32_t(this));

This could be foreseen to fail where the object is allocated into a virtual space with addresses aligned to 2^32, which is entirely possible within the next ten years!

In those cases you might want to go with an instance counter implemented via a singleton/factory pattern. The entry-point function (vstmain, etc) would then possibly (if factory) request the interface be constructed by the factory which would apply a mutex lock and assign a unique identifier to each instance during construction.

This unique identifier (1, 2, 3, ...) could then be mixed with a salt (low precision time?) and hashed to generate a seed value.

Image
Image

'shits making me hungry.
+1

Post Reply

Return to “DSP and Plugin Development”