{"id":977,"date":"2016-07-13T23:50:37","date_gmt":"2016-07-13T22:50:37","guid":{"rendered":"http:\/\/michael-edwards.org\/wp\/?p=977"},"modified":"2017-11-28T15:55:50","modified_gmt":"2017-11-28T15:55:50","slug":"guest-professorship-at-the-folkwang-university-essen","status":"publish","type":"post","link":"https:\/\/michael-edwards.org\/wp\/?p=977","title":{"rendered":"Control Waves and Guest Professorship at the Folkwang University, Essen"},"content":{"rendered":"<p>I&#8217;m just coming to the end of my second week of teaching in the\u00a0Institute for Computer Music and Electronic Media (<a href=\"http:\/\/icem-www.folkwang-uni.de\/\" target=\"_blank\" rel=\"noopener\">ICEM<\/a>) at the\u00a0<a href=\"http:\/\/www.folkwang-uni.de\/\" target=\"_blank\" rel=\"noopener\">Folkwang University of the Arts<\/a>\u00a0in Essen, Germany. It&#8217;s \u00a0a pleasure to be here, working with the dedicated and friendly students and staff. \u00a0I&#8217;ll be a Guest Professor until the end of 2016 and I&#8217;m already looking forward to coming back.<\/p>\n<p>I&#8217;m compressing a lot of teaching into the time I spend here&#8212;each of these two weeks have involved around 30 hours of class time. A lot of this is one-on-one teaching&#8212;always a pleasure&#8212;and I&#8217;m learning a lot by talking through the generative approaches necessary to realising the students&#8217; works.<\/p>\n<h2>control waves<\/h2>\n<p>One thing I developed in response to a student&#8217;s need turned out to be so generally applicable\u00a0that it demanded to be incorporated\u00a0into the\u00a0<em><a href=\"http:\/\/michael-edwards.org\/sc\" target=\"_blank\" rel=\"noopener\">slippery chicken<\/a>\u00a0<\/em>project: control waves. Many of us use classic waveforms like sine and sawtooth to control data in our electronic compositions, particularly in real-time. The use of LFOs (low frequency oscillators) to modulate, say, the cutoff frequencies of filters, has been standard practice since the days of analogue synths. I&#8217;ve not had cause to add and use these\u00a0in my own algorithmic composition work to date (though they&#8217;re in plenty of my mixes and improvisations), but I&#8217;ve now created a set of classes that can create and access such waveforms.\u00a0You can find the code in the latest online <em>slippery chicken<\/em>\u00a0repository and\/or <a href=\"https:\/\/github.com\/mdedwards\/slippery-chicken\/blob\/master\/control-wave.lsp\" target=\"_blank\" rel=\"noopener\">view it online<\/a>.<\/p>\n<h2>CLM<\/h2>\n<p>The parent\u00a0control-wave class takes advantage of the speed of\u00a0<em><a href=\"https:\/\/ccrma.stanford.edu\/software\/snd\/snd\/clm.html\" target=\"_blank\" rel=\"noopener\">Common Lisp Music<\/a>\u00a0<\/em>(CLM)\u00a0to generate all the control-rate sample points necessary for a complete\u00a0piece. The idea is that you pass envelope descriptions of frequency and amplitude changes along with data to offset and scale the wave&#8217;s values as desired, then generate a\u00a0waveform over the whole duration of a piece (with a default but user-selectable sample rate of 1000 points per second). You then query the waveform at any time point during the generation of, say, note, amplitude, rhythm, or any other parameter\/data needed for your algorithmic piece.<\/p>\n<p>The CLM code below is a\u00a0rare example of an\u00a0instrument that returns<em>\u00a0<\/em>useful data from its code via <em>run*<\/em>&#8212;in this case an array of curve points. Most CLM instruments are aimed at writing sound files of course. We do that here almost as a side-effect, so that we can look at our lovely curves in a sound editor, for example. Our main interest though is in the array of data we get back from our implicit call to the CLM instrument made during the creation of our new <em>control-wave<\/em> object.<\/p>\n<pre>(definstrument ctlwav\r\n    ;; frequency can also be an envelope\r\n    (frequency duration &amp;key\r\n               ;; (make-fun #'make-oscil)\r\n               ;; (gen-fun #'oscil)\r\n               (time 0.0)\r\n               ;; case in the run loop can't handle symbols hence integers here:\r\n               ;; 1=sine, 2=cosine, 3=sawtooth, 4=triangle, 5=square,\r\n               ;; 6=pulse(single sample of 1.0 follwed by zeros)\r\n               (type 1)\r\n               (initial-phase 0.0)      ; in radians\r\n               (amplitude 1.0)\r\n               (rescale nil) ; or '(minimum maximum)\r\n               (amp-env '(0 1 100 1)))\r\n  ;; for ease and at the expense of a little computation force a freq-env\r\n  (unless (listp frequency)\r\n    (setf frequency (list 0 frequency 100 frequency)))\r\n  (let* ((beg (floor (* time *srate*)))\r\n         ;; 1+ so we can access the value at  if necessary...it's\r\n         ;; just one sample extra\r\n         (dur-samps (1+ (ceiling (* duration *srate*))))\r\n         (end (+ beg dur-samps))\r\n         (samples (make-double-float-array dur-samps))\r\n         (samp 0.0)\r\n         (rsamp 0.0)\r\n         (indx 0)\r\n         (prop 0.0)\r\n         (fm 0.0)\r\n         (start-freq (second frequency))\r\n         (fenv (make-env :envelope frequency :duration duration\r\n                         :offset (- start-freq)))\r\n         ;; square and pulse go from 0 to 1, the rest -1 to 1\r\n         (wav-min (if (member type '(5 6)) 0.0 -1.0))\r\n         (wav-range (if (zerop wav-min) 1 2))\r\n         (out-min (when rescale (first rescale)))\r\n         (out-max (when rescale (second rescale)))\r\n         (out-range (when rescale (- out-max out-min)))\r\n         (wav (funcall (case type\r\n                         (1 #'make-oscil)\r\n                         (2 #'make-oscil)\r\n                         (3 #'make-sawtooth-wave)\r\n                         (4 #'make-triangle-wave)\r\n                         (5 #'make-square-wave)\r\n                         (6 #'make-pulse-train)\r\n                         (t (error \"ctlwav: unknown wave type: ~a\" type)))\r\n                       :frequency start-freq :initial-phase initial-phase))\r\n         (ampf (make-env :envelope amp-env :scaler amplitude\r\n                         :duration duration)))\r\n    (when (= type 2)                     ; cosine\r\n      (setf (mus-phase wav) (mod (+ initial-phase (\/ pi 2)) pi)))\r\n    ;; save some computation in the run loop if we're not actually rescaling.\r\n    (when (and (= wav-min out-min)\r\n               (= out-max 1.0))\r\n      (setf rescale nil))\r\n    (run* (samples)\r\n          (loop for i from beg to end do\r\n               (setf fm (hz-&gt;radians (env fenv))\r\n                     samp (* (env ampf)\r\n                             ;; can't use funcall in run though apply should\r\n                             ;; work (but doesn't for me here)\r\n                             (case type\r\n                               (1 (oscil wav fm))\r\n                               (2 (oscil wav fm))\r\n                               (3 (sawtooth-wave wav fm))\r\n                               (4 (triangle-wave wav fm))\r\n                               (5 (square-wave wav fm))\r\n                               (6 (pulse-train wav fm))))\r\n                     rsamp samp)\r\n               (when rescale\r\n                 (setf prop (\/ (- samp wav-min) wav-range)\r\n                       rsamp (+ out-min (* prop out-range))))\r\n               (setf (aref samples indx) rsamp)\r\n               (incf indx)\r\n               (outa i samp)))\r\n    samples))<\/pre>\n<p>The following example shows two control-wave classes in action: a sine wave to generate the sweep of notes through the harmonic series, and a sawtooth wave to control the rhythmic aspects:<\/p>\n<pre>(let* ((duration (* 3 60))\r\n       (fundamental 100)\r\n       (harmonics (make-control-sine \r\n                   :frequency '(0 .1 100 1)\r\n                   :minimum 1 :maximum 21 :duration duration\r\n                   :amp-env '(0 .5 20 .8 30 .4 50 .9 70 .5 100 1)))\r\n       (delta (make-control-sawtooth\r\n               :frequency '(0 .1 30 .2 50 .1 100 4)\r\n               :minimum 0.05 :maximum .3 :duration duration\r\n               :amp-env '(0 1 100 .1)))\r\n       d h e\r\n       (time 0.0)\r\n       (events\r\n        (loop while (&lt;= time duration) do\r\n             (setf d (get-data time delta)\r\n                   h (get-data time harmonics)\r\n                   ;; if we want frequency accuracy we should pass an\r\n                   ;; already-created pitch object to make-event; converting to\r\n                   ;; note symbols just will not do.\r\n                   e (make-event (make-pitch (* (round h) fundamental))\r\n                                 (* d .7) :duration t :start-time time))\r\n             (incf time d)\r\n           collect e)))\r\n  (event-list-to-midi-file events :start-tempo 60))\r\n\r\n<\/pre>\n<p>&#8230;which creates this <a href=\"https:\/\/michael-edwards.org\/wp\/wp-content\/uploads\/tmp-1.mid\" target=\"_blank\" rel=\"noopener\">weird little MIDI file<\/a>, full of just-intoned delights and a seemingly unevolving\u00a0but constantly varying yet repetitive curve which almost unexpectedly\u00a0ends up in a quite different place from where it started.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m just coming to the end of my second week of teaching in the\u00a0Institute for Computer Music and Electronic Media (ICEM) at the\u00a0Folkwang University of the Arts\u00a0in Essen, Germany. It&#8217;s \u00a0a pleasure to be here, working with the dedicated and friendly students and staff. \u00a0I&#8217;ll be a Guest Professor until the end of 2016 and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":978,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[143],"tags":[3,149,4,148,146,144,147,145,40,6],"class_list":["post-977","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teaching","tag-algorithms","tag-clm","tag-common-lisp","tag-control-waves","tag-essen","tag-folkwang","tag-germany","tag-icem","tag-musician-tweaked-algorithmic-composition","tag-slippery-chicken"],"_links":{"self":[{"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/posts\/977","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=977"}],"version-history":[{"count":23,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/posts\/977\/revisions"}],"predecessor-version":[{"id":1134,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/posts\/977\/revisions\/1134"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=\/wp\/v2\/media\/978"}],"wp:attachment":[{"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=977"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=977"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michael-edwards.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=977"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}