Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Drum loops

edited December 2020 in Questions Posts: 22

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.

Comments

  • dave1707dave1707 Mod
    edited September 2020 Posts: 8,739

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

  • dave1707dave1707 Mod
    Posts: 8,739

    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.

  • dave1707dave1707 Mod
    Posts: 8,739

    @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
    
  • dave1707dave1707 Mod
    edited December 2020 Posts: 8,739

    @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
    
  • edited December 2020 Posts: 22

    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
    
  • dave1707dave1707 Mod
    Posts: 8,739

    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.

  • dave1707dave1707 Mod
    Posts: 8,739

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

Sign In or Register to comment.