diff --git a/src/performance.clj b/src/performance.clj index 663c84d..39784cc 100644 --- a/src/performance.clj +++ b/src/performance.clj @@ -1,4 +1,15 @@ -(ns performance) +(ns performance + (:require [clojure.core.match :refer [match]])) + +;; A player is an entity that knows how to interpret music in a certain ways +;; I need to flesh most of this out -- see section 8.3 on page 141 +(def a-player + {:name "player1" ;; player name + :play-note + (fn [context note] ()) ;; function to play a note with a context, returns Performance + :interp-phrase + (fn [p-map context attrs music]) ;; function to interpret a Music value, returns performance + :notate [context note]}) ;; function to transcribe a note - not implemented in Euterpea ;; A performance is a data structure that describes the act ;; of performing a piece of music. It is a vector of events, @@ -17,13 +28,41 @@ ;; changing tempo, key signature, tempo, etc. (def my-context {:time 0 ;; time at which the performance starts in seconds - :player {:?? :??} ;; not sure what this is + :player a-player ;; player currently interpreting the music :instrument "Cello" ;; instrument currently playing (?) :duration-t 2 ;; the duration in seconds of a whole note :pitch-offset 0 ;; a pitch offset -- number of semitones to transpose notes up or down :volume 50 ;; volume of performance :key [:C :major]}) ;; current key signature +(defn perform + "Convert a music value to a performance value" + [player-map context music] + (first (perf player-map context music))) + +(defn perf + "Implementation of perform, returns a tuple of (performance, duration)" + [player-map context music] + (let [{:keys [player duration-t]} context] + (match music + {:duration duration + :pitch pitch} (apply (:play-note player) + context + duration + pitch + (* duration duration-t)) + {:duration duration} [[] (* duration duration-t)] + [:+ & ms] (reduce (fn [[events-acc dur-acc] m] + (let [[events dur] (perf player-map + context + m)] + [(concat events-acc dur-acc) + (+ dur-acc dur)])) + [[] 0] + ms) + [:= & ms] :TODO + [:modify control m] :TODO))) + (defn metro "Generates a duration-t value (the duration in seconds of a whole note) from the number of beats per minute and the duration of a beat (1/4 for