# Unknown pleasures with JavaScript

No this blog post is not about how nice JavaScript can be, instead it’s just another one of my attempts at reproducing modern art with procedural generation and the HTML5 `<canvas>`

element. This time I randomly generated images resembling the cover of the album by Joy Division called “Unknown Pleasures”.

According to Wikipedia, this somewhat iconic album cover is based on radio waves. I saw a poster of it in a bar not long ago and decided to reproduce the next time I had some time to kill.

First of all let’s set up a black canvas - I used the same dimensions as the image above.

Next I manually guessed some margins.

I squinted my eyes to count the number of lines on the album cover and I believe there are 80 of them. Based on the height and the number of lines the distance between each line is simply . The same goes for the width and desired number of points on each line.

My “strategy” is to use two nested loops to iterate each line one by one. For example the following snippets draws `nLines`

lines evenly spaced by `dy`

each consisting of `nPoints`

points which are themselves evenly spaced by `dx`

. Essentially this just requires updating the and coordinates respectively by `dx`

and `dy`

. When a line ends the `x`

variable resets to `xMin`

in order to start a new line.

The randomness in the album cover comes from the coordinate. For example by adding values obtained from a uniform distribution in - this is easily done by replacing `ctx.lineTo(x, y)`

by `ctx.lineTo(x, y + Math.random())`

- the lines start to jitter around.

Of course the noise in the album cover is not uniform at all, in fact each line has multiple “peaks” which points the way towards multimodal distributions. It seems that each line has one or more peaks, moreover some of the peaks are skewed towards the left or the right. Although the distributions don’t seem to be normal, using a mixture distribution composed of multiple normal distributions seems to be a reasonably good start.

To obtain values for we have to use the probability density function – in short PDF – of each normal distribution. Basically for each the PDF will tell us the associated value . To make the process different per line we can sample a mean and a standard deviation from two normal distributions – one for each parameter – that we can then inside another normal distribution whose PDF will be used to generate values for .

Sadly the JavaScript standard library doesn’t provide a function to sample from a normal distribution. I didn’t want to use an external library so I decided to implement my own. Although there exist fancy techniques with even fancier names – I’m looking at you Ziggurat algorithm – a simple way of going is simply to compute the average of values sampled from a uniform distribution.

The `randNormal`

function will generate values centered around 0 with a standard deviation of 1. The reason why this technique is not popular is because the values it produces will necessarily be in range – because of the sum. The 6 is arbitrary and any value higher would increase the precision of the method while any lower value is not recommended. Because we are procedural generation we don’t really care about the precision of our methods, in fact noise and imprecision is welcome!

`randNormal`

can be extended to sample from a normal distribution with mean `mu`

and standard deviation `sigma`

.

Finally the PDF of a normal distribution is , which translates to the following JavaScript code.

Now we can generate a normal distribution with random parameters for each line and obtain each thanks to the PDF of the generated normal distributions.

`mu`

and `sigma`

are sampled from normal distributions with manually chosen parameters. `mx`

is half the length of each line. The 1000 is also arbitrary and is simply there to rescale the values returned by the PDF so that they are meaningful, again this is done manually.

We’re getting somewhere! However one issue that has nothing to do with randomness is that the lines sometimes overlap whereas they do not in the album cover. One way to solve this is to draw black pixels under each line to “cover up” the previous lines. This is quite easy to do with the `fill`

method. At the end of each line we fill in all the area under the current line in black, then we paint the current line in white before finally moving to the next line.

This procedure gives a satisfying 3D feel to the image.

Now all we have to do is generate more resembling lines. As I mentioned the lines have multiple peaks and using a multimodal distribution *could* do well. To generate an arbitrary multimodal distribution one may use a mixture distribution, which is nothing more than sum over two or more distributions. For example the following figure – obtained from the Wikipedia page on mixture distributions – shows how summing three normal distributions results in a new distributions with three modes.

Producing a mixture distribution is not too complex code-wise. For each line we want to generate a multimodal distribution with a random number of modes, thus we can first of all assign a random integer to a variable called `nModes`

to indicate how many modes we want. Then we can generate `nModes`

values for and for just as we did previously. Then we can sum returned by the PDF of each distribution and use the sum as a value for .

Again we are getting closer. Now probably should work on some noise. Instead of adding some random as we did previously we could make the noise be proportionate to . After some tinkering I found that the following worked quite well.

At this moment I was quite happy with the result. However, after looking at a few runs I had a feeling that the lines oscillated too much and that they should be a bit smoother. The thing is that for each value of we produce a value for that does not take account the preceding value. I decided to use a basic smoothing function so each value would take into account the previous value . In the end I settled on doing . Implementing this rolling mean only requires the last value of at each iteration; I settled on the following code which does just so.

And that wraps it for this post, I hope you enjoyed it! As usual the final is available on GitHub with the rest of procedural generation I did.

On a side note I discovered the r/proceduralgeneration subreddit which I recommend if you’re interested in procedural generation – albeit more advanced than what I do.