Chord progression tool

I was reading about, and playing with, chord progressions. I used this little interface to play with things.

define :chrd do |deg, tonic, sca|
  n = 3
  if deg.match?('7')
    n = 4
    deg = deg.slice(0,deg.length-1).to_sym
  end
  
  return (chord_degree deg, tonic, sca, n)
end

p1 = [:i,:v,:vi,:iv]
p2 = [:i,:iv,:v,:iv]
p3 = [:ii7,:v7,:i7]
p4 = [:i,:i,:i,:i,:iv,:iv,:i,:i,:v,:iv,:i,:i]
p5 = [:i,:vi,:iv,:v]
p6 = [:i,:v,:vi,:iii,:iv,:i,:iv,:v]



live_loop :chord_progs do
  use_synth :prophet
  progression = p3
  tonic = 62.5
  myScale = :mixolydian
  
  progression.each do |deg|
    play (chrd deg, tonic, myScale),\
      sustain: 1
    sleep 1
  end
  stop
end

5 Likes

This is great. Had a play with it this afternoon and came up with this:

#chord progressions doodles by Robn Newman Jan 2021
#developed from initial code by theibbster
use_debug false
define :chrd do |deg, tonic, sca|
  n = 3
  if deg.match?('7')
    n = 4
    deg = deg.slice(0,deg.length-1).to_sym
  end
  return (chord_degree deg, tonic, sca, n)
end

p1 = [:i,:v,:vi,:iv]
p2 = [:i,:iv,:v,:iv]
p3 = [:ii7,:v7,:i7]
p4 = [:i,:i,:i,:i,:iv,:iv,:i,:i,:v,:iv,:i,:i]
p5 = [:i,:vi,:iv,:v]
p6 = [:i,:v,:vi,:iii,:iv,:i,:iv,:v]
pl=(ring p1,p2,p3,p4,p5,p6).shuffle #set up ring of progressions

with_fx :reverb,room: 0.8,mix: 0.7 do #add reverb
  with_fx :level,amp: 1 do |vol| #vary vol as piece progresses
    set :vol,vol #stopre ref to fx_level for control
    
    live_loop :chord_progs do
      progression = pl.tick #get next progresion
      tick_set :tt,look/6 #define tick for tonic changes
      tonic = (ring 62.5,62.5+7,62.5-5,62.5-12,62.5+7-12,62.5-5-12).look(:tt)
      #puts tonic
      #choose scale from specified list
      myScale = (ring :major,:mixolydian,:minor,:minor_pentatonic,:dorian,:aeolian).choose# or tick(:sc)
      #process next progression
      progression.each_with_index  do |deg,i|
        nl=(chrd deg, tonic, myScale) #get notes to play
        use_synth :dsaw #play bass note with dsaw
        play nl[0]-12,\
          sustain: (nl.length)*0.9*0.095,release: 0.005,\
          amp: 0.7,pan: (-1)**i #alternate notes on pan +-1
        use_synth :pulse #use pulse for fast notes
        nl.each do |n| #play notes in sequence
          play n,\
            sustain: 0.095,release: 0.005,\
            amp: 0.5,pan: (-1)**tick(:iloop) #alternate notes on pan +-1
          sleep 0.1
        end
      end#progression
    end#liveloop
  end#level
end#reverb
live_loop :vet do #control level output on 10 sec up/down ramp
  vlev=[0.4,1].tick
  control get(:vol),amp: vlev,amp_slide: 10
  sleep 10
end

Whole range of possibilities to play with. Made a nice piece to try out my experimental .deb install for SP3.3.0beta4 on my Pi400!

3 Likes

I really enjoyed what you did with it, Robin! Lots of bits for me to learn from.

I played with your code for about 10 minutes and ruined it by adding some drums :grin:

