-
Notifications
You must be signed in to change notification settings - Fork 4
/
seq2.ny
400 lines (345 loc) · 12.8 KB
/
seq2.ny
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
;nyquist plug-in
;version 2
;type process
;name "Audio selection Sequencer 2..."
;action "Sequencing your audio selection..."
;info "seq2.ny by David R. Sky: for help, see seq2.txt in the seq2.zip file, or www.shellworld.net/~davidsky/seq2.htm \nTo generate a rest, use r, n, (), or a blank svp input line. \nReleased under terms of the GNU General Public License version 2"
;control tempo "Tempo [beats per minute], beats per sequence, sequence starting offset [beats]" string " " "210.0 8 0.0"
;control panning "Pan stereo selection [0=no 1=yes]" int " " 1 0 1
;control random-time "Timing randomization [plus or minus percent]" int " " 0 0 100
;control random-measures "Number of repeated randomized sequences" int " " 0 0 8
;control transpose "Overall transpose value, then for successive measures" string " " "0 0 0 5 5 0 0 -5 -5"
;control sequences "Sequences to generate" int " " 4 1 96
;control svp1 "1: Semitone, volume, pan value[s]" string " " "(0 1 0) (4 .5 .2) (7 .5 .8) (2 1 .5)"
;control svp2 "2: SVP value[s]" string " " "(12 .5 .8) (7 .5 .2) (4 1 1) r"
;control svp3 "3: SVP value[s]" string " " " "
;control svp4 "4: SVP value[s]" string " " " "
;control svp5 "5: SVP value[s]" string " " " "
;control svp6 "6: SVP value[s]" string " " " "
; Audio Selection Sequencer 2 by David R. Sky, August 29, 2007
; much improved over seq1b.ny from Dec. 17, 2004
; sequences mono or stereo audio selection in Audacity
; can also pan stereo selection for each note
; can also transpose successive sequences
; Thanks to feedback from Edgar Franke, Martyn Shaw -
; for Nyquist code pointers and visual layout
;
; I have been careful to unbind symbols and functions when no longer needed,
; to hopefully avoid problem[s] encountered
; in previous long Nyquist plug-ins
;
; Released under terms of the GNU General Public License version 2
; http://www.gnu.org/copyleft/gpl.html
; function to convert stereo selection to mono-sounding selection
; if panning = 1
; returns "selection"
(defun sample (s panning)
(if (arrayp s)
(if (= panning 1)
(vector (mult 0.5 (sum (aref s 0) (aref s 1)))
(mult 0 (sum (aref s 1) (aref s 0))))
;
s) ; end inner if
;
s))
; function to replace all occurances of "n", "N", "r", "R"
; [from "nil" and "rest"]
; with replacement text [a rest]
; and get rid of all other alphabetic characters in the string
(defun replace-n&r (string replacement-string)
(setf temp2-string "")
(dotimes (i (length string))
(setf char (char-downcase (char string i)))
(setf temp2-string
(cond
((or (char= char #\r)
(char= char #\n))
(strcat temp2-string " " replacement-string " "))
;
((> (char-code char) 96)
temp2-string)
;
(t
(strcat temp2-string (string char))))))
temp2-string)
; function to convert string to a list
; returns list
(defun string-to-list (string)
(read (make-string-input-stream (format nil "(~a)" string))))
(let* (
(tempo (string-to-list tempo))
(beats-per-seq (if (second tempo) (max 1 (min 96 (truncate (second tempo)))) 8))
(beats-offset (if (third tempo) (third tempo) 0))
; tempo can be expressed as a flonum or as a LISP calculation:
; eg., [/ 210 16] would make tempo 1/16 of 210.0 bpm
; [* 210 16] would make tempo 16 times 210 bpm
(tempo (if (car tempo)
(if (listp (car tempo))
(float (eval (car tempo)))
(car tempo))
210.0))
; end tempo assignment
(beat-dur (/ 60.0 tempo)) ; duration of one beat
(beats-offset (* beat-dur beats-offset)) ; convert beats-offset to time
(small-seq-dur (* beats-per-seq beat-dur)) ; duration of one [small] sequence
(selection (sample s panning))
(dur (/ len *sound-srate*)) ; selection duration
; set s to nil
(s nil)
(svp-string-list (list svp1 svp2 svp3 svp4 svp5 svp6))
(temp-string "")
(temp2-string "")
; convert transpose string input to transpose-list
(transpose-list (string-to-list (replace-n&r transpose "nil")))
(transpose-list (if (null transpose-list)
'(0 0) transpose-list))
(overall-transpose (if (null (car transpose-list)) 0 (car transpose-list)))
(transpose-list (if (> (length transpose-list) 1)
(cdr transpose-list) '(0)))
(transpose-length (length transpose-list))
i j k n
svp-element svp-list temp-list vol semitone pan
samples peak-level) ; end let* args
; unbind s and sample function
(setf (symbol-value 's) '*unbound*)
(setf (symbol-function 'sample) '*unbound*)
; concatenate all svp string inputs into one string
(dotimes (i (length svp-string-list))
(setf temp-string (if
(null (string-to-list (nth i svp-string-list)))
(strcat temp-string " (0 0 0.5)")
(strcat temp-string " " (nth i svp-string-list)))))
; unbind string input values svp1 and up,
; and svp-string-list
(setf (symbol-value 'svp1) '*unbound*)
(setf (symbol-value 'svp2) '*unbound*)
(setf (symbol-value 'svp3) '*unbound*)
(setf (symbol-value 'svp4) '*unbound*)
(setf (symbol-value 'svp5) '*unbound*)
(setf (symbol-value 'svp6) '*unbound*)
(setf (symbol-value 'svp-string-list) '*unbound*)
; convert temp2-string to a list
; and assign to master-list
(setf master-list (string-to-list (replace-n&r temp-string "(0 0 0.5)")))
; unbind temp-string, temp2-string, char,
; and string-to-list, replace-n&r functions
(setf (symbol-value 'temp-string) '*unbound*)
(setf (symbol-value 'temp2-string) '*unbound*)
(setf (symbol-value 'char) '*unbound*)
(setf (symbol-function 'string-to-list) '*unbound*)
(setf (symbol-function 'replace-n&r) '*unbound*)
; create temp-list, which is beats-per-seq long master-list
(dotimes (i beats-per-seq)
(setf temp-list (if (numberp (nth i master-list))
(append temp-list (list (list (nth i master-list))))
(append temp-list (list (nth i master-list))))))
; assign temp-list to master-list
(setf master-list temp-list)
; function to add random time variation to each beat
; if random-time > 0,
; introduces random timing variation to sequenced notes
(defun get-random-time (beat-dur random-time)
(if (= random-time 0) 0
(* beat-dur (nth (random 2) (list -1.0 1.0))
(* 0.001 (random (truncate (* random-time 0.01 1000)))))))
; function to add volume and pan values to sublists
; if they are absent
; also prepends randomized time to each sublist
(defun add-values-to-list (list beat-dur random-time)
(dotimes (i (length list))
(setf temp-list (nth i list))
(setf (nth i list)
(cond
((null temp-list) ; nil, a rest
(list (get-random-time beat-dur random-time) 0 0 0.5))
;
((= (length temp-list) 1) ; semitone value only
(append (list (get-random-time beat-dur random-time)) temp-list (list 1.0 0.5)))
;
((= (length temp-list) 2) ; semitone, vol values
(append (list (get-random-time beat-dur random-time)) temp-list (list 0.5)))
;
(t ; semitone, vol and pan values present
; [any values after these are ignored]
(append (list (get-random-time beat-dur random-time))
(list (first temp-list))
(list (second temp-list))
(list (min 1.0 (max 0 (third temp-list))))))))))
; add default vol and pan values to sublists of master-list
; which do not already have these values,
; and prepend randomized time offsets to each sublist
; note that first sublist of master-list contains time offset value
; which will later be made zero
(add-values-to-list master-list beat-dur random-time)
; unbind get-random-time and add-values-to-list functions
(setf (symbol-function 'get-random-time) '*unbound*)
(setf (symbol-function 'add-values-to-list) '*unbound*)
; for randomized sequences only: function to append
; random-measures number of non-randomized master-list,
; before randomizing
(defun multi-list (list random-measures)
(setf temp-list list)
(dotimes (i (1- random-measures))
(setf temp-list (append temp-list list)))
temp-list)
; function to rotate a list:
; [my-rotate [list 0 1 2 3 4 5]] -> [[1 2 3 4 5 0]
; [my-rotate [list 0 1 2 3 4 5] 2] -> [2 3 4 5 0 1]
(defun my-rotate (list &optional (n 1))
(if (<= n 0)
list
(my-rotate (append (last list) (reverse (cdr (reverse list)))) (1- n))))
; function to randomize a list
; needs my-rotate function above
(defun randomize-list (list)
(setf temp-list nil)
(dotimes (i (length list))
(setf list (my-rotate list (random (length list))))
(setf temp-list (push (car list) temp-list))
(pop list))
temp-list)
; randomize master-list if random-measures > 0
(setf master-list (if (= random-measures 0)
master-list
(randomize-list (multi-list master-list random-measures))))
; unbind temp-list, list, and
; multi-list, my-rotate, randomize-list functions
(setf (symbol-value 'temp-llist) '*unbound*)
(setf (symbol-value 'list) '*unbound*)
(setf (symbol-function 'multi-list) '*unbound*)
(setf (symbol-function 'my-rotate) '*unbound*)
(setf (symbol-function 'randomize-list) '*unbound*)
; make sure first time offset of master-list is 0,
; so first generated note is at the exact start
; [if no beat offset]
(setf (car (car master-list)) 0.0)
; function to retrieve semitone, vol and pan values
; from master-list
(defun get-svp-values (master-list i overall-transpose j transpose-list)
(setf svp-list (nth i master-list))
(cond
((or
(null (nth j transpose-list))
(= (length svp-list) 1)
(null svp-list))
(setf vol 0)) ; a rest
;
(t ; offset, semitone, vol and pan values in svp-list
(setf semitone (+ overall-transpose (nth j transpose-list) (second svp-list)))
(setf vol (third svp-list))
(setf pan (fourth svp-list)))))
; function to return stretch factor
; depending on semitone value
(defun return-stretch (semitone)
(/ (expt 2.0 (/ semitone 12.0))))
; function to pan stereo audio
; [has to be made mono first using sample function]
; works by panning only the l channel of the selection,
; since selection was converted to both channels being mixed in l channel,
; r channel being made silent
; only l channel of selection is stretched,
; saving calculation time during sequence generation
(defun l-channel-pan (where sound)
(vector (mult (diff 1.0 where) (aref sound 0))
(mult where (aref sound 0))))
; function to stretch or shrink selection to new semitone value,
; or return silence if vol = 0
; and pan if panning is called for
(defun stretch-selection (semitone selection)
(if (arrayp selection)
(if (= panning 0)
(vector
(force-srate *sound-srate* (stretch-abs (return-stretch semitone)
(sound (aref selection 0))))
(force-srate *sound-srate* (stretch-abs (return-stretch semitone)
(sound (aref selection 1)))))
;
(vector
(force-srate *sound-srate* (stretch-abs (return-stretch semitone)
(sound (aref selection 0)))))) ; end if panning=0
; stretch mono selection
(force-srate *sound-srate* (stretch-abs (return-stretch semitone)
(sound selection)))))
; function to generate new note in sequence
(defun new-note (selection i j master-list overall-transpose transpose-list)
(get-svp-values master-list i overall-transpose j transpose-list)
(cond
((= vol 0) (s-rest beat-dur)) ; return silence
;
((= semitone 0) ; no transposition needed
(if (arrayp selection)
(if (= panning 0)
(scale vol selection)
(scale vol (l-channel-pan pan selection)))
(scale vol selection)))
;
(t ; return transposed selection
(if (arrayp selection)
(if (= panning 0) ; do not pan stereo selection
(scale vol (stretch-selection semitone selection))
;
(scale vol (l-channel-pan pan
(stretch-selection semitone selection))))
;
(scale vol
(stretch-selection semitone selection))))))
; calculate new beats-per-seq value if random-measures > 0
; beats-per-seq is used in sequence generation,
; rather than length of master-list
; because master-list might not be programmed with beats-per-seq
; number of notes
; so notes after master-list are rests
(setf beats-per-seq
(if (= random-measures 0) beats-per-seq
(* random-measures beats-per-seq)))
; calculate new small-seq-dur value if random-measures > 0
; small-seq-dur: duration of one 'small' sequence
; [made from master-list]
(setf small-seq-dur
(if (= random-measures 0)
small-seq-dur
(* small-seq-dur random-measures )))
; calculate large-seq-dur
; this is duration of sequence
; after one full cycle of transpositions
(setf large-seq-dur (* small-seq-dur transpose-length))
; calculate number of sequences to normalize:
; samples in 1.5 times large-seq-dur
(setf samples (truncate (* 1.5 large-seq-dur *sound-srate*)))
(flet
; local function which is used to normalize sequence
((normalize (samples signal)
(setf peak-level (if (arrayp signal)
(max (peak (aref signal 0) samples)
(peak (aref signal 1) samples))
(peak signal samples)))
(if (> peak-level 0)
(scale (/ 0.95 peak-level) signal)
(cue signal))))
; generateing sequences
(sim
; initial beats-dur offset [silence]...
(if (arrayp selection)
(vector (s-rest beats-offset) (s-rest beats-offset))
(s-rest beats-offset))
; ...followed by sequence
(at-abs beats-offset (cue
(normalize samples (simrep (k sequences)
; generate transposed list of small sequences
(simrep (j (length transpose-list))
; generate one [small] sequence
(simrep (i beats-per-seq)
(at-abs
(+ (car (nth i master-list)) (* k large-seq-dur)
(* j small-seq-dur) (* i beat-dur))
(cue (new-note selection i j master-list overall-transpose transpose-list))
) ; end at-abs
) ; end simrep i
) ; end simrep j
) ; end simrep k
) ; end normalize
) ; end cue
) ; end at-abs
) ; end sim
) ; end flet
) ; end let*