Gibber uses javascript.
// x = kick, o = snare, * = closed hihat, - = open hihat, . = rest
d = Drums( 'xoxo' )
Drums
is a function that we call with a string pattern, and that returns a drum machine object. That object gets assigned to the variable d
so we have a name we can keep track of it with.
IMPORTANT Gibber treats single letter variables as a special case. If you already have something assigned to a single letter variable, then it will be replaced. Otherwise it will create a new object, even if it's to the same variable name.
Try running the following one at a time. You'll have both drums playing at the same time.
d1 = Drums('x.o.')
d1 = Drums('****')
With this you'll only have one drum loop playing.
d = Drums('x.o.')
d = Drums('****')
Drum patterns don't have to be limited to multiples of four beats.
beat = EDrums('x.o.x')
hats = EDrums('**.*.*.')
These two patterns both loop in the same time, but have different numbers of events in them. There's plenty of interesting things that can be done with this.
d = EDrums('x.o.')
d.amp = 0.4
d.pan = -0.5
d.kick.decay = 0.3
d.snare.decay = 40000
d.snare.snappy = 0.2
The drum object has controls that can be changed itself, but the individual sounds can also be changed themselves. The .
here is essentially a way of getting things that are attached to an object. Those can be more controls, but can also be objects themselves.
Changing a control here is just like changing it on a normal drum machine, only here it's done with code.
d = Drums('x.o.')
d.pitch = Mouse.x
Controls can be connected to movements of the mouse. x
is the left to right value, whilst y
is the top to bottom value. This will automatically be scaled to the right range for the control.
d = EDrums('xxxx')
Clock.bpm = 100
The global BPM can be changed using the Clock
object. This is a global object, which means that there is only a single version of it, and changing it affects everything.
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s.note(70)
So there's two big new things that this introduces. The first is the dictionary of settings that are given to the Synth2
function. This is the same as setting each of the options separately.
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s = Synth2()
s.amp = 1
s.attack = 0.1
s.release = 0.2
s.resonance = 2
s.cutoff = 0.1
The second thing is the note
function that's attached to the synth. Calling this triggers it to actually play something. This is similar to the play
function in LiveCodeLab but this is only working on the synth attached to variable s
. These are often called methods
The number that note
is called with is the frequency of the sound we want it to play. It's also possible (and probably easier) to get the synth to play specific notes.
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s.note('c1')
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s.note.seq(['c1', 'e1', 'f1', 'a1'], 1/4)
This might seem kind of weird, because now the seq
method is being called on the note
method. At this point, don't worry about it.
The square brackets [
and ]
create a list which we use as the first argument to the seq
method. It's important to realise that this is different from calling seq
with each of these notes as separate arguments.
s.note.seq(['c1', 'e1', 'f1', 'a1'], 1/4)
// is not the same as
s.note.seq('c1', 'e1', 'f1', 'a1', 1/4)
The synth will now play the notes in the list, one after the other, triggering them every quarter of a beat.
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s.note.seq(['c1', 'e1', 'f1', 'a1'], [1/4, 1/2, 1/8])
The note length can also be sequenced, and the sequences don't have to be the same length.
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s.note.seq(['c1', 'e1', 'f1', 'a1'].random(), [1/4, 1/2, 1/8])
Calling the random
method on the list of notes means that the sequence will randomly pick which of the notes to play. This can be used on the length list as well.
s = Synth2({amp: 1, attack: 0.1, release: 0.2, resonance: 2, cutoff: 0.1})
s.note.seq(['c1', 'e1', 'f1', 'a1'], [1/4, 1/2, 1/8])
c = Chorus({rate: 10, feedback: 0.3, amount: 100})
s.fx.add(c)
s.fx.remove(c)
Effects are created in the same way as the synth and drum machine, but you add them to the output of those instruments. The add
and remove
methods on the fx
control are how you do this.
c.amount.seq([30, 40, 150, 20], 1)
It's worth remembering that in Gibber you can sequence pretty much everything, including controls on instruments and effects.
f = FM({ maxVoices:3 })
f.chord( 'c3M' )
The FM
synth here is a frequency modulating synth with four voices. This means that it can play up to four notes at the same time.
The chord
method gives it a chord to play, in this case a Major chord starting at c3.
f = FM({ maxVoices:4 })
f.chord([0, 2, 5])
Chords can also be specified directly as note intervals based on the global scale and root note.
f = FM({ maxVoices:4 })
f.chord.seq([[0, 2, 5], [0, 3, 5]], 1/2)
Gibber.scale.root = 'c2'
Gibber.scale.root = 'c3'
Gibber.scale.root = 'c4'
The Gibber
object is another global object.