tomoyu719 / simple_sheet_music

A Flutter package for rendering sheet music.
https://pub.dev/packages/simple_sheet_music
MIT License
10 stars 6 forks source link

Speeding up the loading of music symbol paths and metadata #28

Open tomoyu719 opened 1 month ago

tomoyu719 commented 1 month ago

Overview

The process of retrieving music symbol paths and metadata is slow, which has a negative impact on the user experience. To improve this, we propose to review the asynchronous processing and make it possible to retrieve data synchronously.

Objective

Shorten the loading time of music symbols and provide a smooth user experience. Abolish the currently used FutureBuilder and implement a simpler approach.

Proposal

Introduce a mechanism to synchronously retrieve music symbol paths and metadata, referring to techniques such as Vexflow. Shorten loading time by minimizing asynchronous processing. Review and optimize the existing code base.

Scope of impact

All components that display music symbols are affected, so thorough testing is required.

Expected results

Music symbols will be loaded faster, reducing user waiting time.

lukasnalezenec commented 1 month ago

Synchronous processing makes sense. It is common pattern used in similar components.

In the past, I created a pull request that minifies both the Bravura font and metadata, reducing their size to about 1%. I can commit the Python code I used for the minification.

There is also an alternative solution to the issues with FutureBuilder. This solution uses parallel asynchronous loading of the metadata and font, passing the result as part of the Future value.

https://github.com/tomoyu719/simple_sheet_music/pull/18

lukasnalezenec commented 1 month ago

... I can also generate those classes.

lukasnalezenec commented 1 month ago

Do you have any ideas about comparing writing symbols using SVG versus fonts? Have you encountered any issues with writing using SVG?

lukasnalezenec commented 1 month ago

Note that the y numbers are already multiplied by -1


