Kara-Moon Forum

Developers & Technology => Musical MIDI Accompaniment (MMA) => Topic started by: sciurius on January 12, 2019, 03:40:08 PM



Title: Crash with Chord Name Insertion
Post by: sciurius on January 12, 2019, 03:40:08 PM
The following file crashes MMA:

  Time 6
  Lyric Chords=On
  1 C


Code:
Traceback (most recent call last):
  File "/bin/mma", line 74, in <module>
    import MMA.main
  File "/usr/share/mma/MMA/main.py", line 153, in <module>
    MMA.parse.parseFile(f)
  File "/usr/share/mma/MMA/parse.py", line 91, in parseFile
    parse(f)
  File "/usr/share/mma/MMA/parse.py", line 233, in parse
    l, lyrics = lyric.extract(l, rptcount)
  File "/usr/share/mma/MMA/lyric.py", line 355, in extract
    ly.extend(['/'] * i)
TypeError: can't multiply sequence by non-int of type 'float'


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 12, 2019, 04:17:04 PM
Hope this isn't an emergency ... I'm tied up today, but will look tomorrow. I'm pretty sure it's an easy fix :)


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 12, 2019, 05:09:37 PM
No real hurry. Take your time.


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 13, 2019, 01:48:35 AM
I found a very simple fix to this problem ... but in doing more testing I've found a much more serious problem with ints and floats. I'll have to do a bunch of tracing an find this. Oh well, something for me to worry about tonight in my bed :)


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 13, 2019, 05:44:35 PM
Okay ... it was easy. Unfortunately (for me) I'd inserted some debugging code which crashed things after I fixed them :)

But, the problem is easily fixed. In lyric.py change line 353 from

   i = gbl.QperBar - len(ly)

to

   i = int(gbl.QperBar - len(ly))


Let me know if any other problems! Thanks.


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 14, 2019, 12:38:21 PM
This fixes the crash -- thanks!

But it reveals another problem.

Groove G61 has sequence { 1 1. 90 } (it's 6/8)
Groove G614 has sequence { 1 1. 90; 4 1. 80}

Then

  Groove G61
  1 C


results in "C / / / / /" (correct).

but

  Groove G614
  1   C  F


results in "C F / / / /" instead of "C / / F / /".


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 14, 2019, 04:50:50 PM
I don't see a reasonable answer to this one. The code, right now, extends the line out by duplicating the last chord name.

In the case of 6/8 the music chords for "C G" would generate a "C" at beat 1, "G" at 2,3,4,5,6. And the chord-lyric is the same I think?

In any event, my problem is that I really don't have a good idea as to what "proper" output is and how to read it. Right now we're generating a "symbol" on each "beat". So, in 4/4 a line with a single C chord would generate entries in the MIDI at beat 1 with a "C" and 2, 3, and 4 with "/". Is this repetition even right or necessary?


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 14, 2019, 06:38:01 PM
As a programmer I'd be inclined to view the sequence a subroutine, and the chords on the line are its parameters. Sequence { 1 1 90 } takes 1 chord, sequence { 1 1 90 * 8 } takes 8 chords. A drum sequence takes no chords. However, since one line of input may be processed by multiple sequences, this view is not sustainable.

So, although

  Time 4
  Chord Sequence { 1 1 90 * 8 }
  1  A B C


produces A A B B C C C C instead of A B C C C C C C it can be documented why it works that way.

The reference documentation, section Musical Data Format, subsection Positioning, first paragraph, already hints on the sequence not being in control.

So, in "Time 4"

  1  A B C

is just shorthand for

  1  A@1  B@2  C@3  /@4

which also explains why

  1  A B C D E F G

produces an error.

Interesting is that it is often quite intuitive, even for the wrong reasons. For example, sequence { 1 4 90; 4 4 90 } and chords "C F" work as expected because "C F / /" has an F on the 4rd beat.

I wouldn't have noticed the difference if it weren't for the "Lyrics On"...


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 14, 2019, 06:48:01 PM
Defining sequence points for chords and generating music are 2 different operations :)

When MMA finds a line like:

    C  /  D

it first creates a data structure of chord positions. In this case, it says that at position "1" there is a C chord; at position 3 there is a D. We could get more complicated using the @ notation, but it's all the same.

Now, when we process a music line (eg: Chord Sequence ...) we have to examine each requested point in the sequence for the given track (in this case CHORD) and find out what the chord is for that point.

And, to make things more fun, you could actually have a different set of chords for different tracks, but that's a complication in this discussion :)

So, now when it comes to a lyric and auto-chords ... well, there isn't a sequence for this. So, we just assume that we need to put something at each beat (1,2,3,4,etc). If the chord line doesn't have enough text we need to create it ... and that's where the questions come in.

So, in your 6/8 example (btw, 6/8 is always a bugger since it's a duple time but notated in 6) ... the simple answer for me is to use the chord line:
   
    C / / G

and you'll get C on 1,2,3 and G on 4,5,6. Now, a good argument could be made that in 6/8 you should only have chord names on 1 and 2 since it's duple time. Or, is it something else since 6/8 can also be non-duple :)

As you can see, I don't have an answer.


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 14, 2019, 09:33:14 PM
Since the chords in the MIDI are correctly placed, would it be possible to insert the chord name lyrics at the same timestamps as the chords?


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 14, 2019, 09:56:30 PM
Since the chords in the MIDI are correctly placed, would it be possible to insert the chord name lyrics at the same timestamps as the chords?

Not sure what you mean ... "Chords in the MIDI are correctly placed" ... that means that the audio is correct? Chords (and any other note on/off info) is placed in accordance with the defined sequence for that track. So, you can have "chords" (whatever that is) at 1,2,3&4 and other chords at 1.3 & 2.8. The problem with the text data generated with "lyric chords=on" is that there is not a sequence for that. And, having one isn't really possible either.

Note that the chord-text is split into the number of beats in each bar, which might be an error? If you set normal lyric data then that is set as one batch of text per bar, no matter how long or short that is.

I think what you are saying is that you'd like to do something like:

    Chord Sequence {1 1 90 * 4}

and then have chord-text set at 1,2,3,4. Problem is that we need to have a sequence associated with lyric. I suppose we could do Lyric SequencePoints=1,2,3,4 or something like that. But, are we getting to overly complicated solutions to non-problems?


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 15, 2019, 06:39:32 PM
I'm afraid so. It is probably not worth to spend an awful amount of energy in solving obscure edge cases.

What I meant with "Chords in the MIDI are correctly placed" is that with a sequence { 1 4 90; 3 4 90 } a chord is sounded at the 1st and 3rd beat. With chords "C F" this means that C sounds on 1st beat and F sounds on 3rd beat.
Now what I expected the Lyrics=On to do is insert the chord name, as a lyric, with the sounding chord. So "C" at the 1st beat and "F" at the 3rd beat.

As you notice, there is no sequence for the lyrics. But it would be possible to designate sequences for the chord name lyrics, for example:

  Begin Chord
    Sequence     { L1; 6 1. 70 }
    ChordNames   On
  End


So if Lyrics is set to On, the above sequence would be used to place the chord name lyrics.

If course, this is just a thought. I do not know whether that is makes sense considering the MMA implementation details.


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 16, 2019, 01:52:48 AM
One (easy) way to handle this is:

   1. Add an option Lyric Chord=On,Sequence=x1,x2,...

X1, X2 would be offsets into the bar. Just like you currently set offsets in a chord/bass/etc line.

  2. When processing, we look at the seq points (if defined) and fill them in with whatever chord is active at that point. So, if you were to set sequence=1,3 and have the chord line:

      20   Cm /  Em

MetaLyric events would be generated at offsets 1 and 3.

Interestingly,

     20   C   D  E F

would still ONLY generate events C and E at 1 and 3. This is pretty much the same as what happens with musical sequences.

And,

     Sequence=1,2,3,4
     20   C

would generate 3 Meta events (1,2,3 and 4) all with "C".

This nice things about this:

    1. Fairly easy to do (I think)
    2. Consistent with chord/bass/whatever
    3. Doesn't effect existing usage.

Will it be helpful to anyone?




Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 16, 2019, 07:34:59 AM
That would indeed be a great step forward, but still involve a lot of (avoidable) work from the user.

Considering that I have songs with a lot of grooves, and groove (and chord sequence) changes take place every one or two lines, I would either have to insert the "Lyrics Chords=On Sequence=..." as often as groove changes, or make it part of each groove and use a variable to control switching on/off, e.g. "Lyrics Chords=$LyricsChords Sequence=...".

While this is doable, it still involves duplicating information, since the chord sequence is already defined and that is the sequence that is needed:

  Begin Chord
    Sequence   { L1; 5.6 1. 70 }
  End
  Lyrics Chord=$LyricsChords Sequence=1,5.6
  DefGroove G616


So I think it is more inutitive to combine the "Lyrics Chord" with the Chord settings, e.g.

  Begin Chord
    Sequence   { L1; 5.6 1. 70 }
    Lyrics     Chord=$LyricsChords
  End
  DefGroove G616


In any case, please make the syntax for the sequences compatible, so it would be possible to write:

  Begin Chord
    Sequence   { L1; 5.6 1. 70 }
  End
  Lyrics Chord=$LyricsChords Sequence=$_Chord_Sequence
  DefGroove G616


This doesn't look more complex to implement.


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 16, 2019, 03:57:43 PM
Not sure what the problem is with grooves changing ... the lyric setting is NOT saved in a groove. It's sort of a "global" setting that sticks around until it's turned off (I could be wrong, this is from memory). So, once you set the lyric options, it's there for the session.

Now, if you change the TIME, there may be a problem with my latest scheme. I'm not sure what my dream code would do/should do in this case. I have a feeling that may be one of the reasons I didn't do it this way to start :)

I suppose that grabbing a TRACK sequence definition and applying that to lyric positioning would be okay. But, from a user standpoint, what happens if:

    1. Define the lyric distribution to $Chord_Sequence (whatever that might be).
        Okay, all we're doing is taking the offsets out of the seq and setting "print points" for
        them.
    2. $Chord_Sequence might be a 2 or 4 or more sequence. Now, it's getting more complicated ...
         do we set up the lyric distribution for multi-seq points, or just take one (first?) of the
         pattern?
    3. This still leaves the problem of a naive user setting the Sequence to, for example, beats 1,2,3,4 and
         then changing the TIME to 3 or 5 (bigger is less of a problem). Guess we'd just need to issue
         an error.

More thoughts :)


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 17, 2019, 07:27:07 AM
Not sure what the problem is with grooves changing ...

  Time 6
  Groove G13
  Lyrics Chord=On Sequence=1,3
  Am Bm
  Groove G16
  Lyrics Chord=On Sequence=1,6
  Am Bm
  Groove G14
  Lyrics Chord=On Sequence=1,4
  Am Bm
  Groove G16
  Lyrics Chord=On Sequence=1,6
  Am Bm
  Groove G3
  Lyrics Chord=On Sequence=3
  D7
  Groove G16
  Lyrics Chord=On Sequence=1,6
  Am Bm


As you can see:
  • I have to repeat it for every groove change;
  • I must include information that should be private to the groove;
  • It clobbers the song source.
Quote
I suppose that grabbing a TRACK sequence definition and applying that to lyric positioning would be okay.

It would eliminate duplication of private information:

  Time 6
  Groove G13
  Lyrics Chord=On $_Chord_Sequence
  Am Bm
  Groove G16
  Lyrics Chord=On $_Chord_Sequence
  Am Bm
  Groove G14
  Lyrics Chord=On $_Chord_Sequence
  Am Bm
  Groove G16
  Lyrics Chord=On $_Chord_Sequence
  Am Bm
  Groove G3
  Lyrics Chord=On $_Chord_Sequence
  D7
  Groove G16
  Lyrics Chord=On $_Chord_Sequence
  Am Bm


