MidiFire/StreamByter - some myths debunked
I don’t post here very often (prefer to keep discourse about my apps on my own forum), and I suspect I might cop a bit of flak for this, but I want to address some of the comments I have read here recently regarding my apps and make some more general statements about MidiFire and StreamByter and how they work as a reference.
1. StreamByter is hard/arcane/assembler-like/inefficient
Actually, the StreamByter language is very simple (see below). The complexity of MIDI scripting really comes about from needing to understand how MIDI itself works; I would argue that this holds true for any MIDI scripting language. Without understanding MIDI it all appears esoteric. For anyone who understands MIDI, StreamByter makes a lot of sense - it was designed around the MIDI protocol after all.
When boiled down, the StreamByter language consists of just 5 simple commands, generic pattern matching and array variables:
ASS - assign values to array variables
SND - send a MIDI message
MAT - perform a calculation
IF/ELSE/END - conditionals and loops
SET - configure labels and sliders
[input MIDI message] = [output MIDI message] - rewrite a MIDI message using patterns
array variables are just slots of memory (or special values like random, timing, current message or slider) that are used in the above rules.
and that is it.
The language is relatively strict in terms of syntax - this is to make it easier to parse.
I read a comment where someone suggested that StreamByter was inefficient - this could not be further from the truth - Internally StreamByter is massively efficient and carefully hand-coded in pure C (my specialty) - the textual rules are not evaluated dynamically at run time but converted to a binary format and processed at almost bare-metal speed.
Another comment stated that I had made sliders 'difficult' to work with in code. I disagree. A slider's value can be read inside a script by just looking at a variable value. Adjusting a slider from code is done by setting that value - it's dead simple. Changing the name of a slider and its range is a simple SET statement. You can get more advanced if you want and get notified in your script when a slider is moved by looking for a specific MIDI message.
2. You need to know StreamByter for MidiFire
An enormous amount of stuff can be done in MidiFire without needing to go near any scripting. This includes channel/note remapping, keyboard/velocity splits, velocity/pressure curves, sophisticated/accurate MIDI clock, event monitoring, automated CC sweeps, poly to mono conversion, bluetooth/wifi management and remote control of everything via MIDI learn.
MidiFire’s MIDI routing is second to none - it’s totally freeform (no ‘lanes’ or ‘matrices’) - you just drop port and module blocks onto a canvas and connect them in any way you like and MidiFire will sit up and beg. Route, clone and merge ad nauseum all by making connections between blocks. Internally, MidiFire routes using a recursive descent engine, again carefully coded in native C (as are all modules), in order to move MIDI events through the graph as fast and efficiently as possible.
MidiFire scenes and StreamByter scripts are completely portable between iOS and macOS. The same StreamByter code running in AUM will work in Logic Pro X. Both apps have minuscule memory requirements and low CPU overhead even with large rates of events and complex processing.
Scripting is the icing on the cake - it’s designed to allow me, or users if they wish, to extend the capabilities of MidiFire to cater for the thousands of specialised use cases that exist. How anyone believes that a single app can do this with a GUI escapes me.
3. My app philosophy
Because I understand that not everyone wants to write scripts, I stand behind my apps (which is why they are priced as they are, but that is a whole different story) and am always happy to hear from customers with a specific requirement and be able to supply them with a working solution. Those who have tapped me for code via email or via my forum can testify that I respond fairly quickly. Timely and comprehensive support is something I feel should be included in the price of admission for my works.
StreamByter originally appeared in MidiBridge and was really just for me to remotely extend that app’s feature set on demand. Turns out it grew legs and people started using it and so I continued to develop it. I do understand that scripting is not for everyone and that is fine, but I do get disappointed when people (often who have never even used my apps) dismiss them out of hand when in reality scripting just does not suit them (don't get me started on 1 star reviews), even if they have a special use case that needs to be met, and could be satisfied by just asking.
Finally, and this might be the most controversial (and probably needless) comment, but I want to get it off my chest; I have a massive ego. Every app I release is always a first-of-its kind; from MidiVision and MidiBridge to MidiPace. I try to identify a need that is currently not filled and make a new niche rather than make a ‘better’ version of a pre-existing product. Many of my apps have been copied, ranging from concept/features to one that ‘borrowed’ the entire app, UI and all. That’s the nature of competition, but it is not something I tend to do myself. Specifically, the latest StreamByter release has been in the works for a while with many of the enhancements having been on the to-do list for up to a year.
PS. I do realise I am stirring a hornets’ nest. ;-)