Music as data
-
Upload
jonromer -
Category
Technology
-
view
1.345 -
download
1
description
Transcript of Music as data
Hackers and RockstarsLive programming Music in Clojure
John Vlachoyiannis@jonromero
[email protected]://mad.emotionull.com
Who am I?
Jon VlachoyiannisSoftware Samurai and Serial Entrepreneur
Teaching Parallel Processing [Greece]Founder: Sfalma.com
Founder: busyFounder.comHacker: Niobiumlabs.com
http://www.linkedin.com/in/johnvlachoyiannis
Hackers
Not really
Hackers = Creators
Rockstars
> (equals? programming making-music)true
> (equals? music is-data true)true
Notes are data and code
Supercollider
{ [SinOsc.ar(440, 0, 0.2), SinOsc.ar(442, 0, 0.2)] }.play;
Chuck
// make our patch SinOsc s => dac;
// time-loop, in which the osc's frequency is changed every 100 ms
while( true ) { 100::ms => now;
Std.rand2f(30.0, 1000.0) => s.freq;}
Impromptu
; make sure that everything is disconnected(au:clear-graph)
; setup simple au graph; piano -> output
(define piano (au:make-node "aumu" "dls " "appl"))
(au:connect-node piano 0 *au:output-node* 0)(au:update-graph)
; play note on piano(play-note (now) piano 60 80 (* 1.0 *second*))
Toplap.orgTemporary Organisation for the Proliferation of Live Artistic
Programming
I can do it better!
Python
musik:> [a [ [v a d] [e [f a] ] g] [f g] [a b f [ [d s] f] f a a] ]
musik:> [kaboosh bam [dam vd [vd a]]]
musik:>[ k+s [ k k ] s s [ k+a ] ]
●Time (duration) is written like in real music● Easy to understand● Hand-made REPL
# Thanks Darth Eru for the original version! def parse(self, origString): root = "" tokens = re.compile(r'(\[?\]?\ ?)') origString = [word.strip() for word in tokens.split(origString) if word.strip() != '' ]
stack = [] for element in origString: if element[0] == '[': if element[1:] == "": newLevel = [] else: newLevel = [ element[1:] ] stack.append(newLevel) elif element[-1] == ']': if element[0:-1] != "": stack[-1].append(element[0:-1]) finished = stack.pop() if len(stack): stack[-1].append(finished) elif element[0]: root = finished else: stack[-1].append(element) return root
● This bracket syntax is HARD ● Not so easy to add effects
● Concurrency bye-bye
Something “feels” wrong
Meet Clojure
What is Clojure?
Ok, what is Lisp?
“Lisp is worth learning for the profound enlightenment experience you will have
when you finally get it; that experience will make you a better programmer for the rest of your days, even if you never actually use
Lisp itself a lot."
Eric S. Raymond, "How to Become a Eric S. Raymond, "How to Become a Hacker".Hacker".
“LISP stands for: Lots of Insane Stupid Parentheses”
AnonymousAnonymous
The Truth about Lisp
LISLISt PProcessing
● Second oldest high-level language (first is Fortran)
● Code as Data (Homoiconic)● Perfect for Domain-specific languages
(DSL)● Exploratory programming
Clojure
● Lisp in JVM● Concurrent programming● Dynamic Development (REPL)● Lazy sequences● No side effects (almost)
clojure might be a better java than java
public class StringUtils {public static boolean isBlank(String str) {
int strLen;if (str == null || (strLen = str.length()) == 0) {
return true;}for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;}
}return true;
}}
public class StringUtils {public isBlank(str) {
if (str == null || (strLen = str.length()) == 0) {return true;
}for (i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;}
}return true;
}}
public isBlank(str) {if (str == null || (strLen = str.length()) == 0) {
return true;}for (i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {return false;
}}return true;
}
public isBlank(str) {if (str == null || (strLen = str.length()) == 0) {
return true;}
every (ch in str) {Character.isWhitespace(ch);
} return true;
}
public isBlank(str) {every (ch in str) {
Character.isWhitespace(ch);}
}
(defn blank? [s] (every? #(Character/isWhitespace %) s))
Everything is code
(println "Hello World")
function argument
Everything is data
(println "Hello World")
symbol string
list
Where is the correlation?
Let's get M.A.D!
● Live programming (REPL)● Using Processing (processing.org)
● Easy to extend● Easy to understand
● Fun!
> (p (pattern [kick]));; 1/1 is kick
(defsample “kick” path-of-sample);; create as sample kick
(defnote A#4 @*sine*);; create a note
(create-notes);; creates all defnotes for notes
;; helping function
Everything is one data structure
(defrecord Melement [volume pitch duration play-fn data])
play-fn can be anything you like
(defn play-sample [sample] (.trigger (:data sample)))
;; for samples
> (p (pattern [kick]));; 1/1 is kick
pattern calculates the correct timing updates the :duration for notes
> (p (pattern [kick kick]));; play two kicks
;; ½ kick;; ½ kick
p plays each note at the correct timing
(p (pattern [kick (+snare hihat)]));; two times again
;; ½ kick;; ½ snare with hihat
(p (pattern [kick [snare snare snare]]));; two times again
;; ½ kick;; (½ / 3) snare;; (½ / 3) snare;; (½ / 3) snare
Just like real music
Now fun! Hint: transformations
(p (pattern [A4 B4 C5 D5 E5 F5 G5]))
(p (reverse (pattern [A4 B4 C5 D5 E5 F5 G5])))
(p (map #(assoc % :pitch (.nextInt (java.util.Random.) 1100))
(pattern [E4 G4 B4 E5 B4 G4]))
You can manipulate music as a data structure
(keep-looping)
(play! [[E4 G4 E4] [E5 B4 G4 D4 A4 E4 G4 A4]])
play! Lets you experiment in real timeLive programming
Using Processing for Visual effects
Limit? The audio sky!
(play! (text-to-notes (get-latest-twits));; add markov-chains
Searching for members forBand of Emacs
Give me a twit at @jonromero if interested
Thanks! Questions?
[email protected] it at mad.emotionull.com