This repository has been archived by the owner on Feb 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtramontana.lsp
1887 lines (1749 loc) · 77.4 KB
/
tramontana.lsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; File: tramontana.lsp
;;;
;;; Project: tramontana, for solo viola and computer.
;;;
;;; Purpose: Defining the data to be used in the composition: harmonic
;;; material, rhythmic sequences, sequence order etc. etc.
;;;
;;; Author: Michael Edwards: [email protected]
;;;
;;; Creation date: 23rd August 2002 (Graz)
;;;
;;; $$ Last modified: 20:14:17 Thu Jun 16 2016 WEST
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; (in-package :cm)
;;; (setf *scale* (find-object 'twelfth-tone))
(in-package :sc)
(in-scale :twelfth-tone)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Say we want to repeat three notes in each possible permutation of those
;;; three notes, <level> is 3, max is, say, 20, so we get 360 notes:
;;; (permutate-permutations 3 20) ->
;;; ((0 1 2) (0 2 1) (1 2 0) (2 0 1) (1 0 2) (2 1 0) (1 2 0) (0 1 2) (0 2 1)
;;; (2 1 0) (2 0 1) (1 0 2) (0 2 1) (0 1 2) (2 1 0) (1 2 0) (1 0 2) (2 0 1)
;;; (2 0 1) (1 0 2) (0 2 1) (1 2 0) (0 1 2) (2 1 0) (1 0 2) (2 0 1) (0 2 1)
;;; (2 1 0) (0 1 2) (1 2 0) (1 0 2) (2 1 0) (0 2 1) (1 2 0) (2 0 1) (0 1 2)
;;; .......
(defun permutate-permutations (level max &optional (skip 0))
(let* ((perms (permutations level))
(len (length perms))
;; 20 permutations of the 6 possibilities for the perms, each of
;; which is length three so we end up with 6 x 20 x 3 = 360 numbers.
(order (flatten (inefficient-permutations len :max max :skip skip))))
(move-repeats
(loop for i in order collect (nth i perms)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun tramontana-transpose-pitch (pitch semitones)
(declare (ignore semitones))
(make-pitch (get-sounding-note (id pitch))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun tramontana-transpose-chord (chord semitones)
(declare (ignore semitones))
(cond ((chord-equal chord +hc1+)
(simple-chord-transpose chord))
((chord-equal chord +hc2+)
(make-chord '(c3 assf5 assf5)))
((chord-equal chord +hc3+)
(make-chord (list 'assf5
(get-sounding-note 'g3 'iii)
'assf5)))
((chord-equal chord +hc4+)
(make-chord (list 'assf5 'assf5
(get-sounding-note 'd4 'ii))))
((chord-equal chord +hc5+)
(simple-chord-transpose chord))
((chord-equal chord +hc6+)
(simple-chord-transpose chord))
((chord-equal chord +hc7+)
(simple-chord-transpose chord))
((chord-equal chord +hc8+)
(make-chord (list 'g3
(get-sounding-note 'ef4 'iii)
(get-sounding-note 'c5 'ii)
;; harmonic and non-harmonic sound same
(get-sounding-note 'a5))))
((chord-equal chord +hc9t+)
(make-chord (list 'assf5
(get-sounding-note 'g3 'iii)
(get-sounding-note 'd4 'ii))))
(t (error "Unhandled chord: ~a" chord))
))
(defun simple-chord-transpose (chord)
(make-chord
(loop
for p in (data chord)
for new = (tramontana-transpose-pitch p nil)
do (setf (marks new) (marks p))
collect new)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun get-sounding-note (note &optional (force-non-harm nil))
;; meaning 7/6 of a semitone lower = 1 st and a 12th tone lower!
(flet ((iii (harmonic) (freq-to-note (* +viola-III+ harmonic)))
;; a semitone higher minus a 6th tone, i.e. 2/3 of st higher
(ii (harmonic) (freq-to-note (* +viola-II+ harmonic)))
(i (harmonic) (freq-to-note (* +viola-I+ harmonic)))
(iv (harmonic) (freq-to-note (* +viola-IV+ harmonic)))
(iii-non-harm (note) (transpose-note note -7/6))
(ii-non-harm (note) (transpose-note note 2/3))
(i-non-harm (note) (transpose-note note 2/3)))
(if (eq force-non-harm 'iii)
(iii-non-harm note)
(if (eq force-non-harm 'ii)
(ii-non-harm note)
(when note
(case note
;; I-harm
(a5 (i 2))
;; II-harm
(fs4 (ii 5))
(g4 (ii 4))
(a4 (ii 3))
;; III-harm
(b3 (iii 5))
(c4 (iii 4))
(d4 (iii 3))
;; IV-harm
(dssf3 (iv 7))
(e3 (iv 5))
(f3 (iv 4))
(g3 (iv 3))
;; III-non-harm
(df4 (iii-non-harm 'df4))
(ef4 (iii-non-harm 'ef4))
(f4 (iii-non-harm 'f4))
;; IV-non-harm
(fs3 'gf3)
(gs3 'af3)
(bf3 'bf3)
(t (error "Unhandled note: ~a" note))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; This gets indices for those notes that should be "real notes" i.e. not
;;; harmonics, not "dead harmonics" but normal, fingered, sounding notes.
;;; The number of real notes will increase as the algorithm progresses.
(defun get-real-note-indices ()
(let* ((non-harms
;; We use +tramontana-harms-with-rests+, the final form of the
;; algorithm (that starts in the last section (3 3) bar 290), find
;; out which notes in that list are "dead harmonics" ...
(loop
for note in +tramontana-harms-with-rests+
for i from 0
when (or (member note +tramontana-III-non-harm+)
(member note +tramontana-IV-non-harm+))
collect i))
(lsys (do-lookup +tramontana-binary-lfl+ 2 (length non-harms))))
;; ... then use +tramontana-binary-lfl+ (the l-system also used for string
;; selection (just G and C) and selection of harmonics or dead harmonics--
;; where we proceed from mainly 1s to mainly 2s) to decide whether this
;; should be a real note or not: yes when we have a 2, no when it's a 1
(loop for i in non-harms and bin in lsys
when (= bin 2)
collect i)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; This takes a list of notes (symbols) and rests (nil) and creates sc::events
;;; The actual notes have diamond heads as they are harmonics and non-harmonics
;;; played as harmonics (dead harmonics--diamond is filled with gray). If
;;; <do-real-notes> is t then some of the non-harmonics will be changed to
;;; real, normally-fingered notes according to the algorithm defined in
;;; get-real-note-indices above.
(defun make-tramontana-harm-events (notes &optional (do-real-notes nil))
(loop with real-notes = (when do-real-notes (get-real-note-indices))
with stem-up
for note in notes
for e = (make-event note 't32 :is-rest (unless note t))
for fingering = (position note +tramontana-III-non-harm+)
for i from 0
do
#-cmn (warn "No CMN")
#+cmn
(when note
;; notes on the G string are all stem up, C string (and D string) are
;; stem down
(setf stem-up (or (member note +tramontana-III-harm+)
(member note +tramontana-III-non-harm+)))
;; put an accent on the "real notes" (i.e. normal note head)
(if (member i real-notes)
(add-mark e (cmn::accent))
;; make the dead-harmonics (grayed in diamond) ...
(if (or (member note +tramontana-III-non-harm+)
(member note +tramontana-IV-non-harm+))
(dead-harmonic e stem-up)
;; ... or real harmonics
(add-mark e (cmn::note-head :artificial-harmonic))))
(add-mark e (if stem-up
cmn::stem-up
cmn::stem-down)))
collect e))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun make-sounding-notes (notes)
(loop
for n in (get-sounding-notes notes)
for e = (make-event n 't32 :is-rest (unless n t))
do
#-cmn (warn "No CMN")
#+cmn (add-mark e (if n
cmn::no-stem
;; rests
cmn::invisible))
collect e))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun dh ()
#+cmn (cmn::note-head :gray-filled-diamond))
(defun dead-harmonic (event stem-up)
(add-mark event (dh))
;; this makes the whole note and stem gray
;; (add-mark event (cmn::note-head :diamond (cmn::gray-scale .5)))
;; (add-mark event (cmn::note-head (cmn::draw-filled-diamond)))
;; (add-mark event (cmn::dead-harmonic
;; (cmn::dy (if stem-up -.2 .2))))
;;(add-mark event (cmn::natural-harmonic))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun tramontana-symbol (name)
;; (format nil "/winxp/music/tramontana/score/symbols/~a.eps" name))
(format nil "/music/tramontana/score/symbols/~a.eps" name))
(defun no-head ()
#+cmn (cmn::note-head :none))
(defun fist (&optional (dx -.2) (dy 1.5))
#+cmn (cmn::graphics
;; there's a problem with photoshop eps files so try body1 instead
;; (cmn::file (tramontana-symbol "fist"))
(cmn::file (tramontana-symbol "body1"))
(cmn::scale .55 .55)
(cmn::dx dx) (cmn::dy dy)))
(defun tailpiece (&optional (dx -.2) (dy 1.5))
#+cmn (cmn::graphics
;; (cmn::file (tramontana-symbol "tailpiece"))
(cmn::file (tramontana-symbol "body1"))
(cmn::scale .7 .7)
(cmn::dx dx) (cmn::dy dy)))
(defun body1 (&optional (dx -.6) (dy 1.5))
#+cmn (cmn::graphics
(cmn::file (tramontana-symbol "body1"))
(cmn::scale .7 .7)
(cmn::dx dx) (cmn::dy dy)))
(defun body2 (&optional (dx -.6) (dy 1.5))
#+cmn (cmn::graphics
(cmn::file (tramontana-symbol "body2"))
(cmn::scale .7 .7)
(cmn::dx dx) (cmn::dy dy)))
(defun bridge (&optional (dx 0.0) (dy 1.5))
#+cmn (cmn::on-bridge (cmn::dx dx) (cmn::dy dy)))
(defun ntxt (text &key (dx 0.0) (dy 1.5))
#+cmn (cmn::text text (cmn::dx dx) (cmn::dy dy) (cmn::font-name "Times-Roman")
(cmn::font-size 8)))
(defun open-string ()
(first (mk 0)))
(defun clb ()
(ntxt "clb"))
(defun cl ()
(ntxt "cl"))
(defun hair ()
(ntxt "hair"))
(defun spe ()
(ntxt "spe"))
(defun ste ()
(ntxt "ste"))
(defun vlb ()
(ntxt "vlb"))
(defun ord ()
(ntxt "ord"))
(defun sp ()
(ntxt "sp"))
(defun st ()
(ntxt "st"))
(defun pizz ()
(ntxt "pizz"))
(defun arco ()
(ntxt "arco"))
(defun pizz-nail ()
(ntxt "pizz nail"))
(defun br (bar note dy &optional (index 0))
(note-add-bracket-offset +tramontana+ bar note 'vla :dy dy :index index))
(defun tr3 ()
#+cmn (cmn::unmeasured-tremolo (cmn::tremolo-slashes 3)))
(defun tr4 ()
#+cmn (cmn::unmeasured-tremolo (cmn::tremolo-slashes 4)))
(defun text1 (x y text)
(ps-text x y text :font "Verdana-Italic" :font-size 10.0))
(defmacro acmtn (bar note &rest marks)
`(add-marks-to-note +tramontana+ ,bar ,note 'vla ,@marks))
(defun acmtns (mark-function notes)
;; (add-mark-to-notes +tramontana+ mark-function 'vla notes)
)
(defun acmtnsft (mark-function notes)
(add-mark-to-notes-from-to +tramontana+ mark-function 'vla notes))
(defmacro rmbe (bar num-bars new-events &rest keys)
`(replace-multi-bar-events +tramontana+ 'vla ,bar ,num-bars ,new-events
:auto-beam nil
,@keys))
(defmacro re (bar start-event replace-num-events new-events &rest keys)
`(replace-events +tramontana+ 'vla ,bar ,start-event ,replace-num-events
,new-events ,@keys))
(defun treble (bar-num note-num)
#+cmn (add-mark-before +tramontana+ bar-num note-num 'vla cmn::treble))
(defun alto (bar-num note-num)
#+cmn (add-mark-before +tramontana+ bar-num note-num 'vla cmn::alto))
(defun perc (bar-num note-num)
#+cmn (add-mark-before +tramontana+ bar-num note-num 'vla
cmn::percussion))
;; (defun bnum (section seq bar)
;; (get-bar-num-from-ref +tramontana+ section seq bar))
(defun mf-d ()
(mk mf :dy -0.5))
(defun pp-d ()
(mk pp :dy -0.5))
(defun f-d ()
(mk f :dy -0.5))
(defun pp-sub (&optional (dy 0.0))
(mk pp :text "sub" :dy dy))
(defun p-sub (&optional (dy 0.0))
(mk p :text "sub" :dy dy))
(defun mp-sub (&optional (dy 0.0))
(mk mp :text "sub" :text-dx .8 :dy dy))
(defun mf-sub (&optional (dy 0.0))
(mk mf :text "sub" :text-dx .8 :dy dy))
(defun f-sub (&optional (dy 0.0))
(mk f :text "sub" :dy dy))
(defun up-bow (&optional (dy 0.0))
#+cmn (cmn::up-bow (cmn::dy dy) (cmn::scale 1.7 1.7)))
(defun down-bow (&optional (dy 0.0))
#+cmn (cmn::down-bow (cmn::dy dy) (cmn::scale 1.7 1.7)))
(defun battuto ()
#+cmn (cmn::sc-sprechstimme))
(defun ah ()
#+cmn (cmn::note-head :artificial-harmonic))
(defun aux-note (note)
#+cmn (cmn::auxiliary-note note
cmn::no-stem cmn::in-parentheses))
(defun qnp (&key (dx 0.0) (dy 0.5))
#+cmn (cmn::quarter-note-in-parentheses
(cmn::dx dx) (cmn::dy dy)))
(defun tup (ref info &optional (delete t))
(add-tuplet-bracket (get-bar +tramontana+ ref 'vla)
info
;; delete all tuplet brackets in the bar first?
delete))
;; todo: add this to the piece class and update the beams info of the rsb!
(defun bm (ref start-note end-note)
(let ((bar (get-bar +tramontana+ ref 'vla)))
;; (format t "~&re-beaming bar ~a" (bar-num bar))
(start-beam (get-nth-non-rest-rhythm (1- start-note) bar))
(end-beam (get-nth-non-rest-rhythm (1- end-note) bar))
t))
(defun ttie (bar-num note-num)
(tie +tramontana+ bar-num note-num 'vla))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Create running t32s on harmonic and non-harmonic points of the string, but
;;; both played as flageolets. Start off with the non-harm points (1) and
;;; transition to the harmonic points (2) by using an l-system (binary-lfl).
;;; Use the same l-sys to select whether we play the notes on the III or IV
;;; string--should be fairly even all through. On each string four harmonic
;;; and three non-harmonic nodes are available. The order in which these are
;;; chosen is simply permutational.
;;; harmonic nodes on D string
(defparameter +tramontana-II-harm+ '(fs4 g4 a4))
;;; harmonic nodes on G string
(defparameter +tramontana-III-harm+ '(b3 c4 d4))
;;; non-harmonic nodes ("dead harmonics") on G string
(defparameter +tramontana-III-non-harm+ '(df4 ef4 f4))
;;; harmonic nodes on C string
(defparameter +tramontana-IV-harm+ '(e3 f3 g3))
;;; non-harmonic nodes ("dead harmonics") on G string
(defparameter +tramontana-IV-non-harm+ '(fs3 gs3 bf3))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; the l-sequence for transition from non-harmonic to harmonic nodes and
;;; selection of G or C string. A transition will actually be made here when
;;; do-lookup is called from mainly 1s to mainly 2s
(defparameter +tramontana-binary-lfl+
(make-l-for-lookup
'binary-lfl
;; the transition sequences:
;; when we do lookup with the l-sequence, the 1 will cause lookup into the
;; first sequence (line), the 2, lookup into the second sequence. The two
;; lists in each of these sequences represent the list to cycle around at
;; the beginning and the list to cycle around at the end. (Beginning and
;; end here refer to the number of events requested when do-lookup is
;; called.)
'((1 ((1 1 1 2 1 1) (2 1 2 2 2 2)))
(2 ((1 1 2 1 1 1) (1 2 2 2 2 2))))
;; the rules:
;; A simple l-sequence will here return a sequence of fairly evenly
;; distributed 1s and 2s,
'((1 (1 2 2 2 1 1)) (2 (2 1 2 1 1 1 2)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; On each string we have 3 harmonic and 3 non-harmonic nodes to play (see
;;; above). We want to play each of these 3 notes in permutation, not repeating
;;; one until the other 2 are already played, but always with a different order
;;; e.g.
;;; ((1 2 0) (2 0 1) (2 1 0) (1 0 2) (0 1 2) (0 2 1) (2 1 0) (2 0 1) (0 2 1)
;;; (0 1 2) (1 0 2) (1 2 0) (1 2 0) (2 0 1) (0 1 2) (0 2 1) (2 1 0) (1 0 2)
;;; (1 2 0) (1 0 2) (0 2 1) (2 0 1) (2 1 0) (1 2 0) (2 1 0) (2 0 1) (0 1 2)
;;; (0 1 2) (1 0 2) (0 2 1) (0 1 2) (0 2 1) (2 0 1) (2 1 0) (1 2 0) (1 0 2)
;;; .....
(defparameter +tramontana-3perms+ (permutate-permutations 3 50))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; A list of 768 "notes" on strings C and G (fairly evenly distributed) each
;;; note being either a harmonic or a non-harmonic (but played as a harmonic)
;;; and transitioning gradually from almost exclusively non-harmonics to almost
;;; exclusively harmonics.
(defparameter +tramontana-harms+
(let* (;; 8 sequences, each 4 bars of 2/4, rhythm is t32
(total-notes (* 8 4 2 12))
;; whether we're going to play a harmonic or non-harmonic node--this
;; will transition from mainly 1 (non-harmonic) to mainly 2
;; (harmonic)
(binary-transition-type (do-lookup +tramontana-binary-lfl+ 1
total-notes))
;; which string we're going to play on: this is taken from the same
;; l-sequence as that used to choose harmonic or non-harmonic nodes
;; but note that we don't do lookup (which causes the transition)
;; rather we just get the l-sequence which will have roughly the
;; same number of 1s and 2s distributed evenly. So, we alternate
;; string all the way through but transition from non-harmonic to
;; harmonic nodes.
(binary-transition-string (get-l-sequence +tramontana-binary-lfl+ 1
total-notes))
;; on each string there is a group of 3 harmonic and 3 non-harmonic
;; nodes. These will be permutated as documented in the
;; +tramontana-3perms+ parameter above. We start reading a
;; flattened version of that list at 4 different points (0, 9, 18,
;; 27), one each for the harmonic and non-harmonic nodes of each of
;; the two strings.
(permutated-harms1 (flatten (subseq +tramontana-3perms+ 0
(ceiling total-notes 3))))
(permutated-harms2 (flatten (subseq +tramontana-3perms+ 9
(ceiling total-notes 3))))
(permutated-non-harms1 (flatten (subseq +tramontana-3perms+ 18
(ceiling total-notes 3))))
(permutated-non-harms2 (flatten (subseq +tramontana-3perms+ 27
(ceiling total-notes 3)))))
(loop
for type in binary-transition-type
for string in binary-transition-string
with note-group
with note
with note-index
do
;; signal an error if we run out of notes in the permutations
(when (or (not permutated-non-harms1)
(not permutated-non-harms2)
(not permutated-harms1)
(not permutated-harms2))
(error "Permutations!"))
;; using the string (1=G, 2=C) and type (1=non-harmonic,
;; 2=harmonic) variables, get the group we are to select the note
;; from: +tramontana-III-non-harm+, +tramontana-III-harm+,
;; +tramontana-IV-non-harm+ or +tramontana-IV-harm+
(setf note-group (if (= string 1)
(if (= type 1)
+tramontana-III-non-harm+
+tramontana-III-harm+)
(if (= type 1)
+tramontana-IV-non-harm+
+tramontana-IV-harm+))
note-index (if (= type 1) ;; non-harmonic
(if (= string 1) ;; G string
(pop permutated-non-harms1)
(pop permutated-non-harms2)) ;; C string
;; harmonic
(if (= string 1) ;; G string
(pop permutated-harms1)
(pop permutated-harms2))) ;; C string
;; now we have the group to read from, and the index into the
;; group, we can get the note
note (nth note-index note-group))
collect note)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Bring string II into play: We're going to modify +tramontana-harms+ by
;;; gradually introducing more and more harmonics from the D-string overwriting
;;; the C and G-string harmonics that were already there.
;;; Split the 768 +tramontana-harms+ into 24 groups of 32 notes. These 24
;;; groups take the following number of harmonics from string II: 4x0, 4x1,
;;; 4x2, 2x3, 2x4, 2x5, 1x6, 1x7, 4x8
(defparameter +tramontana-harms-with-II+
;; the indices are where the harmonics on the D string come in in the
;; relevant 32-note group.
;; the first 128 have no D harmonics (4x0)
;; each sublist of indices refers to one of the 24 groups of 32 notes,
;; hence the indices range from 0 to 31.
;; the length of the sublist reflects the number of D harmonics that will
;; be introduced
;; the actual indices given here were chosen at will, not really according
;; to any system.
(let* ((indices '((8) (14) (20) (26) ;; 4x1
(9 10) (3 29) (13 19) (29 30) ;; 4x2
(16 17 18) (11 12 21) ;; 2x3
(16 17 18 26) (5 6 24 25) ;; 2x4
(9 10 11 22 23) (13 14 18 19 20) ;; 2x5
(2 3 8 15 16 17) ;; 1x6
(5 6 10 11 12 18 19) ;; 1x7
;; 2 2 3 1, 2 3 2 1, 3 2 2 1, 1 2 3 2
(2 3 9 10 15 16 17 24) (4 5 11 12 13 19 20 31) ;; 4x8
(3 4 5 11 12 17 18 25) (2 5 6 15 16 17 28 29)))
(real-indices (loop
for list in indices
with index = 128 ;; first 128 have no D harmonics
with result = '()
do
(loop for i in list do
(push (+ index i) result))
;; move onto the next group of 32 notes
(incf index 32)
finally (return (nreverse result))))
;; the harmonics and non-harmonics on the G string
;; these are only used to find out if a note is played on the
;; g-string when avoiding string jumps below
(string-III (append +tramontana-III-harm+
+tramontana-III-non-harm+))
;; ditto on the C string
(string-IV (append +tramontana-IV-harm+ +tramontana-IV-non-harm+))
(flattened-3perms (flatten +tramontana-3perms+))
;; get a whole load of G-string harmonics for avoiding string jumps
(III-harms (loop
for i in flattened-3perms
collect (nth i +tramontana-III-harm+)))
;; get a whole load of D-string harmonics for inserting (not just to
;; avoid string jumps!)
(II-harms (loop
for i in flattened-3perms
repeat (length real-indices)
collect (nth i +tramontana-II-harm+)))
;; this is where we copy our original data to modify by introducing
;; the D-string harmonics
(result (copy-list +tramontana-harms+)))
;; and this is where we actually pop the D-string harmonics in,
;; overwriting any C or G-string harmonics that were already there.
(loop for i in real-indices do
(setf (nth i result) (pop II-harms)))
;; here we simply avoid string-jumping:
;; make sure that any notes on string II are preceded by string III
(loop for n1 in result and n2 in (cdr result) and i from 0 do
(if (and (member n1 string-IV)
(member n2 +tramontana-II-harm+))
(setf (nth i result) (pop III-harms))
(when (and (member n1 +tramontana-II-harm+)
(member n2 string-IV))
(setf (nth (1+ i) result) (pop III-harms)))))
result))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Now we modify +tramontana-harms-with-II+ to put occasional rests into the
;;; constant flow of t32 notes. This is actually the final form of the
;;; algorithm that will be inserted in to the piece starting at section (3 3)
;;; (bar 290)--the 768 t32 notes are 32 bars long, taking us to the end of the
;;; piece at 321
;;; This global is used by make-tramontana-harm-events (see functions.lsp) to
;;; actually make the sc::events for the sc structure.
(defparameter +tramontana-harms-with-rests+
(let* ((result (copy-list +tramontana-harms-with-II+))
;; this determines the number of t32 rests when we insert the rest,
;; varies from 1 to 5 with more occuring at the beginning and only 1
;; occuring at the end.
(num-rests-lfl
(make-l-for-lookup
'num-rests
'((1 ((3 1 2) (1 1 2) (1)))
(2 ((4 3 4) (2 1 2) (1)))
(3 ((5 2 4) (1 3 2) (1))))
'((1 (3)) (2 (3 1)) (3 (1 2)))
:auto-check-redundancy nil))
;; should be 768 but let's be sure
(total-notes (length result))
;; this determines how many notes will occur before a rest or rests
;; are inserted. N.B. there is no transition here, we just use the
;; l-sequence.
(num-notes-lfl
(make-l-for-lookup
'num-notes
nil
'((13 (11 17)) (25 (17 13)) (17 (13)) (11 (25 17)))))
(num-rests (do-lookup num-rests-lfl 2 50))
(num-notes (get-l-sequence num-notes-lfl 17 50)))
;; (print num-rests)
;; (print num-notes)
(loop
for nn in num-notes
for nr in num-rests
for count from 1
with i = 0
while (< i total-notes)
;; collect nr into used
do
(incf i nn)
;; insert num-rests nils (i.e. rests) into our copy of
;; +tramontana-harms-with-II+ after num-notes
(loop for j from i repeat nr do
(when (< j total-notes)
(setf (nth j result) nil))))
result))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; This is the algorithm that starts at section (3 1) (bar 222).
;;; It makes sporadic but ever more often little bursts of notes (separated by
;;; long but becoming shorter rests).
;;; It returns a list of notes and nils (rests).
;;; This global is used by make-tramontana-harm-events (see functions.lsp) to
;;; actually make the sc::events for the sc structure.
(defparameter +tramontana-harms-transition+
(let* ((l-distance
;; how many ts notes between harms--becomes less and less, starting
;; at a max of 50 and decreasing to 1 but in fact twice this
;; because of the scaler!
(make-l-for-lookup
'distance
'((1 ((50 35 42) (20 29 17) (6 8 9) (2 1 4)))
(2 ((48 36 42) (29 16 22) (7 9 10) (3 2 1)))
(3 ((30 42 39) (18 23 27) (8 10 7) (4 3 1))))
'((1 (3)) (2 (3 1)) (3 (1 2)))
:scaler 2
:auto-check-redundancy nil))
;; how many harms per appearance---increases.
(l-num-harms
(make-l-for-lookup
'num-harms
'((1 ((2 3 2) (4 5 6)))
(2 ((3 4 2) (4 7 6)))
(3 ((4 3 2) (7 5 8))))
'((1 (3)) (2 (3 1)) (3 (1 2)))
:offset 1
:auto-check-redundancy nil))
;; 3.1 and 3.2 are 68 bars long = (* 68 2 12) = 1632 t32 notes
;; N.B. both use transitions
(distance (do-lookup l-distance 2 49))
(num-harms (do-lookup l-num-harms 2 49))
;; actually 257 last time I looked
(total-harms (loop for h in num-harms sum h))
(result
;; this is where we use the 768 harmonics and non-harmonics on C
;; and G strings as calculated above but reversed so that we
;; actually start with mainly harmonics and gradually progress to
;; more and more non-harmonics so that when
;; +tramontana-harms-with-rests+ at bar 290 we can start the
;; progression back again.
;; N.B. because so few harmonics are presented at a time at the
;; beginning, they will not dominate as at the end of the piece
;; where they run uninterrupted.
(loop
for dist in distance
for num in num-harms
;; so total-harms has to be less the 768-300!!!
with harms = (reverse (subseq +tramontana-harms+ 300
(+ 300 total-harms)))
with return = '()
;; it could be that we want to have more harms
;; than we've got space for...
for do-notes = (min dist num)
for do-nil = (- dist do-notes)
do
;; ran out of notes?
(unless harms
(error "Need more notes (harms)!"))
;; the notes/harmonics
(loop repeat do-notes do
(push (pop harms) return))
;; the rests
(loop repeat do-nil do
(push nil return))
finally (return (nreverse return)))))
;; (print (loop for i in distance sum i))
;; (print (length result))
result))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defparameter +c3+ 130.8128)
(defparameter +c3-7th-harmonic+ (* +c3+ 7))
(defparameter +viola-IV+ +c3+)
(defparameter +viola-III+ (/ +c3-7th-harmonic+ 5))
(defparameter +viola-II+ (/ +c3-7th-harmonic+ 3))
(defparameter +viola-I+ (/ +c3-7th-harmonic+ 2))
(defparameter +tramontana-string-freqs+
(list +viola-IV+ +viola-III+ +viola-II+ +viola-I+))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun make-tr-chord (notes)
(make-chord notes :midi-channel 1 :microtones-midi-channel 2))
(defparameter +h-iv+ 'dssf3)
(defparameter +hc1+ (make-tr-chord (list +h-iv+ 'b3 'a4)))
(defparameter +hc2+ (make-tr-chord '(c3 b3 a4)))
(defparameter +hc3+ (make-tr-chord (list +h-iv+ 'g3 'a4)))
(defparameter +hc4+ (make-tr-chord (list +h-iv+ 'b3 'dbn4))) ; d4 with nat in ()
(defparameter +hc5+ (make-tr-chord '(b3 a4)))
(defparameter +hc6+ (make-tr-chord (list +h-iv+ 'b3)))
(defparameter +hc7+ (make-tr-chord '(a4 a5)))
(defparameter +hc8+ (make-tr-chord '(g3 ef4 c5 a5)))
(defparameter +a4h+ (make-pitch 'a4))
;;; This really does belong here as it is part of the global and should be
;;; added before the global is used.
(add-mark (1st +hc1+) (ah))
(add-mark (2nd +hc1+) (ah))
(add-mark (3rd +hc1+) (ah))
(add-mark (2nd +hc2+) (ah))
(add-mark (3rd +hc2+) (ah))
(add-mark (1st +hc3+) (ah))
(add-mark (3rd +hc3+) (ah))
(add-mark (1st +hc4+) (ah))
(add-mark (2nd +hc4+) (ah))
(add-mark (1st +hc5+) (ah))
(add-mark (2nd +hc5+) (ah))
(add-mark (1st +hc6+) (ah))
(add-mark (2nd +hc6+) (ah))
(add-mark (1st +hc7+) (ah))
(add-mark (2nd +hc7+) (ah))
(add-mark +a4h+ (ah))
#+cmn (add-mark +hc5+ (cmn::fingering "II" "III"))
;;; Same as above but tremolo
(defparameter +hc1t+ (clone +hc1+))
(defparameter +hc2t+ (clone +hc2+))
(defparameter +hc3t+ (clone +hc3+))
(defparameter +hc4t+ (clone +hc4+))
(defparameter +hc8t+ (clone +hc8+))
(defparameter +hc9t+ (make-tr-chord (list +h-iv+ 'g3 'd4)))
(add-mark +hc1t+ (tr4))
(add-mark +hc2t+ (tr4))
(add-mark +hc3t+ (tr4))
(add-mark +hc4t+ (tr4))
(add-mark +hc8t+ (tr4))
(add-mark (1st +hc9t+) (ah))
(add-mark +hc9t+ (tr4))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; This will decide which of the three transpositions of the three basic
;;; chords will be used. Given a call to do-lookup, this will simply create a
;;; transition from 1 to 3.
(defparameter +tramontana-harmonic-lfl+
(make-l-for-lookup
'ternary-lfl
'((1 ((1) (2) (3))))
'((1 (1 1)))
))
(defparameter +tramontana-chord-order+
(let* ((perms (loop for i in
(flatten (subseq +tramontana-3perms+ 0 30))
collect (1+ i)))
(1-to-3-transition (do-lookup +tramontana-harmonic-lfl+ 1 76))
(refs (loop for i in 1-to-3-transition and j in perms collect
(list i j)))
(sections (split-into-sub-groups refs '(25 25 26)))
(sub-sections
(loop for section in sections
for i from 1
for sub-secs1 =
;; the sections are actually (8 9 8) (8 9 8) (8 9 9)
;; but the (8 9 9) will yield (8 9 8) when there's only 25 in
;; the list.
(split-into-sub-groups section '(8 9 9))
for sub-secs2 =
(loop for ss in sub-secs1 and i from 1 collect
(list i ss))
collect
(list i sub-secs2))))
sub-sections))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defparameter +tramontana-loops+
'((14.21644 14.717097 15.155375 15.326848)
(37.45814 37.877552 38.27229 38.73669)
(67.29288 67.6644 68.25796 69.01406)
(72.27647 73.35329 74.4693 75.07592 76.83338 77.937775 78.80272)
(111.81424 112.74884 113.220184)
(123.09914 123.94521 124.985756 126.22803 127.2468)
(130.00853 131.22757 131.81387 132.0098)
(135.3883 135.87012 136.42885 136.91211)
(151.8643 153.18059 153.87283 154.75374)
(163.55556 164.03882 164.53514 165.68889)
(165.9951 166.50594 166.81796)
(168.62767 169.33456 169.58984 170.45769 170.95111 172.05696 172.30948)
(183.844 184.21841 185.45197 186.35754)
(215.02548 215.68726 216.05588 216.60445 217.05434 217.38521)
(217.91637 218.23274 218.95256 219.24861 219.41696 219.73624)
(221.9131 222.58359 223.21342 223.55592 223.84616 224.25844)
(224.30766 224.63855 224.7111 224.78368 225.09424 225.40771)
(225.98358 226.35973 226.66739 227.32045 227.78485)
(230.6293 230.81215 231.23882 232.10957)
(266.925 267.2733 267.66513 268.17596 268.7768 269.33987 270.0916
270.38187 270.6431 271.1278)
(272.13788 272.44553 272.7706 273.2002)
(302.4109 302.91013 303.2439 303.73734)
(368.21335 368.74158 369.38596 370.02158 371.1129)
(376.89758 377.99564 378.79874 379.1267 379.50693 379.84653 380.33997
381.5445)
(381.74475 382.2672 382.69388 382.97833)
(389.67148 390.02267 390.8383 391.48553 392.16763 392.6088)
(411.58847 412.1745 412.6273 413.35583 414.20337 414.81287)
(433.57462 434.36987 434.9678 435.62958 436.23038 437.0837)
(439.0458 439.57407 440.16037 441.0166)
(448.2438 449.65442 451.0331 452.1767 452.69913)
(452.97778 453.2245 453.40735 453.67438 453.9066)
(507.03674 507.29797 507.73044 508.0352 508.53152 509.37323 510.273)
(515.2624 515.8429 516.38855 516.71075)
(578.65576 578.89667 579.0273 579.38434 579.66614 579.79645)
(581.1752 581.27673 581.3928 581.5525 581.65405 581.77594 581.90656
582.0459 582.342 582.4174 582.60315)
(588.0976 588.29205 588.6171 588.9103 589.10474 589.2586 589.3312
589.40955 589.7375 590.1206)
(590.2803 590.46893 590.63727 590.73303 590.8056 591.1597 591.2178)
(596.7151 597.00824 597.22595 597.3827 597.522 597.84705)
(611.9735 612.0954 612.197 612.2986 612.4002 612.48724 612.6469 612.87036
613.05334)
(648.1734 648.54785 648.6872 649.0065 649.0645 649.1951 649.5376)
(659.4148 659.90564 660.2855 660.4858 661.02277 661.37396 661.87317)
(711.62775 711.8832 712.05444 712.246 712.41724 712.6669)
(762.38947 762.6072 762.7436 762.8684 763.028 763.1064 763.3125)
(785.1305 785.27563 785.4846 785.61816 785.82715 786.14056 786.55273
786.97363 787.3306)
(844.7507 845.2092 845.47046 845.6359 845.8478 846.13806)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#|
MDE Sun Jan 1 14:37:30 2012 -- similar to skin, this piece used a version of
slippery chicken without pitch selection routines in detail so can no longer
run.
(make-slippery-chicken
'+tramontana+
;; 16/6/04
;;
;; At the time of composing the viola part, things like the harmonic structure
;; weren't fixed. Work this out here for the generation of the sound files.
;; The notes here are taken from the sounding harmonics on strings ii-iv
:set-palette
(let ((tramontana-diff-iv-iii
(- (midi-note-float (make-pitch +VIOLA-III+))
(midi-note-float (make-pitch +VIOLA-IV+))))
(tramontana-diff-iv-ii
(- (midi-note-float (make-pitch +VIOLA-II+))
(midi-note-float (make-pitch +VIOLA-IV+)))))
`((1 ((1 ((c3 d3 e3 f3 g3 c5 d5 e5 f5 g4 fssf5 assf5)))
(2 ((c3 d3 e3 f3 g3 c5 d5 e5 f5 cstf5 etf5 dssf6)))
(3 ((c3 d3 e3 f3 g3 c5 d5 e5 f5 assf5 gqf6)))))
(2 ((1 ((1 1) :transposition ,tramontana-diff-iv-iii))
(2 ((1 2) :transposition ,tramontana-diff-iv-iii))
(3 ((1 3) :transposition ,tramontana-diff-iv-iii))))
(3 ((1 ((1 1) :transposition ,tramontana-diff-iv-ii))
(2 ((1 2) :transposition ,tramontana-diff-iv-ii))
(3 ((1 3) :transposition ,tramontana-diff-iv-ii))))))
;;
:set-map
+tramontana-chord-order+
:tempo-map
'((((1 1) 1 1) 44)
(27 52) (29 44) (60 48) (72 44) (80 48) (85 44) (99 48) (116 44)
(135 48) (150 50) (199 52) (222 54) (256 52) (267 50) (275 48)
(281 46) (289 44))
:instrument-palette
'((viola (:lowest-written c3
:staff-name "Viola"
:starting-clef percussion
:highest-written f6
:chords t))
(viola-sounding (:lowest-written c3 :highest-written f6 :chords t
:starting-clef treble :staff-name "Viola Sounding"))
(computer (:starting-clef percussion :staff-name "Computer")))
:ensemble
'(((vla-snds (viola-sounding
:midi-channel 3 :microtones-midi-channel 4
:cmn-staff-args (staff-size .7)))
(vla (viola :midi-channel 1 :microtones-midi-channel 2))
(cptr1 (computer :midi-channel 5 :microtones-midi-channel 6))
(cptr2 (computer :midi-channel 7 :microtones-midi-channel 8))))
:staff-groupings '(4)
:instruments-hierarchy '(vla cptr1 cptr2 vla-snds)
;; :instruments-write-bar-nums '(vla)
:bars-per-system-map
'((1 9) (7 12) (82 10)
(102 14) (158 12) (182 10) (200 11) (203 10) (213 9)
(222 9) (234 9) (240 8) (249 6) (256 5) (261 6)
(267 4) (275 3) (286 2))
;; 25 seqs in all.
:rthm-seq-map
(let* ((seqs1 '(2 20 1 9 10 22 16 25 6 14 21 17 4 9 13 24 19 3 11 15 1
18 11 16 12))
(seqs2 '(2 23 3 7 13 22 19 3 8 12 23 14 2 10 15 4 20 25 9 16 5
17 14 18 9))
(seqs3 '(2 21 3 12 11 22 16 1 8 17 23 20 24 9 12 2 18 21 6 15 5
19 11 18 15 26))
;; seq 26 is only one bar...
(3butlast (butlast seqs3))
(seqs1-rev (reverse seqs1))
(seqs2-rev (reverse seqs2))
(seqs3-rev (econs (reverse 3butlast) 26))
(seqs1-reflect (reflect-list seqs1))
(seqs2-reflect (reflect-list seqs2))
(seqs3-reflect (econs (reflect-list 3butlast) 26)))
`((1
((1 ((vla ,(subseq seqs1 0 8))
(vla-snds ,(make-list 8 :initial-element nil))
(cptr1 ,(subseq seqs1-rev 0 8))
(cptr2 ,(subseq seqs1-reflect 0 8))
))
(2 ((vla ,(subseq seqs1 8 17))