back to main page
csound-eel & embedded Emacs Lisp
The csound-eel package is a library based on the embedded-elisp minor mode (provided by embedded-elisp-library.el, which should be part of the csound-x distribution). It is not loaded by default. Its usage is intended for people already familiar with emacs lisp: this is _not_ user-friendly !
Basically, doing "embedded elisp" means stuffing a csd document with lisp code areas and specific comments providing a meta-control of the composition. This is a very powerful feature.
As I don´t really know how to document this, we will proceed with an example.
Let´s start from this csd file (I got it from the Amsterdam catalog of Csound instruments)
We are going to transform it into a template allowing an exploration of its algorithm. The instruments (identical, except from their ouput channel) are very simple: a reference oscillator at frequency p5 is doubled by height extra oscillators whose frequencies are slight variations of p5 controlled by p6. Given p6, the set of shifted frequencies is hardcoded: p5+p6, p5+2*p6, p5+3*p6, p5+4*p6, p5-p6, p5-2*p6, p5-3*p6 and p5-4*p6
Using the "macroify region" in the "Csd" menu, it is easy to transform the csd so that the p6 multipliers are now defined by the macros m1, m2 and m3. We get this file.
Now comes the lisp code. With embedded-elisp enabled (this is done through the "invoke EEL mode" in the "Csd" menu), we can create a new active <ELISP> area at the top of the document (do so from the "EEL" menu):
<ELISP> ;;; [load] - [collapse/unfold] - [save] - [EVAL] - [;EVAL]
(require csound-eel)
</ELISP>
<CsoundSynthesizer>
<CsInstruments>
#define m3 #4#
#define m2 #3#
...
where [EVAL] is actually a button (use the "wake-up embedded buttons" from the "EEL" menu to make it alive if it isn´t): clicking on it does evaluate (require csound-eel)
This area is quite simple: all it does if check that csound-eel has been loaded.
For future usage, it would be nice to have this evaluated automatically when EEL mode is enabled. This possible by having the "<auto>" keyword in the header line of the ELISP area. We can then remove all other text there since it´s useless:
<ELISP> ;;; <auto>
(require csound-eel)
</ELISP>
Note that EEL mode itself can be enabled by default when visiting a csd file: simply set the variable cscsd-use-EEL to t (see this page for a list of all customization variables).
When (require csound-eel) is evaluated, a new "Settings" sub-menu should appear under "Csd": it allows you to jump to the places where the macro m1, m2, and m3 are defined, and also to take a snapshot.
So we click on "take a snapshot" and give it the name "original" at the minibuffer. Here is what we get as a resulting file. As you can see, a new <ELISP> area has been prepended to the csd file. When clicking on its [restore] button, m1, m2 and m3 will get back to their original values.
Restoring a snapshot is also possible from the "Settings" menu, where a "Restore snapshot" submenu should appear, providing a list of all defined snapshots in the buffer.
So now we can go on and change the definitions for m1, m2, m3 to, say, 2, 4 and 8. Then, taking another snapshot called "248", we get this file.
Now, what about having only the upper frequencies added, or maybe only the lower ones ?
We can do so by defining a meta-menu. We just have to replace
outs1 a1+a2+a3+a4+a5+a6+a7+a8+a9
with
;|menu 1Frequencies
;|all
outs1 a1+a2+a3+a4+a5+a6+a7+a8+a9
;|upper
; outs1 a1+a2+a3+a4+a5
;|lower
; outs1 a1+a6+a7+a8+a9
;|endmenu
... and do the same for instrument 2. We get this file.
The ;|... comments are magic. If you go to the "Settings" menu, you will see that there are now two more entries: a submenu "1Frequencies" and a submenu "2Frequencies", both providing the items "all", "upper" and "lower". By selecting those items, you actually comment and uncomment the corresponding sections in the csd.
What´s more: this is also recorded in a snapshot. Let´s select "upper" in both instruments, then take a new snapshot "248up". Here is the resulting csd.
One more step: silenting out part of the score. Let´s replace
; start idur iamp ifq ioff irise idec
i1 0 35 8000 110 0.03 0.07 21
i1 20 20 9600 110 0.04 2 4
i1 28 30 8000 220 0.04 3 6
i1 32.1 23 8000 110 0.03 2.3 4.6
i2 5 20 9600 55 0.02 0.04 12
i2 20 15 8000 220 0.05 1.5 3
i2 32 26 9600 110 0.025 2.6 5.2
i2 36 22 8000 55 0.01 0.04 13
e
with
; start idur iamp ifq ioff irise idec
;|toggles Score
;|i1
i1 0 35 8000 110 0.03 0.07 21
i1 20 20 9600 110 0.04 2 4
i1 28 30 8000 220 0.04 3 6
i1 32.1 23 8000 110 0.03 2.3 4.6
;|i2
i2 5 20 9600 55 0.02 0.04 12
i2 20 15 8000 220 0.05 1.5 3
i2 32 26 9600 110 0.025 2.6 5.2
i2 36 22 8000 55 0.01 0.04 13
;|endtoggles
e
This gives birth to a new submenu "Score" in "Settings", where you can choose weither to include the parts for i1 and i2 in the score.
(the difference between ;|menu and ;|toggles is that ;|menu allows only one among its items to be selected at a given time)
Our eventual csd is now a template where structural choices can be performed in both score and orchestra, and where snapshots make it possible to keep at hand as many combinations of such choices and macro settings as we want. All of this being accessible through the "Settings" menu.
And because everything happens either in comment lines of in XML areas external to the <CsoundSynthesizer> one, the csd is still acceptable as an input file by csound.
I invite you to go through the code in csound-eel.el, since everything is there: the code for meta-menus (a dozen of functions) and snapshots (4 functions only). This is just one example of what is possible with embedded Emacs Lisp...
..another example (a last one): what about being able to explore systematically a set of possible configurations ? Easy. We add this kind of code as an active EEL area:
<ELISP> ;;; [load] - [collapse/unfold] - [save] - [EVAL] - [;EVAL]
(dotimes (i1 3)
(dotimes (i2 3)
(dotimes (i3 3)
(let* ((m1 (+ 2 i1))
(m2 (+ 1 i2 m1))
(m3 (+ 1 i3 m2)))
(cscsd-set-macro-def "m1" m1)
(cscsd-set-macro-def "m2" m2)
(cscsd-set-macro-def "m3" m3)
(write-file (expand-file-name
(format "example%d-%d-%d.csd" m1 m2 m3)
(file-name-directory (buffer-file-name))))
(message "processing m1=%d m2=%d m3=%d ..." m1 m2 m3)
(cscsd-process)))))
</ELISP>
(... note that this example actually does not require csound-eel at all, only embedded-elisp-library)
Clicking [EVAL] will play with the values for m1, m2, m3 and launch the rendering of 27 wave files, while the 27 corresponding csd will be written at the same place where lives the original csd.
(beware that compiling a csd requires that cscsd-process-file is correctly set)