Skip to content

Instantly share code, notes, and snippets.

@rumblesan
Last active December 9, 2020 16:51
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rumblesan/5a107bc7027a9623acf4fd53fff21726 to your computer and use it in GitHub Desktop.
Save rumblesan/5a107bc7027a9623acf4fd53fff21726 to your computer and use it in GitHub Desktop.
Take away doc for the HipHop and Code workshop

Hip Hop and Code Handout

Gibber

http://gibber.cc/

Docs

Gibber uses javascript.

Basic Drums

// 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('****')

Different Length Patterns

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.

Changing Drum Sounds

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.

Mouse Controls

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.

Tempo

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.

Bass

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')

Sequencing

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.

Effects

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.

Chords

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.

Useful Links

Live Coding Information

Courses for Learning to Program

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment