SAOL, MIDI, General Midi and GS Midi. Invitation for discussion.

From: Robin Davies (rerdavies@msn.com)
Date: Wed May 24 2000 - 19:48:36 EDT


<g> Now that we've done mixed-rate opcodes to death, I thought I'd introduce
another topic of discussion.

I've just finished implementing GM and GS MIDI for Sfx. We had discussed the
possibility of making RPNs and NPRNs available to MIDI instruments; here's
the net results of what does and does not seem to be required to support the
GM and Roland GS midi standards from SAOL. The results are somewhat
surprising, and also may have some repercussions on normative MIDI
interpretation in SAOL. I've also taken a brief survey of the Yamaha XG
command set, but XG is clearly above and beyond the call of duty for any
SAOL implementation.

Providing GM and GS compliance for SAOL orchestras comprises several steps.
The most obvious one is providing the GM/GS instrument sets. At the present
time, this seems to be a relatively far-off goal using nothing but SAOL.
However, I have also finished bringing up SoundFont/2 extensions (yes, yes I
know) given that I was utterly unable to find any DLS-2 sample banks. For
the meantime, using soundfont extensions in conjunction with an excellent
EMU GM/GS-compatible soundfont bank, I was able to fully implement GM/GS
voice sets in Sfx. Presumably, DLS-2 banks will become available at some
point in the future (or perhaps SoundFont/2 -> DLS-2 converters. Whichever).

Once instrument sets have been built, there remains the issue of supporting
the full set of Sysex commands, controllers, and RPNs required to support GM
and GS. Initially, I thought that most of the Sysex commands and RPNs would
have to be exposed through extension opcodes. This turned out not to be the
case.

Here are the broad categories of parameters and commands required to support
GM and GS.

(1) Controllers. All exposed already through MIDIctrl[].

(2) Channel-specific tuning parameters. Coarse tuning (semitones via RPN 1),
fine tuning (cents via RPN 2), and alternate scale tuning parameters (in GS
only, channel-specific Sysex).

(3) Global volume (standard MIDI sysex). Global tuning (sysex, not currently
implemented by Sfx, but potentially implementable using the Saol tuning
mechanism).

(4) Percussion channel selection (GS, channel-specific sysex). Part mapping
(GS, channel-specific sysex).

(5) Pitchbend range (MIDI RPN 0).

 Missing or Inaccessible State Variables Required by GM/GS.
 ---------------------------------------------------

The three RPNs could be made accessible via a MIDIrpn[] array. However, the
GS tuning array, (which consists of an array of 12 parameters providing +/-
64 cent tuning for each note of the scale), and the presence of global
tuning parameters that perhaps should be independent or addititive to the
effects of the SAOL tuning mechanism argue slightly for opcodes of the
following forms.

    ivar _midicoarsetuning_();

Returns the channel's coarse tuning setting, plus, potentially, the global
coarse tuning setting. Returns zero always for percussion channels. Units:
semitones. Always integer. The motivation for this is that coarse tuning of
+12 semitones, for example, should really offset the instruments midi note
before things like samples, filters &c are selected.

    ivar _midifinetuning_(ivar iMidiNote);

Return's the channel's fine tuning setting, plus the appropriate value of
the the GS tuning array if GS is enabled. Returns 0 always for percussion
channels (?). Potentially could add in the global fine tuning value as well.

    ivar _midivolume_();

Could return either the actual parameter value (range 0..127, requires
application of the recommended GM volume curve function), or alternately,
the absolute value of the function. My inclination is the latter just
because writing startup instrument code to initialze a global-scope array is
a pain. However, the GM volume curve map gets used with other controllers
such as controller 91 (External Effect Send, but coopted for Reverb Send),
and Chorus Send controllers.

This value has to be channel-specific because the setting presumably
reflects the setting in the current channel-group (group of 16 channels),
rather than a truly global setting.

    ivar _pitchbendrange(), or alternately, just MIDIbendrange.

Range 0..127, specifying the maximum excursion of the MIDIbend controller in
semi-tones. Channel-specific.

 Percussion Channels
 ---------------------

Percussion channels pose a particular problem for SAOL with respect to GM
and GS.

