This seems like a pretty aggressive ask for AI at this stage, particularly for AI vision. But I have no doubt it won't be long before AI is able to do it perfectly. AI progress with various problematic areas has been palpable. I've noticed that in the past year, AI has gone from not really knowing LilyPond to writing entire scheme functions that compile error-free and function as requested. (It's the same for another esoteric language I use, OpenSCAD, where it used generate wrong code that looked like C, but now it writes almost correct code every time.)

Below is one example (Gemini 2.5 Pro) where I requested a function that adds staccato to every note. I could have written it  myself in some hours, but instead I had it in minutes. It's also able to make small modifications without messing up what's there, such as when I requested it handle staccatissimo, or to allow putting the dots up or down, etc. Lately, it's been remembering past conversations and tailoring replies according to what I'm working on as a whole. It can be really unnerving when it's right on the money.


Regards,
Curt

%%% Begin AI-generated \addStaccato
#(define (has-articulation? music-list)
   "Return #t if any object in music-list already has staccato articulation."
   (any (lambda (obj)
          (let ((type (ly:music-property obj 'articulation-type)))
            (or (eq? type 'staccato)
                (eq? type 'staccatissimo))))
        music-list))

#(define (add-staccato-recurse m forced-dir)
   (let ((name (ly:music-property m 'name)))
     (cond
      ; Case 1: EventChord
      ((eq? name 'EventChord)
       (let ((arts (ly:music-property m 'articulations))
             (elts (ly:music-property m 'elements)))
         (if (not (or (has-articulation? arts) (has-articulation? elts)))
             (let ((new-art (make-music 'ArticulationEvent 'articulation-type 
'staccato)))
               ; Apply direction if specific (not 0)
               (if (not (= forced-dir 0))
                   (set! (ly:music-property new-art 'direction) forced-dir))
               (set! (ly:music-property m 'articulations)
                     (cons new-art arts)))))
       m)
      ; Case 2: NoteEvent
      ((eq? name 'NoteEvent)
       (let ((arts (ly:music-property m 'articulations)))
         (if (not (has-articulation? arts))
             (let ((new-art (make-music 'ArticulationEvent 'articulation-type 
'staccato)))
               ; Apply direction if specific (not 0)
               (if (not (= forced-dir 0))
                   (set! (ly:music-property new-art 'direction) forced-dir))
               (set! (ly:music-property m 'articulations)
                     (cons new-art arts)))))
       m)
      ; Case 3: Recursion
      (else
       (let ((elt (ly:music-property m 'element))
             (elts (ly:music-property m 'elements)))
         (if (ly:music? elt)
             (ly:music-set-property! m 'element (add-staccato-recurse elt 
forced-dir)))
         (if (pair? elts)
             (ly:music-set-property! m 'elements
               (map (lambda (x) (add-staccato-recurse x forced-dir)) elts)))
         m)))))

% Create the user-facing music function with optional direction argument.
addStaccato = #(define-music-function (direction music) ((ly:dir? 0)ly:music?)
  "Applies staccato. Usage: \\addStaccato \\music OR \\addStaccato #UP \\music"
  (add-staccato-recurse music direction))
%%% End

On 1/6/26 09:52, Matthew Pierce wrote:
I asked Grok to self-design a prompt for accurately converting sheet music images into Lilypond code. Early results are promising.

My test: I showed Grok a screenshotted page from a cello arrangement I recently constructed in Lilypond, gave it the prompt below, compiled the code it suggested, and compared the results

Results: The visual match was astonishingly good, even though Grok's generated code is different from mine in various ways.

The only major difference was the final system being kicked to the next page by Grok's code. I suspect this may have been caused by a slight cropping at the bottom of the page in my screenshotted image.

This prompt might be a great shortcut for importing existing sheet music into Lilypond code.

Try it on the LLM of your choice. Happy testing!

Prompt follows:

"You are an expert in LilyPond notation and optical music recognition. Given the attached sheet music image, meticulously reverse-engineer the LilyPond code that would reproduce it with the highest possible visual fidelity. Prioritize absolute precision and accuracy in every aspect of the engraving—including exact note placements, stem directions, beam groupings, slur shapes and positions, dynamic markings, articulations, text annotations, staff layout, spacing, and any special elements like scordatura diagrams or irregular meters—over any considerations of speed or efficiency. Proceed slowly and methodically: first, perform a exhaustive layer-by-layer visual analysis of the image, documenting every observable detail (e.g., clef type, key signature sharps/flats, time signature symbol, pitch positions relative to the staff, durations, ties, hairpins, bowings, and markup coordinates). Cross-reference with music theory and LilyPond syntax to resolve ambiguities. Only after this thorough dissection should you generate the complete LilyPond code, including header, global settings, voices, and layout overrides as needed to match the image pixel-for-pixel where possible. If uncertainties arise, note them and propose the most accurate interpretation based on standard engraving practices."

Reply via email to