Modular Music Part 2

In the last post I described how I used Supercollider to model Modular Synthesis. In this post I will describe how I communicate with Supercollider and create music.

The main purpose for me is to write full pieces of music. Therefore I want to have a concise DSL language for interacting with Supercollider where I can play and interact with the Modular Synthesis instruments. The language of choice, currently, is Scala. Early in the composition process I want to have a more interactive way where I can try out different ideas. There I use often Midi to initiate playback. Later in the process I want to write a whole piece of music with many channels and often up to 20 minutes long. I will describe these high level ways of working in future posts.

Supercollider have two parts. The server part is where synthesis is performed. To communicate with the server you usually use a protocol called OSC. It stands for Open Sound Control and can be described as a more generic version of MIDI. In Supercollider the transport is either via UDP or TCP. OSC is a generic communication protocol where you have both simple messages and what is called bundles. Bundles have a timestamp which means that OSC, in comparison to MIDI, have a built in sequencer. Supercollider has a number of messages that it responds too that are described in the Server Command Reference. To communicate with Supercollider via OSC I use the Scala library ScalaOSC.

There is code that is able to generate OSC messages to play the modular Instruments. Each Instrument has its own implementation which means that you get type safe code for each Instrument.

SynthDef(\lineControl, {
	arg dur = 1, startValue = 1, endValue = 1, out = 0;
	var lineEnv;
	lineEnv = Line.kr(start: startValue, 
                          end: endValue, 
                          dur: dur, doneAction:2);
	Out.kr(out, lineEnv);
}).add;

class LineControl extends ControlInstrument {
    val instrumentName: String = "lineControl"

    var startValue: Double = _
    var endValue: Double = _

    def control(startValue: Double, endValue: Double): SelfType = {
      this.startValue = startValue
      this.endValue = endValue
      self()
    }

    override def internalBuild(startTime: Double, 
                               duration: Double): Seq[Any] =
      Seq("startValue", startValue, "endValue", endValue)
  }

Above we see how the earlier described lineControl instrument is implemented in the Scala client code. We need to say how we should send the startValue and endValue. The dur and out bus is handed in a generic way.

We saw in the previous post that in Supercollider communication between Instruments are handled via buses. In the Scala code you pass instances of Instruments as arguments instead. Behind the scenes the instruments are assigned buses and OSC messages are generated before the main instrument are generated. The OSC messages for all instruments in the graph is put together as one OSC bundle and sent to Supercollider with a common timestamp.

class SineOsc extends AudioInstrument {
    type SelfType = SineOsc

    def self(): SelfType = this

    val instrumentName: String = "sineOsc"

    var ampBus: ControlInstrument = _
    var freqBus: ControlInstrument = _
}

Buses in Supercollider are either control buses or audio buses. There are external audio buses that are correspond to the actual audio channels that Supercollider is playing sound on. Usually you have two. One left and one right. Supercollider also have a number of internal audio buses that are used to route audio internally. Control buses are used to route control signals. There are a fixed number of buses that are allocated when the server starts.

There is code in the Scala client that can allocate buses. You specify start and end-time and the allocator knows which buses are free during that time period and allocates them for you. That way we can reuse buses once they are not used in any instruments.

Another important thing to get right is how the instruments are organised. When you play a synth in Supercollider it is always part of what is called a group. You also specify how the synth should be added to the group. In our case it’s important that the control instruments are earlier in the group then the audio instruments because this is the order in which they will be generated by Supercollider.

The Scala client code results in a fluent and type safe API that makes it easy to write tight code to execute complex modular synths.

sineOsc(ampBus = staticControl(1), freqBus = staticControl(440))
    .addAction(TAIL_ACTION)

panning(inBus = audio, panBus = lineControl(-1, 1))
      .addAction(TAIL_ACTION)
      .withNrOfChannels(2)

