Sonic Pi: a new dawn, (and a new dusk) as version 2.6 is released

SP2.6DarkMode

It is a new dawn, as Sonic Pi 2.6 brings a plethora of new features, although there is a dusk involved, as it incorporates an exciting new dark mode setup, where the screen can be configured with a black background, and the text displayed in different colours according to the syntax.

Sam Aaron’s email announcing the release gives an excellent resume of what has changed, and I reproduce it below:

v2.6.0 – Algorave

The laser beams sliced through the wafts of smoke as the subwoofer pumped bass deep into the bodies of the crowd. The atmosphere was ripe with a heady mix of synths and dancing. However something wasn’t quite
right in this nightclub. Projected in bright colours above the DJ booth was futuristic text, moving, dancing, flashing. This wasn’t fancy visuals, it was merely a projection of Sonic Pi running on a Raspberry Pi. The occupant of the DJ booth wasn’t spinning disks or playing MP3s, she was writing, editing and evaluating code. She was live coding and this was an Algorave.

This release is codenamed Algorave to celebrate that Sonic Pi is now ready to be performed within nightclubs as well as still being a fantastic tool for learning how to code
creatively. There are many improvements as detailed below. However, let’s just take a brief look at some of the most fun. Firstly we have the new error reporting system to make it easier to find and debug your errors. Syntax errors are now blue and runtime errors pink. We also have a new look and feel including a new dark mode for performing in dark places. We also have some fantastic new synths, FX and have even improved the standard synths. For example, sample now lets you stretch to match the beat with the beat_stretch: opt and change pitch with pitch:. The slicer FX now sports a fantastic deterministic probability: opt for creating and manipulating rhythmic structures with ease. Finally there’s the new thread local tick/look system which will revolutionise the way you work with rings within live_loops. Of course there’s so much more too!a

Enjoy this release and happy Algoraving!

Breaking Changes

  • The res: opt for all synths and FX now has range 0->1 rather than 1->0. This means that a higher res value results in more resonance. This will hopefully be more intuitive to beginners less surprising for people with existing synth knowledge.
  • The fn stop has been renamed to kill for killing specific synths. In its place a new fn stop has been added to stop a given thread or live_loop.
  • invert_wave opts are now inverted. The default is now 0 which has the same behaviour as the old 1. This means that it’s more intuitive to use the opt as to invert the current wave, you now specify: invert_wave: true, rather than invert_wave: false. This shouldn’t affect any code which doesn’t explicitly set the invert_wave: opt. Pieces which have explicit inversion need to swap all 0s for 1s and visa versa.
  • The res: opt for rrand and rdist has been renamed to step: to avoid confusion with the resonance opt for cutoff filters.
  • Rename pitch_ratio to pitch_to_ratio to keep in line with other similar fns such as midi_to_hz.

New

  • New thread-local (i.e. live_loop local) counter system via fns tick and look.
  • New fn vector which creates a new kind of Array – an immutable vector (SPVector) which is now the default base class for all rings.
  • New fns use_sample_defaults and with_sample_defaults which act similarly as their *_synth_defaults counterparts but for samples not synths.
  • New fns use_tuning and with_tuning for exploring other tuning systems such as :just, :pythagorean, and :meantone.
  • New fn invert_chord for chord inversions.
  • New fn current_beat_duration for returning the duration of the current beat in seconds.
  • New fn note_range for returning a range of notes between two notes with a pitches: opt for constraining the choice of filler notes.
  • New fns scale_names and chord_names for returning a ring of all chords and scales.
  • New example rerezzed – strongly influenced by Daft Punk’s track derezzed.
  • New example reich phase – a nice way of combining live_loops and tick to create sophisticated polyrhythms.
  • New fns use_cue_logging and with_cue_logging for enabling and disabling the logging of cue messages.
  • It is now possible to set the block type in the Minecraft API.

GUI

  • New visual look and feel including a new Dark Mode for live coding in night clubs.
  • New preferences for hiding/showing aspects of the GUI such as the buttons, log, tabs etc.
  • New preference for full screen mode.
  • Improve error message reporting. Syntax errors are now made distinct from runtime errors with colour-coded messages. Also, the line number of the error is much more visible, and the line of the error is highlighted with an arrow in the left-hand margin.
  • Workspaces are now named buffers. This is a smaller word which works better on lower res screens and is also a lovely term used by a number of wonderful programming editors such as Emacs.
  • Print friendly messages to the log on boot.
  • Add pref option to check for updates now.

