# "Monophonic" sample loop?

**URL:** <https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693>\
**Category:** Support, Help & Resources\
**Created:** [June 9, 2021, 8:44pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693 "2021-06-09T20:44:44Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 9, 2021, 8:44pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/1 "2021-06-09T20:44:44Z")

</div>

Hi,

Do you know if it’s possible to automatically stop the sample from playing over itself when re-triggering the loop that contains it? I’d like to have the sample play between 2 manual button presses, with one button press starting it and the second press triggering a new index from the sample pool and stopping the old sample.

This works almost, except that the old sample doesn’t stop playing unless I specify a fixed sustain, for example. But if it was a monophonic sampler or synthesizer, the new triggered note would simply replace the old one and so on, it’s this kind behaviour that I’m looking for, if possible. So that the sustain would equal the time between 2 button presses.

Thank you in advance for your help!

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 9, 2021, 8:58pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/2 "2021-06-09T20:58:44Z")

</div>

Hi @simesky have you checked out the `on:` opt. Explanation in the help file: “If specified and false/nil/0 will stop the sample from being played.”. So might be what you’re looking for, irrespective of release time.

Good luck.  
Hussein

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 9, 2021, 9:06pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/3 "2021-06-09T21:06:02Z")

</div>

Hello @Hussein, thank you for your reply. I’ve tested the on: opt and couldn’t get the sample to stop if it was already triggered. If I hard code the on: value as 0 or 1 then it behaves as expected, but for some reason, I couldn’t do it dynamically (say, via the get opt). Unfortunately, there’s no example in the documentation for this one, but I’ll try it again.

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 9, 2021, 9:11pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/4 "2021-06-09T21:11:26Z")

</div>

Hi @simesky you’re welcome.  
I think you might need to make a variable and use this:

```ruby
live_loop :test do
  playing = 1
  sample :ambi_choir, on:!playing
  sleep 1
end

```

If you remove the ! the sample will play, put it back and it will stop.  
Then combine this with an if statement to determine whether you need to stop the sample playing before pressing on with the next one.

Hopefully that will get you closer.

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 9, 2021, 9:15pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/5 "2021-06-09T21:15:09Z")

</div>

Wow, this might be the cure 🙂 Thank you again, I’ll try that right away!

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 9, 2021, 9:52pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/6 "2021-06-09T21:52:14Z")

</div>

Here’s an update, I tried the following:

```ruby
live_loop :trigger do
  on = (ring 0, 1)
  set :on, on.tick
  cue :tic
  sleep 0.5
end

live_loop :test do
  sync :tic
  playing = get[:on]
  puts playing
  sample :loop_amen, on: playing
end

```

There is a trigger loop simulating the button presses. The sample is indeed stopped, but only after it plays its whole length, not in the middle. So with sleep at 0.5 there is a superposition, but if sleep is 1 you can hear that it stops. The problem is, I’d like to stop the sample whenever. What do you think? It’s quite puzzling!

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 9, 2021, 10:11pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/7 "2021-06-09T22:11:58Z")

</div>

Hi @simesky

perhaps have a look at the `kill` command. Code example is:

```ruby
bar = sample :loop_amen
sleep 0.5
kill bar

```

Hopefully gets you closer.  
Hussein

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 9, 2021, 10:22pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/9 "2021-06-09T22:22:03Z")

</div>

I was just trying that now, as somebody suggested on Reddit. The problem remains with the sleep value in this case, I have to determine its value dynamically (as the time between button presses). I’m looking at vt, but not sure if it’s the way to go. Anyway, thank you very much for all the suggestions!

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 9, 2021, 10:28pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/10 "2021-06-09T22:28:14Z")

</div>

It takes a while to identify each critical point.  
check out this and let me know if it’s closer to what you’re looking for.

