Skip to content

Instantly share code, notes, and snippets.

@daveyarwood
Created August 20, 2016 15:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save daveyarwood/4d5709725a123d6d9cf21cd020f24ad7 to your computer and use it in GitHub Desktop.
Save daveyarwood/4d5709725a123d6d9cf21cd020f24ad7 to your computer and use it in GitHub Desktop.
Steve Reich's "Clapping Music" in Alda
# Clapping Music (1972)
# for two performers
#
# Steve Reich
#
# sheet music:
# https://sites.ualberta.ca/~michaelf/SEM-O/SEM-O_2014/Steve's%20piece/clapping_reich.jpg
(def clap (alda-code "o2 d+8"))
(def pattern
(let [rest (pause (duration (note-length 8)))]
[clap clap clap rest clap clap rest clap rest clap clap rest]))
(defn shift [n pattern]
(take (count pattern) (drop n (cycle pattern))))
(tempo! 172)
midi-percussion:
V1:
(times 13
(times 12 pattern))
V2:
(for [n (range 13)]
(times 12 (shift n pattern)))
@0atman
Copy link

0atman commented Aug 29, 2016

Hey man, am I right in thinking that my tweaks to simplify this using pure alda rather than dropping to closure are semantically the same?

Alda's so readable, it seemed a shame to me to use closure for the static pattern!

@daveyarwood
Copy link
Author

daveyarwood commented Sep 5, 2016

Sorry, just now saw this!

That's a really interesting thought. Unfortunately, though, variables in an Alda score and symbols defined in the Clojure environment are not stored in the same place, so they can't be used interchangeably like this.

I just played around with this for a bit in the Alda REPL, and I realized that the value of (alda-code "pattern") is always ({:event-type :get-variable, :variable :pattern}) regardless of whether or not you've defined a variable called pattern:

> clap = o2 d+8

> rest = r8

> pattern = clap clap clap rest clap clap rest clap rest clap clap rest

> midi-percussion:

mp> (tempo! 172)

# pattern is clapped once
mp> pattern

# the score evaluator retrieves the value of the `pattern` variable in the score;
# pattern is clapped once
mp> (alda-code "pattern")

# this evaluates to nil, so we don't hear anything
# it appears that whatever `(alda-code "pattern")` evaluates to, it must be a sequence of length 1
# hmm, why is that?
mp> (prn (count (alda-code "pattern")))
1

# let's see the value of `(alda-code "pattern")`
# (again the value is nil, so we don't hear anything)
mp> (prn (alda-code "pattern"))
({:event-type :get-variable, :variable :pattern})

As you can see, when we dip down into Clojure, we're working at a "meta level" where we can construct/generate Alda events, but these events have no context of the score in which they're being evaluated, until the score is actually evaluated by Alda.

One consequence of this is that (alda-code "pattern") can only represent ({:event-type :get-variable, :variable :pattern}), which the Alda score evaluation process will replace with the current value of the variable at that point in the score. The variable replacement happens after the Clojure code is evaluated, so we'll always end up with the unmodified variable value.

Is this awkward? Probably yes :) I haven't fully explored this aspect of creating scores with Alda yet, but so far, it seems like once you're in the mindset of writing inline Clojure code in an Alda score, the easiest thing is to work with def'd Clojure vars instead of Alda variables.

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