ModChannel.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * ModChannel.h
  3. * ------------
  4. * Purpose: Module Channel 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 "ModSample.h"
  12. #include "ModInstrument.h"
  13. #include "modcommand.h"
  14. #include "Paula.h"
  15. #include "tuningbase.h"
  16. OPENMPT_NAMESPACE_BEGIN
  17. class CSoundFile;
  18. // Mix Channel Struct
  19. struct ModChannel
  20. {
  21. // Envelope playback info
  22. struct EnvInfo
  23. {
  24. uint32 nEnvPosition = 0;
  25. int16 nEnvValueAtReleaseJump = NOT_YET_RELEASED;
  26. FlagSet<EnvelopeFlags> flags;
  27. void Reset()
  28. {
  29. nEnvPosition = 0;
  30. nEnvValueAtReleaseJump = NOT_YET_RELEASED;
  31. }
  32. };
  33. // Information used in the mixer (should be kept tight for better caching)
  34. SamplePosition position; // Current play position (fixed point)
  35. SamplePosition increment; // Sample speed relative to mixing frequency (fixed point)
  36. const void *pCurrentSample; // Currently playing sample (nullptr if no sample is playing)
  37. int32 leftVol; // 0...4096 (12 bits, since 16 bits + 12 bits = 28 bits = 0dB in integer mixer, see MIXING_ATTENUATION)
  38. int32 rightVol; // Ditto
  39. int32 leftRamp; // Ramping delta, 20.12 fixed point (see VOLUMERAMPPRECISION)
  40. int32 rightRamp; // Ditto
  41. int32 rampLeftVol; // Current ramping volume, 20.12 fixed point (see VOLUMERAMPPRECISION)
  42. int32 rampRightVol; // Ditto
  43. mixsample_t nFilter_Y[2][2]; // Filter memory - two history items per sample channel
  44. mixsample_t nFilter_A0, nFilter_B0, nFilter_B1; // Filter coeffs
  45. mixsample_t nFilter_HP;
  46. SmpLength nLength;
  47. SmpLength nLoopStart;
  48. SmpLength nLoopEnd;
  49. FlagSet<ChannelFlags> dwFlags;
  50. mixsample_t nROfs, nLOfs;
  51. uint32 nRampLength;
  52. const ModSample *pModSample; // Currently assigned sample slot (may already be stopped)
  53. Paula::State paulaState;
  54. // Information not used in the mixer
  55. const ModInstrument *pModInstrument; // Currently assigned instrument slot
  56. SmpLength prevNoteOffset; // Offset for instrument-less notes for ProTracker/ScreamTracker
  57. SmpLength oldOffset; // Offset command memory
  58. FlagSet<ChannelFlags> dwOldFlags; // Flags from previous tick
  59. int32 newLeftVol, newRightVol;
  60. int32 nRealVolume, nRealPan;
  61. int32 nVolume, nPan, nFadeOutVol;
  62. int32 nPeriod; // Frequency in Hz if CSoundFile::PeriodsAreFrequencies() or using custom tuning, 4x Amiga periods otherwise
  63. int32 nC5Speed, nPortamentoDest;
  64. int32 cachedPeriod, glissandoPeriod;
  65. int32 nCalcVolume; // Calculated channel volume, 14-Bit (without global volume, pre-amp etc applied) - for MIDI macros
  66. EnvInfo VolEnv, PanEnv, PitchEnv; // Envelope playback info
  67. int32 nGlobalVol; // Channel volume (CV in ITTECH.TXT) 0...64
  68. int32 nInsVol; // Sample / Instrument volume (SV * IV in ITTECH.TXT) 0...64
  69. int32 nAutoVibDepth;
  70. uint32 nEFxOffset; // Offset memory for Invert Loop (EFx, .MOD only)
  71. ROWINDEX nPatternLoop;
  72. uint16 portamentoSlide;
  73. int16 nTranspose;
  74. int16 nFineTune;
  75. int16 microTuning; // Micro-tuning / MIDI pitch wheel command
  76. int16 nVolSwing, nPanSwing;
  77. int16 nCutSwing, nResSwing;
  78. uint16 nRestorePanOnNewNote; // If > 0, nPan should be set to nRestorePanOnNewNote - 1 on new note. Used to recover from pan swing and IT sample / instrument panning. High bit set = surround
  79. CHANNELINDEX nMasterChn;
  80. ModCommand rowCommand;
  81. // 8-bit members
  82. ResamplingMode resamplingMode;
  83. uint8 nRestoreResonanceOnNewNote; // See nRestorePanOnNewNote
  84. uint8 nRestoreCutoffOnNewNote; // ditto
  85. uint8 nNote;
  86. NewNoteAction nNNA;
  87. uint8 nLastNote; // Last note, ignoring note offs and cuts - for MIDI macros
  88. uint8 nArpeggioLastNote, nArpeggioBaseNote; // For plugin arpeggio
  89. uint8 nNewNote, nNewIns, nOldIns, nCommand, nArpeggio;
  90. uint8 nRetrigParam, nRetrigCount;
  91. uint8 nOldVolumeSlide, nOldFineVolUpDown;
  92. uint8 nOldPortaUp, nOldPortaDown, nOldFinePortaUpDown, nOldExtraFinePortaUpDown;
  93. uint8 nOldPanSlide, nOldChnVolSlide;
  94. uint8 nOldGlobalVolSlide;
  95. uint8 nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos;
  96. uint8 nVibratoType, nVibratoSpeed, nVibratoDepth;
  97. uint8 nTremoloType, nTremoloSpeed, nTremoloDepth;
  98. uint8 nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth;
  99. int8 nPanbrelloOffset, nPanbrelloRandomMemory;
  100. uint8 nOldCmdEx, nOldVolParam, nOldTempo;
  101. uint8 nOldHiOffset;
  102. uint8 nCutOff, nResonance;
  103. uint8 nTremorCount, nTremorParam;
  104. uint8 nPatternLoopCount;
  105. uint8 nLeftVU, nRightVU;
  106. uint8 nActiveMacro;
  107. FilterMode nFilterMode;
  108. uint8 nEFxSpeed, nEFxDelay; // memory for Invert Loop (EFx, .MOD only)
  109. uint8 noteSlideParam, noteSlideCounter; // IMF / PTM Note Slide
  110. uint8 lastZxxParam; // Memory for \xx slides
  111. bool isFirstTick : 1; // Execute tick-0 effects on this channel? (condition differs between formats due to Pattern Delay commands)
  112. bool triggerNote : 1; // Trigger note on this tick on this channel if there is one?
  113. bool isPreviewNote : 1; // Notes preview in editor
  114. bool isPaused : 1; // Don't mix or increment channel position, but keep the note alive
  115. bool portaTargetReached : 1; // Tone portamento is finished
  116. //-->Variables used to make user-definable tuning modes work with pattern effects.
  117. //If true, freq should be recalculated in ReadNote() on first tick.
  118. //Currently used only for vibrato things - using in other context might be
  119. //problematic.
  120. bool m_ReCalculateFreqOnFirstTick : 1;
  121. //To tell whether to calculate frequency.
  122. bool m_CalculateFreq : 1;
  123. int32 m_PortamentoFineSteps, m_PortamentoTickSlide;
  124. //NOTE_PCs memory.
  125. float m_plugParamValueStep, m_plugParamTargetValue;
  126. uint16 m_RowPlugParam;
  127. PLUGINDEX m_RowPlug;
  128. void ClearRowCmd() { rowCommand = ModCommand(); }
  129. // Get a reference to a specific envelope of this channel
  130. const EnvInfo &GetEnvelope(EnvelopeType envType) const
  131. {
  132. switch(envType)
  133. {
  134. case ENV_VOLUME:
  135. default:
  136. return VolEnv;
  137. case ENV_PANNING:
  138. return PanEnv;
  139. case ENV_PITCH:
  140. return PitchEnv;
  141. }
  142. }
  143. EnvInfo &GetEnvelope(EnvelopeType envType)
  144. {
  145. return const_cast<EnvInfo &>(static_cast<const ModChannel *>(this)->GetEnvelope(envType));
  146. }
  147. void ResetEnvelopes()
  148. {
  149. VolEnv.Reset();
  150. PanEnv.Reset();
  151. PitchEnv.Reset();
  152. }
  153. enum ResetFlags
  154. {
  155. resetChannelSettings = 1, // Reload initial channel settings
  156. resetSetPosBasic = 2, // Reset basic runtime channel attributes
  157. resetSetPosAdvanced = 4, // Reset more runtime channel attributes
  158. resetSetPosFull = resetSetPosBasic | resetSetPosAdvanced | resetChannelSettings, // Reset all runtime channel attributes
  159. resetTotal = resetSetPosFull,
  160. };
  161. void Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel, ChannelFlags muteFlag);
  162. void Stop();
  163. bool IsSamplePlaying() const noexcept { return !increment.IsZero(); }
  164. uint32 GetVSTVolume() const noexcept { return (pModInstrument) ? pModInstrument->nGlobalVol * 4 : nVolume; }
  165. ModCommand::NOTE GetPluginNote(bool realNoteMapping) const;
  166. // Check if the channel has a valid MIDI output. A return value of true implies that pModInstrument != nullptr.
  167. bool HasMIDIOutput() const noexcept { return pModInstrument != nullptr && pModInstrument->HasValidMIDIChannel(); }
  168. // Check if the channel uses custom tuning. A return value of true implies that pModInstrument != nullptr.
  169. bool HasCustomTuning() const noexcept { return pModInstrument != nullptr && pModInstrument->pTuning != nullptr; }
  170. // Check if currently processed loop is a sustain loop. pModSample is not checked for validity!
  171. bool InSustainLoop() const noexcept { return (dwFlags & (CHN_LOOP | CHN_KEYOFF)) == CHN_LOOP && pModSample->uFlags[CHN_SUSTAINLOOP]; }
  172. void UpdateInstrumentVolume(const ModSample *smp, const ModInstrument *ins);
  173. void SetInstrumentPan(int32 pan, const CSoundFile &sndFile);
  174. void RestorePanAndFilter();
  175. void RecalcTuningFreq(Tuning::RATIOTYPE vibratoFactor, Tuning::NOTEINDEXTYPE arpeggioSteps, const CSoundFile &sndFile);
  176. // IT command S73-S7E
  177. void InstrumentControl(uint8 param, const CSoundFile &sndFile);
  178. int32 GetMIDIPitchBend() const noexcept { return (static_cast<int32>(microTuning) + 0x8000) / 4; }
  179. };
  180. // Default pattern channel settings
  181. struct ModChannelSettings
  182. {
  183. #ifdef MODPLUG_TRACKER
  184. static constexpr uint32 INVALID_COLOR = 0xFFFFFFFF;
  185. uint32 color = INVALID_COLOR; // For pattern editor
  186. #endif // MODPLUG_TRACKER
  187. FlagSet<ChannelFlags> dwFlags; // Channel flags
  188. uint16 nPan = 128; // Initial pan (0...256)
  189. uint16 nVolume = 64; // Initial channel volume (0...64)
  190. PLUGINDEX nMixPlugin = 0; // Assigned plugin
  191. mpt::charbuf<MAX_CHANNELNAME> szName; // Channel name
  192. void Reset()
  193. {
  194. *this = {};
  195. }
  196. };
  197. OPENMPT_NAMESPACE_END