(ns music) ;; an octave is an int, e.g. 4 ;; a pitch class is a keyword from :Abb to G## ;; a pitch is a [pitch class, octave] vector, e.g. [:C 4] is middle C ;; a duration is a rational number, e.g. 1/8 ;; a note has a duration, optionally a pitch, and optionally any other necessary keys (e.g. loudness) ;; {:duration 1/8 :pitch [:A# 3]} is a note. {:duration 1/4} is a note (really, a rest) ;; [:= noteA noteB] represents noteA played simultaneously with noteB ;; [:+ noteA noteB] represents noteA played followed by noteB ;; [:modify noteA control] annotates noteA with the control map ;; control maps have keys like ::tempo, ::transpose, ::instrument, ::phrase, ::player, ::keysig ;; primitives (def note1 {:duration 1/4, :pitch [:Eb 4]}) (def note2 {:duration 1/4, :pitch [:G 4]}) (def note3 {:duration 1/8, :pitch [:F 4]}) (def rest1 {:duration 1/8}) [:= note1 note2] ;; note1 simultaneous with note2 [:+ note1 note3] ;; note1 followed by note3 [:+ [:= note1 note2] note3] ;; note1 simultaneous with note2, followed by note3 [:modify note1 {::tempo 120}] ;; note1 modified to have tempo 120 [:modify [:= note1 note2] {::tempo 120 ::instrument "Dope Organ"}] ;; note1 simultaneous with note2 modified with tempo and instrument ;; can be nested to arbitrary complexity (def song [:= [:+ {:duration 1/4, :pitch [:D 3]} {:duration 1/4, :pitch [:E 3]} {:duration 1/4, :pitch [:F 3]}] [:+ {:duration 1/4, :pitch [:F 3]} {:duration 1/4, :pitch [:G 3]} {:duration 1/4, :pitch [:A 3]}]]) (defn note [duration pitch] {:duration duration, :pitch pitch}) (defn rest [duration] {:duration duration}) (defn tempo [tempo music] [:modify music {::tempo tempo}]) (defn transpose [abs-pitch music] [:modify music {::transpose abs-pitch}]) (defn instrument [instrument music] [:modify music {::instrument instrument}]) (defn phrase [phrase-attributes music] [:modify music {::phrase phrase-attributes}]) (defn player [player-name music] [:modify music {::player player-name}]) (defn keysig [pitch mode music] [:modify music {::keysig [pitch mode]}])