Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save KC-Liu/11084422 to your computer and use it in GitHub Desktop.
Save KC-Liu/11084422 to your computer and use it in GitHub Desktop.
###
# DO YOU HEAR THE PEOPLE SING? (Uplifting Mix)
# version 1.2
#
# Converted from CoffeeScript
# Source: https://gist.github.com/11080149
# Usage: coffee -bcp file.coffee
#
# Original from Les Miserables
# (http://www.youtube.com/watch?v=QngGvHTOKh4)
# Remixed and coded by Thai Pangsakulyanont
# (https://github.com/dtinth)
###
###
# Major constants
###
BPM = 142
###
# The music itself...
###
music = ->
Instrument =
kick: do ->
click = pipeline(Note.drop(12, 140)).to(Osc.sin).gain(0.4)
click = pipeline(Note.drop(5, 20)).to(Osc.sin).gain(0.3)
sub = pipeline(Note.drop(12, 12)).to(Osc.sin).gain(0.6)
mix(click, sub)
snare: do ->
combine(
combine(Osc.random, Value.approach(1, 0, 3), Filter.gain),
Value.approach(0.4, 0.001, 10),
Filter.Lowpass()
)
hat: do ->
combine(Osc.random, Value.approach(1, 0, 24), Filter.gain)
phat: mix(
pipeline((t) -> t * 1.006).to(Osc.sawtooth).gain(0.3)
pipeline((t) -> t * 1.003).to(Osc.sawtooth).gain(0.3)
pipeline((t) -> t * 1).to(Osc.sawtooth).gain(0.4)
pipeline((t) -> t / 1.003).to(Osc.sawtooth).gain(0.3)
pipeline((t) -> t / 1.006).to(Osc.sawtooth).gain(0.3)
)
Instrument.supersaw = mix(
pipeline(Instrument.phat).gain(0.6)
pipeline((t) -> t / 2).to(Instrument.phat).gain(0.4)
)
line = (text, transpose, transform) ->
notes = (MidiNote.lookup(c) + transpose for c in text.split(' '))
(MidiNote.toFrequency(c) for c in transform(notes))
convert = (array, transpose, transform) ->
result = (line(c, transpose, transform) for c in array)
.reduce(((a, b) -> a.concat(b)), [])
return result
Notes =
melody: Note.step(convert [
'sol Re RE Sol Sol'
'sol Re MI MI RE'
'do sol DO DO RE'
'do sol MI MI FA'
'mi ti SOL SOL SOL'
'mi ti MI RE DO'
'fa Do Ti Ti La'
'fa Do Ti Ti DO'
'Do sol Sol Sol Sol'
'ti sol La Sol Fa'
'mi la Mi Mi Sol'
'mi la DO DO MI'
're la RE RE DI'
're la RE RE La'
're sol DO DO Ti'
're sol Ti Ti DO'
'sol Re RE Sol Sol'
'sol Re MI MI RE'
'do sol DO DO RE'
'do sol MI MI FA'
'mi ti SOL SOL SOL'
'mi ti MI RE DO'
'fa Do Ti Ti La'
'fa Do Ti Ti DO'
'Do sol Sol Sol Sol'
'ti sol La Sol Fa'
'mi la Mi Mi Sol'
'mi la DO DO MI'
're la RE DI RE'
'sol Re FA FA Ti'
'do sol DO DO DO'
'do sol DO DO DO'
'do sol DO DO DO'
'ti mi Mi Mi Mi'
'la mi La La Si'
'la mi La La Ti'
'la mi DO DO Ti'
'la mi La La DO'
'ti mi Ti Ti La'
'ti mi Sol Sol La'
'ti mi Ti Ti Ti'
'ti mi Ti Ti DO'
're la RE RE DO'
're la Ti Ti DO'
're la RE RE DO'
're la Ti Ti RE'
'la mi DO DO Ti'
'la mi La La Ti'
'la mi DO DO DO'
'sol mi DO DO La'
'fa Do DO Ti La'
'fa Do DO Ti La'
'fi Do DO Ti La'
'fi Do DO Ti DO'
'sol Re RE RE RE'
'sol Re RE RE RE'
], 48 + 1, ([a, b, c, d, e]) -> [c, a, b, d, a, b, e, a])
bass: Note.step(convert [
'sol', 'sol',
'Do', 'Do', 'Mi', 'Mi', 'Fa', 'Fa', 'Do', 'ti',
'la', 'la', 'Re', 'Re', 'sol', 'sol', 'sol', 'sol',
'Do', 'Do', 'Mi', 'Mi', 'Fa', 'Fa', 'Do', 'ti',
'la', 'la', 'Re', 'sol', 'Do', 'Do', 'Do', 'mi',
'la', 'la', 'la', 'la', 'mi', 'mi', 'mi', 'mi',
'Re', 'Re', 'Re', 'Re', 'la', 'la', 'la', 'sol',
'fa', 'fa', 'fi', 'fi', 'sol', 'sol'
], 24 + 1, ([a]) -> [a - 12, a, a + 12, a, a - 12, a + 12, a, a + 12])
kick = pipeline(loopEvery 1 * BEAT).to(Instrument.kick)
snare = pipeline((t) -> t + 3 * BEAT).to(loopEvery 2 * BEAT).to(Instrument.snare)
hat = pipeline((t) -> t + 0.5 * BEAT).to(loopEvery 1 * BEAT).to(Instrument.hat)
arp = combine(
pipeline(Notes.melody).to(Instrument.supersaw),
pipeline(loopEvery 1 * STEP).to(Value.approach(0.8, 0.01, 8)),
Filter.Lowpass()
)
bass = combine(
pipeline(Notes.bass).to(Instrument.supersaw),
pipeline(loopEvery 1 * STEP).to(Value.approach(0.5, 0.0001, 30)),
Filter.Lowpass()
)
arpMixed = pipeline(arp).gain(0.4)
delay = (t) -> t + (STEP * (Notes.melody.steps - 3))
arpMixedDelayed = pipeline(delay).to(arpMixed).gain(0.2)
arpMixedDelayedDelayed = pipeline(delay).to(arpMixedDelayedDelayed).gain(0.5)
main = mix(
pipeline(snare).gain(0.7),
kick,
pipeline(hat).gain(0.3),
pipeline((t) -> t + 3 * STEP).to(hat).gain(0.1),
arpMixed,
arpMixedDelayed,
pipeline(bass).gain(0.3))
return main
###
# Other constants...
###
PI = Math.PI
BEAT = 60 / BPM
STEP = BEAT / 4
###
# Define units, so we can use them as unit(1)
###
unit = (value) -> (x) -> x * value
beat = unit(BEAT)
step = unit(STEP)
###
# The oscillators. These oscilators receive the number of rotations.
###
pipeline = (source) ->
f = (t) -> source(t)
f.to = (g) -> pipeline((t) -> g(f(t)))
f.gain = (gain) -> pipeline((t) -> f(t) * gain)
return f
combine = (f, g, h) ->
throw new Error("f must be a function") if typeof f != 'function'
throw new Error("g must be a function") if typeof g != 'function'
throw new Error("h must be a function") if typeof h != 'function'
(t) -> h(f(t), g(t))
mix = (sources...) ->
return (t) -> sources.reduce(((a, source) -> a + source(t)), 0)
loopEvery = (loopLength) -> (time) -> time % loopLength
Osc =
sin: (x) -> Math.sin(x * 2*PI)
sawtooth: (x) -> (x % 1) * 2 - 1
random: (x) -> Math.random() * 2 - 1
Note =
###
# A frequency drop...
# Don't know from which frequency to which frequency though;
# I am not a mathematician!
#
# a : Frequency multiplier
# b : Drop speed
###
drop: (a, b) -> (t) -> (1 - Math.exp(-t * b)) * a
freq: (f) -> (t) -> f * t
step: (frequencies) ->
length = frequencies.length
result = (t) ->
c = (t / STEP) % length
i = Math.floor(c)
it = t - i * STEP
(frequencies[i] * t)
result.steps = length
return result
MidiNote =
lookup: do ->
NOTE_NAMES = 'do di re ri mi fa fi sol si la li ti
Do Di Re Ri Mi Fa Fi Sol Si La Li Ti
DO DI RE RI MI FA FI SOL SI LA LI TI'.split(/\s+/)
return (name) ->
NOTE_NAMES.indexOf(name)
toFrequency: (c) -> 440 * Math.pow(2, (c - 69) / 12)
Value =
approach: (s, f, b) -> (t) -> s + (1 - Math.exp(-t * b)) * (f - s)
Filter =
gain: (signal, volume) -> signal * volume
Lowpass: () ->
current = 0
(signal, factor) ->
current += (signal - current) * factor
###
# Logging facilities....
###
log = do ->
last = 0
(args...) ->
now = new Date().getTime()
if now - last > 1000
console.log(args...)
last = now
args[0]
return music()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment