paulrosen / abcjs

javascript for rendering abc music notation
Other
1.91k stars 283 forks source link

How to control note spacing without wrap #363

Open rualark opened 4 years ago

rualark commented 4 years ago

Could you please help me with controlling spacing between notes when not using wrap?

Let's look at an example, which can be viewed in abcjs editor here:

%%barnumbers 1
M:3/4
K:G
L:1/16
V: V0 clef=treble name="Sop."
V: V1 clef=treble name="Alt."
V: V2 clef=treble-8 name="Ten."
V: V3 clef=bass name="Bas."
[V: V0]z8"^LT "^d4|e4B4A4|B2A2"^9 "B4A4|G8F4|F8"^LT"^G4|A4E4F4|=G4D2E2"^7"=F4|"^7"E12-|E6G2"^LT"^D4|E12|
[V: V1]z8"^7 "A2B2|G8"^7 "G4-|G4E4F4|E4D4C2D2|^D8"^7 "=D2E2|^C8"^LT"^D2"^9!"C2|E4B,4D4-|D4C4E4|B,8B,4|B,4C4B,4|
[V: V2]z8"^9 "c2"^aug2!"^d2|B8e4|"^7 "d2e2^c4"^o "=c4-|c4B4A4|B8B4|E2F2G2A2B4-|B4G4B4|A8G4|G8F4|G4A4G4|
[V: V3]z8"_Em: V9"B,,4|"_I"E,,8"_IV7"C,4|"_I7"E,,4"_Vadd9/VIIo"A,,4"^LT""_VIIo"^D,,2"^9!"C,,2|"_I"E,,4"_(III)"G,,4"_II"F,,2A,,2|"_A: V/V"B,,4"^9!"C,4"_V7"E,,4|"_I"A,,8"_Em: V"B,,4|"_I7"E,,8"_VI7"G,,4|"_II7"F,8"_III"C,4|"_I64"B,,8"_V"B,,4|"_I"E,,4F,,4E,,4|

It looks like this: image

Here notes are too close to each other, considering the spacing of other notes: image

Here notes are too close to the bar, considering the space between the bar and the next note: image

This is how it looks without text:

M:3/4
K:G
L:1/16
V: V0 clef=treble name="Sop."
V: V1 clef=treble name="Alt."
V: V2 clef=treble-8 name="Ten."
V: V3 clef=bass name="Bas."
[V: V0]z8^d4|e4B4A4|B2A2B4A4|G8F4|F8^G4|A4E4F4|=G4D2E2=F4|E12-|E6G2^D4|E12|
[V: V1]z8A2B2|G8G4-|G4E4F4|E4D4C2D2|^D8=D2E2|^C8^D2C2|E4B,4D4-|D4C4E4|B,8B,4|B,4C4B,4|
[V: V2]z8c2^d2|B8e4|d2e2^c4=c4-|c4B4A4|B8B4|E2F2G2A2B4-|B4G4B4|A8G4|G8F4|G4A4G4|
[V: V3]z8B,,4|E,,8C,4|E,,4A,,4^D,,2C,,2|E,,4G,,4F,,2A,,2|B,,4C,4E,,4|A,,8B,,4|E,,8G,,4|F,8C,4|B,,8B,,4|E,,4F,,4E,,4|

The problems seem the same: image

It seems that these problems can be partially solved by tuning some minSpacing parameter, where can I find it?

I was able to produce a better spacing with wrap by using minSpacing = 1.1: image

But still some distances from notes to bars could be better.

paulrosen commented 4 years ago

I think the problem is there are too many notes for the width of the staff. If you don't set it, I think it is set to 700px. You can make it longer with staffwidth 1000 or something. It will try to space the notes out better then.

rualark commented 4 years ago

Thanks! The problem is that user changes notes interactively in visual editor and I cannot set specific staffwidth.

paulrosen commented 4 years ago

I suppose one of the options similar to wrap could be "make staff wider" that takes a number that is how close notes can be to each other and a minimum width.

I need to think about how to present that.

rualark commented 4 years ago

Yes, something like minSpacing.

eltomjan commented 4 years ago

Found interesting workaround - in case you need to move something for a bit left or right, you can add short code to JS (abcjs_basic_6.0.0-beta.8.js) and using dragging.html example... Then select element by mouse or TAB to and use left/right arrows to move.

    case 37: // <-
    case 39: // ->
      handled = true;
      this.dragTarget = this.history[index];
      this.dragIndex = index;
      var transform = this.dragTarget.svgEl.transform.baseVal[0];
      var dir = ev.keyCode - 38;
      if (transform) {
          transform.matrix.e += dir;
      } else this.dragTarget.svgEl.setAttribute("transform", "translate("+dir+",0)");
      break;

Place that to function keyboardSelection(ev) of ./src/write/selection.js In abcjs_basic_6.0.0-beta.8.js I placed that starting from line 23539.

Thought it would be nice to have separate JSON field holding updated tune elements info for particular elements, but it would be quite complex to redraw them (lot of points to change, hard to find where to update lib for this, etc.).

Hope it is not a secret, but single note C is located here Editor.tunes[0].lines[0].staff[0].voices[0][0] and looks like this (abselem.children[4] excluded):

"lines": [{
    "staff": [{
        "voices": [[
            {
                "pitches": [
                    {
                        "pitch": 0,
                        "verticalPos": 0,
                        "highestVert": 6
                    }
                ],
                "duration": 0.125,
                "el_type": "note",
                "startChar": 0,
                "endChar": 1,
                "averagepitch": 0,
                "minpitch": 0,
                "maxpitch": 0,
                "abselem": {
                    "tuneNumber": 0,
                    "duration": 0.125,
                    "durationClass": 0.125,
                    "minspacing": 1,
                    "x": 49.051,
                    "children": [
                        { ... }, ...
                    ],
                    "heads": [ null ],
                    "extra": [ null ],
                    "extraw": 0,
                    "w": 15.902000000000001,
                    "right": [ null, null ],
                    "invisible": false,
                    "bottom": -1.0443870967741935,
                    "top": 7,
                    "type": "note",
                    "specialY": {
                        "tempoHeightAbove": 0,
                        "partHeightAbove": 0,
                        "volumeHeightAbove": 0,
                        "dynamicHeightAbove": 0,
                        "endingHeightAbove": 0,
                        "chordHeightAbove": 0,
                        "lyricHeightAbove": 0,
                        "lyricHeightBelow": 0,
                        "chordHeightBelow": 0,
                        "volumeHeightBelow": 0,
                        "dynamicHeightBelow": 0
                    },
                    "elemset": [
                        {},
                        {}
                    ]
                }
            }
        ]],

Interesting here is also startChar / endChar which links to abc source text - thinking about logic to mix voices - in case I have multi voices in some parts (start single, ex. refrain has multi and there are some special repetitions) MIDI is generated wrong - next voices lost sync and play something/somewhere different, so easiest fix is to mix them all to one staff line before playing, but hard / slow to do by hand... But mixed voices looks ugly on sheet, so it is better to have source with separate and option to mix them before generating MIDI.