#+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 ** NEXT - 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,