Nova Midi - A pure zig Midi I/O Library inpired by libremidi and minimidio

Nova Midi


Nova Midi is a midi I/O library that is inspired by libremidi and minimidio, providing a simple to use and unified function and interface to send and received midi messages across multiple backend. Currently, the library is still in a prototype and proof of concept phase where only winmm and alsa is supported.

https://codeberg.org/Logickin-Lambda/nova-midi

But… Why?

Like you have said before, there are libremidi and minimidio, and possibly many more; why even bother to build another midi library?

Well, I didn’t have no attempts on trying to link the existing solutions, but most of the existing solutions are written in c++ while they have heavy uses of operator overloading and templates, making to understand and to build the library difficult. Some solutions are C based, but there is no midi 2.0 support or the backend is selected at comptime which could crash the target device if they don’t have specific backend instead of safely escaping the problem with an error and let the program continue. Most of the zig solutions I could found are inactive, a few versions ago.

Because of the problems above, I decided to write my own solution, a midi library that is written zig so that zig users could easily maintain without touching other languages, while reducing a layer of translation.

Supported Zig versions

zig-0.16.0

Help wanted:

Currently, the library is still in an early phase, and because of lacking a mac and still attempting on understanding how different platforms handling their endingpoint connections, some part of the features are currently missing. If you have any interest, ideas, questions or even contributions, please let me know through the issues, pull requests and here down below.

AI / LLM usage… disclosure?

Well, that’s the awkward part since I did only used the Duck AI (Mainly Claude Haiku 4.5) as a glorified search engine to narrow down some midi related problems during this iteration; however, nearly all the time, it didn’t return any correct or useful results due to the scarcity of Midi resource, especially anything related to midi 2.0. As a result, I always ended up using the official Midi Association and Alsa Documentation, Articles from Microsoft Midi Service, along with some coding experiment.

3 Likes

Just FYI, not really sure how this is related exactly, but there is sample accurate MIDI in JACK:

I found a old article:

And some comments by Paul Davis:

Thanks! This could be useful when I start to touch jack audio, especially the api reference; in fact, the current design of the library is to support cross platform backend like these; though, I would put this aside since I need to sort out the missing features (like midi timestamp) and how to build an abstraction for ump endpoint for both alsa and midi service first.

For Windows, the ancient WinMM API is now essentially obsolete and exists purely for backward compatibility. New code should use the new (Midi 2.0) API. Mac, Linux and Windows all now support MIdi 2.0.

Yes, i agree that the newer service should be supported which I am currently exploring it, but just in case people still use windows older than windows 11 or when that “ensure midi service” function fails, the winmm acts as a fallback mechanism.

Similar story to linux which I often see people using a very old version that don’t include the ump features, so we still need to support the old api.

The library will be shifted focus toward more to midi 2.0 once I have figured out an api that plays well for all three major platforms which i am currently working on.

i’d be interested in helping with some of the mac stuff.

1 Like

Great! Since the library is new and I am currently reworking it in a way that aligns more to the midi 2.0 terminology, it is better to do that after my next release.

2 Likes

I just came across this, and remembered that I once had a manic episode and converted the Midi WinRT API to zig. Hope you like it !

(I never cleaned it up, sorry)

Could you please explain it a bit more?

I don’t want to say this, but it does look a bit suspicious to see that is your first reply with sharing a link pointing to something I don’t recognized. Could you tell us a bit more about you, what is inside the box, and why are you sharing something without using any git host like codeberg or gitea, but pastebin?

It’s just a pastebin, here it is on a gist.

Those are Windows COM VTables/API, packaged as Zig objects, plus a basic wrapper

1 Like

Thank you so much for providing the github gist version to proof your link! This might not be the direct destination to the Midi 2.0 implementation, but I will study the code to see how to integrate the midi 2.0 into the library. You code could helps a lot by understanding the principle and how to implement the watcher logic.

The reason why I didn’t trust pastebin is that I haven’t ever used and seen this website before, while recently, there are a lot of bots attacking some of the forums I usually wander around, along with increasing number of scam calls and message on my phone, so I tend to be a bit cautious to see an unfamiliar links from a first time poster.

Nonetheless, most importantly, as your first and second replay, Welcome to Ziggit!

Edit: I have just noticed the keyword COM VTables/API, meaning that the watcher will not be included in the Midi Service as the Official Article from Microsoft have mentioned; thus, I need some kind of custom watcher and group filter implementation. Though, this is fine and this is something to keep in mind.

1 Like

A new update has been dropped!

I am proudly announcing that the library has been in a massive overhaul! And here are the new changes to the library:

Dropped Legacy Midi Event

This is one of the most significant change into the library. Having no idea if we need every need to handle the legacy part of the library? No problem because the Legacy Midi Event are now officially dropped from the library, meaning that you need to handle midi IO with ump packets only.

Though, what about Legacy backend like the old version of alsa or winmm? Well, good luck since we have officially remov… (Cough!) Just removed the midi legacy event doesn’t mean the legacy backend are gone! You may send or receive midi message to these backend with ump format, and they will convert into legacy format under the hood! The only thing to keep in mind is that only system realtime, system common, mt2 midi 1.0 channel voice and sysEx7 are supported for legacy backend, and sending message other than the aforementioned type will return an Error.Legacy error to prevent unknown data and status bytes written into these backend.

Forget About Ports

Since the new midi standard have specified to make connection through endpoint, the old concept of ports and the creation process are removed. To create a connection, use the ClientSession type to make connection. Because of the requirement of some backends, connection to the same source/destination can only be created once. Attempting to create an existing connection results in an error. If you want to access the existing port, you may use the function getExistingConnection() for that.

UMP Helpers And Masks

Oh no! UMPs are now a 4 u32 words instead of the good old 3 bytes days; is that means I have to create and parse them bit by bit? I can’t imagine all the shifting process…

The previous design didn’t have any helper since the UMP format was just a proof of concept, but since the library drops the Legacy Event in favor of the packets, we can’t just leave it as it is; thus, the ump format now have a set of helpers under the type Protocol.Ump.UmpData.Builder, provide all possible ump builder functions, providing a more ergonomic ways to spawn these messages.

To parse the ump, I also have provided a set of midi type masks so that you can immediately get the details of the packet by applying the correct mask type.

Future Plans

Although this is a few steps closer to the production ready library, there are still a long way to go. Currently, despite the design of the library is much closer to the midi 2.0 requirement, there are still inaccuracies to how ports are enumerated and connected; thus, the next iteration will address that problem.

In addition, inspired to the handler being better pointers post, I am aware of my memory layout of my current library design is a bit fragmented, and I like the idea of putting the struct into a centralized memory pool, while handler seems suitable for my library. Although the possibly of centralizing all memory is small because some backends have their own allocation process, I will try to find a more organized way to manage memory.

Lastly, and it might be the most difficult one, is to get the COM interface of the windows midi service working.

The AI / LLM usage disclosure?

Well… That’s the awkward part. I did use LLM for searching and narrowing down information in this iteration, but nothing gained and helped from using it… I will share a little bit more on the top post.

1 Like