This keeps crashing my SonicPi after ~32 seconds with “Timing exception: Thread got too far behind time” although I do not really have a slow computer.
Can anybody reproduce that?
I have version v3.2.2
You don’t have to connect a MIDI-device actually, this happens also without one connected.
use_bpm 120
use_midi_defaults channel: 1
midi_note_off :e3
midi_note_off :a3
midi_note_off :g3
ctr = [0,0,0,1,0,0,0,0]
running = 1
live_audio :in, input: 3, stereo: true
in_thread do
sleep 32
while(1) do
if (running) then
sample :bd_tek
sleep 0.5
if (ctr.tick == 1)
sample :drum_snare_hard, hpf: 65, amp: 2
end
sleep 0.5
end
end
end
in_thread do
while (1) do
if (running) then
midi_note_on :e3 #1
sleep 0.2
midi_note_off :e3
sleep 1.35
midi_note_on :e3 #2.55
sleep 0.2
midi_note_off :e3
sleep 1.25
midi_note_on :e3 #4
sleep 0.2
midi_note_off :e3
sleep 0.8
midi_note_on :g3 #1
sleep 0.2
midi_note_off :g3
sleep 1.35
midi_note_on :a3 #2.55
sleep 0.25
midi_note_off :a3
sleep 1.2
midi_note_on :a3 #4
sleep 0.2
midi_note_off :a3
sleep 0.8
end
end
end
sleep 64
running = false
8.times do
midi_note_on :e4
sleep 1
midi_note_off :e4
sleep 1
end
running = true
Let me start by saying that I haven’t been this confused by SP code for a long time.
I see several issues:
There are two nested in_thread blocks without end. I think that is because of the do after while, removing them fixes the open blocks.
Nested threads should probably be avoided anyway, and for some reason SP doesn’t immediately throw an error because of the missing end.
There are two while true loops, you should definitely replace those with live_loops.
The thing I believe causes the crash is the if(running) in the while true loops. When running is set to false after the 64 beat sleep, these while loops repeat without delay.
I am still dissecting this, there is some other strange behaviour.
Unrelated:
If the snare is supposed to repeat, you want ctr to be a ring.
Edit 1:
I’m even more confused than 30 minutes ago.
I’ve tried to change it into something that should run fine and the loops still randomly stop.
Edit 2:
Relaunched SP and now my code works as expected.
As a general piece of advice: Use if and flags on the play/sample commands, not on the sleep. That way you keep the timing.
#Code by gedobbles
#Modified by Davids Fiddle
use_bpm 120
use_midi_defaults channel: 1
midi_note_off :e3
midi_note_off :a3
midi_note_off :g3
running1 = false
running2 = true
running3 = false
ctr = (bools 0,0,0,1,0,0,0,0)
#live_audio :in, input: 3, stereo: true
in_thread do
#Flags are set from this thread
#I think this is close to what you wanted
sleep 16
running1 = true
sleep 32
running1 = false
running2 = false
running3 = true
sleep 16
running1 = true
running2 = true
running3 = false
end
live_loop :one, delay: 0.1 do #Delay to avoid care conditionon the flag
tick
#puts 'loop 1' #For debug
sample :bd_tek if running1
sleep 0.5
sample :drum_snare_hard, hpf: 65,
amp: 2 if ctr.look && running1
sleep 0.5
end
notes = (ring :e3,:e3,:e3,:g3,:a3,:a3).stretch(2)
times = (ring 0.2,1.35,0.2,1.25,0.2,0.8,0.2,1.35,0.25,1.2,0.2,0.8)
live_loop :two, delay: 0.1 do
#puts 'loop 2'
tick
midi_note_on notes.look if running2 #Message only sent when the flag is true
sleep times.look
tick
midi_note_off notes.look #Message is always sent
sleep times.look
end
live_loop :three, delay: 0.1 do
#puts 'loop 3'
midi_note_on :e4 if running3
sleep 1
midi_note_off :e4 if running3
sleep 1
end
Hello @Davids-Music-Lab,
thanks for your work on getting things working.
Actually the in_thread statements are not nested, it only looks like that, because the code indentation doesn’t work too well for that in SonicPi.
I didn’t stick to live_loop, because these have timing issues when using midi.
Also ctr does not necessarily have to be a ring, the snare repeats in my code when adding an else sleep 0.1 to each if (running).
I should have seen the issue with the zero time loops, however I was kindof blind because not these threads died but the one where actually something happened.
This does work and is more readable in my opinion:
@emlyn I found that you can use live_loops with midi, however you have to use_realtime and the latency is still better with in_thread; while(1) do at least the last time i have tried, that was like this. Just try it but I remember to have had a terrible latency with this sort of thing (half a second or so):
live_loop :a do
note, vel = sync "/midi:midi_through_port-0:0:1/note_on"
play note, amp: vel/127.0
end