Sonic Pi Jam Band

################# Sonic Jam ####################
# ( artficial musical intelligence unleashed )
# ( music is in the ear of the beholder )
mn=[:r];for jn in 1..1023
  mn[jn]=(hz_to_midi((440/81.0)*jn))
end; n1=[]; n2=[]; n3=[]

m=[48,54,64,72,81,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

synth :dsaw, note: mn[27],sustain: 1000, detune: 0.1, amp: 0.05
synth :dsaw, note: mn[27]+7,sustain: 1000, detune: 0.1, amp: 0.05

use_random_seed 3
live_loop :i1 do
  for x in 0..7; nr=mn[choose(m)]
    if rand_i(9)==2 then n1[x]=nr; end
    synth :pluck, note: n1[x]
sleep 0.25; end; end

use_random_seed 5
live_loop :i2 do
  for x in 0..7; nr=mn[choose(m)]
    if rand_i(9)==5 then n2[x]=nr; end
    synth :pretty_bell, note: n2[x], release: 0.1
sleep 0.25; end; end

use_random_seed 7
live_loop :i3 do
  for x in 0..7; nr=mn[choose(m)]
    if rand_i(9)==6 then n3[x]=nr; end
    synth :fm, note: n3[x]-12
sleep 0.25; end; end
5 Likes

This is awesome!

Can you explain what is happening here? It is mind-boggling to me lol

mn=[:r];for jn in 1..1023
  mn[jn]=(hz_to_midi((440/81.0)*jn))
end; n1=[]; n2=[]; n3=[]

m=[48,54,64,72,81,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

synth :dsaw, note: mn[27],sustain: 1000, detune: 0.1, amp: 0.05
synth :dsaw, note: mn[27]+7,sustain: 1000, detune: 0.1, amp: 0.05
1 Like
mn= [:r]
# create an array ' midi_numbers ' with the  first element ( mn0 ) 
# being a rest
 
for jn in 1..1023
# use the numbers ( from just intonation ) 1 to 1023 as array index
# the mathematical values of the numbers correspond to their
# frequency ratios

mn[jn]=(hz_to_midi((440/81.0)*jn))
# set just number 81 as A  440 Hz
end

 n1=[]; n2=[]; n3=[]
# create 3 arrays

m=[48,54,64,72,81,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
# array of possible ' just ' numbers ( notes ) to be chosen

synth :dsaw, note: mn[27],sustain: 1000, detune: 0.1, amp: 0.05
synth :dsaw, note: mn[27]+7,sustain: 1000, detune: 0.1, amp: 0.05
# make drone at ~ D ( mn[27]) (+ 7 gives 5th (A))
3 Likes

EDIT @hitsware beat me to it. But here are my thoughts…

If you split it up bit by bit its not too hard to follow what is going on. The fact that there are multiple statements on one line separated by ; although making it more compact can make it harder to read.

mn is a list which starts with its first element being a rest symbol :r In the following jn loop it has further values added to it given by the formula hz_to_midi((440/81.0)*jn) This will vary from about 4.9 when jn is 2 to 112.9 when it is 1023. Interestingly the value of jn=1 gives an erroneous answer of -7.07 I guess because the hz_to_midi function doesn’t cope with input values less than the frequency corresponding to midi value 1. Perhaps this could vbe considered a “bug” in SP. However that value of the mn list is not used in the program subsequently to play a note so it doesn’t matter here.
I illuminated what is happening in these lines by altering the first few lines as shown below

mn=[nil];for jn in (1..1023)
  mn[jn]= (hz_to_midi((440/81.0)*jn))
  (play mn[jn],release: 0.01)if mn[jn]>=0
    sleep 0.01
  end; n1=[]; n2=[];  n3=[]

This gives an aural representation of the slowly increasing values stored in the mn list which actually sounds quite interesting when played rapidly like this,

the n1=[];n2=[];n3=[] in the last line simply sets up three empty lists which are used in the subsequent three live loops.

synth :dsaw, note: mn[27],sustain: 1000, detune: 0.1, amp: 0.05
synth :dsaw, note: mn[27]+7,sustain: 1000, detune: 0.1, amp: 0.05

simply each play a drone note that lasts for 1000 seconds (or until you stop the program)
The first uses a note values of mn[27] which holds 49.98, and the second plays 5 semitones higher at 54.98 They both use the dsaw synth with a detune opt also set.

Each of the three live loops behaves in the same way, but using different synths and a different random_seed at the start. They also have a different match with which to choose a note to be added to their respective play lists n1, n2 and n3
The first one adds a note to the list if rand_i(9)==2 The second if rand_i(9)==5 and the third if rand_i(9)==6

You can see how the different play lists modify themselves as the program runs by adding suitable puts statements as shown in my modified program shown below. (uncomment as desired)
(I added a use_debug false to hide the synth messages)
I hope it gives you a better idea of what is going on, and that this illustrates the techniques you can use to follow programs that may appear inscrutable at first.

use_debug false
mn=[nil];for jn in (1..1023)
  mn[jn]= (hz_to_midi((440/81.0)*jn))
  #(play mn[jn],release: 0.01)if mn[jn]>=0 #miss out jn==1 value
  #  sleep 0.01
end; n1=[]; n2=[];  n3=[]
puts mn[27],"used for drone frequency"
sleep 4 #so you can read the message above
#I think m doesnt need to be quite as long. ONly 8 entries needed
m=[48,54,64,72,81,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

synth :dsaw, note: mn[27],sustain: 1000, detune: 0.1, amp: 0.05
synth :dsaw, note: mn[27]+7,sustain: 1000, detune: 0.1, amp: 0.05

use_random_seed 3
live_loop :i1 do
  for x in 0..7; nr=mn[choose(m)] #choose nr using m list above
    if rand_i(9)==2 then n1[x]=nr; end
    synth :pluck, note: n1[x]
    puts "n1 list ",n1
sleep 0.25; end; end

use_random_seed 5
live_loop :i2 do
  for x in 0..7; nr=mn[choose(m)]
    if rand_i(9)==5 then n2[x]=nr; end
    #puts "n2 list ",n2
    synth :pretty_bell, note: n2[x], release: 0.1
sleep 0.25; end; end

use_random_seed 7
live_loop :i3 do
  for x in 0..7; nr=mn[choose(m)]
    if rand_i(9)==6 then n3[x]=nr; end
    synth :fm, note: n3[x]-12
    #puts "n3list ",n3
sleep 0.25; end; end

slide the boundary of the log window to the left so you can see all of the n1 list printed out. nil values will be treated as rests when you play them

2 Likes
# Thank You Robin .... The Aural with the explanation is nifty !

################## Notes on Just Intonation ###################

# Just intonation attempts to use numerical values to achieve
# musical results.
# The lowest sequence that will produce a western major scale is:
# 24,27,30,32,36,40,45,48
# c, d, e, f, g, a, b, C ( 'normalizing' to the key of C )
# Since we usually set ' A 440 Hz ' as a referance , we can
# see that 11 * the just values will give the notes as frequencies .
# Therefore : midi_number ( frequency ) = hz_to_midi ( 11 * just_number )
midi_number=[]
for just_number in 1..1023 # A '0' will result in an infinity error
  midi_number[just_number]=hz_to_midi(11*just_number)#.round for tempered
end
# To test :
skale = [24,27,30,32,36,40,45,48]
for i in 0..7
  play midi_number[skale[i]]
  puts i,"  ",11*skale[i],"  ",midi_number[skale[i]]
  sleep 1
end
1 Like

Thank you! That clears it up quite a bit.

Fantastic explanation. Thank you for explaining it to me! I’m just getting into this stuff so having you break it down is immensely helpful.

############# Jam Band learns about Chords ###############

mn=[:r];for jn in 1..1023
    mn[jn]=(hz_to_midi(5.5*jn)).round
  n1=[];n2=[]; n3=[]; end

c=[8,6,9,6]; m=[4,5,6,0,0]; f=[2,3,5]
z=[2,0,1,1,4,0,1,1]

live_loop :p do
    for i in 0..7
      synth :noise, release: 0.1, amp: z[i]/15.0
sleep 0.125; end; end

live_loop :k do
    for i in 0..3
      synth :dsaw, note: mn[c[i]*choose(f)], sustain: 1,
          release: 0, amp: 0.03
      synth :dsaw, note: mn[c[i]*choose(f)], sustain: 1,
          release: 0, amp: 0.03
      synth :dsaw, note: mn[c[i]*choose(f)], sustain: 1,
          release: 0, amp: 0.03
    sleep 1; end; end

    use_random_seed 7
    live_loop :i1 do
      for i in 0..15; x=i/4; nr=mn[c[x]*choose(m)]
      if rand_i(63)==1 then n1[i]=nr; end
      synth :pluck, note: n1[i], amp: 0.7
  sleep 0.25; end; end

use_random_seed 2
live_loop :i2 do
    for i in 0..15; x=i/4; nr=mn[c[x]*choose(m)]
      if rand_i(63)==2 then n2[i]=nr; end
      synth :pretty_bell, note: n2[i]+12, release: 0.1, amp: 0.5
  sleep 0.25; end; end

use_random_seed 9
live_loop :i3 do
    for i in 0..15; x=i/4; nr=mn[c[x]*choose(m)]
      if rand_i(63)==7 then n3[i]=nr; end
      synth :fm, note: n3[i]-12, release: 0.5
  sleep 0.25; end; end

Jam Band learns a song of the times …

2 Likes
#### Jam Band Get's a Groove Goin'
##### BALL
mn=[:r]; for jn in 1..1023
  mn[jn]=hz_to_midi((5.5)*jn).round+2
end; use_bpm 150; puts mn[32]

d=[2,0,0,0,8,0,4,4, 0,0,2,0,8,0,4,4]; vz=0;vs=0;vk=0;vd=0
c=[4,8,4,8,8,0,0,0, 7,0,8,0,6,0,7,0, 8,4,8,4,8,0,0,0, 7,0,0,0,0,0,0,0]
m=[2,4,3,4]; o=[3,2,4]; n=[1,4,3,4]; p=[2,0,1,1,3,0,1,1]

for a in 0..3; play mn[128], release: 0.01, amp: 0.5; sleep 2 ; end

synth :dsaw, note: mn[24], detune: 0.01, sustain: 1000,
  release: 0, amp: 0.03
synth :dsaw, note: mn[16], detune: 0.01, sustain: 1000,
  release: 0, amp: 0.03

for i in 0..1000; w=i%32; x=i%16; y=i%8; z=i%4; j=rand_i(3); h=rand_i(3)
  if i > 31 then vz = p[y]/4.0; end
  if i > 63 then vs = 18.0/(n[z]**2.5); end
  if i > 95 then vk = 0.5; end
  if i > 159 then vd = 0.8; end
  synth :noise, release: 0.01, amp: vz
  synth :blade, note: mn[n[z]*16], cutoff: mn[n[z]*16], amp: vs
  synth :piano, note: mn[c[w]*m[z]*o[h]], amp: vk
  synth :piano, note: mn[c[w]*m[z]*o[j]], amp: vk
  synth :beep, note: mn[d[x]*16],release: 0.01, amp: vd
sleep 0.5; end


1 Like

Hi there ;D

Wow, the source make very sweet smouth music ;D

Thanks for sharing ;D

Greetings

Bogus