#ruined with drums by theibbster
#from: chord progressions doodles by Robin Newman Jan 2021
#from: initial code by theibbster
use_debug false
define :chrd do |deg, tonic, sca|
  n = 3
  if deg.match?('7')
    n = 4
    deg = deg.slice(0,deg.length-1).to_sym
  end
  return (chord_degree deg, tonic, sca, n)
end

p1 = [:i,:v,:vi,:iv]
p2 = [:i,:iv,:v,:iv]
p3 = [:ii7,:v7,:i7]
p4 = [:i,:i,:i,:i,:iv,:iv,:i,:i,:v,:iv,:i,:i]
p5 = [:i,:vi,:iv,:v]
p6 = [:i,:v,:vi,:iii,:iv,:i,:iv,:v]
pl=(ring p1,p2,p3,p4,p5,p6).shuffle #set up ring of progressions

with_fx :reverb,room: 0.8,mix: 0.7 do #add reverb
  with_fx :level,amp: 1 do |vol| #vary vol as piece progresses
    set :vol,vol #stopre ref to fx_level for control
    
    live_loop :chord_progs do
      progression = pl.tick #get next progresion
      tick_set :tt,look/6 #define tick for tonic changes
      tonic = (ring 62.5,62.5+7,62.5-5,62.5-12,62.5+7-12,62.5-5-12).look(:tt)
      #puts tonic
      #choose scale from specified list
      myScale = (ring :major,:mixolydian,:minor,:minor_pentatonic,:dorian,:aeolian).choose# or tick(:sc)
      #process next progression
      progression.each_with_index  do |deg,i|
        nl=(chrd deg, tonic, myScale) #get notes to play
        use_synth :dsaw #play bass note with dsaw
        play nl[0]-12,\
          sustain: (nl.length)*0.9*0.095,release: 0.005,\
          amp: 0.7,pan: (-1)**i #alternate notes on pan +-1
        use_synth :pulse #use pulse for fast notes
        nl.each do |n| #play notes in sequence
          play n,\
            sustain: 0.095,release: 0.005,\
            amp: 0.5,pan: (-1)**tick(:iloop) #alternate notes on pan +-1
          sleep 0.1
        end
      end#progression
    end#liveloop
  end#level
end#reverb
live_loop :vet do #control level output on 10 sec up/down ramp
  vlev=[0.4,1].tick
  control get(:vol),amp: vlev,amp_slide: 10
  control get(:vol2),amp: vlev*1.1, amp_slide: 5
  sleep 10
end

live_loop :triplethats do
  off = rrand(-0.025, 0.025)
  samp = :drum_cymbal_soft
  use_sample_defaults lpf: 115
  with_fx :level, amp: 1.1 do |vol2|
    set :vol2, vol2
    with_bpm 120 do
      sample samp, amp: rrand(0.75,1)
      sleep 1
      sample samp, amp: rrand(0.75,0.95), pan: rrand(0.1,0.25)
      sleep 2.0/3 + off
      sample samp, amp: rrand(0.45,0.7), pan: rrand(-0.25,-0.1)
      sleep 1.0/3 - off
    end
  end
end

live_loop :bd do
  with_bpm 120 do
    sample :bd_boom, amp: 1.2
    sleep 1
  end
end

Cool. Suggest you move the live_loop :vet to the end so that :vol2 is defined before you use it.
Also Lots of variations if you set a random seed at the start eg use_random_seed 6148
Drums are dfficult becuase the timing for each progression is different as they have differing lengths. Tricky to match the rhythms.

1 Like

Thanks for the advice. I’m going to try to make my own with more thought out timings so I can match drums. Still got a lot to learn :slightly_smiling_face:

I also thought about chord progressions, some month ago.
This was my idea: https://github.com/stahnirockt/Sonic-ChordProgression

1 Like

Ok, I’ve come up with something after a little jamming today.I don’t think it’s too good, but I had fun making this.

use_sched_ahead_time 2
define :chrd do |deg, tonic, sca|
  n = 3
  if deg.match?('7')
    n = 4
    deg = deg.slice(0,deg.length-1).to_sym
  end
  
  return (chord_degree deg, tonic, sca, n)
