On Fri, Dec 20, 2024 at 1:08 PM Frédéric <ufosp...@gmail.com> wrote:

> Thank you all. I wanted to know if there was already something
> available but I will build a python script for it. I'm also under
> Linux and pretty used to that.
>
> Here is an example of input:
> lower = \relative f, {
>  \key f \major
>  \time 4/4
>  <f f'>2 r
>  | <f f'> r
>  | <c c'>1
>  | <f f'>2 r
>  | <d d'>1
>  | <e e'>2 <c c'>
>  | <f f'> r
>  | <bes, bes'>2. <a a'>4
>  | <g g'>1
>  | <c c'>
>  | <f f'>4 r r <bes g'>
>  | r8 c( g' bes c bes g bes)
>  | <f a>4 r <f, f'> r
> }
>

Since you're going to write a Python script, I figure I can share what I've
done so far on mine.  It uses python-ly so you need to do a `pip install
python-ly` first before you run it.  It makes three very big assumptions:

1) That you're using an absolute pitch of some sort.  Relative pitch is
going to be a problem, I think.
2) That all chords have exactly two notes, and
3) That the first note is the lowest in the chord.

You can change relative pitch to absolute in Frescobaldi, which actually
uses python-ly to do it, so you could incorporate that into your script.

--
Knute Snortum
import ly.lex
import ly.lex.lilypond

with open('test.ly') as f:
    txt = f.read()

s = ly.lex.state("lilypond")
g = s.tokens(txt)

for t in g:
    if isinstance(t, ly.lex.lilypond.ChordStart):
        notes = []
        note_name = ''

        for tt in g:
            if isinstance(tt, ly.lex.lilypond.ChordEnd):
                notes.append(note_name)

                if len(notes) != 2:
                    print(f"\n% *** don't know how to deal with this chord, length({len(notes)})")
                else:
                    tt = next(g)
                    length = ''
                    hold = ''

                    if isinstance(tt, ly.lex.lilypond.Length):
                        length = str(tt)
                    else:
                        hold = str(tt)
                    
                    print(f"<<{{{notes[1]}{length}}} \\\\ {{{notes[0]}{length}}}>>", end='')
                    print(hold, end='')
                break

            if isinstance(tt, ly.lex.lilypond.Note):
                note_name = str(tt)
            elif isinstance(tt, ly.lex.lilypond.Octave):
                note_name += str(tt)
            elif isinstance(tt, ly.lex._token.Space):
                notes.append(note_name)
                note_name = ''

    else:
        print(t, end='')

print()

Reply via email to