0xfe / vextab

A VexTab Parser for VexFlow
Other
588 stars 115 forks source link

WORK-IN-PROGRESS: user beaming -- DO NOT MERGE #124

Open jzohrab opened 3 years ago

jzohrab commented 3 years ago

Opening a draft PR hoping that someone with more experience can weigh in.

Currently, vextab doesn't support user-requested beaming. According to the jison, it should be allowed, eg:

tabstave notation=true tablature=false
notes [ :32 3/4 4/5 ] :q 5/6

Should produce something like beamed 32nd notes, followed by a quarter. The jison (https://github.com/0xfe/vextab/blob/master/src/vextab.jison#L232) refers to commands "open_beam" and "close_beam", but those aren't implemented in artist.coffee, and are ignored.

This wip PR changes the "if/else" to "switch/case" for executing commands, which fails when the user adds [ ... ] in vextab. I then implemented a bare-bone idea for keeping track of the beam groups, but it currently doesn't work, as the beams are rendered in addition to the existing note stems:

image

I tried a few things like this:

    if @in_beam
      @beam_notes.push stave_note
    else
      stave_notes.push stave_note

but that didn't work (fails with Note needs a TickContext assigned for an X-Value)

Hopefully someone can point out what's wrong with this primitive idea, and then beaming can be properly implemented (that is, if it's needed!).

0xfe commented 3 years ago

Thanks for digging in -- the StaveNotes need to know that they are beamed, otherwise they'll render flags. Try note.setBeam to do that.

jzohrab commented 3 years ago

Thank you! That doesn't solve it immediately but puts me on a better path, I think. I'll keep working and pushing to this work-in-progress branch, and if I solve it I'll rebase and reopen a new branch.

0xfe commented 3 years ago

If that doesn't work, it's possible that artist.FormatAndRender is resetting the stave notes somehow -- I haven't looked at this in a while, so I'm not sure when the notes are actually built.

The code in VexFlow: stavenote.js and beam.js should help you figure it out. Good luck!

0xfe commented 3 years ago

Hi @jzohrab -- how did this go? Need any help?

jzohrab commented 3 years ago

Unfortunately I couldn’t sort it out and needed to move on to other things. The branch has my various attempts. If you can complete it, that would be super. Hopefully it’s not too hairy. Sorry I couldn’t work it out myself! jz

El El mar, may. 4, 2021 a la(s) 3:27 a. m., Mohit Cheppudira < @.***> escribió:

Hi @jzohrab https://github.com/jzohrab -- how did this go? Need any help?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/0xfe/vextab/pull/124#issuecomment-831839663, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMPWDKCNTCN74WZRFRU3JLTL7DZDANCNFSM43NWILUA .

jzohrab commented 3 years ago

Looking at the commit history for open_beam:

$ git log -S open_beam --oneline
cafa0b0 WORK-IN-PROGRESS: user beaming.
59d4747 Add release binaries.
82bd6bb Add releases to repository.
ff5877a Basic browserify support for lib and tests.
6911b64 Add releases to repo.
4886ea7 Add support for bars.
fe2eb5f Vextab2 now supports single note lines.
de7bab5 Made grammar proper left-recursive.

it looks like it may have been lost around git show de7bab5 -- perhaps a grammar issue.

(I'm not able to work on it at the moment, retinal issue :-( and it's hard to look at the screen)

tomboul commented 3 years ago

Hello, i made little modification in vextab-div.js to make the bracket command active for beam state

whithout bracket command with this vextab code :

options space=50 font-face=petalumaScript beam-rests=false
tabstave notation=true tablature=false key=C clef=treble time=4/4

 notes  =|: :8 F/4  :q F/4   :8 F/4 tF/4  E/4 :q D/4  
 notes  | :qd D/4     :8 F/4 F/4  A/4 G/4  F/4

I get this rendering :

2021-05-04_20h37_56

Now with the bracket command in this vexTab code :

options space=50 font-face=petalumaScript beam-rests=false
tabstave notation=true tablature=false key=C clef=treble time=4/4

 notes  =|: :8 F/4  :q F/4   :8 F/4 [ tF/4  E/4 ] :q D/4  
 notes  | :qd D/4     :8 F/4 [ F/4  A/4 G/4  F/4 ]

