LMMS / lmms

Cross-platform music production software
https://lmms.io
GNU General Public License v2.0
8.04k stars 1k forks source link

Unicode key names and file content support (Or, ASCII font based cultural symbols) #7238

Open anytizer opened 5 months ago

anytizer commented 5 months ago

What can be done to allow unicode based key names here? The file should be able to compile when saved with Unicode Byte Order mark.

https://github.com/LMMS/lmms/blob/d5f5d00a6f1faabdba4f710d04ad303bd439a6f2/src/gui/editors/PianoRoll.cpp#L123-L125

6162 Desiring unicode labels.

michaelgregorius commented 5 months ago

For me it also compiles and works if I simply replace the code with the symbols:

static std::array<QString, 12> s_noteStrings {
    "C", "C♯ / D♭", "D", "D♯ / E♭", "E", "F", "F♯ / G♭", 
    "G", "G♯ / A♭", "A", "A♯ / B♭", "B"
};

I am not sure if it depends on the system though. It also doesn't work with every character. If I replace one flat with an emoji (🤩) it does not work. I guess that's because the font used on my system doesn't have the emoji.

irrenhaus3 commented 5 months ago

UTF-8 will be guaranteed to be accepted as an input by all C++23-compilant compilers as per https://wg21.link/P2295R6 Until then however, it's generally not portable to encode C++ source files as UTF-8, so putting non-ASCII characters in them might work or it might not. If we want to try, we could test it in our CI to see if any compiler stumbles upon them.

Edit: I should note that all big-3 compilers (GCC, clang and MSVC) already accept UTF-8 encoded files, and have been doing so for years. GCC in particular did it 10 years ago already, so I don't expect many problems with this.

anytizer commented 5 months ago

Just a thought:

Can we "embed" a non-unicode font or SVG symbols for these keys? I had tried replacing with unicode texts in the source file, but I got square blocks instead, when executing the LMMS binary. It may be due to that the machines I used did not have proper unicode fonts.

If we could implement an embedded font file, these symbols would be ASCII like characters from that font, available to all machines; at the additional cost of new font file's disk size.

Veratil commented 5 months ago

Yes, we can add custom fonts via

QFontDatabase::addApplicationFont("/path/to/font.ttf");
anytizer commented 5 months ago

Just borrowed some glyphs from Tillana font | @itfoundry/tillana . I reordered the symbols into characters: A, B, C, D, E, F, G, H, I, J, K, L - as the 12 keys. Resized the numerals into smaller font size to mark the octave numbers. 0 , 1, 2, 3, 4, 5, 6, 7, 8, 9, *, . and a - sign. If it works with these symbols, it can work for any other language. :-)

Expanded set of fonts: culture-keys-for-lmms.zip

Notes: Font preview removed. Added more fonts.

anytizer commented 5 months ago

Yes, we can add custom fonts via

QFontDatabase::addApplicationFont("/path/to/font.ttf");

Font based system worked under Ubuntu. But here are new challenges:

Keys → Culture ↓ C C# D D# E F F# G G# A A# B Notes
English C C# D D# E F F# G G# A A# B Currently in use
Using Flats C D♭ D E♭ E F G♭ G A♭ A B♭ B The word "komal" from classical systems represent flats
Classical सा .रे रे .ग म' .ध ऩि नि Dots to be replaced with underlines
Short form S r R g G m M P d D n N Best selected, as all notes may be in ASCII range.
In Proposed Font A B C D E F G H I J K L All capitals, Binary Character Table - Character set
ASCII in Font 65 66 67 68 69 70 71 72 73 74 75 76 All cultures' symbol should appear in these ASCII characters (replacement)

There are at least 3 places that need new font information, and sharing keys:

  1. Under combo box "No Key" - []()
  2. On the piano labels - []()
  3. At the actual note names in the roll - []()

Important bookmarks:

michaelgregorius commented 5 months ago

This could be implemented with an interface that replaces s_noteStrings. It would have the following functionality:

  1. Provide the font to use for a given QPaintDevice.
  2. Map the index 0-11 to the string that should be painted with that font.

The currently used "English" implementation would simply return the font of the QPaintDevice and map the indices to the values that are currently in s_noteStrings.

The other implementations will return the font that was registered for them via QFontDatabase::addApplicationFont and return the appropriate strings for the indices, e.g. 0 -> "A", 1 -> "B", 2 -> "C", etc.

anytizer commented 5 months ago

Thank you @michaelgregorius. I am making a font for at least 3 notation names (cultures). For predefined single culture, it works. But to add more cultures, we might need an option to pick which system to display/use.

Meanwhile, is it necessary to check a minimum height? https://github.com/LMMS/lmms/blob/d5f5d00a6f1faabdba4f710d04ad303bd439a6f2/src/gui/editors/PianoRoll.cpp#L1026

I had to put the value "4" instead of "6" here, so that notation name got printed on the green note in the roll.

Also, this picture is great to know related to this thread. :-)

michaelgregorius commented 5 months ago

Thank you @michaelgregorius. I am making a font for at least 3 notation names (cultures). For predefined single culture, it works. But to add more cultures, we might need an option to pick which system to display/use.

IMO the option should then be moved from the main menu into the preferences/settings. An additional combo box could be added which lets the users select the notation system that they want to use.

Meanwhile, is it necessary to check a minimum height?

https://github.com/LMMS/lmms/blob/d5f5d00a6f1faabdba4f710d04ad303bd439a6f2/src/gui/editors/PianoRoll.cpp#L1026

I had to put the value "4" instead of "6" here, so that notation name got printed on the green note in the roll.

The check was added so that we do not render text that gets too tiny. See the commit message of 0dc28436fab. If you keep it as is then the text should get rendered if you increase the vertical zooming of the piano roll.

Veratil commented 5 months ago

I haven't checked, but does any of MuseScore's fonts contain the glyphs we're wanting? If so we may be able to use that.

anytizer commented 5 months ago

Just checked: Leland and Edwin - they are huge collection of symbols. I am looking for text based glyphs for readable notes.

My current plan is to build limited font files, per culture for testing purpose. If it works, we can replace with higher quality glyphs from these fonts; even assuming symbols as a culture. Here is the glyph preview list:

devanagari-keys-for-lmms.ttf image

doremi-keys-for-lmms.ttf (in progress)

nashville-keys-for-lmms.ttf (not sure if it is correct) image

sargam-keys-for-lmms.ttf image

solfege-keys-for-lmms.ttf image

Here are the .birdfont files if anyone might be interested in improving these glyphs. keys-for-lmms.zip

anytizer commented 5 months ago

Updates:

Here is a proof that that it now works for the defined culture name (sargam in this case). It is based on embeddable font, and not unicode dependencies to have the missing glyphs. sargam notes

Some questions are about managing the file structure of these fonts and notation system, as well modifying the various parts of PianoRoll.cpp.

Veratil commented 5 months ago
  • How should we organize the file names

It should be a single file, allowing us to utilize the tr() translation function.

  • Qt Font Database does not warn about missing .ttf fonts. In that case, a wrong letter/symbol would display

If it's shipped with LMMS, then we just can check if the file exists in the place we expect and warn if missing.

  • Font size might matter. Somewhere we have 80% of the line height for the font size

This can be adjusted to set the size of the font based on the size we want through QFontMetrics probably.

  • How to display the flats or sharps in one culture?

Translations should take care of that.

  • or let the user choose them

This is the way: translations.