Skip to content

Comments

Support running status#341

Closed
m-vo wants to merge 1 commit intomido:mainfrom
m-vo:feature/running-status
Closed

Support running status#341
m-vo wants to merge 1 commit intomido:mainfrom
m-vo:feature/running-status

Conversation

@m-vo
Copy link
Contributor

@m-vo m-vo commented Oct 10, 2021

We're now storing the last status byte whenever a message with at least one data byte is composed. If a message starts with a data byte this status byte will get injected. This is according to the MIDI spec: running status.

So the following two inputs are considered equal now:

0x9a, 3, 127, 0x9a, 3, 64, 0x9a, 3, 0
0x9a, 3, 127,       3, 64,       3, 0   

I'm not sure about the right base branch, I'll rebase accordingly if needed.

@m-vo m-vo mentioned this pull request Oct 10, 2021
@Jajcus
Copy link

Jajcus commented Jan 4, 2022

I was quite surprised finding out that MIDO cannot handle running status. Such a basic MIDI feature…

I am writing a new back-end and was feeding the parser with midi bytes using running status and wondered why only the first event is accepted.

@m-vo
Copy link
Contributor Author

m-vo commented Jan 4, 2022

@Jajcus did you test if the fixes from this PR work for you? Might be good to get some feedback.

@Jajcus
Copy link

Jajcus commented Jan 4, 2022

@m-vo No, I have not. I wanted to make my code work with the released version of mido, so I implemented a workaround even before I found this merge request.

@rdoursenaud
Copy link
Member

Per the official midi.org specification, page 5, running status is "For Voice and Mode messages only" aka Channel Messages.
System messages (Common, Real-Time and Exclusive) are not Running Status enabled and should exit running status mode.
Same goes for undefined Status bytes.

I don’t see such filtering in your code.

@rdoursenaud
Copy link
Member

I made a mistake in my previous comment. Real-Time messages are a special case and the only ones that should not reset/exit the Running status.

@m-vo
Copy link
Contributor Author

m-vo commented Apr 5, 2022

Real-Time messages are a special case and the only ones that should not reset/exit the Running status.

The code only runs in _feed_data_byte, so IMHO this should not affect SysEx and other messages at all. We could in theory reset self._last_status in certain cases, but I didn't find anything in the spec about this. Do you see any downsides in the current implementation that we should address?

@rdoursenaud
Copy link
Member

The specs says the reverse.
Quote from MIDI 1.0 specification page 5 (10 in PDF form): "For Voice and Mode messages only" and "Running Status will be stopped when any other Status byte intervenes."

Common messages can have data bytes (F1, F2, F3) and SysEx has data bytes but are not Running Status enabled.

How does this test perform?

def test_running_status_common():
    """The last known status byte should not be reused with common or exclusive message"""
    assert tokenize([0xf3, 1, 2]) != [
        [0xf3, 1], [0xf3, 2]
    ]

To be spec compliant it should pass and from just reading the code, I believe it fails.
The second data byte should be considered invalid and not yield another Song Select message.

FWIW I have a spec compliant Running Status implementation part of a work in progress to fix #363. I can extract/PR it since it seems to work fine while I continue working on the EOX issue which is more hairy.

@m-vo
Copy link
Contributor Author

m-vo commented Apr 5, 2022

Thanks for the explanation. I must have jumped over the "Running Status will be stopped …" part each time. 🙈

FWIW I have a spec compliant Running Status implementation part of a work in progress to fix #363. I can extract/PR it since it seems to work fine while I continue working on the EOX issue which is more hairy.

Sounds good. 👍 Closing this PR in favor of #363 then.

@m-vo m-vo closed this Apr 5, 2022
@rdoursenaud
Copy link
Member

If anyone is willing to review my code, I just pushed my work in progress: https://github.com/EMATech/mido/tree/eox

The relevant running status implementation is there: EMATech@c6e13e5#diff-657b1756ea262acda7e2095a923fc3f18e64343552164609e0b5badd451151b4

@m-vo
Copy link
Contributor Author

m-vo commented Apr 13, 2022

If anyone is willing to review my code, I just pushed my work in progress: https://github.com/EMATech/mido/tree/eox

The relevant running status implementation is there: EMATech@c6e13e5#diff-657b1756ea262acda7e2095a923fc3f18e64343552164609e0b5badd451151b4

Thanks. Please consider opening a (draft) PR, because IMHO it's way easier to review this way.

@rdoursenaud
Copy link
Member

@m-vo Thanks for the suggestion, done! I didn't know "Draft PR" were a thing.

rdoursenaud added a commit to rdoursenaud/mido that referenced this pull request Sep 2, 2023
Due to the nature of running status, missing or invalid sysex end bytes
now issue a warning instead of raising a ValueError.

Fix mido#341
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants