Kara-Moon Forum

Developers & Technology => Musical MIDI Accompaniment (MMA) => Topic started by: sciurius on April 26, 2020, 02:55:50 PM



Title: After question
Post by: sciurius on April 26, 2020, 02:55:50 PM
This works:

After Count=2 Print Beep
1 z * 2
1 z * 2


But this does not:

After Count=2 Print Beep
1 z * 4


This seems a bit confusing, since the docs explicitly mention that After works with bar numbers as they are generated, as opposed to Trigger that works with the number label in the file.



Title: Re: After question
Post by: sciurius on April 26, 2020, 03:14:16 PM
This works:

Groove MyGroove
After Count=4 Drum-Crash Sequence { 1 0 90 }
1 z * 4
// Crash here
1 z


But this does not work (as I expected):

Groove MyGroove
After Count=4 Drum-Crash Sequence { 1 0 90 }
1 z * 4
Groove MyGroove
// Crash here???
1 z


The explanation is simple: The Drum-Crash sequence is modified after bar 4, but the groove change resets everything.

So how to get the crash at the right place? Do we need a Before command?

(The Riff command doesn't seem to suffer from this.)


Title: Re: After question
Post by: bvdp on April 26, 2020, 04:18:09 PM
I'm just looking at the code and don't immediately see why it shouldn't work. All we're doing is shoving a command onto the stack after the specified count. And the Groove command shouldn't effect that??? I'll have to run some tests and see what's going on.


Title: Re: After question
Post by: sciurius on April 26, 2020, 05:45:09 PM
No it is not the After mechanism that fails, it is my specific (ab)use of it.

What I want is to perform the sequence change command before bar 5. With After, I have to queue the sequence change after bar 4, and since I change to a new groove between 4 and 5 the sequence change gets lost.

A Before command, similar to After but executed before the measure would allow this.



Title: Re: After question
Post by: sciurius on April 27, 2020, 08:57:20 PM
Can you explain what happens in my 1st message?


Title: Re: After question
Post by: bvdp on April 27, 2020, 09:15:41 PM
What is happening is this ... we check for AFTER at the top of the parse loop, ie. after each line is read. The '*' notation by-passes this ...

In the parse loop (ie after the AFTER check) it's treated like a single line. The AFTER code is checking to see if the current line number (this is a value generated by MMA when each LINE of code is read) matches the value generated when you created the AFTER. But, in your example, it's skipped over completely with the '* 4'.

I think the best thing to do is to note in the docs that AFTER and '*' really don't like each other ?


Title: Re: After question
Post by: bvdp on April 27, 2020, 09:21:38 PM
Thinking a bit more on this (while making tea) ... perhaps a better way to handle this is to check for '*' lines at the top of the parse loop, copy them back into the input stream and then proceed. I have not tried it yet, but I will later. That way we'd avoid a bunch of problems with '*'.


Title: Re: After question
Post by: bvdp on April 27, 2020, 10:59:54 PM
Hey, here's a "simple" solution, maybe. In parse.py at line 346 could you add the 2 new lines and test it out. I think it's doing the AFTER at the right spot and seems to print "beep" correctly :)
Code:
            # and it makes sense to only have it once!
            if rpt and lyric.dupchords:
                _,lyrics = lyric.extract(' '.join(l), 0)

            if rpt:
                MMA.after.check()

I must add that I've only tried this with a "Print BEEP" ...


Title: Re: After question
Post by: bvdp on April 27, 2020, 11:28:55 PM
I will add here (and to the docs) that if an AFTER event occurs during the processing of a repeat bar (*) the event will be found at the correct place, but not acted upon until the the repeat is done. So, in the case of:

Code:
After Count=2 Am
D * 4
C * 4

An 'Am' chord will be inserted between 4 bars of 'D' and 4 bars of 'C'. This is actually quite neat since it maintains the integrity of the bars being repeated AND it runs the AFTER event. If you want a 'Am' chord in at bar 3 (D, D, Am, D, D) then you will need to split the * in 2.


Title: Re: After question
Post by: sciurius on April 28, 2020, 06:20:45 AM
IMHO this is a bad idea...

As I see it, MMA input

Code:
1 D * 4
2 C * 4

is equivalent to

Code:
1 D
 D
 D
 D
2 C
 C
 C
 C

So I would expect this:

Code:
After Count=2 Am
1 D * 4
2 C * 4

to play as

Code:
1 D
 D
 Am
 D
 D
2 C
 C
 C
 C

It is good to document that it currently doesn't work that way (as with Trigger) but I rather have the After ignored (as it is now) than executed at a different place. Count=2 means after two bars, not some arbitrary amount later.

Maybe later we'll find a way to get this working as it should, and then it becomes a problem since many songs will break because they depend on the old behaviour.

I haven't really thought about it, but isn't it possible to duplicate the input lines when a repetition is in place? So that Print Hello * 4 will print Hello
Hello
Hello
Hello
instead of Hello * 4 ?


Title: Re: After question
Post by: bvdp on April 28, 2020, 04:37:33 PM
The SIMPLE and CORRECT solution might be to report as a warning that an AFTER is being skipped over in a repeat section? It should be simple to check to see if there is an active AFTER when one finds a '*', figure the counter and report a warning if needed.

I think that, conceptually, using a * is NOT the same as having separate lines :) Actually, if I were writing from scratch today I might just forget * altogether :) But, it's there now.

I actually tried to get the business of re-parsing the input with a repeat, but for a number of reasons (forgotten in my haze of non-working code) that is just as bad, ugly and subject to problems.



Title: Re: After question
Post by: bvdp on April 28, 2020, 06:10:56 PM
Okay ... worked on this a bit more ... and I have it working the way YOU want :) The code is too ugly right now to post, but what it does is to check the repeat count and if it matches it just creates a new file with the after stuff in it, recurses to process that line, and then continues on. I may be able to avoid the file, but have to look at that ... and might be as simple to just do it with a file.

But, yes, we can stick stuff in the middle of a * line without screwing up the rest of the universe. So, that is probably a good thing :) And, it is an interesting adventure in coding :)


Title: Re: After question
Post by: sciurius on April 28, 2020, 08:45:21 PM
 :o


Title: Re: After question
Post by: bvdp on April 28, 2020, 10:55:37 PM
Be so kind as to try this.

1. Replace yesterdays non-fix to parse.py with:

Code:
if rpt and MMA.after.needed():
                MMA.after.check(recurse=True)

2. Apply the attached patch to after.py

Let her run :)


Title: Re: After question
Post by: sciurius on April 29, 2020, 06:02:40 AM
Great, thanks!