It still clobbers the source.

Quote
Define the lyric distribution to $Chord_Sequence (whatever that might be).
        Okay, all we're doing is taking the offsets out of the seq and setting "print points" for
        them.

Exactly.


Quote
$Chord_Sequence might be a 2 or 4 or more sequence. Now, it's getting more complicated ...
         do we set up the lyric distribution for multi-seq points, or just take one (first?) of the
         pattern?

Not sure what you mean. Do you have an example?

Quote
This still leaves the problem of a naive user setting the Sequence to, for example, beats 1,2,3,4 and
         then changing the TIME to 3 or 5 (bigger is less of a problem). Guess we'd just need to issue
         an error.

Possibly. OTOH if chords can be placed correctly, I think this should also be possible for the chord name lyrics.

Still one can wonder if it is worth to put so much effort into a feature that will probably hardly ever be used (but I may be wrong... I've been wrong before).


Title: Re: Crash with Chord Name Insertion
Post by: bvdp on January 17, 2019, 04:43:33 PM
I'm wrong more often than I'm right :) Mind you, that's gotten me this far in life and it's usually fun!

For now, I'm going to make a note in my wish list and leave things, which are working, for now.

BTW, there are other ways to look at this issue. One might be to actually set points to insert the chords and not rely on some fault algorithm to do it. How about:

   /// to print chord meta data at 1 and 3
   Lyric Chord=On Datapoints=1,3
   10 Cm / Em

   /// to link chord meta data points to whatever the chord-foo track is doing
   Lyric Chord=On Datapoints=Chord_Foo
   /// and, if the groove changes and Chord_foo is no longer active...??

   /// to link to a mythical definition
    Lyric Chord=On Datapoints=Bass Sequence B1234
   /// will need some parsing help. The sequence will continue to exist after groove changes
   /// but ... TIME changes??

I keep harping on time changes. If you define the points for the meta data (no matter how you do it) to
1,2,3,4 in a TIME 4 setting and now change to TIME 3 ... what do we do with meta point 4? If we change to TIME 8, what happens to 5..8? Ignored again?

I keep thinking that the easy way is to simply distribute things across the bar like we currently do.

Don't forget, you can always make things a bit nicer by setting the chord names in lyric text. Only problem here is that you need to do it 2x and no transpose :)

   

 


Title: Re: Crash with Chord Name Insertion
Post by: sciurius on January 18, 2019, 07:23:19 AM
Quote
   /// to link chord meta data points to whatever the chord-foo track is doing
   Lyric Chord=On Datapoints=Chord_Foo
   /// and, if the groove changes and Chord_foo is no longer active...??

What if the groove changes and Chord-Foo is redefined with another sequence...??

For this reason I had an explicit Lyrics setting following each groove change in one of my examples.

Quote
   /// to link to a mythical definition
    Lyric Chord=On Datapoints=Bass Sequence B1234
   /// will need some parsing help. The sequence will continue to exist after groove changes

Not sure if this is useful. Remember we're dealing with chord name lyrics and I'm pretty sure in this case it only makes sense to put the lyrics to the chord sequence and not to some other sequence. 

Quote
I keep harping on time changes. If you define the points for the meta data (no matter how you do it) to
1,2,3,4 in a TIME 4 setting and now change to TIME 3

Personally, I would never do this. When TIME changes, new grooves come into play.

Quote
Don't forget, you can always make things a bit nicer by setting the chord names in lyric text. Only problem here is that you need to do it 2x and no transpose :)

IIUC lyrics can only be placed at measures so there is no way to have the chord name displayed at a particular beat/chord change...

Quote
For now, I'm going to make a note in my wish list and leave things, which are working, for now.

Seconded.