I recently stumbled upon a 7 year old article detailing the creation of the THX sound in the 1980s. It was apparently generated by 250,000 ASP commands that were generated from a program that consisted of 20,000 lines of C code.
While entirely impressed by the work and result, this part stuck out to me.
>> There are many, many random numbers involved in the score for the piece. Every time I ran the C-program, it produced a new “performance” of the piece. The one we chose had that conspicuous descending tone that everybody liked. It just happened to end up real loud in that version.
>> “Some months after the piece was released (along with “Return of the Jedi”) they lost the original recording. I recreated the piece for them, but they kept complaining that it didn’t sound the same. Since my random-number generators were keyed on the time and date, I couldn’t reproduce the score of the performance that they liked. I finally found the original version and everybody was happy.
In visualization, I’ve come across instances in the past where I’ve needed random numbers to get a desired look, but needed repeatable results.
Take these two cases:
1.) I was re-rendering grid-like portions of a scatter-plot where data could be added but not removed. If I had 100 randomly placed points in a grid cell and needed to redraw it with 101 points, I needed the first 100 to be redrawn in the same positions they were in, plus the new one. (This one was in Flash)
2.) I was rendering a video with hundreds of thousands of “people” scattered around a floor in 3D space, but needed to be able to zoom in on particular people. If they were positioned in a truly random formation, the hard-coded positions I zoomed into would no longer show the specific people I was targeting. I needed to be able to re-render the video, position the people randomly, but have them in the same random positions they were in previously. (This one was in Processing)
For both of those cases, I came up with similar solutions. I created an alternate random() function that accepted an input parameter—a seed—and returns a random-ish floating point number between 0 and 1. For example, if you send it a seed of 123456, you might get a value back of 0.382919. If you send 123457, you might get 0.716254. What’s most important, however, is that sending 123456 again would result in the same value, 0.382919.
There are many ways to accomplish this, and I certainly didn’t set out to find the most optimal/scalable method. Within my seeded random function, I simply used the value for pi, performed some arithmetic using the seed, and returned only the digits after the decimal. That resulted in a very random-looking floating point number between 0 and 1, just like basic, non-ranged random() methods tend to provide.
In Case #1 above, I used the grid cell’s static X and Y coordinates plus the UID of the dot being rendered, and then generated a second random number with a slight variation in order to have two values—X and Y coordinates. In Case #2, all I needed was the UID of the person, also varied for a second random number to retrieve a random X and a random Y position.
As for the THX sound, they could have used a similar approach with a single hard-coded base seed value (e.g. the number 1) that is used in all subsequent seeded random function calls. This would result in the same sound being played every time. If they wanted to “compose” a new, randomized piece, the would simply change that base seed value (e.g. 1 becomes 2). To go back to a previous version, change that number back. Upon finding a composition they want to keep, simply leave that base seed in the code. The only way to lose the sound would be to lose the entire codebase, at which point your hopes of recreating the sound would obviously be slim, even if no random (or random-ish) numbers were involved.