[Scummvm-devel] MidiChannel methods

Johannes Schickel lordhoto at scummvm.org
Mon May 9 17:13:24 CEST 2011


> Hi all,
> 
> Some rambling about MidiChannel, about which I may have completely
> misunderstood:
> 
> Back in 2002, in revision 973164a7, the MidiChannel class was created,
> with a whole bunch of (pure) virtual methods for handling control
> changes. They seem to (still) only really be used by iMuse, just as a
> shortcut? Some are used internally by the Adlib driver (like pitchBend).
> 
> Later (2003), in a722d060, various default implementations for most
> of those methods were added, calling controlChange() with the relevant
> parameters.
> 
> The Adlib driver implements all of the methods (sometimes as an empty
> function), and then has a switch statement in controlChange which calls
> the individual functions (or in the send() function, for things like
> pitchBend). Other drivers implement things directly in controlChange
> etc.
> 

That is because most/all of these functions are just short cuts to send a 
controller change event.

> All this confuses me terribly, trying to write new drivers, especially
> since there are still functions which are pure virtual. But I'm not
> really too familiar with any of the code, obviously.
> 


See above and below for more confusion.


> Is it important that things are written this way? Can we simply remove
> the base class methods and call controlChange/send directly if necessary?
> Perhaps adding some constants too? (I would be happy to do the work.)
> Or perhaps the methods could be made into non-virtual helper methods?
> 

If you don't want to bother with all that and just bother about implementing 
send and sysEx you should probably subclass MidiDriver_MPU401, which will 
handle all the channel implementation by just using send.

On a related matter, why is that called code MPU401 btw.?

About the API design itself here: I have no idea why we have all that.

All backend midi drivers seem to just subclass MidiDriver_MPU401.
There's drivers which just return 0 for allocateChannel and 
getPercussionChannel (like the YM2612 driver, but it seems to still have a 
custom MidiChannel implementation, all SCI drivers AFAIK, KYRA's "driver"). 
Others only use the MidiChannel_MPU401, like the FluidSynth driver.

The only real benefits I see in the MidiChannel API are:

1) Seeing the AdLib MIDI driver implementation it seems to really help 
structuring the implementation. Then again we don't need a forced MidiChannel 
API for *all* drivers, if they don't use it in the end.

2) Using allocateChannel helps the code to abstract from the midi channel ids. 
This is especially helpful when working with a MT-32, which does use channels 
1-10, i.e. 0 is not mapped to any hardware channel by default(!). That's why 
we have the channel mask setup for MT-32, of course then the driver code needs 
to worry about the channel mask, but the MPU401 handles that just fine.

We could of course have all that for the client code by a MidIChannel_MPU401 
style implementation, while still requiring drivers only to implement send and 
sysEx (and probably sysEx_customInstrument). I am not sure how well that works 
with the AdLib driver, in case all functions are properly accesiable via the 
corresponding controllers via a control change MIDI command it might work just 
fine.

In fact simplifying the MidiDriver API would be a real nice change. We could 
get rid of some bloat, like the need for every driver to supply the only 
rarely used MidiChannel APIs. Engines which need it could use a 
MidiChannel_MPU401 like class without any virtual functions and thus reducing 
further bloat.

// Johannes






More information about the Scummvm-devel mailing list