In the above example we first create a sine oscillator where the amplitude is 1 and the frequency is 440 hertz. The second example is a panning where you supply the audio instrument and the panning is a line between -1 and 1. Both of these have TAIL_ACTION which means that they will be put last in the group. The panning also specify that it needs two channels (stereo).

The source code for the Scala client on GitHub is organised in two libraries. soundming-tools and soundming-modular.

Here is an example of a finished piece. It is called Concrete Music 9. It uses another abstraction called a SynthPlayer that makes it even easier to write fluent and tight code.

Modular Music Part 1

I use Supercollider to make music. Here I will briefly describe how Supercollider works and are used to generate and work with audio.

It has two parts. A client, with its own programming language. And a server that receives command too, for instance, play a sound on an instrument. One way to work is too create instruments in the server that combines a number of so called UGens. You can then send commands to the server that will play these instruments on the server.

One common problem that arise when working with instruments is that It is hard to make these instruments generic enough so that they are re-usable. If you for instance play a sine tone you sometimes want to make one note and some other times a glissando. You might also want to have different dynamic curves at different times. You quickly end up in a combination hell and need a lot of different instrument where there is very little difference.

Modular synthesis and sound systems has been around for many years. From the early Moog synths to the euro rack system. Also in pure software we have everything from Max to the open source PureData. The main idea is that you control modules by sending one or several signals to them. Each module transform the incoming signals and produce a new outgoing signal. You use that signal to either control other modules or output it as the final sound. It is an elegant and versatile solution.

One way to communicate between instruments in Supercollider is via something called buses. Buses are a way to stream data. Buses come in either control rate buses or audio rate buses. Control rate buses have a lower rate than audio buses and are used to transport control information such as volume changes. Most audio buses are internal, meaning that no sound will come out if you send data to them, they are used for internal routing. You specify how many external audio buses you should have, two is typical to get stereo with left and right.

In my modular system I use buses to communicate between different instruments. I have both instruments that produce control signals such as a static value or going from one value to another in a line. And instruments that produce audio rate signals such as sine signals and filters. Below is an example of a control signal instrument that produces a signal going from one value to another.

SynthDef(\lineControl, {
	arg dur = 1, startValue = 1, endValue = 1, out = 0;
	var lineEnv;
	lineEnv = Line.kr(start: startValue, 
                          end: endValue, 
                          dur: dur, doneAction:2);
	Out.kr(out, lineEnv);
}).add;

The above instruments takes four arguments. The dur means how long the instrument should sound, out means which output bus the instrument should send the result to and start/end-value is the start and end value of the produced values. The Out.kr send the values on the specified bus. By using kr it sends it at control rate.

You can later use this instrument to control other instruments. Below is an example of a sine instrument that reads both its frequency and amplitude from a control bus.

SynthDef(\sineOsc, {
	arg dur = 1, freqBus = 0, ampBus = 0, out = 0;
	var sig, amp, freq;
	Line.kr(dur:dur, doneAction:2);
	amp = In.kr(ampBus, 1);
	freq = In.kr(freqBus, 1);
	sig = SinOsc.ar(freq, mul:amp);
	Out.ar(out, sig);
}).add;

This instrument takes it frequency from freqBus and the amplitude from the ampBus. The In.kr reads from a bus (at control rate). As before it sends the result to the output bus with Out.ar. The difference is that it sends it at audio rate (with ar).

I have a lot of Supercollider instruments that I use to make music. They reflect my needs as a composer and is not a “complete” set of instruments.

There are a number of control instruments. Both simple, such as the above lineControl, and instruments that combines several buses such as multiply, sum and mix.

Many audio instruments are also simple such as sine, triangle and noise. There are also modifying and more complex instruments such as filters, ring modulation and FM modulation.

For working with samples there are sample playback instruments. One special control instrument is an audio amplitude control instrument that takes an audio signal and outputs a control signal from amplitude. This is useful if you for instance want to do a sub base.

All instruments definitions can be found on GitHub.

