-
Notifications
You must be signed in to change notification settings - Fork 7
Language spec
automata edited this page Sep 22, 2012
·
6 revisions
Principles:
- The language should be simple
- Use mnemonics and syntax sugar (with care): few chars, big results
Rules:
- Music is made by voices (instruments)
- Voices have name, timbre and parameters ranging along the time
- Names are something like a, b, c
- Timbre are signals made by chains of audio generators and filters
- Parameters are musical notes, amplitudes, oscillators frequency, delay time, ...
- Parameters changes their values at some times and have some durations
Audio sources:
- osc(freq), saw(freq), square(freq), audio(filename)
Audio filters:
- gain(), reverb(), delay(), echo(), low(freq), high(freq), band(f1, f2)
Code example:
a.sig = audio('foo.wav') # foo.sig defines a signal
a.amp = [1 1 _ 1 | 1 _ _ _ ] # foo.param = [] defines where and how parameter values changes
a.amp = {.25 .25 .25 .25 } # foo.param = {} defines how long parameter changes will apply
# every voice has amp and notes as default parameters
c.signal = osc => gain => reverb
c.notes = [c4 c4# d4 e2 | c4 c4# _ d2 ]
c.notes = {1/4 1/2}
# chords
c.notes = [C2m7 C2 D2 E2]
# complex dsp graphs (+ to add signals, => to chain)
b.sig = (osc1() + osc2(20)) => delay1(100) => gain1, gain1 => delay1
# complex parameter automation
b.osc1.freq = [100 200 100 440]
b.osc1.freq = {1/2 1/4}
# or inline
b.osc1.freq = [100 200 100 440] {1/2 1/4}
# list operations
c.notes reverse
c.notes shake
c.notes circular
c.notes * 2
# event schedulling with @
c.notes = [c4# c4 d4 e4] reverse @ now
c.notes = [c4# c4 d4 e4] reverse @ now + 2
c.notes = [c4# c4 d4 e4] @ now ~ forever # default
Three voices:
a.sig = audio('cello.wav')
b.sig = audio('piano.wav')
c.sig = audio('string.wav')
a.notes = [c0 d0 e0 d0] {1/4}
b.notes = [C2m7 C2m E2m D2m] {1/4}
c.notes = [c0 d0] {1/16}
Sampling:
a.sig = audio('dub.wav') => delay
a.amp = [1 .5 .8 .7] {1/4}
a.dir = [> < > >] {1/4}
a.delay = [100 200 300 200] {1/4}
Granular synthesis:
a.sig = audio('noise.wav')
a.amp = [1 .5 .8] {.02}
a.dir = [<] {.02}
Additive synthesis:
a.sig = osc1(440) + osc2(220) + osc3(110)
Substrative synthesis:
a.sig = noise => adsr(.8, .6, .6, .0)
FM synthesis:
a.sig = osc1 => osc2.freq
# dsp chain with mnemonics
a = wav("foo") => lp => rvb => phz => out
# values x durations
a.lp = [100, 200, 300]
a.lp.dur = [1/2, 1/4]
# at operator
a.lp = [100, 200, 300] @ [1/2, 1/4]
# reverse
a.lp = [100, 200, 300] r # => [300, 200, 100]
# two-first circular
a.lp = [100, 200, 300] c2 # => [200, 100, 300]
# shift left
a.lp = [100, 200, 300] < # => [200, 300, 100]