Bank and patch selection semantics for GM and GS percussion channels are
different from non-percussion channels. In GM, channel 9 is *always* a
percussion channel. The Bank Select controllers are forced to 0 and 128,
respectively (yes, 128. Yes, that's not a legal value for a MIDI
controller). It's difficult to tell whether a program selection actually has
any effect in a GM instrument; in GS instruments, program selection does
change the set of percussion instruments; I'm not sure whether this is only
legal when GS is enabled, but I suspect that GS instruments will respond to
program selections when running in GM mode. GS instruments allow arbitrary
selection of any channel (part, actually, but the semantic difference isn't
worth discussing) as a percussion channel. The bank selection controllers
for GS percussion channels behave as does the GM percussion channel: they
have no effect; however, GS instruments are required to respond to program
selections on percussion channels by select preset (0,128,N) (bankH, bankL,
program#, respectively).

So how does this affect SAOL?

There are two immediate repurcussions, one minor, one major.

The minor repercussion is that the semantics of bank selection should be
explicit about how BankH and BankL and program# selection are translated to
SAOL presets numbers. The correct formula should be

    preset = 128*256*bankH + 128*bankL + program#.

This allows bankL to take a value of 128 when dealing with percussion
channels.

Preferable would be:

    preset = 256*256*bankH, + 256*bankL + program# [2]

but the SAOL standard already states that presets are computed as:

    preset = bank*128 + program#.

Perhaps this should be fixed in the standard in favor of formula 2.

That's the minor issue.

The major issue is that we need to seriously consider is how to handle
percussion channels in MIDI streams. If GM instruments ignore bank selects
on channel 9 coming out of reset, then how should channel 9 be treated in
MPG4 MIDI streams? The GM spec is rather silent on this issue. It is an
implementers decision as to whether a GM instrument comes out of reset in GM
mode. However, following a MIDI GMReset sysex, the instrument must follow
channel 9 GM semantics. Roland instruments definitely come out of reset in
GM mode. If they did not, then percussion patches would be inaccessible.

To the best of my knowlege, there are no other semantic issues wrt/
percussion channels other than the way percussion channels handle bank
selects, and probably, the way percussion channels handling tuning.

 So Who Needs Bank Selects in SAOL Anyway? Aren't 127 Programs Enough?
 ---------------------------------------------------------------------------
------

In true post-modernist fashion, let me lay my biases and personal agendas on
the table.

Sfx provides a _soundfont_ opcode that generates soundfont instrument output
as an opcode. A fully GM-compatible Sfx orchestra looks more or less like
this:

instr sfInstrument(iMidiNote, iVelocity) preset * // note the '*' preset.
Also an extension.
                                // Ranges of the form "10000-20000" are
also permissible.
{
    ksig bReleased;
    ivar iEffectiveMidiNote;
    asig aResult[2];

    iEffectiveMidiNote = iMidiNote + _midicoarsetuning_();

    bReleased = _soundfont_(
        aResult, // receives output. Don't ask.
        preset, iMidiNote+ _coarsetuning_(), iVelocity, // patch
selection.
        released,
        MIDIctrl[7], // channel volume
        MIDIctrl[11], // channel expression.
        MIDIbend*_midibendrange()*(1/8096)+_finetuning(iEffectiveMidiNote)
        );
    if (bReleased) {
        terminate;
    } else if (released && !bReleased) {
        extend 1/k_rate;
    }
    output_bus(reverb_send, aResult*MIDIctrl[91]/127.0);
    output(aResult);
}

This makes it possible to write complete GM-compatible realtime instrument
sets in SAOL/Sfx, which will then be hooked up as a standard MIDI output
device within the Windows environment.

So. GM/GS compatibility as realtime midi instruments is highly desirable.
Mandatory, actually, in the Windows environment.

Standardizing on GM semantics out of reset for SAOL orchestras is therefore
desirable from the perspective of MIDI instrument developers.

However, it also has direct impact on content authors as well. MIDI
authoring is vile enough within the confines of MIDI, and MIDI/GM. SAOL goes
a long way to addressing the historical problems with MIDI: namely, that
cross-synthesizer compatibility is all but non-existent. Even GM only
partially addresses the compatibility issue. At the present time, GM synths
are compatible (barely), but uniformly horrible. OK. They're not very
compatible.

Presumably, authors who are writing MIDI for MP4/SA streams will write using
standard MIDI authoring packages such as CakeWalk or Cubase. They will use
DLS-2/SASBF patch sets heavily, especially for percussion. SAOL will be used
mainly for special effects, high-impact feature instruments, and effects
processing. Custom routing will be used to do things like apply
chorus/flange/distortion effects to selected midi channels. Yes, I know,
that's sad, but that's probably realistic. SAOL doesn't have a lot to add in
the percussion department, for instance, when stacked against a full GM
percussion set decently authored. Authoers are going to preview their work
using a realtime soft-synth while developing it, and then, once they're
happy with the results, they'll convert the composition to a stream. Their
authoring package will analyze the stream and fill in the appropriate SASBF
elements based on actual usage in order to minimize the size of the output
stream. The SASBF elements will be streamed on demand from the DLS-2 sample
bank they were using to create the piece. (Copyright issues are about the
same as for HTML embedded fonts currently; somebody's gonna step up to the
bar with a DLS-2 font that allows this kind of use).

Given that Cubase already supports plug-in software synths, and that
DirectMusic also supports it, this kind of scenario seems pretty reasonable.

The problem occurs when we try to translate from real-time software
synthesizer to MP4/SA stream. If GM semantics don't hold then it's going to
be very difficult to translate the MIDI streams and analyze for SASBF usage.
Consider: the DLS-2 percussion instrument will be patch 0,128,0. This preset
can't be selected in a non-GM synth. How do you decide whether a MIDI stream
contains references to the GM percussion preset?

The major requirement to faciliate this is to specify that channel 9 should
be a percussion channel out of reset; either that or make support of GMReset
mandatory for SAOL/SA midi streams.

  SUMMARY
  --------------

1) MP4 Midi streams should reserve channel 9 as a percussion channel,
compatible with General MIDI.

2) Access to MIDI coarse and fine tuning settings should be provided.

3) Access to MIDI pitch bend range settings should be provided.

4) Although a nicety, access to global MIDI volume settings should be
provided.

Regards,

Robin.



This archive was generated by hypermail 2b29 : Mon Jan 28 2002 - 12:03:56 EST