Jump to content
JulioHerrlein

Parsimonious Voice Leading (again): attempts to provide an algorithm

Recommended Posts

Parsimonious Voice Leading (again): attempts to provide an algorithm

 

;;In a previous post I deleted, I was trying to find a good way to ensure  the minimal parsimonious Voice-Leading (VL) between a sequence of chords.

;;In this post I will try to explain my second attempt.

 

;Let's take a look at a sequence of chords, spreaded out almost in a random way, with no VL

 

(setf chordstovl2 '(b3eb5g3 cs6e7gs3 b4f5g6 f7e5c2 d4f7e4 gs7e2a8)


 

 

image.png.8119f04f427a5e28d603c4233d984bae.png

 

;lLet's specify and evaluate a variable for the number of voices used:

 

(setf voices 3)

 

;Let's try to think the best way to connect this pitches with minimal movement. I will apply the following expression to ensure a better and less ambiguous result when applying the Chord-Closest-Path Function

;;;Evaluate voices before

(setf voices 3)

;;;Then
 

(setf chordized
(mclist
(chordize-list
(gen-divide voices
(setf vlfinal
(integer-to-pitch
(modus
(interval-to-pitch
(replace-map '((-11 1) (-10 2) (-9 3) (-8 4) (-7 5) (7 -5) (8 -4) (9 -3)(10 -2)(11 -1))
(integer-to-interval
(modus
(pitch-to-midi
(setf chordmelo
(pitch-melodize chordstovl2))))))
:start (car chordmelo)))))))))

 

 

image.png.c384ecee7241c0568051027a02991388.png

;;; Please note the use of the replace-map function ensuring that no movement will be greater than a tritone away. This means that a movement like "C to G" (7 semitones) will be convertet in a G to C (5 semitones). This ensure a modulo 12 (octave constraint) reduction of all the material and also a constraint in terms of the size of the movements that will not exceed 6 semitones.

 

;;;Finally, I will apply the Chord-Closest-Path Function

 

(chord-closest-path (car chordized) (chordize-list (gen-divide voices vlfinal)))

 

image.png.858c83b30f9103f794875010d9737692.png

 

Hope it help some VL efforts.

 

Best,

Julio Herrlein

 

 

Share this post


Link to post
Share on other sites

Janusz suggested a different way for the expression:

 

(setf voices 3)
(setf chordstovl2 '(b3eb5g3 cs6e7gs3 b4f5g6 f7e5c2 d4f7e4 gs7e2a8))
(setf chordmelo (pitch-melodize chordstovl2))
(setf intervals (integer-to-interval (modus (pitch-to-midi chordmelo))))
(setf map (replace-map '((-11 1) (-10 2) (-9 3) (-8 4) (-7 5)
                         (7 -5) (8 -4) (9 -3) (10 -2) (11 -1))
                       intervals))
(setf vlfinal (integer-to-pitch
               (modus
                (interval-to-pitch map :start (car chordmelo)))))
(setf chordized (mclist (chordize-list (gen-divide voices vlfinal))))
(chord-closest-path (car chordized) chordized)

 

Share this post


Link to post
Share on other sites

Dear Julio,

 

Thanks for sharing these codes. So I'm trying to understand if the following approach could work - it seems to work for your example (but not for every progression). 

(setf chordstovl2 '(b3eb5g3 cs6e7gs3 b4f5g6 f7e5c2 d4f7e4 gs7e2a8))

(defun voicelead (chords)
  (chord-closest-path (list (car chords)) chords))

(voicelead (ambitus '(c4 c5) chordstovl2))
image.png

 

but 

(voicelead (harmonic-progression '(0 3 6 2) '(c major) :size 4 :step 2 :relative nil :variant 'r))

 

can generate one of two options. The second one is obviously better since it uses a common tone.  Even with ambitus-chord I'm not able to make it work consistently. 

 

image.png

 

image.png

 

If you have any thoughts I'd be happy to hear them. 

 

All the best,

Avner

Share this post


Link to post
Share on other sites

Julio, the CHORD-CLOSEST-PATH function is doing exacly that:

(chord-closest-path '(eb4g4b4) '(b3eb5g3 cs6e7gs3 b4f5g6 f7e5c2 d4f7e4 gs7e2a8))
image.png

Share this post


Link to post
Share on other sites

Hi Janusz, 

 

If I try this: 

 

(chord-closest-path '(b4g4e4c4) '(b4g4e4c4 c5a4e4f4 b4a4f4d4 b4g4e4d4))

 

It produces either 

image.png.3530e620778d5ac3479538522bd8497b.png

 

or 

 

image.png.e7ea4848ef590ee5ab29a8da3d0d1772.png

 

 

My question is why does it produce two variants and how can one make sure it always chooses the shortest path?

 

To me it seems like the second option is the correct one since the total half steps between all the voices is 6 (b-c, g-f, c-a) and in the first the total half steps between the voices is 8. 

 

Thanks!

Avner 

 

p.s. - if anyone's curious - Dmitri Tymoczko wrote a software that does minimal voice leading for music 21 in Python. It's available here - http://dmitri.mycpanel.princeton.edu/voiceleading_utilities.py

Edited by Avner Dorman
Error

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...