The Csound Blog by Jacob Joaquin email jacobjoaquin@gmail.com web www.thumbuki.com/csound/blog (C)2007 Jacob Joaquin Licensed under Creative Commons (see below) 2007.04.20 A Micro Intro to Macros I'm continuing with what I started in the last blog "Adding Zak to the Mix."[1] As promised, I'm breaking down the zak mixer into its respective modular components, beginning with Csound macros. First, I want to give credit to where credit is due. Csound's macro system was written and implemented by John ffitch.[2] I just want to say to John, (thank you)^3, as Csound has been much more pleasurable to work with since I started integrating macros into my personal Csound programming style. My only regret is that I wish I started using them years ago. What is a macro? In The Csound Book, John ffitch defines a macro as being "a string that gets replaced by some other text..."[3] I haven't a found a better description anywhere. In the zak mixer, I only use the #define macro in its simplest form. I define the $NAME, and associate a string of text with it. In the following example, I create a macro called "sine", and associate it with the string "1". #define sine #1# gitemp ftgen $sine, 0, 65536, 10, 1 instr 1 aosc oscil 10000, 440, $sine out aosc endin As Csound interprets the code, it reads every instance of $sine as if it was an actual "1". Internally, the code looks like this: gitemp ftgen 1, 0, 65536, 10, 1 instr 1 aosc oscil 10000, 440, 1 out aosc endin Even in its most basic form, a macro like this helps me avoid the need to make several, dozens or even hundreds of changes by hand. If I need to change the index number of my sine table, for whatever reason, I only have to alter the definition rather than tediously tidying up every single parameter that reads a sinewave table function number. As an extra bonus, the readability of my code is also increased, as $sine is a much better indicator of what the code is doing than some arbitrary number. There is one particular quirk about the macro system I feel obligated to point out. Macros defined in the orchestra are not recognized by the score, and vice versa. This forces us to make definition alterations in not one place, but two. Unless... If we move our definitions into a separate file, we can use #include in both the orchestra and score to point to a single list. The only trade-off with this method is if you normally work in a single unified csd file, you will have to get use to the idea of coding in multiple files. This is probably better programming practice, anyways. Since all these blog entries are self contained, I can't demonstrate a working #include example. Though I do have a line of code in both the orchestra and score, commented out, where I normally include my external definitions. For a more thorough explanation, look up macros in the Csound manual[4], and be sure to read John ffitch's chapter "Using Csound's Macro Language Extensions" in The Csound Book.[5] In some future edition of The Csound Blog, I will discuss how macros are integrated with the zak opcodes to create a more efficient routing system than using zak opcodes alone. Best, Jake Permalink http://www.thumbuki.com/20070420/a-micro-intro-to-macros.html References [1] The Csound Blog - Adding Zak to the Mix http://www.thumbuki.com/csound/files/thumbuki20070410.csd [2] John ffitch @ Wikipedia http://en.wikipedia.org/wiki/John_ffitch [3] Boulanger, Richard C. (Editor) and ffitch, John The Csound Book Ch. 5 Pg. 137 Cambridge, Massachussetts: The MIT Press, 2000 [4] The Csound Manual http://csounds.com/manual/html/index.html [5] Boulanger, Richard C. (Editor) and ffitch, John The Csound Book Ch. 5 Cambridge, Massachussetts: The MIT Press, 2000 License (cc) Creative Commons Attribution-ShareAlike 2.5 You are free: * to Share -- to copy, distribute, display, and perform the work * to Remix -- to make derivative works Under the following conditions: * Attribution. You must attribute the work in the manner specified by the author or licensor. * Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. * For any reuse or distribution, you must make clear to others the license terms of this work. * Any of these conditions can be waived if you get permission from the copyright holder. http://creativecommons.org/licenses/by-sa/2.5/ sr = 44100 kr = 4410 ksmps = 10 nchnls = 1 ; instr 1 Sample and Hold Thumper ; ---- Macro definitions ---- ; #include "foo.macro" ; Example only. File doesn't actually exist. #define sine # 1 # #define triangle # 2 # #define tempo # 90 # #define end # 16 # #define amp # 32768 # ; ---- Sample and Hold Thumper ---- instr 1 idur = p3 iamp = p4 ipch = cpspch( p5 ) imin = p6 imax = p7 ; Get random pitch at tempo dependent time interval krandom random imin, imax kphasor phasor 4 * $tempo / 60 ktrigger trigger kphasor, 0.717, 1 ksamphold samphold krandom, ktrigger kpch = ipch * 2^( int( ksamphold ) / 12 ) ; Envelope kenv linseg 1, idur - 0.05, 1, 0.05, 0 ; Generate Audio a1 oscil $amp * kenv, ( 1 - kphasor ) * kpch, $sine a2 oscil $amp * kenv, ( 1 - kphasor ) * kpch, $triangle ; Crossfade between a1 to a2 over the duration of the instance kcrossfade phasor 1 / idur amix = a1 * ( 1 - kcrossfade ) + a2 * kcrossfade ; Output Audio out amix * iamp endin ; ---- Macro definitions ---- ; #include "foo.macro" ; Example only. File doesn't actually exist. #define sine # 1 # #define triangle # 2 # #define tempo # 90 # #define end # 16 # #define amp # 32768 # ; ---- f-tables ---- f $sine 0 65536 10 1 f $triangle 0 65536 -7 -1 32768 1 32768 -1 t 0 $tempo i1 0 $end 1 8.00 -12 12 e $end