In response to Russell Snyder’s request for my code to generate double harmonics (natural) on the viola d’amore, I’ve abstracted the following from my piece 24-7: freedom fried. This was written for Garth Knox on the viola d’amore and was featured on a 2010 Wergo DVD. Here’s an extract:

Apologies for the light commenting only in the code below. I’ve not tested this for other string instruments but it should be possible to pass new tuning data along with new nodes and get it to work. The function itself should be useful, as it returns lists of lists of harmonics for each string, but the CMN code parses this list and creates notated output for reference (e.g. harmonics)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; File:             24-7-harmonics.lsp
;;;
;;; Class Hierarchy:  None
;;;
;;; Version:          1.0
;;;
;;; Project:          slippery chicken (algorithmic composition)
;;;
;;; Purpose:          To generate all the possible double harmonics (natural)
;;;                   on the 7-string viola d'amore. Abstracted out of my 24-7:
;;;                   freedom fried project. Could be adapted for other string
;;;                   instruments perhaps.
;;;
;;; Author:           Michael Edwards: m@michael-edwards.org
;;;
;;; Creation date:    24/10/14
;;;
;;; $$ Last modified: 15:32:35 Fri Oct 24 2014 BST
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(in-package :sc)

(defun double-harmonics (&key
                           (tuning '(d5 a4 f4 df4 af3 d3 a2))
                           ;; Pairs where first is semitones above open
                           ;; string where the node is, and second is the
                           ;; partial number. NB not complete, just the
                           ;; easy ones
                           (all-nodes
                            '((3 6) (4 5) (5 4) (7 3))))
  ;; All the possible double harmonics in terms
  ;; of fingerings  
  (let ((all-double-harmonics
         (loop for first from 1 to 4 append
              (loop for second from 1 to 4 collect
                   (list first second))))
        (tuning-rev (reverse tuning)))
    ;; This looks something like (((g3 d4) ((bf3 d6) (fs4 fs6)) ...) ((d4
    ;; a5) ...  but of course the pitches are pitch objects.
    (loop 
       for string1 in tuning-rev
       for string2 in (cdr tuning-rev)
       for p1 = (make-pitch string1)
       for p2 = (make-pitch string2)
       collect
         (cons
          (list p1 p2)
          (loop 
             for fingerings in all-double-harmonics ;; e.g. (1 1)
             for f1 = (first fingerings)
             for f2 = (second fingerings)
             for n1 = (nth (1- f1) all-nodes) ;; e.g. (3 6)
             for n2 = (nth (1- f2) all-nodes)
             for n1n = (first n1)
             for n1p = (second n1)
             for n2n = (first n2)
             for n2p = (second n2)
             collect
               (list
                (list (transpose p1 n1n) 
                      (make-pitch (* n1p (frequency p1)))
                      f1)
                (list (transpose p2 n2n) 
                      (make-pitch (* n2p (frequency p2)))
                      f2)))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(in-package :cmn)

(cmn (output-file "/temp/harmonics.eps")
     (size 16)
     (all-output-in-one-file t)
     (automatic-octave-signs t)
     (always-show-clefs nil)
     (page-width 21) (page-height 29.7)
     (line-separation 4)
     (staff 
      (engorge
       (loop 
           for string-pair in (sc::double-harmonics)
           for string1 = (first (first string-pair))
           for string2 = (second (first string-pair))
           do 
             ;; (print string1)
             (format t "~%~%Strings ~a ~a" (sc::id string1) (sc::id string2))
           append 
             (append 
              (list
               alto
               (chord
                (sc::get-cmn-data string1 :just-list nil)
                (sc::get-cmn-data string2 :just-list nil)
                w) 
               (bar))
              (loop 
                  for harmonics in (cdr string-pair)
                  for s1 = (first harmonics)
                  for s2 = (second harmonics)
                  for s1n = (first s1)
                  for s1p = (second s1)
                  for f1 = (third s1)
                  for s2n = (first s2)
                  for s2p = (second s2)
                  for f2 = (third s2)
                  and i from 0 
                  do
                    (format t "~&(~a ~a) (~a ~a)" 
                            (sc::id s1n) (sc::id s1p) 
                            (sc::id s2n) (sc::id s2p))
                  append
                    (list
                     (unless (zerop i)
                       (clef alto (scale .7 .7)))
                     (chord (sc::get-cmn-data s1n :just-list nil)
                            (sc::get-cmn-data s2n :just-list nil)
                            h
                            (note-head :diamond)
                            (no-stem)
                            (fingering f2 f1))
                     (clef treble (scale .7 .7))
                     (chord (sc::get-cmn-data s1p :just-list nil)
                            (sc::get-cmn-data s2p :just-list nil)
                            (no-stem))
                     (bar)))
              (list (line-mark)))))))
                    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; EOF


Share Button