Some guy at work was wearing that Joy Division shirt. You know the one. So naturally my brain went: I bet I could recreate that with Processing in an hour.

So I made a bet with myself… and lost.


I started out doing some measurements, getting the proportions just right and drawing straight white lines, just to have something to start with.

First thought, Best thought First thought, Best thought

At this point I think I’m 90% done.

Just add some Perlin noise, maybe use curves instead of straight lines and amp up the noise in the middle third or so.

But I was going for authenticity and I also figured random noise would look, well… random. And if you look at the original it’s definitely not just some perlin noise. Not just because Unknown Pleasures came out in 1979 and Perlin noise wasn’t invented until 1983.

So no. Random would not do. I did some digging and found out what the story behind the artwork really is.


In 1967 the Mullard Radio Astronomy Observatory built something called the Interplanetary Scintillation Array. It was designed by a man called Anthony Hewish as a 4-acre array of antennas to detect and study Quasars through radio-waves from outer space.

The Array It kind of looks like the worlds largest clothesline, but I’ve been assured it’s all very scientific.

One of Antony Hewish’s research students, Jocelyn Bell, had the most research-student-y-sounding job known to man, namely checking the (probably immeasurably long and boring) daily charts for the twinkling of far-off quasars.

Instead she found a “scruff” on the records that didn’t look like twinkling and didn’t look like man-made interference either. A series of pulses separated by 1.3 seconds of silence, the source too far to be human, the pulsing too fast to be anything star-sized. The source was nicknamed LGM-1 (for “Little green men”), cause who knows: maybe there really was intelligent life out there and they were just very loudly bumping 46 BPM club bangers.

Later they found a second source that did pretty much the same thing, so aliens was out of the question. It turns out what they discovered was a Pulsar, dubbed CP 1919 (later renamed PSR B1919+21 for science-reasons). A pulsar is a fast-spinning clump of protons and neutrons, about 20km across and insanely dense, about “10 trillion times denser than a lead brick”. The density of a atom’s nucleus. The spinning and the magnetic field created by this nuclear matter creates a radio beacon that sweeps across the universe and ended up smudging Jocelyn Bell’s data.

Anthony Hewish and some other guy won the nobel prize for the discovery of Pulsars in 1974, Jocelyn Bell did not. (But aparently she’s pretty cool about the whole thing).

The particular graph used for the album-cover is a computer-generated stacked plot of radio frequency periods from that first Pular, CP 1919. Made by Harold D. Craft Jr. for his PhD thesis and then used by Peter Saville, the cover’s designer.

The plot From The Cambridge Encyclopaedia of Astronomy (1977 edition)


As you can imagine, I was about halfway down this research rabbit hole when the timer I set for the hour-long bet went off. I was still just staring at straight lines.

So now I just had to

  1. Find some audio from PSR B1919+21
  2. Analyse/Graph the amplitude over time
  3. Cut the graph into strips of 1.3 seconds and stack them

Naturally I did none of those things.

I was still trying to get as close as I could as fast as I could, so I made do with an mp3 clip from a completely different pulsar (PSR B0329+54), playing and graphing the sound in real time, starting a new line every 0.7 seconds (this pulsar spins faster than the original) and just filling in the area under each completed line as I went. So you could listen to the cosmos spinning while it was recreating iconic artwork.

Which worked fine in theory, and in practice gave me this:

Math has failed me

Cool. But not what I want.

Enter the jank

So turns out the massive disadvantage of playing a sound and analysing it in real-time is that you get issues with sample-rates vs frame-rates and having to deal with load- and processing times. If you’re running photoshop and watching youtube in the background while you’re rendering, you get a different result than running it without other CPU-hogging distractions.

I hear you asking: Sam, why don’t you just run analysis on the whole file first, then just draw the results whenever you’re ready.

The answer of course is: because I’m a hack and a fraud and I had already run out of time an hour ago.

So after some adding some jank to at least kind of center the peaks, to trim some of the boring parts and accentuating the noise a bit (Remember kids: If the results are large: square them, sarge! If less than one: root them, son!).

The resulting code (and I can’t believe I’m sharing this in public) looked like this:

void draw() { 
    // initialise
    if(t == 0) {
       t = millis();
       beginShape();
       i = 0;
     }
   
     
     int diff_t = millis() - t;
     
     // amp.analyse() is doing the real work, more info here: https://processing.org/reference/libraries/sound/Amplitude.html
     float v = pow(amp.analyze(), 0.3) * amplitude_multiplier;
     // btw: 0.3 is just a value I found when tweaking, amplitude_multiplier is the maximum height a curve should have
     
     // pulsar_period would theoretically be 734ms (according to science) but I had to tweak the shit out of it to get a correct number (and ended up with 1032)
     if(diff_t > pulsar_period) {
       
       line++;
       
       // reset position
       x_pos = padding_x;
       base_y_pos = padding_y + (line * line_padding);
       y_pos = base_y_pos - v;
       
       endShape();
       
       // start a new curve
       beginShape();
       
       curveVertex(x_pos,  y_pos);
       curveVertex(x_pos,  y_pos);
       
       // reset timer
       t = millis(); 
       i = 0;
     } else {
       
       // cutoff_in, cutoff_out and sample_strech is jank added to try and center the pulses, they are inconsistent and required a lot of tweaking
       // next time I'll just put the work in to do it properly, I promise.
       
       if(i < cutoff_out && i > cutoff_in) {
         float new_x_pos = x_pos + (line_interval * sample_stretch);
         float new_y_pos = base_y_pos - v;
         
         curveVertex(new_x_pos,  new_y_pos);
         
         x_pos = new_x_pos;
         y_pos = new_y_pos;
       }
       
       i++;
       
     }
    
     // There's 60 lines in the original graph, I know because I counted.
     if(line > num_lines) {
        // save the result
       save("all-done.png");
       
       // stop the audio
       file.stop();
     }
 }

End result:

Close. Enough.

No, it’s not centered. And no, the curves are not as aesthetically pleasing as the original. And most importantly: no, I didn’t win the bet.

But I did learn a lot about the history of astronomy today, and if that doesn’t make me a winner I don’t know what does.

Sources: