# BPM value to Speed knob %



## EvilDragon (May 25, 2010)

Hello everyone, I'm new here. gregjazz suggested to me to register over here, and I'm finding a lot of useful info.

Here's the issue. I have an instrument which comprises of two sets of loops, which are sorted in a number of groups (as stems). The first set is original loop tempo, and the second set is 65 BPM always. The user has option to play the mix of stems, or combine stems as seen fit. For tempo-syncing I'm using Beat Machine, and here's where the issue starts.

I want to pass a non-integer value to the Speed_to_ep function from Big Bob's math library. So far I'm feeding (BPM*100)/ORIG_TEMPO to it, but that gives me only integer percentages, which doesn't give me perfect tempo sync. The table below shows values needed, if the original loop was at 130 BPM, and I want the final BPM range of 65-200 BPM:




[mrow]	BPM
[mcol]%
[mcol]BPM
[mcol]%
[mcol]BPM
[mcol]%
[mcol]BPM
[mcol]%
[row]	65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
[col]50
50,76923077
51,53846154
52,30769231
53,07692308
53,84615385
54,61538462
55,38461538
56,15384615
56,92307692
57,69230769
58,46153846
59,23076923
60
60,76923077
61,53846154
62,30769231
63,07692308
63,84615385
64,61538462
65,38461538
66,15384615
66,92307692
67,69230769
68,46153846
69,23076923
70
70,76923077
71,53846154
72,30769231
73,07692308
73,84615385
74,61538462
75,38461538
[col]99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
[col]76,15384615
76,92307692
77,69230769
78,46153846
79,23076923
80
80,76923077
81,53846154
82,30769231
83,07692308
83,84615385
84,61538462
85,38461538
86,15384615
86,92307692
87,69230769
88,46153846
89,23076923
90
90,76923077
91,53846154
92,30769231
93,07692308
93,84615385
94,61538462
95,38461538
96,15384615
96,92307692
97,69230769
98,46153846
99,23076923
100
100,7692308
101,5384615
[col]133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
[col]102,3076923
103,0769231
103,8461538
104,6153846
105,3846154
106,1538462
106,9230769
107,6923077
108,4615385
109,2307692
110
110,7692308
111,5384615
112,3076923
113,0769231
113,8461538
114,6153846
115,3846154
116,1538462
116,9230769
117,6923077
118,4615385
119,2307692
120
120,7692308
121,5384615
122,3076923
123,0769231
123,8461538
124,6153846
125,3846154
126,1538462
126,9230769
127,6923077
[col]167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
[col]128,4615385
129,2307692
130
130,7692308
131,5384615
132,3076923
133,0769231
133,8461538
134,6153846
135,3846154
136,1538462
136,9230769
137,6923077
138,4615385
139,2307692
140
140,7692308
141,5384615
142,3076923
143,0769231
143,8461538
144,6153846
145,3846154
146,1538462
146,9230769
147,6923077
148,4615385
149,2307692
150
150,7692308
151,5384615
152,3076923
153,0769231
153,8461538

Here's the code so far. The if conditions in note on callback are for switching between the slower and faster loops.


