Another new tadpole?

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Another new tadpole?

Wols Lists
 Hi,

I've just joined the list too :-)

I know I've tried to do stuff in the past, but my problem has been that
I need some handholding to get started. I've got various things I want
to do, but my scheme-fu and C++fu is nil. Can people give me some
guidance on where and how to start? I'm an experienced programmer, but
my skills are C, databases and DataBasic.

The current thing I'm after doing is adding a capo option to the
chordname engraver, but I've had a look at it (the engraver) and just
can't see the wood for the trees. My next project after that would be a
fingering engraver for brass (valve and slide).

I'm running lilypond over gentoo, so everything should build fine from
git, but I'm not sure it quite worked last time I tried a build.

Not quite sure where I go from here ...

Cheers,
Wol

---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Trevor D-2

Wols Lists wrote Sunday, August 08, 2010 10:43 PM

> I've just joined the list too :-)

:)

> I know I've tried to do stuff in the past, but my problem has been
> that
> I need some handholding to get started. I've got various things I
> want
> to do, but my scheme-fu and C++fu is nil. Can people give me some
> guidance on where and how to start? I'm an experienced programmer,
> but
> my skills are C, databases and DataBasic.

Carl is the frog meister, but he's on vacation at the moment.
I expect to see him on the list soon, and I'm sure he'll
guide you along.

> The current thing I'm after doing is adding a capo option to the
> chordname engraver, but I've had a look at it (the engraver) and
> just
> can't see the wood for the trees. My next project after that would
> be a
> fingering engraver for brass (valve and slide).

These sound like good additions.

> I'm running lilypond over gentoo, so everything should build fine
> from
> git, but I'm not sure it quite worked last time I tried a build.

You'll definitely need to build LilyPond from git to
work on engravers, so ...

> Not quite sure where I go from here ...

... refresh git and try another build.  I suggest
you do

make clean
./autogen.sh
make

and see if that gives you a working binary.  Make will take
quite a while, several hours probably.

Trevor



---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Wols Lists
 On 08/08/10 23:20, Trevor Daniels wrote:

>
> You'll definitely need to build LilyPond from git to
> work on engravers, so ...
>
>> Not quite sure where I go from here ...
>
> ... refresh git and try another build.  I suggest
> you do
>
> make clean
> ./autogen.sh
> make
>
> and see if that gives you a working binary.  Make will take
> quite a while, several hours probably.
>
$ out/bin/lilypond
GNU LilyPond 2.13.30

It rather flies with a Phenom X3 and 4Gb ram :-)

But it's bedtime (GMT+1 here), so if you can give me any further leads
(or do I have to just dive into the engraver and say "help, what does
this mean"), I'll follow it up tomorrow.

TIA

Cheers,
Wol

---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Trevor D-2

Wols Lists wrote Sunday, August 08, 2010 11:52 PM


> It rather flies with a Phenom X3 and 4Gb ram :-)

OK, you're all set.

