-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scroll a view into certain position given as Measure/Beat #166
Comments
@hugbug - I have started to design the changes for adding this functionality. My initial idea was to add a new method There are a variety of situations, not only to display a visual cursor or for scrolling, in which the measure location of a musical event needs to be described, in terms of the content of the measure. The simpler and most convenient method for describing measure location is to express it as a time position, expressed as note durations after the start of its containing measure. For instance, it could be specified as a valid floating-point number that gives the number of whole notes from the start of the measure. Examples:
Another alternative would be to express location in lomse time units (TU). For instance, in Lomse the duration of a whole note is 256 TU. Therefore the above examples would be now:
When using measure locators in time units as above described, the beats in a 4/4 time signature would be at locations 0, 64, 128 and 192. Expressing location in time units has the advantage of being a general measure locator for other purposes, allowing for instance to position a cursor at any note, not only on beat notes or to precisely position an internal cursor at any place in the measure. And for scrolling to a given location a new method But using beats as a locator would require to determine the applicable time signature for the desired measure and to convert 'beat' to 'location'. Although Lomse performs currently these computations, the complexity comes from the objects involved in doing these computations. In current Lomse code, the knowledge for determining beats is associated to the |
Thank you for the explanation.
I like this idea. In my app I'm completely dependent from the external hardware - Yamaha Digital Piano. It provides playback position information as Measure/Beat. I would need to know time signature of a specific measure to compute Or maybe I can use I've attached an example MusicXML-file which has time signature changes in the middle. I'll be testing with it and you may find it useful too. |
My current idea is that all parameters (color, height and width) will be customizable. The above approach will be independent of the final approach to specify the cursor position (using beats or using time units). The approach using time units As I write this, I realize that for cursor width my first idea of specifying it in time units is not good, as for highlighting beats the width (in time units) depends on the beat duration. If in the score there are time signature changes, highlighting beats will require to dynamically adapt cursor width to current time signature. So:
Ok, thank you. Question answerd. I think it is better if lomse is able to deal with beats. |
@juuk100 Latest PR fixes this. The API documentation has been updated and a brief text explaining how to use these new methods has been included. See https://lenmus.github.io/lomse/page-sound-generation.html#sound-generation-external-player |
Thank you very much, great work! |
I've integrated the new Lomse version into my app. It works amazingly well!And because you did all the heavy lifting by implementing native Measure/Beat support, all I needed was to add just a couple of lines to glue the things together. (very happy) So far I've discovered a small glitch. I'm testing with musicxml-file attached above. Most measures have 4/4 signature but there are few with 5/8 and 3/8. Measure 21 has 3/8 signature. The tempo line isn't correct for beats 2 and 3. NOTE: here measure and beat numbers are counted from 1. Measure 21, Beat 1 - displayed correctly:Measure 21, Beat 2 - incorrectly displayed at the beginning of measure 22:Measure 21, Beat 3 - incorrectly displayed in the middle of measure 22:Measure 22, Beat 1 (displayed correctly):Tempo line colorTo change tempo line color I needed to subclass |
I think the tempo line is positioned correctly. 3/8 time signature has only one beat per measure, so after measure 21 beat 1 the next beat is measure 22 beat 1. Therefore, location m21/b2 is three eighth notes after m21/b1 so it is equivalent to m22/b1 and location m21/b3 is six eighth notes after m21/b1 so it is equivalent to the place displayed on the image, in the middle of m22/b2. Are locations m21/b2 and m21/b3 provided by Yamaha piano or are computed by your app? If it is Yamaha piano, I would report a bug to Yamaha. Is it possible for you to check the behaviour of Smart Pianist with this score?
I think the tempo line should be on the note, not on the 4/4 time signature. This is caused by the bug addressed in issue #173. Hope to fix this issue soon. As to how to customize visual effects, I totally agree with you that methods in Interactor must be provided. I'll do it. |
Thinking on this, as the concept of beat is tricky, perhaps Yamaha piano is using as beat the bottom number in the time signature. So any x/8 time signature would use for beat an eighth note. The problem of this approach is that metronome beats will not coincide with Yamaha MIDI beats. Can you test the behaviour of Yamaha piano when the Yamaha piano metronome is switched on while playing back? |
Thanks for the info. This reinforces my guess that Yamaha piano is using as beat the bottom number in the time signature. I did a test with this score using MuseScore to see how they deal with the metronome, from measure 18 to measure 24, and they do as Yamaha piano beats. Metronome is clicking in every quarter note until measure 19; then, in measure 20, it clicks on every eighth note, and returns to click in every quarter note in measure 22. This is not a 'normal' metronome behaviour but, probably, it is the simplest way of dealing with rare time signatures such as 5/8. But I do not understand MuseScore metronome behaviour because when opening a 6/8 score I would expect it would click every three eighth notes or on every eight note, but ... it clicks on every quarter note! three clicks per measure! It would be nice if you could do tests with scores using different time signatures to confirm that Yamaha piano is using as beat the bottom number in the time signature.
The concept of beat is fuzzy and it depends on the purpose. For example, for playing, it depends on how the music is conducted or how you would like to practise (i.e. metronome click for quarter notes or for eighth notes, etc.); from a theoretical point of view, depends on time signature: 3/8 is just one beat per measure. There are 'tricky' time signatures, e.g. 5/8 can be counted as 5 eights or as alternating sub-measures of 2/8+3/8 or 3/8+2/8 (two beats per measure). It is difficult to define what is a beat because there are many definitions, depending on the purpose.
Yes. But before proceeding it would be nice if you could do tests with scores using different time signatures to confirm that Yamaha piano is using as beat the note implied by the bottom number in the time signature. There is also the problem of music without time signature (i.e. some very commonly studied Erick Satie piano pieces). So, the idea would be to allow the user application to define what is a beat before using methods requiring measure/beat parameters or to add an additional parameter to these methods. I devise, for now, the following options:
Other ideas, suggestions? |
I'll gladly do the test on the piano. If you happen to have a set of test files (musicxml or midi or anything MuseScore can open) I could test them instead. |
Perhaps some scores from the Lilypond test set would be enough |
The results for file 11a-TimeSignatures on Yamaha piano:
The number of metronome clicks is equal to number of position events and to number of cursor movements in Smart Pianist. |
Thanks. This supports my guess that Yamaha Piano is using as beat the note implied by the bottom number in the time signature. |
There is one issue which makes such tests with the piano not fully reliable. Smart Pianist can read only midi-files. It then sends the midi-files as is to piano. MIDI-format of course doesn't have enough information to display scores properly, in particular it doesn't have measures nor signatures. Once a song (midi-file) is selected in Smart Pianist it sends the song to piano and then the app shows the score. For this the app has to transform midi to score. This can't be made with 100% certainty because some guess work is needed. To make life even more complex the piano does its own job to decode midi-file and to guess time signatures. We can only hope that the piano and the app both use the same algorithm to decode midi-files but we don't know that for sure. Therefore the time signatures displayed in Smart Pianist are not necessary the same signatures which were in initial musicxml-document (before it was exported to midi in MuseScore). In fact if I import the midi back in MuseScore it sometimes shows different signatures. This especially happens for test files where first measure isn't full. Therefore it seems it wasn't the best idea to use midi-files as interchange format between app and piano. On the other side both the piano (all digital pianos actually) and the app are not marketed for professionals but merely for hobby pianist and for home use. With classic repertoire the app and piano do pretty good job actually. So please keep all this in mind when reading the following test results. 11c-TimeSignatures-CompoundSimple
So it seems although the app didn't show time signature 9/4 for the second measure the piano has detected it correctly and the metronome clicked 9 times. The app also moved playback cursor 9 times as well. However it didn't show a signature for the second measure as if it were having the same signature as the first measure. 11d-TimeSignatures-CompoundMultiple
Midi-file imported back in MuseScore shows time signature 21/8. 11e-TimeSignatures-CompoundMixed
Metronome bell clicked after second beat click. It seems the piano detected two measures: first incomplete measure with two clicks and then a complete measure with 11 clicks. 11b-TimeSignatures-NoTime
Similar to previous one. I think you shouldn't pay much attention to these special cases as we can't tell for sure what signatures piano were dealing with in the first place. Maybe the app and piano would detect signatures better if they were feed with a proper song instead of test file containing only one or two measures. It depends on how good MIDI deciphering is. |
Very illustrative and interesting results! Thank you. MIDI conversion could be a problem but, as you said, probably not for the most common scores for hobby pianists. I now do not understand clearly how your application works, as it seems that two files are needed, the MusicXML and the Midi. Does your application convert MusicXML to a Midi file and send the Midi file to the piano? Or it is the user who generates and deals with the two files, loading midi in the piano and MusicXml in your app? Anyway, to try to improve Lomse support, I would appreciate that, if feasible and not complex, perhaps you could check if Yamaha piano is sending MIDI Time Signature meta messages. See http://www.recordingblogs.com/wiki/midi-time-signature-meta-message |
In my app user selects a midi-file and the app sends it to piano. Then the app looks for the file with the same filename but with .musicxml or .xml extension and loads it into Lomse score viewer. The user is responsible for providing both files (.midi and .muscixml). Initially I wanted to require midi-files only (similar to Smart Pianist) and I needed a way to render scores from midi-files. However it seems to be a very difficult job to decipher midi-files into scores. I've found MuseScore midi-importer to produce results very similar to Smart Pianist. I thought about reusing MuseScore' midi-importer in my app but it is a large module and heavily depends on Qt which I don't use in my app. Currently I'm planning to stick with current approach (user has to provide both files) as it allows me to focus on app related things. Writing a midi-importer (even reusing the one from MuseScore) is a project on it's own. Very interesting about time signature event. There is a way to embed time signature into midi-file after all! I wonder if piano would use that information if it would be provided in the midi-file. I'll construct a midi-file with signatures and will test how piano reacts. I did a lot of analysis of midi events sent by piano but can't remember this particular event. I'll test again to make sure about this and write back. |
Thank you. If you discover that piano is sending time signature events, then the definition of beat will be there and you could inform lomse about a beat definition change. This will solve the problem and will solve all time signature cases!
Another alternative would be that in your application the user selects a MusicXML file, and then your app will generate the midi file and send it to the piano. This approach will give you full control of beats definition for time signatures. And conversion from MusicXML to midi file could be done by lomse. It should not be difficult as midi events are currently generated. It will be just writing the events table to a file in the appropriate format as well as some additional information. This is pure C++ and something I had in my TODO list, but it is very low priority as there are more important and urgent tasks for me. Perhaps you would be interesting in contributing with this; I will help you. Probably he main job is to study and understand the midi file format. The lomse MIDI exporter could be something to do in future, for version 2.0 of your application. This will remove the burden from the user of providing both files, although I would maintain that possibility, as it is included in your application version 1.0. In any case, I have started to code the changes for allowing lomse user applications to define what is a beat. This will solve most of the cases without changing your application and your current approach. |
I did the testing. Piano doesn't send time signature events. But there is another interesting thing. I've inspected midi-files created by MuseScore from musicxml-files. These midi-files do contain time signature meta events! I've made a test and removed these events from a midi-file. I've used 11a-TimeSignatures file which contains many different time signatures and which worked perfectly in Smart Pianist and in piano metronome. After removing events Smart Pianist were not able to display proper score. The piano played the song correctly (note on/off events are there after all) but metronome didn't work properly. That's a nice finding! Both Smart Pianist and piano do use time signatures from midi-files. And not only use, they heavily rely on them. |
I've checked time signature meta events in other files. Below are the same tables as above but with new column Signature in midi-file 11c-TimeSignatures-CompoundSimple
So the piano (metronome) uses time signature from midi meta event. It's strange however that Smart Pianist doesn't show proper signature for second measure (it doesn't show time signature on second measure as if it were not changed; therefore I've written 5/8 in the table). 11d-TimeSignatures-CompoundMultiple
So the piano (metronome) uses time signature from midi meta event. It seems MuseScore isn't exporting correctly. Not a fault of piano then. Smart Pianist again doesn't show signature change on second measure. 11e-TimeSignatures-CompoundMixed
Once again time signature isn't correctly exported. |
The conclusion is clear to me: beat definition will depend on how the Midi file was generated and on the interest of the generator application in preserving time signature. Therefore, there is no solution in lomse for this. I will maintain the idea of allowing to define what is a beat, as it is useful for other purposes, such as fine control of metronome, and also could solve your problem for "standard" scores. Also, I will provide a method move_tempo_line_to(measure, location) and related, as seem to be more useful than the equivalent methods using measure/beat. And for your application, for a better solution, you will need either: |
Thank you for your continued work on this issue.
It would be absolutely enough if Lomse could deal with Yamaha-beats. It's a responsibility of my app (or user) to provide proper midi- and musicxml-files. We can assume that midi-file contains time signatures and the musicxml-file is in sync with midi-file (both represent the same content and have same time signatures).
Being able to select MusicXML files and automatically generate midi is certainly a good idea. Still midi is a primary format for other use case in my app. The piano has full set of MIDI voices and can play very complex midi-files. There are two intended use cases:
I need to (re)implement many features to make my app really useful. I'm afraid I will not be able to contribute to MIDI export feature, at least not in the foreseeable future. I'm glad I've "invented" the trick with requiring two files, so that I can "outsource" a part of work to users instead of implementing midi decoding myself. |
Current new methods using measure/beat are there. A new method Default value when nothing specified is
After committing all these changes, I will also provide equivalent methods to those using measure/beat parameters, but using measure/location parameters; this could be used for instance, if your application would like to deal with beats and compute the position for better control.
No problem. It was just an idea in case you would like to have total control on midi generation.
Yes, this greatly simplifies the problem! |
Beat positioning works perfect now! Also tried the new tempo line adjustments - works as expected. And the auto scrolling is much improved as well. Thank you very much! |
Thanks for the feedback! |
Current API does not permit to scroll a view into a certain position given as Measure/Beat information. The need for this feature was identified in issue #163.
As lomse documents can contain not only just one score but full documents with texts, lists, images, many scores, etc., this feature will be restricted for documents containing only one score, such as MusicXML imported files.
The text was updated successfully, but these errors were encountered: