lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Extracting pitch names from music


From: Michael Ellis
Subject: Re: Extracting pitch names from music
Date: Thu, 9 Dec 2010 13:02:00 -0500

Putting the \midi block inside a separate \score block solved the audio doubling issue.  I could still use some suggestions regarding how to control the font properties of the NoteNames output.  With lyrics, I can do things like

\context {
     \Lyrics
            %% Pack stanzas a little closer vertically
            minimumVerticalExtent = #'(0 . 0)
         %% decrease lyric font size by 1 increment
     \override LyricText #'font-size = #-1
   }                                          

Thanks,
Mike


On Tue, Dec 7, 2010 at 3:40 PM, Michael Ellis <address@hidden> wrote:
Thanks Valentin, that's quite helpful.  I ended up taking an approach you suggested in a previous post to this list.  Using the NoteNames context with alternative note names seems to be doing pretty much everything I want. 

Here's a revised version of my script that works as desired:

% Moveable Do as lyrics example

% define solfege pitchnames
pitchnames = #`(
(do . ,(ly:make-pitch -1 0 NATURAL))
(re . ,(ly:make-pitch -1 1 NATURAL))
(mi . ,(ly:make-pitch -1 2 NATURAL))
    )

#(ly:parser-set-note-names parser pitchnames)

% Apparently, LilyPond reverts to dutch names when
% using the NoteNames context. The following 
% workaround was posted by V. Villenave at

newnames =
#`(("c" . "do")
   ("d" . "re")
   ("e" . "mi"))

myNoteNames =
#(lambda (grob)
   (let* ((default-name (ly:grob-property grob 'text))
          (new-name (assoc-get default-name newnames)))
         (ly:grob-set-property! grob 'text new-name)
   (ly:text-interface::print grob)))

% compose as though in C major
mynotes =  \relative do' {\key do \major do2 re4( mi4) }

% transpose to desired key
melody = \transpose do mi  { \mynotes }

% Produce score with solfege names as lyrics
\score {
    <<
    \new Voice = "myVoice" { 
\melody 
    }
    \context NoteNames \with {
       \override NoteName #'stencil = #myNoteNames
    } { \mynotes }
    
    >>
    }
\version "2.12.3"                              

This approach seems to work ok with a larger example where I defined all the chromatic solfege names.  The only issue I seem to be encountering in the larger example is an unintended doubling of voices on the midi output. Does the NoteNames engraver produce a midi stream by default?  If so, how can I turn it off?

My midi section looks like
\midi {
        %% voodoo that lets us specify instrument in melody
     \context {
       \Staff
       \remove "Staff_performer"
     }
     \context {
       \Voice
       \consists "Staff_performer" 
        }
    }              

Cheers,
Mike



On Tue, Dec 7, 2010 at 11:41 AM, Valentin Villenave <address@hidden> wrote:
On Tue, Dec 7, 2010 at 4:35 PM, Michael Ellis <address@hidden> wrote:
> It seems to me that the best solution would be to use LilyPond's built-in
> Scheme interpreter to extract the pitch names while the file is being
> processed. I've made some attempts to use map with ly:note-pitchname, but so
> far no success. This is probably because I know squat about Scheme,
> especially as used in LilyPond scripts.

Here's an attempt of a patch I recently made, that might give you some pointers:

diff --git a/scm/chord-name.scm b/scm/chord-name.scm
index 7f5909b..2853102 100644
--- a/scm/chord-name.scm
+++ b/scm/chord-name.scm
@@ -59,15 +59,38 @@
      (make-hspace-markup (if (= alteration SHARP) 0.2 0.1))
      ))))

+(define (note-names-vector alist)
+  "Extract note names from a pitchnames ALIST."
+  (let ((name-ls '()))
+    (map (lambda (x)
+          (let* ((pitch (cdr x))
+                 (alteration (ly:pitch-alteration pitch)))
+            (if (eq? alteration 0)
+                (set! name-ls (cons
+                               (string-capitalize (symbol->string (car x)))
+                               name-ls)))))
+         alist)
+    (list->vector (reverse name-ls))))
+
-(define-public (note-name->markup pitch lowercase?)
+(define-public (note-name->markup pitch lowercase? . input-language)
 "Return pitch markup for PITCH."
-  (make-line-markup
-   (list
-    (make-simple-markup
-     (conditional-string-downcase
-      (vector-ref #("C" "D" "E" "F" "G" "A" "B") (ly:pitch-notename pitch))
-      lowercase?))
-    (accidental->markup (ly:pitch-alteration pitch)))))
+  (let* ((get-pitchnames (lambda (x)
+                          (ly:assoc-get (string->symbol x)
+                                        language-pitch-names)))
+        (alist (get-pitchnames default-language)))
+    (if input-language
+       (cond ((string? input-language)
+              (set! alist (get-pitchnames input-language)))
+             ((boolean? input-language))
+             (set! alist pitchnames)))
+    (make-line-markup
+     (list
+      (make-simple-markup
+       (conditional-string-downcase
+       (vector-ref (note-names-vector alist)
+                   (ly:pitch-notename pitch))
+       lowercase?))
+      (accidental->markup (ly:pitch-alteration pitch))))))

Sorry for not being more helpful, if there are things you don't
understand I'll try and help you further.

Cheers,
Valentin.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]