-
-
Notifications
You must be signed in to change notification settings - Fork 8
FM Presets
There are 128 built-in presets. They are based on Wohlstand's XG bank from libOPNMIDI. The interface defaults all FM channels to instrument 0 (Grand Piano) on start-up. You can also define up to 128 user presets (each taking place of a built-in preset).
Don't want to mess around with SysEx? The Mega Drive MIDI Interface CLI can be used to send these SysEx messages for you and also provide the following functionality:
- Load presets from DMP, TFI, WOPN files
- Dump presets to DMP, TFI files
Sending a MIDI program change (0xC) message will select an FM preset.
If MIDI channel 10 is mapped to an FM channel, the interface will make use of a separate bank of percussion instruments. By default, MIDI channel 10 is set to the PSG noise channel. To map MIDI channel 10 to FM channel 6 (for example), use the SysEx sequence 00 22 77 00 09 05
.
You can store the current parameters of any MIDI channel currently assigned to an FM channel by sending CC 87, with the value of the MIDI program you want to define. The UI should indicate a preset has been stored this way. You can then retrieve these parameters at any time using the MIDI program change message.
A preset can be loaded via SysEx as follows:
SysEx:
00 22 77 0A <type> <program> ...
-
type
: Type of preset. FM = 0. -
program
: The MIDI program the user preset will be stored under (0-127)
Followed by channel FM parameters:
... <alg> <fb> <ams> <fms> ...
-
alg
: Algorithm (0-7) -
fb
: Feedback (0-7) -
ams
: AMS (0-3) -
fms
: FMS (0-7)
Then the sets of operator FM parameters (repeat 4 times):
... <mul> <dt> <ar> <rs> <dr> <am> <sl> <sr> <rr> <tl> <ssg>
-
mul
: Multiple (0-15) -
dt
: Detune (0-7) -
ar
: Attack Rate (0-31) -
rs
: Rate Scaling (0-3) -
dr
: Decay Rate (0-31) -
am
: Amplitude Modulation (0-1) -
sl
: Sustain Level (0-15) -
sr
: Sustain Rate (0-15) -
rr
: Release Rate (0-15) -
tl
: Total Level (0-127) -
ssg
: SSG-EG (0-15)
You should get a message on the UI saying a preset has been loaded. Check out the load-fm-preset script for an example of how to construct the SysEx message.
SysEx:
00 22 77 0B <type> <program>
-
type
: Type of preset. FM = 0. -
program
: The MIDI program (0-127) to clear.
SysEx:
00 22 77 0C <type>
First send a dump request using SysEx:
00 22 77 0D <type> <program>
-
type
: Type of preset. FM = 0. -
program
: The MIDI program (0-127) to dump.
MDMI will then respond with the preset data, in the same format as that which you would use to load a preset, except that the command ID will be 0E
(rather than 0A
when loading):
SysEx response:
00 22 77 0E <type> <program> <alg> <fb> <ams> <fms> ...
First send a dump request using SysEx:
00 22 77 0F <type> <midi_channel>
-
type
: Type of channel. FM = 0. -
midi_channel
: The MIDI channel (0-15) assigned to the FM channel from which to dump the parameters
MDMI will then respond with the channel data, in the same format as that which you would use to load a preset, except that the command ID in the response will be 10
:
SysEx response:
00 22 77 10 <type> <midi_channel> <alg> <fb> <ams> <fms> ...
You can change the built-in presets by modifying the FmPreset
definitions in presets.c
.
static const FmPreset M_BANK_0_INST_0_GRANDPIANO =
{ 2, 0, 0, 0, {
{ 1, 0, 26, 1, 7, 0, 7, 4, 1, 39, 0 }, // op 1
{ 2, 7, 31, 3, 23, 0, 9, 15, 1, 4, 0 }, // op 2
{ 4, 6, 24, 1, 9, 0, 6, 9, 7, 36, 0 }, // op 3
{ 1, 3, 27, 2, 4, 0, 10, 4, 6, 2, 0 } // op 4
} };
The structure of FmPreset
is as follows:
typedef struct FmPreset {
u8 algorithm : 3;
u8 feedback : 3;
u8 ams : 2;
u8 fms : 3;
Operator operators[4];
} FmPreset;
typedef struct Operator {
u8 multiple : 4;
u8 detune : 3;
u8 attackRate : 5;
u8 rateScaling : 2;
u8 decayRate : 5;
u8 amplitudeModulation : 1;
u8 sustainLevel : 4;
u8 sustainRate : 5;
u8 releaseRate : 4;
u8 totalLevel : 7;
u8 ssgEg : 4;
} Operator;
Pay also close attention to the order of the operators. They are defined in sequential order (1, 2, 3, 4), rather than register order (1, 3, 2, 4). Check out the algorithm diagrams as these use the same ordering.
These are defined in a similar way to FmPreset
but have an additional key
value, which is the MIDI pitch value that the preset should be played with when the note/key is triggered.
typedef struct PercussionPreset {
FmPreset preset;
u8 key;
} PercussionPreset;
For example:
static const PercussionPreset P_BANK_0_INST_30_CASTANETS =
{ { 4, 3, 0, 0, {
{ 9, 0, 31, 0, 11, 0, 15, 0, 15, 23, 0 },
{ 4, 0, 31, 2, 20, 0, 15, 0, 15, 13, 0 },
{ 1, 0, 31, 0, 19, 0, 15, 0, 15, 15, 0 },
{ 2, 0, 31, 2, 20, 0, 15, 0, 15, 13, 0 } } },
62 // MIDI pitch
};