# 4.2 Types Of Timevar ## Introduction This section introduces the various incarnations of TimeVars that are available to use in FoxDot. So far we have seen the basic, vanilla TimeVar that holds a value for a certain number of beats and then changes to the next value. There also exists a number of TimeVars that gradually change between these values as well as TimeVars for representing whole Pattern objects. Let’s delve into these now: ## Gradual-Change TimeVars There are three types of gradual-change TimeVars that (unsurprisingly) gradually change between values over time instead of instantly changing once the assigned duration has elapsed. These are `linvar`, `sinvar`, and `expvar` and their names relate to the way in which the values change over time, as described below: ### `linvar(values, dur)` This TimeVar changes between values on a linear scale, hence the name `linvar`. As with all TimeVars, it takes a series of values and durations as its input. If `dur` is omitted, then it will use the value of current metre. ``` python-console >>> my_linvar = linvar([0, 1], 4) >>> print(Clock.now(), my_linvar) 0 0 >>> print(Clock.now(), my_linvar) 1 0.25 >>> print(Clock.now(), my_linvar) 2 0.5 >>> print(Clock.now(), my_linvar) 3 0.75 ``` As time progresses, the value changes such that after the given duration (4 beats in this example) it will be exactly 1. Once that duration has elapsed, the `linvar` will start to linearly change its value in the direction of the next input value, which is 0. Over the next 4 beats, the value will decrease at a linear rate towards 0. ``` python-console >>> print(Clock.now(), my_linvar) 4 1 >>> print(Clock.now(), my_linvar) 5 0.75 >>> print(Clock.now(), my_linvar) 6 0.5 >>> print(Clock.now(), my_linvar) 7 0.25 ``` ### `sinvar(values, dur)` Instead of changing between values at a linear rate, a `sinvar` changes at a rate derived from a sinusoidal wave. You can see below that the rate is seemingly much faster but will still reach the final value of 1 at the same time as the `linvar`. ``` python-console >>> my_sinvar = sinvar([0, 1], 4) >>> print(Clock.now(), my_linvar, my_sinvar) 1 0.25 0.38 >>> print(Clock.now(), my_linvar, my_sinvar) 2 0.50 0.71 >>> print(Clock.now(), my_linvar, my_sinvar) 3 0.75 0.92 >>> print(Clock.now(), my_linvar, my_sinvar) 4 1 1 ``` ### `expvar(values, dur)` The rate of change in the `expvar` is exponential, so starts small but finishes in large steps. You can see this is also the case when decreasing values: ``` python-console >>> my_expvar([0, 1], 4) >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 1 0.25 0.38 0.06 >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 2 0.50 0.71 0.25 >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 3 0.76 0.93 0.57 >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 4 1 1 1 >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 5 0.74 0.92 0.93 >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 6 0.50 0.71 0.75 >>> print(Clock.now(), my_linvar, my_sinvar, my_expvar) 7 0.25 0.38 0.43 ``` ### Notes and examples It should be noted when a player is using a gradual change TimeVar it will use the value stored in it at the time the note is triggered. That means, once a note is played, you will not hear a change in value over time in the note itself. Try these lines of code out yourself: ``` python # No gradual change in the high pass frequency p1 >> dirt(dur=4, hpf=linvar([0, 4000], 4)) # Apparent gradual change in the high-pass frequency p2 >> dirt(dur=1/4, hpf=linvar([0, 4000], 4)) ``` You can also use a duration of 0 to immediately skip the gradual change and move on to the next value; this is useful for 'resetting' values and creating drops: ``` python # Ramp up to 4000Hz then reset to 0 p1 >> dirt(dur=1/4, hpf=expvar([0, 4000], [8, 0])) ``` Just as you can with regular TimeVars, gradual-change TimeVars can be nested within other TimeVars to better manage how the values are applied. For example, we can ramp the high-pass filter frequency only on the last 4 beats of a 32 beat cycle like so: ``` python # Use a regular TimeVar to set the value to 0 for 28 beats p1 >> dirt(dur=1/4, hpf=var([0, expvar([0, 4000], [4, 0])], [28, 4])) ``` ## Pattern TimeVars ### `Pvar(patterns, dur)` So far we have only stored single values in a TimeVar but sometimes it is useful to store a whole Pattern object. You can’t do this using a regular TimeVar as any Pattern in the input list of values is treated as a nested list of single values. To avoid this behaviour, you need to use a `Pvar`, short for Pattern-TimeVar. It is created exactly like any other TimeVar but values can be whole lists/Patterns: ``` python-console >>> a = Pvar([[0, 1, 2, 3], [4, 5, 6]], 4) >>> print(Clock.now(), a) 0 P[0, 1, 2, 3] >>> print(Clock.now(), a) 4 P[4, 5, 6] ``` Mathematical operations and transformations also work identically to the regular TimeVars: ``` python-console >>> a = Pvar([[0, 1, 2, 3], [4, 5, 6]], 4) >>> b = (a * 2) + 1 >>> print(Clock.now(), a, b) 0 P[0, 1, 2, 3] P[1, 3, 5, 7] >>> print(Clock.now(), a, b) 4 P[4, 5, 6] P[9, 11, 13] >>> def odd_test(num): ... """ Convert an even number to 3 and an odd to 5 """ ... return 5 if num % 2 == 1 else 3 >>> c = c.transform(odd_test) >>> print(a, b, c) P[0, 1, 2, 3] P[1, 3, 5, 7] P[3, 5, 3, 5] >>> print(a, b, c) P[4, 5, 6] P[9, 11, 13] P[3, 5, 3] ``` You can even nest a `Pvar` within a Pattern as you would a normal Pattern to alternate values being played... and then change this based on time! ``` python # Alternate the alternating notes every 8 beats p1 >> pluck([0, 1, 2, Pvar([[4, 5, 6, 7], [11, 9]], 8)], dur=1/4, sus=1) ```