# Slowing down a loop - what is the best way to handle this?



## RiffWraith (Oct 18, 2010)

So, I have a tom loop @ 120 bpm. I create an instrument in K4, source is set to b.machine, on the sample loop page, I have selected 1, and 'until release', sync slice to 'use b.machine', grid width to 1/8 and 120 bpm 4/4. Everything works fine with the host seq. set to 120:

http://www.jeffreyhayat.com/TomLoop120.mp3

Problem is if I slow down the host seq. Here is the host at 112:

http://www.jeffreyhayat.com/TomLoop112.mp3

I am sure you can hear the drop-outs. Playing with grid width and bpm yields odd results; nothing that helps this issue.

Is there anything I can do to smooth that out, outside of making the loop a slower tempo? Looking at this from a dev perspective. You want to give your customers the option to play loops back at any tempo they wish; if I were to make that loop alot slower, say, 80bpm, that would work, but by the time you set the host seq. up close to 200 bpm, that loop is going to sound funky. What to do? Is there a way to have a second loop triggered once the host seq. gets to a certain tempo?

Thanks in advance!


----------



## EvilDragon (Oct 19, 2010)

Yep, BM is not the best with tempos slower than original. You should try tweaking Release parameter of the BM in the Source module.


----------



## RiffWraith (Oct 19, 2010)

Thanks for the reply.  



EvilDragon @ Tue Oct 19 said:


> Yep, BM is not the best with tempos slower than original.



Yeah, kinda thought that that's the way it is.

Tweaking the Release parameter of the BM in the Source module doesn't really help. I hear it making a small difference, but not nearly enough.

So, what is the answer? Is this just something that we have to live with, or is there a way to have a second loop triggered once the host seq. gets to a certain tempo? 

Thanks again!


----------



## EvilDragon (Oct 19, 2010)

RiffWraith @ 19.10.2010 said:


> or is there a way to have a second loop triggered once the host seq. gets to a certain tempo?



Scripting. :D You could do it like this, yes. Or, you could first try ReCycling a loop, and then instead of importing a WAV, import an RX2 file, then see what happens.

But yeah, theoretically you could switch between different groups holding loops in different tempos via script.


----------



## RiffWraith (Oct 19, 2010)

EvilDragon @ Wed Oct 20 said:


> But yeah, theoretically you could switch between different groups holding loops in different tempos via script.



Great.  Err, care to be a kind feller, and point me in the right direction of a good starting point? o-[][]-o


----------



## EvilDragon (Oct 19, 2010)

Let's say you have two loops, one at 60 and the other at 120 BPM. Let's say you want to have total tempo range from 60-120 BPM.

The easier part is to actually decide which loop is gonna be played depending on tempo. Let's say that the slower loop is in group 1, and faster is in group 2, and we're using sync to host instead of manual tempo control:


```
on note
    ignore_event($EVENT_ID)
    disallow_group($ALL_GROUPS)
    if (60000000 / $DURATION_QUARTER < 120)
        allow_group(0)
    else
        allow_group(1)
    end if
end note
```
60000000 / $DURATION_QUARTER gives you the BPM value, obviously. If we'd used a Tempo knob, the if condition would read: if ($Tempo >= 120)

The tricky part would be actually getting the correct engine parameter values which correspond to the actual BPM value we have. Since Speed parameter of Beat Machine uses percentages, there needs to be a way for us to calculate the percentage from the currently used BPM. In this case, it's a tad more complicated because we're using two loops with two different base tempos, so the actual percentages are different.

For BPM in range 60-119, we have one percentage (which is <current tempo>/60), and for BPM in range 120-180 we have the other percentage (which is <current tempo>/120).

I heartilly recommend calculating a lookup table using the Excel spreadsheet I posted here. Enter a value of 60 in the bold red field, it will recalculate. Take the values in range *C102:C161* and paste them to Notepad or something. Now enter a value of 120 in the bold red field to recalculate again. Take the values in range *C102:C162* and paste them to Notepad AFTER the already pasted values. With a bit of formatting you should have your lookup table ready.

In KSP, you would declare a lookup table like this:


```
declare %lookup[<number of values in the table>] := (<enter all values, comma separated>)
```
Now, I have this table done here, but I want you to sweat a bit, too 

So, with the lookup table done, we only need a helper variable for final BPM value, so we can limit the range from 60-180 BPM, and this is how this simple script should look in the end:

