Skip to content

MegaLoler/Music

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
src
 
 
 
 
 
 
 
 

Music

Just a framework for musical expression in Common Lisp with a focus on music theory!

Totally building it from scratch, there's lots to do and a lot is missing/broken.

It currently uses SBCL timers for queuing real time midi events, so it's SBCL dependant.

See examples/nyan.lisp for an example of a song.

Examples

You can designate pitch classes with symbols:

'c 'c♯ 'f♭ 'g♯♯♯

And actual notes with octaves as well:

'c5 'a♭♭7

You can designate intervals with symbols:

'p5 'maj7 2dim2 (doubly diminished second)

You can designate harmonies like this:

'ii 'IVdom9 'vmin42♯5

You can make a harmony like this:

(harmony 'I7/V)
;; => (D F♯ A C)

(harmony 'IVmaj43)
;; => (C E F A)

You can get a scale like this:

(scale (key 'g-phrygian))
;; => (G A♭ B♭ C D E♭ F)

You can designate scale degrees with either numbers, names or solfège syllables:

'(do re 3 4 dominant submediant)

You can realize scale degrees and pitch class like this:

(realize '(do re 3 4 dominant submediant))
;; => (C4 E4 G4 F4 B4 A4 B4 G2)

You can also nest them:

(realize '(do re mi (fa sol la) ti do))
;;; => (C4 D4 E4 (F4 G4 A4) B4 C5)

And indicate octave displacements and rests like this:

(realize '(mi fa > mi fa > mi r < < < < re r))
;; => (E4 F4 E5 F5 E6 R D2 R)

You can realize harmonic progressions in a simple way like this:

(realize (harmony '(I IV64 V43 I6)))
;; => ((C4 E4 G4) (C4 F4 A4) (D4 F4 G4 B4) (E4 G4 C5))

You can get the interval between notes like this:

(difference (note 'g5) (note 'f6))
;; => MIN7

You can get the note or pitch class an interval above or below another like this:

(above (note 'a♭4) (interval 'p8))
;; => A♭5
(below (pitch-class 'd) (interval 'aug2))
;; => C♭

You can add intervals like this:

(sum (interval 'maj6) (interval 'maj3)
;; => AUG8

Why not stack 100 perfect fifths together and see what you get?

(loop
   :with i = (interval 'p1)
   :repeat 100
   :do (setf i (sum i (interval 'p5)))
   :finally (return i))
;; => 14AUG401

You can get relative or parallel keys like this:

(parallel (key 'f-major) 'minor)
;; => F-MINOR

(relative (key 'f♯-minor) 'mixolydian)
;; => E-MIXOLYDIAN

You can make a sequence like this:

(seq '(> sol la < ri mi re me re do do re))

You can make a chord like this:

(chord '(do mi sol te))

You can designate rhythms using divisions of beats like this:

;; "one and two and three and four
(2 2 2 2 2 2 1 2 2 2 2 2 2 1) ;; twinkle twinkle

;; "one-ee uh ee-and three four"
(4 2 2 4 2 1 1) ;; mario theme opening rhythm

And you can give rhythm to a sequence like this:

(seq '(> sol la < ri mi re me re do do re)
     '(2 2 4 2 4 4 4 2 2 2))

You can play things with live midi using portmidi like this:

(play (seq '(> sol la < ri mi re me re do do re)
	       '(2 2 4 2 4 4 4 2 2 2)))

Which implicitely wraps the expression in event first:

(event (seq '(> sol la < ri mi re me re do do re)
	        '(2 2 4 2 4 4 4 2 2 2)))
;; => (G4@0s-1/4s A4@1/4s-1/2s D♯4@1/2s-5/8s E4@5/8s-7/8s D4@7/8s-1s E♭4@1s-9/8s D4@9/8s-5/4s C4@5/4s-3/2s C4@3/2s-7/4s D4@7/4s-2s)

Which turns the expression into a list of timed events.

About

Music framework in Common Lisp

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published