YouTube2Text

KeyStage Tutorial: The Scripting Language — Transcript

by Ali Gokturk · 13,065 words · 1,875 segments · language en · Watch on YouTube

Full transcript

  1. 0:06Welcome to another tutorial video of
  2. 0:07Keystage. So in this video we are going
  3. 0:10to talk about the scripting language of
  4. 0:12Keystage. So scripts are outputs of
  5. 0:14custom translators which allow you to do
  6. 0:16much more advanced stuff. To start with
  7. 0:19let's start creating a custom translator
  8. 0:22on this track. Uh let's choose notes as
  9. 0:25our input
  10. 0:26and for output we choose script. Okay,
  11. 0:29so this is the script editor. Uh before
  12. 0:32we go into that, uh there is a new
  13. 0:34feature in 2.3
  14. 0:37which is these input conditions can also
  15. 0:40be chosen when the output is scripted.
  16. 0:42In the previous version, you won't be
  17. 0:43able to choose the input conditions. It
  18. 0:46doesn't have matter what input you have.
  19. 0:48For for example, if you have a pitch
  20. 0:49band, you can choose the input range for
  21. 0:51the pitch bands, input channels, and so
  22. 0:53on and so forth. So before the script is
  23. 0:56executed first these input conditions
  24. 0:58are checked and when those conditions
  25. 1:00are matched the script runs. So that's
  26. 1:03how it works. Okay. So before we start I
  27. 1:08strongly recommend you to connect a
  28. 1:10keyboard to your iPads to before working
  29. 1:13on the scripts. So I already connected a
  30. 1:15keyboard here and normally if you don't
  31. 1:19connect a keyboard you you have to use
  32. 1:21the virtual keyboard on on your iPad
  33. 1:24which is not really convenient. Uh
  34. 1:27connecting a keyboard makes it much
  35. 1:28easier because for example when you
  36. 1:31start typing uh autocompletes view
  37. 1:34appears and using up and down arrows you
  38. 1:37can choose between the options in the
  39. 1:38autocomplete view.
  40. 1:43Now we have cheat sheet here. This is
  41. 1:46also new in 2.3. We were going to go
  42. 1:49back to this cheat sheet. But what what
  43. 1:50this shows is all types of commands that
  44. 1:54you can write on on the scripting
  45. 1:57language. And these are all categorized
  46. 1:58in in a convenient way. For example, we
  47. 2:02had the variable types here. Then every
  48. 2:04time you choose one of the commands
  49. 2:07here, you can see the description of the
  50. 2:10command here. what it does.
  51. 2:12Okay, so let's write our first program.
  52. 2:16I'm going to go through the basics, but
  53. 2:17let's write our first program. Print
  54. 2:22hello world. So this is the first
  55. 2:24program that you always write in a
  56. 2:27computer language. So when I press a
  57. 2:29note,
  58. 2:30actually when I press a note and release
  59. 2:32the note, the hello appears in the log
  60. 2:35view here. So print actually writes into
  61. 2:38this log view here. So I can clear the
  62. 2:40lock here. Um why do I why does it
  63. 2:44happen when I press and release? Because
  64. 2:47in the input conditions both note and
  65. 2:49not off are selected here. Okay. So
  66. 2:52before I continue let me talk about
  67. 2:54commenting out lines. This is also
  68. 2:56standard in all computer languages. So
  69. 2:59now compiler completely disregards this
  70. 3:02line. Ignores this line. Now some basic
  71. 3:05rules about the scripting language. You
  72. 3:08can only write one comments on one line.
  73. 3:10You cannot have multiple comments on one
  74. 3:13line. For example, variable assignments,
  75. 3:16actions or whatever. You can have only
  76. 3:19one command. And now let's talk about
  77. 3:22variables first. So you can see there is
  78. 3:25this incoming variables. Since our input
  79. 3:28is a note,
  80. 3:31you can see the variable. So as I start
  81. 3:33playing
  82. 3:35when I press note note is on is true
  83. 3:39channel is zero. So note value and note
  84. 3:42velocity. So we get all the information
  85. 3:44of the input input signal. But for
  86. 3:46example if I
  87. 3:48uh let's assign
  88. 3:50one of the knobs here on my keyboard.
  89. 3:54If I actually choose control change 12.
  90. 3:56Now these incoming variables change. We
  91. 3:59have channel control change number and
  92. 4:01control change value. So you can monitor
  93. 4:04the incoming signals here and you we
  94. 4:06will be using these variables. So these
  95. 4:08are variables. We're going to talk about
  96. 4:10how we create variables. But let's talk
  97. 4:12about variables, variable types here. So
  98. 4:14we have different types of variables.
  99. 4:17We're going to go over them one by one.
  100. 4:19For now, what we're interested in is
  101. 4:21integers, floats, booleans, and strings.
  102. 4:26There are area versions of these
  103. 4:27variables, but we're going to talk about
  104. 4:29them later. So, these four types of
  105. 4:31variables, integers, floats, booleans,
  106. 4:33and strings are called basic variables.
  107. 4:36We're going to talk about non-basic
  108. 4:38variables at the end of this video, but
  109. 4:40for now, we we will be dealing with
  110. 4:42these four types of variables. And
  111. 4:44speaking of which, the input variables,
  112. 4:47incoming variables for the node signal
  113. 4:49are all in integer variables except this
  114. 4:52note on. This is a boo boolean variable.
  115. 4:54You can see that it's either true or
  116. 4:56false but all other variables are
  117. 4:58integers. Okay. So our first example is
  118. 5:01going to be a simple stakato. This is
  119. 5:04actually one of the uh custom
  120. 5:06translators in the database but we're
  121. 5:08going to build it from from scratch
  122. 5:10here. So uh first of all we want to
  123. 5:13apply the stacato only to note on
  124. 5:16signals. So I disabled note off. So
  125. 5:20right now when I press note this never
  126. 5:22becomes false because note off is
  127. 5:24filtered uh in the input conditions.
  128. 5:28Okay. So how do you write a staccato?
  129. 5:32All we need to do is send the note on
  130. 5:34signal and then send the note off signal
  131. 5:37after a certain period of time with a
  132. 5:39delay. So our first comment here is medi
  133. 5:44out. So as I type keep writing I see the
  134. 5:47options and media out is here.
  135. 5:49So what where is media out? Media out is
  136. 5:52here in the actions part in the actions
  137. 5:55menu. So these are all actions
  138. 5:58basically. So med sending a med signal
  139. 6:00is an action. Clearing a log is an
  140. 6:02action. So you can see the descriptions.
  141. 6:04So moving up up and down. We're not
  142. 6:06going to go through all these options.
  143. 6:08So throughout the tutorial we're going
  144. 6:11to use some of these actions but uh you
  145. 6:14can actually read the descriptions of
  146. 6:15all all of them here at the bottom.
  147. 6:18Okay. Okay. So media out. So what are we
  148. 6:20sending where we have medi message types
  149. 6:23here? We're going to send note on
  150. 6:26signal. So let's read the description.
  151. 6:28Note on medi type takes three
  152. 6:31parameters. The first parameter is
  153. 6:32channel. Second parameter is note and
  154. 6:34third parameter is velocity. So this is
  155. 6:36a common sense like these uh note on and
  156. 6:40not off signals are determined by these
  157. 6:43channel note value and velocity. So
  158. 6:47let's type
  159. 6:49note on. So a parenthesis appear. The
  160. 6:52first parameter is channel. So I write
  161. 6:55channel. So this is the incoming
  162. 6:57variable. You can see it here. This is
  163. 6:59your channel number,
  164. 7:02note value, comma.
  165. 7:07So right now when I press a note, the
  166. 7:10note on signal is is sent. But we want
  167. 7:14to send a note off signal with a delay.
  168. 7:17So media out
  169. 7:20note off. It's going to be the same
  170. 7:22channel, same note. Velocity doesn't
  171. 7:26matter in this case, but for some
  172. 7:28synthesizer, it actually does matter.
  173. 7:30And at the end of this, I'm going to add
  174. 7:33a command called delay. This is a
  175. 7:36function. Add the delay to the execution
  176. 7:38of the line. And we're going to talk
  177. 7:40about the rest of the description later.
  178. 7:43The number that you enter here will be
  179. 7:45considered as milliseconds. So let's say
  180. 7:49200 milliseconds.
  181. 7:51So right now
  182. 7:54even if I keep my notes pressed
  183. 7:58uh we just get the stato. So let's
  184. 8:00reduce this number to let's say 50
  185. 8:02milliseconds.
  186. 8:09Right now we have delay uh we have this
  187. 8:11staccato. So if I disable this,
  188. 8:15if I enable this,
  189. 8:18the stato works. Our next step is to add
  190. 8:21some conditionals. So where are
  191. 8:23conditionals? Conditionals and loops
  192. 8:25here. So this should be common sense for
  193. 8:27most of you guys who have some basic
  194. 8:30knowledge about any language bas
  195. 8:32basically C basic whatever they all have
  196. 8:36these
  197. 8:37core functions like the conditionals and
  198. 8:41loops it's going to start with
  199. 8:43conditional so it's easy
  200. 8:45so what I want to do here is I want to
  201. 8:49make the stato
  202. 8:52uh happen only at a high velocity
  203. 8:55And on low velocities I don't want this
  204. 8:58staccato to apply. Okay. So let's write
  205. 9:01if.
  206. 9:03So I want the velocity value to be above
  207. 9:07a certain number in order for this two
  208. 9:10lines to apply. So if velocity
  209. 9:15is greater than let's say 60.
  210. 9:20Uh well for some reason cuts doesn't
  211. 9:23work. I I'm going to work out work out
  212. 9:25this but copy works. So all I have to do
  213. 9:28is just copy and then uh delete the
  214. 9:31original and then paste. Okay. So if is
  215. 9:35greater than 60 we we had the stato.
  216. 9:38Well okay if it's less than 60 which
  217. 9:41means else
  218. 9:43we want to send the original signal. Now
  219. 9:46we have another uh nice
  220. 9:49uh command here actually and a specific
  221. 9:52special variable here which is called
  222. 9:54incoming metadata. So right now low
  223. 9:57velocities doesn't have stacato
  224. 10:02high velocities have stacato.
  225. 10:05Okay. So we're going to improve this uh
  226. 10:08by adding a slider to this an additional
  227. 10:11slider to this custom translator
  228. 10:13controlling the delay. I want to control
  229. 10:15the delay using a variable. So in order
  230. 10:18to create a variable, we just write the
  231. 10:20type of the variable and then name of
  232. 10:22the variable. So I'm going to say delay
  233. 10:25amount. So let's say we initiate it with
  234. 10:3050 and here we add
  235. 10:34delay amount. So right now nothing
  236. 10:36changes.
  237. 10:38We still have delay of 50 50
  238. 10:40milliseconds. Now instead of assigning
  239. 10:4350 here, I'm going to uh create a slider
  240. 10:48on the custom translator
  241. 10:52which is with this function. Okay, I
  242. 10:55haven't added the description of this
  243. 10:57function. I'm going to add it in the in
  244. 10:59in the future. But create a slider has
  245. 11:03four parameters. The first parameter is
  246. 11:05the name of the slider. So I'm going to
  247. 11:09just write delay. The second parameter
  248. 11:12is the variable that we are controlling
  249. 11:15with the slider. So delay amount is the
  250. 11:18variable. The third variable is the
  251. 11:21lower limit of this slider.
  252. 11:24Sorry, the first the third one is the
  253. 11:26upper, the fourth one is the lower limit
  254. 11:28of the slider. So let's say our highest
  255. 11:33uh delay can be 1 second and the lowest
  256. 11:36is let's say 30 seconds. Okay, my bad is
  257. 11:39this this has to be the other way
  258. 11:41around. So this should be lower, this
  259. 11:43should be higher. So that's why we need
  260. 11:45the descriptions. So let's say 30
  261. 11:47milliseconds for the lowest case and uh
  262. 11:52100 1,000 for the higher. And if we
  263. 11:55close this, now we have this delay
  264. 11:56slider added.
  265. 12:06Let's choose uh another instrument
  266. 12:08because piano it's not easy to let's
  267. 12:11choose module pro and choose a string.
  268. 12:15So let's choose a basic string.
  269. 12:25So yeah this is
  270. 12:28this is now the the custom translator in
  271. 12:31the database. This is exactly what the
  272. 12:33custom translator in the database base
  273. 12:35does. Okay before we continue I want to
  274. 12:38talk about these
  275. 12:41uh operators here. So most of these
  276. 12:44operators are just common sense like
  277. 12:47addition, subtraction but I want to
  278. 12:50point out some of the important things
  279. 12:52uh about variable types and how these
  280. 12:55operators convert variable types between
  281. 12:58variable types. So addition you can add
  282. 13:01integers and floats and the result is a
  283. 13:03float. So you you can see all the
  284. 13:05information here binary operator
  285. 13:07addition there's a special case we're
  286. 13:09going to talk about it later. And so
  287. 13:12these are the binary arithmetic
  288. 13:15operations.
  289. 13:16These are the comparison operations
  290. 13:19comparing numbers. The results are
  291. 13:21boolean. So this is one one example. We
  292. 13:24are comparing two numbers and the output
  293. 13:26is a boolean. So inside if we should
  294. 13:29always have a boolean variable and we
  295. 13:32can actually use and and or operations
  296. 13:35for to compare booleans. But you you get
  297. 13:38the point. So all these arithmetic
  298. 13:39operations gives us converts different
  299. 13:42variables to different variables and
  300. 13:44what we call a combination of these
  301. 13:48expressions
  302. 13:50operations along with these functions is
  303. 13:52called an expression. So each expression
  304. 13:56can be combination of different
  305. 13:57variables can be combination of special
  306. 13:59variables variables that we created and
  307. 14:01operations of these variables. But at
  308. 14:03the end we get one of the types here
  309. 14:06eventually and that expression when we
  310. 14:10use that expression in somewhere for
  311. 14:12example in the delay amount or here in
  312. 14:14if all these special cases for example
  313. 14:18the delay amount we should have a number
  314. 14:20variable here either a float or an
  315. 14:23integer. If you try to add a boolean
  316. 14:26variable here, for example, if I try to
  317. 14:28do the following, if delay equals
  318. 14:3156. So comparing two numbers results in
  319. 14:34a boolean variable,
  320. 14:36we have a type mismatch error because we
  321. 14:39should have an integer or actually a
  322. 14:41number here.
  323. 14:46Okay. Next, we're going to talk about
  324. 14:49loops and we're going to go through a
  325. 14:52different example.
  326. 14:53with on that loop. So, I'm going to
  327. 14:55erase this and I'm going to create a new
  328. 14:57custom translator. So, what I want to do
  329. 15:00here is I want to control the volume uh
  330. 15:04with one of my knobs here. But I don't
  331. 15:07want any jumps on the song volume. So,
  332. 15:11whenever I try to change the volume, if
  333. 15:13I jump from a value up to another value,
  334. 15:16I want the I want the song volume to
  335. 15:19change smoothly between those two
  336. 15:20values. Okay? So I have my knob here
  337. 15:24that I want to control. So it's control
  338. 15:26change 12. And as the output I choose
  339. 15:29scripts. Okay. We have two loop
  340. 15:32functions for and while. And we're going
  341. 15:35to be using while in this example. So
  342. 15:37what are we trying to achieve? We want
  343. 15:39to change the song volume uh to this
  344. 15:43control change value uh in a period of
  345. 15:46time. Uh changing the value smoothly. We
  346. 15:50will be iterating through uh a while
  347. 15:53loop while changing the song volume
  348. 15:55starting from the original value of the
  349. 15:58song volume up to or down to this
  350. 16:01control change value. Okay, first of all
  351. 16:03we need to compare our song volume.
  352. 16:06Okay, how do we access the song volume?
  353. 16:08If you go to cheat sheets, go to special
  354. 16:11variables. So these are the variables
  355. 16:12that keystage provides to access certain
  356. 16:15parameters or certain information inside
  357. 16:17keystage. Song volume media and song
  358. 16:20volume decibel are those one two of
  359. 16:22those parameters. So we can get the song
  360. 16:25volume as well as we can assign the song
  361. 16:27volume value here. So this is a special
  362. 16:30variable. You can see that special
  363. 16:31variable type of integer and the decibel
  364. 16:34version is type of floats. When you read
  365. 16:36the description here, song volume value
  366. 16:38in MIDI, the value 100 corresponds to 0
  367. 16:41decibel. Actually 127 corresponds to 6
  368. 16:44decibel, zero corresponds to minus
  369. 16:46infinity decibel. This is an assignable
  370. 16:49variable which means we can use the
  371. 16:51value and also assign different values
  372. 16:53to this changing the song. But for
  373. 16:56example, song name is read only which
  374. 16:59means we cannot assign a new name to the
  375. 17:01song using script. We can only use the
  376. 17:03name uh to compare with other strings.
  377. 17:06We're going to talk about them later.
  378. 17:07But right now, we're going to be using
  379. 17:08this med song volume med. Okay. We first
  380. 17:12need to compare this song volume with
  381. 17:14the initial value with with the value of
  382. 17:16this uh control chain single that we're
  383. 17:19sending. I'm going to create a variable
  384. 17:21called sign. And I'm going to be
  385. 17:25assigning either plus one or minus one
  386. 17:27depending on whether song volume is
  387. 17:30greater than this control change value
  388. 17:32or less than this control change value.
  389. 17:34So we want we are starting from the
  390. 17:36initial song volume value changing to
  391. 17:39control change. So if song volume midi
  392. 17:44is smaller than is less than the control
  393. 17:48change value, we're actually increasing
  394. 17:50the value. We're starting from song
  395. 17:52volume midi up to the control change
  396. 17:54value. We're going to be changing this
  397. 17:56smoothly. So sign is + one. Sign is one
  398. 18:01and otherwise
  399. 18:04sign is minus one.
  400. 18:08So minus one. So how are we using this
  401. 18:11sign? We're going to be adding this
  402. 18:12number through the iteration of while to
  403. 18:15a variable and that variable's initial
  404. 18:17value be will be our song volume mid. So
  405. 18:20let's first create another variable.
  406. 18:23Since we're always working with med
  407. 18:24signals, I'm just creating integer
  408. 18:26values. I'm going to assign say value.
  409. 18:29This value will change through the while
  410. 18:31loop. But the initial value is our song
  411. 18:35volume. Now while this value
  412. 18:41is not equal to control change value,
  413. 18:45what does that mean? our initial volume
  414. 18:47volume I don't our initial value is a
  415. 18:49song volume so I I'm assuming that the
  416. 18:53signal that we send is not the equal to
  417. 18:56the song volume this value is not equal
  418. 18:58so this while starts looping and inside
  419. 19:01this loop we we're going to add sign at
  420. 19:04every loop we're going to add sign to
  421. 19:06this value and at some point at some
  422. 19:09point the value will be equal to the
  423. 19:10control change value and we will going
  424. 19:12to go outside the loop and inside this
  425. 19:14loop we want to change the song value to
  426. 19:16the song volume. So I'm going to say
  427. 19:18song volume mid equals value
  428. 19:22and I'm going to be we're going to be
  429. 19:24adding volume
  430. 19:26equals value equals value plus sign. So
  431. 19:30we're adding the sign. So eventually the
  432. 19:32value will become equal to the control
  433. 19:34change value. So right now this seems
  434. 19:37like it's working but it actually
  435. 19:39doesn't. So if we go into the song
  436. 19:41mixer.
  437. 19:43So let's say we change the song volume
  438. 19:45to something like this and I move my
  439. 19:48slider
  440. 19:50and it just jumps. So it doesn't work.
  441. 19:53Why doesn't it work? It's because this
  442. 19:56while loop actually happens in like a 1
  443. 20:00million of a millisecond and the song
  444. 20:02volume changes
  445. 20:04uh continuously but in a extremely short
  446. 20:07period of time which we cannot observe.
  447. 20:10So we need to add delays to to these
  448. 20:13assignments in order to be able to
  449. 20:15observe this. So
  450. 20:18let's add a delay. Okay. So we have a
  451. 20:22problem here. If we actually execute
  452. 20:25this, this while loop starts, then the
  453. 20:28song volume changes its value from song
  454. 20:31volume med. And all these changes happen
  455. 20:34just 30 milliseconds after I execute
  456. 20:37this script. So we want to increase this
  457. 20:40delay at every iteration. In order to do
  458. 20:43that, I'm going to create another
  459. 20:45variable integer. Let's say counter
  460. 20:48equals zero. I'm going to multiply this
  461. 20:51with counter.
  462. 20:53So initially this will be with delay
  463. 20:55zero. So the song volume will be sent
  464. 20:58right away. But if I increase counter as
  465. 21:01well equals counter + one, the next
  466. 21:06iteration will be 30 mconds. The next
  467. 21:08iteration will be 60 mconds. So you get
  468. 21:10the point. So I press I compile it and
  469. 21:14let's see what happens. So I'm changing
  470. 21:16the volume as you see.
  471. 21:20Even if I So for example, I'm slightly
  472. 21:22moving my slider.
  473. 21:25So 30 milliseconds seems to be a bit
  474. 21:28slow. Let's turn it change it into 10
  475. 21:31milliseconds.
  476. 21:33So, I'm moving my slider drastically,
  477. 21:36but it's always
  478. 21:39going smoothly except there is a small
  479. 21:42slight problem happening here. So, you
  480. 21:44you so I'm moving my slider all and all
  481. 21:47just increasing and decreasing. You
  482. 21:50start seeing these jumps around. So, why
  483. 21:53do these jumps happen?
  484. 21:55The problem is
  485. 21:57this translator starts working as soon
  486. 22:01as it receives a control change value
  487. 22:03different than the song value. Then it
  488. 22:05goes through this iteration with these
  489. 22:06delay triggers. These delay triggers
  490. 22:09goes into a stack into a delay stack so
  491. 22:15to say and they they keep they they're
  492. 22:18executed
  493. 22:20with these delays. But the problem is if
  494. 22:22I keep changing my control change value
  495. 22:25more delays will start appearing. So for
  496. 22:28example I song volume is for example
  497. 22:31zero in mid strong med is zero and I
  498. 22:33send control change value 100. These
  499. 22:36loops starts happening and these
  500. 22:38assignments are put into the delay stack
  501. 22:41and starts operating. But but while
  502. 22:45these are still executing I change the
  503. 22:47control change value to like say 20.
  504. 22:50they they will still keep executing.
  505. 22:53These will still keep executing.
  506. 22:55Now what I need to do is as soon as this
  507. 22:58translator receives another control
  508. 23:00change value, I need to cancel all the
  509. 23:04existing delays. Now we have some
  510. 23:07special functions to perform that. If I
  511. 23:10go to actions here,
  512. 23:13you can see this cancel all delay
  513. 23:15triggers, cancel all delay triggers with
  514. 23:17index, cancel delete group triggers.
  515. 23:20We're going to talk about group triggers
  516. 23:22and all triggers later when we talk
  517. 23:23about non-local variables. Right now,
  518. 23:26we're interested in cancel delay
  519. 23:28translated triggers or cancel delay
  520. 23:30translated triggers with index. Let's
  521. 23:33start with this one. Cancel
  522. 23:36uh delayed translator triggers. So
  523. 23:38translator means this translator when uh
  524. 23:42this is executed whatever
  525. 23:45delay triggers are in the stack they are
  526. 23:48all cancelled all the drill triggers
  527. 23:50that are produced in this translator
  528. 23:52will be cancelled will will just vanish
  529. 23:55and then the new function start
  530. 23:57executing so if I now test my function
  531. 24:01test this translator so even if I
  532. 24:05drastically change the knob here
  533. 24:09it doesn't jump around. It just goes
  534. 24:11smoothly. So yeah, that's how we cancel
  535. 24:14uh existing delay triggers. Now there is
  536. 24:17another one that I want to talk about
  537. 24:20delay triggers with index. So let's say
  538. 24:23I choose index 2. Right now if I try to
  539. 24:27do this, it doesn't work. That cancel
  540. 24:30function doesn't work. And we still have
  541. 24:32these strange jumps all around because
  542. 24:35we didn't add an index to this delay. So
  543. 24:38if we go to cheat sheet and go to
  544. 24:41functions
  545. 24:43and check delay, it adds an delay to the
  546. 24:46execution of the line can have one or
  547. 24:49two parameters. So at right now we only
  548. 24:52have only one parameter which is the
  549. 24:54delay amount. The second parameter is
  550. 24:56the index of the delay. So we can add an
  551. 24:58index to this delay. this f this trigger
  552. 25:01actually. So if I choose two here
  553. 25:06and suppose in this function uh in this
  554. 25:08script we have another delay somewhere
  555. 25:10else and we don't want to cancel those
  556. 25:12delays. We just want to cancel these
  557. 25:13specific delays here with this uh index.
  558. 25:16So right now cancel direct trans uh
  559. 25:19delay translated triggers with index two
  560. 25:21will cancel all the delays inside this
  561. 25:25script with index two. So right now it
  562. 25:28works. So you see we don't have any
  563. 25:30jumps around.
  564. 25:35Next we talk about arrays. So arrays are
  565. 25:38collection of variables of of the chosen
  566. 25:41types. So if we go to cheat sheet and
  567. 25:43variable types you see we have the basic
  568. 25:46types and their array versions and we
  569. 25:49also have non-basic types and there so
  570. 25:50all types have array versions of them.
  571. 25:53So let's just give a simple example. int
  572. 25:55array let's say a okay how do we create
  573. 26:00an array we have that we have various
  574. 26:04ways to create arrays but the most
  575. 26:06convenient one is the list function we
  576. 26:09have the list here in functions the list
  577. 26:11function takes a bunch of uh val values
  578. 26:15and then output is the array type of of
  579. 26:18that variable so for for this we need to
  580. 26:20add integers so let's say 2 6 minus - 3
  581. 26:2689 and so on so forth. So but if we add
  582. 26:32another type here false for example a
  583. 26:35boolean type we get an error all
  584. 26:37parameters should have the same type
  585. 26:39which is in in area type or for example
  586. 26:43if
  587. 26:44we start adding like a different type
  588. 26:47like strings here okay all the types
  589. 26:50match with each other but it doesn't
  590. 26:51match with here so type mismatch. So
  591. 26:54let's view this uh in our
  592. 26:58log print a. By the way this language is
  593. 27:04case insensitive. So I created this as a
  594. 27:08capital A but it doesn't matter. I could
  595. 27:10have created this with lowerase A and in
  596. 27:13fact if I try to create another variable
  597. 27:15with lowerase A, we have an error and
  598. 27:19cannot be used as a variable name
  599. 27:20because the whole language is case in
  600. 27:23sense. we cannot use the same uh
  601. 27:25variable name even if it's lower case or
  602. 27:28upper case but if I try if I write type
  603. 27:30A here the autocomplete version will
  604. 27:33match with the initial variable name if
  605. 27:35I if I compile this so the input was
  606. 27:38note on and note off these are the
  607. 27:41indexes here index zero is 21 index one
  608. 27:45is six and so on and so forth now let's
  609. 27:48use these arrays in an example and we're
  610. 27:51going to talk about more about arrays
  611. 27:53and kind of they're different than the
  612. 27:56standard arrays in other language. This
  613. 27:57is actually a combination of arrays and
  614. 28:00dictionaries. Now in this example, I
  615. 28:02want to assign certain chords to certain
  616. 28:05nodes on my keyboard. So let's first
  617. 28:08create those chords as int arrays. Int
  618. 28:11array chord one. We cannot use numbers
  619. 28:15as variable names as well. Uh a chord.
  620. 28:18So for example, let's start with the
  621. 28:19major chord. the root
  622. 28:23third and the fifth
  623. 28:25and the second chord is the minor third
  624. 28:29and let's say we add the third chord is
  625. 28:31the power chord.
  626. 28:34So these are our three chords. Now I
  627. 28:37want to assign three notes on my
  628. 28:38keyboard. And whenever I press and hold
  629. 28:42one of those notes, for example, the
  630. 28:43note corresponding to chord one. I want
  631. 28:46all the other notes that I play on my
  632. 28:48keyboard playing the that chord. So
  633. 28:51right now I'm pressing the lowest note
  634. 28:53on my keyboard. And you see the note
  635. 28:54value is C2. So when I press C2 and hold
  636. 28:57it, when I play other notes on my
  637. 28:59keyboard, I want them to play major
  638. 29:01third chords based on that note. So I'm
  639. 29:05going to create another int array and
  640. 29:07I'm going to say this as current chord.
  641. 29:12Okay, currently this has zero elements.
  642. 29:16It doesn't have any elements. Now I want
  643. 29:18to change this current chord to one of
  644. 29:21these depending on the input number.
  645. 29:24Okay, we are both monitoring note and
  646. 29:26not off signals. This is important
  647. 29:27because we need both of them. Now if is
  648. 29:31not on. So let's start with this case.
  649. 29:33If we press the note, if our note
  650. 29:37equals comparison C2. Okay, what is the
  651. 29:42integer value of C2? It doesn't matter.
  652. 29:44I can just write type C2 here. This is
  653. 29:47one of the neat features of key stage
  654. 29:49scripting language. So we can actually
  655. 29:51use these note numbers uh anywhere in
  656. 29:54our calculations. So if it's C2, then
  657. 29:57current chord
  658. 30:00equals to chord one. So the this current
  659. 30:03code becomes chord one.
  660. 30:06Else if current value is C# 2. When I
  661. 30:10press enter, these brackets
  662. 30:12automatically appear.
  663. 30:14Current chord is chord 2. Note value
  664. 30:18equals D2. Then current chord equals
  665. 30:22chord three. Okay. Well, what about the
  666. 30:24other num other values? Else else we
  667. 30:27want to play the chord. So as long as we
  668. 30:29keep holding the notes, we want to play
  669. 30:31the chord. We have our current chords.
  670. 30:34What do what do we need to do? We need
  671. 30:36to go through the these pitch shifts on
  672. 30:40on the on the current chord and then add
  673. 30:42that those pitch shifts to this note
  674. 30:44value. Now I'm going to use my other
  675. 30:46loop function to demonstrate it. The for
  676. 30:49loop. The for loop has a special syntax
  677. 30:51and it has some neat features. for index
  678. 30:56actually let's say pitch it
  679. 31:00in current course
  680. 31:04now what happens here is whenever I
  681. 31:07write this line this variable this
  682. 31:10integer variable pitch shift is created
  683. 31:13and then it start iterating with through
  684. 31:16the values of the current code. Now one
  685. 31:18thing that we need to note about this
  686. 31:20scripting language is unlike other
  687. 31:22languages the scores of these variables
  688. 31:25are not bound to these curly brackets.
  689. 31:28So normally in in any language basically
  690. 31:31in C, C++ whatever whenever I create a
  691. 31:34variable inside a for loop or inside any
  692. 31:36curly brackets the scope of this
  693. 31:38variable are bound to these these curly
  694. 31:40brackets and outside these curly
  695. 31:42brackets we don't see this variable. We
  696. 31:43have to either redeclare it or not use
  697. 31:45it at all. But in this language pitch
  698. 31:48shift can be accessed through everywhere
  699. 31:50inside the script in inside the scripts.
  700. 31:52So this is something that you need to
  701. 31:54keep in mind. So we go through the
  702. 31:57pitches of the current note. I'm going
  703. 31:58to send MIDI notes with those pitch
  704. 32:00shifts. Note on. So we are in the note
  705. 32:03on zone. We send note on. Okay. What am
  706. 32:06I sending? I'm sending the original note
  707. 32:08value plus the pitch shifts and with
  708. 32:11original. Okay. I don't want to test
  709. 32:13this right now because I haven't
  710. 32:15actually done anything related to note
  711. 32:17off. We're going to have stock notes if
  712. 32:18I if I try to play this right now. Let's
  713. 32:21do some de debugging lines here. I'm
  714. 32:24going to print current chord here.
  715. 32:27Actually, I want to just do this print
  716. 32:30after I make the changes. I I press C1.
  717. 32:33Actually, I need to compile it. I press
  718. 32:35C1 and we get the major chord. I press
  719. 32:38C2, we get the minor chord. I press C3,
  720. 32:41we get the power chord. And right now
  721. 32:44the current chord is power chord. Okay.
  722. 32:46Now what happens if I release my notes
  723. 32:49else? So when I release the notes one of
  724. 32:53these C, C sharp and D2 notes, uh I want
  725. 32:57to just cancel the whole thing. So what
  726. 33:00do you what does it mean to cancel? I
  727. 33:02don't want to play any any chords. I
  728. 33:03just want to play regularly. Okay. So I
  729. 33:05need to add some additional variables to
  730. 33:08test to check certain things.
  731. 33:10I want to keep track of uh last pressed
  732. 33:15note.
  733. 33:16I want to keep track of the last pressed
  734. 33:18note here as long as it's one of these
  735. 33:20values. So if it's C2, last press note
  736. 33:24is equal to well note value. It's C2. So
  737. 33:27I'm just going to copy and paste this.
  738. 33:30So we keep track of the last press note
  739. 33:32here. One of these three nodes. And I
  740. 33:35want to check the following. When I
  741. 33:37release the note, if it's the last press
  742. 33:39note, I just want to cancel everything.
  743. 33:41I don't want to play a chords anymore.
  744. 33:43So, if not value equals last press note.
  745. 33:48So, how do we cancel? I am just going to
  746. 33:51remove all the pitch shift inside this
  747. 33:53current chord. How do we do that? We're
  748. 33:55going to talk about uh variable
  749. 33:58properties after we talk about other
  750. 34:00variable types. But right now, we I I
  751. 34:03just need to dive into this. Different
  752. 34:05types have different properties. Array
  753. 34:07is one of them. Uh without going into
  754. 34:09too much details, we have remove all
  755. 34:12objects action property of an array. So
  756. 34:14this is like an action applied to that
  757. 34:17specific array. Action property means
  758. 34:19that. So how do we do that action?
  759. 34:22Current dot remove all objects. So this
  760. 34:27is an action property. And when this
  761. 34:29line gets executed, the current code
  762. 34:31becomes just an empty code. Let's test
  763. 34:34this. Let's print current code here. Uh
  764. 34:37let's do the following. Let's also write
  765. 34:40print note release. And at the end of
  766. 34:44note on, we also add some print
  767. 34:46functions current.
  768. 34:48So let's try to debug this. Let's clear
  769. 34:51the log. I press C1 note pressed and I
  770. 34:54release. We got an empty array. So these
  771. 34:57logs keeps adding to the log. I can
  772. 35:01clear the log here. But we have a simple
  773. 35:02function if if you don't want to do this
  774. 35:05manually clear lock. So we have this
  775. 35:08action not function. So right now these
  776. 35:12logs do not add uh after another. Okay
  777. 35:16we have this print function. So we
  778. 35:18release all the current codes. Okay. But
  779. 35:20now when this is empty we have a problem
  780. 35:23here. We don't want to go through this
  781. 35:25iteration anymore because this is now an
  782. 35:27empty set an empty array. So we need to
  783. 35:30add a little check here. If current cord
  784. 35:34count. So this is another property which
  785. 35:37is the number of elements in inside that
  786. 35:39array equals zero. If it's empty, let's
  787. 35:43also do the add function. So if it's non
  788. 35:47empty, we go through this the pitch
  789. 35:49shifts. But if it's empty, I just want
  790. 35:51to send the original signal incoming med
  791. 35:54data. And here if we release the note we
  792. 35:57empty the current chord. Okay. But what
  793. 36:00what if we are on other notes else? Now
  794. 36:03we have to send the corresponding note
  795. 36:06of signals. Whether we are playing a
  796. 36:08chord or we are playing a single note.
  797. 36:10We have to send the corresponding note
  798. 36:11of signal. So we do the same thing here
  799. 36:13except we send note of signal instead of
  800. 36:15note on. So we just copy paste this
  801. 36:18whole line and we just change this to
  802. 36:21off. Okay. If I haven't skipped any
  803. 36:24step, this should work now. Let's Let's
  804. 36:26check.
  805. 36:32That's why we can't hear it.
  806. 36:34So, right now, I'm not I'm not pressing
  807. 36:36one of these special buttons. Let's
  808. 36:38actually open the editor. And
  809. 36:42now I'm pressing and holding
  810. 36:46C C2. I release C2. Now I'm pressing
  811. 36:51holding D2 sorry C sharp two we have the
  812. 36:55minor
  813. 36:57and we have the power chords.
  814. 37:03So that's how it works. So before I
  815. 37:05continue I want to talk about a couple
  816. 37:06of important points about local
  817. 37:09variables and their persistencies. So
  818. 37:13this is a tricky topic. So you realize
  819. 37:16that this last press node is initialized
  820. 37:18here but its value is retained through
  821. 37:21different iterations of this of the
  822. 37:23execution of this script editor. These
  823. 37:25local variables are created at the
  824. 37:27beginning of the compile and when we run
  825. 37:30key stage all the scripts are compiled
  826. 37:32automatically. those variables are
  827. 37:34created and that their values just
  828. 37:36retain as long as the the custom
  829. 37:38translators are not deleted until we
  830. 37:41move to another song or close key stage
  831. 37:43and then we reopen key stage their
  832. 37:45values are reseted again. So this is how
  833. 37:48the local variables work that that also
  834. 37:51works for arrays or integers or any
  835. 37:54type. But there is one exception here.
  836. 37:56The exception is when I create either a
  837. 37:59slider or switch. Let's actually also
  838. 38:02talk about switch here. So the switch
  839. 38:05variable controls boolean variables. Uh
  840. 38:08let's choose B boolean B. And I want to
  841. 38:11create a switch. Name it anything. I'm
  842. 38:15controlling the value variable B and we
  843. 38:18don't have upper and lower values for
  844. 38:20switches. So for switch creating
  845. 38:22switches we have a name and the variable
  846. 38:25that we're controlling. So this switch
  847. 38:27the value of this is retained or is
  848. 38:30stored inside this custom translator and
  849. 38:33even if we close keystage and reopen it
  850. 38:35this value will reappear and the same
  851. 38:38goes true with the uh sliders. So this
  852. 38:40is really important because when you
  853. 38:42create a custom translator and create
  854. 38:44some sliders here, you you assign
  855. 38:47certain values of to those sliders and
  856. 38:49switches and you want those values to
  857. 38:52retain between iterations of keystage or
  858. 38:54when you load different songs, you want
  859. 38:56those values to stay. So if a variable
  860. 39:00is assigned to a switch or slider, their
  861. 39:03values are stored in the custom
  862. 39:05translators, but otherwise their values
  863. 39:08only retain as long as that custom
  864. 39:09translator is active. We switch to
  865. 39:12another song and then back to the
  866. 39:13original song. No values, those values
  867. 39:15are reseted. So this is the persistency
  868. 39:18of values of local variables. One other
  869. 39:20thing that I want to talk about before I
  870. 39:22talk about the dictionary aspect of
  871. 39:24arrays uh I want to talk about this
  872. 39:27print function. So we have you realize
  873. 39:29that we added two lines here. But if I
  874. 39:33go into operators and look at plus we
  875. 39:37have a special case that I talked about
  876. 39:39before. This operator can be used
  877. 39:41between a string and any other object.
  878. 39:43The result is a string. So instead of
  879. 39:45doing this I can actually do the
  880. 39:47following. I add plus current chord.
  881. 39:50Let's do the same thing for note pressed
  882. 39:53instead of that I'm going to add plus
  883. 39:56current chord. So when I will press a
  884. 39:59note press one of these special notes.
  885. 40:02You see in the debugger we have not
  886. 40:04pressed a space and the value of the
  887. 40:07chord. So there's an space automatically
  888. 40:09added between each items here. So as
  889. 40:12long as one of these items is a string,
  890. 40:14the plus function basically adds the
  891. 40:17string version of the variable to the
  892. 40:19end of the first string. So let's talk
  893. 40:21about the dictionary aspect of array. So
  894. 40:23as I said the arrays here in key stage
  895. 40:25are not the simple arrays that you see
  896. 40:28in other languages. So let's create an
  897. 40:31int array. As long as we create an array
  898. 40:33and let's say we initialize it with list
  899. 40:36and print it, you can see the indexes
  900. 40:39here. So this is not just a a set of
  901. 40:42objects next to each other. We have
  902. 40:44indexes which means that this is
  903. 40:46actually a dictionary with integer keys
  904. 40:49technically speaking. So what we can do
  905. 40:51here is for example a we have a special
  906. 40:55notation here a5.
  907. 40:58We assign a number to the fifth index of
  908. 41:01a. So if I print a here let's delete
  909. 41:05this line. You see we added a new index
  910. 41:08here five. So we're skipping index three
  911. 41:10and four and we add index five. So this
  912. 41:12is not just a sequence of numbers. This
  913. 41:15is actually a set of numbers with
  914. 41:17indexes. So these arrays can be used as
  915. 41:19dictionaries. I'm not going to give a
  916. 41:21concrete example here but I'm just going
  917. 41:23to give a a case where you can use it.
  918. 41:26And we're going to be using a special
  919. 41:28variable which is press notes and press
  920. 41:31note velocities. These are arrays. You
  921. 41:33can see these are integer arrays which
  922. 41:35consists of the nodes that are entering
  923. 41:37into the into this translator. It
  924. 41:40doesn't matter whether we have a note
  925. 41:41input or any other input. These
  926. 41:45variables always change as long as we
  927. 41:47press note signals and those note
  928. 41:49signals goes into this script into this
  929. 41:52translator. So for example, if you
  930. 41:54monitor press notes, okay, the problem
  931. 41:57is we need to we need to send pitch
  932. 41:59signals to be able to trigger this
  933. 42:01translator. I'm holding three notes and
  934. 42:03when as I send pitch signals I can
  935. 42:06monitor the press notes that I'm
  936. 42:08pressing right now. So that's press note
  937. 42:10but for example at some point I may need
  938. 42:12to create a variable an integer array
  939. 42:17where the indexes are nodes and the
  940. 42:19values are velocities. For example, int
  941. 42:22array a. I'm going to go through the
  942. 42:25indexes of the press notes for index in
  943. 42:30press notes indices. So press nodes is a
  944. 42:34set of nodes and index starts from 0 1 2
  945. 42:363 depending on how many notes we're
  946. 42:39pressing. But we have another special
  947. 42:41variable press not velocities. So what
  948. 42:43I'm going to do here a press note index.
  949. 42:47Now we're getting the value the note
  950. 42:49value and use it as the index of a
  951. 42:52equals press notes velocities. We use
  952. 42:55the same index because they match the
  953. 42:58indices on the press notes velocities
  954. 42:59and press notes match. And if we print
  955. 43:03this now actually let's change this to
  956. 43:07notes. Okay, we have an error. Yeah, of
  957. 43:08course we haven't printed a yet. We we
  958. 43:12don't hear anything because we we are
  959. 43:14not sending any med signals when we
  960. 43:17press not. So I press a note. Huh? Okay.
  961. 43:21We are not resetting a. So we need to
  962. 43:23add a remove all object. So we want to
  963. 43:26just empty a at every iteration. So
  964. 43:29right now I pressed a note the note 81
  965. 43:32and it velocity.
  966. 43:39So right you see the indexes are note
  967. 43:41values and the velocities are so this is
  968. 43:44like a mapping. So we can use arrays as
  969. 43:47dictionaries or mappings. So speaking of
  970. 43:50the dictionary aspect of arrays there is
  971. 43:52an important function uh that I want to
  972. 43:55talk about actually a variable property
  973. 43:58again for arrays reindex. This is really
  974. 44:02important one because as I said arrays
  975. 44:05are dictionaries with indexes. Reindexes
  976. 44:08basically removes all empty indexes and
  977. 44:10then just squeeze the remaining values
  978. 44:14starting from zero preserving their
  979. 44:16order. So let's actually show you what
  980. 44:19what I mean. Of course in this example
  981. 44:21it's kind of weird. So let's actually
  982. 44:23create another example here. Int array a
  983. 44:27let's say a 1 equals something. Then we
  984. 44:33have a different index a 4 equals choose
  985. 44:36another number and a let's say 67
  986. 44:41equals -24.
  987. 44:44Okay. So if we print this we have index
  988. 44:47one corresponds to this index 4 and
  989. 44:49index uh 67. Now if we say a reindex and
  990. 44:55then print it again one becomes zero
  991. 44:57four becomes one 67 becomes two. So the
  992. 45:00all the empty indexes are removed and
  993. 45:02then this becomes a basic array.
  994. 45:04Reindexes means that it converts a
  995. 45:06dictionary into an array in in in some
  996. 45:09way. We also have functions like add or
  997. 45:11add to the beginning. So when add
  998. 45:13function adds an object to the end of
  999. 45:15the array and then automatically
  1000. 45:16reindexes. So when you add you lose all
  1001. 45:19the information about indices and you
  1002. 45:21just have a basic array with indexes
  1003. 45:23starting from 0 1 2 3 and so on. You
  1004. 45:26have to really read these descriptions.
  1005. 45:28And the remove functions also remove
  1006. 45:30first object, remove last object also
  1007. 45:32reindexes. Remove object at index
  1008. 45:35doesn't reindex. So when we remove a
  1009. 45:37specific index, we don't lose the index
  1010. 45:39information. And we can also sort these
  1011. 45:42arrays with ascending or descending
  1012. 45:44order depending on their values and also
  1013. 45:47they it's reindexed. So you have to be
  1014. 45:49careful while you're using these
  1015. 45:51properties. If you are using your array
  1016. 45:54as dictionary, I suggest that you don't
  1017. 45:56use these properties. You use them if
  1018. 45:58you're using this as pure arrays. Before
  1019. 46:01I move on to the next topic, I want to
  1020. 46:03talk about two more things which are
  1021. 46:04also related to arrays. So remember when
  1022. 46:06we write media out, we had this incoming
  1023. 46:10media data that we we wrote before and
  1024. 46:13this was basically the med signal from
  1025. 46:14the incoming nodes. Okay, but what is
  1026. 46:16this incoming med data? If you look at
  1027. 46:18it, it's the special variable with int
  1028. 46:21array. So it's an integer array. Okay,
  1029. 46:23what does this integer array contain?
  1030. 46:25Let's print it incoming metadata. It's
  1031. 46:28an array with three integers and as you
  1032. 46:31guessed it's a med signal with three
  1033. 46:32bytes. So this represents the bytes of
  1034. 46:35the med signal. So as you know
  1035. 46:38144 which is 90 in hexodimal form stands
  1036. 46:44for not signal and 128 which is 80 in
  1037. 46:47hexodimal stands for not signal. The
  1038. 46:49second bite is the note value. So keep
  1039. 46:52changing and the last one is the
  1040. 46:53velocity value as you know. So the
  1041. 46:55incoming med data is the array of MIDI
  1042. 46:58signal. So this also gives us one more
  1043. 47:01clue. MIDI out normally we have these
  1044. 47:04MIDI types that we keep writing or
  1045. 47:06incoming med data. But we can actually
  1046. 47:08put any array here any integer array
  1047. 47:11here. As long as that integer array
  1048. 47:13represents a MIDI signal media out just
  1049. 47:15works. So we can actually write lists
  1050. 47:18something like 144 let's say 65 and 100.
  1051. 47:24So this is a noton signal with note
  1052. 47:26value 65 and with velocity 100. We can
  1053. 47:28actually send med signals like that. And
  1054. 47:30speaking of that we also have an
  1055. 47:33important notation to represent that
  1056. 47:35notation. I want to talk about system
  1057. 47:37exclusive messages. So you know the
  1058. 47:39system exclusive messages starts with f0
  1059. 47:42and ends with f7. So let's actually read
  1060. 47:44that uh again print incoming metadata
  1061. 47:48real value of f0 is 240 and f7 is 247.
  1062. 47:54So we can send system exclusive messages
  1063. 47:57like that but we can actually write them
  1064. 47:59in hexodimal form. So let's let me show
  1065. 48:02you. We can actually create an int array
  1066. 48:06for example
  1067. 48:07cis x message.
  1068. 48:09Yeah I'll just write cis x. I'm going to
  1069. 48:12create a list. Let's say the first bite
  1070. 48:14is so instead of writing uh 140 I'm
  1071. 48:20going to write 0 x f0. So we can
  1072. 48:25actually write hexadimal notations
  1073. 48:28anywhere. Again it doesn't have to be
  1074. 48:30just for since system exclusive message.
  1075. 48:33It can be any message. So let's say 0 x
  1076. 48:38I don't know a3
  1077. 48:40and let's finish it with 0 x f7 and if I
  1078. 48:46print this this is an exclusive message
  1079. 48:49so we are okay we are printing two the
  1080. 48:51first one is the incoming signal the
  1081. 48:53second one as you see it starts with the
  1082. 48:55240 and ends with 247
  1083. 48:58so we can write system exclusive
  1084. 49:01messages by hand using hexodimal
  1085. 49:03notation if we
  1086. 49:08Now let's talk about non-local
  1087. 49:10variables. So non-local variables are
  1088. 49:12really important when we want to have
  1089. 49:14multiple custom translators working
  1090. 49:16together. So let's start with creating a
  1091. 49:18custom translator. Now we have this
  1092. 49:21button called non-local variables. Okay,
  1093. 49:24group variables, layer variables, strong
  1094. 49:26variables and global variables. So we
  1095. 49:27have four types of non local variables.
  1096. 49:30And so what is a group variable? And
  1097. 49:33when I tap here, create a new group
  1098. 49:34variable. These are the eight basic
  1099. 49:37types that we have the four basic types
  1100. 49:39and their array versions. So we can
  1101. 49:41create uh let's say an integer variable
  1102. 49:44called test. We can actually see the
  1103. 49:46same variables here when we so let's
  1104. 49:49create another translator here. When we
  1105. 49:52tap the output, this is this variables
  1106. 49:54part and also the same goes as variables
  1107. 49:57change in the input and we can actually
  1108. 49:59see the variable test here as integer.
  1109. 50:02Even if we are now on a different custom
  1110. 50:04translator, we can see the variable that
  1111. 50:06is created here. Group means all the
  1112. 50:08translators in in this line here. For
  1113. 50:11example, if we're in a parts, the
  1114. 50:13translators here form a group. We if
  1115. 50:15we're in song translators. So you see
  1116. 50:17the point that the group is the
  1117. 50:19translators that are working next to
  1118. 50:20each other in whatever object they are
  1119. 50:23in. For example, whether they're in a
  1120. 50:24part or in a track or in a media LIS, it
  1121. 50:27doesn't matter. Group means that. So for
  1122. 50:29example, this translator can see test
  1123. 50:32but the translators here can't see test
  1124. 50:35here. For example, we can create the
  1125. 50:37same variable name test here but with a
  1126. 50:40different type. So in in this part the
  1127. 50:43test variable that we created here is of
  1128. 50:46type float array. Whereas in this track
  1129. 50:50the variable even if we use the same
  1130. 50:53name is now an integer. So you see the
  1131. 50:55point the variable group variables are
  1132. 50:58uh can be accessed by custom translator
  1133. 51:01in the same group. But if we create by
  1134. 51:03the way we can also create variables
  1135. 51:05here. If you create song variable for
  1136. 51:07example let's choose a variable with
  1137. 51:10boolean array.
  1138. 51:13Now this variable can be accessed
  1139. 51:16anywhere in the song in this song. So if
  1140. 51:18I type variable change song variable can
  1141. 51:21be accessed here. We can delete those
  1142. 51:23variables just as we delete anything.
  1143. 51:26Let's delete both the group and song
  1144. 51:28variable. The group variables I I
  1145. 51:30already described. Layer variables are
  1146. 51:32the variables that can be accessed from
  1147. 51:34within this layer. The those layer
  1148. 51:37variables can also be used in the layer
  1149. 51:39translators. But from any other layer,
  1150. 51:41you can't see the layer variables
  1151. 51:43created in this layer. And the next step
  1152. 51:45is the global variables. Global
  1153. 51:46variables are variables that can be
  1154. 51:48accessed from anywhere inside keystage,
  1155. 51:51even from other songs. So those
  1156. 51:53variables, we're going to give an
  1157. 51:54example about global variables. Global
  1158. 51:57variables can even be used inside media
  1159. 52:00aliases since these are global objects
  1160. 52:02as you know. So if you create custom
  1161. 52:05translators inside these aliases and you
  1162. 52:07want them to communicate with other
  1163. 52:09translators in the song or anywhere, you
  1164. 52:12can use global variables. And in any
  1165. 52:14song, these global variables work. But
  1166. 52:16for now, in our example, we are focused
  1167. 52:18on group variables. These are the the
  1168. 52:21ones that you probably will use most
  1169. 52:23common. So in our example, we want to
  1170. 52:26have something like an arpeggiator. Not
  1171. 52:28exactly an arpeggiator, but a repeating
  1172. 52:31note functionality using custom trans.
  1173. 52:34So when I press a note, I want that note
  1174. 52:37or when I press a chord, I want that
  1175. 52:39chord to keep repeating with with a
  1176. 52:41certain period until I release the
  1177. 52:43notes. So this is what I want to
  1178. 52:45achieve. And I need more than one custom
  1179. 52:47translator to be able to achieve that.
  1180. 52:48And I need those translators to
  1181. 52:51communicate with each other using group
  1182. 52:53variables. So first we need since we're
  1183. 52:56talking about nodes, we want to create a
  1184. 52:58translator with node inputs. Remember we
  1185. 53:01talked about a special variable called
  1186. 53:03press notes here and press notes
  1187. 53:05velocities and actually channels are
  1188. 53:07also stored on another special variable.
  1189. 53:09But I don't care about channels right
  1190. 53:11now since my keyboard only send notes
  1191. 53:13from channel zero. Okay, these press
  1192. 53:16nodes can be accessed through this
  1193. 53:18custom translator. But the problem is I
  1194. 53:21am going to need another translator here
  1195. 53:24and I'm going to need those press nodes
  1196. 53:26in this translator. The problem here
  1197. 53:29what I so here's the structure that I'm
  1198. 53:31going to do in this translator I want to
  1199. 53:34store those notes and whether not
  1200. 53:37pressed or not and I want to pass that
  1201. 53:39information to this translator and this
  1202. 53:41translator will keep repeating those
  1203. 53:43notes over and over again. So what I
  1204. 53:46need is I need to store those press
  1205. 53:47notes. This is the first step and I need
  1206. 53:50to have integer variables which are
  1207. 53:53group variables because I need the other
  1208. 53:55translator to access those variables. So
  1209. 53:58I'm going to name current nodes instead
  1210. 54:01of press node. I'm going to use this
  1211. 54:03this name and I'm going to create
  1212. 54:05another one to keep track of their
  1213. 54:07velocities. Current node velocities
  1214. 54:11current node velocities. So I'm going to
  1215. 54:13store
  1216. 54:15the press notes information in these
  1217. 54:18global group variables. Okay. Why do we
  1218. 54:21have a type mismatch? Current not
  1219. 54:23integers. Yeah, we actually didn't
  1220. 54:24create integer arrays. We create
  1221. 54:26integers. So let's let's correct that.
  1222. 54:33Okay. So yeah, I corrected. Uh so these
  1223. 54:37are now integer variables, integer
  1224. 54:39arrays. and current node velocities is
  1225. 54:45pressed node velocities. So we store
  1226. 54:46those information. Okay. Now I'm going
  1227. 54:50to create a boolean variable this time
  1228. 54:52again a group variable and call it uh
  1229. 54:57there is
  1230. 54:59a press note.
  1231. 55:02So I created this boolean variable. So
  1232. 55:03here's what I'm going to do. If not
  1233. 55:07is on. If we're on nodes, if there isn't
  1234. 55:11a pressed note, so this is the uh
  1235. 55:14boolean negation. If there isn't a
  1236. 55:16pressed node, we want that to be true.
  1237. 55:20And when we release the note, okay, when
  1238. 55:23we release a node, we need to check the
  1239. 55:25number of notes that are currently
  1240. 55:26pressed. If it's the last note that we
  1241. 55:30release, then press notes count has to
  1242. 55:33be equal to zero. If it's a zero, we
  1243. 55:37forgot to add if. If it's zero, then
  1244. 55:41we'll make this variable false, which
  1245. 55:44means that we are no longer pressing any
  1246. 55:46notes here. We're also going to use this
  1247. 55:49uh boolean variable in in the other
  1248. 55:52translator. Okay. So, right now we're
  1249. 55:55keeping track of notes. We're keeping
  1250. 55:56track of whether there is a press note
  1251. 55:58or not. Now we need to start triggering
  1252. 56:02the next translator here. To be able to
  1253. 56:05do that, we're going to be using another
  1254. 56:07global variable to trigger that. Now the
  1255. 56:10type of variable here doesn't matter.
  1256. 56:13I'm just going to choose boolean. I'm
  1257. 56:14going to talk why. I'm going to talk
  1258. 56:17about why. We don't need to choose
  1259. 56:19boolean or we can choose any other
  1260. 56:21variable here. So I'm going to call this
  1261. 56:24trigger notes. This is like an action
  1262. 56:27instead of a variable. So when do I want
  1263. 56:30to trigger it? I want to trigger it when
  1264. 56:33when we first pressed a node. When while
  1265. 56:35there was no notes, this becomes true.
  1266. 56:37And I want to trigger the other
  1267. 56:39translator. So I'm going to just change
  1268. 56:42the value to anything I want. It doesn't
  1269. 56:45matter whether this is true or false
  1270. 56:47because here's what I'm going what I'm
  1271. 56:49going to do. So this is our first
  1272. 56:50translator. Let's turn this basic. Now
  1273. 56:53variable changed group variable trigger
  1274. 56:57notes trigger notes changed I don't care
  1275. 57:00whether it turned into false or true I
  1276. 57:02just want to trigger this translator
  1277. 57:04when we first pressed a note because why
  1278. 57:07am I doing this when I first press a
  1279. 57:10note I want the the loop to start but
  1280. 57:13when I press a second note I don't want
  1281. 57:15to re-trigger it I just want the loop to
  1282. 57:17continue with the currently pressed not
  1283. 57:19I don't want to trigger it again that's
  1284. 57:21why I'm using this variable here. Okay.
  1285. 57:24When the trigger not starts, I want to
  1286. 57:27start a loop. So, when do I want to
  1287. 57:30start a loop? If
  1288. 57:33there's a press note, if there isn't a
  1289. 57:35any press notes, I don't want to start
  1290. 57:37any loop here. So, what I what do I want
  1291. 57:40to do? I want to play the notes, the
  1292. 57:43currently pressed notes. I want to send
  1293. 57:45the note on signals and then note off
  1294. 57:47signals after certain way like we did in
  1295. 57:49the stato. So, what am I going to do? I
  1296. 57:52need to go through for index in current
  1297. 57:57nodes indices because we still need the
  1298. 58:01values in the velocities the current
  1299. 58:03node velocities that's why we're going
  1300. 58:05through the indices not the values. So
  1301. 58:07for all these indices we want the note
  1302. 58:09value equals current nodes index and we
  1303. 58:14also need the velocity value current
  1304. 58:17node velocities
  1305. 58:19index. So we had a note and velocity in
  1306. 58:22this for loop. So we just going to send
  1307. 58:24the med notes media out note on channel
  1308. 58:28zero and I want to bother with channel
  1309. 58:30note and I want to send the note off
  1310. 58:33signal of the same note after certain
  1311. 58:35delay note of zero note velocity with
  1312. 58:41some delay. Let's say again 50
  1313. 58:44milliseconds. So right now we just play
  1314. 58:47one note. We're not really doing any
  1315. 58:49repetition here. Now, here is the
  1316. 58:51interesting trick. So, when does this
  1317. 58:53translator trigger? When trigger notes
  1318. 58:57change changes and as you see, we didn't
  1319. 59:00use the value of the trigger notes
  1320. 59:01inside. So, parameter shows the value of
  1321. 59:03the trigger notes. We didn't use
  1322. 59:04parameter here. But, so what I want to
  1323. 59:07do, I sent the note signals and not of
  1324. 59:09signals after certainly, but I want to
  1325. 59:11retrigger it after with with some
  1326. 59:13duration. So that duration will be the
  1327. 59:16repetition of period of my notes. So
  1328. 59:19what I'm going to do, I'm going to
  1329. 59:20re-trigger itself. So trigger notes
  1330. 59:23equals false. It doesn't matter whether
  1331. 59:26I choose false or true, but with with a
  1332. 59:28delay. And that delay, let's say 200
  1333. 59:30millconds. So right now, as long as I
  1334. 59:33have pressed nodes, we go into this
  1335. 59:35translator, we send the note signals and
  1336. 59:38there not of signals with delay. And
  1337. 59:41then after 200 millconds, we trigger
  1338. 59:43this again. And after 200 seconds we
  1339. 59:45trigger this again. But as long as there
  1340. 59:48is an press note when we release all the
  1341. 59:50notes we we we stop this loop. So let's
  1342. 59:52see how how this works now.
  1343. 59:57So you see I first press a note
  1344. 1:00:02and when I add a note to this
  1345. 1:00:06the they they just work parallel. Even
  1346. 1:00:10if I press the second note at a
  1347. 1:00:12completely different time
  1348. 1:00:16and I keep releasing the note and then
  1349. 1:00:18we So let's actually do uh
  1350. 1:00:22debugging. Let's just print something
  1351. 1:00:24here.
  1352. 1:00:26So
  1353. 1:00:30when I release all the notes, we were no
  1354. 1:00:32longer in this loop. Okay, let's improve
  1355. 1:00:35this. I want to control this delay, but
  1356. 1:00:38not with a slider on this custom
  1357. 1:00:40translator, but with my knob on my
  1358. 1:00:43keyboard. So, how do I do that? It's
  1359. 1:00:46simple. I'm going to assign another
  1360. 1:00:48variable to this delay. So, instead of
  1361. 1:00:51200, I'm going to create another group
  1362. 1:00:53variable. This time, an integer delay
  1363. 1:00:56amount. And I'm going to change this to
  1364. 1:00:59delay amount. Now, the problem is that
  1365. 1:01:00the delay amount is zero. When when it's
  1366. 1:01:03first created, the value is zero. So as
  1367. 1:01:06soon as I move to a part, I want to
  1368. 1:01:08reset that value to something. So here's
  1369. 1:01:11what I'm going to do. I'm going to
  1370. 1:01:12create another translator and choose
  1371. 1:01:16when section is activated. I want to
  1372. 1:01:19delay amount set delay amount. So you
  1373. 1:01:23see both input and output are
  1374. 1:01:25parametric. So that but I want a fixed
  1375. 1:01:28value for for this delay amount. Let's
  1376. 1:01:30say 40 uh let's say 50 milliseconds
  1377. 1:01:33actually. let's say 100 milliseconds. So
  1378. 1:01:37when we move to a section, this is resed
  1379. 1:01:39to 100 millconds. But now I want to
  1380. 1:01:41control this value, this parameter with
  1381. 1:01:43another custom translator. So we add one
  1382. 1:01:46last custom translator. We don't need a
  1383. 1:01:48script with this one either. I want to
  1384. 1:01:51use my control change 12 to control.
  1385. 1:01:54Okay, we have two ways to do that. I can
  1386. 1:01:58control the delay amount here. But if
  1387. 1:02:00you don't use scripts, we're bound to
  1388. 1:02:02these numbers 0 and 12 27. If you want
  1389. 1:02:07to go beyond those numbers, we actually
  1390. 1:02:09need scripts and we we have more control
  1391. 1:02:11over here now. So my control change
  1392. 1:02:13value here ranges between 0 and 120. But
  1393. 1:02:18I don't want those values. So I want
  1394. 1:02:22delay amount to be equal to let's say I
  1395. 1:02:25want my delay amount to be equal to
  1396. 1:02:29uh let's say 50
  1397. 1:02:31minimum plus
  1398. 1:02:34control change value. So right now this
  1399. 1:02:37ranges between 50 and 1777.
  1400. 1:02:40But if I multiply this let's say with
  1401. 1:02:43four. Now this ranges between some other
  1402. 1:02:46numbers. Let's see. Let's see on what
  1403. 1:02:48range what is the range play amount.
  1404. 1:02:53So it goes up to 558.
  1405. 1:02:57Now if I start
  1406. 1:03:02So I'm changing my knob. Changing to
  1407. 1:03:09H.
  1408. 1:03:11Okay. When I turn my knob all the way
  1409. 1:03:14down, we we're having some something
  1410. 1:03:16strange like the note cut off. Why is
  1411. 1:03:18that? Well, that's because the note of
  1412. 1:03:21signals delay amount is 50 like the
  1413. 1:03:23minimum amount. So, we have to actually
  1414. 1:03:25make it 40 less than 50 or maybe we
  1415. 1:03:28should change that 50 to something as
  1416. 1:03:29greater.
  1417. 1:03:32So, now my note controls the gaps, the
  1418. 1:03:35time gap between each note.
  1419. 1:03:42Okay, our final topic is non-basic
  1420. 1:03:45variables. This is a really advanced
  1421. 1:03:47feature which allows us to control
  1422. 1:03:49different aspects, different behaviors
  1423. 1:03:52inside Keystage and you can even use
  1424. 1:03:54scripts while you're editing your song.
  1425. 1:03:57Okay, if you go to cheat sheets, you see
  1426. 1:04:00we have these basic variables and we
  1427. 1:04:02have non-basic variables and you see the
  1428. 1:04:04names just are familiar like parts,
  1429. 1:04:06layer, track, translator and more will
  1430. 1:04:10be added to these variables as key stage
  1431. 1:04:12keeps evolving and we also have player
  1432. 1:04:15and the array versions of them as well.
  1433. 1:04:17Okay, so let's start by creating a track
  1434. 1:04:21variable for example. So track a
  1435. 1:04:25now there are two important distinction
  1436. 1:04:28between non-basic variables and basic
  1437. 1:04:30variables. The first one is non-basic
  1438. 1:04:33variables cannot be used as non-local
  1439. 1:04:36variables. They are always local
  1440. 1:04:37variables. We cannot use group variables
  1441. 1:04:40non-basic variables as group global or
  1442. 1:04:42song or layer variables. The second one
  1443. 1:04:44is whenever we create an integer it
  1444. 1:04:48automatically starts with the default
  1445. 1:04:49value which is zero. When we create a
  1446. 1:04:52string, it's an empty string. We always
  1447. 1:04:54have a value of the basic variable. For
  1448. 1:04:57non-basic variables, we don't have that.
  1449. 1:05:00When we create a track A, this is a
  1450. 1:05:02placeholder for an actual track inside
  1451. 1:05:05keystage, but currently it doesn't point
  1452. 1:05:08to any track and its value is nil. In
  1453. 1:05:11technical terms, its value is nil. And
  1454. 1:05:14this is true for all non-basic
  1455. 1:05:15variables. As soon as we create them,
  1456. 1:05:18they're actually pointers to actual
  1457. 1:05:20objects inside Keystage. And right now,
  1458. 1:05:22it doesn't hold any information. It
  1459. 1:05:24doesn't point to an actual track. Okay,
  1460. 1:05:26how do we make this point an actual
  1461. 1:05:28track? First of all, we cannot create an
  1462. 1:05:30actual track inside the scripting
  1463. 1:05:32language. We can only create tracks
  1464. 1:05:33here. And the same is true for all other
  1465. 1:05:36objects. So, we can only point to an
  1466. 1:05:38existing track here. So, how do we do
  1467. 1:05:41that? So our special variables is the
  1468. 1:05:44way that we access those actual objects.
  1469. 1:05:47So for example, so by the way there is a
  1470. 1:05:49filter here in all these. If I say
  1471. 1:05:51track, we have two special variables,
  1472. 1:05:54all tracks and current track. Okay. Uh
  1473. 1:05:58all tracks is kind of obvious and all
  1474. 1:06:00track is a special variable of track
  1475. 1:06:01array. So we can access all tracks and
  1476. 1:06:03put them in a track array. Okay. What is
  1477. 1:06:06current track? Current track actually
  1478. 1:06:08depends on where the custom translator
  1479. 1:06:10is. Well, since it's on a track, it's
  1480. 1:06:12obvious this we're talking about this
  1481. 1:06:14track as the current track. While we're
  1482. 1:06:16on a part, for example, this part, we're
  1483. 1:06:18talking about again this track connected
  1484. 1:06:20to that track. But on all other cases,
  1485. 1:06:22for example, if you create a custom
  1486. 1:06:24translator here with a script, current
  1487. 1:06:25track doesn't point to anything. It it
  1488. 1:06:27can't point to anything. So, it's always
  1489. 1:06:29new. We can't use current track in a
  1490. 1:06:32script inside song properties or layers
  1491. 1:06:34or anywhere else. anywhere else other
  1492. 1:06:36than a part or track and all the other
  1493. 1:06:39things like parts, translators and so on
  1494. 1:06:41and so forth. All these variables there
  1495. 1:06:43is a current version current section.
  1496. 1:06:45For example, if we're on a part, the
  1497. 1:06:46current section is the section that we
  1498. 1:06:48are on. If we're on a track, the current
  1499. 1:06:51section points to the active section
  1500. 1:06:53here. Now, the current section also
  1501. 1:06:55works on song properties for example
  1502. 1:06:57because the active section is global is
  1503. 1:07:00a global information in inside the song.
  1504. 1:07:02So for example we say a equals current
  1505. 1:07:05track.
  1506. 1:07:07So now a has a specific value. If you
  1507. 1:07:10want to print a so our input is let's
  1508. 1:07:14change the input to notes so we can
  1509. 1:07:16monitor easier.
  1510. 1:07:20Module pro channel one that's the name
  1511. 1:07:22of our track. So if we actually name
  1512. 1:07:24this to something else my track. And if
  1513. 1:07:28we go into mood motor this becomes my
  1514. 1:07:30track. By the way, we have another uh
  1515. 1:07:33debugging functionality message to media
  1516. 1:07:35monitor. This is also really convenient.
  1517. 1:07:38Uh if you need to monitor certain
  1518. 1:07:41properties, certain functions while you
  1519. 1:07:43are not inside the editor, you can
  1520. 1:07:45actually send those messages to media
  1521. 1:07:48monitor. Especially if you're working
  1522. 1:07:50with multiple custom translators and you
  1523. 1:07:52need to monitor different variables in
  1524. 1:07:53all those custom translators, you can
  1525. 1:07:55use that uh debugging option message to
  1526. 1:07:58media monitor. Okay, so we get the
  1527. 1:08:00current track. What are we going to do
  1528. 1:08:01with this current track variable? So how
  1529. 1:08:04are we going to use it? That's really
  1530. 1:08:06where these properties takes place. So
  1531. 1:08:08we already have gone through properties
  1532. 1:08:10of arrays and we gone through some
  1533. 1:08:12actions or some variables like count
  1534. 1:08:14indices and the same is true for all
  1535. 1:08:17these types and in fact the track has
  1536. 1:08:20lots of properties here. Okay, regular
  1537. 1:08:23properties are divided into two
  1538. 1:08:24categories read only and not read only.
  1539. 1:08:27For example, name name is a read only
  1540. 1:08:30property of the current track of a
  1541. 1:08:32track. But unity volume midi is not read
  1542. 1:08:35only. So this is very similar to special
  1543. 1:08:37variables like we we did in the song
  1544. 1:08:40volume. Some of them are read only like
  1545. 1:08:42song name and some of them are not. The
  1546. 1:08:45same is true for variable properties. In
  1547. 1:08:48some of them we can assign values in
  1548. 1:08:50some of them we can't. So let's do the
  1549. 1:08:53this with current track and let's change
  1550. 1:08:56this to my knob here and let's control
  1551. 1:08:59the volume of this track. We don't need
  1552. 1:09:01to assign this to a variable name. We
  1553. 1:09:04can directly use the current track
  1554. 1:09:06special variable unit volume midi equals
  1555. 1:09:10current track again unit volume midi +
  1556. 1:09:15one. So we're not using the value of
  1557. 1:09:17control change value but as long as we
  1558. 1:09:18change the value we just keep increasing
  1559. 1:09:20the volume. So I'm just sending some
  1560. 1:09:22random values or not the volume just
  1561. 1:09:24keeps increasing as you see. So yeah you
  1562. 1:09:26can use the values and assign the values
  1563. 1:09:29for those uh which are not read only
  1564. 1:09:33that's important. So like name is a read
  1565. 1:09:36only property. So for example, if I try
  1566. 1:09:38to do current track
  1567. 1:09:41name equals something, it says this
  1568. 1:09:45property is read only. Okay. Uh let's
  1569. 1:09:49talk about properties of property. So
  1570. 1:09:51let's actually try something
  1571. 1:09:53interesting. So on this track I have
  1572. 1:09:56three parts. Now I do current track. One
  1573. 1:10:00of the properties of current track is
  1574. 1:10:02parts. So you can actually have other
  1575. 1:10:05non-basic variables as properties of
  1576. 1:10:08these non-basic variables. So parts is
  1577. 1:10:12an part array. Now we have an
  1578. 1:10:15interesting functionality here. When I
  1579. 1:10:17tap parts, so these are the properties
  1580. 1:10:20of arrays. So let's say autosustain. Now
  1581. 1:10:23this is an interesting situation because
  1582. 1:10:25this is an part array. We have all the
  1583. 1:10:28three parts and we are trying to control
  1584. 1:10:31the auto sustain of all of them. Now
  1585. 1:10:33this is one of the cool logics of
  1586. 1:10:35operators or in also works for operators
  1587. 1:10:39but also for assignments. When I try to
  1588. 1:10:41assign let's say uh true here it's going
  1589. 1:10:45to assign true to all of those auto
  1590. 1:10:48things of all these parts. So we can
  1591. 1:10:50assign values to arrays of the same
  1592. 1:10:53value. So this it's not restricted to
  1593. 1:10:55only properties. This is true for all
  1594. 1:10:58types of arrays. So you can assign
  1595. 1:11:00single values to arrays. All the object
  1596. 1:11:03inside that array will be assigned that
  1597. 1:11:05value. The same goes with the
  1598. 1:11:07properties. So right now uh when I tap
  1599. 1:11:10these parts their autosustains are off.
  1600. 1:11:13As soon as I press notes all these parts
  1601. 1:11:16auto sustains are turned on. Okay. Uh
  1602. 1:11:19let's say these two have autosustain on
  1603. 1:11:21and others are off. Let's try something
  1604. 1:11:24more interesting. I am going to assign
  1605. 1:11:28the negation of this. I'm assigning an
  1606. 1:11:31array another array. Okay, that's okay.
  1607. 1:11:34But I'm negating this array. So negating
  1608. 1:11:37an array means that we're negating each
  1609. 1:11:39boolean value inside that array. So it's
  1610. 1:11:42the same logic like we can perform
  1611. 1:11:44operations like negation or addition uh
  1612. 1:11:47to arrays or between arrays and numbers.
  1613. 1:11:51Uh so for example when I do this so this
  1614. 1:11:54is on this is off this is on I press it
  1615. 1:11:57it's just inversed I press it again
  1616. 1:12:00again it's inverse so you get the point
  1617. 1:12:02let's give another interesting example I
  1618. 1:12:05want to have an interesting control over
  1619. 1:12:08PDF so I have already loaded a PDF file
  1620. 1:12:12let's open that it's a KCH user manual
  1621. 1:12:15now in my controller I have two system
  1622. 1:12:19exclusive messages so Let's let's show
  1623. 1:12:21you that I want to scroll down
  1624. 1:12:24automatically when I use that system
  1625. 1:12:26exclusive message and with another
  1626. 1:12:28message I want to scroll up. So for
  1627. 1:12:30example if I do this is actually
  1628. 1:12:32automatically detects that system
  1629. 1:12:34exclusive message. So let's assign this
  1630. 1:12:36for up. Oh actually let's just do down
  1631. 1:12:40auto detect I have this single system
  1632. 1:12:42exclusive message and as I keep pressed
  1633. 1:12:45on that actually the problem is let's
  1634. 1:12:49monitor meditor this ah I don't have a
  1635. 1:12:52release functionality of this button so
  1636. 1:12:54I cannot really use this. So I want to
  1637. 1:12:56hold a button and as long as the button
  1638. 1:12:58is hold I want to scroll down but the
  1639. 1:13:00release functionality is cannot be
  1640. 1:13:02detected on this keyboard. So I cannot
  1641. 1:13:04use that. I have to use something. Okay,
  1642. 1:13:05I'm just going to use a note. Then
  1643. 1:13:08choose note. I'm going to choose this
  1644. 1:13:10note as my input. Huh? Okay. Whenever I
  1645. 1:13:15change the output, the input resets. So
  1646. 1:13:17I have to reassign it. So for this note,
  1647. 1:13:20note on will keep scrolling. Note off
  1648. 1:13:23will stop scrolling. Okay. I'll again
  1649. 1:13:26need a repetitive action. So this
  1650. 1:13:29translator, let's see, I still have
  1651. 1:13:31those group variables here, right?
  1652. 1:13:32because I haven't changed the track.
  1653. 1:13:35Let's delete all of them. So, I'm going
  1654. 1:13:38to need another variable to detect my uh
  1655. 1:13:41note input. So, it's I just need a
  1656. 1:13:44boolean variable in this case. Note is
  1657. 1:13:47pressed.
  1658. 1:13:48Okay, so it's really easy. Note is
  1659. 1:13:52pressed equals note is on. Okay, so this
  1660. 1:13:56controls not is pressed. Now I'm going
  1661. 1:13:59to show you another new feature in 2.3
  1662. 1:14:02actually a really interesting input. I'm
  1663. 1:14:05going to use it with a different purpose
  1664. 1:14:07but audio meters. Normally this gives me
  1665. 1:14:09the input signals or of this track
  1666. 1:14:13pre-ffect input signal. And the
  1667. 1:14:15important thing about these translators
  1668. 1:14:17is whenever I have this translator, this
  1669. 1:14:20output triggers continuously. Every
  1670. 1:14:23frame, every sample frame, this triggers
  1671. 1:14:26and these are the only inputs which
  1672. 1:14:29allows you to have a continuous
  1673. 1:14:31repetitive uh custom translator. So this
  1674. 1:14:34script will just keep rolling on every
  1675. 1:14:38sample frame. Of course, we don't want
  1676. 1:14:40this to just work all all the time.
  1677. 1:14:43That's why we added that uh control if
  1678. 1:14:47note is pressed. So as long as note is
  1679. 1:14:50pressed we we're going to execute this
  1680. 1:14:53repetitive function. What I want to do I
  1681. 1:14:55want to scroll down my PDF. Now I can do
  1682. 1:14:58current section PDF position. Now this
  1683. 1:15:01PDF position is position in terms of
  1684. 1:15:04float. Zero means top of the document.
  1685. 1:15:07One means top of the first page. Two
  1686. 1:15:09means top of the second page. So it's
  1687. 1:15:11intermediate values allows you to scroll
  1688. 1:15:14the different positions on that. So I'm
  1689. 1:15:16going to set PDF position equals current
  1690. 1:15:19section PDF position plus okay I really
  1691. 1:15:23need to choose a very small number here
  1692. 1:15:25because as I said this iteration just
  1693. 1:15:28keeps every frame. Okay let's test this.
  1694. 1:15:32So as I press my notes it scrolls down
  1695. 1:15:34as I release it just stops. uh since I'm
  1696. 1:15:37at here I want to show you one other
  1697. 1:15:40important uh convention I would say
  1698. 1:15:43instead of writing current section PDF
  1699. 1:15:46position I can just write PDF page
  1700. 1:15:49position now you can see property of
  1701. 1:15:53current section so properties of current
  1702. 1:15:56objects either current track current
  1703. 1:15:59part current section current player unit
  1704. 1:16:02uh we can access those properties right
  1705. 1:16:04away by just typing them and although
  1706. 1:16:06automatically means that we are this
  1707. 1:16:09this simply means current section dot
  1708. 1:16:12PDF page position. So we can simply use
  1709. 1:16:15this convention which allows us to
  1710. 1:16:17access certain properties of the object
  1711. 1:16:19that we are on much faster. Put a plus.
  1712. 1:16:23Let's do minus this time. Right now we
  1713. 1:16:25are scrolling up instead. Okay. I'm
  1714. 1:16:28going to present a final example that I
  1715. 1:16:31actually actively use in my setups. I
  1716. 1:16:34have I have already created a project
  1717. 1:16:36for this.
  1718. 1:16:39Now uh this is a song file and we have
  1719. 1:16:42the stems of this song file on each
  1720. 1:16:45different player unit. So we have the
  1721. 1:16:47lead vocals here, back vocals, guitars,
  1722. 1:16:49bass, drums, keys and metronome and all
  1723. 1:16:52of these are synced together. So for
  1724. 1:16:54example, if I play the global play
  1725. 1:16:58button, let's go into song mixer. All of
  1726. 1:17:01them are started playing synchron in
  1727. 1:17:02sync. So I can mute the monetronome.
  1728. 1:17:08All of them are playing. So why am I why
  1729. 1:17:10do I have these? So I have these in all
  1730. 1:17:13my song files. Like for example, for the
  1731. 1:17:16song file of Dhun, I have all these
  1732. 1:17:18seven tracks. So first of all, the click
  1733. 1:17:20track, I'm sending it to to the rest of
  1734. 1:17:23the band to their inairs during live
  1735. 1:17:25shows or also during our rehearsals. But
  1736. 1:17:27for these stem files, first of all, I am
  1737. 1:17:30using this while I'm practicing myself
  1738. 1:17:32at home. I disabled the keys and played
  1739. 1:17:36all the rest including the metronome and
  1740. 1:17:38play on them during my uh practice at
  1741. 1:17:40home. But during rehearsals sometimes
  1742. 1:17:43our lead vocalist uh is not in stumble.
  1743. 1:17:46So most of in most of our practices we
  1744. 1:17:49don't have the lead vocalist there. So I
  1745. 1:17:51had to along with the click track I had
  1746. 1:17:54to send the lead vocals to the iners of
  1747. 1:17:56all of us to to be able to play and
  1748. 1:17:59sometimes our for example if our
  1749. 1:18:00guitarist cannot make to the uh
  1750. 1:18:03rehearsal we also give the backing track
  1751. 1:18:05of the rehearsal. So I want to have a
  1752. 1:18:08control of all these. So this global
  1753. 1:18:10button start playing all of them
  1754. 1:18:11together. What I want is I need a button
  1755. 1:18:14on my keyboard and when I press that
  1756. 1:18:17button, I want to just play the ones
  1757. 1:18:20that are necessary for that rehearsal.
  1758. 1:18:21And to be able to control that, I want
  1759. 1:18:23to create a custom translator here in
  1760. 1:18:25the song properties. And in fact, I can
  1761. 1:18:27actually do that also in an input ls
  1762. 1:18:30because it's going to be a global
  1763. 1:18:31object. But this is an easier place to
  1764. 1:18:33access. So I want to create a custom
  1765. 1:18:35translator here uh with the inputs from
  1766. 1:18:39my keyboard uh a control button, play
  1767. 1:18:42and stop button with those buttons. So I
  1768. 1:18:44can actually use the system exclusive
  1769. 1:18:47buttons on my keyboard here to
  1770. 1:18:48demonstrate that here in the scripts I
  1771. 1:18:51have a bunch of switches here which
  1772. 1:18:54controls these player units. So for
  1773. 1:18:56example if the switch for guitar is on
  1774. 1:18:58when I press the play button on my
  1775. 1:19:00keyboard guitar starts playing. If bass
  1776. 1:19:03is also on, bass and guitar play starts
  1777. 1:19:05playing together. So I can control which
  1778. 1:19:08player units to play from the switches
  1779. 1:19:10here. So that's that's the general idea.
  1780. 1:19:13Okay. Now I'm creating a custom
  1781. 1:19:16translator and I want to control these
  1782. 1:19:18player units. How how do I do that? One
  1783. 1:19:21way is to create variables, global
  1784. 1:19:24variables and then for on each of these
  1785. 1:19:27translators I can have different custom
  1786. 1:19:29translators with the same global
  1787. 1:19:31variable so that I can have a connection
  1788. 1:19:33between this custom translator and all
  1789. 1:19:35the custom translators here. But the
  1790. 1:19:37thing is I want to create a custom
  1791. 1:19:38translator here where I can use in all
  1792. 1:19:41of my projects because in all my
  1793. 1:19:43projects I have these tracks and I don't
  1794. 1:19:45want to add a global variable in all of
  1795. 1:19:48these and have custom translators in all
  1796. 1:19:50these play. I I want to have a much
  1797. 1:19:53simpler way to control these. So So
  1798. 1:19:56here's how I do it. First of all, let's
  1799. 1:19:58press the play button on my keyboard.
  1800. 1:20:00This is actually a play button which
  1801. 1:20:02sends this is an exclusive message. So
  1802. 1:20:05this will be the play functionality. Now
  1803. 1:20:07here's what I want to do. I want to so
  1804. 1:20:09when I press this play button I want to
  1805. 1:20:12first of all I want to create some uh
  1806. 1:20:14switches to be able to control those
  1807. 1:20:16player units. So I need integers
  1808. 1:20:18actually booleans for for each of the
  1809. 1:20:20player units. So let's say lead vocals.
  1810. 1:20:25Okay. I created these boolean variables
  1811. 1:20:27and I created switches controlling those
  1812. 1:20:29boolean variables. And as you remember,
  1813. 1:20:31so if I close this window, I have all
  1814. 1:20:33these switches controlling those
  1815. 1:20:35variables. Okay, so I need to go through
  1816. 1:20:37all the player units, all the tracks.
  1817. 1:20:39And actually, I'm going to use the
  1818. 1:20:41variable player unit for that. So for
  1819. 1:20:44player, that's the name of my unit in
  1820. 1:20:48all player units. So we we go through
  1821. 1:20:52all the player units. If that player's
  1822. 1:20:55name is equal to lead vocals but okay
  1823. 1:20:58first of all we need to check this
  1824. 1:21:00variable if lead vocals if the switch is
  1825. 1:21:03on and we can actually do an and
  1826. 1:21:06structure here if the switch is on and
  1827. 1:21:08player track we need to access the track
  1828. 1:21:12of the player units and you see actually
  1829. 1:21:14there is a we can have the player units
  1830. 1:21:16property as track and track as a player
  1831. 1:21:18units property we can go both ways name
  1832. 1:21:22equals lead vocals
  1833. 1:21:24If both conditions are are true, then we
  1834. 1:21:27start playing.
  1835. 1:21:29So this is an action property and we're
  1836. 1:21:31going to repeat this with all all the
  1837. 1:21:34other uh player units. Okay. So I put
  1838. 1:21:37all the conditions for each loaded
  1839. 1:21:39vocals, back vocals. I have to make sure
  1840. 1:21:42that these names exactly matches with
  1841. 1:21:44the names of the track. So otherwise it
  1842. 1:21:46doesn't work. So we always have to use
  1843. 1:21:48the same names. But now I haven't
  1844. 1:21:51actually uh set up the same thing for
  1845. 1:21:54the stop button, but it's the same idea.
  1846. 1:21:57So for example, I just want to play
  1847. 1:21:59leads, guitars, and drums. And I press
  1848. 1:22:02play. You see lead, guitar, and drums
  1849. 1:22:05are on the playing. Let's stop it like
  1850. 1:22:07this. And this time I'm going to play
  1851. 1:22:10bass, lead, guitar, bass. And I can
  1852. 1:22:14also, you know, assign rewind buttons
  1853. 1:22:16and everything. I'm just going to do it
  1854. 1:22:18like that. But now in this state leads,
  1855. 1:22:21bass, drums and keys will start playing.
  1856. 1:22:24Uh let's also add metronome.
  1857. 1:22:30But you get the point. So yeah, using
  1858. 1:22:33the non-basic variables and their
  1859. 1:22:35properties, we can have tons and tons of
  1860. 1:22:37controls. All you need to do is just go
  1861. 1:22:39into the script editor and uh go into
  1862. 1:22:42cheat sheets. So one thing you probably
  1863. 1:22:45realize, you can access for example
  1864. 1:22:47parts. What are the properties of parts?
  1865. 1:22:48You can do that or you can uh do this on
  1866. 1:22:52all. You can select all here. So you
  1867. 1:22:54access all the properties of everything.
  1868. 1:22:56Also there's this all button. This
  1869. 1:22:58basically shows all the commands in
  1870. 1:23:00keystage so far. And in every version
  1871. 1:23:03there will be new variable types, new
  1872. 1:23:05functions, new actions, new properties.
  1873. 1:23:08So this will keep evolving
  1874. 1:23:10automatically. So that's all about
  1875. 1:23:12scripts.

About this transcript

This page contains the full transcript of KeyStage Tutorial: The Scripting Language by Ali Gokturk, generated from the public captions YouTube serves with the video. The transcript has 13,065 words across 1,875 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to choose a caption track available on the video.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, caption language selection, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.