314 lines
7.8 KiB
Common Lisp
314 lines
7.8 KiB
Common Lisp
;; https://github.com/defaultxr/cl-patterns/blob/master/doc/tutorial.org
|
|
;; https://github.com/defaultxr/cl-patterns/blob/master/doc/cookbook.org - other examples
|
|
(ql:quickload :cl-patterns/supercollider)
|
|
(cl-patterns:backend-start 'supercollider)
|
|
|
|
;; also launch QjackCTL and connect SuperCollider outputs 1 & 2 to headphones
|
|
;; to force restart, use killall scsynth
|
|
|
|
|
|
|
|
(in-package #:cl-patterns)
|
|
|
|
(start-clock-loop :tempo 136/60)
|
|
|
|
|
|
(pb :automatic-jazz
|
|
:note (pshuf (scale-notes :minor) 4)
|
|
:octave (pr (pwhite 2 7))
|
|
:root (pr (pwhite 0 12))
|
|
:dur (pshuf (list 1/3 1/4)))
|
|
|
|
(play :automatic-jazz)
|
|
|
|
(end :automatic-jazz)
|
|
|
|
;; (tempo 136/60) ; this raises error
|
|
|
|
(pb :hat
|
|
:instrument :hat
|
|
:dur 1/2 ;; play the hihat every 1/2 beat
|
|
:pfindur 4 ;; limit the pattern to 4 beats in length (it loops automatically)
|
|
:quant 4 ;; ensure that the pattern starts on a beat that is divisible by 4
|
|
)
|
|
|
|
(pb :snare
|
|
:embed (pcycles "----o--o-o--o--o") ;; using the snare tab from the page linked above
|
|
:instrument :snare
|
|
:dur 1/4
|
|
:quant 4)
|
|
(play :snare)
|
|
(end :snare)
|
|
|
|
(pb :kick
|
|
:embed (pcycles "o-o-------oo----")
|
|
:instrument :kick
|
|
:dur 1/4
|
|
:quant 4)
|
|
|
|
;; play the patterns we've defined:
|
|
(play :hat) ; for some reason just NIL
|
|
(end :hat)
|
|
(play (list :hat :snare :kick)) ; hm
|
|
|
|
|
|
(pb :12-bar-blues
|
|
:scale :chromatic
|
|
:root 4 ;; E for all guitar lovers out there
|
|
:octave 4
|
|
:dur (pseq (list 2/3 1/3))
|
|
:amp (pseq (list 0.5 0.4))
|
|
:legato (pseq (list 0.7 0.2))
|
|
:degree (pr (pseq (list (pseq '((0 7) (0 9)) 8)
|
|
(pseq '((5 12) (5 14)) 4)
|
|
(pseq '((0 7) (0 9)) 4)
|
|
|
|
(pseq '((7 14) (7 16)) 2)
|
|
(pseq '((5 12) (5 14)) 2)
|
|
(pseq '((0 7) (0 9)) 2)
|
|
(pseq '((7 14) (7 16)) 2))
|
|
1)
|
|
2))
|
|
|
|
(play :12-bar-blues)
|
|
(end :12-bar-blues)
|
|
|
|
;; what do I want to learn though?
|
|
(pb :foo ;; define a new pattern named :foo
|
|
:instrument :kik ;; use the :kik synth we defined above
|
|
:play-quant 4 ;; make sure the pattern will only start on a beat that is divisible by 4, to stay in sync
|
|
:dur 1 ;; give each event a duration of 1 beat
|
|
:pfin 4 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
|
)
|
|
|
|
(pb :bar
|
|
:instrument :default
|
|
:play-quant 4
|
|
:dur 1/2
|
|
:scale :major ;; select the major scale
|
|
:degree (pwhite 0 7) ;; pick a random note from the first 7 notes in the selected scale
|
|
:pfindur 4 ;; limit the length of the pattern to 4 beats. pfindur causes the pattern to be limited based on its duration in beats, rather than the number of events.
|
|
)
|
|
|
|
(play :foo)
|
|
(end :foo)
|
|
|
|
;; let's try to modify most basic ones? copy them again
|
|
|
|
(in-package #:cl-collider)
|
|
|
|
(defsynth kik ((freq 440) (out 0))
|
|
(let* ((env (env-gen.kr (env (list 0 1 0) (list 0.001 1)) :act :free))
|
|
(fenv (env-gen.kr (env (list 1 0) (list 0.25)) :level-scale freq))
|
|
(sig (sin-osc.ar fenv 0 0.2)))
|
|
(out.ar out (pan2.ar sig 0 env))))
|
|
|
|
(in-package #:cl-patterns)
|
|
|
|
(pb :foo ;; define a new pattern named :foo
|
|
:instrument :kik ;; use the :kik synth we defined above
|
|
:play-quant 4 ;; make sure the pattern will only start on a beat that is divisible by 4, to stay in sync
|
|
:dur 1 ;; give each event a duration of 1 beat
|
|
:pfin 4 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
|
)
|
|
|
|
(play :foo)
|
|
(end :foo)
|
|
|
|
;; ok, I'm starting to try something of my own
|
|
(pb :my-foo
|
|
:note (pseq '(1 (1 2) (1 3) (1 4) 2 4))
|
|
:play-quant 3
|
|
:dur 1
|
|
)
|
|
|
|
(play :my-foo)
|
|
(stop :my-foo)
|
|
|
|
;; what's this :note? are they steps of an ocave?
|
|
(pb :my-notes
|
|
:note (pseq '(0 1 2 3 4 5 6 7 8 9))
|
|
:play-quant 3
|
|
:dur 1
|
|
)
|
|
|
|
(play :my-notes)
|
|
(stop :my-notes)
|
|
|
|
;; maybe! let's do octave
|
|
|
|
(pb :my-octave
|
|
:note (pseq '(0 1 2 3 4 5 6 7 (0 7)))
|
|
:dur (pseq (concatenate 'list (make-list 7 :initial-element 0.5) '(4 8)))
|
|
:play-quant 4
|
|
:dur 1
|
|
)
|
|
|
|
|
|
(play :my-octave)
|
|
(stop :my-octave)
|
|
|
|
;; why :dur doesn't influence things?
|
|
|
|
(pb :my-lengths
|
|
:note (pseq '(0 1))
|
|
:dur (pseq '(1 1 2 2 4 4 8 8 16 16))
|
|
:play-quant 4
|
|
)
|
|
(play :my-lengths)
|
|
(stop :my-lengths)
|
|
|
|
;; well that's because there was another :dur with single value, cool
|
|
|
|
;; maybe! let's do octave fixed
|
|
|
|
(pb :my-octave2
|
|
:note (pseq '(0 1 2 3 4 5 6 7 (0 7)) 1)
|
|
:dur (pseq (concatenate 'list (make-list 7 :initial-element 1) '(2 4)))
|
|
:play-quant 4
|
|
)
|
|
|
|
|
|
(play :my-octave2)
|
|
(end :my-octave2)
|
|
|
|
;; by adding 1 as pseq REPEATS thing, I can stop the pattern by END, which ends after the pattern completion
|
|
;; and pattern completes after single repetition,
|
|
;; but without END pattern repeats, that's cool
|
|
|
|
;;; now, what about other ways to set up pitch? apart from note there were other?
|
|
|
|
|
|
(pb :what-note
|
|
:note (pseq '(0 1 2 3 4 5 6 7 (0 7)) 1)
|
|
:octave 5
|
|
:dur (pseq (concatenate 'list (make-list 7 :initial-element 1) '(2 4)))
|
|
:play-quant 4
|
|
)
|
|
;; looks like octave 5 is default, and quite high.
|
|
;; 1 - 2 are barely audible
|
|
;; 3 is bass
|
|
|
|
|
|
(play :what-note)
|
|
(end :what-note)
|
|
|
|
|
|
(pb :what-degree
|
|
:octave 3
|
|
:note (pseq '(0 1 2 3 4 5 6 7 (0 7)) 1)
|
|
:dur (pseq (concatenate 'list (make-list 7 :initial-element 1) '(2 4)))
|
|
:play-quant 4
|
|
)
|
|
|
|
|
|
(play :what-degree)
|
|
(end :what-degree)
|
|
|
|
;; so, is that same thing?
|
|
|
|
;;; now. let's look at :root
|
|
|
|
(pb :what-root
|
|
:note (pseq '(0 7 (0 7)) 1)
|
|
:octave 4
|
|
:root 2
|
|
:dur (pseq '(1 1 3))
|
|
:play-quant 4
|
|
)
|
|
|
|
(play :what-root)
|
|
(end :what-root)
|
|
;; yup, root changes root of the key
|
|
|
|
;;; now let's try to write some chords?
|
|
(setq *M1* '(0 2 4))
|
|
(setq *Min1* '(0 1.5 4))
|
|
(setq *M3* '(2 4 6))
|
|
|
|
(setq *chord* *Min1*)
|
|
|
|
(pb :what-chord
|
|
:note (pseq `(,*m1* ,*min1*))
|
|
:octave 4
|
|
:root 2
|
|
:dur (pseq '(2 2) 1)
|
|
;; :play-quant 4
|
|
)
|
|
|
|
(play :what-chord)
|
|
(end :what-chord)
|
|
|
|
;; those are major and minor chord, but very ugly cheap sound.
|
|
;; is there are way to make it clear?
|
|
;; is that about "instrument"?
|
|
|
|
;; https://github.com/defaultxr/cl-patterns/blob/master/doc/supercollider-example.lisp
|
|
(in-package #:cl-collider)
|
|
(defsynth default ((gate 1) (freq 440) (out 0))
|
|
(let* ((env (env-gen.kr (asr 0.01 1 0.1) :gate gate :act :free))
|
|
(sig (sin-osc.ar freq 0 0.2)))
|
|
(out.ar out (pan2.ar sig 0 env))))
|
|
(defsynth kik ((freq 440) (out 0))
|
|
(let* ((env (env-gen.kr (env (list 0 1 0) (list 0.001 1)) :act :free))
|
|
(fenv (env-gen.kr (env (list 1 0) (list 0.25)) :level-scale freq))
|
|
(sig (sin-osc.ar fenv 0 0.2)))
|
|
(out.ar out (pan2.ar sig 0 env))))
|
|
(defsynth sine-wave ((note 60) (freq 400))
|
|
(let* ((freq (midicps note))
|
|
(sig (sin-osc.ar freq 0 .2)))
|
|
(out.ar 0 sig)))
|
|
|
|
(in-package #:cl-patterns)
|
|
|
|
(pb :what-instrument
|
|
:note (pseq `(0 1))
|
|
:instrument :default
|
|
:octave 5
|
|
:root 2
|
|
:dur (pseq '(2 2) 1)
|
|
;; :play-quant 4
|
|
)
|
|
|
|
(play :what-instrument)
|
|
(end :what-instrument)
|
|
|
|
|
|
;; changing instrument on the fly leaves something running
|
|
;; how do I disable it all?
|
|
(cl-patterns:stop t)
|
|
|
|
;;; and some aux functions discovered:
|
|
(all-chords)
|
|
(all-scales)
|
|
(all-tunings)
|
|
|
|
(defparameter *some-chord* (chord "Major Triad"))
|
|
(chord-notes *some-chord*)
|
|
|
|
;;; can I just use chord as :note ?
|
|
(mapcar #'chord-notes (list (chord "Major Triad") (chord "Minor Triad")))
|
|
|
|
(pb :what-predef-chord
|
|
:note (pseq (mapcar #'chord-notes (list (chord "Major Triad") (chord "Minor Triad") (chord "Minor 7th") (chord "Major 7th") (chord "Diminished Triad") (chord "Major Triad"))) 1)
|
|
:octave 4
|
|
:root 2
|
|
:dur (pseq '(2 2 4))
|
|
;; :play-quant 4
|
|
)
|
|
|
|
(play :what-predef-chord)
|
|
(end :what-predef-chord)
|
|
|
|
|
|
(in-package #:cl-collider)
|
|
(proxy :foo (sin-osc.ar 440 0 0.2))
|
|
|
|
;; so, attempt to call #'PLAY for those predef chords, leads to nothing playing
|
|
;; and previous things not starting.
|
|
;; more or less stable setup is
|
|
;; - restart emacs
|
|
;; - whole "setting-up-cl-collider"
|
|
;; - whole "supercollider-examples"
|
|
;; let's put that into single file maybe? as cargo cult
|