more arpeggio, per-phrase-attr
This commit is contained in:
parent
12f0c80af7
commit
788c27c54b
|
@ -0,0 +1,533 @@
|
|||
|
||||
(in-package :cl-patterns)
|
||||
|
||||
(pdef :maybe-arpegio
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
(pbind :note (pseq (pnary #'nchord (pk :chord)) 2))))
|
||||
;; (play :maybe-arpegio)
|
||||
;; (end :maybe-arpegio)
|
||||
;; (stop :maybe-arpegio)
|
||||
(next-upto-n (pdef :maybe-arpegio) 10)
|
||||
|
||||
;; now about including patterns one into another, can I reference this pattern
|
||||
;; in another which would specify an instrument?
|
||||
;; judging by https://github.com/defaultxr/cl-patterns/blob/master/doc/patterns.org
|
||||
;; maybe #'PSYM or #'PPAR would help?
|
||||
|
||||
(pb :legato-keys
|
||||
:legato 1
|
||||
:instrument :fmrhodes1)
|
||||
|
||||
(pdef :maybe-joined-patterns (psym (ppar (list :maybe-arpegio :legato-keys))))
|
||||
;; (play :maybe-joined-patterns)
|
||||
;; (end :maybe-joined-patterns)
|
||||
;; (stop :maybe-joined-patterns)
|
||||
|
||||
;; nope, they just play in parallel, :legato-keys plays single note,
|
||||
;; how would I merge them into a single pattern \ stream?
|
||||
|
||||
;;; maybe #'IPSTREAM ?
|
||||
(pdef :attempt-2-at-joining (ipstream (list (pdef :maybe-arpegio) (pdef :legato-keys))))
|
||||
;; (play :attempt-2-at-joining)
|
||||
;; (stop :attempt-2-at-joining)
|
||||
;; nope.
|
||||
;; (and I actually can use #NEXT-UPTO-N to introspect
|
||||
|
||||
(next-upto-n (pdef :maybe-joined-patterns) 10)
|
||||
(next-upto-n (pdef :attempt-2-at-joining) 10) ; also has EVENT :TYPE :REST inserted
|
||||
|
||||
;;; what about #'PMETA ?
|
||||
;; nope
|
||||
;;; let's check how #'PBIND works, it might just be able to extend existing patterns
|
||||
;; looking at #'PBIND code I saw ":embed" key and went searching through the file
|
||||
;; and found this:
|
||||
;;
|
||||
;;; pchain
|
||||
;; :documentation Combine multiple patterns into one event stream.
|
||||
;; (next-n (pchain (pbind :foo (pseq '(1 2 3))) (pbind :bar (pseq '(7 8 9) 1))) 4)
|
||||
;;
|
||||
;; ;=> ((EVENT :FOO 1 :BAR 7) (EVENT :FOO 2 :BAR 8) (EVENT :FOO 3 :BAR 9) NIL)
|
||||
;; "see also pbind :embed key"
|
||||
;;
|
||||
;; So I don't know what :embed does, but pchain seems to be what I need, right?
|
||||
;;
|
||||
;; from the "patterns.org" : pchain - Chain patterns together by using the first source pattern’s output as the input to the second, etc.
|
||||
;; didn't seem like the thing
|
||||
|
||||
;;; let's try it
|
||||
(pdef :attempt-3
|
||||
(pchain (pdef :legato-keys) (pdef :maybe-arpegio)))
|
||||
(next-upto-n (pdef :attempt-3) 10)
|
||||
;; (play :attempt-3)
|
||||
;; (end :attempt-3)
|
||||
;; (stop :attempt-3)
|
||||
|
||||
;; that's it!
|
||||
;; now let's try :embed ?
|
||||
|
||||
(pb :attempt-4
|
||||
:instrument :fmrhodes1
|
||||
:legato 1
|
||||
:embed :maybe-arpegio)
|
||||
;; (play :attempt-4)
|
||||
;; (end :attempt-4)
|
||||
;; this also works, yay!
|
||||
;; now, can I have several :embed arguments?
|
||||
|
||||
(pbind :dur 2) ; so #'PBIND "binds keys to patterns"
|
||||
(pdef :with-lengths
|
||||
(pbind :dur 2)) ; #'PDEF gives this name
|
||||
; and takes in patterns, so can take in "pattern-constructors"
|
||||
(pb :with-lengths-2
|
||||
:dur 2) ; is a shorthand
|
||||
; where we can use "pattern-combiners" for each key anyway
|
||||
|
||||
(pb :attempt-5
|
||||
:instrument :fmrhodes1
|
||||
:legato 1
|
||||
:embed :with-lengths-2
|
||||
:embed :maybe-arpegio)
|
||||
;; (play :attempt-5)
|
||||
;; (end :attempt-5)
|
||||
;; (stop :attempt-5)
|
||||
;; this also works, yay!
|
||||
;; now, can I have several :embed arguments?
|
||||
(next-upto-n (pdef :attempt-5) 10)
|
||||
|
||||
;; for some reason :dur shows up in a stream printed form, but same thing plays
|
||||
;; maybe I need :embed in the beginning, so that I would overwrite it?
|
||||
;; nope. I just had (play :attempt-4), so whops, more than a reason to get emacs support package
|
||||
|
||||
;;; It works!
|
||||
;; yay.
|
||||
|
||||
;;; so, next? is trying to set attributes like :legato or :octave
|
||||
;; per tact \ phrase regardless of how many events are there
|
||||
;; maybe #'PMETA , maybe with :stepinject
|
||||
;; nah?
|
||||
;;
|
||||
;; or maybe still arpeggio?
|
||||
;; it would play first pattern until the end, but would also want the pattern of the repeating attribute to end
|
||||
;; right?
|
||||
;; I guess maybe as there are limits for "amount of events from stream"
|
||||
;; there could be limits for "amount of clock ticks / beats"?
|
||||
;; yup, pfindur
|
||||
|
||||
(pdef :with-with-beat-limiting (pfindur (pbind :eitght-beat-limiting t) 8))
|
||||
(pb :test-limiting
|
||||
:embed :with-with-beat-limiting
|
||||
:dur 1/4
|
||||
:degree (pwhite 0 7))
|
||||
(next-upto-n (pdef :test-limiting) 30)
|
||||
|
||||
;; nah, what do I really want?
|
||||
;; let's take the arpeggio as it is,
|
||||
;; but then to 2 tacts of 1 beat per event,
|
||||
;; and then 2 tacks of 1/4
|
||||
|
||||
(pb :try-arpeggio-with-durs
|
||||
:embed :maybe-arpegio
|
||||
)
|
||||
;; (play :try-arpeggio-with-durs)
|
||||
;; (end :try-arpeggio-with-durs)
|
||||
;; (stop :try-arpeggio-with-durs)
|
||||
|
||||
(pbind
|
||||
:dur (pseq (list 1 1/4)))
|
||||
;; now that maybe done with arpeggio?
|
||||
;; (next-upto-n (pdef :try-per-tact-with-parp) 20)
|
||||
(next-upto-n (parp
|
||||
(pbind :dur (pseq (list 1 1/2)))
|
||||
(pfindur (pr (pk :dur)) 4)) 30)
|
||||
;; oh, wow, yea
|
||||
(pdef :durations-per-tact
|
||||
(parp
|
||||
(pbind :value (pseq (list 1 1/2)))
|
||||
(pfindur (pr (pk :value)) 4)))
|
||||
(next-upto-n (pdef :durations-per-tact) 30)
|
||||
|
||||
(pb :try-arpeggio-with-durations-per-tact
|
||||
:instrument :fmrhodes1
|
||||
:embed :maybe-arpegio
|
||||
:dur (pdef :durations-per-tact)
|
||||
;; :embed :durations-per-tact
|
||||
)
|
||||
(next-upto-n (pdef :try-arpeggio-with-durations-per-tact) 40)
|
||||
;; (play :try-arpeggio-with-durations-per-tact)
|
||||
;; (stop :try-arpeggio-with-durations-per-tact)
|
||||
;; (end :try-arpeggio-with-durations-per-tact)
|
||||
|
||||
;; so, this is almost what I want?
|
||||
;; with durations I'd likely want either something different, or make sure
|
||||
;; that phrases can be sped up to the multiple
|
||||
;;
|
||||
;; but that's exactly what I want for legato?
|
||||
|
||||
(pb :try-arpeggio-with-legato-per-tact
|
||||
:instrument :fmrhodes1
|
||||
:embed :maybe-arpegio
|
||||
:legato (pdef :durations-per-tact)
|
||||
;; :embed :legato-per-tact
|
||||
)
|
||||
(next-upto-n (pdef :try-arpeggio-with-legato-per-tact) 40)
|
||||
;; (play :try-arpeggio-with-legato-per-tact)
|
||||
;; (stop :try-arpeggio-with-legato-per-tact)
|
||||
;; (end :try-arpeggio-with-legato-per-tact)
|
||||
;; oh no that's not it!
|
||||
;; :durations-per-tact don't actually look at :dur of the final stream
|
||||
;; but produce static
|
||||
;; (1 1 1 1 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1/2 1 1 1 1 1/2 1/2 1/2 1/2 1/2 1/2 1/2
|
||||
;; 1/2 1 1 1 1 1/2 1/2)
|
||||
;; stream. whlp.
|
||||
|
||||
;; so, what if that would be for any other type of attribute, not for duration
|
||||
;; then I could use pbind :dur (pk :dur) I guess,
|
||||
;; and then pfindur would use duration of the embedding stream?
|
||||
|
||||
(pdef :try-keep-attribute-per-tact
|
||||
(parp
|
||||
(pbind :value (pseq (list 1 1/2)))
|
||||
(pbind :dur (pfindur (pr (pk :dur)) 4))))
|
||||
(next-upto-n (pdef :try-keep-attribute-per-tact) 30)
|
||||
;; i think I just need to (pfindur (pr ...) 4)
|
||||
;; but that's for single value
|
||||
;; so if I'm keeping it too simple for stupid first step:
|
||||
(pdef :abc-per-tact
|
||||
(pseq (list
|
||||
(pfindur (pbind :attr "a" :dur (pk :dur)) 4)
|
||||
(pfindur (pbind :attr "b" :dur (pk :dur)) 4)
|
||||
(pfindur (pbind :attr "c" :dur (pk :dur)) 4))
|
||||
))
|
||||
(next-upto-n (pdef :abc-per-tact) 30)
|
||||
;; so right now this has default :dur of 1,
|
||||
;; but if I :embed this into a stream with variable
|
||||
|
||||
(pb :trying-abc-with-different-durations
|
||||
:dur 1/2
|
||||
:embed :abc-per-tact)
|
||||
(next-upto-n (pdef :trying-abc-with-different-durations) 30)
|
||||
;; yep, that seems to work
|
||||
|
||||
;; now I want to not hardcode :attr, and possibly not hardcode 4
|
||||
;; I don't know whether I can use actual :dur
|
||||
|
||||
(pb :trying-abc-with-different-durations-2
|
||||
:dur (pseq (list (pfindur 1 4) (pfindur 1/2 4)))
|
||||
:embed :abc-per-tact
|
||||
)
|
||||
(next-upto-n (pdef :trying-abc-with-different-durations-2) 30)
|
||||
;; yep, that seems to work too
|
||||
|
||||
;; so I could probably define that :attr-per-duration with a marco
|
||||
;; but is there a way to defite it with a fucntion?
|
||||
|
||||
|
||||
|
||||
;;; also, let's make our arpeggio aligned by 2 tacts in 4 measure, so 8 beats?
|
||||
;; there was something that aligns with padding pauses in the end?
|
||||
|
||||
(pdef :maybe-arpegio-padded
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
;; (pbind :note (psync (pseq (pnary #'nchord (pk :chord)) 2) 8))
|
||||
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)) 2)) 4)))
|
||||
;; (play :maybe-arpegio-padded)
|
||||
;; (end :maybe-arpegio-padded)
|
||||
;; (stop :maybe-arpegio-padded)
|
||||
(next-upto-n (pdef :maybe-arpegio-padded) 30)
|
||||
|
||||
(next-upto-n (psync (pseq (list 1 2 3) 6) 8) 30)
|
||||
;; maybe that doesn't work because #'PSYNC need to be in context of bound stream, with :dur present?
|
||||
;; that's possible
|
||||
|
||||
(next-upto-n (psync (pbind
|
||||
:attr (pseq (list 1 2 3) 6)
|
||||
:dur 1) 8) 30)
|
||||
;; yup, thats it
|
||||
|
||||
;; so. ugh. if I have arpeggio.
|
||||
;; then how do I add padding? possibly around the whole thing?
|
||||
;; but then I'm loosing information about each particular chord
|
||||
|
||||
;;; well, now I have arpegios psync'ed to 8 beats \ 2 tacts
|
||||
;; so I could try to do per tact legato
|
||||
|
||||
(pdef :legato-per-tact
|
||||
(pseq (list
|
||||
(pfindur (pbind :legato 1 :dur (pk :dur)) 8)
|
||||
(pfindur (pbind :legato 0.7 :dur (pk :dur)) 8)
|
||||
(pfindur (pbind :legato 0.2 :dur (pk :dur)) 8))
|
||||
))
|
||||
(next-upto-n (pdef :legato-per-tact) 30)
|
||||
|
||||
(pb :arpegio-synced-and-per-tact-legato
|
||||
:embed :maybe-arpegio-padded
|
||||
:embed :legato-per-tact)
|
||||
;; (play :arpegio-synced-and-per-tact-legato)
|
||||
;; (stop :arpegio-synced-and-per-tact-legato)
|
||||
(next-upto-n (pdef :arpegio-synced-and-per-tact-legato) 30)
|
||||
|
||||
;;; that is kind of a solution
|
||||
;; and likely mapping patterns is a thing, so I could have
|
||||
|
||||
;; now, let's try overwriting duration?
|
||||
|
||||
|
||||
;;; well, current padding is still "outside" of pseq that is limited to 2 repetitions.
|
||||
;; so, I'd want psync somehow inside of pseq?
|
||||
|
||||
;; arpegiator is like this
|
||||
(next-upto-n (pseq (list 0 1 2 3) 2) 30)
|
||||
;; but I want it to be 0 1 2 3 .... repeated as many times as needed to be inside of 8 beats, and padded with pauses
|
||||
|
||||
|
||||
(next-upto-n (psync (pbind :degree (pseq (list 0 1 2 3))) 8 8 ) 30)
|
||||
;; nope.
|
||||
;; well, i guess maybe it's here where I'd need pmeta?
|
||||
|
||||
|
||||
(pdef :maybe-arpegio-padded-2
|
||||
(parp (pbind :chord (pseq (list :minor-triad :major) 2))
|
||||
;; (pbind :note (psync (pseq (pnary #'nchord (pk :chord)) 2) 8))
|
||||
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)))) 8 8)))
|
||||
;; (play :maybe-arpegio-padded-2)
|
||||
;; (end :maybe-arpegio-padded-2)
|
||||
;; (stop :maybe-arpegio-padded-2)
|
||||
(next-upto-n (pdef :maybe-arpegio-padded-2) 30)
|
||||
|
||||
;; or maybe I need to make pseq repeat 1 time
|
||||
;; and then wrap that in repeat, and then do psync over that?
|
||||
|
||||
(next-upto-n (psync (pn (pbind :degree (pseq (list 0 1 2) 1))) 8 8 ) 30)
|
||||
;; pr - repeats each event - so 0 1 2 repeated once
|
||||
;; pn - loops source pattern - so 0 1 2 0 1 2 0 1 | psynced here
|
||||
;; because psync still considers per single event
|
||||
|
||||
;;; so the question is:
|
||||
;; how can I write a pseq and have it repeating for duration,
|
||||
;; taking into account durations of notes that can be set in the outer stream
|
||||
;; so that repeat would end on a final note and padded rest with pause, not breaking last loop?
|
||||
|
||||
;;; well, while I don't know the answer, let's work with "per phrase legato"
|
||||
;; just have 'breaking last loop iteration' repeat
|
||||
;; and play around with durations
|
||||
|
||||
(pb :lets-vary-durations-in-arpegio-with-phrase-legato
|
||||
:instrument :fmrhodes1
|
||||
:octave 3
|
||||
:embed :maybe-arpegio-padded-2
|
||||
:embed :legato-per-tact
|
||||
:dur 1/3
|
||||
)
|
||||
;; (play :lets-vary-durations-in-arpegio-with-phrase-legato)
|
||||
;; (end :lets-vary-durations-in-arpegio-with-phrase-legato)
|
||||
;; (stop :lets-vary-durations-in-arpegio-with-phrase-legato)
|
||||
|
||||
;; during the playthrough setting :dur to different 1 1/2 1/3 1/6, that's nice
|
||||
|
||||
|
||||
;;; now let's copy things over so that all components are close together:
|
||||
|
||||
;; exhibit A
|
||||
(defun not-perfect-but-arpeggio (chords &optional (phrase-dur 8))
|
||||
(parp
|
||||
(pbind :chord (pseq chords 2)) ; base for arpegio - for each chord next pattern will play out
|
||||
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)))) phrase-dur phrase-dur)))
|
||||
(pdef :maybe-arpegio-padded-3 (not-perfect-but-arpeggio (list :major :minor)))
|
||||
;; (play :maybe-arpegio-padded-3)
|
||||
;; (end :maybe-arpegio-padded-3)
|
||||
;; (stop :maybe-arpegio-padded-3)
|
||||
;; (next-upto-n (pdef :maybe-arpegio-padded-3))
|
||||
;; (next-upto-n (pdef (not-perfect-but-arpeggio (list :major :minor))) 30)
|
||||
;; (next-upto-n (not-perfect-but-arpeggio (list :major :minor)) 30)
|
||||
;; (next-upto-n (not-perfect-but-arpeggio (list :major :minor :minor-6th)) 30)
|
||||
|
||||
;; so to have patterns with arguments
|
||||
;; I just need to return the pattern - pbind or another constructor from the function
|
||||
;; and then bind it to the name with pdef, or just pass in to #NEXT-UPTO-N or to key in #'PB (likely, right?)
|
||||
|
||||
;; can I do same thing with legato per phrase?
|
||||
(defun attr-per-phrase (attr-name values &optional (phrase-dur 8))
|
||||
(pseq (mapcar (lambda (val) (pfindur (pbind attr-name val :dur (pk :dur)) phrase-dur phrase-dur)) values)))
|
||||
(attr-per-phrase :legato (list 1 0.7 0.2))
|
||||
;; #<PSEQ (#<PFINDUR (PBIND :LEGATO 1 :DUR #<PK :DUR 1>) 8 0>
|
||||
;; #<PFINDUR (PBIND :LEGATO 0.7 :DUR #<PK :DUR 1>) 8 0>
|
||||
;; #<PFINDUR (PBIND :LEGATO 0.2 :DUR #<PK :DUR 1>) 8 0>) :INF 0>
|
||||
;; wowy, is that what I think it is?
|
||||
|
||||
(pb :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually
|
||||
:embed (not-perfect-but-arpeggio (list :major :minor :minor-6th :minor-7th :major-7th :major)) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; each phrase takes single value for legato
|
||||
; even if amount of events in phrase change with change of :dur
|
||||
:dur 1/3
|
||||
)
|
||||
;; (play :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually)
|
||||
;; (end :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually)
|
||||
;; (stop :lets-have-arpeggio-with-phrase-settings-and-vary-other-things-manually)
|
||||
|
||||
;; and now I'm limited by my understanding of chords and how to select progressions
|
||||
;; also - the base for the chord! currently we only select root
|
||||
;; it's maybe not as clean as have root coupled with the chord, but could add attr-per-phrase with root seleciton, that could work?
|
||||
;; but! the root is in "note" mode or "degree" mode?
|
||||
(pb :is-root-degree-or-note
|
||||
:degree 0
|
||||
:root (pseq (list 0 1 2 3 4 5 6 7) 1))
|
||||
;; (play :is-root-degree-or-note)
|
||||
;; (end :is-root-degree-or-note)
|
||||
;; definitely degree, right?
|
||||
|
||||
;; so let's do arpegios for some of the chord progressions I had as whole chords?
|
||||
;; i - III - iv - VI
|
||||
(pb :lets-arpegio-i-III-iv-VI
|
||||
:embed (not-perfect-but-arpeggio (list :minor :major :minor :major)) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; each phrase takes single value for legato
|
||||
; even if amount of events in phrase change with change of :dur
|
||||
:embed (attr-per-phrase :root (list 0 2 3 5))
|
||||
:dur 1/4
|
||||
)
|
||||
;; (play :lets-arpegio-i-III-iv-VI)
|
||||
;; (end :lets-arpegio-i-III-iv-VI)
|
||||
;; (stop :lets-arpegio-i-III-iv-VI)
|
||||
|
||||
;; IV V iii vi
|
||||
(pb :lets-arpegio-IV-V-iii-vi
|
||||
:embed (not-perfect-but-arpeggio (list :major :major :minor :minor)) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; each phrase takes single value for legato
|
||||
; even if amount of events in phrase change with change of :dur
|
||||
:embed (attr-per-phrase :root (list 3 4 2 5))
|
||||
:dur 1
|
||||
)
|
||||
;; (play :lets-arpegio-IV-V-iii-vi)
|
||||
;; (end :lets-arpegio-IV-V-iii-vi)
|
||||
;; (stop :lets-arpegio-IV-V-iii-vi)
|
||||
|
||||
;;; now, if I want a simple pase line?
|
||||
;;; like taking a chord and holding it, or playing whole with simle pattern?
|
||||
(next-upto-n (pdef :lets-arpegio-iv-v-iii-vi) 30)
|
||||
;; well, #'not-perfect-but-arpeggio does inject :chord as an attribute
|
||||
;; but if I don't merge this with base line, and only #'PPAR, then base pattern \ stream wouldn't have it
|
||||
;; so, I guess I'd want to have "generic base line" that takes in a list of chords
|
||||
;; and pass in same list (or maybe even a different list sometimes)
|
||||
;; and well, I'd also need to pass in roots for those chords, since right now they are separate, oh well
|
||||
|
||||
(setq *my-chords* (list :major :major :minor :minor))
|
||||
;; (setq *my-chords* (list :major :minor))
|
||||
;; (setq *my-bases* (list 3 4))
|
||||
(setq *my-bases* (list 3 4 2 5))
|
||||
|
||||
;; let's have a phrase that plays chord over base for 4 beats - 2 tacts
|
||||
;; still would need parp, right?
|
||||
(pb :simple-base-line
|
||||
(parp
|
||||
(pbind
|
||||
:chord (pseq *my-chords* 2)
|
||||
:root (pseq *my-bases* 2)
|
||||
)
|
||||
(pbind
|
||||
:note (pnary #'chord-notes (pk :chord))
|
||||
:dur (pseq (list 4 1/2 1/2 (prest 3)) 1)) ; that's 2 tacts
|
||||
))
|
||||
(pb :simple-base
|
||||
:instrument :fmbass
|
||||
:embed :simple-base-line
|
||||
:embed (attr-per-phrase :octave (list 3 2) (* 4 2 4))) ; 4 beats per tact, 2 tacts per chord, 4 hard coded chords
|
||||
|
||||
;; (play :simple-base)
|
||||
;; (end :simple-base)
|
||||
;; (stop :simple-base)
|
||||
|
||||
;; other simpler way would be to make parp - with simple-base-line playing for each :octave
|
||||
|
||||
(next-upto-n (pdef :simple-base) 60)
|
||||
;;; and yes this could also be more configurable, let's just try to combine these first
|
||||
|
||||
;; IV V iii vi - same 3 4 2 5 from :simple-base
|
||||
(pdef :try-one-arpeggio-and-bass
|
||||
(ppar (list (pdef :simple-base) (pdef :lets-arpegio-IV-V-iii-vi))))
|
||||
;; (play :try-one-arpeggio-and-bass)
|
||||
;; (stop :try-one-arpeggio-and-bass)
|
||||
;; (end :try-one-arpeggio-and-bass)
|
||||
|
||||
|
||||
;;; wait, so my arpeggio doesn't keep whole 2 tacts of same chord, oh, sad
|
||||
|
||||
;; IV V iii vi
|
||||
(pb :lets-arpegio-IV-V-iii-vi
|
||||
;; :instrument :strings
|
||||
:embed (not-perfect-but-arpeggio (list :major :major :minor :minor) 1/4) ; each chord plays arpeggio for whole phrase
|
||||
:embed (attr-per-phrase :legato (list 1 0.7 0.2 0.8)) ; each phrase takes single value for legato
|
||||
; even if amount of events in phrase change with change of :dur
|
||||
:embed (attr-per-phrase :root (list 3 4 2 5))
|
||||
:dur 1/4
|
||||
)
|
||||
;; (next-upto-n (pdef :lets-arpegio-iv-v-iii-vi) 30)
|
||||
;; (play :lets-arpegio-IV-V-iii-vi)
|
||||
;; (end :lets-arpegio-IV-V-iii-vi)
|
||||
;; (stop :lets-arpegio-IV-V-iii-vi)
|
||||
|
||||
;; yup, :dur 1 and :dur 1/2 still produce 8 notes for the :chord
|
||||
|
||||
;; exhibit B
|
||||
(defun not-perfect-but-arpeggio (chords &optional (dur 1) (phrase-dur 8))
|
||||
(parp
|
||||
(pbind :chord (pseq chords 2)) ; base for arpegio - for each chord next pattern will play out
|
||||
(psync (pbind :note (pseq (pnary #'nchord (pk :chord)))
|
||||
;; :dur (pk :dur) ; looks like parent :dur here inaccessible
|
||||
:dur dur
|
||||
)
|
||||
phrase-dur phrase-dur)))
|
||||
|
||||
;; and now it's worse, since need to specify durations twice
|
||||
;; but should align with simple bass
|
||||
|
||||
;; same as before
|
||||
;; IV V iii vi - same 3 4 2 5 from :simple-base
|
||||
(pdef :try-one-arpeggio-and-bass
|
||||
(ppar (list (pdef :simple-base) (pdef :lets-arpegio-IV-V-iii-vi))))
|
||||
;; (play :try-one-arpeggio-and-bass)
|
||||
;; (stop :try-one-arpeggio-and-bass)
|
||||
;; (end :try-one-arpeggio-and-bass)
|
||||
|
||||
;;; let's try updating and rendering again?
|
||||
;; (render (pdef :try-one-arpeggio-and-bass) "/tmp/arpeggio-and-bass-1.wav" :dur 16)
|
||||
;; well, let' copy long recording thingy and just record already
|
||||
;; https://github.com/byulparan/cl-collider#record-audio-output
|
||||
;;; write a single channel to disk
|
||||
|
||||
;; we can write to buffer number out_buf_num by reading in from the 0 bus
|
||||
;; (in-package cl-collider)
|
||||
;; (defsynth disk_writer ((out_buf_num 99))
|
||||
;; (disk-out.ar out_buf_num (in.ar 0)))
|
||||
|
||||
;; (setf mybuffer (buffer-alloc (expt 2 17)))
|
||||
;; mybuffer
|
||||
|
||||
;; ;; start a disk_writer synth
|
||||
;; (setf writer_0 (synth 'disk_writer))
|
||||
|
||||
;; ;; make it output to buffer you allocated
|
||||
;; (ctrl writer_0 :out_buf_num (bufnum mybuffer))
|
||||
|
||||
;; ;; continuously write the buffer contents to a file
|
||||
;; (buffer-write mybuffer "/tmp/arpeggio-and-bass.aiff" :leave-open-p t)
|
||||
|
||||
;; ;; now play whatever sounds you like
|
||||
|
||||
;; ;; e.g.
|
||||
;; (in-package :cl-patterns)
|
||||
;; (play :try-one-arpeggio-and-bass)
|
||||
;; (stop :try-one-arpeggio-and-bass)
|
||||
|
||||
|
||||
;; ;; then when you are done
|
||||
|
||||
;; (in-package cl-collider)
|
||||
;; ;; stop the disk_writer synth
|
||||
;; (free writer_0)
|
||||
|
||||
;; ;; close and free the buffer
|
||||
;; (buffer-close mybuffer)
|
||||
;; (buffer-free mybuffer)
|
||||
|
||||
|
||||
;; ;; then you can play what you recorded with a utility like mpv:
|
||||
;; ;; mpv /tmp/foo.aiff
|
|
@ -322,7 +322,7 @@ or something
|
|||
what I want is "pitch model"
|
||||
http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html
|
||||
:degree - is from an octave, and :octave 5 default and quite high, :root is which octave to take
|
||||
** NEXT - how to keep same note pattern repeating with different settings of legato \ duration
|
||||
** DONE - how to keep same note pattern repeating with different settings of legato \ duration
|
||||
I'll try to define notes separately with pdef and insert it? would then single length would be for all?
|
||||
** so, I tried to figure out how to change parameters for whole "phrases"
|
||||
"automatic jazz" does that with getting new random value, that gets repeated "forever" until the end of the pattern
|
||||
|
@ -331,3 +331,77 @@ if I try to use not random, but "from sequence", then on pattern restart I'd get
|
|||
|
||||
so then "kind of working" solution, is keep melogy repeating,
|
||||
then - know what is the length of the melody and repeat for "amount of events" in the melody,
|
||||
* [2022-09-08 Thu]
|
||||
** one day I'll move all instruments into easy to evaluate \ import \ use package
|
||||
but not today? because I don't yet too comfortable with the concept of Common-Lisp packages
|
||||
** and today?
|
||||
*** TODO get more code on creating arpeggios by specifying chords
|
||||
not quite, but yeah
|
||||
*** DONE and maybe how to combine \ merge \ include patterns
|
||||
so that chord pattern is defined separately and merged into separate patterns for base \ melogy
|
||||
|
||||
one convenient way to do it is to use :embed key in the pdef
|
||||
#+begin_src common-lisp
|
||||
(pb :with-lengths-2
|
||||
:dur 2)
|
||||
(pb :attempt-5
|
||||
:instrument :fmrhodes1
|
||||
:legato 1
|
||||
:embed :with-lengths-2)
|
||||
(next-upto-n (pdef :attempt-5) 10)
|
||||
#+end_src
|
||||
|
||||
and there can be several :embed's yay
|
||||
|
||||
another pay is #'PCHAIN
|
||||
judging by documentation it's very similar, not sure when it would be more convenient
|
||||
#+begin_src common-lisp
|
||||
(pdef :attempt-3
|
||||
(pchain (pdef :legato-keys) (pdef :maybe-arpegio)))
|
||||
(next-upto-n (pdef :attempt-3) 10)
|
||||
#+end_src
|
||||
|
||||
*** DONE also - maybe I'd learn about setting parameters "per tact" and not "per event"
|
||||
- I already guess that it would be infinitely repeating pattern that somehow aligns by beat number, maybe?
|
||||
then we'd get emitting for example :legato for each event in a tact regardless of it being 1 or 1/16s
|
||||
|
||||
I think something similar I saw at #'PMETA, like connecting patterns with some kind of measuring
|
||||
|
||||
kind of have some kind of solution here
|
||||
** so what was going on today:
|
||||
*** :embed - in pb
|
||||
if I have separate stream \ patter with some of the values
|
||||
I can "include" it into currently defined stream.
|
||||
so for example notes and durations are saved under :melody-pattern
|
||||
|
||||
and other patterns embed it and specify own :instrument and :octave
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pb :attempt-5]]
|
||||
*** trying "attribute per tact" - with PARP - arpegio
|
||||
**** starting with durations per tact:
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pdef :durations-per-tact]]
|
||||
|
||||
not quite
|
||||
|
||||
**** then attribute per tact:
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pdef :abc-per-tact]]
|
||||
**** the simplest hardcoded version
|
||||
and with :legato
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::(pdef :legato-per-tact]]
|
||||
|
||||
**** to probably what I want?
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::defun attr-per-phrase (attr-name values &optional (phrase-dur 8)]]
|
||||
*** also wanted to "pad" arpeggio, so that it would fill full two tacts, but only have complete loop iterations
|
||||
in that I didn't succeed
|
||||
having PSYNC around PSEQ - inner pattern started last incomplete iteration instead of producing rest
|
||||
**** initial implementation also didn't fill two tacts
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::defun not-perfect-but-arpeggio (chords &optional (phrase-dur 8)]]
|
||||
in it the #'PSYNC didn't really work because it was around pattern that didn't have :dur
|
||||
**** next iteration that starts unfinished last loops
|
||||
[[file:2022-09-08-more-on-chord-melodies.lisp::defun not-perfect-but-arpeggio (chords &optional (dur 1) (phrase-dur 8)]]
|
||||
|
||||
but I have to pass in :dur,
|
||||
so in pattern I currently have to change it in two places.
|
||||
seems that "parent" pattern is inaccessible with (pk :dur)
|
||||
|
||||
- note: I somewhere read phrase "parent pattern", so possibly in some #'PFUNC or #'PNARY
|
||||
maybe I could access attributes of a pattern that :embed this one
|
||||
|
|
Loading…
Reference in New Issue