;; jellyfish-2.sal -- left-hand/right-hand simulation ;; (c) 2008 by Roger B. Dannenberg define variable lh-heap = list(g3, ef4, f4), rh-heap = list(g4, bf4, c5, d5), lh-pat = make-heap(lh-heap, for: 1), rh-pat = make-heap(rh-heap, for: 1), lh-cnt = 0, ; how many previous lh? rh-cnt = 0, ; how many previous rh? lh-prev, rh-prev ; remember prev pitches ; choose left or right hand, ; generate non-duplicate pitch define function select-pitch() begin with lhw = 1 + lh-cnt * lh-cnt, rhw = 1 + rh-cnt * rh-cnt ; weights ; favor the hand used the least so far if rrandom() > float(lhw) / (lhw + rhw) then begin ; use left hand set lh-cnt += 1 ; increment use count ; generate left-hand pitch until itŐs ; not a duplicate loop for pitch = next(lh-pat) while pitch = lh-prev finally begin ; remember selection set lh-prev = pitch return pitch end end end else ; use right hand begin ; just like the left-hand code set rh-cnt += 1 ; increment use count loop for pitch = next(rh-pat) while pitch = rh-prev finally begin ; remember the selection set rh-prev = pitch return pitch end end end end ;; define some global variables here. Without this, ;; SAL will issue warnings because variable names have ;; operators (*) embedded and this could indicate a ;; missing space, e.g. 1 * score * 3 vs 1 *score* 3 define variable *score*, *time* ;; However, we want to initialize *score* and *time* ;; each time the file is loaded (define variable only ;; initialized variables once when they are first created) ;; so use a set command: set *score* = nil, *time* = 251.5 ;; uses variable definitions and select-pitch definition ;; from Example 18.1.2 define function j-sect( start, dur, beatdur, lh-heap, rh-heap) begin with notes = (start + dur - *time*) / beatdur, section ; result score for this section ;; reset some variables used by select-pitch: set lh-pat = make-heap(lh-heap, for: 1) set rh-pat = make-heap(rh-heap, for: 1) set lh-cnt = 0 ; how many previous lh selections? set rh-cnt = 0 ; how many previous rh selections? set notes = 2 * round(notes / 2) ; even # of nts set section = score-gen(score-len: notes, begin: *time*, ioi: beatdur, vel: real-random(70, 120), pitch: select-pitch()) ;; merge new notes with previous ones in *score*: set *score* = score-merge(*score*, section) ;; update time so next section follows this one set *time* += notes * beatdur end define function j3() begin ;; start dur beatdur lh-heap/rh-heap exec j-sect(251.5, 11.5, 0.44, {g3 ef4 f4}, {g4 bf4 c5 d5}) exec j-sect(263 , 6 , 0.38, {f3 df4 ef4}, {f4 af4 c5}) exec j-sect(269 , 11 , 0.33, {fs3 ds4 e4}, {g4 af4 df5}) exec j-sect(280 , 9 , 0.33, {bf2 af3}, {d4 gf4 af4 bf4}) exec j-sect(289 , 12 , 0.36, {ef3 c4 df4}, {ef4 af4 bf4 df5}) exec j-sect(301 , 4 , 0.33, {f3 c4}, {f4 g4 bf4 c4}) exec j-sect(305 , 7 , 0.33, {cs3 b3}, {fs4 cs5 e5}) exec j-sect(312 , 7 , 0.33, {cs3 b3}, {e4 fs4 b4} ) exec j-sect(319 , 15 , 0.33, {bf3 af3}, {ef4 f4 bf4 c5}) exec j-sect(334 , 10 , 0.36, {ef3 af3 df4}, {f4 af4 bf4 c5}) exec j-sect(344 , 10 , 0.40, {bf3 f3 c4}, {af4 bf4 f5 g5}) end exec j3() exec score-play(score-shift(*score*, -251.0))