2018-07-16 22:39:51 +00:00
|
|
|
(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)
|
2018-07-17 03:12:32 +00:00
|
|
|
|
2018-07-19 03:22:20 +00:00
|
|
|
;; [:= 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
|
2018-07-17 03:12:32 +00:00
|
|
|
;; control maps have keys like ::tempo, ::transpose, ::instrument, ::phrase, ::player, ::keysig
|
2018-07-19 03:22:20 +00:00
|
|
|
|
|
|
|
;; 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]}]])
|
|
|
|
|
2018-07-19 03:34:31 +00:00
|
|
|
;; TODO exercise 2.1 (ii-V-I function)
|
|
|
|
;; this will involve being able to answer, "what pitch is n semitones above this one?"
|
|
|
|
|
|
|
|
(def ii-V-I
|
|
|
|
(let [Dm [:= (note 1 [:D 4])
|
|
|
|
(note 1 [:F 4])
|
|
|
|
(note 1 [:A 4])]
|
|
|
|
Gmaj [:= (note 1 [:G 4])
|
|
|
|
(note 1 [:B 4])
|
|
|
|
(note 1 [:D 5])]
|
|
|
|
Cmaj [:= (note 2 [:C 4])
|
|
|
|
(note 2 [:E 4])
|
|
|
|
(note 2 [:G 4])]]
|
|
|
|
[:+ Dm Gmaj Cmaj]))
|
|
|
|
|
2018-07-19 03:22:20 +00:00
|
|
|
(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]}])
|