HISE Logo Forum
    • Categories
    • Register
    • Login

    MIDI Player/Transport bugs & info requests

    Scheduled Pinned Locked Moved Bug Reports
    33 Posts 6 Posters 2.0k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ustkU
      ustk
      last edited by ustk

      So two things I narrowed down a wee bit:

      • The loop end seems to happen after the last note-off event, meaning that if you have only one note, let say the first beat for a quarter duration, it's looping back to the beginning at the second beat instead of lasting 3 more beats of silence.

      • A side effect of this is that the NbBars property in the midi file metadata depends on this duration, no matter it is containing 4 beats. (So even if you round this information you never know what you get since a 4/4 bar can be rounded to 0 if you have only one short note...)

      Side question:
      I have seen 4/4 measures having a last note off exceeding the bar duration, leading to a bar length (NbBars) > 1
      What happens to that note-off after looping?

      Can't help pressing F5 in the forum...

      ustkU 1 Reply Last reply Reply Quote 1
      • ustkU
        ustk @ustk
        last edited by

        @Christoph-Hart Alright, so the early loop end issue seems to come from the fact the EndOfTrack event isn't read...
        It should also be used for the NbBars calculation

        Can't help pressing F5 in the forum...

        1 Reply Last reply Reply Quote 1
        • ustkU
          ustk @Christoph Hart
          last edited by ustk

          @Christoph-Hart What about the loop that is always enabled, and the buggy looping point? (not playing the first/last beat depending on loop on/off)

          Can't help pressing F5 in the forum...

          Christoph HartC 1 Reply Last reply Reply Quote 1
          • Christoph HartC
            Christoph Hart @ustk
            last edited by

            @ustk Can you upload the MIDI file that doesn't read the end of track?

            There are three checks for getting the end time as you can see here:

            double HiseMidiSequence::getLengthInQuarters() const
            {
            	SimpleReadWriteLock::ScopedReadLock sl(swapLock);
            
            	if (artificialLengthInQuarters != -1.0)
            		return artificialLengthInQuarters;
            
            	if (signature.numBars != 0.0)
            		return signature.getNumQuarters();
            
            	if (auto currentSequence = sequences.getFirst())
            		return currentSequence->getEndTime() / (double)TicksPerQuarter;
            
            	return 0.0;
            }
            

            So it first checks if the user has set an artificial length to override the actual sequence length, then it uses the NumBars property if it's defined (which I think I am doing all the time so I don't see this issue) and as last resort it checks the timestamp of the last event in the sequence (which is a JUCE method and should also find the end of track event and not only the last note off).

            ustkU 1 Reply Last reply Reply Quote 0
            • ustkU
              ustk @Christoph Hart
              last edited by ustk

              @Christoph-Hart Yeah I've searched a lot around that end of track event to see if it was read by Hise but I wasn't able to go further.

              I am speaking about the last note off, but I either made a mistake or something because I'm not able to reproduce this.
              I remember now, the last note OFF is another issue. It is utilised to output the track length while it should be the end of track event...

              What I am able to confirm 100% of the time is that it misses either the last portion of the last bar or the start of the first bar depending on the loop on/off state...

              I tried multiple files from @gorangrooves library to my own quick export from Ableton, but same issue...
              I wanted to see if it was a End Of Track problem, I don't think they can all miss that event but I haven't found a tool that can dissect what's really inside

              MIDI Files.zip

              It's strange nobody noticed such an obvious issue till now so I wonder if it's not my built that has a problem

              if the user has set an artificial length to override the actual sequence length

              Not my case

              then it uses the NumBars property if it's defined

              How do you do this? Shouldn't it be automatically exported with the MIDI file from the DAW?

              as last resort it checks the timestamp of the last event in the sequence (which is a JUCE method and should also find the end of track event and not only the last note off).

              That's what I thought so either I'm not lucky and the files don't contains an end of track event, or there's a bug here...

              Could someone send me a simple 4/4 file to check if it works on my end, please?

              Can't help pressing F5 in the forum...

              Christoph HartC 1 Reply Last reply Reply Quote 0
              • Christoph HartC
                Christoph Hart @ustk
                last edited by

                @ustk Alright I've taken a look at this and it appears that the MidiFiles contain no information about the actual end of file so it uses the last note off by default. Rounding this up to the full bar is a simple job with scripting (and I think I did this in all my projects without thinking too much about it :)

                const var MIDIPlayer1 = Synth.getMidiPlayer("MIDI Player1");
                
                MIDIPlayer1.setSequenceCallback(function(mp)
                {
                    var s = mp.getTimeSignature();
                	
                    if(isDefined(s))
                    {
                        s.NumBars = Math.ceil(s.NumBars);
                        mp.setTimeSignature(s);
                    }
                });
                

                If you're using the sequence callback already, pass in a broadcaster instead of the function directly, then make sure that this is the first function the broadcaster calls.

                Now the LoopEnabled button is indeed broken (and the fact that if you disable the loop, it keeps on looping but misses the first beat is some regression issue (I just didn't use the MIDI Player without loop enabled at all).

                d.healeyD ustkU 2 Replies Last reply Reply Quote 3
                • d.healeyD
                  d.healey @Christoph Hart
                  last edited by

                  @Christoph-Hart said in MIDI Player/Transport bugs & info requests:

                  Now the LoopEnabled button is indeed broken

                  Is this related to the broken loop enabled button in the sample editor too?

                  Libre Wave - Freedom respecting instruments and effects
                  My Patreon - HISE tutorials
                  YouTube Channel - Public HISE tutorials

                  Christoph HartC 1 Reply Last reply Reply Quote 0
                  • Christoph HartC
                    Christoph Hart @d.healey
                    last edited by

                    @d-healey no, but loop enable states seem to become a general issue in HISE :)

                    1 Reply Last reply Reply Quote 1
                    • ustkU
                      ustk @Christoph Hart
                      last edited by ustk

                      @Christoph-Hart Thanks Christoph that's awesome!

                      A strange thing the files don't contain an EndOfTrack meta-message since it is stated by the midi normalisation and they are exports from different DAWs... I couldn't find a tool to show me what's aside from the on/off notes and controllers. Thinking about it, it would be a nice addition for a Hise custom panel or just an API that throws a meta content object. I'll see if I can make something interesting since JUCE reads the EndOfTrack and probably other kinds of meta...

                      I'm not using the setSequenceCallback in the project so I guess I don't need a broadcaster, right?
                      I imagine it's for a priority reason and I don't know what it should be linked to anyway... MidiPlayer maybe?

                      Can't help pressing F5 in the forum...

                      Christoph HartC ulrikU 2 Replies Last reply Reply Quote 0
                      • Christoph HartC
                        Christoph Hart @ustk
                        last edited by

                        @ustk you can pass in a broadcaster instead of a function into any callback slot and then it will send a message to all its listeners (think of it as a distribution tool for events).

                        ustkU 1 Reply Last reply Reply Quote 1
                        • ustkU
                          ustk @Christoph Hart
                          last edited by

                          @Christoph-Hart The code you provided works if we assume NumBars is below the length we need. But then if a note off exceeds the required bar length then ceil will add an empty bar... That is the test I have made previously for getting the right sequence length.

                          But I assume there's no other way to get the length if the EndOfTrack is missing, so the loop creator has to make sure no noteOff exceeds the last bar, am I right, Christoph?

                          Can't help pressing F5 in the forum...

                          Christoph HartC 1 Reply Last reply Reply Quote 0
                          • Christoph HartC
                            Christoph Hart @ustk
                            last edited by

                            @ustk if there is no end of track marker (and actually I don't see anywhere in the JUCE code where that would be parsed), then the length of the MIDI file is the position of the last note off, that's basically the definition of the length :)

                            If you know how long you want it to be, you can just set it to the fix value, or you can use Math.round() if you want to round down values, but then you would also have to iterate over the sequence and make sure that no timestamp lies beyond that.

                            so the loop creator has to make sure no noteOff exceeds the last bar, am I right, Christoph?

                            Yes this would be the most sane approach.

                            ustkU 2 Replies Last reply Reply Quote 1
                            • ustkU
                              ustk @Christoph Hart
                              last edited by

                              @Christoph-Hart yeah everything seems quite logical, it's just weird the length isn't something plainly written but something that has to be calculated.

                              Can't help pressing F5 in the forum...

                              clevername27C 1 Reply Last reply Reply Quote 0
                              • ustkU
                                ustk @Christoph Hart
                                last edited by

                                @Christoph-Hart Alright so the loop fix is working but it brings another weirdness.
                                The first time it loops, beat 1 is played twice, causing a nasty comb filtering:

                                Can't help pressing F5 in the forum...

                                1 Reply Last reply Reply Quote 0
                                • clevername27C
                                  clevername27 @ustk
                                  last edited by clevername27

                                  @ustk Thank you for this thread (and thank you @Christoph-Hart for your participation). I've written a proper little snippet to capture incoming MIDI data—both live and from a host. You don't need to pre-set anything (time signatures, tempos or sequence lengths).

                                  Link Preview Image
                                  Code Snippet for Y'All: Capture Incoming MIDI Notes Without Limitations

                                  Here's a self-contained snippet that will capture all incoming MIDI notes, from either a live input or from a host sequencer. Notes— As such a function shou...

                                  favicon

                                  Forum (forum.hise.audio)

                                  @ustk Can you please consider contributing the second half here — the playback portion?

                                  __________________________________ DISCUSSION __________________________________

                                  Specifically, the code to automatically play back the captured events in synch (time and position) with a host. It seems like a short snippet, above the length of what I wrote, could likewise handle all playback scenarios. (Adaption to playing back recordings of live MIDI data would then be trivial.)

                                  Below are examples of what I'm (and others) are struggling with. I realise some of these questions have been answered in this thread, but my wayward brain can't seem to assemble them into the proper code within the context of real-time world applications (e.g., multiple time signatures, tempo maps, changes to the duration of the host DAW song).

                                  My capture code deals with all of these problems—but we can't play them back!

                                  I'm not literally asking these questions—just describing what I'm thinking the playback code should address given my (and other's. including I think your own) questions about this tantalising topic.

                                  • How do we learn what tempo and time signature changes are in the host sequence? The only way I can see to do this is to play the entire song, and capture every time signature and tempo change. But that won't work because (among other things) the user may change them.

                                  • Given that the position data of the MIDI Player seems to be a float from 0.0 to 1.0, how would I know where I am on the timeline if I don't know all the time signature and tempo changes?

                                  • How do we store (e.g., Flush) and access these changes in the MIDI Player's sequence—literally by creating the corresponding MIDI events? (Will that even work, considering the capture is in real-time?)

                                  • Everything is stored in ticks, but still—maybe it's just my OCD, but it's just wrong to create a sequence with a specific time signature and tempo when they don't apply to the song. 🤪 For example, the sequencer requires us to pre-determine a fixed length for the sequence—but without knowing the tempos and time signatures, what values should be used? (I see Chris answers this, but my tiny mind struggles to apply it here.) The user will inevitably extend the song length in the DAW.

                                  • Once the event list is flushed into a MIDI player sequence, how do I synch the clocks? (I see this is explained in the thread, but I'm a bit lost within the above context.)

                                  • Once the clocks are synched, I set my transport callbacks to start and stop the MIDI player when the host does so—will the event positions of my HISE-based sequence magically play back according to their time-stamps? (E.g., if the use goes a specific point on the DAW's timeline, and presses play, will HISE's MIDI Player play the correct notes at right time?)

                                  Thank you, as always, all.

                                  Christoph HartC 1 Reply Last reply Reply Quote 0
                                  • Christoph HartC
                                    Christoph Hart @clevername27
                                    last edited by

                                    @clevername27 I think the most important point you're getting wrong is that the tempo and the time signature do not matter at all for the MIDI player if it the data is stored in ticks - it's the DAW's job to change the playback properties and propagate it to the MIDI player and if the player is synced to the DAW clock, then it will handle tempo changes, position changes (seeking) and even DAW loops correctly.

                                    will the event positions of my HISE-based sequence magically play back according to their time-stamps?

                                    Yes :)

                                    ustkU clevername27C 2 Replies Last reply Reply Quote 3
                                    • ustkU
                                      ustk @Christoph Hart
                                      last edited by ustk

                                      @Christoph-Hart After having the above double triggering issue fixed, I wonder how one would approach automatic file change when reaching the end of the current sequence?
                                      I can't find a reliable method to perform a synced sequence change...
                                      I tried using setOnBeatChange and getPlaybackPosition, and computing the sequence length from the ceiled Numbars times the Nominator to count the beats but it behaves unreliably...

                                      Another one, when not having the endOfTrack event, the midi player overlay draws the content ending at the last noteOff.
                                      So in the end, I wonder if this shouldn't be handled by Hise, instead of rounding the bars in script?

                                      Can't help pressing F5 in the forum...

                                      1 Reply Last reply Reply Quote 0
                                      • clevername27C
                                        clevername27 @Christoph Hart
                                        last edited by

                                        @Christoph-Hart Thank you - understood.

                                        gorangroovesG 1 Reply Last reply Reply Quote 0
                                        • gorangroovesG
                                          gorangrooves @clevername27
                                          last edited by

                                          @Christoph-Hart I want to provide further info regarding the bug @ustk demonstrated in the video above, regarding the double triggering of the same note when a MIDI file loops.

                                          The dual kick notes (#36/C1) happen on beat 1 of the 2nd play through the loop, when the tempo is set to 120bpm and 160bpm.
                                          If the tempo is set to 80bpm, the dual kick note plays on beat 1 of the 4th repeat.
                                          If the tempo is set to 240bpm, the dual kick note plays on beat 1 of the 3rd repeat. Other tempos seem OK.

                                          I don't know if the issue is present on any other notes, but it is definitely there on C1.

                                          And just to clarify, @ustk did not fix the bug, as it may seem from his previous answer.

                                          Goran Rista
                                          https://gorangrooves.com

                                          Handy Drums and Handy Grooves
                                          https://library.gorangrooves.com

                                          1 Reply Last reply Reply Quote 0
                                          • ulrikU
                                            ulrik @ustk
                                            last edited by ulrik

                                            @ustk said in MIDI Player/Transport bugs & info requests:

                                            A strange thing the files don't contain an EndOfTrack meta-message since it is stated by the midi normalisation and they are exports from different DAWs... I couldn't find a tool to show me what's aside from the on/off notes and controllers.

                                            I found this tool (MacOS), and opened one of you midi files

                                            Synalyze it

                                            It will show the end of track info

                                            Did you manage to get Hise Midi Player to read the End of track data?

                                            Hise Develop branch
                                            MacOs 15.3.1, Xcode 16.2
                                            http://musikboden.se

                                            ustkU 1 Reply Last reply Reply Quote 1
                                            • First post
                                              Last post

                                            52

                                            Online

                                            1.7k

                                            Users

                                            11.7k

                                            Topics

                                            102.1k

                                            Posts