```
import "KSPMath_v215.txt"

on init
	declare ui_knob BPM (65,200,1)
	declare ui_menu Tempo
	add_menu_item(Tempo,"Normal",1)
	add_menu_item(Tempo,"Double",2)
	add_menu_item(Tempo,"Half",3)
	add_menu_item(Tempo,"Triplet Slow",4)
	add_menu_item(Tempo,"Triplet Fast",5)
	add_menu_item(Tempo,"---------------",0)
	add_menu_item(Tempo,"Manual",6)
	add_menu_item(Tempo,"Default",7)
	move_control(Tempo,1,2)
	Tempo := 7

	declare out
	declare count
	declare ORIG_TEMPO := 149 { this particular loop is in 149 BPM, I used 130 BPM just as an example for the table above! }
	declare TEMPO_SW
	declare percent

	BPM := ORIG_TEMPO
	if (BPM < ORIG_TEMPO)
        TEMPO_SW := 65
	else
        TEMPO_SW := ORIG_TEMPO
	end if

	message ("")
end on

on ui_control (Tempo)
	select (Tempo)
		case 1
			BPM := 60000000/DURATION_QUARTER
		case 2
			BPM := 60000000/DURATION_QUARTER*2
		case 3
			BPM := 60000000/DURATION_QUARTER/2
		case 4
			BPM := 60000000/DURATION_QUARTER*666/1000
		case 5
			BPM := 60000000/DURATION_QUARTER*1333/1000
		case 7
			BPM := ORIG_TEMPO
	end select
	if (BPM < ORIG_TEMPO)
		TEMPO_SW := 65
	else
		TEMPO_SW := ORIG_TEMPO
	end if
	message("")
end on

on ui_control (BPM)
	Tempo := 6
	if (BPM < ORIG_TEMPO)
		TEMPO_SW := 65
	else
		TEMPO_SW := ORIG_TEMPO
	end if
end on

on note
	ignore_event(EVENT_NOTE)
	select (Tempo)
		case 1
			BPM := 60000000/DURATION_QUARTER
		case 2
			BPM := 60000000/DURATION_QUARTER*2
		case 3
			BPM := 60000000/DURATION_QUARTER/2
		case 4
			BPM := 60000000/DURATION_QUARTER*666/1000
		case 5
			BPM := 60000000/DURATION_QUARTER*1333/1000
		case 7
			BPM := ORIG_TEMPO
	end select
	if (BPM > 200)
		BPM := 200
	end if
	if (BPM < 65)
		BPM := 65
	end if
	message("")
	percent := (BPM*100/TEMPO_SW)

	Speed_to_ep(percent,out)

	disallow_group(ALL_GROUPS)
	count := 0
	if (BPM >= ORIG_TEMPO)
		while (count < NUM_GROUPS/2)
			allow_group(count)
			set_engine_par(ENGINE_PAR_SPEED,out,count,-1,-1)
			inc(count)
		end while
	else
		while (count < NUM_GROUPS/2)
			allow_group(count+12)
			set_engine_par(ENGINE_PAR_SPEED,out,count+12,-1,-1)
			inc(count)
		end while
	end if
    
	if ((EVENT_NOTE = 60) or (EVENT_NOTE = 62) or (EVENT_NOTE = 64) or (EVENT_NOTE = 65))
		play_note(EVENT_NOTE+12,EVENT_VELOCITY,0,-1)
		play_note(EVENT_NOTE+19,EVENT_VELOCITY,0,-1)
		if (in_range(EVENT_NOTE,62,65))
			play_note(EVENT_NOTE+24,EVENT_VELOCITY,0,-1)
		end if
	end if
end on
```


Thanks for any help, and sorry if this was tl;dr!


----------



## EvilDragon (May 27, 2010)

No dice, anyone? ^^'


----------



## EvilDragon (May 30, 2010)

OK, at least can someone hint me on how would I enter Big Bob's formula for converting % to engine values into Excel... that's some pretty complex math there (not that I don't understand it, but I'm not so good with functions in Excel).

If I can get this function into Excel, then I'd at least be able to make a lookup table. Big Bob, care to take a minute over here, pretty please? ^^'


----------



## Big Bob (May 30, 2010)

Hi ED,

If you can wait about a week, I may be able to have some time to look into this for you. But, right now, I no got :lol: 

Bob


----------



## EvilDragon (May 30, 2010)

It's OK Bob 

I inputted this into Excel:

=CEILING((POWER((LOG(((3*C2)+50);2)/2,807354922)-3,010382197;1/3)*500000)+500000;1)

C2 being the cell which holds the percentage value.

I don't know if I did it right, because I got 498053 for 100%, shouldn't I get 500000?


However, if you can look into this, I could wait a week, till then I have 800 loops to slice :D Script can always be corrected. What matters me the most is to get the most precise value to Speed knob, to ensure perfect tempo sync. So, essentially, this would be tweaking your Speed_to_ep function to accept THREE parameters instead of two: original BPM, wanted BPM, output value, and it would calculate the percentage ((wanted BPM/original BPM)*100) internally, so we could possibly bypass lookup tables? This would be SO AWESOME and I'd be most grateful!

Hey, I know that my ASCII keyboard is probably nothing in comparison, but I have some other tiny tricks to show, sometime, I guess 

Thanks!


EDIT: in fact, I have now edited my Excel spreadsheet, so it creates a lookup table in the blink of an eye, so no need for additional math functions here, at least for me! If you're gonna do it just for kicks, ok, but it seems it's not necessary now  In practice, using lookup tables should definitely be more practical and faster than calculation on the fly, right? (This particular lookup table has an array of 136 elements)


----------



## Big Bob (May 31, 2010)

Hi ED,

Glad you solved the problem, now I won't have to try to find the time to look into this :lol: 



> EDIT: in fact, I have now edited my Excel spreadsheet, so it creates a lookup table in the blink of an eye, so no need for additional math functions here, at least for me! If you're gonna do it just for kicks, ok, but it seems it's not necessary now In practice, using lookup tables should definitely be more practical and faster than calculation on the fly, right? (This particular lookup table has an array of 136 elements)



Table lookup will of course always be faster than 'calculation on the fly' as you put it. However, sometimes it can be very convenient to 'build' the lookup table 'on the fly' during the ICB. This can then avoid the lengthy block of code that would otherwise be devoted to filling in the arrays during the ICB execution.

Bob


----------



## Big Bob (May 31, 2010)

So maybe you might like me to look this over in a week or so if time allows?


----------



## EvilDragon (May 31, 2010)

No, it's ok Bob, I really appreciate offer for help. The lookup table works swell!

I'd like you to take a look at this, though


----------

