Hi,
I always wanted to learn how to transform music with scheme, so I
implemented half of it. If some of you experts could look at it and tell
me what could be done more elegantly (Scheme is not my native language),
and especially what needs to be done to make this easy to use, that would
be super!
Ciao,
Dscho
#(define (scale-semitones scale)
"Get a vector of semitones for a given scale"
(if (equal? scale "ionian") #(0 2 4 5 7 9 11)
(if (equal? scale "dorian") #(0 2 3 5 7 9 10)
(if (equal? scale "phrygian") #(0 1 3 5 7 8 10)
(if (equal? scale "lydian") #(0 2 4 6 7 9 11)
(if (equal? scale "mixolydian") #(0 2 4 5 7 9 10)
(if (equal? scale "aeolian") #(0 2 3 5 7 8 10)
(if (equal? scale "locrian") #(0 1 3 5 6 8 10)
(error "scale unknown: " scale)))))))))
#(define (alter-mode-aux music transpose-vector)
"Transpose according to transpose-vector"
(if (ly:music? music)
(let ((pitch (ly:music-property music 'pitch)))
(if (ly:pitch? pitch)
(let* ((off (modulo (ly:pitch-semitones pitch) 12))
(trans (vector-ref transpose-vector off)))
(if (eq? trans null)
(begin (display "Warning: Mode mismatch")
(display-music pitch))
(if (not (eq? trans 0))
(begin (set! pitch (ly:pitch-transpose pitch trans))
(ly:music-set-property! music 'pitch pitch))))))))
music)
#(define (pitch-name->semitone name)
"Find semitone for given name"
(let ((p pitchnames)(sym (string->symbol name)))
(while (and (> (length p) 0)
(not (equal? sym (caar p))))
(set! p (cdr p)))
(if (< (length p) 2)
(error "No such pitch")
(ly:pitch-semitones (cdar p)))))
#(define (alter-mode music key source-scale target-scale)
"Transpose between types of scales"
(let ((vector (make-vector 12 null))
(source-semitones (scale-semitones source-scale))
(target-semitones (scale-semitones target-scale))
(key-offset (pitch-name->semitone key)) (i 0))
(while (< i 7)
(let* ((source (vector-ref source-semitones i))
(target (vector-ref target-semitones i))
(diff (- target source)))
(if (or (> diff 1) (< diff -1))
(error "Thinko!!"))
(vector-set! vector
(modulo (+ key-offset source) 12)
(if (= diff 0)
0
(ly:make-pitch 0 0 (if (= diff 1) SHARP FLAT)))))
(set! i (1+ i)))
(music-map (lambda (x) (alter-mode-aux x vector)) music))
music)
normalScale = \relative c' { c4 d e f g a b c }
\score {
\applyMusic #(lambda (x) (alter-mode x "c" "ionian" "phrygian")) \normalScale
}
_______________________________________________
lilypond-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-devel