```ruby
live_loop :trigger do
  on = (ring 0, 1)
  set :on, on.tick
  # puts get[:on]
  cue :tic
  sleep 0.5
end

live_loop :test do
  sync :tic
  
  playing = get[:on]
  test = sample :loop_amen, beat_stretch: 2, sustain:1.0, on: playing
  sleep 0.5
  
  if playing
    kill test
  end
  
end

live_loop :test2 do
  sync :tic
  
  playing = !get[:on]
  
  testy = sample :loop_amen, beat_stretch:2, sustain:1.0, on: !playing
  sleep 0.5
  
  if playing
    kill testy
  end
  
end

```

I’ve duplicated the sample play loop except one triggers on false and the other on true. Not guaranteed but might work better. I suspect you might also need to look at sample duration to be able to work out the value for `sustain`.

Actually just tried it again and doesn’t seem to be giving the result I thought. Perhaps experiment with taking `beat_stretch` out and adjusting sustain. It’s late here, so probably misheard the process.

Regards  
Hussein

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 9, 2021, 10:38pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/11 "2021-06-09T22:38:17Z")

</div>

Hi again,  
Haha, it’s getting late here too 🙂 I try to comprehend your approach and I think I see what you’re getting at with the opposite action for both loops. I’ll study this carefully and see.

Kind regards,  
Alex

---

<div class="post-metadata">

