diff --git a/src/um/measure.lfe b/src/um/measure.lfe new file mode 100644 index 0000000..5e23c9c --- /dev/null +++ b/src/um/measure.lfe @@ -0,0 +1,17 @@ +(defmodule um.measure + (export all)) + +(defun time-sig (beats-per-measure beat-value) + `#(,beats-per-measure ,beat-value)) ; this is isomorphic to, e.g., 4/4, 3/4, 3/8, etc. + +(defun make (time-sig key-sig voices) + '#m(time-sig ,time-sig + key-sig ,key-sig + voices ,(add-voices))) + +(defun add-voices + (('() acc) + acc) + ((`(,voice . ,tail) acc) + ;; TODO process voice + (add-voices tail acc))) diff --git a/src/um/note.lfe b/src/um/note.lfe index 089e90d..f91b20b 100644 --- a/src/um/note.lfe +++ b/src/um/note.lfe @@ -1,6 +1,10 @@ (defmodule um.note (export all)) +;;;;;;;;;;;;; +;;; PITCH ;;; +;;;;;;;;;;;;; + (defun G9 () 127 ) (defun F#9 () 126 ) (defun Gb9 () 126 ) @@ -183,7 +187,7 @@ (defun Db-1 () 1 ) (defun C-1 () 0 ) -(defun all () +(defun midi-names () #m( G9 127 F#9 126 @@ -385,6 +389,74 @@ C-1 0 C 0 )) +(defun get-pitch (name) + (mref (midi-names) name)) + +(defun get-pitches (names) + (let ((all (midi-names))) + (list-comp ((<- n names)) + (mref all n)))) + +(defun make + ((names) (when (is_list names)) + (list-comp ((<- n names)) (make n))) + ((name) + (make name (get-velocity 'mp)))) + +(defun make(name velocity) + (make name velocity 100)) + +(defun make + ((name velocity duration) (when (is_atom name)) + (make (get-pitch name) velocity duration)) + ((pitch velocity duration) + `#m(pitch ,pitch + velocity ,velocity + duration ,duration))) + +(defun make-fuzzy + ((names) (when (is_list names)) + (list-comp ((<- n names)) (make-fuzzy n))) + ((name) + (make-fuzzy name (get-velocity 'mp)))) + +(defun make-fuzzy (v velocity) + (make-fuzzy v velocity 100)) + +(defun make-fuzzy + ((name velocity duration) (when (is_atom name)) + (make-fuzzy (get-pitch name) velocity duration)) + ((p v d) + `#m(pitch ,p + velocity ,(fuzzy-velocity v) + duration ,(fuzzy-duration d)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; NOTE VALUE & DURATION ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun note-values () + '(2 ; double note / breve + 1 ; whole note / semibreve + 1/2 ; half note / minim + 1/4 ; quarter note / crotchet + 1/8 ; eighth note / quaver + 1/16 ; sixteenth note / semiquaver + 1/32 ; thirty-second note / demisemiquaver + 1/64 ; sixty-fourth note / hemidemisemiquaver + 1/128 ; semihemidemisemiquaver + )) + +(defun fuzzy-duration (ms) + (fuzzy-duration ms 2)) + +(defun fuzzy-duration (ms variance) + (round (rand:normal ms variance))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; DYNAMICS & VELOCITY ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;; + #| The initial division of the range 0-127 into the ppp to fff dynamic ranges (of which there are eight) was done in the following manner: @@ -420,7 +492,7 @@ Note that these may be changed to taste/hearing at a latter date. #| To get the MIDI ranges for the dynamics, did the following in the LFE REPL: -lfe> lfe_io:format "~w~n" (list (lists:reverse (++ '(127) +lfe> (lfe_io:format "~w~n" (list (lists:reverse (++ '(127) (cdr (lists:flatten (lists:map (match-lambda ((`(,a ,b)) @@ -467,53 +539,9 @@ range of a given dynamic. ((v variance) (round (rand:normal v variance)))) -(defun fuzzy-duration (name) - (fuzzy-duration name 2)) - -(defun fuzzy-duration (ms variance) - (round (rand:normal ms variance))) - -(defun get-pitch (name) - (mref (all) name)) - -(defun get-pitches (names) - (let ((all (all))) - (list-comp ((<- n names)) - (mref all n)))) - -(defun make - ((names) (when (is_list names)) - (list-comp ((<- n names)) (make n))) - ((name) - (make name (get-velocity 'mp)))) - -(defun make(name velocity) - (make name velocity 100)) - -(defun make - ((name velocity duration) (when (is_atom name)) - (make (get-pitch name) velocity duration)) - ((pitch velocity duration) - `#m(pitch ,pitch - velocity ,velocity - duration ,duration))) - -(defun make-fuzzy - ((names) (when (is_list names)) - (list-comp ((<- n names)) (make-fuzzy n))) - ((name) - (make-fuzzy name (get-velocity 'mp)))) - -(defun make-fuzzy (v velocity) - (make-fuzzy v velocity 100)) - -(defun make-fuzzy - ((name velocity duration) (when (is_atom name)) - (make-fuzzy (get-pitch name) velocity duration)) - ((p v d) - `#m(pitch ,p - velocity ,(fuzzy-velocity v) - duration ,(fuzzy-duration d)))) +;;;;;;;;;;;;;;;;;;; +;;; PERFORMANCE ;;; +;;;;;;;;;;;;;;;;;;; (defun play ((device channel notes) (when (is_list notes)) diff --git a/src/um/tempo.lfe b/src/um/tempo.lfe new file mode 100644 index 0000000..5398198 --- /dev/null +++ b/src/um/tempo.lfe @@ -0,0 +1,65 @@ +(defun um.tempo + (export all)) + +(defun tempos () + '(#(prestissimo 200) + #(presto 184) + #(vivace 166) + #(allegro 138) + #(allegretto 116) + #(moderato 108) + #(andante 92) + #(adagio 72) + #(lento 60) + #(largo 48) + #(grave 36))) + +(defun bpms () + (list-comp ((<- `#(,k ,v) (tempos))) `#(,v ,k))) + +(defun to-bpm (name) + (proplists:get_value name (tempos))) + +(defun from-bpm (bpm) + (proplists:get_value bpm (bpms))) + +#| To get the nearest tempo for a given BPM, did the following in the LFE REPL: + +lfe> (set bpms (list-comp ((<- `#(,k ,v) (tempos))) v))) +(200 184 166 138 116 108 92 72 60 48 36) +lfe> (list-comp ((<- `#(,hi ,lo) (lists:zip bpms (cdr bpms) 'trim))) (round (+ lo (/ (- hi lo) 2)))) +(192 175 152 127 112 100 82 66 54 42) + +|# +(defun nearest-tempo + ((bpm) (when (=< bpm 42)) + 'grave) + ((bpm) (when (=< bpm 54)) + 'largo) + ((bpm) (when (=< bpm 66)) + 'lento) + ((bpm) (when (=< bpm 82)) + 'adagio) + ((bpm) (when (=< bpm 100)) + 'andante) + ((bpm) (when (=< bpm 112)) + 'moderato) + ((bpm) (when (=< bpm 127)) + 'allegretto) + ((bpm) (when (=< bpm 152)) + 'allegro) + ((bpm) (when (=< bpm 175)) + 'vivace) + ((bpm) (when (=< bpm 199)) + 'presto) + ((bpm) (when (> bpm 199)) + 'prestissimo)) + +(defun fuzzy-bpm (name) + (fuzzy-bpm name 5)) + +(defun fuzzy-bpm + ((name variance) (when (is_atom name)) + (fuzzy-bpm (to-bpm name) variance)) + ((bpm variance) + (round (rand:normal bpm variance))))