I get this result

2021-05-06_04h11_26

I am a former programmer, (since 1983, at the time I was writing programs in assembly language on paper) but I'm beginner with github, if you are interessed by this,i can give you my modification, but i dont know how to do It's a very little modification

jzohrab commented 3 years ago

Hi Thomas, great job! At the moment I can’t program due to a vision issue. But perhaps someone could implement it.

If you paste the section of code that you changed in a comment in this PR, perhaps someone could make the change for you. At some point I’ll be able to but I’m not sure when

Cheers! Jz

El El mié, may. 5, 2021 a la(s) 7:26 p. m., Thomas @.***> escribió:

Hello, i made little modification in vextab-div.js to make the bracket command active for beam state

whithout bracket command with this vextab code :

options space=50 font-face=petalumaScript beam-rests=false tabstave notation=true tablature=false key=C clef=treble time=4/4

notes =|: :8 F/4 :q F/4 :8 F/4 tF/4 E/4 :q D/4 notes | :qd D/4 :8 F/4 F/4 A/4 G/4 F/4

I get this rendering :

[image: 2021-05-04_20h37_56] https://user-images.githubusercontent.com/5411049/117232731-09b65f00-ae22-11eb-8292-9103930ae5ec.png

Now with the bracket command in this vexTab code :

options space=50 font-face=petalumaScript beam-rests=false tabstave notation=true tablature=false key=C clef=treble time=4/4

notes =|: :8 F/4 :q F/4 :8 F/4 [ tF/4 E/4 ] :q D/4 notes | :qd D/4 :8 F/4 [ F/4 A/4 G/4 F/4 ]

I get this result

[image: 2021-05-06_04h11_26] https://user-images.githubusercontent.com/5411049/117232587-be9c4c00-ae21-11eb-8e78-fd8eb611ac15.png

I am a former programmer, (since 1983, at the time I was writing programs in assembly language on paper) but I'm beginner with github, if you are interessed by this,i can give you my modification, but i dont know how to do

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/0xfe/vextab/pull/124#issuecomment-833178277, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMPWDPH7GVDKAWBZPXCWMDTMH46XANCNFSM43NWILUA .

tomboul commented 3 years ago

If you paste the section of code that you changed in a comment in this PR,

in VexTab.prototype.parseStaveElements i get command open_beam and close beam, and i put it in this.artist property

(TOMBOUL comment)

VexTab.prototype.parseStaveElements = function(notes) {
    var element, i, len, results;
    L("parseStaveElements:", notes);
    results = [];
    for (i = 0, len = notes.length; i < len; i++) {
      element = notes[i];
      if (element.time) {
        this.artist.setDuration(element.time, element.dot);
      }
      if (element.command) {
        // TOMBOUL open_beam and close_beam, are not really command but state
        // TOMBOUL set beam state (this state would be saved in stavenote array)
        if(element.command == "open_beam") { // TOMBOUL
          this.artist.setBeam("open");      // TOMBOUL  
        }                                   // TOMBOUL
        else if(element.command == "close_beam") {// TOMBOUL
          this.artist.setBeam("close");     // TOMBOUL
        }                                   // TOMBOUL
        this.parseCommand(element);
      }
      if (element.chord) {
        this.parseChord(element);
      }
      if (element.abc) {
        results.push(this.parseABC(element));
      } else if (element.fret) {
        results.push(this.parseFret(element));
      } else {
        results.push(void 0);
      }
    }
    return results;
 };