**Author:** ![Eli](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/eli/32/116_2.png) [@Eli](https://in-thread.sonic-pi.net/u/Eli)\
**Post date:** [June 10, 2021, 2:28am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/12 "2021-06-10T02:28:12Z")

</div>

Have you considered the kiill command?

```ruby
x = sample :loop_amen
kill x if on: playing

```

Or something like that.

Eli…

---

<div class="post-metadata">

**Author:** ![ethancrawford](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@ethancrawford](https://in-thread.sonic-pi.net/u/ethancrawford)\
**Post date:** [June 10, 2021, 6:47am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/13 "2021-06-10T06:47:40Z")

</div>

Hi @simesky 🙂  
As others have already mentioned, `kill` is the key to stopping a sample mid-play.  
Here is one small example that I believe demonstrates something similar to what you’re after:

```ruby
live_loop :trigger do
  cue :trig if (bools 1, 0, 1).tick
  sleep 0.5
end

live_loop :samps do
  sync :trig
  samps = sample_names(:loop)
  kill get(:samp) if get(:samp)
  set(:samp, sample(samps.choose))
end

```

(With a little extra work this could of course be extended to triggering samples in multiple loops too).

---

<div class="post-metadata">

**Author:** ![ethancrawford](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@ethancrawford](https://in-thread.sonic-pi.net/u/ethancrawford)\
**Post date:** [June 10, 2021, 6:56am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/14 "2021-06-10T06:56:23Z")

</div>

> [@Hussein](#):
>
> Explanation in the help file:

It’s perhaps not entirely clear, but what it means by ‘will stop the sample from being played’ is ‘will not play this potential new instance of the sample at all’, rather than ‘will stop a currently playing sample’.

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 10, 2021, 7:29am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/15 "2021-06-10T07:29:51Z")

</div>

Hi @ethancrawford , thank you for clarification.

is this because every `loop` is a new instance, rather than dealing with a fixed entity such as a sampler VST instrument?

I had wondered whether it would be possible to create opts for trigger behaviour such as play to end or play while key down. Would be similar to setting an observer that watches for state change. Or if the objects could be added to a message list, similar to `cue` and `sync`. `sustain` sort of accomplishes this, but not tied to event/action, which can lead to imprecision.

I also recognise that there’s a danger of conforming SPi to be the same as DAWs, rather than seeing it as a new instrument/tool. So, even though I am mindful of this, I do actually wish that in some aspects its behaviour conformed a bit more with devices such as samplers and their playback /trigger modes. The field of sample based music would be weird indeed if we did not have a monophonic trigger mode.

Much appreciated.  
Hussein

---

<div class="post-metadata">

**Author:** ![Eli](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/eli/32/116_2.png) [@Eli](https://in-thread.sonic-pi.net/u/Eli)\
**Post date:** [June 10, 2021, 7:32am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/16 "2021-06-10T07:32:17Z")

</div>

Hmmm… then perhaps something based on time, plus the sample duration,  
such that a new sample will not start until the sample\_duration of the current  
sample has passed?

x = sample\_duration(:loop\_amen)

Eli…

---

<div class="post-metadata">

**Author:** ![ethancrawford](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@ethancrawford](https://in-thread.sonic-pi.net/u/ethancrawford)\
**Post date:** [June 10, 2021, 8:05am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/17 "2021-06-10T08:05:43Z")

</div>

Live loops are essentially looping threads. Their threads will remain persistent instances until killed. If I understand it correctly, then each time around the loop, if the code that the thread is executing contains `sample ...`, `synth ...` or `fx ...`, then a new instance of that sample, synth or fx is created and sent to the Supercollider server to play.  
The model here is that sounds are all scheduled in advance - with (as far as I can remember) the only ‘live’ (ie while a synth is _actually playing_) manipulation being through the `control` or `kill` functions.  
@samaaron may have further comments about playback/trigger modes. There was an experiment he made a little while ago demonstrating a basic button grid GUI built in to Sonic Pi - perhaps that would be related in some way.

@Eli - not sure what you’re describing there. If you’re talking about solutions to monophonic sample triggering, I show an example above…

---

<div class="post-metadata">

**Author:** ![Hussein](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/hussein/32/1972_2.png) [@Hussein](https://in-thread.sonic-pi.net/u/Hussein)\
**Post date:** [June 10, 2021, 8:48am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/18 "2021-06-10T08:48:43Z")

</div>

@ethancrawford thank you for this. yes I meant the instance of sample, so thank you for the correction.

So could `control` offer a potential solution here? One hack could be to control playback via `amp:` modification i.e. shuttle between values of off/on.

I think the way that Sam has solved the problem of concurrency is amazing. It works. I’ve programmed a version of Riley’s In C for 40 players, which is great. Still got some bits to iron out, such as knowing when to stop! What’s also amazing is that I can run the program at a tempo most musicians can’t play the piece at. Produces a whole new set of results for my own curiosity. If I had to build the whole thing in Supercollider, I think I’d be a bit less enthused. Sam has done the heavy lifting, and I am for one am highly appreciative.

In roughly four months from now, I’ll be incorporating SPi into my performance teaching work. Something I could not say, if using Supercollider. The ‘useable by a 10 year old’ philosophy works on so many levels and is one of the reasons why I feel confident to be able to use SPi with my performance students, especially where the assessment criteria require an engagement with technology to be built into their practice. A DAW is sometimes not the right solution and Live Coding opens the door to so many other discipline areas, whether building from scratch or modifying/varying values/code. SPi runs on the main platforms, on modest computers, something DAWs will find challenging.

Regards  
Hussein

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 10, 2021, 10:38am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/19 "2021-06-10T10:38:46Z")

</div>

Thank you all for the amazing responses and for your time, I appreciate it. I’ll check the proposed solutions and see how it turns out!

---

<div class="post-metadata">

**Author:** ![simesky](https://avatars.discourse-cdn.com/v4/letter/s/7c8e57/32.png) [@simesky](https://in-thread.sonic-pi.net/u/simesky)\
**Post date:** [June 10, 2021, 10:53am UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/20 "2021-06-10T10:53:42Z")

</div>

I’ve seen it, that’s the behavior that I got for the on: opt. Thank you!

---

<div class="post-metadata">

**Author:** ![ethancrawford](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@ethancrawford](https://in-thread.sonic-pi.net/u/ethancrawford)\
**Post date:** [June 10, 2021, 12:48pm UTC](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693/21 "2021-06-10T12:48:49Z")

</div>

> So could `control` offer a potential solution here? One hack could be to control playback via `amp:` modification i.e. shuttle between values of off/on.

Sure, that would work also!

> [@Hussein](#):
>
> In roughly four months from now, I’ll be incorporating SPi into my performance teaching work.

Exciting! Definitely keep us updated about how it goes - it’s always wonderful to hear feedback 😄

[Next page](https://in-thread.sonic-pi.net/t/monophonic-sample-loop/5693.md?page=2)
