Mute and unmute samples?

Been coding for less than a day so please be patient with me.
I’m trying to build a looper. I want to be able to mute and unmute loops.
How would I go about muting and unmuting samples with a midi controller?
I’m guessing it’s some sort of “get and set” thing but I barely can understand what that is.
If I press a note, I want it to mute a sample and stay muted. The next time I trigger the same note, I want it to unmute the sample and stay unmuted. I want the sample to continue to play and loop so it stays in time. I just want it silenced. Is sonic pi even the right tool for this creation? I’m completely lost and can’t find any resources on the topic.
Please help, thank you!

Here’s a very rough and ready way to do what you ask. It can probably be tidied up and refined, but shows it is possible

set :flag,1
set :flag2,1
use_bpm 120
live_loop :s1 do
  if get(:flag)==1
    sample  :loop_amen,beat_stretch: 4
  end
  sleep 4
end

live_loop :s2 do
  if get(:flag2)==1
    sample :drum_splash_hard
  end
  sleep 2
end


live_loop :midIn do
  use_real_time
  n,v=sync "/midi*/note_on"
  puts n,v
  if n==60
    set :flag,1
  elsif n==62
    set :flag,0
  elsif n==64
    set :flag2,1
  elsif n==65
    set :flag2,0
  end
end

use midi input for C4,D4 and E4.F4 to control the two loops. The loops keep running all the time. We just mote the samples from playing. When you reenable a loop it starts sounding on the next timed pass, not immediately.

EDIT you could use midi_cc signals instead

1 Like

This is insanely useful. Thanks, Robin!

Thank you for your response! My new goal is to understand what this code means and how it works.
Any advice or tips on how the flags work or what they mean would be greatly appreciated!
Thanks so much for the help!

Hi @robin.newman,

I messed around with your example, attempting to program a toggle instead of two keys; I have kind of this code working with OSC and Monome, so I am quite sure that something like that should work also with Midi:

set :flag, true
set :flag_state, true
use_bpm 120

live_loop :s1 do
  if get(:flag)
    sample  :loop_amen,beat_stretch: 4
  end
  sleep 4
end

live_loop :midIn do
  use_real_time  
  n,v=sync "/midi*/note_off"
  puts n,v
    if n == 60 and v == 0
      last_state = get(:flag_state)
      if last_state
      set :flag, true
      state = false
    else
      set :flag, false
      state = true
    end
    set :flag_state, state
  end
    puts "state: #{state}, flag_state: #{get(:flag_state)}"
end

Alas, it doesn’t because each click SP receives two events:

{run: 2, time: 26.0796, thread: :live_loop_midIn}
 ├─ 60 0
 └─ "state: false, flag_state: false"
 
{run: 2, time: 26.0803, thread: :live_loop_midIn}
 ├─ 60 0
 └─ "state: true, flag_state: true"

… where as Midisnoop recognises this IMHO correctly:

Am I thinking incorrectly? Is my program wrong. Is my SP compilation some flawed? Any other idea?

The program below works as a toggle. The problme is that many keyboards use note_on and note_off, setting the velocity (volume) to note_off. Sonic Pi interprets this literally not as a note_off signal. Adding a check for v > 0 lets you select note_on that is starting a new note.

set :flag,1
set :flag2,1
set :flagState,true
set :flagState2,trues
use_bpm 120
live_loop :s1 do
  if get(:flag)==1
    sample  :loop_amen,beat_stretch: 4
  end
  sleep 4
end

live_loop :s2 do
  if get(:flag2)==1
    sample :drum_splash_hard
  end
  sleep 2
end

set :flagState,false
live_loop :midIn do
  use_real_time
  n,v=sync "/midi*/note_on"
  puts n,v
  if n==60 and v>0
    if get(:flagState)
      
      set :flag,0
      set :flagState,false
    else
      set :flag,1
      set :flagState,true
    end
    
  elsif n==64 and v>0
    if get(:flagState2)
      set :flag2,0
      set :flagState2,false
    else
      set :flag2,1
      set :flagState2,true
    end   
  end
end
2 Likes

The flags are just variable names they could be called foo or bar or anything else.
set :flag,1 stores a value 1 in the timeline referenced by :flag. The latest value referenced by :flag can later be retrieved using get(:flag)
The if statement cheks the current value referenced by :flag and takes appropriate action.

In the :midIn live loop the values of the note and its velocity (how hard the key was hit) are retrieved and compared to the values 60, 62, 64, and 65. If there is a match then the following action is taken to adjust the relevant :flag stored value.

The second more complicated program uses similar ideas but uses a toggle which can either be set to true or false which flips between those two values every time a specified note value is detected. IT then has logic associated which turns :flag from 0 to 1 or 1 to 0 as appropriate.
I explain why you also have to use the v setting as well in that program to differentiate between note on and note off, otherwise as Martin found you get a double input when you press and release a keyboard key.

1 Like

I see. Thanks a lot Robin!

I have a piece of code that does this with an APC, including lighting up the pads to show active or muted.

3 Likes

Thank you so much! I don’t understand a lot of this but I can tell it will be useful once I do.
I will keep studying, I’m struggling to figure out what to study though. Are there any resources for learning these things? How’d you guys learn this stuff and how do you recommend I learn it?

You learn by experimenting and trying things out, reading what others are doing and looking at their code, searching the internet Basically by gaining experience. I know a bit about certain areas but am a newbie in others. I just kept doing the above and slowly improving. There can be frustrating moments but also some great highs and moments of elation when things come together. Keep at it. The more you try the more you progress.

1 Like