Musical Fireworks with Sonic Pi and Minecraft!

A major new feature is being introduced with Sonic Pi version 2.5 shortly due to be released, which enables it to control Minecraft on a Raspberry Pi. This is particularly effective on a Pi 2 which has the power to comfortably run both programs in tandem.

Over the last couple of weeks I have been playing with the interface using SP 2.5dev, and it has been really great fun getting to grips with producing graphic on Minecraft created from Sonic Pi. I am still learning a lot, and there is quite a lot of experimentation necessary to get the best effects. For example, if you want to produce patterns and to move around freely to view them, then it is a good idea to create a blank world to start with. This is also helpful as it means that Minecraft has less to do to update the screen if you are producing an animation. Secondly, I discovered that you need to put in a delay to synchronise music with Minecraft. Somewhat surprisingly it is Minecraft which has to be delayed to sync with music from Sonic Pi.
I wanted to be able to use circular patterns and spirals, so I also looked at using Math function from Ruby, which can be accessed in Sonic Pi. I had never really used Minecraft before, but I have found the immediacy of using it with Sonic Pi preferable to first writing code in Python and then running that….. Now I’d better put my helmet on to protect it from the brickbats! :-)

The first three programs I wrote have been published on youtube, with accompanying gists for the code, You can see them here.

I also posted a brief video from my phone of the explosions used in this current program I am discussing (  https://youtu.be/WJZ8KLNXZ10  ) but I have now modified the program to add the musical accompaniment.

In many previous posts, I have discussed the use of sample based voices in Sonic Pi, and in this program I have utilised three sample based voices, for Trumpet, Tenor Trombone and Bass Trombone to play the minuet from Handel’s Royal Fireworks Music, which was originally played in Green Park in London to accompany a fireworks display on 27th April 1748. It is an appropriate piece to put into this modern setting to accompany this fireworks display.

This is written in a program in its own workspace in Sonic Pi, completely separate from the code which produces the fireworks. It is possible in Sonic Pi to send a cue from one workspace to synchronise something happening in another. I actually do this twice. The music program is started, but then stops and waits for a cue from the graphics code producing the fireworks, so that they start together. Also when the music finishes playing it sends a cue back to the graphic program to stop it from producing any further fireworks.

I have discussed in previous post how to create sample based voices, These also utilise a new function in Sonic Pi 2.5dev called pitch_ratio which lets you calculate the rate at which to play a sample to play a note which is a certain number of semitones away from the natural pitch at which the sample was recorded. An equivalent to the play function for synths which I call pl is coded to play a note using a sample. A similar function to the play_pattern_timed function which I call plarray is defined which enables you to play a pair of lists of notes and their durations, although it has the added feature of setting an appropriate envelope for each note to give a sustained output.
One or two further tricks are employed. A function  part is defined which plays arrays for each of the instruments together (two trumpets, a tenor and bass trombone) utilising threads. Because there are different sections to the music including repeats and first and second time bars, this is written in such a way that the it can be utilised many times, by feeding in the data for the lists to be played from an array lar (short for list of arrays). Each “play” requires 8 lists: 2 each (for the notes and durations) for each of the parts. By using an offset into this array, different sets of the 8 lists can be selected, so when we play the piece we have in turn part(0) part(8) part(16) part(8) part(24) part(32) part(0) part(8) part(24) selecting the appropriate lists to play.
This program is placed in a workspace and is the first to be run in Sonic Pi. It then sits and waits for a cue form the graphics program to start it.

The Minecraft driver program which produces the explosions sits in its own workspace.
As discussed, it first clears out any existing world and lays down a grass layer. The first time you run this, it may take a long time to complete this program, and in fact I usually stop and start the program 2 or 3 times until the Minecraft display comes up with blue sky and a grass layer underneath. On subsequent runs, the 6 second pause allows things to settle, and give you time to switch to the Minecraft screen before the program starts to animate.
Incidentally, if you create a new world when Minecraft has already been running, then I find that you have to restart Minecraft for Sonic Pi to pick up the correct world with which to communicate. If in doubt and nothing much seems to be happening it is best to quit and restart Minecraft: don’t just go back to the menu screen. It is quite a quick process on a Pi2!
Next the program sends a cue :Fireworks to start the music program playing.
Because the firework explosion is based on a circular pattern we need to be able to use some trigonometry. Happily Sonic Pi is based on the Ruby language, and we can utilise the Math module built in to the language. If you Google sites about Ruby you will discover that for example you can access the value of Pi as

Math::PI

This is a bit a a mouthful so I assign it to a variable using

pi=Math::PI

(note the capitalisation is important)
Likewise I utilise the sine and cosine functions supplied by the Math library but define my own functions to make it slightly easier to use them.

define :sin do |v|
  return Math:sin(v)
end

and

define :cos do |v|
  return Math:cos(v)
end

Also, because these functions like their arguments in radians I define a further function to convert degrees to radians

define :rad do |v|
  return v * Math::PI/180
end

The equation for a circle is given by x=r*sin(i),  y=r*sin(i) where i goes from 0 to 2Pi (or 0 to 360 degrees) where r is the desired radius
You can add offsets xs and xs  to change the position of the origin.

Putting this altogether we can define a circle function as

define :circle do |brick,xs,ys,zs,r,updown,ang=angresolution|
  if updown == 1 then
    0.step(360,ang) do |i|
      mc_set_block brick,xs + r*sin(rad(i)),ys+r*cos(rad(i)),zs
      sleep s
    end
  else
    360.step(0,-ang) do |i|
      mc_set_block :air,xs + r*sin(rad(i)),ys+r*cos(rad(i)),zs
      sleep s
    end
  end
  #sleep 0.1
end

brick is the required material eg :gold, xs,ys,zs position the centre of the circle, r is the circle radius, and ang is the resolution (in degrees) i.e. the angle through which you rotate between points on the circle. The circle can either be drawn with a solid brick (:gold, :iron or :diamond) when updown is set to 1, or wiped when updown is set to 0 by drawing it with air bricks. In this program the variable s is set to 0 so that the circle is drawn at maximum speed.

To build the exploding firework, I made a pattern which I called target (because it looked a bit like one). This utilised 13 circles, adjusted so that each one was 1 unit larger in radius than the last, with the colours cycling through three brick materials. Also the resolution or ang parameter of the circles is adjusted as the radius increases to give minimum build time. The smaller circles don’t need as many points to draw them. The pattern is drawn twice. On the first pass v is set to 1, which is passed to the updown parameter. On the second pass v is set to 0 and the circles are removed.

Having set up the various bits, the program can now do something.
We teleport to 0,30,0 which is an appropriate position from which to observe, and then prime the variable flag setting it to 0. This is used to stop the program at the end. A thread sits and waits for a cue named :finish to be received from the music program. When this happens flag is set to 1
Until then, a loop starts which repeatedly performs the target function, each time drawing an exploding pattern like a firework burst. This is accompanied by the sample :ambi_lunar_land the first 3.5 seconds of which played at 1.5 times normal rate gives an explosive sound, especially when played at amp: 2

When the finish flag is set to 1 the loop stops and a final credit notice is displayed.

You can see a video of the program in operation

a gist containing the two programs is here

you can download the three samples required here

You should place them in a folder named Fireworks inside a folder named samples in the Pi home directory.

I hope this will inspire you to try out Sonic Pi with Minecraft. it is a great combination!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s