diff --git a/2022-09-01-more-percussions-and-write-to-file.lisp b/2022-09-01-more-percussions-and-write-to-file.lisp new file mode 100644 index 0000000..5da41fa --- /dev/null +++ b/2022-09-01-more-percussions-and-write-to-file.lisp @@ -0,0 +1,317 @@ +;;; 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 +;; # +;; 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 +;; # +;; 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 diff --git a/programming-music-journal.org b/programming-music-journal.org index 7e97f54..9b13d50 100644 --- a/programming-music-journal.org +++ b/programming-music-journal.org @@ -207,3 +207,21 @@ I'm not sure if that's what you were using for that recording, but it may be mor ** 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