"Monophonic" sample loop?

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!

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

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.

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

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.

1 Like

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

Here’s an update, I tried the following:

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!

Hi @simesky

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

bar = sample :loop_amen
sleep 0.5
kill bar

Hopefully gets you closer.
Hussein

1 Like

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!

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.

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

1 Like

Hi again,
Haha, it’s getting late here too :slight_smile: 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

Have you considered the kiill command?

x =  sample :loop_amen
kill x if on: playing

Or something like that.

Eli…

1 Like

Hi @simesky :slight_smile:
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:

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).

1 Like

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’.

1 Like

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

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…

1 Like

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…

1 Like

@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

3 Likes

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!

2 Likes

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

1 Like

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!

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

2 Likes