1
0

ModInstrument.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * ModInstrument.h
  3. * ---------------
  4. * Purpose: Module Instrument header class and helpers
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "modcommand.h"
  12. #include "tuningbase.h"
  13. #include "Snd_defs.h"
  14. #include "openmpt/base/FlagSet.hpp"
  15. #include "../common/misc_util.h"
  16. #include <map>
  17. #include <set>
  18. OPENMPT_NAMESPACE_BEGIN
  19. struct ModChannel;
  20. // Instrument Nodes
  21. struct EnvelopeNode
  22. {
  23. using tick_t = uint16;
  24. using value_t = uint8;
  25. tick_t tick = 0; // Envelope node position (x axis)
  26. value_t value = 0; // Envelope node value (y axis)
  27. EnvelopeNode() { }
  28. EnvelopeNode(tick_t tick, value_t value) : tick(tick), value(value) { }
  29. bool operator== (const EnvelopeNode &other) const { return tick == other.tick && value == other.value; }
  30. };
  31. // Instrument Envelopes
  32. struct InstrumentEnvelope : public std::vector<EnvelopeNode>
  33. {
  34. FlagSet<EnvelopeFlags> dwFlags; // Envelope flags
  35. uint8 nLoopStart = 0; // Loop start node
  36. uint8 nLoopEnd = 0; // Loop end node
  37. uint8 nSustainStart = 0; // Sustain start node
  38. uint8 nSustainEnd = 0; // Sustain end node
  39. uint8 nReleaseNode = ENV_RELEASE_NODE_UNSET; // Release node
  40. // Convert envelope data between various formats.
  41. void Convert(MODTYPE fromType, MODTYPE toType);
  42. // Get envelope value at a given tick. Assumes that the envelope data is in rage [0, rangeIn],
  43. // returns value in range [0, rangeOut].
  44. int32 GetValueFromPosition(int position, int32 rangeOut, int32 rangeIn = ENVELOPE_MAX) const;
  45. // Ensure that ticks are ordered in increasing order and values are within the allowed range.
  46. void Sanitize(uint8 maxValue = ENVELOPE_MAX);
  47. uint32 size() const { return static_cast<uint32>(std::vector<EnvelopeNode>::size()); }
  48. using std::vector<EnvelopeNode>::push_back;
  49. void push_back(EnvelopeNode::tick_t tick, EnvelopeNode::value_t value) { emplace_back(tick, value); }
  50. };
  51. // Instrument Struct
  52. struct ModInstrument
  53. {
  54. uint32 nFadeOut = 256; // Instrument fadeout speed
  55. uint32 nGlobalVol = 64; // Global volume (0...64, all sample volumes are multiplied with this - TODO: This is 0...128 in Impulse Tracker)
  56. uint32 nPan = 32 * 4; // Default pan (0...256), if the appropriate flag is set. Sample panning overrides instrument panning.
  57. uint16 nVolRampUp = 0; // Default sample ramping up, 0 = use global default
  58. ResamplingMode resampling = SRCMODE_DEFAULT; // Resampling mode
  59. FlagSet<InstrumentFlags> dwFlags; // Instrument flags
  60. NewNoteAction nNNA = NewNoteAction::NoteCut; // New note action
  61. DuplicateCheckType nDCT = DuplicateCheckType::None; // Duplicate check type (i.e. which condition will trigger the duplicate note action)
  62. DuplicateNoteAction nDNA = DuplicateNoteAction::NoteCut; // Duplicate note action
  63. uint8 nPanSwing = 0; // Random panning factor (0...64)
  64. uint8 nVolSwing = 0; // Random volume factor (0...100)
  65. uint8 nIFC = 0; // Default filter cutoff (0...127). Used if the high bit is set
  66. uint8 nIFR = 0; // Default filter resonance (0...127). Used if the high bit is set
  67. uint8 nCutSwing = 0; // Random cutoff factor (0...64)
  68. uint8 nResSwing = 0; // Random resonance factor (0...64)
  69. FilterMode filterMode = FilterMode::Unchanged; // Default filter mode
  70. int8 nPPS = 0; // Pitch/Pan separation (i.e. how wide the panning spreads, -32...32)
  71. uint8 nPPC = NOTE_MIDDLEC - NOTE_MIN; // Pitch/Pan centre (zero-based)
  72. uint16 wMidiBank = 0; // MIDI Bank (1...16384). 0 = Don't send.
  73. uint8 nMidiProgram = 0; // MIDI Program (1...128). 0 = Don't send.
  74. uint8 nMidiChannel = 0; // MIDI Channel (1...16). 0 = Don't send. 17 = Mapped (Send to tracker channel modulo 16).
  75. uint8 nMidiDrumKey = 0; // Drum set note mapping (currently only used by the .MID loader)
  76. int8 midiPWD = 2; // MIDI Pitch Wheel Depth and CMD_FINETUNE depth in semitones
  77. PLUGINDEX nMixPlug = 0; // Plugin assigned to this instrument (0 = no plugin, 1 = first plugin)
  78. PlugVelocityHandling pluginVelocityHandling = PLUGIN_VELOCITYHANDLING_CHANNEL; // How to deal with plugin velocity
  79. PlugVolumeHandling pluginVolumeHandling = PLUGIN_VOLUMEHANDLING_IGNORE; // How to deal with plugin volume
  80. TEMPO pitchToTempoLock; // BPM at which the samples assigned to this instrument loop correctly (0 = unset)
  81. CTuning *pTuning = nullptr; // sample tuning assigned to this instrument
  82. InstrumentEnvelope VolEnv; // Volume envelope data
  83. InstrumentEnvelope PanEnv; // Panning envelope data
  84. InstrumentEnvelope PitchEnv; // Pitch / filter envelope data
  85. std::array<uint8, 128> NoteMap; // Note mapping, e.g. C-5 => D-5
  86. std::array<SAMPLEINDEX, 128> Keyboard; // Sample mapping, e.g. C-5 => Sample 1
  87. mpt::charbuf<MAX_INSTRUMENTNAME> name;
  88. mpt::charbuf<MAX_INSTRUMENTFILENAME> filename;
  89. std::string GetName() const { return name; }
  90. std::string GetFilename() const { return filename; }
  91. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  92. // WHEN adding new members here, ALSO update InstrumentExtensions.cpp
  93. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  94. ModInstrument(SAMPLEINDEX sample = 0);
  95. // Assign all notes to a given sample.
  96. void AssignSample(SAMPLEINDEX sample)
  97. {
  98. Keyboard.fill(sample);
  99. }
  100. // Reset note mapping (i.e. every note is mapped to itself)
  101. void ResetNoteMap()
  102. {
  103. std::iota(NoteMap.begin(), NoteMap.end(), static_cast<uint8>(NOTE_MIN));
  104. }
  105. // If the instrument has a non-default note mapping and can be simplified to use the default note mapping by transposing samples,
  106. // the list of samples that would need to be transposed and the corresponding transpose values are returned - otherwise an empty map.
  107. std::map<SAMPLEINDEX, int8> CanConvertToDefaultNoteMap() const;
  108. // Transpose entire note mapping by given number of semitones
  109. void Transpose(int8 amount);
  110. bool IsCutoffEnabled() const { return (nIFC & 0x80) != 0; }
  111. bool IsResonanceEnabled() const { return (nIFR & 0x80) != 0; }
  112. uint8 GetCutoff() const { return (nIFC & 0x7F); }
  113. uint8 GetResonance() const { return (nIFR & 0x7F); }
  114. void SetCutoff(uint8 cutoff, bool enable) { nIFC = std::min(cutoff, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
  115. void SetResonance(uint8 resonance, bool enable) { nIFR = std::min(resonance, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
  116. bool HasValidMIDIChannel() const { return (nMidiChannel >= 1 && nMidiChannel <= 17); }
  117. uint8 GetMIDIChannel(const ModChannel &channel, CHANNELINDEX chn) const;
  118. void SetTuning(CTuning *pT)
  119. {
  120. pTuning = pT;
  121. }
  122. // Get a reference to a specific envelope of this instrument
  123. const InstrumentEnvelope &GetEnvelope(EnvelopeType envType) const
  124. {
  125. switch(envType)
  126. {
  127. case ENV_VOLUME:
  128. default:
  129. return VolEnv;
  130. case ENV_PANNING:
  131. return PanEnv;
  132. case ENV_PITCH:
  133. return PitchEnv;
  134. }
  135. }
  136. InstrumentEnvelope &GetEnvelope(EnvelopeType envType)
  137. {
  138. return const_cast<InstrumentEnvelope &>(static_cast<const ModInstrument &>(*this).GetEnvelope(envType));
  139. }
  140. // Get a set of all samples referenced by this instrument
  141. std::set<SAMPLEINDEX> GetSamples() const;
  142. // Write sample references into a bool vector. If a sample is referenced by this instrument, true is written.
  143. // The caller has to initialize the vector.
  144. void GetSamples(std::vector<bool> &referencedSamples) const;
  145. // Translate instrument properties between two given formats.
  146. void Convert(MODTYPE fromType, MODTYPE toType);
  147. // Sanitize all instrument data.
  148. void Sanitize(MODTYPE modType);
  149. };
  150. OPENMPT_NAMESPACE_END