You can use the Supercollider client to combine these instruments and play them but it can be a bit of a hassle to do. Especially to manage the buses that you use. I play these Supercollider instruments from a different environment that I will describe in a future post.

The Classical mixtape #007

Notes about update #007 of The Classical mixtape.

Talking about Jean-Philippe Rameau. The true classical recording of his piano music is probably the one that Marcelle Meyer did in 1953 and 1946. She worked with Lex Six and they had her as their favourite pianist. She also made a number of recordings and the one with music by Jean-Philippe Rameau is legendary. I usually find it difficult to appreciate really old albums but this is really good.

You don’t hear the the symphonies of Villa-Lobos that often. Naxos is currently making a series of albums with them. The eleventh, for instance, is really good.

Lastly I must mention Valery Gargiev’s recording of the sixth symphony by Tchaikovsky. Such power.

the-classical-mixtape
Click to open in Spotify

 

 

 

The Early mixtape #001

Notes about update #001 of The Early mixtape.

I really like the keyboard music of Jean-Philippe Rameau. For me he is one of the most important composers for the keyboard during the baroque era and on par with both  François Couperin and Domenico Scarlatti. He wrote three collections of keyboard music where Nouvelles Suites de Pièces de Clavecin is the last one.

Another very good collection of chamber music by Rameau is the Pièces de clavecin en concerts for harpsichord, violin and viol.

The Early mixtape
Click to open in Spotify

 

The Modern mixtape #005

Notes on update #005 of The Modern mixtape.

Regarding Le Déluge d’après Poussin by Hugues Dufourt. It’s like a spectral variant of Morton Feldman. Brian Eno compares ambient music with a river that is floating by. It is always evolving and moving but from your point of view, as a observer, it is standing still. I find these qualities in both Morton Feldman and John Cage music. Le Déluge d’après Poussin is constantly changing, with new harmonies and timbres but standing still at the same time. Very beautiful.

The pianist Sabine Liebner has a atmospheric and dreamy way of playing the piano. She have done very nice recordings of both of Feldman’s late piano pieces and Cage number pieces for solo piano. Here is Tilbury by Christian Wolff.

In the second movement of Voyage into the Golden Screen Per Nørgård uses his infinity series melody for the first time. It is a fractal way that constructs a never ending infinite melody. In the second symphony it is explored even more with a tone row that consists of over 4000 notes. The result is a strange and beautiful piece of music.

Neptuni Ã…krar is an orchestra piece by the Swedish composer Henrik Strindberg. The basic idea is arpeggios of natural harmonics played on string instruments. You can read a detailed description about the structure and techniques used in the piece in Swedish here. It won the Christ Johnson prize in 2007.

the-modern-mixtape
Click to open in Spotify

The Classical mixtape #006

Notes on update #006 of The Classical mixtape.

Valses nobles et sentimentales is a piano/orchestra piece by Maurice Ravel. He first published the piano version 1911 and one year later the version for orchestra. It is dedicated to Schubert and his two collections with waltzes Valses nobles and Valses sentimentales. 

Karol Szymanowski is one of the most notable Polish composers from the 20th century. Impressionistic and modern. A favourite.

Erich Wolfgang Korngold was both a very talented classical composer and a famous and influential film music composer. The style is late romantic with a modern touch and a lyric tone.

the-classical-mixtape
Click to open in Spotify

 

 

The Early mixtape

The Early mixtape is a playlist with music from the Medieval, Renaissance and Baroque era.

Some highlights.

Domenico Scarlatti is one of my favourite composers. A very good interpreter of his sonatas is Pierre Hantaï who have recorded four albums with Scarlatti’s sonatas.

Membra Jesu Nostri is seven cantatas, each one dedicated to one of Jesu crucified limbs, by Dieterich Buxtehude.

Graindelavoix astonishing recording of Guillaume de Machaut Messe de Nostre Dame.

Claudio Monteverdi stands between the Renaissance and Baroque Era. The music is both bold beautiful.

Click to open in Spotify