#pragma once
#include "BuildSettings.h"
#include "Snd_defs.h"
#include "../common/misc_util.h"
OPENMPT_NAMESPACE_BEGIN
class CSoundFile;
#define NOTE_NONE (ModCommand::NOTE(0))
#define NOTE_MIN (ModCommand::NOTE(1))
#define NOTE_MAX (ModCommand::NOTE(120))
#define NOTE_MIDDLEC (ModCommand::NOTE(5 * 12 + NOTE_MIN))
#define NOTE_KEYOFF (ModCommand::NOTE(0xFF))
#define NOTE_NOTECUT (ModCommand::NOTE(0xFE))
#define NOTE_FADE (ModCommand::NOTE(0xFD))
#define NOTE_PC (ModCommand::NOTE(0xFC))
#define NOTE_PCS (ModCommand::NOTE(0xFB))
#define NOTE_MAX_SPECIAL NOTE_KEYOFF
#define NOTE_MIN_SPECIAL NOTE_PCS
enum VolumeCommand : uint8
{
VOLCMD_NONE = 0,
VOLCMD_VOLUME = 1,
VOLCMD_PANNING = 2,
VOLCMD_VOLSLIDEUP = 3,
VOLCMD_VOLSLIDEDOWN = 4,
VOLCMD_FINEVOLUP = 5,
VOLCMD_FINEVOLDOWN = 6,
VOLCMD_VIBRATOSPEED = 7,
VOLCMD_VIBRATODEPTH = 8,
VOLCMD_PANSLIDELEFT = 9,
VOLCMD_PANSLIDERIGHT = 10,
VOLCMD_TONEPORTAMENTO = 11,
VOLCMD_PORTAUP = 12,
VOLCMD_PORTADOWN = 13,
VOLCMD_DELAYCUT = 14, VOLCMD_OFFSET = 15,
MAX_VOLCMDS = 16
};
enum EffectCommand : uint8
{
CMD_NONE = 0,
CMD_ARPEGGIO = 1,
CMD_PORTAMENTOUP = 2,
CMD_PORTAMENTODOWN = 3,
CMD_TONEPORTAMENTO = 4,
CMD_VIBRATO = 5,
CMD_TONEPORTAVOL = 6,
CMD_VIBRATOVOL = 7,
CMD_TREMOLO = 8,
CMD_PANNING8 = 9,
CMD_OFFSET = 10,
CMD_VOLUMESLIDE = 11,
CMD_POSITIONJUMP = 12,
CMD_VOLUME = 13,
CMD_PATTERNBREAK = 14,
CMD_RETRIG = 15,
CMD_SPEED = 16,
CMD_TEMPO = 17,
CMD_TREMOR = 18,
CMD_MODCMDEX = 19,
CMD_S3MCMDEX = 20,
CMD_CHANNELVOLUME = 21,
CMD_CHANNELVOLSLIDE = 22,
CMD_GLOBALVOLUME = 23,
CMD_GLOBALVOLSLIDE = 24,
CMD_KEYOFF = 25,
CMD_FINEVIBRATO = 26,
CMD_PANBRELLO = 27,
CMD_XFINEPORTAUPDOWN = 28,
CMD_PANNINGSLIDE = 29,
CMD_SETENVPOSITION = 30,
CMD_MIDI = 31,
CMD_SMOOTHMIDI = 32,
CMD_DELAYCUT = 33,
CMD_XPARAM = 34,
CMD_NOTESLIDEUP = 35, CMD_NOTESLIDEDOWN = 36, CMD_NOTESLIDEUPRETRIG = 37, CMD_NOTESLIDEDOWNRETRIG = 38, CMD_REVERSEOFFSET = 39, CMD_DBMECHO = 40, CMD_OFFSETPERCENTAGE = 41, MAX_EFFECTS = 42
};
enum EffectType : uint8
{
EFFECT_TYPE_NORMAL = 0,
EFFECT_TYPE_GLOBAL = 1,
EFFECT_TYPE_VOLUME = 2,
EFFECT_TYPE_PANNING = 3,
EFFECT_TYPE_PITCH = 4,
MAX_EFFECT_TYPE = 5
};
class ModCommand
{
public:
typedef uint8 NOTE;
typedef uint8 INSTR;
typedef uint8 VOL;
typedef uint8 VOLCMD;
typedef uint8 COMMAND;
typedef uint8 PARAM;
enum : int { maxColumnValue = 999 };
static ModCommand Empty() { return ModCommand(); }
bool operator==(const ModCommand& mc) const
{
return (note == mc.note)
&& (instr == mc.instr)
&& (volcmd == mc.volcmd)
&& (command == mc.command)
&& ((volcmd == VOLCMD_NONE && !IsPcNote()) || vol == mc.vol)
&& ((command == CMD_NONE && !IsPcNote()) || param == mc.param);
}
bool operator!=(const ModCommand& mc) const { return !(*this == mc); }
void Set(NOTE n, INSTR ins, uint16 volcol, uint16 effectcol) { note = n; instr = ins; SetValueVolCol(volcol); SetValueEffectCol(effectcol); }
uint16 GetValueVolCol() const { return GetValueVolCol(volcmd, vol); }
static uint16 GetValueVolCol(uint8 volcmd, uint8 vol) { return (volcmd << 8) + vol; }
void SetValueVolCol(const uint16 val) { volcmd = static_cast<VOLCMD>(val >> 8); vol = static_cast<uint8>(val & 0xFF); }
uint16 GetValueEffectCol() const { return GetValueEffectCol(command, param); }
static uint16 GetValueEffectCol(uint8 command, uint8 param) { return (command << 8) + param; }
void SetValueEffectCol(const uint16 val) { command = static_cast<COMMAND>(val >> 8); param = static_cast<uint8>(val & 0xFF); }
void Clear() { memset(this, 0, sizeof(ModCommand)); }
bool IsEmpty() const
{
return (note == NOTE_NONE && instr == 0 && volcmd == VOLCMD_NONE && command == CMD_NONE);
}
bool IsInstrPlug() const { return IsPcNote(); }
bool IsPcNote() const { return IsPcNote(note); }
static bool IsPcNote(NOTE note) { return note == NOTE_PC || note == NOTE_PCS; }
bool IsNote() const { return IsInRange(note, NOTE_MIN, NOTE_MAX); }
static bool IsNote(NOTE note) { return IsInRange(note, NOTE_MIN, NOTE_MAX); }
bool IsSpecialNote() const { return IsInRange(note, NOTE_MIN_SPECIAL, NOTE_MAX_SPECIAL); }
static bool IsSpecialNote(NOTE note) { return IsInRange(note, NOTE_MIN_SPECIAL, NOTE_MAX_SPECIAL); }
bool IsNoteOrEmpty() const { return note == NOTE_NONE || IsNote(); }
static bool IsNoteOrEmpty(NOTE note) { return note == NOTE_NONE || IsNote(note); }
bool IsPortamento() const { return command == CMD_TONEPORTAMENTO || command == CMD_TONEPORTAVOL || volcmd == VOLCMD_TONEPORTAMENTO; }
bool IsGlobalCommand() const;
bool IsAmigaNote() const { return IsAmigaNote(note); }
static bool IsAmigaNote(NOTE note) { return !IsNote(note) || (note >= NOTE_MIDDLEC - 12 && note < NOTE_MIDDLEC + 24); }
static EffectType GetEffectType(COMMAND cmd);
EffectType GetEffectType() const { return GetEffectType(command); }
static EffectType GetVolumeEffectType(VOLCMD volcmd);
EffectType GetVolumeEffectType() const { return GetVolumeEffectType(volcmd); }
void Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &sndFile);
void ExtendedMODtoS3MEffect();
void ExtendedS3MtoMODEffect();
static size_t GetEffectWeight(COMMAND cmd);
static bool ConvertVolEffect(uint8 &effect, uint8 ¶m, bool force);
static bool TwoRegularCommandsToMPT(uint8 &effect1, uint8 ¶m1, uint8 &effect2, uint8 ¶m2);
static bool CombineEffects(uint8 &eff1, uint8 ¶m1, uint8 &eff2, uint8 ¶m2);
public:
uint8 note = NOTE_NONE;
uint8 instr = 0;
uint8 volcmd = VOLCMD_NONE;
uint8 command = CMD_NONE;
uint8 vol = 0;
uint8 param = 0;
};
OPENMPT_NAMESPACE_END