aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h
diff options
context:
space:
mode:
authorJean-Francois Mauguit <jfmauguit@mac.com>2024-09-24 09:03:25 -0400
committerGitHub <noreply@github.com>2024-09-24 09:03:25 -0400
commitbab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h
parent4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff)
parent20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff)
downloadwinamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h')
-rw-r--r--Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h197
1 files changed, 197 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h b/Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h
new file mode 100644
index 00000000..2c04fa76
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/soundlib/ModInstrument.h
@@ -0,0 +1,197 @@
+/*
+ * ModInstrument.h
+ * ---------------
+ * Purpose: Module Instrument header class and helpers
+ * Notes : (currently none)
+ * Authors: OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+
+#pragma once
+
+#include "openmpt/all/BuildSettings.hpp"
+
+#include "modcommand.h"
+#include "tuningbase.h"
+#include "Snd_defs.h"
+#include "openmpt/base/FlagSet.hpp"
+#include "../common/misc_util.h"
+#include <map>
+#include <set>
+
+OPENMPT_NAMESPACE_BEGIN
+
+struct ModChannel;
+
+// Instrument Nodes
+struct EnvelopeNode
+{
+ using tick_t = uint16;
+ using value_t = uint8;
+
+ tick_t tick = 0; // Envelope node position (x axis)
+ value_t value = 0; // Envelope node value (y axis)
+
+ EnvelopeNode() { }
+ EnvelopeNode(tick_t tick, value_t value) : tick(tick), value(value) { }
+
+ bool operator== (const EnvelopeNode &other) const { return tick == other.tick && value == other.value; }
+};
+
+// Instrument Envelopes
+struct InstrumentEnvelope : public std::vector<EnvelopeNode>
+{
+ FlagSet<EnvelopeFlags> dwFlags; // Envelope flags
+ uint8 nLoopStart = 0; // Loop start node
+ uint8 nLoopEnd = 0; // Loop end node
+ uint8 nSustainStart = 0; // Sustain start node
+ uint8 nSustainEnd = 0; // Sustain end node
+ uint8 nReleaseNode = ENV_RELEASE_NODE_UNSET; // Release node
+
+ // Convert envelope data between various formats.
+ void Convert(MODTYPE fromType, MODTYPE toType);
+
+ // Get envelope value at a given tick. Assumes that the envelope data is in rage [0, rangeIn],
+ // returns value in range [0, rangeOut].
+ int32 GetValueFromPosition(int position, int32 rangeOut, int32 rangeIn = ENVELOPE_MAX) const;
+
+ // Ensure that ticks are ordered in increasing order and values are within the allowed range.
+ void Sanitize(uint8 maxValue = ENVELOPE_MAX);
+
+ uint32 size() const { return static_cast<uint32>(std::vector<EnvelopeNode>::size()); }
+
+ using std::vector<EnvelopeNode>::push_back;
+ void push_back(EnvelopeNode::tick_t tick, EnvelopeNode::value_t value) { emplace_back(tick, value); }
+};
+
+// Instrument Struct
+struct ModInstrument
+{
+ uint32 nFadeOut = 256; // Instrument fadeout speed
+ uint32 nGlobalVol = 64; // Global volume (0...64, all sample volumes are multiplied with this - TODO: This is 0...128 in Impulse Tracker)
+ uint32 nPan = 32 * 4; // Default pan (0...256), if the appropriate flag is set. Sample panning overrides instrument panning.
+
+ uint16 nVolRampUp = 0; // Default sample ramping up, 0 = use global default
+
+ ResamplingMode resampling = SRCMODE_DEFAULT; // Resampling mode
+
+ FlagSet<InstrumentFlags> dwFlags; // Instrument flags
+ NewNoteAction nNNA = NewNoteAction::NoteCut; // New note action
+ DuplicateCheckType nDCT = DuplicateCheckType::None; // Duplicate check type (i.e. which condition will trigger the duplicate note action)
+ DuplicateNoteAction nDNA = DuplicateNoteAction::NoteCut; // Duplicate note action
+
+ uint8 nPanSwing = 0; // Random panning factor (0...64)
+ uint8 nVolSwing = 0; // Random volume factor (0...100)
+
+ uint8 nIFC = 0; // Default filter cutoff (0...127). Used if the high bit is set
+ uint8 nIFR = 0; // Default filter resonance (0...127). Used if the high bit is set
+ uint8 nCutSwing = 0; // Random cutoff factor (0...64)
+ uint8 nResSwing = 0; // Random resonance factor (0...64)
+ FilterMode filterMode = FilterMode::Unchanged; // Default filter mode
+
+ int8 nPPS = 0; // Pitch/Pan separation (i.e. how wide the panning spreads, -32...32)
+ uint8 nPPC = NOTE_MIDDLEC - NOTE_MIN; // Pitch/Pan centre (zero-based)
+
+ uint16 wMidiBank = 0; // MIDI Bank (1...16384). 0 = Don't send.
+ uint8 nMidiProgram = 0; // MIDI Program (1...128). 0 = Don't send.
+ uint8 nMidiChannel = 0; // MIDI Channel (1...16). 0 = Don't send. 17 = Mapped (Send to tracker channel modulo 16).
+ uint8 nMidiDrumKey = 0; // Drum set note mapping (currently only used by the .MID loader)
+ int8 midiPWD = 2; // MIDI Pitch Wheel Depth and CMD_FINETUNE depth in semitones
+ PLUGINDEX nMixPlug = 0; // Plugin assigned to this instrument (0 = no plugin, 1 = first plugin)
+
+ PlugVelocityHandling pluginVelocityHandling = PLUGIN_VELOCITYHANDLING_CHANNEL; // How to deal with plugin velocity
+ PlugVolumeHandling pluginVolumeHandling = PLUGIN_VOLUMEHANDLING_IGNORE; // How to deal with plugin volume
+
+ TEMPO pitchToTempoLock; // BPM at which the samples assigned to this instrument loop correctly (0 = unset)
+ CTuning *pTuning = nullptr; // sample tuning assigned to this instrument
+
+ InstrumentEnvelope VolEnv; // Volume envelope data
+ InstrumentEnvelope PanEnv; // Panning envelope data
+ InstrumentEnvelope PitchEnv; // Pitch / filter envelope data
+
+ std::array<uint8, 128> NoteMap; // Note mapping, e.g. C-5 => D-5
+ std::array<SAMPLEINDEX, 128> Keyboard; // Sample mapping, e.g. C-5 => Sample 1
+
+ mpt::charbuf<MAX_INSTRUMENTNAME> name;
+ mpt::charbuf<MAX_INSTRUMENTFILENAME> filename;
+
+ std::string GetName() const { return name; }
+ std::string GetFilename() const { return filename; }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // WHEN adding new members here, ALSO update InstrumentExtensions.cpp
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ ModInstrument(SAMPLEINDEX sample = 0);
+
+ // Assign all notes to a given sample.
+ void AssignSample(SAMPLEINDEX sample)
+ {
+ Keyboard.fill(sample);
+ }
+
+ // Reset note mapping (i.e. every note is mapped to itself)
+ void ResetNoteMap()
+ {
+ std::iota(NoteMap.begin(), NoteMap.end(), static_cast<uint8>(NOTE_MIN));
+ }
+
+ // If the instrument has a non-default note mapping and can be simplified to use the default note mapping by transposing samples,
+ // the list of samples that would need to be transposed and the corresponding transpose values are returned - otherwise an empty map.
+ std::map<SAMPLEINDEX, int8> CanConvertToDefaultNoteMap() const;
+
+ // Transpose entire note mapping by given number of semitones
+ void Transpose(int8 amount);
+
+ bool IsCutoffEnabled() const { return (nIFC & 0x80) != 0; }
+ bool IsResonanceEnabled() const { return (nIFR & 0x80) != 0; }
+ uint8 GetCutoff() const { return (nIFC & 0x7F); }
+ uint8 GetResonance() const { return (nIFR & 0x7F); }
+ void SetCutoff(uint8 cutoff, bool enable) { nIFC = std::min(cutoff, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
+ void SetResonance(uint8 resonance, bool enable) { nIFR = std::min(resonance, uint8(0x7F)) | (enable ? 0x80 : 0x00); }
+
+ bool HasValidMIDIChannel() const { return (nMidiChannel >= 1 && nMidiChannel <= 17); }
+ uint8 GetMIDIChannel(const ModChannel &channel, CHANNELINDEX chn) const;
+
+ void SetTuning(CTuning *pT)
+ {
+ pTuning = pT;
+ }
+
+ // Get a reference to a specific envelope of this instrument
+ const InstrumentEnvelope &GetEnvelope(EnvelopeType envType) const
+ {
+ switch(envType)
+ {
+ case ENV_VOLUME:
+ default:
+ return VolEnv;
+ case ENV_PANNING:
+ return PanEnv;
+ case ENV_PITCH:
+ return PitchEnv;
+ }
+ }
+
+ InstrumentEnvelope &GetEnvelope(EnvelopeType envType)
+ {
+ return const_cast<InstrumentEnvelope &>(static_cast<const ModInstrument &>(*this).GetEnvelope(envType));
+ }
+
+ // Get a set of all samples referenced by this instrument
+ std::set<SAMPLEINDEX> GetSamples() const;
+
+ // Write sample references into a bool vector. If a sample is referenced by this instrument, true is written.
+ // The caller has to initialize the vector.
+ void GetSamples(std::vector<bool> &referencedSamples) const;
+
+ // Translate instrument properties between two given formats.
+ void Convert(MODTYPE fromType, MODTYPE toType);
+
+ // Sanitize all instrument data.
+ void Sanitize(MODTYPE modType);
+
+};
+
+OPENMPT_NAMESPACE_END