pub enum EffectCmd {
Show 26 variants
SetSpeed(RangedU8<1, 255>),
JumpOrder(u8),
BreakRow(u8),
VolumeSlide(Option<VolumeSlide>),
PortamentoDown(Option<Portamento>),
PortamentoUp(Option<Portamento>),
TonePortamento(Option<RangedU8<1, 0xFF>>),
Vibrato(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>),
Tremor(Option<(RangedU8<1, 0x0F>, RangedU8<1, 0x0F>)>),
Arpeggio(Option<(RangedU8<0, 0x0F>, RangedU8<0, 0x0F>)>),
VolumeSlideAndVibrato(Option<VolumeSlide>),
VolumeSlideAndPortamento(Option<VolumeSlide>),
SetChannelVolume(RangedU8<0, 0x40>),
ChannelVolumeSlide(Option<VolumeSlide>),
SetSampleOffset(SetSampleOffset),
PanningSlide(Option<PanningSlide>),
Retrigger(Option<(RangedU8<1, 0x0F>, RangedU8<1, 0x0F>)>),
Tremolo(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>),
Special(Option<Special>),
Tempo(Option<Tempo>),
FineVibrato(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>),
SetGlobalVolume(RangedU8<0, 0x80>),
GlobalVolumeSlide(Option<VolumeSlide>),
SetPanningPosition(u8),
Panbrello(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>),
Midi(u8),
}Expand description
Effect column commands
All parameters are displayed in hexadecimal.
Parameters are parsed by nibbles and masks on them. Each command has one byte of parameter data
to work with. Axx means the command A uses the whole byte as its argument, Hxy means the
command H uses the first nibble as parameter x and second nibble as parameter y.
Some commands like D use masks to further granularize the command, however some commands only
use a subset of the values u8 can have.
The parser should be handling of out-of-range values by canonicalizing them into some in range value and this behaviour should be documented for each value in a “Canonicalization” section. Parser should never crash because of an out-of-range value and the representation should not allow for out-of-range values to get through.
§Additional resources
Variants§
SetSpeed(RangedU8<1, 255>)
Axx Set Speed
Sets the module Speed (ticks per row).
§Canonicalization
The value 0 does nothing so the effect command get skipped by the parser.
JumpOrder(u8)
Bxx Jump to Order
Causes playback to jump to pattern position xx.
B00 would restart a song from the beginning (first pattern in the Order List).
If Cxx is on the same row, the pattern specified by Bxx will be
the pattern Cxx jumps into.
BreakRow(u8)
Cxx Break to row xx of next pattern
Jumps to row xx of the next pattern in the Order List.
If the current pattern is the last pattern in the Order List, Cxx will jump to row xx
of the first pattern.
If Bxx is on the same row, the pattern specified by Bxx will be
the pattern Cxx jumps into.
Ranges from 0x00 to the next pattern’s row length, higher values are to be treated as 0x00.
VolumeSlide(Option<VolumeSlide>)
Dxx Volume Slide or Fine Volume Slide
Slides the current volume up or down.
None uses the last value, memory is shared with Hxy and Uxy.
PortamentoDown(Option<Portamento>)
Exx Portamento down
See Portamento for more details.
None uses the last value, memory is shared with the e0x volume command.
PortamentoUp(Option<Portamento>)
Fxx Portamento up
See Portamento for more details.
None uses the last value, memory is shared with the f0x volume command.
TonePortamento(Option<RangedU8<1, 0xFF>>)
Gxx Slide to note with speed xx
Slides the pitch of the previous note towards the current note by xx units on every tick
of the row except the first.
Slide can be either smooth or semitone-wise, see Special::SetGlissando for details.
None uses the last value.
Vibrato(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>)
Hxy Vibrato with speed x, depth y
Executes vibrato with speed x and depth y on the current note.
Modulates with selected vibrato waveform Special::SetVibratoWaveform.
None uses the last value, each parameter has its separate memory.
Memory is shared with Uxy.
Tremor(Option<(RangedU8<1, 0x0F>, RangedU8<1, 0x0F>)>)
Ixy Tremor with ontime x and offtime y
None uses the last value.
Arpeggio(Option<(RangedU8<0, 0x0F>, RangedU8<0, 0x0F>)>)
Jxy Arpeggio with halftones x and y
Plays an arpeggiation of three notes in one row, cycling between the current note, current
note + x semitones, and current note + y semitones.
None uses the last value. Currently None gets parsed only if both parameters are 0.
Serialization is not implemented yet and this type will very likely change before it is.
For more information see the notes below.
§Notes
We remember reading somewhere (even the code had it that way) that the arpeggiation was
only between two notes if x == y. Now we can’t find it either on the OpenMPT wiki Effect
Reference page, nor in OpenMPT or Schism Tracker source code. This might be just
misremembering but we’ll be leaving this note here for now in case somebody finds somewhere
mentioning that thing. Sorry.
Ok! We found something. In OpenMPT (master, rev 70efda227)
file soundlib/Sndmix.cpp, function CSoundFile::ProcessArpeggio (link):
// Trigger new note:
// - If there's an arpeggio on this row and
// - the note to trigger is not the same as the previous arpeggio note or
// - a pattern note has just been triggered on this tick
// - If there's no arpeggio
// - but an arpeggio note is still active and
// - there's no note stop or new note that would stop it anyway
if((arpOnRow && chn.nArpeggioLastNote != chn.nArpeggioBaseNote + step && (!m_SongFlags[SONG_FIRSTTICK] || !chn.rowCommand.IsNote()))
|| (!arpOnRow && chn.rowCommand.note == NOTE_NONE && chn.nArpeggioLastNote != NOTE_NONE))
SendMIDINote(nChn, chn.nArpeggioBaseNote + step, static_cast<uint16>(chn.nVolume));
// Stop note:
// - If some arpeggio note is still registered or
// - When starting an arpeggio on a row with no other note on it, stop some possibly still playing note.
if(chn.nArpeggioLastNote != NOTE_NONE)
SendMIDINote(nChn, chn.nArpeggioLastNote + NOTE_MAX_SPECIAL, 0);
else if(arpOnRow && m_SongFlags[SONG_FIRSTTICK] && !chn.rowCommand.IsNote() && ModCommand::IsNote(lastNote))
SendMIDINote(nChn, lastNote + NOTE_MAX_SPECIAL, 0);
if(chn.rowCommand.command == CMD_ARPEGGIO)
chn.nArpeggioLastNote = chn.nArpeggioBaseNote + step;
else
chn.nArpeggioLastNote = NOTE_NONE;If we read this correctly it means arpeggio can have either None (reuse last effect) or
can make 0, 1 or 2 retriggers, or even act like a note cut if the command doesn’t have any
base note.
VolumeSlideAndVibrato(Option<VolumeSlide>)
Kxy Dual Command: H00 & Dxy
Functions like Dxy with H00. Parameters are used the same way as Dxy.
None uses the last value.
VolumeSlideAndPortamento(Option<VolumeSlide>)
Lxx Dual Command: G00 & Dxy
Functions like Dxy with G00. Parameters are used the same way as Dxy.
None uses the last value.
SetChannelVolume(RangedU8<0, 0x40>)
Mxx Set channel volume to xx
Sets the current channel volume, which multiplies all note volumes it encompasses.
§Canonicalization
All values above 0x40 are clipped to 0x40.
ChannelVolumeSlide(Option<VolumeSlide>)
Nxy Channel volume slide
Similar to Dxy, but applies to the current channel’s volume.
None uses the last value.
SetSampleOffset(SetSampleOffset)
Oxx Set sample offset to 0xyxx00, SAy Set high value of sample offset 0xyxx00
See SetSampleOffset for more details.
PanningSlide(Option<PanningSlide>)
Retrigger(Option<(RangedU8<1, 0x0F>, RangedU8<1, 0x0F>)>)
Qxy Retrigger note every y ticks with volume modifier x
Values for x:
0: No volume change 8: Not used
1: -1 9: +1
2: -2 A: +2
3: -4 B: +4
4: -8 C: +8
5: -16 D: +16
6: *2/3 E: *3/2
7: *1/2 F: *2None uses the last value.
§Canonicalization
Value 8 is replaced by 0 during parsing.
Tremolo(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>)
Rxy Tremolo with speed x, depth y
Executes tremolo weith speed x and depth y on the current note.
Modulates with selected tremolo waveform Special::SetTremoloWaveform.
None uses the last value, each parameter has its separate memory.
Memory is shared with Uxy.
Special(Option<Special>)
Sxx Special commands
None uses the last value, memory is shared by all Sxx subcommands.
§Canonicalization
The second nibble is ignored when parsing the special subcommand, any value in range
S00..=S0F will be parsed as None, but it will only be serialized as S00.
Tempo(Option<Tempo>)
FineVibrato(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>)
Uxy Fine vibrato with speed x, depth y
Similar to Hxy, but with 4 times the precision.
See EffectCmd::Vibrato for more details.
None uses the last value, each parameter has its separate memory.
Memory is shared with Hxy.
SetGlobalVolume(RangedU8<0, 0x80>)
GlobalVolumeSlide(Option<VolumeSlide>)
Wxx Global volume slide
Similar to Dxy, but applies to global volume.
None uses the last value.
SetPanningPosition(u8)
Xxx Set panning position
Sets the current channel’s panning position.
Ranges from 0x00 (left) to 0xFF (right).
Panbrello(Option<RangedU8<1, 0x0F>>, Option<RangedU8<1, 0x0F>>)
Yxy Panbrello with speed x, depth y
Executes panbrello with speed x and depth y on the current note.
Modulates with selected panbrello waveform Special::SetPanbrelloWaveform.
None uses the last value, each parameter has its separate memory.
Memory is shared with Uxy.
Midi(u8)
Zxx MIDI Macros
Executes a MIDI macro.
This effect is rather complicated so we don’t attempt to parse it any further. For more information see the OpenMPT wiki article.