Or ... how's this for a different approach?
On the topic of underlying data structures, what's clearly important is that they adequately model the domain specifics of notation, with the added concern of integrating nicely into a DAW workflow. It's no mean feat, but I'm sure we can get there and in some aspects it's there already.
It's really a matter of building on a solid design: a loosely coupled relationship between voices, channels, tracks, staves and instruments to allow for flexible (re)interpretation and a reduction of assumptions regarding the exact nature of the given input. As kerryg has said, a track may not necessarily correspond to an instrument, and the grouping of staves together is not necessarily related to their track or channel configurations out of the box. There should be some room for creativity here for the maximum coverage of use cases.
So ... perhaps instead of a huge number of voices for sorting everything, which I've admittedly been banging on about a bit, we could describe everything simply and accurately using text events to distinguish between instruments, staves and voices. This would be the ultimate in separation of concerns, leaving the interpretation wide open. For example...
NOTE 3 81 instrument Flute staff 3 voice 2
where:
- "Flute" is taken directly from the given name for this associated instrumental staff group (perhaps substituting something like '_' or '-' for any spaces),
- staff 3 means the 4th staff (if we start with 0) on the score,
- and voice is pretty much as we're used to seeing it: 1 for upper, 2 for lower, (0) for default (with 3, 4... included later in a DLC)
- the channel and pitch are also as before, so no change is needed there
Access to the
instrument name directly would be simply stunning for automatic contextual treatment of various instruments, as you could define specific rules based on string matches, internally or externally. It could also help to make sure the routing is correct. If all flutes need to go to bus 3, for instance, that's where these events go. My head is spinning at the possibilities.
The
staff number is primarily related to the display order but could help with routing and so on if we chose to tap that resource. Clefs and non-global time/key signatures would all relate to a staff number. Such a number would likely be global (a per-project ID). Also, adding or incorporating new tracks/channels would automatically create another staff to host those events, which could later be combined with others if you so wished. This is the part I'm struggling with the most in this thought experiment. Any ideas? Is there a more elegant and extensible way?
Here's another way of expressing the same sort of information, but in a declarative start-of-play "setup" format:
STAF 15 instrument Trombone => staff 15 has the instrument name of "Trombone"
or
INST 15 1 Trombone => the instrument "Trombone" starts at staff 15 and is a total of 1 staff in size
STAF 15 clef bass => staff 15 has a bass clef, then later...
STAF 15 clef tenor => staff 15 has a tenor clef
STAF 15 type 5line => staff 15 is a 5-line staff
The
brac*ing would be a separate layer again, so there could be text markers for these too.
BRCE 12 13 => staves 12 and 13 are connected with a brace
BRKT 1 5 => staves 1-5 are connected with a bracket
BRKT 2 3 => staves 2-3 are connected, in this case via a sub-bracket within the larger 1-5 bracket group
It may be worth introducing another text element to express the depth in the hierarchy for clarity, so something like:
BRKT level 1 staff 1 5
BRKT level 2 staff 2 3
One handy thing about using text events exclusively for layout is that if you were to import the midi into another reaper project then the staves would all be there for you. If it had to merge with existing midi then perhaps there could be some options: include as-is or start from the first available staff number, as two likely candidates.
In any case, through a cleaner separation of the notions of instrument, staff, track, channel and voice we have the utmost independence in how we want to treat these parameters, as developers and end users.