end

define :play_lead do |n,s|
  use_synth :blade
  play n, amp: rrand(0.75,0.8), sustain: 0.2*s, release: 0.5*s,\
    vibrato_rate: 8, vibrato_depth: 0.3, vibrato_delay: 0.25
end


define :strum do |notes, s=1|
  notes = one_in(4) ? notes.scale(0.999) : notes
  time_warp 0 do
    notes.each do |n|
      play_lead n, s
      sleep rrand(0.08,0.12)
    end #notes
  end #time_warp
end #strum function

p1 = [:i7,:v,:vi,:iv]
p2 = [:i7,:iv,:v,:iv]
p3 = [:ii7,:v7,:i7]

t1 = [2,1,1]
t2 = [1.5,1.5,1]
t3 = [1,1,1,1]


use_bpm 110
live_loop :chord_setter do
  progression = [p1,p2,p3].choose
  tonic = 62.5
  myScale = :mixolydian
  progression.each do |deg|
    set :chord, (chrd deg, tonic, myScale)
    sleep rrand_i(2,4)
  end
end

live_loop :lead do
  t = [t1,t2,t3].choose.shuffle
  t.each do |s|
    strum (get :chord), s
    sleep s
  end#t.each
end #:lead loop

live_loop :bass, sync: :lead do
  use_synth :fm
  c = (get :chord)
  n = one_in(3) ? c[0] - 12 : c[1]-12
  play n, amp: 0.5, release: 1.5, divisor: 2, depth: 3
  sleep 1
end

live_loop :rhythm, sync: :lead do
  sample :elec_cymbal, amp: [0.2, 0.1, 0.2].tick
  off = rrand(-0.025, 0.025)
  sleep [1,2.0/3+off,1.0/3-off].look
end

live_loop :bd, sync: :lead do
  sample :bd_gas
  sleep 1
end