In createGroups function from generateBeams function


        function createGroups() { // TOMBOUL treatment beamset open/close vaxtab command witk bracket [ ]
          var nextGroup = [];
          var beamOpen = false; // TOMBOUL set state of beam command
          unprocessedNotes.forEach(function (unprocessedNote) {
            nextGroup = [];

            if (unprocessedNote.shouldIgnoreTicks()) {
              noteGroups.push(currentGroup);
              currentGroup = nextGroup;
              return; // Ignore untickables (like bar notes)
            }
            // TOMBOUL beamset == open ("[") close preview group create new group
            if(unprocessedNote.beamset == "open" && beamOpen == false) { 
                beamOpen = true;
                noteGroups.push(currentGroup);
                currentGroup = nextGroup;  
            }
            // TOMBOUL beamset == close ("[") while open state = true
            else if(unprocessedNote.beamset == "close" && beamOpen == true) {
                beamOpen = false;
                noteGroups.push(currentGroup);
                currentGroup = nextGroup;  
            }
            // TOMBOUL beamset == close ("[") while open state = true

            currentGroup.push(unprocessedNote);
            var ticksPerGroup = tickGroups[currentTickGroup].clone();
            var totalTicks = getTotalTicks(currentGroup);

            // Double the amount of ticks in a group, if it's an unbeamable tuplet
            var unbeamable = Flow.durationToNumber(unprocessedNote.duration) < 8;
            if (unbeamable && unprocessedNote.tuplet) {
              ticksPerGroup.numerator *= 2;
            }

            // If the note that was just added overflows the group tick total
            if (totalTicks.greaterThan(ticksPerGroup)) {
              // If the overflow note can be beamed, start the next group
              // with it. Unbeamable notes leave the group overflowed.
              if (!unbeamable) {
                nextGroup.push(currentGroup.pop());
              }
              noteGroups.push(currentGroup);
              currentGroup = nextGroup;
              nextTickGroup();
            } else if (totalTicks.equals(ticksPerGroup)) {
              noteGroups.push(currentGroup);
              currentGroup = nextGroup;
              nextTickGroup();
            }
          });

          // Adds any remainder notes
          if (currentGroup.length > 0) {
            noteGroups.push(currentGroup);
          }
        }

i add this prototype :

  // TOMBOUL set beamset for the command [ ]
  Artist.prototype.setBeam = function(action) { // TOMBOUL BEAM
    this.beamset = action;
    return;// TOMBOUL BEAM
  };// TOMBOUL BEAM

and in Artist.prototype.addStaveNote before the return


    stave_note.beamset = this.beamset; // TOMBOUL
    return stave_notes.push(stave_note);
  };

I don’t know if that’s the best way to do it, but there’s the operating principle.

And because i associated command beam one note, you can't have "] [" :

notes =|: [:8 F/4 :q F/4 :8 F/4] [ tF/4 E/4 :q D/4]

the close_beam "]" after :8 F/4 is associated with the next note (tF/4), but the following command "open_beam" overwrites the close_beam, so it's continued exactly like if they was no beam command, because it's always open ;-)

I think i can do best to have a real operating command "open" and "close", it would be very practical for signature like 7/8 or 9/8 in "Blue rondo a la Turk" from Dave Brubeck

0xfe commented 3 years ago

Thanks for figuring this out @tomboul -- we'll try to get it into the main codebase. Much appreciated!

@jzohrab I'm so sorry to hear that, I hope your eyes get better soon! Rest, relax, and recover!

tomboul commented 3 years ago

we'll try to get it into the main codebase. Much appreciated!

I think, it's possible to code this better, to give a real possibility of closing and opening beam, to produce correct beam with signature like 7/8 (can be, 2-2-3 or 2-3-2 or 3-2-2) or 9/8 (can be 3-3-3 or 2-2-2-3 and so on) etc .13/8 etc ...

At the moment I can’t program due to a vision issue.

I'm so sorry @jzohrab !!! take care of yourself !

jzohrab commented 3 years ago

Hi @0xfe and @tomboul, I've added the TOMBOUL code to this branch with comments :-) thanks for that @tomboul.

I haven't made any changes to the actual beaming code, though, as that's in the other vexflow repo and I wasn't sure if this is the best way to implement it ... perhaps Mohit can weigh in. So, the tests still show bad beaming because the [ ... ] parts aren't really being handled.

Also, this PR's wip code now contains some redundant parts, my old code and tomboul's code. But it's a wip branch, so that's no issue.

My sight's still not 100%, blurry right eye, but much better :-) Cheers all! jz