> But it's bedtime (GMT+1 here), so if you can give me any further
> leads
> (or do I have to just dive into the engraver and say "help, what
> does
> this mean"), I'll follow it up tomorrow.

Yes, diving into the chords engraver is the next step.

Carl wrote a few generic words on engravers in the CG
which will give you a start.  Then read through the
engraver to understand how it works, asking questions
on the list as soon as you can't find an answer yourself
within, say, 10 minutes thinking.  Your C experience will
help.  Watch out for macros (in uppercase); see what they
do.  git grep will help you find things.  When you have a
feel for what is happening you can begin to plan what you
need to do.  Hopefully Carl will be back before then and
can take over from me.

It's midnight here too, so I'm off to bed myself shortly.

Trevor



---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Wols Lists
 On 09/08/10 00:05, Trevor Daniels wrote:

>
> Yes, diving into the chords engraver is the next step.
>
> Carl wrote a few generic words on engravers in the CG
> which will give you a start.  Then read through the
> engraver to understand how it works, asking questions
> on the list as soon as you can't find an answer yourself
> within, say, 10 minutes thinking.  Your C experience will
> help.  Watch out for macros (in uppercase); see what they
> do.  git grep will help you find things.  When you have a
> feel for what is happening you can begin to plan what you
> need to do.  Hopefully Carl will be back before then and
> can take over from me.
>
Okay. I've looked through chord-name-engraver.cc, and I think I've
understood roughly what's going on. It looks like the main thing I've
got to change is Chord_name_engraver::process_music(). As far as I can
see, this is building up a list of note pitches in the variable
"pitches" and then passing it to a function to convert it to a chord name.

So what I need to do, is create a new variable "capo_pitches", and just
as pitches are assigned to "pitches", I need to transpose them and
assign them to "capo_pitches". I can then create "capo_markup", which
will (if I've understood the code correctly) contain a text description
of the transposed chord. So I now have - hopefully - "markup" == eg "Gm"
giving me "capo_markup" == "Em" if capo is 3. I now need
chord_name_->set_property("text", "markup ( capo_markup )" )

The other thing I need to do is write a new engraver ...

I've tried to look at the key signature engraver, but that doesn't seem
to be so simple (I'm not surprised ...). What I need to do is have some
lilypond syntax "\capo 3 vertical|horizontal", with it defaulting to
horizontal. This will then need to get the key signature and print
(assuming a key of G minor, the example in front of me) "Capo 3 (Em)",
transposing the key down three semitones. It'll also need to leave the 3
somewhere (along with vertical/horizontal), so the chord engraver knows
what to do. Wherever it stores the transposition, should that default to
null or 0?

Okay. Where do I start with writing my new engraver? And have I got my
changes to chord-name-engraver close? One of the things that gets me
(dunno if it's common practice, it isn't to me) is the almost complete
lack of comments in the code. What I'll probably do is write up what I'm
doing as I do it, and heavily comment my engraver so that even if the
comments don't make it into production code, they can make documentation
as a "sample engraver".

Cheers,
Wol


---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Trevor D-2

Wols Lists wrote Monday, August 09, 2010 9:30 PM

Let me say up-front I'm getting a little out of my depth
now, having never written an engraver myself ... and
Carl hasn't showed up yet.  And I'm not a guitar player,
so I may be missing something obvious in my comments,
But here goes - if anyone else can offer better advice
please step in.


> On 09/08/10 00:05, Trevor Daniels wrote:
>>
>> Yes, diving into the chords engraver is the next step.
>>
>>  When you have a
>> feel for what is happening you can begin to plan what you
>> need to do.
>>
> Okay. I've looked through chord-name-engraver.cc, and I think I've
> understood roughly what's going on. It looks like the main thing
> I've
> got to change is Chord_name_engraver::process_music(). As far as I
> can
> see, this is building up a list of note pitches in the variable
> "pitches" and then passing it to a function to convert it to a
> chord name.

This sounds right to me.

> So what I need to do, is create a new variable "capo_pitches", and
> just
> as pitches are assigned to "pitches", I need to transpose them and
> assign them to "capo_pitches". I can then create "capo_markup",
> which
> will (if I've understood the code correctly) contain a text
> description
> of the transposed chord. So I now have - hopefully - "markup" ==
> eg "Gm"
> giving me "capo_markup" == "Em" if capo is 3. I now need
> chord_name_->set_property("text", "markup ( capo_markup )" )

So far so good, but I'm beginning to wonder if this is not
duplicating something...

> The other thing I need to do is write a new engraver ...

Hhm.  Why is that?  Would that be better than modifying
the existing chord name engraver to be aware of capos (capi?).

> I've tried to look at the key signature engraver, but that doesn't
> seem
> to be so simple (I'm not surprised ...). What I need to do is have
> some
> lilypond syntax "\capo 3 vertical|horizontal", with it defaulting
> to
> horizontal.

This sounds like a new context property set in the ChordName
context and used by the ChordName engraver to decide whether
to transpose and by how much.

> This will then need to get the key signature and print
> (assuming a key of G minor, the example in front of me) "Capo 3
> (Em)",
> transposing the key down three semitones. It'll also need to leave
> the 3
> somewhere (along with vertical/horizontal), so the chord engraver
> knows
> what to do. Wherever it stores the transposition, should that
> default to
> null or 0?

I'm getting puzzled now.  \transpose can already be invoked to
change chord names, can't it?  What functionality does
it lack that you need?  (Sorry if the answer's obvious - I'm not
a guitar player.)  I can see the capo is not fully supported in
fret diagrams.  AFAICS this currently has to be provided for every
fret diagram.  But if you only want chord names perhaps a slightly
different way of invoking \transpose would suffice?

> Okay. Where do I start with writing my new engraver? And have I
> got my
> changes to chord-name-engraver close? One of the things that gets
> me
> (dunno if it's common practice, it isn't to me) is the almost
> complete
> lack of comments in the code. What I'll probably do is write up
> what I'm
> doing as I do it, and heavily comment my engraver so that even if
> the
> comments don't make it into production code, they can make
> documentation
> as a "sample engraver".

Assuming you really do need a new engraver this is where
I have to hand over to someone more competent.  But a commented
engraver would be a useful addition to the CG.

> Wol

Trevor



---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Carl Sorensen



On 8/9/10 5:18 PM, "Trevor Daniels" <[hidden email]> wrote:

>
>
> Wols Lists wrote Monday, August 09, 2010 9:30 PM
>
> Let me say up-front I'm getting a little out of my depth
> now, having never written an engraver myself ... and
> Carl hasn't showed up yet.  And I'm not a guitar player,
> so I may be missing something obvious in my comments,
> But here goes - if anyone else can offer better advice
> please step in.

I'm back, but my Lilypond time will be extremely limited over the next three
weeks, so any help that others can give will be greatly appreciated.  And I
appreciate your helping out Wol and William in my absence.

>
>
>> On 09/08/10 00:05, Trevor Daniels wrote:
>>>
>>> Yes, diving into the chords engraver is the next step.
>>>
>>>  When you have a
>>> feel for what is happening you can begin to plan what you
>>> need to do.
>>>
>> Okay. I've looked through chord-name-engraver.cc, and I think I've
>> understood roughly what's going on. It looks like the main thing
>> I've
>> got to change is Chord_name_engraver::process_music(). As far as I
>> can
>> see, this is building up a list of note pitches in the variable
>> "pitches" and then passing it to a function to convert it to a
>> chord name.
>
> This sounds right to me.

Yes, this is so.

>
>> So what I need to do, is create a new variable "capo_pitches", and
>> just
>> as pitches are assigned to "pitches", I need to transpose them and
>> assign them to "capo_pitches". I can then create "capo_markup",
>> which
>> will (if I've understood the code correctly) contain a text
>> description
>> of the transposed chord. So I now have - hopefully - "markup" ==
>> eg "Gm"
>> giving me "capo_markup" == "Em" if capo is 3. I now need
>> chord_name_->set_property("text", "markup ( capo_markup )" )

Not quite.  It's not a text description, but actually a markup description.
The property name is "text", but the result from calling the scheme
procedure stored in the context property chordNameFunction returns a markup.

Better I think to just have line 95 change to something like

SCM raw_pitch = n->get_property ("pitch");
SCM p = raw_pitch->transposed (Pitch (0, 0, capo_semitones));

Now you have p transposed, and everything should work properly, IIUC.

>
> So far so good, but I'm beginning to wonder if this is not
> duplicating something...
>
>> The other thing I need to do is write a new engraver ...
>
> Hhm.  Why is that?  Would that be better than modifying
> the existing chord name engraver to be aware of capos (capi?).
>

I'm guessing that you're wanting a capo_indicating_engraver to write the
statement that tells you what fret to put the capo on, and indicates the key
in the "capo" worldview.  I don't think you should need to do the key
signature engraver.  Something like the metronome engraver is probably a
better pattern.

>> I've tried to look at the key signature engraver, but that doesn't
>> seem
>> to be so simple (I'm not surprised ...). What I need to do is have
>> some
>> lilypond syntax "\capo 3 vertical|horizontal", with it defaulting
>> to
>> horizontal.

If you really need a new engraver, then you'll also need to create a new
event (a capoEvent) that both the Capo engraver and the ChordName engraver
will need to listen to.  You might want to consider Trevor's suggestion, of
just defining a new context property.

>
> This sounds like a new context property set in the ChordName
> context and used by the ChordName engraver to decide whether
> to transpose and by how much.
>
>> This will then need to get the key signature and print
>> (assuming a key of G minor, the example in front of me) "Capo 3
>> (Em)",
>> transposing the key down three semitones. It'll also need to leave
>> the 3
>> somewhere (along with vertical/horizontal), so the chord engraver
>> knows
>> what to do. Wherever it stores the transposition, should that
>> default to
>> null or 0?

No, you don't "leave the 3 somewhere".  You have an event that both the Capo
engraver and the ChordName engraver listen to.  Then the ChordName engraver
puts the 3 in the appropriate place.  And the Capo engraver creates the
appropriate output.

Just out of curiosity, what does vertical/horizontal do?


>
> I'm getting puzzled now.  \transpose can already be invoked to
> change chord names, can't it?  What functionality does
> it lack that you need?  (Sorry if the answer's obvious - I'm not
> a guitar player.)  I can see the capo is not fully supported in
> fret diagrams.  AFAICS this currently has to be provided for every
> fret diagram.  But if you only want chord names perhaps a slightly
> different way of invoking \transpose would suffice?
>
>> Okay. Where do I start with writing my new engraver? And have I
>> got my
>> changes to chord-name-engraver close? One of the things that gets
>> me
>> (dunno if it's common practice, it isn't to me) is the almost
>> complete
>> lack of comments in the code. What I'll probably do is write up
>> what I'm
>> doing as I do it, and heavily comment my engraver so that even if
>> the
>> comments don't make it into production code, they can make
>> documentation
>> as a "sample engraver".
>
> Assuming you really do need a new engraver this is where
> I have to hand over to someone more competent.  But a commented
> engraver would be a useful addition to the CG.

I agree wholeheartedly.   The real problem (IMO) with engravers is that he
general structure of an engraver is not documented anywhere very well
(although we're adding some stuff to the CG).  Most of the comments that
would help to understand an engraver are unneeded once you understand an
engraver structure (e.g. we don't really want to have a comment in every
engraver describing what stop_translation_timestep (), process_music (),
etc. do -- that would just clutter up the code).  Once you understand
process_music (), you only really want comments related to the *specific*
procsess_for this engraver, and with good variable names, it's not really
that hard in most cases to figure most of it out.

But the overall structure is *very* hard to get figured out, in my
experience.

Thanks,

Carl


---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Capo-ChordNames

Carl Sorensen
In reply to this post by Wols Lists
If you are fine to have the Capo chord names and the non-capo chord names
stacked, then it's possible to do something like:

myChords = \chordmode {
  c1 g f:7 c
}"

<<
  \new ChordNames = "capoNames" {
      \transpose c b {
        \myChords  
      }
  }
  \new ChordNames = "originalNames" {
    \myChords
  }
>>


Which is what Trevor was suggesting.

And a music function could probably be written to make all of that happen
automatically

e.g.

\capo 3 \myChords

could be used as syntax to do the transposition and create both ChordNames
contexts.

Of course, this wouldn't handle the horizontal setting; to do that you
really would need to modify the ChordNames engraver.

HTH,

Carl


---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Wols Lists
In reply to this post by Trevor D-2
 On 10/08/10 00:18, Trevor Daniels wrote:
> I'm getting puzzled now.  \transpose can already be invoked to
> change chord names, can't it?  What functionality does
> it lack that you need?  (Sorry if the answer's obvious - I'm not
> a guitar player.)  I can see the capo is not fully supported in
> fret diagrams.  AFAICS this currently has to be provided for every
> fret diagram.  But if you only want chord names perhaps a slightly
> different way of invoking \transpose would suffice?
I'll reply more thoroughly to Carl's emails, but what I'm doing is
annotating piano music with guitar chords.

So given my example of a piece in g-minor, it prints the piano music and
the chords in g-minor. Fine. BUT as the chord engraver prints the
chord-names in g-minor, it needs to transpose them on the fly and print
them in e-minor AS WELL.

Carl's response makes me think I can call transpose from the chord
engraver, that's great, but I can't see any way of doing that from a
lily score at the moment. And imho it feels like this does belong in the
engraver, anyway.

Cheers,
Wol

---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Capo-ChordNames

Wols Lists
In reply to this post by Carl Sorensen
 On 10/08/10 01:05, Carl Sorensen wrote:

> If you are fine to have the Capo chord names and the non-capo chord names
> stacked, then it's possible to do something like:
>
> myChords = \chordmode {
>   c1 g f:7 c
> }"
>
> <<
>   \new ChordNames = "capoNames" {
>       \transpose c b {
>         \myChords  
>       }
>   }
>   \new ChordNames = "originalNames" {
>     \myChords
>   }
>
> Which is what Trevor was suggesting.
>
> And a music function could probably be written to make all of that happen
> automatically
>
> e.g.
>
> \capo 3 \myChords
>
> could be used as syntax to do the transposition and create both ChordNames
> contexts.
>
> Of course, this wouldn't handle the horizontal setting; to do that you
> really would need to modify the ChordNames engraver.
>
Ah... but the horizontal setting is the norm. Sounds like you've guessed
correctly what I meant by vertical|horizontal. And the transposed chord
is ALWAYS parenthesised - how easy is that in a music function? So let's
say I'm in the key of C, capo=3 (weird example I know, but never mind),
and I want to actually have a C chord. It normally prints as "C (A)",
but in vertical mode it would print as

C
(A)

(centred, of course).

I'll take the engraver route, and hope I don't need TOO much
hand-holding (cf Graham's talk :-) If it gets me into Scheme and C++
I'll be well pleased.

I'll look at your long email, probably respond, and then hack at it and
come back with more questions :-)

Cheers,
Wol

---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Capo-ChordNames

Carl Sorensen
On 8/10/10 7:18 AM, "Wols Lists" <[hidden email]> wrote:

>  On 10/08/10 01:05, Carl Sorensen wrote:
>> If you are fine to have the Capo chord names and the non-capo chord names
>> stacked, then it's possible to do something like:
>>
>> myChords = \chordmode {
>>   c1 g f:7 c
>> }"
>>
>> <<
>>   \new ChordNames = "capoNames" {
>>       \transpose c b {
>>         \myChords
>>       }
>>   }
>>   \new ChordNames = "originalNames" {
>>     \myChords
>>   }
>>
>> Which is what Trevor was suggesting.
>>
>> And a music function could probably be written to make all of that happen
>> automatically
>>
>> e.g.
>>
>> \capo 3 \myChords
>>
>> could be used as syntax to do the transposition and create both ChordNames
>> contexts.
>>
>> Of course, this wouldn't handle the horizontal setting; to do that you
>> really would need to modify the ChordNames engraver.
>>
> Ah... but the horizontal setting is the norm.

OK, sounds like engraver work is the thing, then.

> Sounds like you've guessed
> correctly what I meant by vertical|horizontal. And the transposed chord
> is ALWAYS parenthesised - how easy is that in a music function?

Actually, it would be quite easy, since there are parenthesize commands and
map functions.  But since horizontal is the default behavior you want,
you'll need to change the engraver.

> So let's
> say I'm in the key of C, capo=3 (weird example I know, but never mind),
> and I want to actually have a C chord. It normally prints as "C (A)",
> but in vertical mode it would print as
>
> C
> (A)
>
> (centred, of course).
>
> I'll take the engraver route, and hope I don't need TOO much
> hand-holding (cf Graham's talk :-)

Note that the amount of hand-holding is not the thing that determines
whether the mentoring is successful or not; the determination of the user to
stay on board and contribute is what defines things.  You've been around
long enough that I'm satisfied you'll stay with it, so virtually any amount
of hand-holding is likely to be a net gain.

> If it gets me into Scheme and C++
> I'll be well pleased.

At the moment, probably not too much Scheme (although you might want to try
writing the CapoEngraver in Scheme).

>
> I'll look at your long email, probably respond, and then hack at it and
> come back with more questions :-)

Sounds great.

But there's some wrong advice in my email, because I wasn't thinking about
having *both* chord names created by the engraver.  You'll want to follow up
more on your original approach, i.e. having both pitches and capo_pitches.
Then you'll need to call the chordNameFunction twice, once with pitches,
bass, inversion and once with capo_pitches, capo_bass, capo_inversion.  Then
you'll need to combine the two markups into one, probably with another
scheme call.

vertical/horizontal should be a context property, rather than a keyword.

I'm not sure yet about capo_fret.  It could be a context property, or it
could be part of the structure of a capoEvent.

For getting started, I'd recommend making it a context property, and
avoiding the use of a capoEvent.

Then you'd do something like

\set ChordNames.capoFret = #3
\set ChordNames.capoOffset = #'horizontal

to set up the engraver properly.

HTH,

Carl


---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Wols Lists
In reply to this post by Carl Sorensen
 On 10/08/10 00:54, Carl Sorensen wrote:

>>>
>>> Okay. I've looked through chord-name-engraver.cc, and I think I've
>>> understood roughly what's going on. It looks like the main thing
>>> I've
>>> got to change is Chord_name_engraver::process_music(). As far as I
>>> can
>>> see, this is building up a list of note pitches in the variable
>>> "pitches" and then passing it to a function to convert it to a
>>> chord name.
>> This sounds right to me.
> Yes, this is so.
>
Okay. So I'm on the right track.

>>> So what I need to do, is create a new variable "capo_pitches", and
>>> just
>>> as pitches are assigned to "pitches", I need to transpose them and
>>> assign them to "capo_pitches". I can then create "capo_markup",
>>> which
>>> will (if I've understood the code correctly) contain a text
>>> description
>>> of the transposed chord. So I now have - hopefully - "markup" ==
>>> eg "Gm"
>>> giving me "capo_markup" == "Em" if capo is 3. I now need
>>> chord_name_->set_property("text", "markup ( capo_markup )" )
> Not quite.  It's not a text description, but actually a markup description.
> The property name is "text", but the result from calling the scheme
> procedure stored in the context property chordNameFunction returns a markup.
>
> Better I think to just have line 95 change to something like
>
> SCM raw_pitch = n->get_property ("pitch");
> SCM p = raw_pitch->transposed (Pitch (0, 0, capo_semitones));
>
> Now you have p transposed, and everything should work properly, IIUC.
Great. I assume to transpose down I need a negative, so if capo is 3, I
either print 3 and set capo_semitones to -3, or I pass -capo_semitones.
Either way, I'll cross that bridge when I get to it.

Don't forget I need both "raw_pitch" and "p", though. My pseudo-code may
have misled (the joys of multiple meanings of parentheses :-). So I'll
be asking how to combine markup next :-) because the output needs to be
eg "C(A)".

>> So far so good, but I'm beginning to wonder if this is not
>> duplicating something...
>>
>>> The other thing I need to do is write a new engraver ...
>> Hhm.  Why is that?  Would that be better than modifying
>> the existing chord name engraver to be aware of capos (capi?).
>>
> I'm guessing that you're wanting a capo_indicating_engraver to write the
> statement that tells you what fret to put the capo on, and indicates the key
> in the "capo" worldview.  I don't think you should need to do the key
> signature engraver.  Something like the metronome engraver is probably a
> better pattern.
>
Spot on again. Okay, I'll investigate that engraver and see how I can
revamp it as a capo_indicating_engraver.

>>> I've tried to look at the key signature engraver, but that doesn't
>>> seem
>>> to be so simple (I'm not surprised ...). What I need to do is have
>>> some
>>> lilypond syntax "\capo 3 vertical|horizontal", with it defaulting
>>> to
>>> horizontal.
> If you really need a new engraver, then you'll also need to create a new
> event (a capoEvent) that both the Capo engraver and the ChordName engraver
> will need to listen to.  You might want to consider Trevor's suggestion, of
> just defining a new context property.
>
Bear in mind I've just jumped into the pond and am already out of my
depth :-) How do I create a context property? And if I go down that
route how will I get the capo indicator to print at the start of the
piece? Basically, my idea is that the user will simply put the capo
command with the key signature command in their .ly file, and that will
trigger the capo indicator plus automatically transpose any chord-names
they choose to print.

>> This sounds like a new context property set in the ChordName
>> context and used by the ChordName engraver to decide whether
>> to transpose and by how much.
>>> This will then need to get the key signature and print
>>> (assuming a key of G minor, the example in front of me) "Capo 3
>>> (Em)",
>>> transposing the key down three semitones. It'll also need to leave
>>> the 3
>>> somewhere (along with vertical/horizontal), so the chord engraver
>>> knows
>>> what to do. Wherever it stores the transposition, should that
>>> default to
>>> null or 0?
> No, you don't "leave the 3 somewhere".  You have an event that both the Capo
> engraver and the ChordName engraver listen to.  Then the ChordName engraver
> puts the 3 in the appropriate place.  And the Capo engraver creates the
> appropriate output.
>
> Just out of curiosity, what does vertical/horizontal do?
>
As you guessed, places the two chords side-by-side or vertically
stacked. Can an event return two values, so the chord name engraver gets
the transposition and stacking?

>> I'm getting puzzled now.  \transpose can already be invoked to
>> change chord names, can't it?  What functionality does
>> it lack that you need?  (Sorry if the answer's obvious - I'm not
>> a guitar player.)  I can see the capo is not fully supported in
>> fret diagrams.  AFAICS this currently has to be provided for every
>> fret diagram.  But if you only want chord names perhaps a slightly
>> different way of invoking \transpose would suffice?
>>
>>> Okay. Where do I start with writing my new engraver? And have I
>>> got my
>>> changes to chord-name-engraver close? One of the things that gets
>>> me
>>> (dunno if it's common practice, it isn't to me) is the almost
>>> complete
>>> lack of comments in the code. What I'll probably do is write up
>>> what I'm
>>> doing as I do it, and heavily comment my engraver so that even if
>>> the
>>> comments don't make it into production code, they can make
>>> documentation
>>> as a "sample engraver".
>> Assuming you really do need a new engraver this is where
>> I have to hand over to someone more competent.  But a commented
>> engraver would be a useful addition to the CG.
> I agree wholeheartedly.   The real problem (IMO) with engravers is that he
> general structure of an engraver is not documented anywhere very well
> (although we're adding some stuff to the CG).  Most of the comments that
> would help to understand an engraver are unneeded once you understand an
> engraver structure (e.g. we don't really want to have a comment in every
> engraver describing what stop_translation_timestep (), process_music (),
> etc. do -- that would just clutter up the code).  Once you understand
> process_music (), you only really want comments related to the *specific*
> procsess_for this engraver, and with good variable names, it's not really
> that hard in most cases to figure most of it out.
>
> But the overall structure is *very* hard to get figured out, in my
> experience.
So if I can crack and document this, it'll be a worthwhile effort. Good!

Cheers,
Wol

---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Mike Solomon
On 8/10/10 3:44 PM, "Wols Lists" <[hidden email]> wrote:

>  On 10/08/10 00:54, Carl Sorensen wrote:
>>>>
>>>> Okay. I've looked through chord-name-engraver.cc, and I think I've
>>>> understood roughly what's going on. It looks like the main thing
>>>> I've
>>>> got to change is Chord_name_engraver::process_music(). As far as I
>>>> can
>>>> see, this is building up a list of note pitches in the variable
>>>> "pitches" and then passing it to a function to convert it to a
>>>> chord name.
>>> This sounds right to me.
>> Yes, this is so.
>>
> Okay. So I'm on the right track.
>>>> So what I need to do, is create a new variable "capo_pitches", and
>>>> just
>>>> as pitches are assigned to "pitches", I need to transpose them and
>>>> assign them to "capo_pitches". I can then create "capo_markup",
>>>> which
>>>> will (if I've understood the code correctly) contain a text
>>>> description
>>>> of the transposed chord. So I now have - hopefully - "markup" ==
>>>> eg "Gm"
>>>> giving me "capo_markup" == "Em" if capo is 3. I now need
>>>> chord_name_->set_property("text", "markup ( capo_markup )" )
>> Not quite.  It's not a text description, but actually a markup description.
>> The property name is "text", but the result from calling the scheme
>> procedure stored in the context property chordNameFunction returns a markup.
>>
>> Better I think to just have line 95 change to something like
>>
>> SCM raw_pitch = n->get_property ("pitch");
>> SCM p = raw_pitch->transposed (Pitch (0, 0, capo_semitones));
>>
>> Now you have p transposed, and everything should work properly, IIUC.
> Great. I assume to transpose down I need a negative, so if capo is 3, I
> either print 3 and set capo_semitones to -3, or I pass -capo_semitones.
> Either way, I'll cross that bridge when I get to it.
>
> Don't forget I need both "raw_pitch" and "p", though. My pseudo-code may
> have misled (the joys of multiple meanings of parentheses :-). So I'll
> be asking how to combine markup next :-) because the output needs to be
> eg "C(A)".
>>> So far so good, but I'm beginning to wonder if this is not
>>> duplicating something...
>>>
>>>> The other thing I need to do is write a new engraver ...
>>> Hhm.  Why is that?  Would that be better than modifying
>>> the existing chord name engraver to be aware of capos (capi?).
>>>
>> I'm guessing that you're wanting a capo_indicating_engraver to write the
>> statement that tells you what fret to put the capo on, and indicates the key
>> in the "capo" worldview.  I don't think you should need to do the key
>> signature engraver.  Something like the metronome engraver is probably a
>> better pattern.
>>
> Spot on again. Okay, I'll investigate that engraver and see how I can
> revamp it as a capo_indicating_engraver.
>>>> I've tried to look at the key signature engraver, but that doesn't
>>>> seem
>>>> to be so simple (I'm not surprised ...). What I need to do is have
>>>> some
>>>> lilypond syntax "\capo 3 vertical|horizontal", with it defaulting
>>>> to
>>>> horizontal.
>> If you really need a new engraver, then you'll also need to create a new
>> event (a capoEvent) that both the Capo engraver and the ChordName engraver
>> will need to listen to.  You might want to consider Trevor's suggestion, of
>> just defining a new context property.
>>
> Bear in mind I've just jumped into the pond and am already out of my
> depth :-) How do I create a context property? And if I go down that
> route how will I get the capo indicator to print at the start of the
> piece? Basically, my idea is that the user will simply put the capo
> command with the key signature command in their .ly file, and that will
> trigger the capo indicator plus automatically transpose any chord-names
> they choose to print.
>>> This sounds like a new context property set in the ChordName
>>> context and used by the ChordName engraver to decide whether
>>> to transpose and by how much.
>>>> This will then need to get the key signature and print
>>>> (assuming a key of G minor, the example in front of me) "Capo 3
>>>> (Em)",
>>>> transposing the key down three semitones. It'll also need to leave
>>>> the 3
>>>> somewhere (along with vertical/horizontal), so the chord engraver
>>>> knows
>>>> what to do. Wherever it stores the transposition, should that
>>>> default to
>>>> null or 0?
>> No, you don't "leave the 3 somewhere".  You have an event that both the Capo
>> engraver and the ChordName engraver listen to.  Then the ChordName engraver
>> puts the 3 in the appropriate place.  And the Capo engraver creates the
>> appropriate output.
>>
>> Just out of curiosity, what does vertical/horizontal do?
>>
> As you guessed, places the two chords side-by-side or vertically
> stacked. Can an event return two values, so the chord name engraver gets
> the transposition and stacking?
>>> I'm getting puzzled now.  \transpose can already be invoked to
>>> change chord names, can't it?  What functionality does
>>> it lack that you need?  (Sorry if the answer's obvious - I'm not
>>> a guitar player.)  I can see the capo is not fully supported in
>>> fret diagrams.  AFAICS this currently has to be provided for every
>>> fret diagram.  But if you only want chord names perhaps a slightly
>>> different way of invoking \transpose would suffice?
>>>
>>>> Okay. Where do I start with writing my new engraver? And have I
>>>> got my
>>>> changes to chord-name-engraver close? One of the things that gets
>>>> me
>>>> (dunno if it's common practice, it isn't to me) is the almost
>>>> complete
>>>> lack of comments in the code. What I'll probably do is write up
>>>> what I'm
>>>> doing as I do it, and heavily comment my engraver so that even if
>>>> the
>>>> comments don't make it into production code, they can make
>>>> documentation
>>>> as a "sample engraver".
>>> Assuming you really do need a new engraver this is where
>>> I have to hand over to someone more competent.  But a commented
>>> engraver would be a useful addition to the CG.
>> I agree wholeheartedly.   The real problem (IMO) with engravers is that he
>> general structure of an engraver is not documented anywhere very well
>> (although we're adding some stuff to the CG).  Most of the comments that
>> would help to understand an engraver are unneeded once you understand an
>> engraver structure (e.g. we don't really want to have a comment in every
>> engraver describing what stop_translation_timestep (), process_music (),
>> etc. do -- that would just clutter up the code).  Once you understand
>> process_music (), you only really want comments related to the *specific*
>> procsess_for this engraver, and with good variable names, it's not really
>> that hard in most cases to figure most of it out.
>>
>> But the overall structure is *very* hard to get figured out, in my
>> experience.
> So if I can crack and document this, it'll be a worthwhile effort. Good!
Achtung!  Just a small aside that someone did a really good job with this:

http://lilypond.org/doc/v2.13/Documentation/contributor/engraver-tutorial

The only thing that is missing (assuming that I haven't overlooked it, which
is often an incorrect assumption) is a good definition of what a translation
timestep is (a definition that, unfortunately, I cannot furnish), although
perhaps that's somewhere else in the dox.

Anyway, I thought I'd bring it to your attention to save you a bit of work.

I've just implemented a host of scheme engraver stuff (meaning engravers
100% implemented in Scheme) if you want to check that out.  Let me know.

On that subject, any takers to try out my new patch for adding event-classes
via scheme?  There's a 15 second two-part-invention in it for the first
person who applies it and tries it!

~Mike

> Cheers,
> Wol
>
> ---
> ----
> Join the Frogs!
>
>



---
----
Join the Frogs!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Another new tadpole?

Wols Lists
On 10/08/10 15:32, Mike Solomon wrote:
But the overall structure is *very* hard to get figured out, in my
>> experience.
> So if I can crack and document this, it'll be a worthwhile effort. Good!
Achtung!  Just a small aside that someone did a really good job with this:

http://lilypond.org/doc/v2.13/Documentation/contributor/engraver-tutorial

The only thing that is missing (assuming that I haven't overlooked it, which
is often an incorrect assumption) is a good definition of what a translation
timestep is (a definition that, unfortunately, I cannot furnish), although
perhaps that's somewhere else in the dox.

Anyway, I thought I'd bring it to your attention to save you a bit of work.

I've just implemented a host of scheme engraver stuff (meaning engravers
100% implemented in Scheme) if you want to check that out.  Let me know.

On that subject, any takers to try out my new patch for adding event-classes
via scheme?  There's a 15 second two-part-invention in it for the first
person who applies it and tries it!

Thank you very much. I hadn't found it, but last I looked I couldn't find it in the 2.13 docs (found it now :-)

The scheme engraver stuff sounds interesting, but I'm having enough fun understanding the C++ stuff (which I sort-of get) that I think I'll leave the scheme stuff for the moment. If you can give me a few file-names to look at, however, I will.

Cheers,
Wol
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Capo-ChordNames

Wols Lists
In reply to this post by Carl Sorensen
On 10/08/10 14:39, Carl Sorensen wrote:
If it gets me into Scheme and C++
> I'll be well pleased.
At the moment, probably not too much Scheme (although you might want to try
writing the CapoEngraver in Scheme).

Actually, I was thinking that writing this engraver first might be a good idea, seeing as it should set capoFret as a side effect. oops :-) If Mike gets back to me with some scheme engravers to investigate, I'll try that route if I can (or I'll just try and find a few candidates myself).

      
> 
> I'll look at your long email, probably respond, and then hack at it and
> come back with more questions :-)
Sounds great.

But there's some wrong advice in my email, because I wasn't thinking about
having *both* chord names created by the engraver.  You'll want to follow up
more on your original approach, i.e. having both pitches and capo_pitches.
Then you'll need to call the chordNameFunction twice, once with pitches,
bass, inversion and once with capo_pitches, capo_bass, capo_inversion.  Then
you'll need to combine the two markups into one, probably with another
scheme call.
Actually, I was wondering if I could take a different approach ...

I've twigged that scm_call_4 simply calls the procedure in argument 1 with four more arguments. It MIGHT be possible to rewrite that instead. I've got a nasty feeling, however, that there are a whole bunch of chord name functions, so that's probably a non-starter :-(

Do you know if I'll need capo_inversion, or can I just use inversion? Don't worry about investigating if you don't know, it's more experience for me :-) but it's quicker to ask than duplicate knowledge :-)
vertical/horizontal should be a context property, rather than a keyword.

I'm not sure yet about capo_fret.  It could be a context property, or it
could be part of the structure of a capoEvent.

For getting started, I'd recommend making it a context property, and
avoiding the use of a capoEvent.

Then you'd do something like

\set ChordNames.capoFret = #3
\set ChordNames.capoOffset = #'horizontal

to set up the engraver properly.
Okay. Next task. Actually sit down and start writing some code, then post it to the list to see if it makes sense :-)

Cheers,
Wol
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Capo-ChordNames

Carl Sorensen
On 8/10/10 3:38 PM, "Wols Lists" <[hidden email]> wrote:

>    On 10/08/10 14:39, Carl Sorensen wrote:
>>  
>>>  
>>> If it gets me into Scheme and C++
>>>>> I'll be well pleased.
>>>  
>>  
>> At the moment, probably not too much Scheme (although you might want to try
>> writing the CapoEngraver in Scheme).
>>
>>  
>  Actually, I was thinking that writing this engraver first might be a good
> idea, seeing as it should set capoFret as a side effect. oops :-) If Mike gets
> back to me with some scheme engravers to investigate, I'll try that route if I
> can (or I'll just try and find a few candidates myself).

You're welcome to write a CapoEngraver first if you want to.  I wouldn't
recommend this, though.  The output of the CapoEngraver can be created right
now as a \mark, so it's not strictly needed.  The modification to the
ChordNamesEngraver is necessary to get the output you want, so I think
that's where you should start.

>  
>>  
>>  
>>>  
>>>>>
>>>>> I'll look at your long email, probably respond, and then hack at it and
>>>>> come back with more questions :-)
>>>  
>>  
>> Sounds great.
>>
>> But there's some wrong advice in my email, because I wasn't thinking about
>> having *both* chord names created by the engraver.  You'll want to follow up
>> more on your original approach, i.e. having both pitches and capo_pitches.
>> Then you'll need to call the chordNameFunction twice, once with pitches,
>> bass, inversion and once with capo_pitches, capo_bass, capo_inversion.  Then
>> you'll need to combine the two markups into one, probably with another
>> scheme call.
>>  
>  Actually, I was wondering if I could take a different approach ...
>  
>  I've twigged that scm_call_4 simply calls the procedure in argument 1 with
> four more arguments. It MIGHT be possible to rewrite that instead. I've got a
> nasty feeling, however, that there are a whole bunch of chord name functions,
> so that's probably a non-starter :-(

Yes, I think it's a non-starter.  The modularity we're trying to enforce is
to have a scheme procedure that turns pitches, bass, and inversion into a
markup.  That way, if someone wants a different chord name function, they
just add it in.  And it shouldn't have to handle the capo stuff.

>  
>  Do you know if I'll need capo_inversion, or can I just use inversion? Don't
> worry about investigating if you don't know, it's more experience for me :-)
> but it's quicker to ask than duplicate knowledge :-)

I don't know the answer to this question.  I haven't looked carefully at the
data type of inversion.  It may be that the inversion data doesn't change
based on the chord root.  If so, you can just use inversion.

>  
>>  
>>
>> vertical/horizontal should be a context property, rather than a keyword.
>>
>> I'm not sure yet about capo_fret.  It could be a context property, or it
>> could be part of the structure of a capoEvent.
>>
>> For getting started, I'd recommend making it a context property, and
>> avoiding the use of a capoEvent.
>>
>> Then you'd do something like
>>
>> \set ChordNames.capoFret = #3
>> \set ChordNames.capoOffset = #'horizontal
>>
>> to set up the engraver properly.
>>  
>  Okay. Next task. Actually sit down and start writing some code, then post it
> to the list to see if it makes sense :-)

Sounds great to me!

Carl



---
----
Join the Frogs!

Loading...