# [CM] Simple oscillator?

Heinrich Taube taube at uiuc.edu
Wed Nov 17 12:12:38 PST 2010

```here is a chunk of a lesson on mapping (from my algocomp1 class) that
and demonstrates its use in processes, hopefully it will answer some

ive pasted the contents here in case the attached file (sin.sal2) gets
rejected by the listserv.

;;; -*- syntax: Sal2; font-size: 18; theme: "Emacs"; -*-

;
;; 'Sin'ful composition
;

; Lots of math functions also perform mapping. For example 'sin'
; (sine) maps radians values into amplitudes between -1 and 1.
; Recall that radians are simply another way to measure angles:
; degrees chop the unit circle up int 360 equal parts and radians chop
; the circle up into 2pi parts. In other words 360 degrees equals 2pi
; radians. Let's use rescale to show this:

loop for deg from 0 to 360 by 45
for rad = rescale(deg, 0, 360, 0, 2 * pi)
end

; Now forget about degrees, lets just move 2pi radians in 8 steps from
; 0 to 1 see what sine gives us:

loop for x from 0 to 1 by 1/8
for rad = rescale(x, 0, 1, 0, 2 * pi)
end

; so as x goes from 0 to 1, radians goes from 0 to 2pi and sin returns
; the amplitude. if we plot these values of sine left to right we get
; a perfectly symmetrical 'wave figure' (called the sine wave) with a
; shape that looks something like this:

; +1 |   *  *
;    | *      *
;  0 |*--------*--------*----->
;    |          *      *
; -1 |            *  *

;X  : 0  1/4  1/2 3/4   1
;Rad: 0  pi/2 pi  3pi/2 2pi

; Since sin values range from -1 to 1 all we have to do is use the
; 'rescale' function to map sin values to appropriate ranges for
; musical parameters. For example, this loop maps sin values to key
; numbers between 60 and 84:

loop for x from 0 to 1 by 1/8
for rad = rescale(x, 0, 1, 0, 2 * pi)
for key = rescale(amp, -1, 1, 60, 84)
end

; So we've mapped x from 0:1 to a sine wave shape of key numbers
; between 60 and 84! What would this sound like?

;
;; Using sin in a musical process
;

; How can we use sin to control the evolution of a musical process?
; The loop example above hints at how we can solve at least one
; approach to the problem. Imagine that we want to control the key
; numbers of a process that runs for 100 iterations of a counter
; variable i. On each iteration we want to calculate the current value
; of sin and output a corresponding keynum. Calculating the keynum
; from the output value of sin is easy (we use rescale), but how do we
; convert the process iteration variable 'i' into a radian value 'r'
; that we can pass into sin? A moments reflection will tell that
; something like this will work:

; [1]    r = 2 * pi * (i / 100))

; formula [1] says that as counter i moves from 0 to 100 the radians r
; moves from 0 to 2pi. For example:
; when i=0   then i/100=0  so r=2pi*0  and r=0;
; when i=50  then i/100=.5 so r=2pi*.5 and r=pi
; when i=100 then i/100=1  so r=2pi*1  and r=2pi and so on.

; lets implement the 100 event test process:

process sine1 ()
for i below 100
for r = 2 * pi * (i / 100)
for a = sin(r)
send("mp:midi", key: rescale(a, -1, 1, 21, 21 + 88))
wait .1
end

sprout( sine1() )

; TODO: This example can be generalized! Copy/paste the definition
; to create a new process called sine2 that accept four arguments:
; reps, rate, low and high. The process should run for reps
; iterations, output keynums between low and high, and wait rate
; seconds between iterations. For example here are two calls to the
; function you will create:

sprout( sine2(100, .1, 0, 127) )

sprout( sine2(100, .1, 30, 90) )

; How can we make the process generate more than one cycle of the wave
; as i goes from 0 to num?  Perhaps we can see if we compare formula
; [1] with a second version:

; [1]    r = 2 * pi * (i / 100))
; [2]    r = 2 * pi * 10 * (i / 100)

; As i goes from 1 to 100, formula [1] goes 1 trip around 2pi radians
; and formula [2] goes 10 trips around 2 pi radians. Since [2] make
; ten trips from 0-pi in the same time [1] makes 1 trip, the frequency
; of [2] is ten times that of [1]

; Lets generalize this by adding a new parameter 'cycs' just after the
; 'num' parameter use that parameter as a "frequency" for radian
; calculation.

process sine3 (len, cycs, low, hi, rhy, dur, amp)
with 2pi = 2 * pi
for i below len
for a = sin ( (2pi * cycs * (i / len)) )
send("mp:midi", key: rescale(a ,-1, 1, low, hi),
amp: amp, dur: dur)
wait rhy
end

;; we test it out by specify 4 cycles in 100 notes:

sprout( sine3(100, 4, 20, 100, .1, .1, .6) )

; lastly, we can "dirty up" the deterministic motion of sin by adding a
; random component to its values:

process sine4 (len, cycs, low, hi, dirty, rhy, dur, amp)
with 2pi = 2 * pi
for i below len
for a = sin ( (2pi * cycs * (i / len)) )
for r = between(- dirty, dirty)
send("mp:midi", key: rescale( a + r ,-1 - dirty, 1 + dirty, low, hi),
amp: amp, dur: dur)
wait rhy
end

sprout (sine4(100, 4, 20, 100, .2, .1, .1, .6))

; and lastly, here is a process that uses sin to generate
; "oscillating" rhythmic patterns, ie moving faster and slower around
; a central rhythmic value.

process sinrhy (num, cycs, fast, slow, lb, ub)
for x to num
for s = sin( 2 * pi * cycs * (x / num))
for k = between(lb, ub)
send( "mp:midi", key: k, dur: .1 )
wait rescale( s, -1, 1, slow, fast)
end

sprout( sinrhy(40, 3, .05, .6, 60, 80) )

;; the discrete function is like rescale but it maps floating point
;; values onto integers, or lists of values.

loop repeat 20
for x = ran(1.0)
for d = discrete(x, 0.0, 1.0, 48, 90)
print( "x=", x, " d=", d )
end

;; you can also map onto lists of discrete values

process sine5 (len, cycs, scal, rhy, dur, amp)
with 2pi = 2 * pi
for i below len
for a = sin ( (2pi * cycs * (i / len)) )
send("mp:midi", key: discrete(a ,-1, 1, scal),
amp: amp, dur: dur)
wait rhy
end

begin
with scal = scale(50, 20, 1, 2)
sprout( sine5(100, 4, scal, .1, .1, .6) )
end

-------------- next part --------------
A non-text attachment was scrubbed...
Name: sin.sal2
Type: application/octet-stream
Size: 6009 bytes
Desc: not available
Url : http://ccrma-mail.stanford.edu/pipermail/cmdist/attachments/20101117/5cf59e37/attachment.obj
```