Live code session using csound-live-code and https://live.csound.com.
Initial code happens for about 2m40s, then sound begins.
For those interested in the code, the session uses:
1. start UDO for working with the different always-on instruments
2. vco2 square wave for enveloping (has a nicer quality to it than
using lfo with type 3, IMO)
3. portk for frequency glide
4. chnset for immediate setting of a channel value as part of performance
5. chnset within an always-on instrument (“Mod”) together with k-rate
randh to show how to approach using continuous values with channels
This past weekend I was happy to participate in the Algosix celebration of Algorave with a live code performance. (The first few minutes of the test sound were me trying to check sound on the stream and failing to realize it was working…).
The video shows a little bit of vim, csound, and csound-live-code. In particular, it demonstrates the hex beats work in the live code project, as well as using phasors and non-interpolating oscillator functions for pitch values. Drum sounds are from Iain McCurdy’s TR808 code and synth sounds were ones I have been working on in the live code project.
The event was a lot of fun with lots of different approaches, aesthetics, tools, etc. Lots of appreciation for the community and organizers of the event! (And many thanks for the opportunity to perform!)
Short version is that Pink has a number of new filters and effects, updates to minimize object allocations (e.g., Distruptor-style message ring buffers), and utility code for building streaming disk-based caches for pre-rendered (“frozen”) parts. Score has new functions geared towards live coding (e.g., euclidean and hexadecimal beats), a new mini-language for notating musical lines, and number of other updates.
Codox-generated documentation/site is now published at:
I have long avoided FM (Frequency Modulation) synthesis in my own musical practice as I never felt connected with the results I was able to get myself. However, I recently had the great pleasure to attend a talk about the 50th anniversary of FM synthesis, given by its creator, John Chowning, and I was very inspired to explore FM once again. In so doing, I came across the Yamaha reface DX synthesizer and became fascinated with reproducing its feedback system to morph an operator’s output from a Sine to either Saw or Square waveform.
Now, I do not own a reface DX, so most of my research into it was through looking at manuals and watching video demonstrations on YouTube to try to get an idea of how it might be done. I knew from going through literature on FM and PM (Phase Modulation) that using PM with feedback could get an operator’s signal to move from a Sine to Sawtooth wave, depending upon the amount of feedback. I was quickly able to setup a PM instrument in Csound and test this out and it sounded much like what I had heard for the reface DX.
In the code above, one can see that the acar output from tablei is also used as input into the opcode. The code above runs in a single-sample context (in Csound parlance, with ksmps=1).
Now, the part I could not find anywhere in literature or discussion online was how to use operator feedback to morph from Sine to Square. (This is done by using 0 to -127 range for feedback on the reface DX.) After a couple days of research and exploration, I stumbled upon a calculation that sounded to my ears very much like what I had heard on the reface DX videos.
This instrument is virtually the same as the first instrument with the exception of one additional calculation: the multiplication of the acar feedback by itself. (This is seen in the acar*acar calculation.) Adding this one additional multiplication made the signal move from Sine to Square.
I posted this to the Csound User list and Iain McCurdy gave great feedback that the waveform could be morphed between Saw and Square by interpolating between acar and 1. This made a lot of sense as when one of the acar‘s becomes 1, it reduces back down to the normal feedback addition to produce a Saw sound. After some further emails, I did some experiments to use a cosine-based mapping for the interpolation that resulted in a nice transition.
;; feedback PM - feedback moves from square to saw
;; Based on Iain McCurdy's comments on Csound User List
ifreq = p4
iamp = p5
kfb = 0.25
;;kfb = linseg(0, p3 * .5, 0.5, p3 * .5, 0)
kwaveshape = linseg(0, p3 * .5, 1, p3 * .5, 0) ;; range 0-1 for saw->square
kwaveshape *= kwaveshape ;; adjust curve
kwaveshape = $M_PI * (kwaveshape + 1) ;; adjust from PI->2PI
kwaveshape = (cos(kwaveshape) * 0.5) + 0.5 ;; adjust to 0-1
aphs = phasor(ifreq)
; init for feedback
acar init 0
acar = tablei(aphs+(ntrpol(acar, a(1), kwaveshape)*acar*kfb), 1, 1, 0, 1)
acar *= linen:a(1, 0.1, p3, 0.1) * iamp
I do not know if these calculations are what are used in the reface DX, but regardless, the sine->square sounded good to my ear and I felt it was usable for the kind of sound work I was interested in doing. For now, I have posted the Csound CSD project file here. The audio example at the top of this post is an MP3 version of the output rendered from this project.
Hexadecimal (base 16) has been used in various forms of computer music for a very long time, generally as a condensed way to notate values within a power-of-two range. For example, rather than write out “15” as a decimal value (base 10), one can use “F”, and rather than write out “255”, one can use “FF”. The notation of hexadecimal numbers, in general, take up less horizontal space on the screen than its base 10 counterpart.
The differences in screen real estate is even more pronounced when comparing the binary value (base 2) to the decimal and hex values. Let’s compare some values here:
A chart showing the binary, decimal, and hex values for number 0-255 are available here.
Now, one of the interesting challenges in live coding pattern-oriented music for me has been trying to have a very condensed notation for expressing beats (onsets). One way I’ve seen used is to notate values in a binary form within a string, such as “1000100010101000” which would mean “play notes where there are 1’s, but don’t play notes where there are 0’s”. In this case, on beat 1, 5, 9, 11, and 13.
Binary values in a string, on the one hand, quite clearly notates when an instrument should play. On the other hand, I’ve found it visually takes up quite some space and can be a bit slow to parse mentally.
One thing I’ve found rather useful is to notate onset patterns using hexadecimal strings. I first explored this in my Clojure systems Pink and Score, but recently translated the function I was using to Csound code. The Csound code turned out to be quite simple:
opcode hexbeat, i, Si
Spat, ibeat xin
;; 4 bits/beats per hex value
ipatlen = strlen(Spat) * 4
;; get beat within pattern length
ibeat = ibeat % ipatlen
;; figure which hex value to use from string
ipatidx = int(ibeat / 4)
;; figure out which bit from hex to use
ibitidx = ibeat % 4
;; convert individual hex from string to decimal/binary
ibeatPat = strtol(strcat("0x", strsub(Spat, ipatidx, ipatidx + 1)))
;; bit shift/mask to check onset from hex's bits
xout (ibeatPat >> (3 - ibitidx)) & 1
The above is saying: “within the hexadecimal beat string of f0d0d0f0, and given the current beat value between 0 and 32, check if the onset is a 1 and, if so, perform Synth 1”.
The code above may be a little tricky to grok at first glance. I’ve started a Github repository for this code and made an online web app for live coding with Csound and this library. The live web site is available at:
In working with the hex beat patterns, I found it took a little practice but the meaning of various hex values started to become intuitive over time. Hexadecimal works really well, in my opinion, for notating pattern onsets as each hex value maps to 4 bits, which works perfectly for 4 16th-notes. With this, 4 hex values can be used to notate a single measure of 16 16th-notes, 8 hex for 2 measures, and so on.
Reflections is a three-movement study that arose out of exploration into randomly generated symmetric odd/even signal wave tables for synthesis. The piece uses a number of different “reflected” table generation methods with each movement developed intuitively according to the sound qualities of the table methods. Each piece has some indeterminant qualities in form as well as sound, thus each rendering of the piece is its own unique performance.
In Max Mathews’ “The Technology of Computer Music,” (the manual to Music V, for those who haven’t encountered it before), are two wonderful quotes:
“Scores for the instruments thus far discussed contain many affronts to a lazy composer, and all composers should be as lazy as possible when writing scores.” – pg. 62
“Furthermore, the note duration is already written in P4; it is an indignity to have to write P6 (= .02555/duration).” – pg. 63
I think these quotes describe that even in 1969, a schism was identified between what one writes that is relevant to them and their work and the underlying representation that is necessary for the operation of the musical system. It’s been an interesting thing to think about what it signifies and how it presents itself even today.
The above quotes come from the section describing C0NVT, the routine one defined to transform what the composer wrote into the instructions that would work within the MUSIC V base system. While C0NVT would later see a descendant in Csound’s SCOT system, I think the general idea would be superceded by custom tools and/or language changes that allowed users to customize things in other ways. Thinking more broadly outside of just the world of MUSIC N systems, today’s computer music systems generally involve many layers between what the user uses (i.e., the GUI interface of a DAW, a custom score language, programming in a general purpose language) and the representation used for performance (text score events, MIDI, OSC).
These layers of notation–what the composer writes, the various processes of transformation, and arriving at what is used for performance–need not be seen only to the digital music world. For example, the metric modulation notation of Carter might represent well what the performer needs for performing material that changes tempi in synchrony with other performers in other tempi, but it obscures the musical character of the material, which is often much simpler rhythmically when viewed within its native tempo. This might be seen then as score that has already been processed by C0NVT, and we are left to analyze and make out the pre-processed material. (I do wonder then if Carter might have seen the modulations as a kind of indignity in having to write…)
Returning to the digital world, it is somewhat of a painful thing to see composers who must jump through many hoops to use the technologies available to realize their goals for which the technologies were not designed. Here I am thinking of the microtonal composer using MIDI, who might resort to using tuning tables and pitch bends to arrive at their desired tuning. When microtonal composers use tools that allows them to write in one notation and transforms the material to one suitable for the target system automatically, it is quite a delight to see the notation and to hear the results and to clearly see the mapping between the two. But for those who must work within tunings with many divisions of the octave, to see the coercion of a MIDI piano roll to fulfill their notation needs is quite painful.
On a personal note, these musings touch on recent issues in my musical practice of finding the right balance between how I would like to write and notate ideas and what I need to do to realize them in sound. Sometimes text/code works so well and is so precise and clear, yet other times visual interfaces yield more overall information and provide intuitive handling and development of material. Both have their appeals and drawbacks, and I suppose Blue represents a kind of hybrid system that allows one to not only explore either end of the spectrum but also the area in-between. I have thought of this off an on for a long time, but not so much recently. Perhaps some quiet time to meditate upon it all and experiment with different designs is in order.