Drum loops

I am trying to create a drum loop.
So I have to be able to set the time between beats. I have attempted to set a time of 1 second between loops.
Here is my code

function setup()
   — t1 = Elapsed Time
    —t2 = ElapsedTime
    —I was wondering if these needed to be defined as global.. It made no difference. 
end

function draw()
    
    background(40, 40, 50)
    strokeWidth(5)

    rect(WIDTH/2-100,HEIGHT/2-50,200,100)
end

function touched(t)
    if t.state == BEGAN and t.x>WIDTH/2-100 and t.x<WIDTH/2+100 and t.y>HEIGHT/2-50 and t.y<HEIGHT/2+50 then
        
        DrumLoop()
    end
end

function DrumLoop()
    t1 = ElapsedTime
    --t1 = os.time()
    sound(asset.documents.MySounds.Honey_Bucket_Mid)
    
    repeat
    t2=ElapsedTime
    --until os.difftime(t2-t1)>1
    until (t2-t1)>1
    sound(asset.documents.MySounds.Honey_Bucket_Mid)
    
 
end

The “repeat until loop” doesn’t work. If I use t2 - t1 the first beat is played then the code goes into a continual loop not getting to the second beat (or sound)
If I use os.difftime I get an error. Something like expecting a numerical value for the second argument in difftime.

I have also tried this with os.clock and os.time

I must be doing something wrong.

@congokjt A lot of build in variables don’t get updated again until you exit the function they’re used in. So in the function DrumLoop(), the variable t1 will get the value from ElapsedTime. The variable t2 will have the same value as t1 because ElapsedTime won’t be updated again until you exit DrumLoop(). Codea can’t update the variable if you’re in a loop and don’t exit the function. So what you’re doing won’t work. You’ll have to come up with a different way you’re doing that. You could add more variables so when you play the first sound, you don’t play the second sound until you set a second variable.

Here’s an example to show what’s happening. Tap the button to start DrumLoop which will loop for several seconds. It prints the ElapsedTime value before and after the loop. They’ll be the same. Tap again to see an updated ElapsedTime.

function setup()
end

function draw()    
    background(40, 40, 50)
    strokeWidth(5)    
    rect(WIDTH/2-100,HEIGHT/2-50,200,100)
end

function touched(t)
    if t.state == BEGAN and t.x>WIDTH/2-100 and t.x<WIDTH/2+100 and 
            t.y>HEIGHT/2-50 and t.y<HEIGHT/2+50 then        
        DrumLoop()
    end
end

function DrumLoop()
    print("start drumloop")
    t1=ElapsedTime
    print(t1)
    for z=1,100000000 do
        a=math.sqrt(z)
    end
    print("end drumloop")
    t1=ElapsedTime
    print(t1)
end

I know it’s been a while but I had another look at the ElapsedTime function. As long as you use it inside the draw function it works perfectly. Even if you put it in a function (in the draw function) it reads the elapsed time perfectly. So you can code in drum loops and set the BPM.

@congokjt ElapsedTime is not going to change while it’s in a loop. Here’s your above code with print statements showing the values of ElapsedTime, t1 and t2. You can change the number of 0’s in the “if count” statement to increase the delay between printing t1 and t2. They are not going to change no matter where DrumLoop is called from. The DrumLoop function will never end using the “until t2-t1>1” because t1 and t2 will always be equal.

function setup()
end

function draw()    
    background(40, 40, 50)
    strokeWidth(5)    
    rect(WIDTH/2-100,HEIGHT/2-50,200,100)
    if loop then
        print("start DrumLoop")
        DrumLoop()
        print("end DrumLoop")
    end
end

function touched(t)
    if t.state == BEGAN and t.x>WIDTH/2-100 and t.x<WIDTH/2+100 and t.y>HEIGHT/2-50 and t.y<HEIGHT/2+50 then        
        loop=true
    end
end

function DrumLoop()
    loop=false
    t1 = ElapsedTime
    print("t1",t1)
    --sound(asset.documents.MySounds.Honey_Bucket_Mid  
    count=0
    repeat
        t2=ElapsedTime
        count=count+1
        if count>1000000 then
            print("count  "..count)
            print("t2",t2)
            return
        end
    until (t2-t1)>1
    --sound(asset.documents.MySounds.Honey_Bucket_Mid) 
    print("t2>t1")
end

@congokjt Heres your above code using socket gettime which works in a loop.

function setup()
    s=require("socket")
end

function draw()    
    background(40, 40, 50)
    strokeWidth(5)    
    rect(WIDTH/2-100,HEIGHT/2-50,200,100)
end

function touched(t)
    if t.state == BEGAN and t.x>WIDTH/2-100 and t.x<WIDTH/2+100 and t.y>HEIGHT/2-50 and t.y<HEIGHT/2+50 then        
        DrumLoop()
    end
end

function DrumLoop()
    print("start DrumLoop")
    t1 = s:gettime()
    print("t1",t1)
    --sound(asset.documents.MySounds.Honey_Bucket_Mid )
    repeat
        t2=s:gettime()
    until (t2-t1)>1
    print("t2",t2)
    --sound(asset.documents.MySounds.Honey_Bucket_Mid) 
    print("end DrumLoop 1 sec")
end

Hi
Thanks for the reply dave1707.
That code looks interesting. I haven’t heard of socket or get time before. I will try it.

Apologies, I got confused.
I was using OS.clock, not elapsed time. difftime doesn’t work as as it only accepts integer values, so I just used t1 and t2 in the appropriate places in the code.
The loop function can be outside or inside the draw function.

I put the code below in case anyone is interested.
This a simple 1 bar loop, with BPM = 120.
I tried to include the two files needed but I failed.

I found some other ways of doing loops but this is my favourite.

This is my code.

--a simple 4/4 loop using os.clock. BPM =  120

function setup()
BPM = 100
end
function draw()
    
    background(40, 40, 50)
    strokeWidth(5)
    
    rect(WIDTH/2-100,HEIGHT/2-50,200,100)
    

end

function touched(t)
    if t.state == BEGAN and t.x>WIDTH/2-100 and t.x<WIDTH/2+100 and t.y>HEIGHT/2-50 and t.y<HEIGHT/2+50 then
        
        DrumLoop()
    end
end
function DrumLoop()
    for a = 1 , 4 do
        t1 = os.clock()
        if a == 1 or a == 3 then
            
            sound(asset.documents.MySounds.Honey_Bucket_Low_3)
        end
        if a == 2 or a== 4 then
            
            sound(asset.documents.MySounds.Honey_Bucket_Mid)
        end
        
        t2 = os.clock()
        
        while t2-t1<0.5 do
            t2 = os.clock()
        end
    end
end

Here’s another example of beats per minute. Just change the value in the beats call. Currently it’s set at 120 bpm ( beats(120) ) . Tap the screen to start or stop the beat.

function setup()
    s=require("socket")
    s1=0
end

function draw()
    background(0)
    fill(255)
    text("tap screen to start or stop the beat",WIDTH/2,HEIGHT/2)
    beats(120)
end

function beats(bpm)
    if s1>0 and s:gettime()-s1>c then
        c=c+60/bpm
        sound(SOUND_PICKUP, 46564)
    end
end

function touched(t)
    if t.state==BEGAN then
        if s1==0 then
            c=0
            s1=s:gettime()
        else
            s1=0
        end
    end
end

Very cool.
I tried your loop. It worked nicely. I will look through it and try and understand. So for example s=require(“socket”). I couldn’t find anything about this in the reference, but I had no idea where to look.
I will keep on working on it.

@congokjt I don’t think it’s in the Codea reference. A google search will give more info, but gettime is the only thing I use.