Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fanfare for St. Cecilia's Hall by Andrew Blair, played by Sonic Pi. Hear both versions on soundcloud at https://soundcloud.com/user-195236670/sets/fanfareforstceciliashall and there is an article at https://rbnrpi.wordpress.com/2017/12/05/fanfare-for-st-cecilias-hall-played-by-sonic-pi/
#Fanfare for St Cecilia's Hall by Andrew Blair, first performed 29th November 2017
#at the official opening of St Cecilia's Hall by HRH The Princess Royal, following a major refurbishment
#coded by Robin Newman, December 2017 with the composer's permission
#I am using code I developed to play samples from Sonatina Symphonic Library, but I have replaced
#the trumpet samples with ones I created myself, using the same file names.
#path to library samples folder (including trailing /)
path="~/Desktop/samples/Fanfare/"
#create array of instrument details
# each entry: name,folder name,sample prefix,offsetclass type,lowest note, highest note
voices=[
["Trumpet","Trumpet","trumpet-",1,:e3,:f6]]
uncomment do #can comment if samples loaded, to allow quick redefine of functions
killit = 0 #used to stop live_loop :t when all samples loaded
define :load do |i|
trigger=0
live_loop :t do
sleep 0.3
if trigger== 1
cue :start
end
stop if killit == 1 # stop when all samples loaded
end
load_samples path+voices[i][1],voices[i][2]
trigger=1
sync :start
end
load(0)
killit = 1 #stop live_loop :t
sleep 2
end
puts "The following voices can be used:-"
voices.each_with_index do |n,i|
puts i.to_s,n[0]
end
puts voices.length.to_s+" voices"
#setup global variables
sampledir=""
sampleprefix=""
offsetclass=""
low=""
high=""
paths=""
#setup data for current inst
define :setup do |inst,path|
sampledir=voices.assoc(inst)[1]
sampleprefix=voices.assoc(inst)[2]
offsetclass=voices.assoc(inst)[3]
low=voices.assoc(inst)[4]
high=voices.assoc(inst)[5]
#amend path for instrument sampledir
paths=path+sampledir+"/"
end
sleep 0.2
#define routine to play sample using "Sonatina like" data
define :pl do |np,d,inst,vol=1,s=0.9,r=0.1,tp=0,pan=0| #nv,d,offsetclass,vol,s,r,tp,pan
m=60.0/current_bpm #missing scaling factor
setup(inst,path)
#check if note in range of supplied samples
#use lowest/highest sample for out of range
change=0 #used to give rpitch for coverage outside range
frac=0
n=np+tp #note allowing for transposition
if n.is_a?(Numeric) #allow frac tp or np
frac=n-n.to_i
n=n.to_i
end
if note(np)+tp<note(low) #calc adjustment for low note
change=note(np).to_i+tp-note(low)
n=note(low)
end
if note(np).to_i+tp > note(high) #calc adjustment for high note
change = note(np).to_i+tp-note(high)
n=note(high)
end
if change < -5 or change > 5 #set allowable out of range
#if outside print messsage
puts 'inst: '+inst+' note '+np.to_s+' with transpostion '+tp.to_s+' out of sample range'
else #otherwise calc and play it
#calculate base note and octave
base=note(n)%12
oc = note(n) #do in 2 stages because of alignment bug
oc=oc/12 -1
#find first part of sample note
slookup=['c','c#','d','d#','e','f','f#','g','g#','a','a#','b']
#lookup sample to use,and rpitch offset, according to offsetclass
case offsetclass
when 0
oc += 1 if base == 11 #adjust if sample needs next octave
snumber=[0,0,3,3,3,6,6,6,9,9,9,0]
offset=[ 0,1,-1,0,1,-1,0,1,-1,0,1,-1]
when 1
snumber=[1,1,1,4,4,4,7,7,7,10,10,10]
offset=[-1,0,1,-1,0,1,-1,0,1,-1,0,1]
when 2
oc -= 1 if base == 0 #adjust if sample needs previous octave
snumber=[11,2,2,2,5,5,5,8,8,8,11,11]
offset=[1,-1,0,1,-1,0,1,-1,0,1,-1,0]
when 3
snumber=[0,1,2,3,4,5,6,7,8,9,10,11] #this class has sample for every note
offset=[0,0,0,0,0,0,0,0,0,0,0,0]
end
#generate sample name
sname=sampleprefix+(slookup[snumber[base]]).to_s+oc.to_s
#play sample with appropriate rpitch value
sample paths,sname,rpitch: offset[base]+change+frac,sustain: s*d*m,release: r*d*m,pan: pan,amp: vol
end
end
#define function to play lists of linked samples/durations using Sonatina samples
define :plarray do |notes,durations,offsetclass,tp=0,pan=0,vol=1,s=0.9,r=0.1|
#puts offsetclass
notes.zip(durations).each do |n,d|
if n.respond_to?(:each)
n.each do |nv|
pl(nv,d,offsetclass,vol,s,r,tp,pan) if ![nil,:r,:rest].include? nv#allow for rests
end
else
pl(n,d,offsetclass,vol,s,r,tp,pan) if ![nil,:r,:rest].include? n#allow for rests
end
sleep d
end
end
use_bpm 85
with_fx :reverb, room: 0.8,mix: 0.6 do
##| define :plarray do |notes,durations,pan=0,amp =0.5|
##| notes.zip(durations).each do |n,d|
##| play n,sustain: d*0.9,release: d*0.1,amp: amp,pan: pan
##| sleep d
##| end
##| end
b=4;md=3;m=2;cd=1.5;c=1;qd=0.75;q=0.5;sqd=0.375;sq=0.25;dsq=0.125
n1=[:c4,:g4,:c5,:f5,:bb5,:f5,:c6,:g5,:g5,:bb5,:f5,:e5,:d5,:e5,:r]
d1=[c,c,c,c,m,m,m,cd,q,m,md,q,q,m+md,c+c]
#d1=[1,1,1,1,2,2,2,1.5,0.5,2,3,0.5,0.5,5,2]
n1b=[:c5,:g4,:c5,:c5,:c5,:c5,:g4,:c5,:c5,:d5,:e5,:d5,:e5,:d5,:c5,:g5,\
:d5,:g4,:g4,:g4,:e5,:d5,:f5,:e5,:d5,:c5,:d5,:c5,:d5,:e5,:r,:c5,:g4,:c5,:c5,:c5,:c5,:g4,:c5]
d1b=[q,q,qd,dsq,dsq,q,q,c,sq,sq,c,dsq/2,dsq/2,dsq,sq,m,\
qd,dsq,dsq,q,q,cd,q,sq,sq,q,qd,dsq,dsq,m,q,q,q,qd,dsq,dsq,q,q,c]
n1c=[:c5,:d5,:e5,:d5,:e5,:d5,:c5,:g5,:f5,:e5,:d5,:e5,:f5,:e5,:d5,:e5,:f5,:g5,:g5,:c6,:e5,:f5,:g5,:g5,:c5,:r,:g4]
d1c=[sq,sq,c,dsq/2,dsq/2,dsq,sq,m,cd,sq,sq,dsq/2,dsq/2,dsq,sq,sq,sq,q,q,q,sq,sq,q,q,c,q,q]
n1d=[:c5,:c5,:c5,:d5,:e5,:d5,:e5,:d5,:g4,:g4,:g4,:d5,:d5,:d5,:e5,:f5,:e5,:f5,:e5,:d5,:c5,:c5,\
:af5,:f5,:f5,:g5,:af5,:g5,:e5,:g5,:c6,:g5,:r,:g4]
d1d=[qd,sq,q,sq,sq,dsq/2,dsq/2,dsq+q,sq,q,q,qd,sq,q,sq,sq,dsq/2,dsq/2,dsq+q,sq,q,q,qd,sq,q,sq,sq,c+sq,sq,sq,sq,m+cd,sq,q]
n1e=[:c5,:g4,:e4,:g4,:c5,:d5,:e5,:d5,:e5,:d5,:g4,:g4,:g4,:g4,:d5,:c5,:d5,:e5,:d5,:e5,:f5,\
:e5,:f5,:e5,:d5,:e5,:d5,:c5,:c5,:c5,:g4,:c5,:e5,:d5,:e5,:d5,:c5,:d5,:e5,:d5,:e5,:g5]
d1e=[sqd,dsq,sqd,dsq,q,sq,sq,dsq/2,dsq/2,dsq+sq,sqd,dsq,q,q, sqd,dsq,sqd,dsq,q,sq,sq,dsq/2,dsq/2,dsq,sq,sq,sq,q,q,q,q,q,sq,sq,dsq,dsq,sq,sq,sq,q,sq,sq]
n1f=[:c6,:e5,:f5,:g5,:g5,:c5,:r,:c4,:g4,:c5,:f5,:bb5,:ab5,:g5,:ab5,:g5,:f5,:c6,:g5,:g5,\
:bb5,:f5,:e5,:f5,:e5,:d5,:e5,:r]
d1f=[q,sq,sq,q,q,m,sq,c,c,c,c,cd,q,dsq/2,dsq/2,dsq+sq+q,c,m,cd,q,m,md,dsq/2,dsq/2,dsq+sq,q,b+q,q+c]
n2=[:c4,:g4,:c5,:d5,:bb4,:c5,:g4,:g4,:bb4,:g4,:c5,:c4,:r]
d2=[m,c,m,m,c,m,cd,q,md,c,b,md,c+c]
n2b=[:r,:c4,:g4,:c4,:c4,:c4,:c4,:g4,:c5,:c5,:d5,:e5,:e5,:f5,:e5,:d5,:c5,:g4,:g4,:g4,:g4,:g4,:d5,:c5,:g4,:g4,:g4,:c4,\
:r,:r,:c5,:g4,:c4,:c4,:c4]
d2b=[c,cd,q,qd,dsq,dsq,q,q,c,sq,sq,q,dsq/2,dsq/2,dsq+sq,sq,sq,m,qd,dsq,dsq,q,q,q,q,qd,sq,m,q, c,cd,q,qd,dsq,dsq]
n2c=[:c4,:g4,:c5,:c5,:d5,:e5,:e5,:f5,:e5,:d5,:c5,:d5,:g4,:g4,:c5,:g4,:c5,:d5,:e5,:g4,:g4,:g3,:g3,:c4,:r,:g4]
d2c=[q,q,c,sq,sq,q,dsq/2,dsq/2,dsq+sq,sq,sq,qd,sq,c,sq,sq,sq,sq,q,q,c,qd,sq,c,q,q]
n2d=[:c4,:c4,:g3,:g3,:g3,:g3,:c4,:c4,:c4,:c4,:e4,:g4,:c5,:g4,:g4,:g4,:g4,:r,:g4]
d2d=[cd,q,cd,q,cd,q,cd,q,cd,q,c,q,q,cd,sqd,dsq,cd,sq,q]
n2e=[:c4,:e4,:c4,:g3,:g3,:g3,:g4,:e4,:c4,:c4,:c4,:g3,:c4,:e4,:g4,:c5,:g4,:g4,:g4]
d2e=[c,qd,sq,cd,q,c,qd,sq,cd,q,q,q,q,q,qd,sq,q,sq,sq]
n2f=[:c5,:e4,:g4,:g4,:c4,:r,:c4,:g4,:c5,:d5,:bb4,:c5,:g4,:g4,:bb4,:g4,:c5,:c4,:c4,:c4,:c4,:r]
d2f=[q,q,q,q,m,sq,m,c,m,m,c,m,cd,q,md,c,md,qd,dsq,dsq,m+q,q+c]
tr=-2
#use_transpose -2
in_thread do
plarray(n1,d1,"Trumpet",tr,-0.5)
end
plarray(n2,d2,"Trumpet",tr,0.5)
in_thread do
plarray(n1b,d1b,"Trumpet",tr,-0.5)
end
plarray(n2b,d2b,"Trumpet",tr,0.5)
in_thread do
plarray(n1c,d1c,"Trumpet",tr,-0.5)
end
plarray(n2c,d2c,"Trumpet",tr,0.5)
in_thread do
plarray(n1d,d1d,"Trumpet",tr,-0.5)
end
plarray(n2d,d2d,"Trumpet",tr,0.5)
in_thread do
plarray(n1e,d1e,"Trumpet",tr,-0.5)
end
plarray(n2e,d2e,"Trumpet",tr,0.5)
in_thread do
plarray(n1f,d1f,"Trumpet",tr,-0.5)
end
plarray(n2f,d2f,"Trumpet",tr,0.5)
end #reverb
#Fanfare for St Cecilia's Hall by Andrew Blair, first performed 29th November 2017
#at the official opening of St Cecilia's Hall by HRH The Princess Royal, following a major refurbishment
#coded by Robin Newman, December 2017, with the composer's permission
use_bpm 85
use_synth :saw
with_fx :reverb, room: 0.8,mix: 0.8 do
define :plarray do |notes,durations,pan=0,amp =0.5|
notes.zip(durations).each do |n,d|
play n,sustain: d*0.9,release: d*0.1,amp: amp,pan: pan
sleep d
end
end
b=4;md=3;m=2;cd=1.5;c=1;qd=0.75;q=0.5;sqd=0.375;sq=0.25;dsq=0.125
n1=[:c4,:g4,:c5,:f5,:bb5,:f5,:c6,:g5,:g5,:bb5,:f5,:e5,:d5,:e5,:r]
d1=[c,c,c,c,m,m,m,cd,q,m,md,q,q,m+md,c+c]
n1b=[:c5,:g4,:c5,:c5,:c5,:c5,:g4,:c5,:c5,:d5,:e5,:d5,:e5,:d5,:c5,:g5,\
:d5,:g4,:g4,:g4,:e5,:d5,:f5,:e5,:d5,:c5,:d5,:c5,:d5,:e5,:r,:c5,:g4,:c5,:c5,:c5,:c5,:g4,:c5]
d1b=[q,q,qd,dsq,dsq,q,q,c,sq,sq,c,dsq/2,dsq/2,dsq,sq,m,\
qd,dsq,dsq,q,q,cd,q,sq,sq,q,qd,dsq,dsq,m,q,q,q,qd,dsq,dsq,q,q,c]
n1c=[:c5,:d5,:e5,:d5,:e5,:d5,:c5,:g5,:f5,:e5,:d5,:e5,:f5,:e5,:d5,:e5,:f5,:g5,:g5,:c6,:e5,:f5,:g5,:g5,:c5,:r,:g4]
d1c=[sq,sq,c,dsq/2,dsq/2,dsq,sq,m,cd,sq,sq,dsq/2,dsq/2,dsq,sq,sq,sq,q,q,q,sq,sq,q,q,c,q,q]
n1d=[:c5,:c5,:c5,:d5,:e5,:d5,:e5,:d5,:g4,:g4,:g4,:d5,:d5,:d5,:e5,:f5,:e5,:f5,:e5,:d5,:c5,:c5,\
:af5,:f5,:f5,:g5,:af5,:g5,:e5,:g5,:c6,:g5,:r,:g4]
d1d=[qd,sq,q,sq,sq,dsq/2,dsq/2,dsq+q,sq,q,q,qd,sq,q,sq,sq,dsq/2,dsq/2,dsq+q,sq,q,q,qd,sq,q,sq,sq,c+sq,sq,sq,sq,m+cd,sq,q]
n1e=[:c5,:g4,:e4,:g4,:c5,:d5,:e5,:d5,:e5,:d5,:g4,:g4,:g4,:g4,:d5,:c5,:d5,:e5,:d5,:e5,:f5,\
:e5,:f5,:e5,:d5,:e5,:d5,:c5,:c5,:c5,:g4,:c5,:e5,:d5,:e5,:d5,:c5,:d5,:e5,:d5,:e5,:g5]
d1e=[sqd,dsq,sqd,dsq,q,sq,sq,dsq/2,dsq/2,dsq+sq,sqd,dsq,q,q, sqd,dsq,sqd,dsq,q,sq,sq,dsq/2,dsq/2,dsq,sq,sq,sq,q,q,q,q,q,sq,sq,dsq,dsq,sq,sq,sq,q,sq,sq]
n1f=[:c6,:e5,:f5,:g5,:g5,:c5,:r,:c4,:g4,:c5,:f5,:bb5,:ab5,:g5,:ab5,:g5,:f5,:c6,:g5,:g5,\
:bb5,:f5,:e5,:f5,:e5,:d5,:e5,:r]
d1f=[q,sq,sq,q,q,m,sq,c,c,c,c,cd,q,dsq/2,dsq/2,dsq+sq+q,c,m,cd,q,m,md,dsq/2,dsq/2,dsq+sq,q,b+q,q+c]
n2=[:c4,:g4,:c5,:d5,:bb4,:c5,:g4,:g4,:bb4,:g4,:c5,:c4,:r]
d2=[m,c,m,m,c,m,cd,q,md,c,b,md,c+c]
n2b=[:r,:c4,:g4,:c4,:c4,:c4,:c4,:g4,:c5,:c5,:d5,:e5,:e5,:f5,:e5,:d5,:c5,:g4,:g4,:g4,:g4,:g4,:d5,:c5,:g4,:g4,:g4,:c4,\
:r,:r,:c5,:g4,:c4,:c4,:c4]
d2b=[c,cd,q,qd,dsq,dsq,q,q,c,sq,sq,q,dsq/2,dsq/2,dsq+sq,sq,sq,m,qd,dsq,dsq,q,q,q,q,qd,sq,m,q, c,cd,q,qd,dsq,dsq]
n2c=[:c4,:g4,:c5,:c5,:d5,:e5,:e5,:f5,:e5,:d5,:c5,:d5,:g4,:g4,:c5,:g4,:c5,:d5,:e5,:g4,:g4,:g3,:g3,:c4,:r,:g4]
d2c=[q,q,c,sq,sq,q,dsq/2,dsq/2,dsq+sq,sq,sq,qd,sq,c,sq,sq,sq,sq,q,q,c,qd,sq,c,q,q]
n2d=[:c4,:c4,:g3,:g3,:g3,:g3,:c4,:c4,:c4,:c4,:e4,:g4,:c5,:g4,:g4,:g4,:g4,:r,:g4]
d2d=[cd,q,cd,q,cd,q,cd,q,cd,q,c,q,q,cd,sqd,dsq,cd,sq,q]
n2e=[:c4,:e4,:c4,:g3,:g3,:g3,:g4,:e4,:c4,:c4,:c4,:g3,:c4,:e4,:g4,:c5,:g4,:g4,:g4]
d2e=[c,qd,sq,cd,q,c,qd,sq,cd,q,q,q,q,q,qd,sq,q,sq,sq]
n2f=[:c5,:e4,:g4,:g4,:c4,:r,:c4,:g4,:c5,:d5,:bb4,:c5,:g4,:g4,:bb4,:g4,:c5,:c4,:c4,:c4,:c4,:r]
d2f=[q,q,q,q,m,sq,m,c,m,m,c,m,cd,q,md,c,md,qd,dsq,dsq,m+q,q+c]
use_transpose -2
in_thread do
plarray(n1,d1,-0.5)
end
plarray(n2,d2,0.5)
in_thread do
plarray(n1b,d1b,-0.5)
end
plarray(n2b,d2b,0.5)
in_thread do
plarray(n1c,d1c,-0.5)
end
plarray(n2c,d2c,0.5)
in_thread do
plarray(n1d,d1d,-0.5)
end
plarray(n2d,d2d,0.5)
in_thread do
plarray(n1e,d1e,-0.5)
end
plarray(n2e,d2e,0.5)
in_thread do
plarray(n1f,d1f,-0.5)
end
plarray(n2f,d2f,0.5)
end #reverb
@rbnpi

This comment has been minimized.

Show comment
Hide comment
@rbnpi

rbnpi Dec 5, 2017

The first version will run "as is" in Sonic Pi, utilising the :tri synth
You can download the samples required for the second file at http://r.newman.ch/rpi/Fanfare.zip
extract the folder Fanfare and place in a suitable location on your computer.
Adjust line 8 in the program to point to this location.

Owner

rbnpi commented Dec 5, 2017

The first version will run "as is" in Sonic Pi, utilising the :tri synth
You can download the samples required for the second file at http://r.newman.ch/rpi/Fanfare.zip
extract the folder Fanfare and place in a suitable location on your computer.
Adjust line 8 in the program to point to this location.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment