Please help me boil this down

Having a little trouble because there 2 notes played with no pause,
and ‘sleep 0’ is not an option. The ‘release: 4, sustain: 4’ every 3 notes
doesn’t help either…

(I’ve never claimed to be a coder).

Eli…

with_fx :reverb, room: 0.8 do
  with_fx :lpf, cutoff: (range 75,65,5).mirror.tick do
    with_synth :piano do
      live_loop :piano0 do
        use_bpm 120
        sync :bar
        with_fx :level, amp: 0.5 do
          play :f5
          play :d4, release: 4, sustain: 4
          sleep 2
          play :a4
          sleep 2
          play :d5
          play :c4, release: 4, sustain: 4
          sleep 1
          play :c5
          sleep 3
          play :d5
          play :b3, release: 4, sustain: 4
          sleep 1
          play :a5
          sleep 3
          play :a4
          play :as3, release: 4, sustain: 4
          sleep 1
          play :g5
          sleep 3
        end
      end
    end
  end
end

Is your loop playing alone, with no sync, do what you want ?

Well I tried this, but perhaps because of the Sleep 0.001, some of the
notes dont sound quite the same…

use_bpm 120

notes = (ring :a4, :d4, :c4, :a5)
time = (ring 2.0,2.0,1.0,2.0,)

notes1=(ring :f5, :d4, :a4, :d5, :c4, :c5, :d5, :b3, :a5, :a4, :as3, :g5)
time1 =(ring 0.001,2,2,0.001,1,3,0.001,1,3,0.001,1,3)
mod =(ring 0,1,0,0,1,0,0,1,0,0,1,0,0)


with_fx :reverb, room: 0.8 do
  with_fx :lpf, cutoff: (range 75,65,5).mirror.tick do
    
    with_fx :level, amp: 0.5 do
      
      live_loop :piano2 do
        use_synth :piano
        if mod.tick == 1 then
          play notes1.look, release: 4, sustain: 4
        else
          play notes1.look, release: 1, sustain: 1
        end
        sleep time1.look
      end
      
    end
    
  end
end

If I can solve the difference in the sound of the notes, I can
sync a counter-point off it, which sounds nice, but the different
notes make a dissonance which is noticable…

live_loop :piano1 do
  sync :piano2
  if rand() >0.95
    notes = (ring :a4, :d4, :c4, :a5)
    time = (ring 2.0,2.0,1.0,2.0,)
  else
    notes = notes.shuffle
    time = time.shuffle
  end
  use_synth :piano
  6.times do
    play notes.tick, amp: 0.125, sustain: (time.look)-0.5
    sleep time.look
  end
end

Eli…

1 Like

When I ran your code on my 3.1 install I was seeing warnings in the log about the loop being behind whenever those 0.001 sleeps went through. It seems reasonable - at 120 BPM, that’s only 0.5 milliseconds for the scheduler to act.

It seems like your intent is to play some notes simultaneously so that’s what I set out to solve. I took advantage of play_chord being able to accept a list of one note, so we can convert your melody into a list of lists, with some notes paired together.

use_bpm 120

notes = (ring :a4, :d4, :c4, :a5)
time = (ring 2.0,2.0,1.0,2.0,)

notes1=(ring [:f5, :d4], [:a4], [:d5, :c4], [:c5], [:d5, :b3], [:a5], [:a4, :as3], [:g5])
time1 =(ring          2,     2,          1,     3,          1,     3,           1,     3)
mod =(ring 0,1,0,0,1,0,0,1,0,0,1,0,0)


with_fx :reverb, room: 0.8 do
  with_fx :lpf, cutoff: (range 75,65,5).mirror.tick do
    
    with_fx :level, amp: 0.5 do
      
      live_loop :piano2 do
        use_synth :piano
        if mod.tick == 1 then
          play_chord notes1.look, release: 4, sustain: 4
        else
          play_chord notes1.look, release: 1, sustain: 1
        end
        sleep time1.look
      end
      
    end
    
  end
end
1 Like

Quite a sad pattern, but also sweet. Love it.

Thank you very much matey. I dont use play_chord much… still so much to learn…

Eli…

Yes, it is rather… perfect for a piece of slow anime… or as the piano repeat in a lo-fi song perhaps.

I also have a sort-of music box I’d love to find a use for… it’s no ’ elfen lied’ but it works.

Mind, it would be a lot shorter if I took out my framework, but then I wouldn’t have the control I
want… always a compromise… just play it, see what you think. Worry less about my Franken-code. :slight_smile:

Eli…

# Title: Music Box
# Artist: Paul 'Just Eli...' Whitfield
# Date: 17/06/2019
#
# Sonic Pi v3.1
# Eli's Framework v1.0

use_bpm 60

tracker = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
volume =  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

strings = (ring :c,:c3,:c,:c2,:c1,:c )
strings1 = (ring :r, :r, :c,:c3,:c,:c2,:c1,:c )

chords = [(chord :C, :minor7), (chord :Ab, :major7), (chord :Eb, :major7), (chord :Bb, "7")].ring
c = chords[0]

# Start a loop.
define :start_loop do |i|
  tracker[i] = 1
end

# Stop a loop.
define :stop_loop do |i|
  tracker[i] = 0
end

# Reduce loop's volume
define :decrease_volume do |i, n |
  if volume[i] - n > 0 then
    volume[i] = volume[i] - n
  end
end

# Increase loop's volume
define :increase_volume do |i, n |
  if volume[i] + n < 10 then
    volume[i] = volume[i] + n
  end
end

# Violin
with_fx :flanger do
  with_fx :echo do
    
    live_loop :background_strings do
      sync :piano_tinkle
      if tracker[0] > 0 then
        
        
        use_synth_defaults amp: volume[0]*0.25, attack: 0.5, sustain: 1, release: 1
        use_synth :blade
        use_transpose 12
        play strings.tick
        
        sleep 0.75
      else
        sleep 0.1
      end
      
      # Violin 1
      live_loop :background_strings1 do
        sync :piano_tinkle
        if tracker[1] > 0 then
          use_synth_defaults amp: volume[1]*0.25, attack: 0.5, sustain: 1, release: 1
          use_synth :blade
          use_transpose 36
          play strings1.tick
          sleep 0.75
        else
          sleep 0.1
        end
      end
    end
    
  end
end

# Music Box

with_fx :flanger do
  with_fx :reverb do
    
    live_loop :piano_tinkle do
      r = [0.5, 0.6, 0.7, 0.6].choose
      if tracker[2] > 0 then
        use_synth :sine
        
        use_octave +2
        3.times do
          play c[0], release: 0.1, amp: volume[2]*0.5, decay: 0.0125+r, sustain: r/2# play the first note of the chord
          sleep 1
        end
        play c[2], release: 0.1, amp: volume[2]*0.5, decay: 0.0125+r, sustain: r/2 # play the third note of the chord
        sleep 0.5
        play c[1], release: 0.1, amp: volume[2]*0.5, decay: 0.0125+r, sustain: r/2 # # play the second note of the chord
        sleep 0.5
        c = chords.tick
      end
      sleep 0.1
    end
    
    # Music Box 1
    live_loop :piano_highlight do
      if tracker[3] > 0 then
        sync :piano_tinkle
        use_synth :sine
        use_octave +2
        r = [0.25, 0.25, 0.5, 1].choose
        with_transpose 0 do
          #   play c.choose, attack: 0, decay: 1, sustain: 2, amp: volume[3]
          play c.choose, release: 0.1, amp: volume[3]*0.5, decay: 0.0125+r, sustain: r/2
          sleep 2
        end
        
      else
        sleep 0.1
      end
    end
    
  end
end

# Drums
live_loop :light_drums do
  sync :piano_tinkle
  if tracker[4] > 0 then
    1. times do
      with_fx :reverb, room:1, damp: 0.7 do
        sample :drum_tom_lo_hard, rate: 1, pitch_dis: 0.001, amp: volume[4]*0.25
        sleep 0.75
        sample :drum_tom_lo_hard, rate: 0.5, pitch_dis: 0.001, amp: volume[4]*0.25
        sleep 2
      end
      sleep 0.75
    end
  else
    sleep 0.1
  end
end

#__________________________________________________________________________________________________
#Code ends here...
#__________________________________________________________________________________________________

background_strings=0
background_strings1=1
piano_tinkle=2
piano_highlight=3
light_drums=4

start_loop background_strings
increase_volume background_strings,1
sleep 8
start_loop background_strings1
increase_volume background_strings1,1
sleep 8
start_loop piano_highlight
increase_volume piano_highlight,0.5
sleep 4
increase_volume piano_highlight ,0.5
sleep 4
start_loop light_drums
increase_volume light_drums,1
sleep 4
increase_volume light_drums,1
sleep 4
increase_volume light_drums,1
sleep 4
increase_volume light_drums,1
sleep 4
start_loop 2
increase_volume piano_tinkle,0.5
decrease_volume piano_highlight,0.5
sleep 4
increase_volume piano_tinkle,0.5
sleep 8
decrease_volume light_drums,1
sleep 4
decrease_volume light_drums,1
sleep 4
decrease_volume light_drums,1
decrease_volume piano_highlight,0.5
sleep 4
decrease_volume light_drums,1
decrease_volume piano_highlight,0.5
sleep 32
decrease_volume light_drums,1
decrease_volume piano_highlight,0.5
sleep 4
decrease_volume light_drums,1
decrease_volume piano_highlight,0.5
decrease_volume piano_tinkle,0.5
sleep 4
stop_loop 4
decrease_volume piano_highlight,0.5
decrease_volume piano_tinkle,0.5
sleep 4
decrease_volume piano_highlight,0.5
sleep 4
stop_loop piano_highlight
decrease_volume background_strings1,1
sleep 12
stop_loop piano_tinkle
decrease_volume background_strings1,1
sleep 8
stop_loop background_strings1
sleep 4
stop_loop background_strings
1 Like

Eli, it a nice piece, it make me think about a end-scene, or a OST for a final boss fight for a RPG game (like final fantasy VII). What I find really impressive (and I want to understand it) it’s the control code you did for this piece. I’m looking for understend the |i| after the define function, and the tracker list at the beginning. Maybe it something like defining a pattern sequence, it would be really usefull.

Hi Mattia,

It’s fairly straight forward really… (though Sam has
warned me that passing variables this way may not be
consistant, and that using set/get would be better)

tracker is an array used to decide if a live_loop
is outputting a sound or is simply waiting…

tracker = [ 0,1,0,0,0,0,0,0,0,0,0]

A live_loop checks the state of tracker before it plays
anything…

live_loop :beeper do
  if tracker[1] > 0 then
     play 62
     sleep 0.5
  else
     sleep 0.5
  end

So, if we want loop :beeper to play a sound, we set
the value of tracker[1] = 1, using the define :start_loop.

# Start a loop.
define :start_loop do |i|
  tracker[i] = 1
end

|i| is the value we have passed to :start_loop, which it uses
to set tracker[i] equal to one.

At the end of the code you will see a… ‘script’ for the song.

start_loop 1
sleep 8
start_loop 8
sleep 4
stop_loop 1

By giving the name of the loop a number equal to it’s tracker[number] we
can start and stop loops by name, which makes the 'script a little clearer…

beeper = 0

start_loop beeper
sleep 8
stop_loop beeper

And thats pretty much it…

volume = [ 0,1,0,0,0,0,0,0,0,0,0] does the same for a loops volume, using the
define:

# Increase loop's volume
define :increase_volume do |i, n |
  if volume[i] + n < 10 then
    volume[i] = volume[i] + n
  end
end

So…

live_loop :beeper do
  if tracker[1] > 0 then
     play 62, amp: volume[1]
     sleep 0.5
  else
     sleep 0.5
  end

and the script might become:

beeper = 0

start_loop beeper
# Increase the volume of loop beeper by 0.5
increase_volume beeper, 0.5
sleep 8
stop_loop beeper

You can use this for lots of other things… controlling
the amount of echo in a loop,or whatever you want to tailor
it to.

Hope that helps clarify things a little.

Eli…

2 Likes

@Eli thank you so much, now it’s super clear. I had try something, just a while a go, and I published the code in “creations & Ideas”. With that composition (Multidimensional Repetitions) I had understand the use of |i|, for give a integer to a definition and use, for example, as the n of n.times do … end. In the next days I will try to code something with this array method, that seems really good to keep a clear form and a deep control.
So thank you again for your precious help! :relaxed:

1 Like