Great approach. If we would want to respect the relationship between chord degrees and scales as used in Jazz music (see Wikipedia article here, a fixed relationship could achieve that. Here is how it can be done using a modification of the :chrd definition:

#chord progressions doodles by Robn Newman Jan 2021
#developed from initial code by theibbster
use_debug false

scales = {
  :i => :ionian,
  :ii => :dorian,
  :iii => :phrygian,
  :iv => :lydian,
  :v => :mixolydian,
  :vi => :aeolian,
  :vii => :locrian
}

define :chrd do |deg, tonic, sca|
  n = 3
  if deg.match?('7')
    n = 4
    deg = deg.slice(0,deg.length-1).to_sym
  end
  sc = scales[deg]  # ignoring the sca parameter here
  return (chord_degree deg, tonic, sc, n)
end

p1 = [:i,:v,:vi,:iv]
p2 = [:i,:iv,:v,:iv]
p3 = [:ii7,:v7,:i7]
p4 = [:i,:i,:i,:i,:iv,:iv,:i,:i,:v,:iv,:i,:i]
p5 = [:i,:vi,:iv,:v]
p6 = [:i,:v,:vi,:iii,:iv,:i,:iv,:v]
pl=(ring p1,p2,p3,p4,p5,p6).shuffle #set up ring of progressions

with_fx :reverb,room: 0.8,mix: 0.7 do #add reverb
  with_fx :level,amp: 1 do |vol| #vary vol as piece progresses
    set :vol,vol #stopre ref to fx_level for control
    
    live_loop :chord_progs do
      progression = pl.tick #get next progresion
      tick_set :tt,look/6 #define tick for tonic changes
      tonic = (ring 62.5,62.5+7,62.5-5,62.5-12,62.5+7-12,62.5-5-12).look(:tt)
      #puts tonic
      #choose scale from specified list
      myScale = (ring :major,:mixolydian,:minor,:minor_pentatonic,:dorian,:aeolian).choose# or tick(:sc)
      #process next progression
      progression.each_with_index  do |deg,i|
        nl=(chrd deg, tonic, myScale) #get notes to play
        use_synth :dsaw #play bass note with dsaw
        play nl[0]-12,\
          sustain: (nl.length)*0.9*0.095,release: 0.005,\
          amp: 0.7,pan: (-1)**i #alternate notes on pan +-1
        use_synth :pulse #use pulse for fast notes
        nl.each do |n| #play notes in sequence
          play n,\
            sustain: 0.095,release: 0.005,\
            amp: 0.5,pan: (-1)**tick(:iloop) #alternate notes on pan +-1
          sleep 0.1
        end
      end#progression
    end#liveloop
  end#level
end#reverb
live_loop :vet do #control level output on 10 sec up/down ramp
  vlev=[0.4,1].tick
  control get(:vol),amp: vlev,amp_slide: 10
  sleep 10
end
3 Likes

I don’t fully understand this, but I don’t think it works like that.

As far as I understand these are scales that match up to the major chords when played with a different tonic.

From the table “Modes of the C major scale”, the V scale is listed as “G7”. I used Sonic Pi to compare the G7 chord, the V chord from C major and C mixolydian, as well as the G mixolydian chord.

 "G 7              [67, 71, 74, 78]"
 "V, c Major       [67, 71, 74, 77]"
 "V, c mixolydian  [67, 70, 74, 77]"
 "G Mixolydian     [67, 69, 71, 72, 74, 76, 77, 79]"

If your musical idea is to stay within a key then for example within key C you would use these chords:
C major7, D minor7, E minor7, F major7, G dom7, A minor7, B dim

And to these chords, within key C, correspond these scales:
C ionian, D dorian, E phrygian, F lydian, G mixolydian, A aeolian, B locrian

Wheneven you use these chords and scales, you will use notes from the c major scale. If you decide to use another scale, let’s say D moxolydian, then you have effectively changed the key to G. This is used in music to do modulations from one key to another: the melody slightly shifts from one scale to another and the chords follow, until you end up with a different key.

Example for a modulation from key F major to key C major:
F major7 - G minor7 - C dom7 - F major7 - D minor7 - C major7 - G dom7 - C major7
The first 3 chords are fixing the key F, chords 4 & 5 are both in key F and C, and chords 6 to 8 are finally fixing key C.

My propsal therefore can be summarized as an attempt to do less key changes but have more notes within a given key.

EDIT: to better hear the differences between the scales, at least 4 notes of each chord should be played. You could do even 5 and it still will sound good.

And here is the example in code. Please have a look at the scales. The first 4 scales belong to key F major, while the last 4 scales belong to key C major. If you want the last 4 scales to belong to key F, you should use:
D aeolian (instead of D dorian)
C mixolydian (instead of C ionian)
G dorian (instead of G mixolydian)
It is these choices that modulate the key from F to C.

use_bpm 70

chords = [chord(:F2, :major7),
          chord(:G2, :minor7),
          chord(:C3, :dom7),
          chord(:F2, :major7),
          chord(:D3, :minor7),
          chord(:C3, :major7),
          chord(:G2, :dom7, inverse: 1),
          chord(:C3, :major7),
          ]


with_synth :piano do
  live_loop :piano do
    play chords.tick, hard: 0.6, sustain: 2, release: 0.5, amp: 1.5
    sleep 2
  end
end


scales = [scale(:F2, :ionian),
          scale(:G2, :dorian),
          scale(:C3, :mixolydian),
          scale(:F2, :ionian),
          scale(:D3, :dorian),
          scale(:C3, :ionian),
          scale(:G2, :mixolydian),
          scale(:C3, :ionian),
          ]

with_synth :pulse do
  live_loop :melody do
    sca = scales.tick
    num_notes = 6
    sca[0, num_notes].each do |n|
      play n, release: 2.0/num_notes, amp: 0.5
      sleep 2.0/num_notes
    end
  end
end

CORRECTION: the scales do not work inside the chord_degree as I expected. Therefore, a separate scale objects is created and used for the arpeggios.

# chord progressions doodles by Robn Newman Jan 2021
# developed from initial code by theibbster
# further developped scales by nechoj

use_debug false
use_bpm 60

scales = {
  :i => :ionian,
  :ii => :dorian,
  :iii => :phrygian,
  :iv => :lydian,
  :v => :mixolydian,
  :vi => :aeolian,
  :vii => :locrian
}

p1 = [:i, :v, :vi, :iv]
p2 = [:i, :iv, :v, :iv]
p3 = [:ii, :v, :i]
p4 = [:i, :vii, :i, :i, :iv, :iv, :i, :i, :v, :iv, :i, :i]
p5 = [:i, :vi, :iv, :v]
p6 = [:i, :v, :vi, :iii, :iv, :i, :iv, :v]
p7 = [:i, :iv, :vi, :vii, :v]
pr = (ring p1, p2, p3, p4, p5, p6, p7).shuffle

nn = 6
st = 0.1

with_fx :reverb, room: 0.8, mix: 0.6 do # add reverb
  with_fx :level, amp: 1 do |vol| # vary vol as piece progresses
    set :vol,vol # stopre ref to fx_level for control
    
    live_loop :foo, auto_cue: false do
      
      base = [:C3, :F4, :C4, :G3].choose
      pl = pr.tick
      pl.each do |deg|
        sc = scales[deg]
        
        n = (chord_degree deg, base, :major, nn)
        
        with_synth :dsaw do
          play n[0] - 12, amp: 0.6, sustain: nn*st, release: 0.1, pan: [-0.7, 0.7].tick(:pan)
        end
        
        sca = scale n[0] + 12, scales[deg], num_octaves: 2
        with_synth :pulse do
          sca[rrand_i(0, 3), nn].each do |m|
            play m, sustain: 0.1, release: 0.05, amp: 0.5, pan: rrand(-1, 1)
            sleep st
          end
        end
      end
    end
  end
end

live_loop :vet do # control level output on 10 sec up/down ramp
  vlev=[0.4,1].tick
  control get(:vol),amp: vlev,amp_slide: 10
  sleep 10
end
1 Like

Stumbled to this jazz theory video which shows how different 7th chords are related to different modes. This way you could randomize different scales for all chords in the progression. Would be dope to do some kind of mapping from different chord types to related scales in Sonic Pi. Only problem is that there are 33 scales and some are not even in Sonic Pi. Scales also listed in here as PDF.

Hi @amiika, that’s exactly what I am currently after. A first experiment on that matter is contained in this post Improvisations over chord progressions. The basis for automatic harmony selection is contained in a recent post here: Harmonic random walk in major.

Next step is to extend this work to a wider range of jazz harmonies and scales. Missing scales in SPI will not pose a too big problem, as scales can easily be constructed from midi notes and the ring mechanism. I cannot foresee when the next version of the random walk including imporvisations using jazz scales will be ready to show, but the complexity of the matter is quite high. A couple of weeks, I guess …

Cool. I made some experiments expanding Sonic Pi’s scales and chords using monkey patching.

Here’s the idea. Create a new file extending the scales and chords via monkey patching:

#scale_patch.rb
class SonicPi::Scale
  def self.patch(scales)
    scales.each { |name, intervals|
      self::SCALE[name] = intervals unless self::SCALE.key? name
    }
  end
end

class SonicPi::Chord
  def self.patch(chords)
    chords.each { |name, intervals|
      unless self::CHORD.key? name.to_sym
        self::CHORD[name.to_sym] = intervals
        self::CHORD_LOOKUP[name.to_sym] = intervals
        self::CHORD_NAMES.append(name)
      end
    }
  end
end

#Missing scales based on: https://www.newjazz.dk/Compendiums/scales_of_harmonies.pdf
scales = lambda {
  ionian1s = [1,2,1,2,2,2,2]
  ionian5s = [2,2,1,3,1,2,1]
  ionian6b = [2,2,1,2,1,3,1]
  {
    # Family 2
    :ionian1s=>ionian1s,
    :dorian7s=>ionian1s.rotate(1),
    :phrygian6s=>ionian1s.rotate(2),
    :lydian5s=>ionian1s.rotate(3),
    :mixolydian4s=>ionian1s.rotate(4),
    :aeolian3s=>ionian1s.rotate(5),
    :locrian2s=>ionian1s.rotate(6),
    # Family 3
    :ionian5s=>ionian5s,
    :dorian4s=>ionian5s.rotate(1),
    :phrygian3s=>ionian5s.rotate(2),
    :lydian2s=>ionian5s.rotate(3),
    :mixolydian1s=>ionian5s.rotate(4),
    :aeolian7s=>ionian5s.rotate(5),
    :locrian6s=>ionian5s.rotate(6),
    # Family 4
    :ionian6b=>ionian6b,
    :dorian5b=>ionian6b.rotate(1),
    :phrygian4b=>ionian6b.rotate(2),
    :lydian3b=>ionian6b.rotate(3),
    :mixolydian2b=>ionian6b.rotate(4),
    :aeolian1b=>ionian6b.rotate(5),
    :locrian7b=>ionian6b.rotate(6),
  }
}.call

chords = {
  # https://en.wikipedia.org/wiki/Minor_major_seventh_chord
  'mM7'=> [0, 3, 7, 11],
  # https://en.wikipedia.org/wiki/Augmented_major_seventh_chord
  'maj7+5'=> [0, 4, 8, 11],
  '6+5'=> [0, 4, 8, 9],
  # Missing altered chords: https://en.wikipedia.org/wiki/Altered_chord
  '7-5-3'=>[0, 3, 6, 10],
  '7+5+9'=>[0, 4, 8, 10, 14],
  '7-5-9'=>[0, 4, 6, 10, 13],
  '7-5+9'=>[0, 4, 6, 10, 14]

}

SonicPi::Scale.patch(scales)
SonicPi::Chord.patch(chords)

EDIT: Fixed a bug, thanks to @Nechoj and added some missing altered 7th chords.

Then load it to the Sonic Pi and create mapping between chord types and those new scales:

load "~/patch.rb" # Load extra scales and chords from separate file

use_random_seed 31
use_bpm 90

harmonic_scales = {
  :M7=>[:ionian, :lydian, :lydian2s, :ionian6b, :augmented],
  :minor7=>[:dorian, :phrygian, :aeolian, :phrygian6s, :dorian4s, :phrygian4b],
  '7'=>[:mixolydian, :mixolydian4s, :aeolian3s, :phrygian3s, :mixolydian2b, :diminished],
  'm7-5'=>[:locrian, :locrian2s, :ionian1s, :locrian6s, :dorian5b],
  'mM7'=>[:dorian7s, :aeolian7s, :lydian3b],
  :dim7=>[:mixolydian1s, :locrian7b, :aeolian1b, :diminished],
  'maj7+5'=>[:lydian5s, :ionian5s, :aeolian1b],
  '7-5'=>[:whole_tone],
  '7+5'=>[:whole_tone],
  '6+5'=>[:augmented2],
  # Other altered chords
  '7-5-3'=>[:ionian1],
  'm7+5'=>[:ionian1],
  '9'=>[:ionian1]
}

prog = [{tonic: :D, type: 'm7-5', invert: -1}, {tonic: :G, type: '7', invert: -1},{tonic: :C, type: 'mM7', invert: 1}]

live_loop :chords do
  with_fx :flanger, feedback: 0.5 do
    prog.each do |c|
      synth :hollow, note: chord(c[:tonic], c[:type], invert: c[:invert] ? c[:invert] : 0), sustain: 3, amp: 2
      sleep 4
    end
  end
end

live_loop :impro do
  with_synth :tri do
    with_synth_defaults sustain: 0.20, env_curve: 2, cutoff: 40, decay: 0.05, decay_level: 0.5, sustain_level: 0.5 do
      prog.each do |c|
        harmonic_scale = harmonic_scales[c[:type]].choose
        notes = scale(c[:tonic], harmonic_scale).shuffle
        4.times do
          s = [0.25,0.5,1.0].choose
          (1/s).times do
            if s>0.25 and rand>0.85
              2.times do
                play notes.tick
                sleep s/2
              end
            else
              play notes.tick
              sleep s
            end
          end
        end
      end
    end
  end
end

live_loop :bass do
  with_fx :reverb, damp: 0.9, room: 0.8  do
    with_synth :fm do
      use_synth_defaults depth: -1, divisor: 1, release: [0.25,0.5].choose, amp: 0.5
      use_octave -2
      prog.each_with_index do |c,i|
        harmonic_scale = harmonic_scales[c[:type]].choose
        notes = scale(c[:tonic], harmonic_scale).shuffle
        play chord(c[:tonic], c[:type], invert: c[:invert] ? c[:invert] : 0)[0]
        sleep 0.5
        play chord(c[:tonic], c[:type], invert: c[:invert] ? c[:invert] : 0)[2]
        sleep 0.5
        3.times do
          if rand>0.7
            2.times do
              play notes.tick
              sleep 0.25
            end
          else
            play notes.tick
            sleep 0.5
          end
        end
        peek = prog.ring[i+1]
        play chord(peek[:tonic], peek[:type], invert: peek[:invert] ? peek[:invert] : 0)[0] - [-1,1,].choose
        sleep 0.5
      end
    end
  end
end

live_loop :swing do
  with_fx :reverb, amp: 2 do
    sample :drum_cymbal_closed, amp: 0.2, beat_stretch: [0.1,0.2,0.3].choose
    sample :drum_cymbal_soft, amp: 0.1
    sleep 1
    sample :drum_cymbal_soft, amp: 0.1
    sleep 0.8
    sample :drum_cymbal_soft, amp: 0.1
    sleep 0.2
  end
end

EDIT EDIT: Added variations to walking bass

Sounds quite nice, even for random serialist approach. Creating arpeggios and filling in the gaps should create even nicer outcome.

3 Likes

I will ask some feedbacks to my little cousin 8 years old and I will tell you his point of view.

It seems that some sonic pi users are great children for ever :blush:

By the way a little joke :
What is the difference between a jazz band and a rock band ?
A jazz band it’s 2000 chords by song and 3 people into the public. You guess for the rock band ?

Cheers and keep sharing friens your amazing scripts !

Cool! Thanks for sharing. Good idea to do the monkey patches, it always helps if nothing else helps :sunglasses: :monkey_face:
Nice voices in the piece, too!

Well, somehow I have heard this joke before … Fact is, however, that every serious composer in our days should have a solid background in jazz harmonies and scales. One of my favorite YouTube’er explaining the harmonic structure of contemporary pieces is Adam Neely. Watch his video on Lady Gaga’s presentation of the US anthem at Joe Biden’s inauguration. I guess, there have been more than 3 people listening to it and this piece is loaded with jazz hamonies and was played by the military corps band. (Btw, Lady Gaga has a solid jazz background as well, hear e.g. this piece with Tony Bennett who - I am said to mention - died on 1st of February this year)

There was a bug in this piece which made it more random than serial. Made few tweaks. Subtle differences.

To be honest I don’t care if a song is listened by lot of people or not. It was a joke.
Not sure every punk or rock band had some jazz background. Jésus and Mary chain : 2 chords, (power chord otherwise it will have sound too rich ) but a fingerprint, a sound that you know it’s them.

Some jazz tunes seem to me just a technical show with 2000 chords per song. And happy few people can really appreciate but they are right to play or listen what they like.

Every kind of music is worth to exist to represent the variety of human beings.

I get back to Schubert right now :relaxed: