diff --git a/2022-09-04-more-synths-and-chord-progressions.lisp b/2022-09-04-more-synths-and-chord-progressions.lisp new file mode 100644 index 0000000..4f1d64f --- /dev/null +++ b/2022-09-04-more-synths-and-chord-progressions.lisp @@ -0,0 +1,334 @@ + +;;; maybe more synths, maybe trying for repeated phrases with different settings for whole phrase +;;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/strings/prophet5pwmStrings.scd +(in-package #:cl-collider) +(defsynth prophet5pwmStrings ((out 0) (pan 0.0) (freq 440) (amp 1.0) (gate 1) (att 0.01) + (rel 0) (sus 1) (dec 0.5) (lforate 10) (lfowidth 0.5) (cutoff 12000) (rq 0.5)) + (let* ((lfo (lf-tri.kr (mapcar (lambda (x) (* lforate x)) (list 1 1.01)) (make-list 2 :initial-element (rand.ir 0 2.0)))) + (pulse (pulse.ar (mapcar (lambda (x) (* freq x)) (list 1 1.01)) (+ (* lfo lfowidth) 0.5))) + (filter (rlpf.ar pulse cutoff rq)) + (env (env-gen.ar (adsr att dec sus rel amp) :gate gate :act :free))) + (out.ar out (pan2.ar (* (mix filter) env 0.5) pan)))) +;; (synth :prophet5pwmstrings) +;; (stop) + +(in-package #:cl-patterns) +(pb :foo-with-pluck-synth +:instrument :prophet5pwmStrings +:play-quant 4 + ;; :rq 0.8 + ;; :cutoff 35200 + ;; :dec 0.1 +;; :att 0.07 +;; :sus 0.8 +:legato 1 +:degree (pseq (list 0 1 2 3 4 5 6 7) 1) +:dur 1) +;; (play :foo-with-pluck-synth) +;; (end :foo-with-pluck-synth) +;; (stop :foo-with-pluck-synth) +;; +;; let's make it a simple gamma? +;; cool, and easy with the :degree (from pitch model http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html ) + +(pb :mary-had-a-little-lamb +:instrument :prophet5pwmStrings +:play-quant 16 +:legato 1 +:degree (pseq (list 6 5 4 5 6 6 6 5 5 5 6 6 6 6 5 4 5 6 6 6 6 5 5 6 5 4) 1) +:dur (pseq (list 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 4)) +:attack (pseq (list 0.1 0 0 0))) + + +;; (play :mary-had-a-little-lamb) +;; (end :mary-had-a-little-lamb) +;; (stop :mary-had-a-little-lamb) + +;;; sure, another? +;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/strings/strings.scd +;; (taken from http://sccode.org/1-5aD ) +(in-package #:cl-collider) + +(defsynth strings ((out 0) (freq 440) (amp 1) (gate 1) (pan 0) (freqLag 0.2) (att 0.001) (dec 0.1) (sus 0.75) (rel 0.3) + (rq 0.001) (combHarmonic 4) (sawHarmonic 1.5) (mix 0.33)) + (let* ((combFreq (/ 1 (* (lag.kr freq (/ freqLag 2)) combHarmonic))) + (envelope (env-gen.kr (adsr att dec sus rel amp) :gate gate :act :free)) + (snd-step-1 (sync-saw.ar (* freq (range (white-noise.kr) (/ 1 1.025) 1.025)) (* freq sawHarmonic) 8)) + (snd-step-2 (+ (* snd-step-1 (- 1 mix)) (pink-noise.ar (* 180 mix)))) + (snd-step-3 (comb-l.ar snd-step-2 combFreq combFreq -1)) ; try 1 for decay as well + (snd-step-4 (abs (resonz.ar snd-step-3 (lag.kr freq freqLag) rq))) + (snd-step-5 (* snd-step-4 envelope)) + (snd-step-6 (limiter.ar snd-step-5 amp))) + (out.ar out (pan2.ar snd-step-6 pan)))) +;; (synth :strings :freq 400) +;; (stop) + +(in-package #:cl-patterns) +(pb :foo-with-pluck-synth-with-strings +:instrument :strings +:play-quant 4 + ;; :rq 0.8 + ;; :cutoff 35200 + ;; :dec 0.1 +;; :att 0.07 +;; :sus 0.8 + ;; :freqLag 0.7 +:legato 1 +:degree (pseq (list 0 1 2 3 4 5 6 7) 1) +:dur 1) +;; (play :foo-with-pluck-synth-with-strings) +;; (end :foo-with-pluck-synth-with-strings) +;; (stop :foo-with-pluck-synth-with-strings) +;; +;; let's make it a simple gamma? +;; cool, and easy with the :degree (from pitch model http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html ) + +(pb :mary-had-a-little-lamb-with-strings + :instrument :strings + :play-quant 16 + :legato 1 + :degree (pseq (list 6 5 4 5 6 6 6 5 5 5 6 6 6 6 5 4 5 6 6 6 6 5 5 6 5 4) 1) + :dur (pseq (list 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 4)) + :attack (pseq (list 0.1 0 0 0))) + +;; (play :mary-had-a-little-lamb-with-strings) +;; (end :mary-had-a-little-lamb-with-strings) +;; (stop :mary-had-a-little-lamb-with-strings) +;; +;; cool, i like it + +;;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/winds/waveguideFlute.scd +;; let's try the winds? +(in-package #:cl-collider) +(defsynth waveguideFlute ((scl 0.2) (freq 440) (ipress 0.9) (ibreath 0.09) (ifeedbk1 0.4) (ifeedbk2 0.4) + (dur 1) (gate 1) (amp 2)) + (let* ((sr (sample-rate.ir)) + (cr (control-rate.ir)) + (a-block (reciprocal cr)) + (ifqc freq) + (kenv1 (env-gen.kr (env + (list 0.0 (* 1.1 ipress) ipress ipress 0.0) + (list 0.06 0.2 (- dur 0.46) 0.2) + :linear))) ; noise envelope + (kenv2 (env-gen.kr (env + (list 0.0 amp amp 0.0) + (list 0.1 (- dur 0.2) 0.1) + :linear))) ; overall envelope + (kenvibr (env-gen.kr (env + (list 0.0 0.0 1 1 0.0) + (list 0.5 0.5 (- dur 1.5) 0.5) + :linear))) ; vibrato envelope + (aflow1 (lf-clip-noise.ar sr kenv1)) ; create air flow and vibrato + (kvibr (sin-osc.ar 5 0 (* 0.1 kenvibr))) + + (asum1 (+ (* ibreath aflow1) kenv1 kvibr)) + (afqc (+ (reciprocal ifqc) (/ ifqc 12000000) (- (/ asum1 20000)) (- (/ 9 sr)) (- a-block))) + (fdbckArray (local-in.ar 1)) + (aflute1 fdbckArray) + (asum2 (+ asum1 (* aflute1 ifeedbk1))) + (ax (delay-c.ar asum2 + (- (reciprocal ifqc) (* a-block 0.5)) ; original has strange asum1/ifqc/cr thing, is that consequtive division, or third is on top? + (* afqc 0.5))) + (apoly (- ax (cubed ax))) + (asum3 (+ apoly (* aflute1 ifeedbk2))) + (avalue (lpf.ar asum3 2000)) + (aflute2 (delay-c.ar avalue (- (reciprocal ifqc) a-block) afqc)) + (fdbckArray (list aflute2)) + ;; (no-name (local-out.ar fdbckArray)) ; does that work at all? are there side effects? + (signalOut avalue)) + (local-out.ar fdbckArray) + (offset-out.ar 0 (list (* signalOut kenv2) (* signalOut kenv2))))) +(synth :waveguideFlute :dur 2 + :freq 300 + :amp 1 + ) +(stop) + +;; (scl 0.2) (freq 440) (ipress 0.9) (ibreath 0.09) (ifeedbk1 0.4) (ifeedbk2 0.4) +;; (dur 1) (gate 1) (amp 2) +(in-package #:cl-patterns) +(pb :foo-with-pluck-synth-with-flute +:instrument :waveguideFlute +:play-quant 4 + :ibreath 0.1 + :octave 5 +:degree (pseq (list 0 1 2 3 4 5 6 7) 1) +:dur 1) +;; (play :foo-with-pluck-synth-with-flute) +;; (end :foo-with-pluck-synth-with-flute) +;; (stop :foo-with-pluck-synth-with-flute) +;; +;; let's make it a simple gamma? +;; cool, and easy with the :degree (from pitch model http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html ) + +(pb :mary-had-a-little-lamb-with-flute + :instrument :waveguideFlute + :play-quant 16 + :legato 1 + :degree (pseq (list 6 5 4 5 6 6 6 5 5 5 6 6 6 6 5 4 5 6 6 6 6 5 5 6 5 4) 1) + :dur (pseq (list 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 4)) + :attack (pseq (list 0.1 0 0 0))) + +;; (play :mary-had-a-little-lamb-with-flute) +;; (end :mary-had-a-little-lamb-with-flute) +;; (stop :mary-had-a-little-lamb-with-flute) + +;;; I'd say - I messed something up, this doesn't quite work, too much breath, too little clear sound +;; almost nothing but break in 4th octave & higher + +;;; well, let's try some keyboard +;;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/keyboards/FMRhodes1.scd +(in-package #:cl-collider) +(defsynth FMRhodes1 ((out 0) (freq 440) (gate 1) (pan 0) (amp 0.1) (att 0.001) (rel 1) (lfoSpeed 4.8) (inputLevel 0.2) + (modIndex 0.2) (mix 0.2) (lfoDepth 0.1)) ;; all of these range from 0 to 1 + (let* ((env1 (env-gen.kr (perc att (* rel 1.25) inputLevel :lin))) + (env2 (env-gen.kr (perc att rel inputLevel :lin))) + (env3 (env-gen.kr (perc att (* rel 1.25) inputLevel :lin))) + (env4 (env-gen.kr (perc att (* rel 1.25) inputLevel :lin))) + (osc4 (* (sin-osc.ar freq) 6.7341546494171 modIndex env4)) + (osc3 (* (sin-osc.ar (* freq 2) osc4) env3)) + (osc2 (* (sin-osc.ar (* freq 30)) 0.683729941 env2)) + (osc1 (* (sin-osc.ar (* freq 2)) env1)) + (snd-step-1 (+ (mix (* osc3 (- 1 mix))) (* osc1 mix))) + (snd-step-2 (* snd-step-1 (range (sin-osc.ar lfoSpeed) (- 1 lfoDepth) 1))) + (snd-step-3 (* snd-step-2 (env-gen.kr (asr 0 1 0.1) :gate gate :act :free))) + (snd-step-4 (pan2.ar snd-step-3 pan amp))) + (out.ar out snd-step-4))) +(synth :fmrhodes1 :freq 800) +(stop) + +(in-package #:cl-patterns) +(pb :foo-with-pluck-synth-with-fmrhodes1 +:instrument :fmrhodes1 +:play-quant 4 + :legato 1 + :octave 3 + ;; :lfospeed 1 + ;; :inputlevel 0.1 + ;; :lfodepth 0.01 +:degree (pseq (list 0 1 2 3 4 5 6 7) 1) +:dur 1) +;; (play :foo-with-pluck-synth-with-fmrhodes1) +;; (end :foo-with-pluck-synth-with-fmrhodes1) +;; (stop :foo-with-pluck-synth-with-fmrhodes1) +;; +;; let's make it a simple gamma? +;; cool, and easy with the :degree (from pitch model http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html ) + +(pb :mary-had-a-little-lamb-with-fmrhodes1 + :instrument :fmrhodes1 + :play-quant 16 + :octave 3 + :degree (pseq (list 6 5 4 5 6 6 6 5 5 5 6 6 6 6 5 4 5 6 6 6 6 5 5 6 5 4) 1) + :dur (pseq (list 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 4)) + :legato (pseq (list 1 1 1 0.7))) ; unfortunately this is not by beats, but by count, not cooooool + +;; (play :mary-had-a-little-lamb-with-fmrhodes1) +;; (end :mary-had-a-little-lamb-with-fmrhodes1) +;; (stop :mary-had-a-little-lamb-with-fmrhodes1) + +;;; but now I have a keyboard, a bass and a somewhat drum +;; let's try something more? + +;;; i guess I'd need to better understand difference between pb pbind + +(pb :hm-lallaa + :instrument :fmrhodes1 + :octave 3 + :degree (pseq (list 0 1 4 8 (prest 0) 0 2 4 7 4 2) 1)) +(play :hm-lallaa) +(end :hm-lallaa) +(stop :hm-lallaa) +;; yup, that's a pause, cool +;; so, do I bring that stuff into a separate file? + +(mapcar (lambda (chord) (list (chord-name chord) (chord-notes chord))) (all-chords)) +(chord-notes (chord "Minor 7th")) +(chord-notes (chord "Minor 7th")) + + ;; :degree (pseq (mapcar #'chord-notes (list :major :minor :maj7 :major)) 1) + +;; now, + +(defun nchord (symbol &optional (base 0)) + "Return list of notes for chord names by SYMBOL over the BASE." + (mapcar (lambda (note) (+ base note)) (chord-notes symbol))) + +(nchord :major 3) + +(pb :hm-chords-progression + :instrument :fmrhodes1 + :octave 3 + ;; :degree (pseq (mapcar #'chord-notes (list :major :minor :maj7 :major)) 1) ; works, but can't insert (prest 0) among chords + ;; :degree (pseq (list (chord :major) (chord :minor) (chord :maj7) (chord :major)) 1) ; doesn't seem to work + :degree (pseq (list (nchord :major) (nchord :minor) (prest 0) (nchord :maj7) (nchord :major) (prest 0)) 1) ; doesn't seem to work + :base 2 + :root 5 + ) +(play :hm-chords-progression) +(end :hm-chords-progression) +(stop :hm-chords-progression) + +;; so, what's a good way to use them? just wrap separately into #'CHORD-NOTES +;; maybe at least for now +;; and then? how do I change the base note of the chord? I kind of remember that having 5th step 7chord is useful, and stuff + +;; oh, I guess I could just change :root attribute, as a stream? +;; hmmm + +;; but what if I want a sequence of chords, over different bases, like I IV V steps, and would want to change root for whole phrase +;; first off, I don't yet know how to repeate whole phrase several times with changing attributes, let's try that +;;; https://rockguitaruniverse.com/simple-easy-chord-progressions/ + +;; i - III - iv - VI +(pb :hm-chords-progress-em-g-am-c + :instrument :fmrhodes1 + :octave 3 + ;; :degree (pseq (mapcar #'chord-notes (list :major :minor :maj7 :major)) 1) ; works, but can't insert (prest 0) among chords + ;; :degree (pseq (list (chord :major) (chord :minor) (chord :maj7) (chord :major)) 1) ; doesn't seem to work + :degree (pseq (list (nchord :minor) (nchord :major 2) (nchord :minor 3) (nchord :major 5) (prest 0)) 1) ; doesn't seem to work + :dur (pseq (list 1 2 1 3 1)) + :base 2 + :root 5 + ) +(play :hm-chords-progress-em-g-am-c) +(end :hm-chords-progress-em-g-am-c) +(stop :hm-chords-progress-em-g-am-c) + +;; Am – F – C – G (i – VI – III – VII) +(pb :hm-chords-progress-am-f-c-g + :instrument :fmrhodes1 + :octave 3 + ;; :degree (pseq (mapcar #'chord-notes (list :major :minor :maj7 :major)) 1) ; works, but can't insert (prest 0) among chords + ;; :degree (pseq (list (chord :major) (chord :minor) (chord :maj7) (chord :major)) 1) ; doesn't seem to work + :degree (pseq (list (nchord :minor) (nchord :major 3) (nchord :minor 2) (nchord :major 6) (prest 0)) 1) ; doesn't seem to work + :dur (pseq (list 1 2 1 3 1)) + :base 2 + :root 5 + ) +(play :hm-chords-progress-am-f-c-g) +(end :hm-chords-progress-am-f-c-g) +(stop :hm-chords-progress-am-f-c-g) + +;; IV V iii vi (from video on japan's favourite chord progression) +;; https://youtu.be/6aezSL_GvZA +(pb :hm-chords-progress-golden-road + :instrument :strings + :octave 4 + :legato 1 + ;; :degree (pseq (mapcar #'chord-notes (list :major :minor :maj7 :major)) 1) ; works, but can't insert (prest 0) among chords + ;; :degree (pseq (list (chord :major) (chord :minor) (chord :maj7) (chord :major)) 1) ; doesn't seem to work + :degree (pseq (list (nchord :major 3) (nchord :major 4) (nchord :minor 2) (nchord :minor 5) ) 1) ; doesn't seem to work + :dur (pseq (list 4 4 4 4 )) + :root 0) +(play :hm-chords-progress-golden-road) +(end :hm-chords-progress-golden-road) +(stop :hm-chords-progress-golden-road) + +;; does it sound like in the video then? + +;;; would want +;; - giving chord name and base to get a pattern of arpeggio +;; - giving (note/chord) and rhythm to get form that single note + +;; latter should be possible from defining a subpattern? with static note? diff --git a/programming-music-journal.org b/programming-music-journal.org index c8caeaa..29cd366 100644 --- a/programming-music-journal.org +++ b/programming-music-journal.org @@ -297,3 +297,24 @@ http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html * [2022-09-04 Sun] ** evil marcro for wrapping consecutive values (or args) into pairwise brackets: well, not being inserted due to backspace, sad +* [2022-09-04 Sun] +** reading patterns.lisp to figure out bpind pdef and pb +found prest +#+begin_src common-lisp +(defclass prest () + ((value :initarg :value :initform 1)) + (:documentation "An object representing a rest. When set as a value in an event, the event's :type becomes :rest and the prest's value slot is used as the actual value for the event key instead.")) + +defun prest (&optional (value 1)) + Make a prest object, which, when used in a `pbind' or similar event pattern, turns the current event into a rest and yields VALUE for the key's value. + +Note that this is not a pattern; it is just a regular function that returns a prest object. + +Example: + +;; (next-upto-n (pbind :degree (pseq (list 0 1 (prest 2) 3) 1))) +;; ;=> ((EVENT :DEGREE 0) (EVENT :DEGREE 1) (EVENT :TYPE :REST :DEGREE 2) (EVENT :DEGREE 3)) +#+end_src + +is that pause? +but why would event then still have :DEGREE attribute?