Compare commits
18 Commits
c563cae51b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b07c84a2f7 | ||
|
|
adb02840ba | ||
|
|
e6270ea435 | ||
|
|
00515cd9df | ||
|
|
788c27c54b | ||
|
|
12f0c80af7 | ||
|
|
6a9b9a88c4 | ||
|
|
0ae86a5f51 | ||
|
|
38eab3f355 | ||
|
|
c8c7b0a45c | ||
|
|
99dff2c53b | ||
|
|
6d54d6bf37 | ||
|
|
0ef13a532f | ||
|
|
babaf1156a | ||
|
|
e4a109e45e | ||
|
|
602fc34c0a | ||
|
|
ba4ee2767d | ||
|
|
da7eaa45b5 |
12
README.org
Normal file
12
README.org
Normal file
@@ -0,0 +1,12 @@
|
||||
#+title: Learning music with cl-patterns & cl-collider
|
||||
* structure of files here
|
||||
** dirty-journal
|
||||
per-day lisp files and single org-journal as I'm figuring things out for the first time
|
||||
** stabler-things
|
||||
cleaned up definitions and functions, saved for possible reuse
|
||||
1. setting-up.lisp
|
||||
What I evaluate to start up and test setup
|
||||
2. synthesizer.lisp
|
||||
single collection of definitions for instruments
|
||||
** and hopefully there will be cleaned up journal
|
||||
that would separate significant things I've been figuring out in a form that would be helpful for other to figure them out
|
||||
@@ -181,7 +181,7 @@
|
||||
|
||||
(pb :what-note
|
||||
:note (pseq '(0 1 2 3 4 5 6 7 (0 7)) 1)
|
||||
:octave 3
|
||||
:octave 5
|
||||
:dur (pseq (concatenate 'list (make-list 7 :initial-element 1) '(2 4)))
|
||||
:play-quant 4
|
||||
)
|
||||
@@ -283,19 +283,24 @@
|
||||
(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 `((chord "Major Triad") (chord "Minor Triad")))
|
||||
: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) 1)
|
||||
: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))
|
||||
|
||||
268
dirty-journal/2022-08-20-will-i-get-instruments.lisp
Normal file
268
dirty-journal/2022-08-20-will-i-get-instruments.lisp
Normal file
@@ -0,0 +1,268 @@
|
||||
|
||||
(setq *M1* '(0 2 4))
|
||||
(setq *Min1* '(0 1.5 4))
|
||||
(setq *M3* '(2 4 6))
|
||||
|
||||
(setq *chord* *Min1*)
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(start-clock-loop :tempo 110/60)
|
||||
(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)
|
||||
|
||||
(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))))
|
||||
|
||||
(server-query-all-nodes) ; not sure how to interpret, but all things submitted to servier to play?
|
||||
|
||||
|
||||
;; ok, reading found article: https://nunotrocado.com/software/cl-collider-tutorial-1.html
|
||||
(defsynth tone ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (saw.ar freq amp)))
|
||||
;; (synth 'tone)
|
||||
;; (stop)
|
||||
|
||||
(defparameter *tone*
|
||||
(synth 'tone
|
||||
:freq (midicps 42)
|
||||
:amp 0.3))
|
||||
(free *tone*)
|
||||
|
||||
|
||||
(defsynth tone-buzz ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune)))
|
||||
(/ amp 2))))
|
||||
|
||||
;; (let ((node (synth 'tone-buzz)))
|
||||
;; (sleep 2)
|
||||
;; (free node))
|
||||
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
|
||||
;; (synth 'tone-pluck)
|
||||
|
||||
;; (in-package #:cl-patterns)
|
||||
(all-instruments)
|
||||
(pb :what-instrumented
|
||||
:intrument :tone-pluck
|
||||
;; :note (pseq `(,*m1* ,*min1*))
|
||||
:note (pseq '(0 3 7) 1)
|
||||
:octave 4
|
||||
:root 2
|
||||
:dur (pseq '(2 2) )
|
||||
;; :play-quant 4
|
||||
)
|
||||
|
||||
;; (play :what-instrumented)
|
||||
;; (stop :what-instrumented)
|
||||
|
||||
;;; yo, I think I understood that predef chords stuff:
|
||||
|
||||
(pb :what-predef-chord
|
||||
:instrument :tone-buzz
|
||||
: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)
|
||||
|
||||
(pb :what-try-instrument
|
||||
:instrument :tone-pluck
|
||||
:note (pseq '(1 2 3 7) 1)
|
||||
:octave 4
|
||||
:root 2
|
||||
:dur (pseq '(2 2 4))
|
||||
;; :play-quant 4
|
||||
)
|
||||
|
||||
|
||||
;; (play :what-try-instrument)
|
||||
;; (stop :what-try-instrument)
|
||||
|
||||
(pb :what-instrumented-2-maybe
|
||||
:instrument :tone-pluck
|
||||
;; :note (pseq `(,*m1* ,*min1*))
|
||||
:note (pseq '(0 3 7) 1)
|
||||
:octave 4
|
||||
:root 2
|
||||
:dur (pseq '(2 2) )
|
||||
;; :play-quant 4
|
||||
)
|
||||
|
||||
;; (play :what-instrumented-2-maybe)
|
||||
;; (stop :what-instrumented-2-maybe)
|
||||
|
||||
|
||||
|
||||
;;; now let's try to get some synths for percussions?
|
||||
|
||||
|
||||
|
||||
|
||||
;; copied from https://github.com/defaultxr/cl-patterns/blob/master/doc/supercollider-example.lisp
|
||||
|
||||
(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))))
|
||||
(synth :kik)
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :what-percussion
|
||||
:instrument :kik
|
||||
;; :note (pseq `(,*m1* ,*min1*))
|
||||
:note (pseq '(0 3 7) 1)
|
||||
:octave 4
|
||||
:root 2
|
||||
:dur (pseq '(2 2) )
|
||||
;; :play-quant 4
|
||||
)
|
||||
;; (play :what-percussion)
|
||||
;; (stop :what-percussion)
|
||||
|
||||
;; well, I don't understand, do I go read supercollider docs?
|
||||
;; about EnvGen SinOsc ?
|
||||
;; woa, there's old archived https://github.com/madskjeldgaard/awesome-supercollider
|
||||
;;; let's try to convert drum-kik https://github.com/everythingwillbetakenaway/Synthdefs/blob/master/drum_kick.scd
|
||||
;; (
|
||||
;; SynthDef(\drum_kick, {
|
||||
;; arg freq=440, gate=1, amp=0.5, source,pan = 0.0 ;
|
||||
;; source =
|
||||
;; Pan2.ar(
|
||||
;; SinOsc.ar(EnvGen.kr(Env.perc(0.0001, 1.5, 1, -200), gate, 1000, 45, doneAction:2), 1, 1) +
|
||||
;; ((BPF.ar([GrayNoise.ar(6),GrayNoise.ar(6)],EnvGen.kr(Env.perc(0.001, 0.3, 1, -200), gate, 6000, 70), 1.5)).distort * Line.kr(0.3,0,0.1))
|
||||
;; *
|
||||
;; EnvGen.kr(Env.perc(0.0001, 0.09, amp, 8)),0);
|
||||
;; Out.ar(0, source);
|
||||
;; }).add;
|
||||
;; )
|
||||
;; Synth(\drum_kick);
|
||||
|
||||
(in-package #:cl-collider)
|
||||
|
||||
(defsynth drum-kik ((freq 440) (out 0) (gate 1) (amp 0.5) (pan 0.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))
|
||||
(pan (pan2.ar sig 0 env)))
|
||||
(out.ar out pan)))
|
||||
(synth :drum-kik)
|
||||
(cl-patterns::all-instruments)
|
||||
|
||||
;;; ok, fuck that let's play
|
||||
;; just do some percussion with existing kik and chord progressions, and maybe a melody
|
||||
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
(pb :what-predef-chord
|
||||
:instrument :tone-pluck
|
||||
: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)
|
||||
|
||||
(pb :what-basic-percussion
|
||||
:instrument :kik
|
||||
:note 0
|
||||
:dur (pseq '(1) 1) ; ok, too hard again, want to finish something and go on
|
||||
:play-quant 4)
|
||||
|
||||
;; (play :what-basic-percussion)
|
||||
;; (stop :what-basic-percussion)
|
||||
|
||||
;; how do I now join both of these?
|
||||
|
||||
(pb :first-composition (ppar (list :what-predef-chord :what-basic-percussion))) ; bs, wtf
|
||||
|
||||
(next-upto-n (ppar (list (pbind :dur (pn 1/2 4))
|
||||
(pbind :dur (pn 2/3 4)))))
|
||||
|
||||
(next-upto-n (ppar (list :what-basic-percussion :what-predef-chord)))
|
||||
|
||||
;; (play :first-composition)
|
||||
;; (stop :first-composition)
|
||||
|
||||
;; (next-upto-n (pmeta :pattern (pseq (list :what-basic-percussion :what-predef-chord) 1) :sync 2))
|
||||
|
||||
;; god, I have no idea how to have two patterns play at the same time =C
|
||||
|
||||
;; (play (list :what-basic-percussion :what-predef-chord))
|
||||
;; (stop (list :what-basic-percussion :what-predef-chord))
|
||||
;;
|
||||
;; welp that workds
|
||||
;; bs, but maybe I'll put it into file and get a break already
|
||||
|
||||
(in-package #:cl-collider)
|
||||
|
||||
;; from https://github.com/byulparan/cl-collider
|
||||
;;; write a single channel to disk
|
||||
|
||||
;; we can write to buffer number out_buf_num by reading in from the 0 bus
|
||||
(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/foo.aiff" :leave-open-p t)
|
||||
|
||||
;; now play whatever sounds you like
|
||||
|
||||
;; e.g.
|
||||
(proxy :blah (sin-osc.ar 440))
|
||||
(free :blah)
|
||||
|
||||
|
||||
;; then when you are done
|
||||
|
||||
;; 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
|
||||
|
||||
|
||||
|
||||
|
||||
;; (cl-patterns:stop t)
|
||||
171
dirty-journal/2022-08-21-parallel-and-precussion.lisp
Normal file
171
dirty-journal/2022-08-21-parallel-and-precussion.lisp
Normal file
@@ -0,0 +1,171 @@
|
||||
|
||||
(in-package #:cl-collider)
|
||||
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
;; (synth :tone-pluck)
|
||||
|
||||
(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))))
|
||||
;; (synth :kik)
|
||||
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
(pb :what-predef-chord
|
||||
:instrument :tone-pluck
|
||||
: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)
|
||||
|
||||
(pb :what-basic-percussion
|
||||
:instrument :kik
|
||||
:note 0
|
||||
:dur (pseq '(1 1 1 1 1) 1) ; ok, too hard again, want to finish something and go on
|
||||
:play-quant 4)
|
||||
|
||||
;; (play :what-basic-percussion)
|
||||
;; (stop :what-basic-percussion)
|
||||
|
||||
;;; now, previous stuff copied off the
|
||||
(pdef :maybe-parallel (ppar (list (pdef :what-basic-percussion) (pdef :what-predef-chord))))
|
||||
|
||||
(setq *maybe-parallel* (ppar (list (pdef :what-basic-percussion) (pdef :what-predef-chord))))
|
||||
;; (play *maybe-parallel*)
|
||||
|
||||
;; (play :maybe-parallel)
|
||||
;; (stop :maybe-parallel)
|
||||
|
||||
;; ok, that is a bit interesting? there's additional beep in the beginning
|
||||
|
||||
;; yay. so, it did parallel.
|
||||
;; how do I add pauses then?
|
||||
|
||||
(pb :what-symbols-percussion
|
||||
:instrument :kik
|
||||
:note 0
|
||||
:embed (pcycles "oo-o-o--oo--o--o")
|
||||
:dur 1
|
||||
:play-quant 4)
|
||||
|
||||
;; (play :what-symbols-percussion)
|
||||
;; (stop :what-symbols-percussion)
|
||||
|
||||
(pdef :better-parallel (ppar (list (pdef :what-symbols-percussion) (pdef :what-predef-chord))))
|
||||
;; (play :better-parallel)
|
||||
;; (stop :better-parallel)
|
||||
|
||||
;; well, I still don't understand the metering
|
||||
;; but good enough for now. let's go looking for the better definitions of percussions?
|
||||
|
||||
;;; let's start with trying to get synthdefs from super-collider guide?
|
||||
;; https://supercollider.github.io/examples
|
||||
;;
|
||||
;;
|
||||
;; {
|
||||
;; var snare, bdrum, hihat;
|
||||
;; var tempo = 4;
|
||||
;; tempo = Impulse.ar(tempo); // for a drunk drummer replace Impulse with Dust !!!
|
||||
;; snare = WhiteNoise.ar(Decay2.ar(PulseDivider.ar(tempo, 4, 2), 0.005, 0.5));
|
||||
;; bdrum = SinOsc.ar(Line.ar(120,60, 1), 0, Decay2.ar(PulseDivider.ar(tempo, 4, 0), 0.005, 0.5));
|
||||
;; hihat = HPF.ar(WhiteNoise.ar(1), 10000) * Decay2.ar(tempo, 0.005, 0.5);
|
||||
;; Out.ar(0, (snare + bdrum + hihat) * 0.4 ! 2)
|
||||
;; }.play
|
||||
|
||||
(in-package #:cl-collider)
|
||||
|
||||
(defsynth tempo ()
|
||||
(out.ar 0 (impulse.ar 4)))
|
||||
;; (synth :tempo)
|
||||
;; (stop)
|
||||
;;
|
||||
;; but is that multiple repeating
|
||||
|
||||
;; (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))))
|
||||
;; ;; (synth :kik)
|
||||
;;
|
||||
;; and how would I add :free / end to the synth thingy
|
||||
;;
|
||||
;; let's try snare
|
||||
;; WhiteNoise.ar(Decay2.ar(PulseDivider.ar(tempo, 4, 2), 0.005, 0.5));
|
||||
(defsynth snare ()
|
||||
(out.ar 0 (decay2.ar (pulse-divider.ar 4 4 2) 0.005 0.5))
|
||||
;; (white-noise.ar (decay2.ar (pulse-divider.ar 4 4 2) 0.005 0.5))
|
||||
)
|
||||
;; (synth :snare)
|
||||
;; (stop)
|
||||
|
||||
;;; let's try to figure out white noise
|
||||
(defsynth wh-no ()
|
||||
;; (out.ar 0 (white-noise.ar 1 1))
|
||||
(out.ar 0 (white-noise.ar))
|
||||
)
|
||||
;; (synth :wh-no)
|
||||
;; (stop)
|
||||
;;
|
||||
;; so, pulse-divider is a way to emit frequencies?
|
||||
;; https://doc.sccode.org/Classes/PulseDivider.html
|
||||
;;
|
||||
;; now to decay
|
||||
;; https://doc.sccode.org/Classes/Decay2.html
|
||||
;;
|
||||
;; still snare doesn't seem to work, even though I kind of understand it
|
||||
;; maybe if I add it to pattern as instrument?
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(all-instruments)
|
||||
(pb :what-test-percussion
|
||||
:instrument :wh-no
|
||||
:note 0
|
||||
:dur (pseq '(1 1 1 1 1) 1) ; ok, too hard again, want to finish something and go on
|
||||
:play-quant 4)
|
||||
|
||||
;; (play :what-test-percussion)
|
||||
;; (stop :what-test-percussion)
|
||||
|
||||
|
||||
;; // since attack and decay are a difference of two Decays,
|
||||
;; // swapping the values, the envelope turns upside down:
|
||||
;; plot({ Decay2.ar(Impulse.ar(1), 0.001, 0.01) })
|
||||
;; plot({ Decay2.ar(Impulse.ar(1), 0.01, 0.001) })
|
||||
|
||||
;; // used as an envelope
|
||||
;; { Decay2.ar(Impulse.ar(XLine.kr(1,50,20), 0.25), 0.01, 0.2, FSinOsc.ar(600)) }.play;
|
||||
|
||||
;; // compare the above with Decay used as the envelope
|
||||
;; { Decay.ar(Impulse.ar(XLine.kr(1,50,20), 0.25), 0.2, FSinOsc.ar(600), 0) }.play;
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth decay2 ()
|
||||
(out.ar 0 (decay2.ar (impulse.ar (x-line.kr 1 50 20) 0.2 (sin-osc.ar 600) 0)))
|
||||
;; (out.ar 0 (decay2.ar (impulse.ar (x-line.kr 1 50 20) 0.2 (sin-osc.ar 600) 0)))
|
||||
;; (white-noise.ar (decay2.ar (pulse-divider.ar 4 4 2) 0.005 0.5))
|
||||
)
|
||||
;; (synth :decay2)
|
||||
;; (stop)
|
||||
|
||||
;; bdrum = SinOsc.ar(Line.ar(120,60, 1), 0, Decay2.ar(PulseDivider.ar(tempo, 4, 0), 0.005, 0.5));
|
||||
;; well, let's try this one?
|
||||
|
||||
(defsynth maybe-bdrum ()
|
||||
(out.ar 0 (sin-osc.ar (line.ar 120 60 1) 0 (decay2.ar (pulse-divider.ar 4 4 4) 0.005 0.5)))
|
||||
)
|
||||
;; (synth :maybe-bdrum)
|
||||
;; (stop)
|
||||
204
dirty-journal/2022-08-28-trying-for-percussion-again.lisp
Normal file
204
dirty-journal/2022-08-28-trying-for-percussion-again.lisp
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
;;; so the copied from supercollider examples is
|
||||
;; {
|
||||
;; var snare, bdrum, hihat;
|
||||
;; var tempo = 4;
|
||||
;; tempo = Impulse.ar(tempo); // for a drunk drummer replace Impulse with Dust !!!
|
||||
;; snare = WhiteNoise.ar(Decay2.ar(PulseDivider.ar(tempo, 4, 2), 0.005, 0.5));
|
||||
;; bdrum = SinOsc.ar(Line.ar(120,60, 1), 0, Decay2.ar(PulseDivider.ar(tempo, 4, 0), 0.005, 0.5));
|
||||
;; hihat = HPF.ar(WhiteNoise.ar(1), 10000) * Decay2.ar(tempo, 0.005, 0.5);
|
||||
;; Out.ar(0, (snare + bdrum + hihat) * 0.4 ! 2)
|
||||
;; }.play
|
||||
|
||||
|
||||
;; and that didn't work
|
||||
;; (defsynth snare ()
|
||||
;; (out.ar 0 (decay2.ar (pulse-divider.ar 4 4 2) 0.005 0.5))
|
||||
;; ;; (white-noise.ar (decay2.ar (pulse-divider.ar 4 4 2) 0.005 0.5))
|
||||
;; )
|
||||
;; (synth :snare)
|
||||
;; (stop)
|
||||
|
||||
;;; advice I got:
|
||||
;; As for your question about the snare synthdef, pulse-divider doesn't actually generate any triggers on its own, it just outputs a trigger every div triggers. So instead you could try something like this:
|
||||
(in-package #:cl-collider)
|
||||
(defsynth snare ()
|
||||
(out.ar 0 (white-noise.ar (decay2.ar (pulse-divider.ar (impulse.ar 8) 4 2) 0.005 0.5))))
|
||||
;; (synth :snare)
|
||||
;; (stop)
|
||||
;;
|
||||
;; yup. that works (in a loop)
|
||||
;; now I want to figure out that :free thing
|
||||
|
||||
;;; continuation of advice
|
||||
;; But if you just want to use snare in a pattern, I would write it like this:
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth snare ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (white-noise.ar (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :snare)
|
||||
;; (stop)
|
||||
;; that's a bit longer that I'd like
|
||||
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :test
|
||||
:instrument :snare
|
||||
:dur 1
|
||||
;; :amp (pwhite 0.0 0.5)
|
||||
:pfindur 4)
|
||||
;; (play :test)
|
||||
;; (end :test)
|
||||
;;
|
||||
;; ok, that works
|
||||
;;
|
||||
;; of the things I really should do, is go and read
|
||||
;; about Envelope generators, ones that have that :act :free thing
|
||||
;;
|
||||
;; one other thing - is to get one or two other drums and mock up a beat
|
||||
|
||||
;; well, if I'm doing this in small steps, let's read about envelope
|
||||
;; and make first snare synth usable in patterns
|
||||
;;
|
||||
;; tried to read just about EnvGen and Env
|
||||
;; https://doc.sccode.org/Classes/EnvGen.html
|
||||
;; https://doc.sccode.org/Classes/Env.html
|
||||
;;
|
||||
;; then got directed to the Tutorial, good idea to read it,
|
||||
;; if not previous "first tutorial", then on concepts:
|
||||
;; http://doc.sccode.org/Tutorials/Streams-Patterns-Events1.html
|
||||
|
||||
|
||||
;;; So, env-gen takes in lists for intensity and timings, from that builds output signal that can be used in other gens?
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth env-test-1 ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (sin-osc.ar 440.0 0.0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :env-test-1)
|
||||
;; (stop)
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth env-test-1-1 ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (sin-osc.ar 440.0 0.0 (env-gen.ar (env (list 0 1 0.1 0) (list 0.005 0.01 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :env-test-1-1)
|
||||
;; (stop)
|
||||
(in-package #:cl-collider)
|
||||
(defsynth env-test-2 ((amp 0.5) (out 0) (start 100) (middle 400) (end 200))
|
||||
(out.ar out (* amp (sin-osc.ar (env-gen.ar (env (list start middle end) (list 0.5 1.0)) :act :free)))))
|
||||
|
||||
;; (synth :env-test-2)
|
||||
;; (synth :env-test-2 :start 200 :middle 200 :end 200)
|
||||
;; (synth :env-test-2 :start 200 :middle 300 :end 200)
|
||||
;; (synth :env-test-2 :start 100 :middle 400 :end 100)
|
||||
;; (stop)
|
||||
;;
|
||||
;; so, yes, env-gen can define stream of numbers by times, and the numbers can be used for example in sin-osc.ar frequency input
|
||||
|
||||
;; now, how could I make other percussions? attempting to look at the example from SC
|
||||
|
||||
;; {
|
||||
;; var snare, bdrum, hihat;
|
||||
;; var tempo = 4;
|
||||
;; tempo = Impulse.ar(tempo); // for a drunk drummer replace Impulse with Dust !!!
|
||||
;; snare = WhiteNoise.ar(Decay2.ar(PulseDivider.ar(tempo, 4, 2), 0.005, 0.5));
|
||||
;; bdrum = SinOsc.ar(Line.ar(120,60, 1), 0, Decay2.ar(PulseDivider.ar(tempo, 4, 0), 0.005, 0.5));
|
||||
;; hihat = HPF.ar(WhiteNoise.ar(1), 10000) * Decay2.ar(tempo, 0.005, 0.5);
|
||||
;; Out.ar(0, (snare + bdrum + hihat) * 0.4 ! 2)
|
||||
;; }.play
|
||||
;;
|
||||
;; so let's try bdrum?
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth bdrum ((amp 0.5) (out 0) )
|
||||
(out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :bdrum :amp 1)
|
||||
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth snare ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (white-noise.ar (env-gen.ar (env (list 0 1 0.3 0) (list 0.005 0.01 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :snare)
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth hihat ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (hpf.ar (white-noise.ar 1) 10000) (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free))))
|
||||
;; hihat = HPF.ar(WhiteNoise.ar(1), 10000) * Decay2.ar(tempo, 0.005, 0.5);
|
||||
;; (synth :hihat)
|
||||
|
||||
;;; whoa, now I can try to combine these in a pattern!
|
||||
;; let's just copy another pattern with my instruments maybe?
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :foo ;; define a new pattern named :foo
|
||||
:instrument :bdrum ;; 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 2 ;; give each event a duration of 1 beat
|
||||
:pfin 2 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
||||
)
|
||||
;; (play :foo)
|
||||
;; (end :foo)
|
||||
|
||||
(pb :fee ;; define a new pattern named :foo
|
||||
:instrument :hihat ;; 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 3 ;; give each event a duration of 1 beat
|
||||
:pfin 1 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
||||
)
|
||||
;; (play :fee)
|
||||
;; (end :fee)
|
||||
|
||||
(pb :fum ;; define a new pattern named :foo
|
||||
:instrument :snare ;; 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 0.5 ;; give each event a duration of 1 beat
|
||||
:pfin 8 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
||||
:amp 0.1
|
||||
)
|
||||
;; (play :fum)
|
||||
;; (end :fum)
|
||||
|
||||
(pdef :all-parallel (ppar (list (pdef :foo) (pdef :fee) (pdef :fum))))
|
||||
;; (play :all-parallel)
|
||||
;; (end :all-parallel)
|
||||
;;
|
||||
|
||||
;; (in-package #:cl-patterns)
|
||||
;; (render (pdef :all-parallel) "/tmp/perc-1.aiff" :dur 16)
|
||||
;; doesn't work for some reason
|
||||
;; let's write as I did previously, and maybe ask a question later
|
||||
|
||||
(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/foo.aiff" :leave-open-p t)
|
||||
|
||||
;; now play whatever sounds you like
|
||||
|
||||
;; stop the disk_writer synth
|
||||
(free writer_0)
|
||||
|
||||
;; close and free the buffer
|
||||
(buffer-close mybuffer)
|
||||
(buffer-free mybuffer)
|
||||
;; wow, now that's a success
|
||||
;; question on how to write
|
||||
;; and what else?
|
||||
364
dirty-journal/2022-09-01-more-percussions-and-write-to-file.lisp
Normal file
364
dirty-journal/2022-09-01-more-percussions-and-write-to-file.lisp
Normal file
@@ -0,0 +1,364 @@
|
||||
;;; copy from previous day
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth bdrum ((amp 0.5) (out 0) )
|
||||
(out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :bdrum :amp 1)
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth snare ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (white-noise.ar (env-gen.ar (env (list 0 1 0.3 0) (list 0.005 0.01 0.5)) :act :free)))))
|
||||
|
||||
;; (synth :snare)
|
||||
|
||||
(in-package #:cl-collider)
|
||||
(defsynth hihat ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (hpf.ar (white-noise.ar 1) 10000) (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free))))
|
||||
;; hihat = HPF.ar(WhiteNoise.ar(1), 10000) * Decay2.ar(tempo, 0.005, 0.5);
|
||||
;; (synth :hihat)
|
||||
|
||||
;;; whoa, now I can try to combine these in a pattern!
|
||||
;; let's just copy another pattern with my instruments maybe?
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :foo ;; define a new pattern named :foo
|
||||
:instrument :bdrum ;; 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 2 ;; give each event a duration of 1 beat
|
||||
:pfin 2 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
||||
)
|
||||
;; (play :foo)
|
||||
;; (end :foo)
|
||||
|
||||
(pb :fee ;; define a new pattern named :foo
|
||||
:instrument :hihat ;; 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 1 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
||||
)
|
||||
;; (play :fee)
|
||||
;; (end :fee)
|
||||
|
||||
(pb :fum ;; define a new pattern named :foo
|
||||
:instrument :snare ;; 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 0.5 ;; give each event a duration of 1 beat
|
||||
:pfin 8 ;; limit the length of the pattern to 4 events (the default is infinite events)
|
||||
:amp 0.1
|
||||
)
|
||||
;; (play :fum)
|
||||
;; (end :fum)
|
||||
|
||||
(pdef :all-parallel (ppar (list (pdef :foo) (pdef :fee) (pdef :fum))))
|
||||
;; (play :all-parallel)
|
||||
;; (end :all-parallel)
|
||||
|
||||
;;; new day.
|
||||
;; let's think more about it.
|
||||
;; my guess is that things don't align properly
|
||||
|
||||
|
||||
;; another new thing, I guess here drum is every 2nd beat, hihat every beat and snare double beats
|
||||
|
||||
;; let's try another beat by drum?
|
||||
;; tuum, tu-tu-tum, tum-tum-tum
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
;; 2 tacts of 4 beats each
|
||||
(pb :more-drum ;; define a new pattern named :more-drum
|
||||
:instrument :bdrum ;; 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 (pseq '(2.5 0.5 1 1 1 1 1) 1)
|
||||
)
|
||||
;; (play :more-drum)
|
||||
;; (end :more-drum)
|
||||
;; (stop :more-drum)
|
||||
;;
|
||||
;; what I need is seq as duration?
|
||||
;;
|
||||
;; ok. what kind of plates I need?
|
||||
;; maybe quick 6 pause 2, repeat
|
||||
(pb :hihat-aligned-with-long-notes-to-4
|
||||
:instrument :hihat
|
||||
:play-quant 4 ; that helps to start this rhythm not on current beat, but on some beat in future
|
||||
; to sync with others, ok.
|
||||
; but only works for startup? not for aligning after end of 1 cycle?
|
||||
:dur (pseq '(1 0.5 0.5 2) 1)
|
||||
:amp (pseq '(1 0.5 0.5 0.5) 1)
|
||||
;; how to make pause for 2?
|
||||
)
|
||||
;; (play :hihat-aligned-with-long-notes-to-4)
|
||||
;; (end :hihat-aligned-with-long-notes-to-4)
|
||||
|
||||
;; so, I'd like a pause in the beginning?
|
||||
;; like 2 beat pause in the beginning, start with 3rd beat?
|
||||
;; would aligning work for that?
|
||||
;;
|
||||
;; i don't think so.
|
||||
;;
|
||||
;; then let's try to read more articles on patterns (in SC)?
|
||||
;; maybe there will something about pauses
|
||||
;;
|
||||
;; or, let's finish this with long hihat in beginning
|
||||
|
||||
;; maybe 1 drum per beat will help me understand :play-quant better?
|
||||
;; i tried setting it to 16 for hihat and it still repeated itself without stop
|
||||
;; while I expected it to play once every two 4 tacts
|
||||
(pb :metered-beat
|
||||
:instrument :bdrum
|
||||
:dur 1
|
||||
:play-quant 4 ; skip first two beats?
|
||||
:amp (pseq '(1 0.5 0.5 0.5) 1))
|
||||
;; (play :metered-beat)
|
||||
;; (stop :metered-beat)
|
||||
;; I could try adding accents?
|
||||
|
||||
|
||||
(pb :single-hihat
|
||||
:instrument :hihat
|
||||
:dur (pseq '(1) 1)
|
||||
:play-quant 4)
|
||||
;; (play :single-hihat)
|
||||
;; (end :single-hihat)
|
||||
;; (stop :single-hihat)
|
||||
|
||||
;; so, it still repeats? hmmmmmm
|
||||
|
||||
;; ok, I have no idea how to alighn things with pauses
|
||||
;;
|
||||
;; let's go on and read http://doc.sccode.org/Tutorials/Streams-Patterns-Events3.html
|
||||
;; so Pseq would have offset? would that be used for pauses in between?
|
||||
;; and "pauses during pattern" could be simulated with "longer beats", even though how do I separate that from long-notes?
|
||||
|
||||
;; well, from
|
||||
;; pb :hihat-aligned-with-long-notes-to-4
|
||||
;; pb :single-hihat
|
||||
;; it seems that :play-quant helps to start-up new pattern on particular beat, for example 4th
|
||||
;; (starting from 0 that's start of a new tact in 4/4 meter)
|
||||
;; but doesn't help if pattern is less than 4 beats to align each repetition with start of new tact
|
||||
|
||||
;; (midinote-freq) ; this is for writing melodies
|
||||
|
||||
;;; so, some synths from article http://doc.sccode.org/Tutorials/Streams-Patterns-Events3.html
|
||||
;; (
|
||||
;; SynthDef( \help_SPE3_Mridangam, { |out, t_amp|
|
||||
;; var sound;
|
||||
|
||||
;; sound = Resonz.ar(
|
||||
;; WhiteNoise.ar(70) * Decay2.kr( t_amp, 0.002, 0.1 ),
|
||||
;; 60.midicps,
|
||||
;; 0.02,
|
||||
;; 4
|
||||
;; ).distort * 0.4;
|
||||
|
||||
;; Out.ar(out, sound);
|
||||
;; DetectSilence.ar(sound, doneAction: Done.freeSelf);
|
||||
;; }).add;
|
||||
|
||||
;; (in-package #:cl-collider)
|
||||
;; (defsynth help_spe3_mridangam ((amp 0.5) (out 0))
|
||||
;; (let* ((sound '())))
|
||||
;; (out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
;; ;; (synth ::bdrum)
|
||||
;; ;; (stop)
|
||||
;;
|
||||
;; well, it seems that these generators are not present in the cl library, that's ok
|
||||
;;
|
||||
;; should I try doing pauses by setting amptitude to 0?
|
||||
|
||||
(pb :single-hihat
|
||||
:instrument :hihat
|
||||
:dur (pseq '(1) )
|
||||
:amp (pseq '(0.5 0 0 0) 1)
|
||||
:play-quant 4)
|
||||
;; (play :single-hihat)
|
||||
;; (end :single-hihat)
|
||||
;; (stop :single-hihat)
|
||||
|
||||
;;; cool, i like that.
|
||||
;; so initial thing - metered beat and attempt at hiheads with pauses
|
||||
(pdef :metered-and-first-hihead
|
||||
(ppar (list (pdef :metered-beat) (pdef :hihat-aligned-with-long-notes-to-4))))
|
||||
;; (play :metered-and-first-hihead)
|
||||
;; (end :metered-and-first-hihead)
|
||||
|
||||
;;; trying quick 3-hihead, aligned with pauses
|
||||
(pb :hihead-3-quick-with-pauses-to-tact
|
||||
:instrument :hihat
|
||||
:play-quant 4 ; that helps to start this rhythm not on current beat, but on some beat in future
|
||||
; to sync with others, ok.
|
||||
; but only works for startup? not for aligning after end of 1 cycle?
|
||||
:dur (pseq '(1 0.5 0.5 0.5 1.5) 1)
|
||||
:amp (pseq '(0 0.5 0.5 0.5 0) 1)
|
||||
;; how to make pause for 2?
|
||||
)
|
||||
;; (play :hihead-3-quick-with-pauses-to-tact)
|
||||
;; (end :hihead-3-quick-with-pauses-to-tact)
|
||||
|
||||
(pdef :metered-and-three-quick
|
||||
(ppar (list (pdef :metered-beat) (pdef :hihead-3-quick-with-pauses-to-tact))))
|
||||
;; (play :metered-and-three-quick)
|
||||
;; (end :metered-and-three-quick)
|
||||
|
||||
(pb :pause-tact
|
||||
:instrument :hihat ; without instrument - :amp doesn't do anything
|
||||
:dur (pseq '(4) 1) ; just having 4 - repeats endlessly
|
||||
:amp 0)
|
||||
;; (play :pause-tact)
|
||||
;; (end :pause-tact)
|
||||
;; (stop :pause-tact)
|
||||
|
||||
;;; now let's add a pause tact
|
||||
(pdef :hihead-3-quick-and-pause
|
||||
(pseq (list
|
||||
(pdef :hihead-3-quick-with-pauses-to-tact)
|
||||
(pdef :pause-tact)) 1))
|
||||
;; (play :hihead-3-quick-and-pause)
|
||||
;; (end :hihead-3-quick-and-pause)
|
||||
;; (stop :hihead-3-quick-and-pause)
|
||||
|
||||
;;; well, that works somewhat.
|
||||
;; let's add this to my "more complicated drum line"
|
||||
(pdef :more-complicated-drum-and-three-quick-hiheads
|
||||
(ppar (list (pdef :more-drum) (pdef :hihead-3-quick-and-pause))))
|
||||
;; (play :more-complicated-drum-and-three-quick-hiheads)
|
||||
;; (end :more-complicated-drum-and-three-quick-hiheads)
|
||||
;;
|
||||
;;; yay, I guess!
|
||||
|
||||
;;; let's play all three in order?
|
||||
(pdef :all-from-today-in-order
|
||||
(pseq (list
|
||||
(pseq (list (pdef :metered-and-first-hihead)) 4)
|
||||
(pseq (list (pdef :all-parallel)) 3)
|
||||
(pseq (list (pdef :more-complicated-drum-and-three-quick-hiheads)) 4)
|
||||
(pseq (list (pdef :all-parallel)) 3)) 1))
|
||||
;; (play :all-from-today-in-order)
|
||||
;; (end :all-from-today-in-order)
|
||||
;; (stop :all-from-today-in-order)
|
||||
|
||||
;;; now let's try again to write this down with a more advised function
|
||||
|
||||
;; (in-package #:cl-collider)
|
||||
;; (in-package #:cl-patterns)
|
||||
;; (render (pdef :metered-and-three-quick) "/tmp/attempt-1.wav" :dur 4)
|
||||
;; let's copy the error
|
||||
;; There is no applicable method for the generic function
|
||||
;; #<STANDARD-GENERIC-FUNCTION CL-PATTERNS::BACKEND-INSTRUMENT-CONTROLS (1)>
|
||||
;; when called with arguments
|
||||
;; (:BDRUM (EVENT :INSTRUMENT :BDRUM :DUR 2.5 :DELTA 0)).
|
||||
;; [Condition of type SB-PCL::NO-APPLICABLE-METHOD-ERROR]
|
||||
;;
|
||||
;; with other pattern:
|
||||
;; There is no applicable method for the generic function
|
||||
;; #<STANDARD-GENERIC-FUNCTION CL-PATTERNS::BACKEND-INSTRUMENT-CONTROLS (1)>
|
||||
;; when called with arguments
|
||||
;; (:BDRUM
|
||||
;; (EVENT :INSTRUMENT :BDRUM :DUR 1 :PLAY-QUANT (4) :AMP 1 :DELTA 0)).
|
||||
;; [Condition of type SB-PCL::NO-APPLICABLE-METHOD-ERROR]
|
||||
|
||||
;;; so let's write them with previous writing method?
|
||||
;; and save a link to it?
|
||||
|
||||
;;; oh, but there's "non-real time rendering" in cl-collider
|
||||
;; let's try that? I don't see how to connect it with the patterns
|
||||
;;
|
||||
;; so https://github.com/byulparan/cl-collider#record-audio-output it is
|
||||
;;; 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/all-from-today-in-order.aiff" :leave-open-p t)
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
;; now play whatever sounds you like
|
||||
(play :all-parallel)
|
||||
(end :all-parallel)
|
||||
(play :metered-and-first-hihead)
|
||||
(end :metered-and-first-hihead)
|
||||
(play :more-complicated-drum-and-three-quick-hiheads)
|
||||
(end :more-complicated-drum-and-three-quick-hiheads)
|
||||
(play :all-from-today-in-order)
|
||||
(end :all-from-today-in-order)
|
||||
|
||||
;; e.g.
|
||||
(proxy :blah (sin-osc.ar 440))
|
||||
(free :blah)
|
||||
|
||||
|
||||
;; 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
|
||||
|
||||
(in-package #:cl-collider)
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bass/acidOto3091.scd
|
||||
|
||||
(defsynth bdrum ((amp 0.5) (out 0) )
|
||||
(out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
;; out = 0, gate = 1, freq = 440, amp = 0.1, pan = 0, att = 0.001, dec = 0.5, sus = 0.1, rel = 0.5, curve = -4,
|
||||
;; // Other Controls
|
||||
;; // width is 0 - 1
|
||||
;; // filterRange is in octaves
|
||||
;; lagTime = 0.12, filterRange = 6, width = 0.51, rq = 0.3;
|
||||
(defsynth acid0to3091 ((amp 0.5) (out 0) (gate 1) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0) :gate gate))
|
||||
;; (filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (list (* -1 curve) curve curve curve ) 1) gate :act :free))
|
||||
;; this is likely not correct way to set up cure of the form curve: [-1 * curve, curve, curve, curve],
|
||||
;; does that mean multichannel things?
|
||||
;; let's just set as single curve and check how it looks?
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (* -1 curve) 1) :gate gate :act :free))
|
||||
;; is LFPulse.ar(...).range(-1, 1) gets from _range ?
|
||||
(sndStep1 (_range nil (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
(synth :acid0to3091)
|
||||
(stop)
|
||||
|
||||
;; that a nice acid base, just not freeing the thing, so can't be used as is, sad.
|
||||
;; let's try something else?
|
||||
|
||||
;;; (and that one seems interesting for later : https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bass/fmBass.scd )
|
||||
;;
|
||||
;;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bass/bassWarsaw.scd
|
||||
(defsynth fmBass ((out 0) (freq 440) (gate 1) (amp 0.5) (pan 0) (att 0.01) (dec 0.3) (sus 0.4) (rel 0.1) (slideTime 0.17) (cutoff 1100) (width 0.15) (detune 1.005) (preamp 4))
|
||||
(let* ((env (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (lag.kr freq slideTime))
|
||||
(sndStep1 (var-saw.ar freq 0 width preamp))
|
||||
(sndStep2 (distort sndStep1))
|
||||
(sndStep3 (* sndStep2 env))
|
||||
(sndStep4 (lpf.ar sndStep3 cutoff amp)))
|
||||
(out.ar out (pan2.ar sndStep4 pan))))
|
||||
(synth :fmBass :freq 80)
|
||||
(stop)
|
||||
|
||||
;; overall this is not quite success, not quite a failure
|
||||
;; I've practiced searching for tihngs I don't konw between the libraries
|
||||
165
dirty-journal/2022-09-02.lisp
Normal file
165
dirty-journal/2022-09-02.lisp
Normal file
@@ -0,0 +1,165 @@
|
||||
;;; my yesterday's attempt
|
||||
|
||||
(in-package #:cl-collider)
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bass/acidOto3091.scd
|
||||
|
||||
(defsynth bdrum ((amp 0.5) (out 0) )
|
||||
(out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
(defsynth acid0to3091-my-attempt ((amp 0.5) (out 0) (gate 1) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0) :gate gate))
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (* -1 curve) 1) :gate gate :act :free))
|
||||
(sndStep1 (_range nil (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
;; (synth :acid0to3091-my-attempt :freq 80)
|
||||
;; (stop)
|
||||
|
||||
;; after getting help with translation of other synth examples
|
||||
(defsynth acid0to3091-from-getting-help ((amp 0.5) (out 0) (gate 1) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0) :gate gate))
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (list (* -1 curve) curve curve) 1) :gate gate :act :free))
|
||||
(sndStep1 (range (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
;; (synth :acid0to3091-from-getting-help :freq 80)
|
||||
;; (stop)
|
||||
;; and let's remove gate?
|
||||
|
||||
(defsynth acid0to3091-without-gate ((amp 0.5) (out 0) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0)))
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (list (* -1 curve) curve curve) 1) :act :free))
|
||||
(sndStep1 (range (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
;; (synth :acid0to3091-without-gate :freq 80)
|
||||
;; (stop)
|
||||
;; just removing gate does nothing? so maybe gate should be controlled from patterns? by pasting in another
|
||||
;; and sound the same, so I'd need to put in maybe an envelope? in a pattern?
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :foo-with-acid
|
||||
|
||||
:instrument :acid0to3091-from-getting-help
|
||||
:play-quant 4
|
||||
:freq (pseq (list 40 50 60 70 80) 1)
|
||||
:dur (pseq (list 1 2))
|
||||
)
|
||||
;; (play :foo-with-acid)
|
||||
;; (end :foo-with-acid)
|
||||
;;
|
||||
;; wait, so it does work? maybe because "gate" is default parameter
|
||||
;; that gets created when events with duration get created?
|
||||
|
||||
;;; fmbass after getting help:
|
||||
(in-package #:cl-collider)
|
||||
;;; my attempt
|
||||
;;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bass/bassWarsaw.scd
|
||||
(defsynth fmBass-my-attempt ((out 0) (freq 440) (gate 1) (amp 0.5) (pan 0) (att 0.01) (dec 0.3) (sus 0.4) (rel 0.1) (slideTime 0.17) (cutoff 1100) (width 0.15) (detune 1.005) (preamp 4))
|
||||
(let* ((env (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (lag.kr freq slideTime))
|
||||
(sndStep1 (var-saw.ar freq 0 width preamp))
|
||||
(sndStep2 (distort sndStep1))
|
||||
(sndStep3 (* sndStep2 env))
|
||||
(sndStep4 (lpf.ar sndStep3 cutoff amp)))
|
||||
(out.ar out (pan2.ar sndStep4 pan))))
|
||||
;; (synth :fmBass-my-attempt :freq 80)
|
||||
;; (stop)
|
||||
(defsynth fmBass ((out 0) (freq 440) (gate 1) (amp 0.5) (pan 0) (att 0.01) (dec 0.3) (sus 0.4) (rel 0.1) (slideTime 0.17) (cutoff 1100) (width 0.15) (detune 1.005) (preamp 4))
|
||||
(let* ((env (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (lag.kr freq slideTime))
|
||||
(sndStep1 (var-saw.ar (list freq (* freq detune)) 0 width preamp))
|
||||
(sndStep2 (distort (mix sndStep1)))
|
||||
(sndStep3 (* sndStep2 env))
|
||||
(sndStep4 (lpf.ar sndStep3 cutoff amp)))
|
||||
(out.ar out (pan2.ar sndStep4 pan))))
|
||||
;; (synth :fmBass :freq 80)
|
||||
;; (stop)
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :foo-with-fmbass
|
||||
:instrument :fmBass
|
||||
:play-quant 4
|
||||
:legato 1
|
||||
:freq (pseq (list 40 50 60 70 80) 1)
|
||||
:dur 1 ;; (pseq (list 1 2 3))
|
||||
)
|
||||
;; (play :foo-with-fmbass)
|
||||
;; (end :foo-with-fmbass)
|
||||
|
||||
;; changing :legato between 1 0.7 0.4 0.2
|
||||
;; and duration between 1 0.5 0.2
|
||||
;; produces cool sounds, and reevaluation while thing runs on #'PLAY is super cool
|
||||
;;
|
||||
;; apart from pitch model I'd like to learn how to merge patterns, so that all notes of phrase would play on one setting for :dur & :legato
|
||||
;; then on others,
|
||||
|
||||
(in-package #:cl-collider)
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bells/glockenspiel.scd
|
||||
;; Skipping because of dyn-klang.ar ? not having arguments?
|
||||
;; (defsynth glockenspiel ((freq 440) (amp 0.01) (pan 0) (out 0) (att 0.001) (rel 6) (exciterRel 0.05))
|
||||
;; (let* ((envelope (env-gen.kr (perc att exciterRel 0.25)))
|
||||
;; (exciter (white-noise.ar envelope))
|
||||
;; (snd (dyn-klang.ar (list (list 1 2 2.803 3.871 5.074 7.81 10.948 14.421) ;; harmonics
|
||||
;; (list 1 0.044 0.891 0.0891 0.794 0.1 0.281 0.079) ;; amplitudes
|
||||
;; (list 1 0.205 1 0.196 0.339 0.047 0.058 0.047)) ;; ring times
|
||||
|
||||
;; )))))
|
||||
|
||||
;; too bad example has /input and /freqoffset : http://doc.sccode.org/Classes/DynKlank.html
|
||||
;; (defsynth whelp ((freq 40) (rel 6))
|
||||
;; (out.ar 1 (dyn-klang.ar (list (list 1 2 2.803 3.871 5.074 7.81 10.948 14.421) ;; harmonics
|
||||
;; (list 1 0.044 0.891 0.0891 0.794 0.1 0.281 0.079) ;; amplitudes
|
||||
;; (list 1 0.205 1 0.196 0.339 0.047 0.058 0.047)) ;; ring times
|
||||
|
||||
;; freq rel)))
|
||||
|
||||
;; (synth :whelp)
|
||||
;; (stop)
|
||||
|
||||
;;; so, let's go with another?
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/guitar/pluck.scd
|
||||
(defsynth pluck-synth-sample ((amp 0.1) (freq 440) (decay 5) (coef 0.1) (pan 0))
|
||||
(let* ((envelope (env-gen.kr (linen 0 decay 0) :act :free))
|
||||
(snd-step-1 (pluck.ar (white-noise.ar amp) (impulse.kr 0) 0.1 (reciprocal freq) decay coef))
|
||||
(snd-step-2 (pan2.ar snd-step-1 pan)))
|
||||
(out.ar 0 (list snd-step-2 snd-step-2))))
|
||||
;;; ??? Big question: what's with the ENVELOPE that is not inputed anywhere
|
||||
;; (synth :pluck-synth-sample :freq 360 :decay 9)
|
||||
;; (stop)
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :foo-with-pluck-synth
|
||||
:instrument :pluck-synth-sample
|
||||
:play-quant 4
|
||||
;; :legato 1
|
||||
:decay 2
|
||||
:freq (pseq (list 340 350 360 370 380) 1)
|
||||
:dur 2 ;; (pseq (list 1 2 3))
|
||||
)
|
||||
;; (play :foo-with-pluck-synth)
|
||||
;; (end :foo-with-pluck-synth)
|
||||
;; (stop :foo-with-pluck-synth)
|
||||
|
||||
;;; let's get some chords, from a previous day and stop for tonight
|
||||
;; so, from 08.19
|
||||
|
||||
(pb :what-predef-chord
|
||||
:instrument :pluck-synth-sample
|
||||
: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
|
||||
:decay (pseq (list 2 2 4))
|
||||
:dur (pseq (list 2 2 4))
|
||||
;; :play-quant 4
|
||||
)
|
||||
|
||||
;; (play :what-predef-chord)
|
||||
;; (end :what-predef-chord)
|
||||
;; (stop :what-predef-chord)
|
||||
56
dirty-journal/2022-09-03-small-time-more-synthdefs.lisp
Normal file
56
dirty-journal/2022-09-03-small-time-more-synthdefs.lisp
Normal file
@@ -0,0 +1,56 @@
|
||||
(in-package #:cl-collider)
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths
|
||||
;; https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/strings/violin.scd
|
||||
|
||||
(defsynth violin ((freq 440) (gate 1) (amp 1) (pan 0) (out 0) (att 0.1) (dec 0.1) (sus 0.5) (rel 0.1)
|
||||
(vRate 4.6) (vDepth 0.02) (vAtt 0.15) (vRateVar 0.25) (vDepthVar 0.05)
|
||||
(pwmVarRate 2) (pwmMin 0.7) (pwmMax 0.8) (pwmRate 5)
|
||||
(bridgeFreq 2500) (scratchDepth 0.15))
|
||||
(let* ((scratch (+ 1.025 (env-gen.kr (perc att (* 1.25 dec) scratchDepth))))
|
||||
(envelope (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (vibrato.kr freq vRate vDepth (+ att dec) vAtt vRateVar vDepthVar))
|
||||
(pwm-step-1 (range (sin-osc.kr pwmRate (rand.ir 0.0 1.0)) pwmMin pwmMax))
|
||||
(pwm-step-2 (* pwm-step-1 (range (lf-noise2.kr pwmVarRate) 0.2 0.8)))
|
||||
(snd-step-1 (var-saw.ar (*
|
||||
(lag.kr freq)
|
||||
(range (lf-pulse.ar (* freq 1.5)) (/ 1 scratch) scratch))))
|
||||
(snd-step-2 (+ (* snd-step-1 0.7)
|
||||
(bpf.ar snd-step-1 bridgeFreq 2 2)))
|
||||
(snd-step-3 (* snd-step-2 amp envelope)))
|
||||
(out.ar out (pan2.ar snd-step-3 pan))))
|
||||
;; (synth :violin :freq 400)
|
||||
;; (stop)
|
||||
(in-package #:cl-patterns)
|
||||
(pb :foo-with-pluck-synth
|
||||
:instrument :violin
|
||||
:play-quant 4
|
||||
:decay 2
|
||||
:att 0.07
|
||||
:sus 0.8
|
||||
:amp 0.1
|
||||
: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 :violin
|
||||
: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))
|
||||
:scratchdepth (pseq (list 0.1 0 0 0))
|
||||
:vdepth (pseq (list 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.02 0.06))
|
||||
)
|
||||
|
||||
;; (play :mary-had-a-little-lamb)
|
||||
;; (end :mary-had-a-little-lamb)
|
||||
;; (stop :mary-had-a-little-lamb)
|
||||
|
||||
;; there has to be a better way to split the tacts
|
||||
;; (render (pdef :mary-had-a-little-lamb) "/tmp/mary.wav" :dur 32)
|
||||
345
dirty-journal/2022-09-04-more-synths-and-chord-progressions.lisp
Normal file
345
dirty-journal/2022-09-04-more-synths-and-chord-progressions.lisp
Normal file
@@ -0,0 +1,345 @@
|
||||
|
||||
;;; 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 (chord 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 :violin
|
||||
:instrument :fmrhodes1
|
||||
:octave 4
|
||||
:amp 0.2
|
||||
: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
|
||||
;; :degree (pseq (list 1 2 3) 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?
|
||||
|
||||
;;; now, I'd like to use (render (pdef :your-pattern) "/path/to/output.wav" :dur 4)
|
||||
;; for that I'd need to use more recent version than I get from quicklisp, so clone repo
|
||||
quicklisp:*local-project-directories*
|
||||
(ql:register-local-projects)
|
||||
(ql:where-is-system :cl-patterns) ;; #P"/home/efim/quicklisp/local-projects/cl-patterns/"
|
||||
|
||||
;; (render (pdef :hm-chords-progress-golden-road) "/tmp/chords-4.wav" :dur 16)
|
||||
130
dirty-journal/2022-09-05-maybe-sequences-from-chords.lisp
Normal file
130
dirty-journal/2022-09-05-maybe-sequences-from-chords.lisp
Normal file
@@ -0,0 +1,130 @@
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
(pb :notes
|
||||
:degree (pseq (list 0 1 2 3) 1))
|
||||
;; (play :notes)
|
||||
;; (stop :notes)
|
||||
|
||||
(setq *notes* (pseq (list 0 1 2 3)))
|
||||
(pb :just-*notes*
|
||||
:degree *notes*)
|
||||
;; (play :just-*notes*)
|
||||
;; (stop :just-*notes*)
|
||||
;;
|
||||
;; but that would certainly not help with changing other params
|
||||
;; "per phrase"
|
||||
|
||||
|
||||
(pb :attempt-at-repeating-pattern
|
||||
:degree (pseq (list 0 1 2 3) 2)
|
||||
:octave (pr (pwhite 2 5))
|
||||
)
|
||||
;; (play :attempt-at-repeating-pattern)
|
||||
;; (end :attempt-at-repeating-pattern)
|
||||
;; (stop :attempt-at-repeating-pattern)
|
||||
|
||||
;; how does that work? why octave only changes after the degree pseq ends?
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
;; (next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)))
|
||||
;; this started some computations in sbcl, which are in backgournd and I don't know how to stop
|
||||
;; (defpattern pr (pattern)
|
||||
;; (pattern
|
||||
;; (repeats :initform :inf)
|
||||
;; (current-value :state t :initform nil)
|
||||
;; (current-repeats-remaining :state t))
|
||||
;; :documentation "Repeat each value from PATTERN REPEATS times. If REPEATS is 0, the value is skipped.
|
||||
|
||||
;; Example:
|
||||
|
||||
;; (next-upto-n (pr (pseries) (pseq '(1 3 0 2) 1)))
|
||||
;; ;=> (0 1 1 1 3 3)
|
||||
|
||||
;; See also: `pdurstutter', `pn', `pdrop', `parp'")
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(next-upto-n (pseq '(1 2 3) 6) 4)
|
||||
(next-upto-n (pwhite 2 7) 4)
|
||||
(next-upto-n (pr (pwhite 2 7) 3) 7)
|
||||
(next-upto-n (pr (pwhite 2 7) (list 1 2 3)) 7)
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)) 10) ; still not working?
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)) 6) ; for some reason works up to 6
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 1)) 7) ; for some reason works up to 6
|
||||
;;; so, if I go into M-x sly-list-threads - I see worker threads,
|
||||
;;; and I could kill them, but also could d for debug, and "return value from thread", then that value is appended as 7th iteam
|
||||
;;; so the stream gets frozen, waiting for something to compute?
|
||||
; well, I guess OBJECT is stream that always repeats itself
|
||||
; so when I just put 3 or 4 - that's endless stream of 3s and 4s
|
||||
;; and to have pseq work - I need to remove that "1" and pseq would repeat forever, and numbers from pseq would be "multipliers" for endless stream of random numbers
|
||||
;; and random numbers would be new for second circle?
|
||||
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2) 2)) 7) ; yep
|
||||
(next-upto-n (pr (pwhite 2 7) (pseq '(1 3 0 2))) 17) ; yep
|
||||
|
||||
;; so when "automatic jazz" https://github.com/defaultxr/cl-patterns/blob/master/doc/cookbook.org#random-notes-from-a-scale
|
||||
;; does :octave (pr (pwhite 2 7))
|
||||
;; that means repeat (randomly selected from 2 to 7) "forever/until end of pattern"
|
||||
;; and end of pattern doesn't come from the :octave or :root
|
||||
;; but comes from the fact that #'PSHUF for :note has "end after 4"
|
||||
;; cool
|
||||
|
||||
;; so to have sequence of parameters that apply for whole melody
|
||||
;; I'd need "pr forever" and then take items from the list, so from pseq
|
||||
|
||||
(pb :at-repeating-pattern
|
||||
;; :degree (pseq (list 0 1 2 3) 2)
|
||||
:note (pshuf (scale-notes :minor) 1)
|
||||
:octave (pr (pseq (list 3 4 5)))
|
||||
)
|
||||
;; (play :at-repeating-pattern)
|
||||
;; (end :at-repeating-pattern)
|
||||
;; (stop :at-repeating-pattern)
|
||||
|
||||
(next-upto-n (pdef :at-repeating-pattern) 20)
|
||||
;; well, no, I don't understand after all!
|
||||
;; the pattern ends when :degree or :note part ends, and not restarts
|
||||
;; let's just copy "automatic jazz" and view it with #'NEXT-UPTO-N
|
||||
|
||||
(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)
|
||||
;; (stop :automatic-jazz)
|
||||
|
||||
(next-upto-n (pdef :automatic-jazz) 30)
|
||||
;; well, maybe pr only doesn't work with pseq, since it always selects first from the stream?
|
||||
|
||||
(pb :at-with-random-repeating-pattern
|
||||
:degree (pseq (list 0 1 2 3) 2)
|
||||
:octave (pr (pwhite 3 5))
|
||||
)
|
||||
;; (play :at-with-random-repeating-pattern)
|
||||
;; (end :at-with-random-repeating-pattern)
|
||||
;; (stop :at-with-random-repeating-pattern)
|
||||
|
||||
;;; hm, not exactly what I imagined in a way of combining patterns
|
||||
|
||||
;; then I guess, I want the melody to repeat in pseq endlessly, and match pr repeat size to length of melody (in events, and not beats, alas!)
|
||||
;; and use something like pxrand and end with end of pxrands
|
||||
;; even though that is not yet satisfactory, let's try it
|
||||
|
||||
(pb :at-with-outside-pseq-repeating-pattern
|
||||
;; :degree (pseq (list 0 1 2 3))
|
||||
:degree (pseq (list 0 1 2 (list 0 7)))
|
||||
:octave (pr (pseq (list 3 4 5 4 3)) 4)
|
||||
:amp (pseq (list 0.7 0.5 0.5 0.5)))
|
||||
;; (play :at-with-outside-pseq-repeating-pattern)
|
||||
;; (end :at-with-outside-pseq-repeating-pattern)
|
||||
;; (stop :at-with-outside-pseq-repeating-pattern)
|
||||
(next-upto-n (pdef :at-with-outside-pseq-repeating-pattern) 12)
|
||||
|
||||
;; so I guess when the pattern "repeats" it will be "exactly same" with randoms recalculated
|
||||
;; also - can I save the seeds? in case I'd like to record a random sequence that I liked on the walkthough?
|
||||
|
||||
;; also - how would I specify "a multiplier" for durations? if the notes are not of the same duration
|
||||
|
||||
;; (render (pdef :at-with-outside-pseq-repeating-pattern) "/tmp/repeating-4.wav" :dur 16)
|
||||
101
dirty-journal/2022-09-06-maybe-chord-melodies.lisp
Normal file
101
dirty-journal/2022-09-06-maybe-chord-melodies.lisp
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
(in-package :cl-patterns)
|
||||
(all-instruments)
|
||||
(all-chords)
|
||||
|
||||
(nchord :major 3) ; so, i could then inject / what's the verb
|
||||
; splice list as notes
|
||||
(nchord "Dominant 7th" 2)
|
||||
(chord :major)
|
||||
(chord "Major Triad")
|
||||
|
||||
(chord-indexes :major) ; (0 2 4) this goes into :degree
|
||||
(chord-notes :major) ; (0 4 7) and this goes into :notes?
|
||||
(chord-midinotes :major)
|
||||
|
||||
;; (pb :first-try-sequencing
|
||||
;; )
|
||||
|
||||
;; i want something like
|
||||
;; (pb
|
||||
;; :degree chorded-arpeggio '(0 1 3 2 3 0)
|
||||
|
||||
;; ok, let's settle situation with notes vs degrees
|
||||
(pb :with-notes
|
||||
:instrument :fmrhodes1
|
||||
;; :note (pseq (list 0 1 2 3 4 5 6 7) 1))
|
||||
;; :note (pseq (list 0 2 4 5 7 9 11 12) 1)
|
||||
:note (pseq (list 0 2 4 5 7 9 11 12) 1))
|
||||
;; (play :with-notes)
|
||||
;; (end :with-notes)
|
||||
;; (stop :with-notes)
|
||||
;; not whole octave from 0 to 7, so every key one after anothe
|
||||
;; and that would be just tuning steps, not taking into account the "lad"
|
||||
;; 0 2 4 5 7 9 11 12 is the major. ok
|
||||
|
||||
(pb :with-degrees
|
||||
:instrument :fmrhodes1
|
||||
:degree (pseq (list 0 1 2 3 4 5 6 7) 1))
|
||||
;; (play :with-degrees)
|
||||
;; (end :with-degrees)
|
||||
;; (stop :with-degrees)
|
||||
|
||||
;; so if I take 'chord-notes' in nchord, i need to use :note
|
||||
;; in the pattern
|
||||
|
||||
;; yay, and the patterns from 09-04 sound much better now
|
||||
|
||||
;;; so, back to arpeggio things
|
||||
;; i'd want something like
|
||||
;; (pb :hopes-for-arpegio
|
||||
;; :note (arpegio-thingy (list 0 2 3 1 3 0))
|
||||
;; :dur (pseq (list 1 1 2 1 1 2))
|
||||
;; :chords (pseq (list :maj :min :maj7 :maj6 :maj)))
|
||||
|
||||
;;; and then maybe have only :note and :dur as one names pattern
|
||||
;; which somehow later combines with the :chords pseq
|
||||
|
||||
;; (defpattern pfunc (pattern)
|
||||
;; ((func :type function-designator)
|
||||
;; (length :initform :inf)
|
||||
;; (current-repeats-remaining :state t))
|
||||
;; :documentation "Yield the result of evaluating FUNC. Note that the current event of the parent pattern is still accessible via the `*event*' special variable.
|
||||
|
||||
;; Example:
|
||||
|
||||
(next-upto-n (pfunc (lambda () (random 10)) 4))
|
||||
;=> ((5 2 8 9))
|
||||
|
||||
;; (next-upto-n (pbind :foo (pwhite 0 10 4)
|
||||
;; :bar (pfunc (lambda ()
|
||||
;; (if (> (event-value *event* :foo) 5) :greater :lesser)))))
|
||||
;; ;=> ((EVENT :FOO 0 :BAR :LESSER) (EVENT :FOO 6 :BAR :GREATER)
|
||||
;; (EVENT :FOO 7 :BAR :GREATER) (EVENT :FOO 8 :BAR :GREATER))
|
||||
|
||||
;; See also: `pf', `pnary', `plazy', `pif'")
|
||||
|
||||
;;; so, maybe that's the way?
|
||||
;; I really could have :chord attribute, and could possibly have :arpeggio-steps attribute
|
||||
;; and those would combine to create :note attribute
|
||||
|
||||
;; i was recommended PARP
|
||||
;; but I don't understand how it could be used in conjunction with chords?
|
||||
;; well, no, I see - I could change :octave, and in first pattern return :notes, right?
|
||||
|
||||
(chord-notes :major)
|
||||
|
||||
;;; full on gift of help:
|
||||
(pdef :foo
|
||||
(parp (pbind :note (pnary #'chord-notes (pseq (list :major :minor :maj7 :maj6 :major) 1))
|
||||
:dur (pseq (list 1 1 2 1 1 2)))
|
||||
(pbind :note (p+ (pk :note)
|
||||
(pseq (list 0 2 3 1 3 0) 1)))))
|
||||
(next-upto-n (pdef :foo) 4)
|
||||
;; (play :foo)
|
||||
;; (end :foo)
|
||||
;; (stop :foo)
|
||||
|
||||
(next-upto-n (pbind :note (p+ 1 (pseq (list 0 2 3) 1))) 4)
|
||||
|
||||
;; let's try to get sequence of steps when we give as input notes of a chord
|
||||
;; tomorrow
|
||||
89
dirty-journal/2022-09-07-trying-more-arpegioing-chords.lisp
Normal file
89
dirty-journal/2022-09-07-trying-more-arpegioing-chords.lisp
Normal file
@@ -0,0 +1,89 @@
|
||||
|
||||
;; let's try the pfunc to create arpegio from the chord
|
||||
(in-package :cl-patterns)
|
||||
(next-upto-n (pbind :chord (pseq (list :major :minor :minor-triad :major))
|
||||
:note (pfunc (lambda ()
|
||||
(let* ((chord (event-value *event* :chord))
|
||||
(notes (nchord chord)))
|
||||
;; let's keep it simple for a moment
|
||||
notes))
|
||||
)) 10)
|
||||
;; ((EVENT :CHORD :MAJOR :NOTE (0 4 7)) (EVENT :CHORD :MINOR :NOTE (0 3 7))
|
||||
;; (EVENT :CHORD :MINOR-TRIAD :NOTE (0 3 7)) (EVENT :CHORD :MAJOR :NOTE (0 4 7))
|
||||
;; (EVENT :CHORD :MAJOR :NOTE (0 4 7)) (EVENT :CHORD :MINOR :NOTE (0 3 7))
|
||||
;; (EVENT :CHORD :MINOR-TRIAD :NOTE (0 3 7)) (EVENT :CHORD :MAJOR :NOTE (0 4 7))
|
||||
;; (EVENT :CHORD :MAJOR :NOTE (0 4 7)) (EVENT :CHORD :MINOR :NOTE (0 3 7)))
|
||||
|
||||
;; And I'd still in parp generator
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pfunc (lambda ()
|
||||
(let* ((chord (event-value *event* :chord))
|
||||
(notes (nchord chord)))
|
||||
;; let's keep it simple for a moment
|
||||
(pseq notes 1)))
|
||||
))) 10)
|
||||
;; for some reason this stays on first chord forever, but does arpegio
|
||||
;; bit of something I don't understand
|
||||
|
||||
(next-upto-n (parp (pbind :ocatave (pseq (list 3 4 3 5)))
|
||||
(pbind :note (pseq (list 0 1 2) 1))) 12) ; needed 1 repeat limit here
|
||||
|
||||
;; let's try with #'PK
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (let* ((chord (pk :chord))
|
||||
(notes (nchord chord)))
|
||||
;; let's keep it simple for a moment
|
||||
(pseq notes 1)))) 10)
|
||||
;; error, no applicable method
|
||||
;; how does that work then?
|
||||
|
||||
(pdef :foo
|
||||
(parp (pbind :note (pnary #'chord-notes (pseq (list :major :minor :maj7 :maj6 :major) 1))
|
||||
:dur (pseq (list 1 1 2 1 1 2)))
|
||||
(pbind :note (p+ (pk :note)
|
||||
(pseq (list 0 2 3 1 3 0) 1)))))
|
||||
(next-upto-n (pdef :foo) 10)
|
||||
;; and what if I change :note to :chord here?
|
||||
|
||||
(next-upto-n (pdef :foo
|
||||
(parp (pbind :chord (pnary #'chord-notes (pseq (list :major :minor :maj7 :maj6 :major) 1))
|
||||
:dur (pseq (list 1 1 2 1 1 2)))
|
||||
(pbind :note (p+ (pk :chord)
|
||||
(pseq (list 0 2 3 1 3 0) 1))))) 10)
|
||||
|
||||
;; maybe difference is that #'LET* can't be directly in the place that defined :note?
|
||||
;; and I should use #'PSEQ and move #'LET* into list definiton?
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pseq (let* ((chord (pk :chord))
|
||||
(notes (nchord chord)))
|
||||
notes)
|
||||
1)))
|
||||
10)
|
||||
;; or maybe (pk :chord) is a pattern and can't be used as "just function to get value"
|
||||
;; seems true
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pk :chord)))
|
||||
10)
|
||||
;; here pk :chord is object so, endless pattern and we never switch to :major
|
||||
;; but that's ok,
|
||||
;; main lesson I guess that I need to use pattern transformation functions,
|
||||
;; and lisp transformations mainly on arguments
|
||||
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pfunc (lambda ()
|
||||
(pseq (nchord (event-value *event* :chord)) 1)))))
|
||||
10)
|
||||
;; endless stream, inner :note doesn't end?
|
||||
(next-upto-n (parp (pbind :chord (pseq (list :minor-triad :major)))
|
||||
(pbind :note (pseq (pnary #'nchord (pk :chord)) 2)))
|
||||
20)
|
||||
;; not that seems to work?
|
||||
(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)
|
||||
|
||||
;; could I maybe now insert this into a pb
|
||||
;; so that I could change speed and root for whole thing?
|
||||
532
dirty-journal/2022-09-08-more-on-chord-melodies.lisp
Normal file
532
dirty-journal/2022-09-08-more-on-chord-melodies.lisp
Normal file
@@ -0,0 +1,532 @@
|
||||
|
||||
(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
|
||||
176
dirty-journal/2022-09-09-maybe-cleanup-bass-from-chords.lisp
Normal file
176
dirty-journal/2022-09-09-maybe-cleanup-bass-from-chords.lisp
Normal file
@@ -0,0 +1,176 @@
|
||||
(in-package :cl-patterns)
|
||||
|
||||
(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)))
|
||||
|
||||
;;; change with previous - another attempt after advice to move :dur higher in outer pattern, that this /should/ pick up (pk :dur)
|
||||
;; and function wouldn't need dur argument
|
||||
(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) ; yes, that is picked up, if :dur is defined above :embed in the outer pattern, yay
|
||||
)
|
||||
phrase-dur phrase-dur)))
|
||||
|
||||
;; IV V iii vi
|
||||
(pb :lets-arpegio-IV-V-iii-vi
|
||||
:dur 1/2
|
||||
:embed (not-perfect-but-arpeggio (list :major :minor)) ; each chord plays arpeggio for whole phrase (two bars)
|
||||
:embed (attr-per-phrase :legato (list 1 0.7)) ; 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))
|
||||
)
|
||||
;; (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)
|
||||
|
||||
;; Now, if I have totally repeating phrases (like here)
|
||||
;; I suppose it would be much better to just use PARP to set per phrase attributes?
|
||||
|
||||
(pb :lets-arpegio-in-arpegio
|
||||
(parp (pbind
|
||||
:legato (pseq (list 1 0.7))
|
||||
:root (pseq (list 3 2)))
|
||||
(pbind
|
||||
:dur 1/3
|
||||
:embed (not-perfect-but-arpeggio (list :major :minor)))))
|
||||
;; I already see how this wouldn't be the same!
|
||||
;; PARP would play both chords :major and :minor for setting of (:legato 1 :root 3) and then again both for setting (:legato 0.7 :root 2)
|
||||
;; so ATTR-PER-PHRASE does something different
|
||||
|
||||
;; yup. generally it does (pseq (list (pfindur (pbind .. value ..)) ..)
|
||||
;; ok!
|
||||
|
||||
;;; now let's clean up bass thingy?
|
||||
;; pattern (list 4 1/2 1/2 (prest 3))
|
||||
(defun simple-bass-line (chords strum-pattern)
|
||||
(parp (pbind :chord (pseq chords 2))
|
||||
(pbind
|
||||
:note (pnary #'chord-notes (pk :chord)) ; repeated list of chord notes - played together
|
||||
:dur (pseq strum-pattern 1))))
|
||||
(pb :simple-base
|
||||
:instrument :fmbass
|
||||
:embed (simple-bass-line (list :major :minor) (list 4 1/2 1/2 (prest 3)))
|
||||
:embed (attr-per-phrase :root (list 3 2) 8)
|
||||
:embed (attr-per-phrase :octave (list 3 2) (* 4 2 2))) ; 4 beats per tact, 2 tacts per chord, 2 hard coded chords
|
||||
(next-upto-n (pdef :simple-base) 40)
|
||||
;; (play :simple-base)
|
||||
;; (end :simple-base)
|
||||
;; (stop :simple-base)
|
||||
|
||||
(pdef :new-arpegio-and-bass-1
|
||||
(ppar (list :lets-arpegio-iv-v-iii-vi :simple-base)))
|
||||
;; (play :new-arpegio-and-bass-1)
|
||||
;; (end :new-arpegio-and-bass-1)
|
||||
;; (stop :new-arpegio-and-bass-1)
|
||||
|
||||
;;; notes:
|
||||
;; arpegio hardcodes 2 repetitions
|
||||
;; base hardcodes now 2 repetiitons as well, to match with :octave change thing
|
||||
|
||||
;; also #'SIMPLE-BASE-LINE could just take in pattern for strum-pattern,
|
||||
;; not list to be used in #'PSEQ
|
||||
|
||||
;;; ok! now let's do 4 bars of same, then 4 bars with 1/3 duration in arpeggios
|
||||
|
||||
;; IV V iii vi
|
||||
;; (setq *my-chords* (list :major :major :minor :minor)
|
||||
;; *my-roots* (list 3 4 2 5))
|
||||
;; for now will set in 09-11.lisp
|
||||
|
||||
(pb :lets-arpegio-before-duration
|
||||
:embed (not-perfect-but-arpeggio *my-chords*) ; each chord plays arpeggio for whole phrase (two bars)
|
||||
:embed (attr-per-phrase :root *my-roots*)
|
||||
:embed (attr-per-phrase :legato (list 1 0.8 0.6 0.9)) ; each phrase takes single value for legato
|
||||
; even if amount of events in phrase change with change of :dur
|
||||
)
|
||||
;; (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)
|
||||
|
||||
(pb :arpegio-in-halves
|
||||
:dur 1/2
|
||||
:embed :lets-arpegio-before-duration)
|
||||
(pb :arpegio-in-thirds
|
||||
:dur 1/4
|
||||
:embed :lets-arpegio-before-duration)
|
||||
;; (play :arpegio-in-halves)
|
||||
;; (stop :arpegio-in-halves)
|
||||
;; (play :arpegio-in-thirds)
|
||||
;; (stop :arpegio-in-thirds)
|
||||
|
||||
(pb :simple-base-2
|
||||
:instrument :fmbass
|
||||
:embed (simple-bass-line *my-chords* (list 4 1/2 1/2 (prest 3)))
|
||||
:embed (attr-per-phrase :root *my-roots* 8)
|
||||
:embed (attr-per-phrase :octave (list 3 2) (* 4 2 4))) ; 4 beats per tact, 2 tacts per chord, 4 hard coded chords
|
||||
(next-upto-n (pdef :simple-base-2) 40)
|
||||
;; (play :simple-base-2)
|
||||
;; (end :simple-base-2)
|
||||
;; (stop :simple-base-2)
|
||||
|
||||
;; now. I want 8 bars of base, and 8 bars of arp-in-halves
|
||||
;; then another 8 bars of base and 8 bars of arp-in-thirds
|
||||
|
||||
(pb :arpegios-one-after-another
|
||||
(pseq (list (pdef :arpegio-in-halves) (pdef :arpegio-in-thirds)) 1))
|
||||
;; (play :arpegios-one-after-another)
|
||||
;; (end :arpegios-one-after-another)
|
||||
;; (stop :arpegios-one-after-another)
|
||||
|
||||
(pb :arpegios-and-bass
|
||||
(ppar (list :arpegios-one-after-another (pn (pdef :simple-base-2) 2))))
|
||||
;; (play :arpegios-and-bass)
|
||||
;; (end :arpegios-and-bass)
|
||||
;; (stop :arpegios-and-bass)
|
||||
|
||||
;;; note - and through all of this I'm forgetting about :quant setting
|
||||
;; that would help align patterns if I start \ end them manually
|
||||
|
||||
;; now let's record this and share and get on with the day
|
||||
|
||||
;; 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/two-arpeggios-and-bass.aiff" :leave-open-p t)
|
||||
|
||||
;; ;; now play whatever sounds you like
|
||||
|
||||
;; ;; e.g.
|
||||
;; (in-package :cl-patterns)
|
||||
;; (play :arpegios-and-bass)
|
||||
;; (end :arpegios-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
|
||||
232
dirty-journal/2022-09-11-attempting-more-with-arpegios.lisp
Normal file
232
dirty-journal/2022-09-11-attempting-more-with-arpegios.lisp
Normal file
@@ -0,0 +1,232 @@
|
||||
;;; today I'd like to do bass arpegios, with high chords
|
||||
;; and maybe drums for both parts (from 09-09)
|
||||
;; and join them?
|
||||
|
||||
;; IV V iii vi
|
||||
;; (setq *my-chords* (list :major :major :minor :minor)
|
||||
;; *my-roots* (list 3 4 2 5))
|
||||
;; (setq *my-chords* (list :major)
|
||||
;; *my-roots* (list 3))
|
||||
|
||||
;; Am – F – C – G (i – VI – III – VII)
|
||||
;; (setq *my-chords* (list :minor :major :major :major)
|
||||
;; *my-roots* (list 0 3 2 6))
|
||||
|
||||
;; i - III - iv - VI
|
||||
(setq *my-chords* (list :minor :major :minor :major)
|
||||
*my-roots* (list 0 2 3 5))
|
||||
|
||||
(in-package :cl-patterns)
|
||||
|
||||
(start-clock-loop :tempo 90/60 :force t)
|
||||
|
||||
(pb :lets-slow-bass-arpegio
|
||||
:dur 2
|
||||
:octave 3
|
||||
;; :instrument :fmbass
|
||||
:embed (not-perfect-but-arpeggio *my-chords*)
|
||||
:embed (attr-per-phrase :root *my-roots*)
|
||||
)
|
||||
;; (play :lets-slow-bass-arpegio)
|
||||
;; (stop :lets-slow-bass-arpegio)
|
||||
|
||||
;; well, what if I rather take my simple-bass thing
|
||||
;; and give it some kind of slow pattern
|
||||
;; nope, that simple-bass plays whole chords
|
||||
;;
|
||||
;; at this point I'm just tempted to not use chords,
|
||||
;; and have a PARP
|
||||
(pdef :chord-defs
|
||||
(pbind :chord (pseq *my-chords* 1)
|
||||
:chord-base (pseq *my-roots* 1)))
|
||||
|
||||
(pb :lets-slow-bass-melody
|
||||
(parp
|
||||
(pdef :chord-defs)
|
||||
(pbind :step (pseq (list 0 1 0 1 2 0 1 2) 1)
|
||||
:dur (pseq (list 1/4 1/4 1 1 1 1 1 5/2) 1)
|
||||
;; :note (pfunc (lambda ()
|
||||
;; (event-value *event* :step)))
|
||||
:note (pfunc (lambda ()
|
||||
(+ (event-value *event* :chord-base)
|
||||
(nth (event-value *event* :step)
|
||||
(chord-notes (event-value *event* :chord))))))
|
||||
)))
|
||||
;; (next-upto-n (pdef :lets-slow-bass-melody) 10)
|
||||
;; (play :lets-slow-bass-melody)
|
||||
;; (end :lets-slow-bass-melody)
|
||||
;; (stop :lets-slow-bass-melody)
|
||||
|
||||
(pb :embedding-bass-melogy-into-pattern
|
||||
(pseq (list (pbind
|
||||
:quant 4
|
||||
:dur (pseq (list (prest 7/2)) 1))
|
||||
(pbind
|
||||
:octave 2 ; let's add these later? when join both?
|
||||
:instrument :fmbass
|
||||
:embed :lets-slow-bass-melody))
|
||||
1))
|
||||
(next-upto-n (pdef :embedding-bass-melogy-into-pattern) 20)
|
||||
;; (play :embedding-bass-melogy-into-pattern)
|
||||
;; (stop :embedding-bass-melogy-into-pattern)
|
||||
;; (end :embedding-bass-melogy-into-pattern)
|
||||
|
||||
;; now. let's brainstorm the pattern on a single chord?
|
||||
|
||||
;; and well, my guess is that pattern should start from 1/2 before tha bar start?
|
||||
|
||||
;; so is there a "timer shift" for pattern?
|
||||
;; if I can only align by quant
|
||||
;; ( upbeat ? )
|
||||
;; well 3 6 9 - and we have -1 +2 and +1 over the quant :4
|
||||
|
||||
;; ok, let's for not simulate that stuff by writing continuous bass melody
|
||||
;; and adding 3 1/2 rest in the beginning
|
||||
|
||||
;; I'd like to add bottom note repeating at 1/2 ?
|
||||
|
||||
;;; let's just do same? quant 4, wait for the upbeat of next bar
|
||||
;;; and start playing 1/2 8 times?
|
||||
(pb :lets-slow-bass-melody-root-repeating
|
||||
(pseq (list (pbind :dur (pseq (list (prest 4)) 1)
|
||||
:quant 4)
|
||||
(parp
|
||||
(pdef :chord-defs)
|
||||
(pbind
|
||||
:octave 1
|
||||
:instrument :fmbass
|
||||
:dur (pseq (list (prest 5/2) (pfindur 1/2 7/2) (prest 2)) 1)
|
||||
:legato 0.5
|
||||
:note (pk :chord-base)))
|
||||
(pbind :dur (pseq (list (prest 1)) 1)))
|
||||
1))
|
||||
(next-upto-n (pdef :lets-slow-bass-melody-root-repeating) 20)
|
||||
;; (play :lets-slow-bass-melody-root-repeating)
|
||||
;; (end :lets-slow-bass-melody-root-repeating)
|
||||
;; (stop :lets-slow-bass-melody-root-repeating)
|
||||
|
||||
(pdef :full-bass-melody
|
||||
(ppar (list :embedding-bass-melogy-into-pattern :lets-slow-bass-melody-root-repeating)))
|
||||
;; (play :full-bass-melody)
|
||||
;; (stop :full-bass-melody)
|
||||
|
||||
;; yay, not sure whether I want :octave 1 or 2, but overall, cool,
|
||||
;; even though - so much still to learn to not have to do manual calculaitons of prest and such
|
||||
|
||||
;; let's have some kind of light chord holding. not sure what I want, maybe default
|
||||
;; maybe strings? or pluck
|
||||
|
||||
(pb :high-chords-hold
|
||||
:embed :chord-defs
|
||||
:instrument :tone-buzz
|
||||
:dur 8
|
||||
:quant 4
|
||||
:amp 0.05
|
||||
:note (p+ (pk :chord-base) (pnary #'chord-notes (pk :chord))))
|
||||
(next-upto-n (pdef :high-chords-hold) 30)
|
||||
;; (play :high-chords-hold)
|
||||
;; (end :high-chords-hold)
|
||||
;; (stop :high-chords-hold)
|
||||
|
||||
(pb :high-chords-with-pre-bar
|
||||
(pseq (list
|
||||
(pbind :dur (pseq (list (prest 4)) 1)) ; most awkward thing
|
||||
(pdef :high-chords-hold))
|
||||
1))
|
||||
|
||||
(pdef :total-base-section
|
||||
(ppar (list :full-bass-melody :high-chords-with-pre-bar)))
|
||||
;; (play :total-base-section)
|
||||
;; (stop :total-base-section)
|
||||
|
||||
;; well, it seems that with restarts defsynts of fmbass start playing worse?
|
||||
;; responding less and less to short notes and legato?
|
||||
;; is that due to not restarting sbcl?
|
||||
;; let's try full restart
|
||||
|
||||
;;; I've done full restart, didn't totally help.
|
||||
;; and I've set slower clock speed
|
||||
|
||||
;;; now, let's add intro, connection and ending?
|
||||
|
||||
(pb :intro
|
||||
:embed :chord-defs
|
||||
:dur (pseq (list 2 2 4) 1)
|
||||
:instrument :strings
|
||||
:amp 0.1
|
||||
:note (p+ (first *my-roots*) (pnary #'chord-notes (first *my-chords*))))
|
||||
;; (play :intro)
|
||||
;; (stop :intro)
|
||||
;; (end :intro)
|
||||
;; idea for not now - third chord make in two octaves?
|
||||
|
||||
;;; maybe add a scratch inbetween?
|
||||
(pb :phrase-connection
|
||||
:instrument :fmbass
|
||||
:dur (pseq (list (prest 2) 12 (prest 4)) 1)
|
||||
:embed :chord-defs
|
||||
:octave 2
|
||||
:note (p+ (first *my-roots*) (pnary #'chord-notes (first *my-chords*)))
|
||||
)
|
||||
;; (play :phrase-connection)
|
||||
;; (stop :phrase-connection)
|
||||
|
||||
;;; for this to work, also evaluate ~/Documents/personal/common-lisp-study/music/dirty-journal/2022-09-09-maybe-cleanup-bass-from-chords.lisp
|
||||
;; maybe later on cleanup I'd put everything into same file
|
||||
|
||||
(pdef :is-that-first-experiment
|
||||
(pseq (list (pdef :intro)
|
||||
(pdef :total-base-section)
|
||||
(pdef :phrase-connection)
|
||||
(pdef :arpegios-and-bass))
|
||||
1))
|
||||
;; (play :is-that-first-experiment)
|
||||
;; (stop :is-that-first-experiment)
|
||||
;; (end :is-that-first-experiment)
|
||||
|
||||
;; welp, when notes are too quick, they are not produced
|
||||
;; and I also kind of wanted a percussion line, but oh well
|
||||
|
||||
;; ;;; ok, let's record that,
|
||||
|
||||
;; ;; 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
|
||||
;; ;; ;; IV V iii vi
|
||||
;; ;; Am – F – C – G (i – VI – III – VII)
|
||||
;; ;; i - III - iv - VI
|
||||
;; (buffer-write mybuffer "/tmp/first-experiment-i-III-iv-VI.aiff" :leave-open-p t)
|
||||
|
||||
;; ;; now play whatever sounds you like
|
||||
|
||||
;; ;; e.g.
|
||||
;; (in-package :cl-patterns)
|
||||
;; (play :is-that-first-experiment)
|
||||
;; (stop :is-that-first-experiment)
|
||||
;; (end :is-that-first-experiment)
|
||||
|
||||
;; ;; 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
|
||||
171
dirty-journal/2022-09-21-trying-new-arpeggios.lisp
Normal file
171
dirty-journal/2022-09-21-trying-new-arpeggios.lisp
Normal file
@@ -0,0 +1,171 @@
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
|
||||
;; i want to get arpeggios of configurable speed
|
||||
;; and configured by chord
|
||||
;; and configured by places of notes in a chord
|
||||
;; let's again first do consecutive notes from a chord
|
||||
;; idea is to have
|
||||
;; a) endless loop of notes from a chord
|
||||
;; b) have pdurstutter - for the duration of desired arpeggio, with maybe figuring out to make each part of stutter into a separate item in arpeggio
|
||||
|
||||
(all-chords)
|
||||
(chord-notes (chord "Minor 7th"))
|
||||
|
||||
(pdef :at-first-chords
|
||||
(pbind :note (pseq (chord-notes (chord "Minor 7th")))))
|
||||
;; (play :at-first-chords)
|
||||
;; (stop :at-first-chords)
|
||||
|
||||
(pdef :initial-stutter
|
||||
(pdurstutter (pbind
|
||||
:dur (pseq (list 4) 1)) 16))
|
||||
;; (play :initial-stutter)
|
||||
;; (end :initial-stutter)
|
||||
;; (stop :initial-stutter)
|
||||
|
||||
(pb :initial-combination
|
||||
;; :embed :initial-stutter
|
||||
;; :arpeggio-chord :minor-6th
|
||||
:dur (pdurstutter (pseq (list 4) 1) 16)
|
||||
:note (pseq (pnary #'chord-notes (pk :arpeggio-chord)))
|
||||
)
|
||||
;; (next-upto-n (pdef :initial-combination) 32)
|
||||
;; (play :initial-combination)
|
||||
;; (end :initial-combination)
|
||||
;; (stop :initial-combination)
|
||||
|
||||
(chord-notes :minor-6th)
|
||||
|
||||
;; now do arpegio pattern to play arpegio per each chord?
|
||||
(pb :with-changing-chords
|
||||
(parp
|
||||
(pbind :arpeggio-chord (pseq (list :minor-6th :minor :minor-7th :minor)))
|
||||
(pdef :initial-combination)))
|
||||
;; (next-upto-n (pdef :with-changing-chords) 40)
|
||||
;; (play :with-changing-chords)
|
||||
;; (stop :with-changing-chords)
|
||||
|
||||
;; that's kind of ok if chords have same amount of notes in it?
|
||||
(mapcar #'chord-notes (list :minor-6th :minor :minor-7th :minor))
|
||||
(chord :major)
|
||||
|
||||
;; would it be better if it's all in single def?
|
||||
(pb :with-changing-chords-2
|
||||
(parp
|
||||
(pbind :arpeggio-chord (pseq (list :major :minor :major :minor) 1)
|
||||
:chord-root (pseq (list 0 3 2 6) 1))
|
||||
(pbind
|
||||
:dur (pdurstutter (pseq (list 4) 1) 24)
|
||||
:note (pseq (p+ (pk :chord-root) (pnary #'chord-notes (pk :arpeggio-chord)))))))
|
||||
;; (play :with-changing-chords-2)
|
||||
;; (end :with-changing-chords-2)
|
||||
|
||||
;; now I could use stats of the :arpeggio-chord in the :dur part
|
||||
;; i guess i'd like to what?
|
||||
;; to be adding root of the chord
|
||||
;; and then pattern to be played over the chord
|
||||
|
||||
;; let's first make simple endless pattern that takes list of steps, and takes them out of chord-notes
|
||||
(pb :initial-patterned
|
||||
:pattern (list 0 1 2 0 3)
|
||||
:note (pnary (lambda (a) (nth a (chord-notes :major-7th))) (pseq (pk :pattern))))
|
||||
(next-upto-n (pdef :initial-patterned) 20)
|
||||
;; (play :initial-patterned)
|
||||
;; (stop :initial-patterned)
|
||||
|
||||
;; and now i want what? i want to do pnary? pfunc
|
||||
|
||||
(pb :with-patterned-changing-chords
|
||||
(parp
|
||||
;;; first part of parp is "base values" for each event whole second pattern will be played
|
||||
;;; so this pattern produces "settings for each phrase"
|
||||
(pbind :arpeggio-chord (pseq (list :minor-6th :minor :minor-7th :minor))
|
||||
:chord-root (pseq (list 0 3 2 6) 1)
|
||||
:pattern (list 0 1 2 1 2 1 2 0))
|
||||
;;; this patten would play our fully with settings values
|
||||
(pbind
|
||||
:note (pnary (lambda (chord-step chord chord-root)
|
||||
(+ chord-root (nth chord-step (chord-notes chord))))
|
||||
(pseq (pk :pattern))
|
||||
(pk :arpeggio-chord)
|
||||
(pk :chord-root))
|
||||
:dur (pdurstutter (pseq (list 8) 1) 32))))
|
||||
;; (next-upto-n (pdef :with-patterned-changing-chords) 30)
|
||||
;; (play :with-patterned-changing-chords)
|
||||
;; (stop :with-patterned-changing-chords)
|
||||
|
||||
;; next I'd probably want to what? somehow align chords that have 3 \ 4 \ 5 notes in them
|
||||
;; not sure what could be done though logically
|
||||
;; we could have different patterns, based on chord size, yup
|
||||
|
||||
(pb :instrumented-play
|
||||
:instrument :fmbass
|
||||
:legato 0.5
|
||||
:octave 2
|
||||
:embed :with-patterned-changing-chords)
|
||||
;; (play :instrumented-play)
|
||||
;; (end :instrumented-play)
|
||||
|
||||
;; i guess next is making this pattern a function that takes patterns to provice chords, roots and pattrn
|
||||
;; then could use embed and set attributes in place
|
||||
;; this is actually fun
|
||||
|
||||
(defun patterned-arpeggio (chords roots patterns &optional (chord-duration 8) (events-in-chord 32))
|
||||
(parp
|
||||
;;; first part of parp is "base values" for each event whole second pattern will be played
|
||||
;;; so this pattern produces "settings for each phrase"
|
||||
(pbind :arpeggio-chord chords
|
||||
:chord-root roots
|
||||
:pattern patterns)
|
||||
;;; this patten would play our fully with settings values
|
||||
(pbind
|
||||
:note (pnary (lambda (chord-step chord chord-root)
|
||||
(+ chord-root (nth chord-step (chord-notes chord))))
|
||||
(pseq (pk :pattern))
|
||||
(pk :arpeggio-chord)
|
||||
(pk :chord-root))
|
||||
:dur (pdurstutter (pseq (list chord-duration) 1) events-in-chord))))
|
||||
|
||||
(pb :first-try-of-function
|
||||
:instrument :fmbass
|
||||
:legato 0.5
|
||||
:octave 2
|
||||
:embed (patterned-arpeggio
|
||||
(pseq (list :minor-6th :minor :minor-7th :minor))
|
||||
(pseq (list 0 3 2 6) 1)
|
||||
(list 0 1 2 1 2 1 2 0)))
|
||||
;; (play :first-try-of-function)
|
||||
;; (end :first-try-of-function)
|
||||
|
||||
;; taking progressions from
|
||||
;; https://en.wikipedia.org/wiki/List_of_chord_progressions
|
||||
|
||||
(pb :second-try-of-function
|
||||
:instrument :fmbass
|
||||
:legato 0.5
|
||||
:octave 2
|
||||
:embed (patterned-arpeggio
|
||||
(pseq (list :major :minor :major :major))
|
||||
(pseq (list 0 5 3 4) 1)
|
||||
(list 0 1 2 1 2 1 2 0)
|
||||
2 8))
|
||||
;; (play :second-try-of-function)
|
||||
;; (end :second-try-of-function)
|
||||
|
||||
;; andalusian cadence iv-III-II-I
|
||||
(pb :third-try-of-function
|
||||
;; :instrument :fmbass
|
||||
;; :instrument :strings
|
||||
:instrument :prophet5pwmstrings
|
||||
:legato 1
|
||||
:octave 5
|
||||
:embed (patterned-arpeggio
|
||||
(pseq (list :minor :major :major :major))
|
||||
(pseq (list 3 2 1 0) 1)
|
||||
(list 0 1 2 1 2 1 2 0)
|
||||
;; 2 16
|
||||
8 16
|
||||
))
|
||||
;; (play :third-try-of-function)
|
||||
;; (stop :third-try-of-function)
|
||||
430
dirty-journal/programming-music-journal.org
Normal file
430
dirty-journal/programming-music-journal.org
Normal file
@@ -0,0 +1,430 @@
|
||||
#+title: Programming Music Journal
|
||||
* [2022-08-19 Fri]
|
||||
** past friday I've done some basic setup (painfully) and had simplest examples running
|
||||
[[file:supercollider-example.lisp::;; to use cl-patterns with its SuperCollider backend, you'll first need to load the cl-patterns/supercollider system with quicklisp:][setting up supercollider]] package - so this doesn't work for some reason
|
||||
** here simplest things seem to work
|
||||
[[file:setting-up-cl-collider.lisp::;; https://defaultxr.github.io/cl-collider-tutorial/02-getting-started.html][cl-collider-tutorial-getting-started]]
|
||||
** so, let's just go the site?
|
||||
nope, continue with the file that had some promise
|
||||
the one about cl-collider turorial
|
||||
** also, let's make this a separate repo?
|
||||
oh, no, the 'supercollider-example' which is about cl-patterns started to work?
|
||||
|
||||
how and why? maybe reinit of some shit, or what
|
||||
|
||||
so, new file to hopefully learn something about cl-patterns
|
||||
*** what is it that I want o learn ideally?
|
||||
setting up drum sequences?
|
||||
|
||||
doing chord things with synth?
|
||||
** what's this thing about "FAILURE IN SERVER /n_set Node 1539 not found "
|
||||
?
|
||||
** this seems to be startup
|
||||
#+begin_src common-lisp
|
||||
(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)
|
||||
#+end_src
|
||||
|
||||
but what's most basic pattern that would play then?
|
||||
|
||||
ones in [[file:2022-08-12-supercollider-example.lisp::end :bar][supercollider example seem to work]]
|
||||
|
||||
and example seem to require me to define synth, right?
|
||||
to set it into the :instrument key
|
||||
|
||||
wtf am I to do.
|
||||
** maybe let's try to do stuff inside of org file?
|
||||
** how do I clear things, it seems that cl-patterns seems to send things to server?
|
||||
** should I try a different backend?
|
||||
** so, when SC returned lots of errors on pb what helped - starting syn wave from "setting-up" file
|
||||
;;; https://defaultxr.github.io/cl-collider-tutorial/03-make-a-sound.html
|
||||
(setf *s* (make-external-server "localhost" :port 4444))
|
||||
(server-boot *s*) ; already in use
|
||||
|
||||
|
||||
;;; https://defaultxr.github.io/cl-collider-tutorial/03-make-a-sound.html
|
||||
(proxy :foo (sin-osc.ar 440 0 0.2)) ; no error, but hear no sound
|
||||
;; opened QjackCtl, connected Graph SuperCollider to Air by Aftershokz left
|
||||
(proxy :foo (sin-osc.ar 300 0 0.2))
|
||||
(proxy :foo (saw.ar 300 0.2))
|
||||
|
||||
** how do I make sounds better?
|
||||
do I go to cl-collider package for explanation of synths and such?
|
||||
** to stopp things that run amok:
|
||||
(cl-patterns:stop t)
|
||||
** ugh. why doesn't it produce sounds?
|
||||
** ok, what did I learn today?
|
||||
- some interaction with pseq
|
||||
having scales, root / ocave
|
||||
- intersecting with durations, also seq and not totally alighning
|
||||
- some combined sounds, which don't sound nice
|
||||
- maybe reliant startup procedure
|
||||
- and attempting to run chords hangs it all
|
||||
** cl-patterns docs:
|
||||
https://github.com/defaultxr/cl-patterns/tree/master/doc
|
||||
that's all files
|
||||
* [2022-08-20 Sat]
|
||||
** now I'd like to create an instrument for which chords would sound nice
|
||||
and after than some kind of percussion things
|
||||
** cool! that was just my type :instument instead of :instrument
|
||||
and article on cl-collider now helps with some cool synhts, like chord strum
|
||||
#+begin_src common-lisp
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
|
||||
;; (synth 'tone-pluck)
|
||||
|
||||
(in-package #:cl-patterns)
|
||||
(pb :what-predef-chord
|
||||
:instrument :tone-pluck
|
||||
: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)
|
||||
;; (stop :what-predef-chord)
|
||||
|
||||
#+end_src
|
||||
|
||||
yay.
|
||||
** now let's figure out percussions?
|
||||
** searching : "super collider percussion synth"
|
||||
got all sorts of cool results:
|
||||
*** main page of supercollider: https://supercollider.github.io/
|
||||
*** awesome list : https://github.com/madskjeldgaard/awesome-supercollider#synthdefs
|
||||
and it has link to defs!
|
||||
*** defs : https://github.com/everythingwillbetakenaway/Synthdefs
|
||||
for example a drum kik which I'd try to convert?
|
||||
https://github.com/everythingwillbetakenaway/Synthdefs/blob/master/drum_kick.scd
|
||||
** to file https://github.com/byulparan/cl-collider#record-audio-output
|
||||
whoh
|
||||
** now for the well deserved fucking rest
|
||||
** things I want to figure out in the future:
|
||||
1. joining patterns in parallel - percussion + rythm + solo
|
||||
2. having 3 beats in percussion but aligning to 4 beats
|
||||
3. getting cool instruments from existing repos for supercollider
|
||||
* [2022-08-21 Sun]
|
||||
** now, I got another response!
|
||||
Yes unfortunately it's not always easy to directly translate synthdefs from SC into cl-collider. Some of the UGens are named differently (i.e. SinOsc in SC is sin-osc in cl-collider). The UGens are defined in cl-collider with defugen though, so you could do a grep or similar on the library to get a list of the defined ugens.
|
||||
Regarding the "attributes" you mention, do you mean the arguments for each ugen? If so, are you using Emacs or another editor? I believe Emacs should show the function signature in the echo area at the bottom of the screen if you're in the right package (i.e. you need to have an in-package form in your file)
|
||||
If you have a specific synthdef you're having trouble translating, feel free to link me to it and I'll see if I can translate it for you as an example
|
||||
Oh I see you do have an in-package in the example you posted. It might not be showing the function signature since you're doing in-package cl-patterns but the cl-patterns package doesn't include the UGens. so you might have to make a new package that :uses cl-patterns and cl-collider, so it has all the ugens as well as all the patterns.
|
||||
efim
|
||||
Apart from guidance on how to better translate SC definition of sync into DEFSYNTH attributes to get other instruments
|
||||
|
||||
could you help me understand how to join patterns?
|
||||
|
||||
I created two
|
||||
|
||||
(pb :what-predef-chord
|
||||
:instrument :tone-pluck
|
||||
: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
|
||||
)
|
||||
|
||||
|
||||
(pb :what-basic-percussion
|
||||
:instrument :kik
|
||||
:note 0
|
||||
:dur (pseq '(1) 1)
|
||||
:play-quant 4)
|
||||
and wanted to join them to play in parallel as a pattern
|
||||
|
||||
and I think I'm getting lost in understanding types, what is pattern, what isn't
|
||||
|
||||
because there's an example for PPAR:
|
||||
|
||||
(next-upto-n (ppar (list (pbind :dur (pn 1/2 4))
|
||||
(pbind :dur (pn 2/3 4)))))
|
||||
but doing
|
||||
(next-upto-n (ppar (list :what-basic-percussion :what-predef-chord)))
|
||||
|
||||
doesn't yield sound events
|
||||
|
||||
so maybe I can't reference patterns by name they get in PB ?
|
||||
|
||||
would I need to use PBIND to define both of previous patterns,
|
||||
set them to some variables,
|
||||
and then they could be used as subpatterns?
|
||||
|
||||
For now I already got tired with how much there is to learn,
|
||||
I've set up "live recording" from (next-upto-n (ppar (list :what-basic-percussion :what-predef-chord)))
|
||||
|
||||
and celebrate initial success, theres 9 second pause in the beginning, but that's my first composition with so much to learn
|
||||
|
||||
next-upto-n won't play any sounds on its own, it's just used to get the resulting event objects from the patterns. You'd still need to call play on whatever pattern you define. So something like this could work:
|
||||
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
(pdef :foo (ppar (list (pdef :what-predef-chord)
|
||||
(pdef :what-basic-percussion))))
|
||||
|
||||
(play (pdef :foo))
|
||||
Oh, I see what you meant. Yeah, it looks like ppar doesn't accept just the pattern names, so you would have to do this instead:
|
||||
|
||||
1
|
||||
(next-upto-n (ppar (list (pdef :what-basic-percussion) (pdef :what-predef-chord))))
|
||||
It probably should accept the pattern names directly though, so I will see about fixing that soon.
|
||||
When you define a pattern like (pb :foo ...) it's basically the same as doing (pdef :foo (pbind ...)). So if you define a pattern with pb you can refer back to it with pdef later on.
|
||||
Today
|
||||
modula
|
||||
efim
|
||||
foo.aiff (4.74 MB)
|
||||
very nice! definite good first steps, glad to hear you're making progress :)
|
||||
it does take some learning but hopefully it will make more sense as you gain familiarity with it
|
||||
I'm trying to make cl-patterns as intuitive as possible, but there are definitely some rough edges i don't notice until they're pointed out.
|
||||
Oh, also, if you want to record a pattern, you might be interested in the render function. Basically you can do something like (render (pdef :your-pattern) "/path/to/output.wav" :dur 4) and it will save 4 beats of :your-pattern to /path/to/output.wav.
|
||||
I'm not sure if that's what you were using for that recording, but it may be more convenient if you were using something else.
|
||||
** ok, so let's search github for synthdef ?
|
||||
** now I want to do what?
|
||||
1. try out parallel
|
||||
2. try to get precussion
|
||||
3. also let's try to get defpackage and stuff
|
||||
** so, let's copy yesterdays instruments and patterns and try to join them in parallel
|
||||
* [2022-08-28 Sun]
|
||||
** ok, got new responses
|
||||
more about :act :free and nuances of creating with pulse-driver
|
||||
** and I think I understand Env(elope) better now, yay?
|
||||
* [2022-09-01 Thu]
|
||||
** DONE so, I do have some percussion rhythm, let's try something more interesting?
|
||||
** DONE and try to write with the adviced better function
|
||||
** and maybe try to get other instruments
|
||||
** new thing! if I keep pattern playing and reeval it's definition - new definition would start playing, cool
|
||||
** message
|
||||
Over the weekends I've learned quite a bit!
|
||||
|
||||
Previous questions were definitely more pointed to me figuring out how to do synthdefs that could be used as :instrument in patterns
|
||||
|
||||
Now I kind of understand part of EnvGen (Envelope) - it takes two lists, and emits values of first list by timeperiods from the second list
|
||||
and that can be fed into any part of other generator - as frequency for SIN-OSC, or amptitue
|
||||
|
||||
past sunday with your help I've figured out how to make percussion instruments from SuperCollider example and done simplest regular beat
|
||||
|
||||
Today I tried to figure out more complicated beats, and how to join different lines with pauses
|
||||
|
||||
Still lots to do, but will share what I've accomplished in hopes that it returns you a little bit of excitement your project brings
|
||||
** reading more guids : here about pitch model, duration model
|
||||
http://doc.sccode.org/Tutorials/Streams-Patterns-Events5.html
|
||||
** some advice from a veteran:
|
||||
https://nathan.ho.name/posts/supercollider-tips/
|
||||
** so, now I could try figuring out other instruments?
|
||||
i already found link to examples:
|
||||
[[*awesome list : https://github.com/madskjeldgaard/awesome-supercollider#synthdefs][awesome list : https://github.com/madskjeldgaard/awesome-supercollider#synthdefs]]
|
||||
|
||||
https://github.com/SCLOrkHub/SCLOrkSynths/tree/master/SynthDefs/bass
|
||||
|
||||
these are specifically for use with patterns, cool, but more things to learn before I can rewrite them in cl =0
|
||||
*** so, "go to definition" didn't work with #'ENV but worked with #'ENV-GEN and env was close
|
||||
there I searched for "perc" to see
|
||||
https://depts.washington.edu/dxscdoc/Help/Classes/Env.html
|
||||
what is the analogue Env.perc
|
||||
and that I guess is just #'PERC
|
||||
|
||||
yay, I suppose
|
||||
*** a question into the matrix channel:
|
||||
I've tried to go and convert some of the synths found online into CL form
|
||||
overall when I needed to figure out something I don't quite understand
|
||||
|
||||
for example
|
||||
|
||||
Env.adsr(...)
|
||||
I went to SuperCollider documentation, saw that it's a constructor method for Env, went to definition of EnvDef and searched for adsr, and it's a convenient separate method
|
||||
or
|
||||
|
||||
LFPulse.ar(freq: freq, width: width).range(-1, 1);
|
||||
went to #'LF-PULSE definition and searched for "range" found that it's a separate generic method that supposedly takes in lf-pusle object (I'm after basics, but at the beginning of figuring out CL)
|
||||
With that - I think I missed something important, could you help me out?
|
||||
|
||||
When translating https://github.com/SCLOrkHub/SCLOrkSynths/blob/master/SynthDefs/bass/acidOto3091.scd
|
||||
|
||||
I totally didn't know what to do with
|
||||
curve: [-1 * curve, curve, curve, curve],
|
||||
|
||||
my guess is that it's connected to multi-level? That's when I think I was arrays used?
|
||||
|
||||
What I got produced an interesting sound, but didn't stop
|
||||
|
||||
(defsynth acid0to3091 ((amp 0.5) (out 0) (gate 1) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0) :gate gate))
|
||||
;; (filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (list (* -1 curve) curve curve curve ) 1) gate :act :free))
|
||||
;; this is likely not correct way to set up cure of the form curve: [-1 * curve, curve, curve, curve],
|
||||
;; does that mean multichannel things?
|
||||
;; let's just set as single curve and check how it looks?
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (* -1 curve) 1) :gate gate :act :free))
|
||||
;; is LFPulse.ar(...).range(-1, 1) gets from _range ?
|
||||
(sndStep1 (_range nil (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
(synth :acid0to3091)
|
||||
(stop)
|
||||
And I'm currently very far from being able to debug \ troubleshoot what's going on here,
|
||||
I do have one #'ENV-GEN that has :act :free
|
||||
but can't follow all the transformations, so have no idea what's going wrong
|
||||
* [2022-09-02 Fri]
|
||||
** got a helpful response
|
||||
with fixed synthdefs
|
||||
** tried synths in a pattern and they work!
|
||||
even though they don't stop on their own,
|
||||
so maybe `gate` is a default argument that passes control from the pattern system, using `dur`
|
||||
* [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?
|
||||
* [2022-09-05 Mon]
|
||||
** let's what? move instruments into separate organized files?
|
||||
meh, let's try for arpeggio from chords?
|
||||
or something
|
||||
** DONE - learn more about puttin melodies in, midinotes and stuff
|
||||
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
|
||||
** 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
|
||||
|
||||
if I try to use not random, but "from sequence", then on pattern restart I'd get first element of the sequence every time.
|
||||
|
||||
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
|
||||
** what I want next - clean up defsynths, clean up arpegio thing, bass thing
|
||||
maybe put everything under "dirty-journal" directory
|
||||
and start a "clean" journal
|
||||
* [2022-09-09 Fri]
|
||||
** let's move everything into "dirty-journal"
|
||||
* [2022-09-11 Sun]
|
||||
** so, today I've been writing bass arpeggios
|
||||
** biggest questin - upbeat before first bar,
|
||||
how to effectively write that?
|
||||
|
||||
so that it would be easy to sync things on :quant
|
||||
** thing I found out -
|
||||
it would be nice to specify chords and chord-bases as a pattern
|
||||
to be embedded
|
||||
|
||||
that way I'd be able to switch it up on the go and all patterns extending it would pick it up?
|
||||
well, maybe not all at the same time, if they are not synched =C
|
||||
** would be nice to put everything of 09-09 and 09-11 into single file
|
||||
to make it easier to restart whole first experiment with different chords
|
||||
|
||||
also, have I saved a link to the side where I saw the chord progressions I used?
|
||||
|
||||
also-also having a keyboard could be a nice help
|
||||
@@ -1,71 +0,0 @@
|
||||
#+title: Programming Music Journal
|
||||
* [2022-08-19 Fri]
|
||||
** past friday I've done some basic setup (painfully) and had simplest examples running
|
||||
[[file:supercollider-example.lisp::;; to use cl-patterns with its SuperCollider backend, you'll first need to load the cl-patterns/supercollider system with quicklisp:][setting up supercollider]] package - so this doesn't work for some reason
|
||||
** here simplest things seem to work
|
||||
[[file:setting-up-cl-collider.lisp::;; https://defaultxr.github.io/cl-collider-tutorial/02-getting-started.html][cl-collider-tutorial-getting-started]]
|
||||
** so, let's just go the site?
|
||||
nope, continue with the file that had some promise
|
||||
the one about cl-collider turorial
|
||||
** also, let's make this a separate repo?
|
||||
oh, no, the 'supercollider-example' which is about cl-patterns started to work?
|
||||
|
||||
how and why? maybe reinit of some shit, or what
|
||||
|
||||
so, new file to hopefully learn something about cl-patterns
|
||||
*** what is it that I want o learn ideally?
|
||||
setting up drum sequences?
|
||||
|
||||
doing chord things with synth?
|
||||
** what's this thing about "FAILURE IN SERVER /n_set Node 1539 not found "
|
||||
?
|
||||
** this seems to be startup
|
||||
#+begin_src common-lisp
|
||||
(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)
|
||||
#+end_src
|
||||
|
||||
but what's most basic pattern that would play then?
|
||||
|
||||
ones in [[file:2022-08-12-supercollider-example.lisp::end :bar][supercollider example seem to work]]
|
||||
|
||||
and example seem to require me to define synth, right?
|
||||
to set it into the :instrument key
|
||||
|
||||
wtf am I to do.
|
||||
** maybe let's try to do stuff inside of org file?
|
||||
** how do I clear things, it seems that cl-patterns seems to send things to server?
|
||||
** should I try a different backend?
|
||||
** so, when SC returned lots of errors on pb what helped - starting syn wave from "setting-up" file
|
||||
;;; https://defaultxr.github.io/cl-collider-tutorial/03-make-a-sound.html
|
||||
(setf *s* (make-external-server "localhost" :port 4444))
|
||||
(server-boot *s*) ; already in use
|
||||
|
||||
|
||||
;;; https://defaultxr.github.io/cl-collider-tutorial/03-make-a-sound.html
|
||||
(proxy :foo (sin-osc.ar 440 0 0.2)) ; no error, but hear no sound
|
||||
;; opened QjackCtl, connected Graph SuperCollider to Air by Aftershokz left
|
||||
(proxy :foo (sin-osc.ar 300 0 0.2))
|
||||
(proxy :foo (saw.ar 300 0.2))
|
||||
|
||||
** how do I make sounds better?
|
||||
do I go to cl-collider package for explanation of synths and such?
|
||||
** to stopp things that run amok:
|
||||
(cl-patterns:stop t)
|
||||
** ugh. why doesn't it produce sounds?
|
||||
** ok, what did I learn today?
|
||||
- some interaction with pseq
|
||||
having scales, root / ocave
|
||||
- intersecting with durations, also seq and not totally alighning
|
||||
- some combined sounds, which don't sound nice
|
||||
- maybe reliant startup procedure
|
||||
- and attempting to run chords hangs it all
|
||||
4
stabler-things/functions.lisp
Normal file
4
stabler-things/functions.lisp
Normal file
@@ -0,0 +1,4 @@
|
||||
(in-package :cl-patterns)
|
||||
(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 (chord symbol))))
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
;; https://defaultxr.github.io/cl-collider-tutorial/02-getting-started.html
|
||||
|
||||
(ql:quickload :cl-collider)
|
||||
@@ -8,6 +7,7 @@
|
||||
(server-boot *s*) ; already in use
|
||||
|
||||
|
||||
(ql:quickload :cl-patterns)
|
||||
(ql:quickload :cl-patterns/supercollider)
|
||||
|
||||
;; ...this will take care of loading cl-collider for you if it's not already loaded.
|
||||
170
stabler-things/synthesizers.lisp
Normal file
170
stabler-things/synthesizers.lisp
Normal file
@@ -0,0 +1,170 @@
|
||||
(in-package #:cl-collider)
|
||||
|
||||
;;; keys
|
||||
|
||||
(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)))
|
||||
|
||||
;;; strings
|
||||
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
|
||||
(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))))
|
||||
|
||||
(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))))
|
||||
|
||||
(defsynth violin ((freq 440) (gate 1) (amp 1) (pan 0) (out 0) (att 0.1) (dec 0.1) (sus 0.5) (rel 0.1)
|
||||
(vRate 4.6) (vDepth 0.02) (vAtt 0.15) (vRateVar 0.25) (vDepthVar 0.05)
|
||||
(pwmVarRate 2) (pwmMin 0.7) (pwmMax 0.8) (pwmRate 5)
|
||||
(bridgeFreq 2500) (scratchDepth 0.15))
|
||||
(let* ((scratch (+ 1.025 (env-gen.kr (perc att (* 1.25 dec) scratchDepth))))
|
||||
(envelope (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (vibrato.kr freq vRate vDepth (+ att dec) vAtt vRateVar vDepthVar))
|
||||
(pwm-step-1 (range (sin-osc.kr pwmRate (rand.ir 0.0 1.0)) pwmMin pwmMax))
|
||||
(pwm-step-2 (* pwm-step-1 (range (lf-noise2.kr pwmVarRate) 0.2 0.8)))
|
||||
(snd-step-1 (var-saw.ar (*
|
||||
(lag.kr freq)
|
||||
(range (lf-pulse.ar (* freq 1.5)) (/ 1 scratch) scratch))))
|
||||
(snd-step-2 (+ (* snd-step-1 0.7)
|
||||
(bpf.ar snd-step-1 bridgeFreq 2 2)))
|
||||
(snd-step-3 (* snd-step-2 amp envelope)))
|
||||
(out.ar out (pan2.ar snd-step-3 pan))))
|
||||
|
||||
;;; percussion
|
||||
|
||||
(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 bdrum ((amp 0.5) (out 0) )
|
||||
(out.ar out (* amp (sin-osc.ar (line.ar 120 60 1) 0 (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free)))))
|
||||
|
||||
(defsynth snare ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (white-noise.ar (env-gen.ar (env (list 0 1 0.3 0) (list 0.005 0.01 0.5)) :act :free)))))
|
||||
|
||||
(defsynth hihat ((amp 0.5) (out 0))
|
||||
(out.ar out (* amp (hpf.ar (white-noise.ar 1) 10000) (env-gen.ar (env (list 0 1 0) (list 0.005 0.5)) :act :free))))
|
||||
|
||||
;;; bass
|
||||
|
||||
(defsynth acid0to3091 ((amp 0.5) (out 0) (gate 1) (freq 440) (pan 0) (att 0.001) (dec 0.5) (sus 0.1) (rel 0.5) (curve -4) (lagTime 0.12) (filterRange 6) (width 0.51) (rq 0.3))
|
||||
(let* ((freq (lag.kr freq lagTime))
|
||||
(ampEnv (env-gen.kr (adsr att dec sus rel amp 0) :gate gate))
|
||||
(filterEnv (env-gen.kr (adsr att (* 2 dec) (/ sus 2) (* 2 rel) (expt 2 filterRange) (list (* -1 curve) curve curve) 1) :gate gate :act :free))
|
||||
(sndStep1 (range (lf-pulse.ar freq 0.0 width) -1 1))
|
||||
(sndStep2 (rlpf.ar sndStep1 (* freq filterEnv) rq))
|
||||
(sndStep3 (* sndStep2 ampEnv)))
|
||||
(out.ar out (pan2.ar sndStep3 pan))))
|
||||
|
||||
(defsynth fmBass ((out 0) (freq 440) (gate 1) (amp 0.5) (pan 0) (att 0.01) (dec 0.3) (sus 0.4) (rel 0.1) (slideTime 0.17) (cutoff 1100) (width 0.15) (detune 1.005) (preamp 4))
|
||||
(let* ((env (env-gen.kr (adsr att dec sus rel) :gate gate :act :free))
|
||||
(freq (lag.kr freq slideTime))
|
||||
(sndStep1 (var-saw.ar (list freq (* freq detune)) 0 width preamp))
|
||||
(sndStep2 (distort (mix sndStep1)))
|
||||
(sndStep3 (* sndStep2 env))
|
||||
(sndStep4 (lpf.ar sndStep3 cutoff amp)))
|
||||
(out.ar out (pan2.ar sndStep4 pan))))
|
||||
|
||||
;;; air
|
||||
|
||||
;; doesn't seem to work, right?
|
||||
(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)))))
|
||||
|
||||
;;; simplistic
|
||||
|
||||
(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 tone-buzz ((freq 440) (amp 0.2) (gate 1))
|
||||
(out.ar 0 (*
|
||||
(saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune)))
|
||||
(/ amp 2))
|
||||
(env-gen.kr (asr 0 1 0.1) :gate gate :act :free))))
|
||||
|
||||
(defsynth tone-pluck ((freq 440) (amp 0.2))
|
||||
(out.ar 0 (* (saw.ar (let ((detune (* freq 0.01)))
|
||||
(list (- freq detune) (+ freq detune))))
|
||||
(env-gen.kr (perc 0.1 1.8)
|
||||
:level-scale amp
|
||||
:act :free))))
|
||||
|
||||
(defsynth sine-wave ((note 60) (freq 400))
|
||||
(let* ((freq (midicps note))
|
||||
(sig (sin-osc.ar freq 0 .2)))
|
||||
(out.ar 0 sig)))
|
||||
Reference in New Issue
Block a user