Synths & FX

  • New FX – krush for krushing the sound.
  • New FX – panslicer similar to slicer and wobble but modulates the stereo panning of the audio.
  • New synth subpulse for a full range pulse with extra bass.
  • New synth blade – a moody Blade Runner-esque synth violin
  • New synth piano – a basic piano emulation. Only capable of whole notes.
  • FXs slicer and wobble now have a wonderful new probability: opt which will only slice on (or off depending on wave inversion) with the specified probability. The behaviour is deterministic, so repeated calls with the same seed: and probability: opts will result in the same behaviour. Great for adding interesting rhythmic variation to sound.
  • FXs slicer and wobble now have smoothing opts for even more control over the resulting wave form.
  • Teach sample the opt beat_stretch: for modifying the rate of the sample to make sure the duration of the sample is n beats long (with respect to the current bpm). Note: stretching the beat does change the pitch.
  • Teach sample the opt pitch to enable pitch shifting on any sample.
  • FX flanger’s feedback mixing is now more fair and is less likely to hike up the amplitude.

Improvements

  • Teach note_info to also handle a number as its param.
  • Teach factor? to handle division by 0.
  • Teach load_sample to throw exception when passed an empty path.
  • Now throws an exception when you attempt to create an empty ring.
  • Rings are now immutable (in the Clojure sense) which means they can be safely passed to multiple threads/live_loops without any issues.
  • Teach use_sample_bpm the opt num_beats: to indicate that a given sample consists of a specific number of beats.
  • Teach comment and uncomment to require blocks.
  • Teach synth chord groups to allow their notes to be controlled individually to allow transitions between chords.
  • Throw nicer exception when unable to normalise synth args
  • Teach chord the new opt invert: as a shortcut to the new invert_chord fn.
  • Teach sample_duration about the opts start: and finish: and envelope opts such as attack: and release:. This allows you to replace any call to sample with sample_duration to get the exact duration of that call.
  • Teach chord the opt num_octaves to enable the easy creation of arpeggios.

Bug Fixes

  • Fix bug in with_sample_pack_as to now correctly accept a block.
  • mx_surface_teleport no longer throws an error.
  • Array#shuffle now works correctly with the random seeds for deterministic behaviour.
  • Fix broken behaviour with multiple nested calls to *_sample_bpm.

As you can see there is much that is new to get your teeth into. The help system will enable you to become familiar with the new features, with plenty of syntax examples and additions to the tutorial.

The improved GUI is a delight to use and is more polished in its looks. The ability to turn off the log pane together with the buttons and tabs can give a much larger space in which to display code on a small screen. Although the new Dark Mode is intended to make it nicer to use Sonic Pi in live coding sessions without projecting a garish white screen, I find it preferable to use it most of the time, because of the coloured syntax which makes it easier to follow the code in the newly named buffer 9rather than workspace). The new error reporting system is great. It specifies the nature and position of errors much more clearly than in 2.5 and earlier versions.
I have been using 2.6dev throughout the gestation period and I have found the new commands very useful. In particular the tick system revolutionises the way you can use live_loop(s) to generate rhythms and note patterns in conjunction with rings. A new Ticking section in the tutorial gets you going on this. In fact the last few pieces I have written for Sonic Pi all involve using the tick system. These can be heard in the links below, which all also contain links to the code used to produce them, which all run on version 2.6

https://soundcloud.com/rbnman/ticksgalore

https://soundcloud.com/rbnman/sequencegeneratorwithbinaryrhythmtune

https://soundcloud.com/rbnman/ambiglassrhythms

https://soundcloud.com/rbnman/scaletypecontrolledarpeggios

If you are just getting going with Sonic Pi, and think it may be a bit bewildering take heart. The tutorial system will introduce you slowly to its many features, and the examples section contains many completed scripts which you can copy and paste and try out.

Simultaneously with the new release of Sonic Pi 2.6  is the newest issue of the MagPi Magazine, freely downloadable or on sale in W.H.Smiths. In this issue Sam Aaron has written the first part of a Tutorial entitled Sonic Pi Live Coding. So if you have never used Sonic Pi, why not give a it a go. You will not regret it!

The new version for the Raspberry Pi will appear soon in the Raspian repository, or it can be downloaded now manually from sonic-pi.net  and versions for the Mac and PC are downloadable from sonic-pi.net.

Sonic Pi playlist program

Previously  I have detailed here a jukebox program which enables you to select files from a directory to be played in Sonic Pi, making use of the Sonic Pi CLI gem module written by Nick Johnstone. This works well, but although it contains an option to play a series of linked files together, it does not enable this to happen without first modifying the files.

I decided to write a playlist script which could be run and would enable Sonic Pi to play all the SP files in a specified folder one after the other, with a 2 second break between each one. Once again the program relies on the Sonic Pi CLI and this needs to be installed, which is a simple process. You also need to have Sonic Pi running.

The script for the program is shown below

#!/usr/bin/ruby

#ruby script to play a playlist of sonic pi files contained in a specified directory by Robin Newman, July 2015
#sample usage: ./pl.rb /home/pi/spfiles    (where spfiles contains the sonic pi files to be played)
#A 2 second gap is placed between each file playing and the next
#requires the Command Line Interface gem sonic_pi downloadable from https://github.com/Widdershin/sonic-pi-cli

#check for arg
if ARGV.length == 0 then
  puts 'usage: ./pl.rb absolute/path/to/directory/of/sonicpifiles'
  exit 1
else
  spfiles = ARGV[0]
end

#PATHNAMES WHICH ARE USED
path="/tmp/jukebox" #path for temporary files folder
clipath="/usr/local/bin" #absolute path to sonic_cli command line interface

#setup temp file directory
system 'mkdir '+path
#set up init.txt file containing initialisation commands for SP
#makes sure that any changes made in one sp file are cancelled before the next one plays
f=open(path+'/init.txt','w')
f.puts "use_debug false"
f.puts "set_volume! 1"
f.close
#get list of filenames and number of files to be played
fnames=[]
Dir.foreach(spfiles) do |filename|
  next if File.directory?(spfiles+"/"+filename) #ignore non file entries
  fnames.concat [filename]
end
fnames=fnames.sort_by{|word| word.downcase}.reverse #sort in reverse order alpahbetically case insensitive

numfiles= fnames.length

#send commands to cli for each file, topping and tailing with sync and cue commands
for x in 0..(numfiles-1) do
    #set up sync command ahead of next file
    f=open(path+'/sync.txt','w')
    f.puts "\nsync :link"+(numfiles-x-1).to_s
    f.puts "sleep 2" #add sleep gaps between files
    f.close
    #set up cue command after next file
    f=open(path+'/cue.txt','w')
    f.puts "\ncue :link"+(numfiles-x).to_s
    f.close
    #check if last file
    if x < (numfiles -1) then
      #if not last file send sync, init, file data and cue commands
      system "cat "+path+"/sync.txt "+path+"/init.txt "+spfiles+"/"+fnames[x]+" "+path+"/cue.txt| "+clipath+"/sonic_pi "# >> "+path+"/out.txt" #
    else
      #now do last file, omitting the sync command so that this plays straight away
      system "cat "+path+"/init.txt "+spfiles+"/"+fnames[x]+" "+path+"/cue.txt| "+clipath+"/sonic_pi "# >> "+path+"/out.txt" #
    end
    puts "Now loading "+fnames[x]+" play number "+(numfiles-x).to_s
  end
  puts "\nNB files loaded in reverse to playorder"
  #tidy up by deleting temporary files
  system 'rm -fR '+path

Basically the program extracts the location of the sonic pi files folder from the argument supplied when it is called, and it makes a list of all the files in that folder in reverse alphabetical order.
It then goes into a loop calling the sonic_pi cli and sending it the code for each file in turn. The trick is that it sends a sync command BEFORE each file (except for the last one (which is the first name alphabetically). AFTER each file code it sends a cue command which links to the sync command of the previous file. By this mechanism, the last file sent (the first one alphabetically) plays, and then trigger the next file, and so on until all the files have been played.
Two further additions are made. After each sync command a series of commands are inserted to reset the standard volume and to disable debug. This is in case any of the files alter these values whilst they are playing. Secondly a sleep 2 is inserted to separate each file from the previous one.

As presented the file is for use on a Raspberry Pi. It can be amended slightly to work on a Mac (and no doubt a PC) as well. Differences may be:
The location of the ruby interpreter in the first line of the file. You can miss this line out and call ruby explicitly if it is easier: e g ruby pl.rb /path/to/sonicpi/files
Secondly the path to the sonic_cli command line interpreter. On my mac this was
/Users/rbn/.rvm/gems/ruby-2.1.2/bin/sonic_pi giving a clipath of
/Users/rbn/.rvm/gems/ruby-2.1.2/bin as opposed to /usr/local/bin on the Pi.

This leads on to installing the cli. Start a terminal window on the Pi and type

cd ~
git clone https://github.com/Widdershin/sonic-pi-cli.git

gem install sonic-pi-cli

The script can be downloaded by typing

wget https://gist.githubusercontent.com/rbnpi/8ae698b50e540b50ad21/raw/211e5356f67d5fe4e4a20b46358abf0b7b7dfc83/pl.rb

To use the script, assemble some sonic pi files in a folder in the Pi home directory, eg spfiles

Startup Sonic Pi

In the terminal window make sure the script is executable by typing

chmod 755 pl.rb

start the playlist running from the terminal window by typing

./pl.rb /home/pi/spfiles

You should see a list of the files on the screen as they are processed and then Sonic Pi will start playing them.