final boundingBoxes = {
  "accidentalDoubleFlat": Rect.fromPoints(
    Offset(0.0, 0.7),
    Offset(1.644, -1.748),
  ),
  "accidentalDoubleSharp": Rect.fromPoints(
    Offset(0.0, 0.5),
    Offset(0.988, -0.508),
  ),
  "accidentalFlat": Rect.fromPoints(
    Offset(0.0, 0.7),
    Offset(0.904, -1.756),
  ),
  "accidentalNatural": Rect.fromPoints(
    Offset(0.0, 1.34),
    Offset(0.672, -1.364),
  ),
  "accidentalSharp": Rect.fromPoints(
    Offset(0.0, 1.392),
    Offset(0.996, -1.4),
  ),
  "cClef": Rect.fromPoints(
    Offset(0.0, 2.024),
    Offset(2.796, -2.024),
  ),
  "fClef": Rect.fromPoints(
    Offset(-0.02, 2.54),
    Offset(2.736, -1.048),
  ),
  "flag128thDown": Rect.fromPoints(
    Offset(0.0, 2.320034471092627),
    Offset(1.092, -3.248),
  ),
  "flag128thUp": Rect.fromPoints(
    Offset(0.0, 3.248),
    Offset(1.044, -2.1320003247537183),
  ),
  "flag16thDown": Rect.fromPoints(
    Offset(-1.9418183745617774e-05, 0.03601094374150052),
    Offset(1.1635806326044895, -3.2480256),
  ),
  "flag16thUp": Rect.fromPoints(
    Offset(0.0, 3.252),
    Offset(1.116, -0.008),
  ),
  "flag32ndDown": Rect.fromPoints(
    Offset(0.0, 0.687477099907407),
    Offset(1.092, -3.248),
  ),
  "flag32ndUp": Rect.fromPoints(
    Offset(0.0, 3.248),
    Offset(1.044, -0.596),
  ),
  "flag64thDown": Rect.fromPoints(
    Offset(0.0, 1.5040263329569774),
    Offset(1.092, -3.248),
  ),
  "flag64thUp": Rect.fromPoints(
    Offset(0.0, 3.248),
    Offset(1.044, -1.387108),
  ),
  "flag8thDown": Rect.fromPoints(
    Offset(0.0, 0.0575672),
    Offset(1.224, -3.232896633157715),
  ),
  "flag8thUp": Rect.fromPoints(
    Offset(0.0, 3.240768470618394),
    Offset(1.056, -0.03521239682756091),
  ),
  "gClef": Rect.fromPoints(
    Offset(0.0, 2.632),
    Offset(2.684, -4.392),
  ),
  "noteheadBlack": Rect.fromPoints(
    Offset(0.0, 0.5),
    Offset(1.18, -0.5),
  ),
  "noteheadHalf": Rect.fromPoints(
    Offset(0.0, 0.5),
    Offset(1.18, -0.5),
  ),
  "noteheadWhole": Rect.fromPoints(
    Offset(0.0, 0.5),
    Offset(1.688, -0.5),
  ),
  "rest128th": Rect.fromPoints(
    Offset(0.0, 3.0),
    Offset(1.94, -2.756),
  ),
  "rest16th": Rect.fromPoints(
    Offset(0.0, 2.0),
    Offset(1.28, -0.716),
  ),
  "rest32nd": Rect.fromPoints(
    Offset(0.0, 2.0),
    Offset(1.452, -1.704),
  ),
  "rest64th": Rect.fromPoints(
    Offset(0.0, 3.012),
    Offset(1.692, -1.72),
  ),
  "rest8th": Rect.fromPoints(
    Offset(0.0, 1.004),
    Offset(0.988, -0.696),
  ),
  "restHalf": Rect.fromPoints(
    Offset(0.0, 0.008),
    Offset(1.128, -0.568),
  ),
  "restQuarter": Rect.fromPoints(
    Offset(0.004, 1.5),
    Offset(1.08, -1.492),
  ),
  "restWhole": Rect.fromPoints(
    Offset(0.0, 0.54),
    Offset(1.128, -0.036),
  ),
  "stem": Rect.fromPoints(
    Offset(-0.06, -0.0),
    Offset(0.06, -3.5),
  ),
  "timeSig0": Rect.fromPoints(
    Offset(0.08, 1.0),
    Offset(1.8, -1.004),
  ),
  "timeSig1": Rect.fromPoints(
    Offset(0.08, 1.0),
    Offset(1.256, -1.004),
  ),
  "timeSig2": Rect.fromPoints(
    Offset(0.08, 1.028),
    Offset(1.704, -1.016),
  ),
  "timeSig3": Rect.fromPoints(
    Offset(0.08, 1.004),
    Offset(1.604, -0.996),
  ),
  "timeSig4": Rect.fromPoints(
    Offset(0.08, 1.0),
    Offset(1.8, -1.004),
  ),
  "timeSig5": Rect.fromPoints(
    Offset(0.08, 1.004),
    Offset(1.532, -0.984),
  ),
  "timeSig6": Rect.fromPoints(
    Offset(0.08, 0.996),
    Offset(1.656, -1.004),
  ),
  "timeSig7": Rect.fromPoints(
    Offset(0.08, 1.0),
    Offset(1.684, -0.996),
  ),
  "timeSig8": Rect.fromPoints(
    Offset(0.08, 1.036),
    Offset(1.664, -1.036),
  ),
  "timeSig9": Rect.fromPoints(
    Offset(0.08, 0.996),
    Offset(1.656, -1.004),
  )
};
tomoyu719 commented 1 month ago

@lukasnalezenec The BoundingBox wants to obtain the BoundingBox from the SvgPath. This is to ensure consistency. First, we would like to create some kind of script, like VexFlow, to be able to handle SvgPath in Dart's Map format.

lukasnalezenec commented 1 month ago

"That would work. But every music font contains a definition of bounding boxes. And this code is based on the official data, so in the end, you'll get the same result anyway."