Menu

#1627 MIDI export changes note duration

None
open
None
5
2022-05-05
2022-03-29
No

Rosegarden version: 1:20.12-1 (Debian 11.3 "bullseye")

The attached Rosegarden file is a simplified version of a problem that I encountered while sequencing a much longer and larger MIDI file. That file started life as a Lilypond-generated MIDI file, which I then imported into Rosegarden and massaged until I liked how it sounded.

This file looks very simple: it has a time signature, a tempo change, and a D scale in quarter notes. When I play it in Rosegarden, it sounds exactly how you'd expect. But when I export it as MIDI, all this information is preserved -- except that several of the quarter notes (three in a row, beginning with the third beat of measure 2) become MUCH shorter -- they appear to become a bit more than an eighth note, although they aren't an even multiple of 1/64. The original had multiple segments playing simultaneously, and they all were affected.

My expectation is that the MIDI file should sound more or less the way it does in Rosegarden, and specifically that the events should look pretty much the same.

The only thing I can find that's really weird is the way that the file starts at measure 0. This is preserved from the original, which used Rosegarden's "Anacrusis" feature to start on the pickup to measure 1. Interestingly, if I drag the segment back to start at measure 1, the shortened beats "stay in the same place" -- that is, a DIFFERENT set of three notes get shortened, but it's still three notes starting at beat 3 of measure 2.

I've experimented with removing / tweaking various things in the music to see if the problem goes away. The one thing that helps is removing all tempo changes -- but (at least in the original) the problem comes back when I re-enter the tempo changes.

If I've created it correctly, the attached tarball contains the original Rosegarden file, the exported MIDI, and some screenshots of what I'm seeing (the original file and various exported versions) in the Matrix View.

Thanks!

1 Attachments

Discussion

  • Daniel Burrows

    Daniel Burrows - 2022-03-29

    Playing around a little more, I constructed an identical file from scratch. It also exhibits the behavior described above, although the point where the shortening starts appears to be different. I've attached it as an example to remove one more variable (the previous file had a long edit history and I imagine some weird corruption could have been carried forward).

     
  • Mark R. Rubin

    Mark R. Rubin - 2022-04-01

    I tested this out of curiosity, mainly because I've had reports that RG-exported MIDI files I've emailed to friends won't play on macOS.

    I used the latest [abdf22] commit and I can confirm the problem with simplified-bug-from-scratch.rg. Also, if the exported MIDI file is re-imported back into RG it runs from measure 2 to 134+1/3 with the timeline starting at 1 instead of original's timeline at 0 and the segment from 1 to 3+2/3. If the new, long segment is moved to start at 1 and the tempo change shifted to match, and then re-exported as MIDI, a similar but different shortening of the notes happens. All of this to say that the anacrusis might not be the problem.

    FWIW, I'm attaching the output of lilymidi --dump on the original MIDI export. I'm not 100% sure how t interpret the timestamps in that, so I'm also attaching the output of an old utility of mine which I do understand and think is fairly intuitive. Both show the shortened notes.

    I don't have time right now (nor likely the expertise anyway) to look at RG's MIDI exporter. If someone else provides a fix I'll retest emailing a MIDI file to my macOS-using friends and report if they still have problems.

     

    Related

    Commit: [abdf22]

  • Yves Guillemot

    Yves Guillemot - 2022-04-01

    The problem comes from the combination of anacrousis and tempo change.

    Here are four test files with the same four notes:
    - test1.rg : no anacrousis, no tempo change
    - test2.rg : anacrousis, no tempo change
    - test3.rg : no anacrousis, tempo change
    - test4.rg : anacrousis, tempo change

    Exporting the four compositions to midi then reimporting them to RG shows that test4.mid only is wrong.
    Dumping the .mid files with smfsh shows that the problem exists in the test4.mid. So the issue is related to exporting midi file and not to importing them (at least not only...)
    The screen copies shows something which looks like a mismatch between the wanted 80 bpm tempo and the default 120 bpm tempo preceding it.

     
  • Philip Leishman

    Philip Leishman - 2022-04-02

    Yes - anacrusis and tempo change. Or more generally - negative start time and tempo change.
    I think the negative start time is a problem.
    Question:
    Must we have negative start time ? The anacrusis could be achieved by shifting the whole composition one bar to the right and then extending the selected segments to the left.
    This would have the same effect except that the bar numbers would be shifted.
    Also disallow numbers less than one in the composition start/end dialog.
    What do you all think ?

     
  • Ted Felix

    Ted Felix - 2022-04-02

    Must we have negative start time ? The anacrusis could be achieved by shifting the whole composition one bar to the right and then extending the selected segments to the left.

    This is what I usually do. However, a lot of effort went into implementing that anacrusis feature, so there must have been a very good reason. My best guess is so that there would be no silence at the beginning of a composition. Be it .rg, MIDI file, or lilypond. I suspect lilypond is really the key here. An anacrusis must look like an anacrusis in lilypond or else there's no point in having the feature. So I don't think a one bar shift would be a good idea.

    Unfortunately, the MIDI rendering code which serves both the sequencer and MIDI file export is really complicated and brain melting. I've been in there a few times and I can probably take a shot at fixing this. But I'm not going to be happy. 🤣

    If you can come up with a clever alternative that looks right in notation and lilypond, and plays right in the sequencer and MIDI files, then that would probably be fine. Hopefully there's someone on the user list that uses this and can make sure we've not broken something.

     
  • Philip Leishman

    Philip Leishman - 2022-04-02

    So I made two files. One with a 2 bar segment and anacrusis. The second with a 2 bar segment starting at bar 2 - then shifting it back a quarter note (essentially what the shift as described above would do.
    I can detect no real difference between the two (except for the bar numbers) - either as initial silence or as lilypond output.
    Here is an image showing the two files in rosegarden notation and lilypond.

     
  • Philip Leishman

    Philip Leishman - 2022-04-02

    and the 2 rg files

     
  • Philip Leishman

    Philip Leishman - 2022-04-02

    the second file

     
  • Philip Leishman

    Philip Leishman - 2022-04-02

    the second file

     
  • Yves Guillemot

    Yves Guillemot - 2022-04-03

    The difference is the bar numbering.
    The anacrusis should precede the bar one and LilyPond does it.
    In attached file, created from a2.rg, RG and LilyPond bar numbering differs.

     
  • Ted Felix

    Ted Felix - 2022-04-03

    Ok, that makes sense. So the bar numbers are the reason we have the anacrusis feature. So we either find a way to shift the bar numbers and make them correct, or we fix the MIDI rendering code (MappedBufMetaIterator et al.) that is currently not working right for MIDI export. Am I on the right track here?

     
  • Philip Leishman

    Philip Leishman - 2022-04-04

    OK. So the whole point is to get the bar numbers in rosegarden the same as in lilypond!
    A bar number shift would do that too.
    But I suppose it would be good to improve the midi export code so it works with negative start time.
    After a quick look I found
    getControllers(instrument, RealTime::zeroTime) in InternalSegmentMapper::insertChannelSetup
    That should surely be the composition start time ?
    I can look around for further problems.

     
  • Yves Guillemot

    Yves Guillemot - 2022-04-05

    Here is another bug.
    Maybe it needs another ticket, but I presume it's closely related to the current one.
    When a composition which begins with an anacrusis is exported in a midi file, the midi controllers usually sent at the beginning of a track follows the anacrusis.

    smfsh> load x.mid
    File 'x.mid' loaded.
    format: 1 (several simultaneous tracks); number of tracks: 2; division: 480 PPQN.
    Track number 1 selected; it contains 6 events.
    smfsh> track 2
    Track number 2 selected; it contains 21 events.
    smfsh> events
    List of events in track 2 follows:
    1: Metadata: Unknown event: 0xff 0x3 0x0, 0.000000 seconds, 0 pulses, 0 delta pulses
    2: Metadata: Key Signature: C, 1.000000 seconds, 960 pulses, 960 delta pulses
    3: Event: Note On, channel 1, note C4, velocity 100, 1.000000 seconds, 960 pulses, 0 delta pulses
    4: Event: Note Off, channel 1, note C4, velocity 64, 1.500000 seconds, 1440 pulses, 480 delta pulses
    5: Event: Note On, channel 1, note D4, velocity 100, 1.500000 seconds, 1440 pulses, 0 delta pulses
    6: Event: Program Change, channel 1, controller 0, 2.000000 seconds, 1920 pulses, 480 delta pulses
    7: Event: Controller, channel 1, controller 10, value 64, 2.000000 seconds, 1920 pulses, 0 delta pulses
    8: Event: Controller, channel 1, controller 93, value 0, 2.000000 seconds, 1920 pulses, 0 delta pulses
    9: Event: Controller, channel 1, controller 7, value 100, 2.000000 seconds, 1920 pulses, 0 delta pulses
    10: Event: Controller, channel 1, controller 91, value 0, 2.000000 seconds, 1920 pulses, 0 delta pulses
    11: Event: Pitch Wheel, channel 1, value 8256, 2.000000 seconds, 1920 pulses, 0 delta pulses
    12: Event: Note Off, channel 1, note D4, velocity 64, 2.000000 seconds, 1920 pulses, 0 delta pulses
    13: Event: Note On, channel 1, note E4, velocity 100, 2.000000 seconds, 1920 pulses, 0 delta pulses
    14: Event: Note Off, channel 1, note E4, velocity 64, 2.500000 seconds, 2400 pulses, 480 delta pulses
    15: Event: Note On, channel 1, note F4, velocity 100, 2.500000 seconds, 2400 pulses, 0 delta pulses
    16: Event: Note Off, channel 1, note F4, velocity 64, 3.000000 seconds, 2880 pulses, 480 delta pulses
    17: Event: Note On, channel 1, note G4, velocity 100, 3.000000 seconds, 2880 pulses, 0 delta pulses
    18: Event: Note Off, channel 1, note G4, velocity 64, 3.500000 seconds, 3360 pulses, 480 delta pulses
    19: Event: Note On, channel 1, note A4, velocity 100, 3.500000 seconds, 3360 pulses, 0 delta pulses
    20: Event: Note Off, channel 1, note A4, velocity 64, 4.000000 seconds, 3840 pulses, 480 delta pulses
    21: Metadata: End Of Track, 200.000000 seconds, 192000 pulses, 188160 delta pulses
    smfsh> 
    
     
  • Philip Leishman

    Philip Leishman - 2022-04-05

    This is the same bug.
    Time 0 comes after the anacrusis and the controllers are exported at time 0.
    I have been looking at this problem. According to the comment in Composition.h getElapsedRealTime should return the time since the start of the composition. At the moment it returns the time after 0.
    Tricky ....

     
  • Philip Leishman

    Philip Leishman - 2022-04-05

    So I had a go at fixing this. It seems to work OK for the test cases I have . but I am far from sure that everything is taken care of correctly.
    Please test !!!
    See merge request

     
  • Philip Leishman

    Philip Leishman - 2022-04-05
    • assigned_to: Philip Leishman
     
  • Ted Felix

    Ted Felix - 2022-05-03

    I am digging into this now. On the surface, this is a big improvement. However, it seems like some other behavior has changed unexpectedly.

    I am far from sure that everything is taken care of correctly.

    Me too.

    I've been trying to develop a test plan that covers all the code that has been changed. This is a rather huge effort as the code within each of these routines is rather complicated and has no comments. Plus these routines are used all over the system. This is going to take a while to review and test completely.

    I've made a great number of cleanup and comment changes. I think I'm going to conditionally compile out the new versions so that I can push this. Then we can do further cleanup and discuss the changes without having any effect on the users.

    Anyway, this has given me a huge headache. I need a break.

     
  • Ted Felix

    Ted Felix - 2022-05-05

    Ok, as of [492430] Philip's fix has been merged, but it has been deactivated with a #define BUG1627. Searching the code on BUG1627 will find the proposed fix. Enabling that #define will activate Philip's fix.

    I am going to continue my review, cleanup, and attempt to assemble a test plan that will confirm that these changes are safe and correct. I have a feeling this will take a while. But it definitely needs doing if we are going to have the anacrusis feature.

     

    Related

    Commit: [492430]


Log in to post a comment.