[code:ò.)   ì?–.)   ì?—.)   ì?˜.)   ì?™.)   ì?š.)   ì?›.)   ì?œ.)   ì?.)   ì?ž.)   ì?Ÿ.)   ì? .)   ì?¡.)   ì?¢.)   ì?£.)   ì?¤.)   ì?¥.)   ì?¦.)   ì?§.)   ì?¨.)   ì?©.)   ì?ª.)   ì?«.)   ì?¬.)   ì?­.)   ì?®.)   ì?¯.)   ì?°.)   ì?±.)   ì?².)   ì?³.)   ì?´.)   ì?µ.)   ì?¶.)   ì?·.)   ì?¸.)   ì?¹.)   ì?º.)   ì?».)   ì?¼.)   ì?½.)   ì?¾.)   ì?¿.)   ì?À.)   ì?Á.)   ì?Â.)   ì?Ã.)   ì?Ä.)   ì?ß.)   ì?à.)   ì?á.)   ì?â.*   ì?Å.*   ì?Æ.*   ì?Ç.*   ì?È.*   ì?É.*   ì?Ê.*   ì?Ë.*   ì?Ì.*   ì?Í.*   ì?Î.*   ì?Ï.*   ì?Ð.*   ì?Ñ.*   ì?Ò.*   ì?Ó.*   ì?Ô.*   ì?Õ.*   ì?Ö.*   ì?×.*   ì?Ø.*   ì?Ù.*   ì?Ú.*   ì?Û.*   ì?Ü.*   ì?Ý.*   ì?Þ.+   ì?g.+   ì?h.+   ì?ã.+   ì?ä.+   ì?å.+   ì?æ.+   ì?ç.+


----------



## RiffWraith (Oct 20, 2010)

Ok, it's official. YOU ROCK! =o 

Will let you know how it turns out - THANKS!!!


----------



## RiffWraith (Oct 23, 2010)

Ok, so I gave this a shot, using 60/120 bpm. This is assuming the very first code at the top of your last post is not required - that that was only a small portion of the example...

Did the excel thing, tho...



EvilDragon @ Wed Oct 20 said:


> Enter a value of 60 in the bold red field, it will recalculate. Take the values in range *C102:C161* and paste ...



Recalulated @ 60 only gave me up until C160 (where '160' is column A - not line 160). Ok, not sure if that matters or not for now.

So I got the table, and formatted it proeprly, and then inserted as needed.

This is what I have:


```
on init 
    declare $BPM 
    declare %lookup[162] := (500476, 596947, 621860, 639173, 652830, 664259, 674162, 682940, 690849, 698062, ... 
                             704703, 710863, 716614, 722010, 727095, 731906, 736473, 740819, 744967, 748934, ...
                             752737, 756388, 759899, 763282, 766545, 769697, 772745, 775696, 778556, 781330, ...
                             784023, 786640, 789185, 791662, 794074, 796424, 798716, 800953, 803136, 805269, ...
                             807353, 809391, 811384, 813335, 815245, 817115, 818948, 820745, 822506, 824234, ...
                             825930, 827594, 829228, 830833, 832410, 833959, 835482, 836979, 838452, 839900, ...
                             841325, 842728, 844109, 845468, 846807, 848125, 849424, 850704, 851966, 853210, ...
                             854436, 855645, 856837, 858013, 859174, 860319, 861449, 862564, 863665, 864752, ...
                             865826, 866886, 867933, 868967, 869989, 870998, 871996, 872982, 873957, 874921, ...
                             875873, 876815, 877747, 878668, 879579, 880480, 881372, 882254, 883127, 883991, ...
                             884846, 293228, 297400, 301716, 306190, 310843, 315698, 320781, 326127, 331778, ...
                             337788, 344229, 351196, 358823, 367311, 376973, 388359, 402590, 422778, 500476, ...
                             577038, 596947, 610847, 621860, 631118, 639173, 646343, 652830, 658770, 664259, ...
                             669372, 674162, 678673, 682940, 686991, 690849, 694534, 698062, 701447, 704703, ...
                             707838, 710863, 713786, 716614, 719353, 722010, 724589, 727095, 729533, 731906, ...
                             734218, 736473, 738672, 740819, 742917, 744967, 746972, 748934, 750855, 752737, ...
                             754580, 756388) 
 
end on 

on note 
    ignore_event($EVENT_ID) 

    $BPM := 60000000 / $DURATION_QUARTER 

    if ($BPM < 60) 
        $BPM := 60 
    end if 
    if ($BPM > 120) 
        $BPM := 120
    end if 

    disallow_group($ALL_GROUPS) 
    if ($BPM < 120) 
        allow_group(0) 
        set_engine_par($ENGINE_PAR_SPEED,%lookup[$BPM-60],0,-1,-1) 
    else 
        allow_group(1) 
        set_engine_par($ENGINE_PAR_SPEED,%lookup[$BPM-60],1,-1,-1) 
    end if 
end on
```

When i click 'apply', I get *ERROR line 32: newline expected *- this is where I am stuck - I have no idea where to even begin to look. :? It points to *$BPM := 60 *

And the very last line is 'end note' - should that not be 'end on'?

Thanks!


----------



## RiffWraith (Oct 23, 2010)

Thanks for the response.



kb123 @ Sun Oct 24 said:


> you have an extra ) at the end of that line, and it should be end on



The problem line of *$BPM := 60* has no *)*.... :?:


----------



## RiffWraith (Oct 23, 2010)

Ah - got it. Ok, edited my above post to reflect that change.

Also, had *declare %lookup[152]* = shoulda been *162*....math was off. D'oh!

So now, no errors, but no sound. :(


----------



## RiffWraith (Oct 24, 2010)

That's it - you rule. :D 

Next and hopefully final Q:

I want to add a third group to the mix. I have taken the 


```
if ($BPM < 60) 
        $BPM := 60 
    end if 
    if ($BPM > 120) 
        $BPM := 120 
    end if
```

and added 


```
if ($BPM > 180) 
        $BPM := 180 
    end if
```

and tried adding 


```
allow_group(2) 
        set_engine_par($ENGINE_PAR_SPEED,%lookup[$BPM-60],0,-1,-1)
```

and various combos - but no matter what I try, I cant seem to get a 3rd group to work. What am I missng?

Thanks!


----------



## EvilDragon (Oct 27, 2010)

RiffWraith @ 25.10.2010 said:


> Next and hopefully final Q:
> 
> I want to add a third group to the mix.



What are the BPM ranges for each of the 3 groups?


Oh, and sorry about that ignore_event($EVENT_ID) - a play_note was supposed to come afterwards in my implementation, although it's not completely necessary, yeah.


----------



## RiffWraith (Oct 27, 2010)

EvilDragon @ Wed Oct 27 said:


> Oh, and sorry about that ignore_event($EVENT_ID) - a play_note was supposed to come afterwards in my implementation, although it's not completely necessary, yeah.



No apologies, please - you are helping me out here, and I appreciate it.



EvilDragon @ Wed Oct 27 said:


> What are the BPM ranges for each of the 3 groups?



Hmmm - well, it may change, but as of right now, say 60, 120, 180

Thanks!


----------



## EvilDragon (Oct 28, 2010)

The ranges, please 

Loop 1 - 60-119
Loop 2 - 120-179
Loop 3 - 180-??? 

Anyways, let's call them:

Loop 1 - Low1-High1
Loop 2 - Low2-High2
Loop 3 - Low3-High3

Then your on note callback should look a little something like this:


```
on note
    $BPM := 60000000 / $DURATION_QUARTER

    if ($BPM < Low1)
        $BPM := Low1
    end if
    if ($BPM > High3)
        $BPM := High3)
    end if

    disallow_group($ALL_GROUPS)
    if (in_range($BPM,Low1,High1))
        allow_group(0)
        set_engine_par($ENGINE_PAR_SPEED,%lookup[$BPM-Low1],0,-1,-1)
    else
        if (in_range($BPM,Low2,High2))
            allow_group(1)
            set_engine_par($ENGINE_PAR_SPEED,%lookup[$BPM-Low1],1,-1,-1)
        else
            allow_group(2)
            set_engine_par($ENGINE_PAR_SPEED,%lookup[$BPM-Low1],1,-1,-1)
        end if
    end if
end note
```

Of course, your lookup table should have correct engine parameter values recalculated this time for 3 slopes and not 2: Low1-High1, then Low2-High2, then Low3-High3.


----------



## RiffWraith (Oct 30, 2010)

*Awesome! Thanks so much!* :D 




EvilDragon @ Thu Oct 28 said:


> The ranges, please



Oh. :| 

Entered the correct ranges, corrected an erroneous bracket  , and it works great!

Now all I have left is a Q: you seem to stress the importance of the lookup table having correct engine parameter values. I have not yet done anything further there yet; as of right now, the lookup table is as it was when I had the two groups. Not saying I don't want to do a new lookup table, but I am curious as to what the importance there is.

Thanks again!


----------

