Created
March 11, 2015 11:16
-
-
Save tomasos/17e2acd21a17d600ffc9 to your computer and use it in GitHub Desktop.
Overtone presentation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Tomas Osland | |
;; tomas.osland@knowit.no | |
;; @tomasosland | |
;; Welcome to this presentation about functional music. In this lightning talk we | |
;; will construct a drum machine and make som beats, play the piano, and experiment with synthesizers. | |
;; Start overtone.cid | |
(ns overtone.examples.timing.one-bar-sequencer | |
(:use [overtone.live] | |
[overtone.inst drum] | |
[overtone.inst.sampled-piano])) | |
;; Overtone is a library for creating synthesizers and composing music. The hard way. | |
;; The library is written in Clojure and uses the SuperCollider synthesis engine, | |
;; wich is written in Java. You can also use midi i/o for devices, such as the monome. | |
;; https://github.com/overtone/overtone/ | |
;; http://overtone.github.io/ | |
;; This defines the instruments. | |
(def instruments {:kick quick-kick | |
:snare noise-snare | |
:hit soft-hat}) | |
(quick-kick) | |
(noise-snare) | |
(soft-hat) | |
;; And this is our drum machine sequence. | |
(def sequence {:kick [1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0] | |
:snare [0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0] | |
:hit [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0]}) | |
;; Overtone provides a metronome, which is basically a ticker incrementing a count. | |
(def metro (metronome 130)) | |
(metro) | |
;; And now to some logic. play-sequence is a function with a beat count and a instrument | |
;; for parameters. The function will go through the next 4 beats and play the given | |
;; instrument at a future time. | |
(defn play-sequence [beat instr] | |
(let [time (mod beat 4) | |
seq (vec (take 4 (drop (* 4 time) (sequence instr))))] | |
(if (= 1 (seq 0)) (at (metro (+ 0.00 beat)) ((instruments instr)))) | |
(if (= 1 (seq 1)) (at (metro (+ 0.25 beat)) ((instruments instr)))) | |
(if (= 1 (seq 2)) (at (metro (+ 0.50 beat)) ((instruments instr)))) | |
(if (= 1 (seq 3)) (at (metro (+ 0.75 beat)) ((instruments instr)))))) | |
(vec (take 4 (drop (* 4 0) (sequence :hit)))) | |
(at (metro (+ 0.50 0)) ((instruments :kick))) | |
;; The player will iterate over the instruments and play the instruments sequence. | |
;; This function is recursive and will loop for ever. | |
(defn player [beat] | |
(doseq [instr (keys instruments)] (play-sequence beat instr)) | |
(apply-at (metro (inc beat)) #'player (inc beat) [])) | |
(player (metro)) | |
;; Lets change the beat | |
(def sequence {:kick [1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0] | |
:snare [0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0] | |
:hit [0 0 1 0 0 0 1 0 1 0 1 0 0 1 1 1]}) | |
;; And the tempo | |
(metro :bpm 90) | |
(metro :bpm 140) | |
(stop) | |
;; Overtone has two built in piano modules where one of them is based on piano | |
;; samples from Freesound.org. | |
(sampled-piano) | |
(sampled-piano 40 (+ 0.3 (rand 0.5))) | |
(for [i (range 110)] (at (+ (+ (now) i) (* i (rand 2) 20)) (sampled-piano i (+ (rand 0.6) 0.3)))) | |
;; A chord is composed of three or more tones played simultaneous. | |
;; Overtone has already defined the chords for us, | |
;; but we must define how they are played. | |
(defn play-chord | |
[chord] | |
(doseq [note chord] (sampled-piano note (+ (rand 0.5) 0.3)))) | |
(play-chord (chord :D3 :m7)) | |
;; When we have defined how to play chords, we can use this to play | |
;; chord progressions. | |
(defn play-progression | |
[beat chords] | |
(let [next-beat (+ beat 3)] | |
(at (metro beat) (play-chord (first chords))) | |
(apply-by (metro next-beat) #'play-progression [next-beat (rest chords)]))) | |
(play-progression (metro) [(chord :D3 :m7) (chord :A3 :m7)]) | |
(play-progression (metro) | |
(cycle [(chord :C3 :m9) (chord :F3 :7) (chord :Bb3 :maj9) (chord :Eb3 :maj9) (chord :A3 :m7-5) (chord :D3 :7-9) (chord :G3 :minor7)])) | |
(stop) | |
;; To play a melody we will send in a list of notes wich we will cycle | |
;; through recursively and play at each beat of the metronome. | |
(defn play-melody | |
[beat notes] | |
(let [note (first notes)] | |
(when note | |
(at (metro beat) (sampled-piano note (+ (rand 0.6) 0.3)))) | |
(let [next-time (+ beat 1)] | |
(apply-by (metro next-time) play-melody [next-time (rest notes)])))) | |
;; Overtone lets us specify which note in a scale to play. This gives us more | |
;; flexibility in changing scales and tonality. | |
(def deg [:ii :v :iii :vi :v]) | |
(metro :bpm 180) | |
(play-melody (metro) (degrees->pitches deg :mixolydian :C4)) | |
(play-progression (metro) | |
(cycle [(chord :C3 :m9) (chord :F3 :7) (chord :Bb3 :maj9) (chord :Eb3 :maj9) (chord :A3 :m7-5) (chord :D3 :7-9) (chord :G3 :minor7)])) | |
(play-melody (metro) (cycle (degrees->pitches deg :mixolydian :F4))) | |
;; Since Overtone is using the SuperCollider engine, we are able to define | |
;; our own synthesizers. | |
;; Lets make some noise. | |
(defsynth drone | |
[out-bus 0] | |
(out out-bus (pan2 (* 1.0 (sin-osc 30) (lf-pulse 30))))) | |
(drone) | |
(definst sawdrone [] | |
(* 0.2 | |
(+ (sin-osc 300) (saw 200) (saw 11) (sin-osc 30)))) | |
(sawdrone) | |
(stop) | |
;; Check out https://github.com/overtone/overtone for code examples. | |
;; Check out http://meta-ex.com for some music examples. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment