Arduino interface to sonic pi

can someone assist me to understand this as as I understand this r is the cutoff value that should be used in the code below, but how or where is that value being used?

#r is a reference to the fx :nlpf
  with_fx :nlpf,cutoff: 50,mix: 0.7 do |r|
    #store r in the time state as :r
    set :r,r
    live_loop :getmidi do
      use_real_time
      n,v = sync "/midi*/note_on"
      play n,release: 0.2,amp: v/127.0
    end
``` but where is this value being used?

If I understand your thinking correctly, (might be wrong, so let me know if otherwise) youā€™re actually thinking about it back to front.

  with_fx :nlpf,cutoff: 50,mix: 0.7 do |r|
    #store r in the time state as :r
    set :r,r

This bit comes before live_loop :control. The idea is that we first use set to store some value in the global time-state memory store, and later on use get to retrieve this value for use. Ie, the above few lines create a new fx, store a reference to it called r to use within the fxā€™s own block, but we in turn then set this reference to the fx, r, in the global time-state system, so that we can refer to it somewhere outside the current loop without worrying about race conditions (for example).
Then, later down, when we want to use this fx reference, we use get to retrieve it.

 control get(:r), cutoff: 50+v*60

Does that make things any clearer? It may also help to read Chapters 10 and 10.1 of the tutorial about the time state system, set and get.

thanks appreciate the explanation makes a bit more sense now

Hi - if I want to add some rhythm to the above code ```
#demo on controlling level and cutoff for midi input

seems to have cutoff my text - ā€¦ rhythm or beats to play during when notes are played and after notes are played, how would this be done?

can anyone assist please?

Can you please elaborate on what you mean by this?:

  • Are you simply wanting an additional percussion loop to play at the same time, and then for it to continue doing so after the melody has finished?
  • Are you wanting this percussion loop to be receiving input from MIDI to trigger the drum samples, or just playing samples directly?
  • Are you wanting the percussion to be a single sample of an entire drum sequence or many individual drum samples making up a sequence?
  • etc

Has there been anything in the tutorial that may shed light on what youā€™re after? What is your specific challenge?

As an aside, it is often helpful to be as descriptive as you can about your end goal. Then, instead of trying to solve them all at once, it may help to think about your challenges by breaking them down into the smallest possible questions/problems/tasks, working through them one at a time, and building on each individual result until you eventually reach your desired goal. For example: (and this may be a significant generalisation, but you get the idea) - If I want to have a percussion loop running at the same time as a melody:

  • do I know how to play a single percussion loop sample in a solitary live_loop?
  • do I know how to loop through a list of samples in a solitary live_loop?
  • do I know how to play two (or more) separate musical items (such as a melody and some percussion) at the same time?
  • do I know how to synchronise two (or more) separately looping items so that they keep in time?

Answering each of these in turn gives a good base to work with when answering the next. Much easier than trying to immediately trying to solve the end goal all at once.
Martin was spot on in his reply above about spending time to analyse/research/play with code in smaller detail often being quite productive. Granted, you have mentioned that you ā€˜usually do that but the code has some concepts you donā€™t quite followā€™ - so ask specific questions about them! :grin: What didnā€™t you understand? :slight_smile:

Hi, appreciate your methodology and approach,
I would like these options

  1. to play at the same time as the melody and after the melody finishes.
  2. the drum sequence to end after a set time span if no more midi inputs received. But if there are midi inputs then for the drum sequence to continue.

thanks for assistance

Ok, so start from the beginning. Thinking about my example of breaking things down - what do you know, that you could build on?

Iā€™m just looking for an example on how to do this .
I have a midi control already as pr code above and I have a drum sequence but not able to do as requested .
if I knew I wouldnā€™t be posting this .

Sure, no problem, understandable :slight_smile: So you have Robinā€™s code, and a drum sequence, thatā€™s good. What form is the drum sequence? Sonic Pi code?
Knowing what weā€™re working with would make it a bit easier.

yep sonic pi codeā€¦

Great, letā€™s have a look.

FYI itā€™s currently late evening here where I am so Iā€™ll be calling it a night for now. Share what you have when you can, and Iā€™ll be happy to take this up again tomorrow. Others are of course free to jump in in the meantime :slight_smile:

Sure no worries.
beat section is below:

define :beats_section do
#in_thread(name: :beats) do
live_loop :bass_drums do
vol = rrand(0.5,1)
#amp = 0.5
amp = vol -0.5
puts ":bass_drums and vol #{vol} "
if (spread 7, 8).reverse.tick
sample :bd_haus, rate: 1, attack: 0.01, release: 0.25, amp: amp
sleep 0.5
sync
else
sample :drum_bass_hard, rate: rrand_i(1, 3), attack: 0.025, sustain: 0.5, release: 0.1, amp: amp
sleep 0.09
sample :bass_hit_c, rate: rrand_i(5, 10),attack: 0.025, sustain: 0.05, release: 1, amp: amp
sleep 0.41
end
end#rate: rrand_i(5, 10),

define :beats_section2 do
#use_bpm get(:bpm) #gets 60
with_fx :reverb, room: 0.8, mix: 0.5 do
#bpm
live_loop :drums do
# amp = 0.8
vol = rrand(0.2,1)
amp = vol -0.2
sample :drum_cymbal_closed, rate: 0.9, attack: 0.01, sustain: 0.01, release: 0.05, amp: amp
if (spread rrand_i(1, 6), 8).tick
sample :drum_cowbell, rate: [0.4, 0.8, 0.9, 1.8, 1.9].choose, attack: 0, sustain: 0, release: 0.1, amp: amp
sleep 0.125
else
sample :bd_tek, rate: [3, 5, 7].choose, attack: 0, sustain: 0, release: 0.25, amp: amp
sleep 0.25
end
puts ":drums amp #{amp} and vol #{vol} "
end

  live_loop :drums2 do
    use_synth :pluck
    vol = rrand(0.3,1)
    amp = vol -0.3
    puts ":drums2 amp  #{amp}  and vol #{vol} "
    if (spread 3, 8).tick
      sample :drum_cymbal_closed, rate: [3, 4, 5].choose, attack: 0, sustain: 0, release: 0.05, amp: amp
      sleep 0.25
    else
      sample :drum_cymbal_closed, rate: [1, 2].choose, attack: 0, sustain: 0, release: 0.08, amp: amp
      sleep 0.125
    end
  end
  
  live_loop :melody do
    use_synth :pluck
    vol = rrand(0.1,1)
    amp = vol -0.1
    amp = 1
    puts ":melody amp  #{amp}  and vol #{vol} "
    with_fx :echo, decay: 6 do
      with_fx :lpf, cutoff: (line 40, 130, steps: 20).tick do
        ##| play (scale :c2, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 0.5
        play (scale :c3, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 0
        play (scale :c4, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 0
        ##| play (scale :c6, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 1.5
        sync :processnote
      end
    end
    sleep 0.125
  end
  
  live_loop :deep_saws do
    use_synth :saw
    vol = rrand(0.2,1)
    amp = vol -0.2
    release = 8
    attack = rrand_i(1, release / 2)
    puts ":deep_saws amp  #{amp}  and vol #{vol} "
    notex = [:c1, :g1, :d1, :f1, :g1].tick
    with_fx :lpf, cutoff: 50 do
      play notex, attack: attack, sustain: 0, release: release, amp: amp
      play notex + 12, attack: attack, sustain: 0, release: release, amp: amp
      play notex + 12 * 2, attack: attack, sustain: 0, release: release, amp: amp
      play notex + 12 * 3, attack: attack, sustain: 0, release: release, amp: amp
      ##| play note + 12 * 4, attack: attack, sustain: 0, release: release, amp: amp
    end
    sleep release
  end
  
end

end
end

Hi Wro,

I tidied up your code a little and fixed a small error in
the beats_section define (youā€™d left out an ā€˜endā€™ which
was throwing the rest of your code off.

There was also a ā€˜sync :processnoteā€™ in fhe melody
loop which was keeping it stopped for ever.

Hope this helps.

Eliā€¦

define :beats_section do
  
  live_loop :bass_drums do
    vol = rrand(0.5,1)
    amp = vol -0.5
    
    if (spread 7, 8).reverse.tick
      sample :bd_haus, rate: 1, attack: 0.01, release: 0.25, amp: amp
      sleep 0.5
      sync
    else
      sample :drum_bass_hard, rate: rrand_i(1, 3), attack: 0.025, sustain: 0.5, release: 0.1, amp: amp
      sleep 0.09
      sample :bass_hit_c, rate: rrand_i(5, 10),attack: 0.025, sustain: 0.05, release: 1, amp: amp
      sleep 0.41
    end
  end
  
end

define :beats_section2 do
  
  with_fx :reverb, room: 0.8, mix: 0.5 do
    
    live_loop :drums do
      vol = rrand(0.2,1)
      amp = vol -0.2
      sample :drum_cymbal_closed, rate: 0.9, attack: 0.01, sustain: 0.01, release: 0.05, amp: amp
      if (spread rrand_i(1, 6), 8).tick
        sample :drum_cowbell, rate: [0.4, 0.8, 0.9, 1.8, 1.9].choose, attack: 0, sustain: 0, release: 0.1, amp: amp
        sleep 0.125
      else
        sample :bd_tek, rate: [3, 5, 7].choose, attack: 0, sustain: 0, release: 0.25, amp: amp
        sleep 0.25
      end
    end
    
  end
  
end

live_loop :drums2 do
  use_synth :pluck
  vol = rrand(0.3,1)
  amp = vol -0.3
  if (spread 3, 8).tick
    sample :drum_cymbal_closed, rate: [3, 4, 5].choose, attack: 0, sustain: 0, release: 0.05, amp: amp
    sleep 0.25
  else
    sample :drum_cymbal_closed, rate: [1, 2].choose, attack: 0, sustain: 0, release: 0.08, amp: amp
    sleep 0.125
  end
end

live_loop :melody do
  use_synth :pluck
  vol = rrand(0.1,1)
  amp = vol -0.1
  amp = 1
  with_fx :echo, decay: 6 do
    with_fx :lpf, cutoff: (line 40, 130, steps: 20).tick do
      ##| play (scale :c2, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 0.5
      play (scale :c3, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 0
      play (scale :c4, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 0
      ##| play (scale :c6, :mixolydian).choose, attack: 0.0, sustain: 0.0, release: 0.05, amp: amp + 1.5
    end
  end
  sleep 0.125
end

live_loop :deep_saws do
  use_synth :saw
  vol = rrand(0.2,1)
  amp = vol -0.2
  release = 8
  attack = rrand_i(1, release / 2)
  notex = [:c1, :g1, :d1, :f1, :g1].tick
  with_fx :lpf, cutoff: 50 do
    play notex, attack: attack, sustain: 0, release: release, amp: amp
    play notex + 12, attack: attack, sustain: 0, release: release, amp: amp
    play notex + 12 * 2, attack: attack, sustain: 0, release: release, amp: amp
    play notex + 12 * 3, attack: attack, sustain: 0, release: release, amp: amp
    ##| play note + 12 * 4, attack: attack, sustain: 0, release: release, amp: amp
  end
  sleep release
end

Thanks!
Ok, bear with me - Iā€™ll definitely help you with an example for your particular goal, though also show examples of the thoughts, questions and answers that could perhaps lead towards such a goal.

So, the end goal:

is to have percussion that runs independently from a melody, and that starts (or stops, after a time) based on a MIDI input trigger (or lack thereof).

Your above code snippets show that you have an independent percussion live_loop, :drums2. Thatā€™s half of 1. covered already - it can play at the same time as the melody.
Looking at 2. - we already know from the above that the drum sequence will play quite happily by itself. So the next goal might be starting with something simpler like: how do we make the percussion loop only make noise when we want it to?

There are two ways that we can do that - we can either have the percussion loop always playing no matter what, and just mute or un-mute it, or we can make it actually pause until weā€™re ready. In this case, it doesnā€™t strictly matter, so letā€™s go with actually pausing it. So the next question is: what mechanisms exist in Sonic Pi to make a piece of code pause until something happens? The same one that we use to wait for midi input - the sync command :slight_smile: (part of working with the Time State system, as described in chapter 10 of the tutorial as mentioned previously).

Great! So, how could it look when using the sync command to wait until something has happened to trigger the drum sequence? We could place the sync directly in the drum sequence live_loop itself (along with use_real_time to cancel the built in scheduling delay that Sonic Pi usually uses):

live_loop :drums2 do
  use_real_time
  sync [some midi event]
  use_synth :pluck
  vol = rrand(0.3,1)
  amp = vol -0.3
  puts ":drums2 amp  #{amp}  and vol #{vol} "
  if (spread 3, 8).tick
    sample :drum_cymbal_closed, rate: [3, 4, 5].choose, attack: 0, sustain: 0, release: 0.05, amp: amp
    sleep 0.25
  else
    sample :drum_cymbal_closed, rate: [1, 2].choose, attack: 0, sustain: 0, release: 0.08, amp: amp
    sleep 0.125
  end
end

If we tried that, what might happen?
We would only hear a single drum beat every time we pressed the button/rotated the dial or otherwise sent a MIDI command, since the live_loop was set up to play one drum beat at a time before looping around again - and every time it looped it would hit the sync and wait for another MIDI input. I assume this is not what we want.

So the next question might be: is it enough to make the live_loop play a whole bunch of drum beats at a time before looping around again? Possibly not, because it would play a sequence of drums, and still pause when it hits the sync until a new MIDI input was received. In order to answer that question, we need to know more - what is the nature of the MIDI input that will be used to trigger the playing of the drum sequence? Compared to the duration of the drum sequence, will the stream of events be received more or less frequently? How long after a MIDI input do we want to wait before pausing the drum sequence? (Just until the current drum sequence has ended? or longer?)

Eli thank youā€¦ I am in the process of a relocation ā€¦ I will look at your points as soon as I get a gap once things settle here.

@robin.newman - Iā€™m interested in your thoughts about how this would be solved too actually :sweat_smile: - have time to chime in at some point?