csound-expression-4.9.1: library to make electronic music

Safe HaskellNone




We can convert notes to sound signals with instruments. An instrument is a function:

(Arg a, Sigs b) => a -> SE b

It takes a tuple of primitive Csound values (number, string or array) and converts it to the tuple of signals and it makes some side effects along the way so the output is wrapped in the SE-monad.

There are only three ways of making a sound with an instrument:

  • Suplpy an instrument with notes (Mix-section).
  • Trigger an instrument with event stream (Evt-section).
  • By using midi-instruments (see Csound.Control.Midi).

Sometimes we don't want to produce any sound. Our instrument is just a procedure that makes something useful without being noisy about it. It's type is:

(Arg a) => a -> SE ()

To invoke the procedures there are functions with trailing underscore. For example we have the function trig to convert event stream to sound:

trig :: (Arg a, Sigs b) => (a -> SE b) -> Evts (D, D, a) -> b 

and we have a trig with underscore to convert the event stream to the sequence of the procedure invkations:

trig_ :: (Arg a) => (a -> SE ()) -> Evts (D, D, a) -> SE () 

To invoke instruments from another instrumetnts we use artificial closures made with functions with trailing xxxBy. For example:

trigBy :: (Arg a, Arg c, Sigs b) => (a -> SE b) -> (c -> Evts (D, D, a)) -> (c -> b)

Notice that the event stream depends on the argument of the type c. Here goes all the parameters that we want to pass from the outer instrument. Unfortunately we can not just create the closure, because our values are not the real values. It's a text of the programm (a tiny snippet of it) to be executed. For a time being I don't know how to make it better. So we need to pass the values explicitly.

For example, if we want to make an arpeggiator:

pureTone :: D -> SE Sig
pureTone cps = return $ mul env $ osc $ sig cps
   where env = linseg [0, 0.01, 1, 0.25, 0]

majArpeggio :: D -> SE Sig
majArpeggio = return . schedBy pureTone evts
    where evts cps = withDur 0.5 $ fmap (* cps) $ cycleE [1, 5/3, 3/2, 2] $ metroE 5

main = dac $ mul 0.5 $ midi $ onMsg majArpeggio

We should use schedBy to pass the frequency as a parameter to the event stream.



We can invoke instrument with specified notes. Eqch note happens at some time and lasts for some time. It contains the argument for the instrument.

We can invoke the instrument on the sequence of notes (sco), process the sequence of notes with an effect (eff) and convert everything in the plain sound signals (to send it to speakers or write to file or use it in some another instrument).

The sequence of notes is represented with type class CsdSco. Wich has a very simple methods. So you can use your own favorite library to describe the list of notes. If your type supports the scaling in the time domain (stretching the timeline) you can do it in the Mix-version (after the invokation of the instrument). All notes are rescaled all the way down the Score-structure.

type Sco a = Track D a

data Mix a :: * -> *

Special type that represents a scores of sound signals. If an instrument is triggered with the scores the result is wrapped in the value of this type.

sco :: (Arg a, Sigs b) => (a -> SE b) -> Sco a -> Sco (Mix b)

Plays a bunch of notes with the given instrument.

res = sco instrument scores 

mix :: Sigs a => Sco (Mix a) -> a

Renders a scores to the sound signals. we can use it inside the other instruments.

eff :: (Sigs a, Sigs b) => (a -> SE b) -> Sco (Mix a) -> Sco (Mix b)

Applies an effect to the sound. Effect is applied to the sound on the give track.

res = eff effect sco 
  • effect - a function that takes a tuple of signals and produces a tuple of signals.
  • sco - something that is constructed with sco or eff.

With the function eff you can apply a reverb or adjust the level of the signal. It functions like a mixing board but unlike mixing board it produces the value that you can arrange with functions from your favorite Score-generation library. You can delay it or mix with some other track and apply some another effect on top of it!

mixLoop :: Sigs a => Sco (Mix a) -> a Source

Mixes the scores and plays them in the loop.

sco_ :: Arg a => (a -> SE ()) -> Sco a -> Sco (Mix Unit)

Invokes a procedure for the given bunch of events.

mix_ :: Sco (Mix Unit) -> SE ()

Converts a bunch of procedures scheduled with scores to a single procedure.

mixLoop_ :: Sco (Mix Unit) -> SE () Source

Mixes the procedures and plays them in the loop.

mixBy :: (Arg a, Sigs b) => (a -> Sco (Mix b)) -> a -> b

Imitates a closure for a bunch of notes to be played within another instrument.

infiniteDur :: Num a => a


sched :: (Arg a, Sigs b) => (a -> SE b) -> Evt (Sco a) -> b

retrig :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> b Source

schedHarp :: (Arg a, Sigs b) => D -> (a -> SE b) -> Evt [a] -> b

An instrument is triggered with event stream and delay time is set to zero (event fires immediately) and duration is set to inifinite time. The note is held while the instrument is producing something. If the instrument is silent for some seconds (specified in the first argument) then it's turned off.

schedUntil :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> Evt c -> b Source

Invokes an instrument with first event stream and holds the note until the second event stream is active.

schedToggle :: Sigs b => SE b -> Evt D -> b Source

Invokes an instrument with toggle event stream (1 stands for on and 0 stands for off).

sched_ :: Arg a => (a -> SE ()) -> Evt (Sco a) -> SE ()

Triggers a procedure on the event stream.

schedUntil_ :: Arg a => (a -> SE ()) -> Evt a -> Evt c -> SE () Source

Invokes an instrument with first event stream and holds the note until the second event stream is active.

schedBy :: (Arg a, Sigs b, Arg c) => (a -> SE b) -> (c -> Evt (Sco a)) -> c -> b

A closure to trigger an instrument inside the body of another instrument.

schedHarpBy :: (Arg a, Sigs b, Arg c) => D -> (a -> SE b) -> (c -> Evt [a]) -> c -> b

A closure to trigger an instrument inside the body of another instrument.

withDur :: D -> Evt a -> Evt (Sco a) Source

Sets the same duration for all events. It's useful with the functions sched, schedBy, sched_.


alwaysOn :: SE () -> SE () Source

Executes some procedure for the whole lifespan of the program,

playWhen :: forall a b. Sigs a => BoolSig -> (b -> SE a) -> b -> SE a Source

Transforms an instrument from always on to conditional one. The routput instrument plays only when condition is true otherwise it produces silence.


Converters to make it easier a construction of the instruments.

class Sigs (SigOuts a) => Outs a where Source

Associated Types

type SigOuts a :: * Source


toOuts :: a -> SE (SigOuts a) Source

onArg :: Outs b => (a -> b) -> a -> SE (SigOuts b) Source

class AmpInstr a where Source

Constructs a drum-like instrument. Drum like instrument has a single argument that signifies an amplitude.

Associated Types

type AmpInstrOut a :: * Source


onAmp :: a -> D -> SE (AmpInstrOut a) Source

class CpsInstr a where Source

Constructs a simple instrument that takes in a tuple of two arguments. They are amplitude and the frequency (in Hz or cycles per second).

Associated Types

type CpsInstrOut a :: * Source


onCps :: a -> (D, D) -> SE (CpsInstrOut a) Source