Unique random seeds for each instance of a plugin?
- KVRer
- Topic Starter
- 12 posts since 19 Jan, 2017 from Helsinki, Finland
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.)
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.)
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
You could use the adress of your main object for this?
You should also store the value somewhere so that your processing is reproducible.
You should also store the value somewhere so that your processing is reproducible.
- KVRist
- 251 posts since 7 Feb, 2017
http://en.cppreference.com/w/cpp/chrono ... tion_clock in <chrono> gives something like nano-second resolution.
-
- Banned
- 12368 posts since 30 Apr, 2002 from i might peeramid
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.
-
- KVRian
- 1379 posts since 26 Apr, 2004 from UK
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.nonnaci wrote:http://en.cppreference.com/w/cpp/chrono ... tion_clock in <chrono> gives something like nano-second resolution.
- KVRist
- 251 posts since 7 Feb, 2017
Hrmm, pray that resolution is higher than the thread-process schedulerMiles1981 wrote: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.nonnaci wrote:http://en.cppreference.com/w/cpp/chrono ... tion_clock in <chrono> gives something like nano-second resolution.
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.
- KVRAF
- 2237 posts since 25 Sep, 2014 from Specific Northwest
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?
- KVRAF
- 12555 posts since 7 Dec, 2004
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.
'shits making me hungry.
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.
'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.
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.
- KVRist
- 91 posts since 24 Dec, 2015 from Bristol, UK
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++/
- KVRian
- 509 posts since 1 May, 2006 from lancaster, pa
On Windows, you could use
On OS X, you can define this first
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.
Code: Select all
unsigned int seed = (unsigned int)(__rdtsc());
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
- KVRAF
- 12555 posts since 7 Dec, 2004
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.
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.
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.
- KVRian
- 509 posts since 1 May, 2006 from lancaster, pa
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.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.
- KVRAF
- 12555 posts since 7 Dec, 2004
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.
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.
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.
- Banned
- 697 posts since 29 Oct, 2016
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.
-
Zaphod (giancarlo) Zaphod (giancarlo) https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=111268
- KVRAF
- 2596 posts since 23 Jun, 2006
+1aciddose 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.
'shits making me hungry.