#(define (normalize pitch)
   (if (>= (ly:pitch-alteration pitch) 1)
       (normalize (ly:pitch-transpose pitch (ly:make-pitch 0 1 -1)))
       (if (<= (ly:pitch-alteration pitch) -1)
           (normalize (ly:pitch-transpose pitch (ly:make-pitch 0 -1 1/2)))
           pitch)))

#(define (semitones->pitch st chord)
   (if (null? chord)
       (normalize (ly:make-pitch 0 0 (/ st 2)))
       (if (eqv? 0
                 (modulo (-
                          st
                          (ly:pitch-semitones (car chord)))
                         12))
           (let* ((ref-pitch (ly:make-pitch 0
                                            (ly:pitch-notename (car chord))
                                            (ly:pitch-alteration (car chord))))
                  (ref-st (ly:pitch-semitones ref-pitch))
                  (st-diff (- st ref-st)))
             (ly:make-pitch (/ st-diff 12)
                            (ly:pitch-notename (car chord))
                            (ly:pitch-alteration (car chord))))
           (semitones->pitch st (cdr chord)))))

#(define (defn-to-frets defn)
   (if (null? defn)
       defn
       (let ((string (cadar defn))
             (fret (cond ((eqv? (caar defn) 'open) 0)
                         ((eqv? (caar defn) 'place-fret) (caddar defn))
                         (else #f))))
         (if fret
           (cons (cons string fret) (defn-to-frets (cdr defn)))
           (defn-to-frets (cdr defn))))))

translateToChords =
#(define-music-function (fretboard-table tuning music) (hash-table? list? ly:music?)
   (define (iter music)
     (let ((elts (ly:music-property music 'elements))
           (elt (ly:music-property music 'element)))
       (if (music-is-of-type? music 'event-chord)
           (let* ((pitches (event-chord-pitches music))
                  (hash-key (cons tuning pitches))
                  (defn (hash-ref fretboard-table hash-key #f))
                  (dparts (if defn (defn-to-frets defn)))
                  (notes (event-chord-notes music))
                  (dur (if (not (null? notes)) (ly:music-property (car notes) 'duration))))
             (if defn
                 (let* ((notes (map
                                (lambda (def)
                                  (let* ((sno (car def))
                                         (rpi (list-ref tuning (1- sno)))
                                         (fret-no (cdr def))
                                         (root-st (ly:pitch-semitones rpi))
                                         (pitch (semitones->pitch (+ root-st fret-no)
                                                                  pitches)))
                                    (if (< fret-no 0)
                                        #f
                                        (make-music 'NoteEvent
                                                    'pitch pitch
                                                    'duration dur
                                                    'articulations
                                                    (list (make-music
                                                            'StringNumberEvent
                                                            'string-number
                                                            sno
                                                            'tweaks
                                                            '((stencil . #f))))))))
                                dparts))
                        (non-note-elts (filter (lambda (x) (not (music-is-of-type? x 'note-event)))
                                               elts)))
                   (ly:music-set-property! music 'elements
                                           (append (filter (lambda (x) x) notes)
                                                   non-note-elts)))))
           (begin
            (if (not (null? elt))
                (iter elt))
            (for-each iter elts)))))
   (iter music)
   music)
