aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp b/Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp
new file mode 100644
index 00000000..4d6550a4
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/soundlib/ModChannel.cpp
@@ -0,0 +1,222 @@
+/*
+ * ModChannel.cpp
+ * --------------
+ * Purpose: Module Channel 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.
+ */
+
+
+#include "stdafx.h"
+#include "Sndfile.h"
+#include "ModChannel.h"
+#include "tuning.h"
+
+OPENMPT_NAMESPACE_BEGIN
+
+void ModChannel::Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel, ChannelFlags muteFlag)
+{
+ if(resetMask & resetSetPosBasic)
+ {
+ nNote = nNewNote = NOTE_NONE;
+ nNewIns = nOldIns = 0;
+ pModSample = nullptr;
+ pModInstrument = nullptr;
+ nPortamentoDest = 0;
+ nCommand = CMD_NONE;
+ nPatternLoopCount = 0;
+ nPatternLoop = 0;
+ nFadeOutVol = 0;
+ dwFlags.set(CHN_KEYOFF | CHN_NOTEFADE);
+ dwOldFlags.reset();
+ //IT compatibility 15. Retrigger
+ if(sndFile.m_playBehaviour[kITRetrigger])
+ {
+ nRetrigParam = 1;
+ nRetrigCount = 0;
+ }
+ microTuning = 0;
+ nTremorCount = 0;
+ nEFxSpeed = 0;
+ prevNoteOffset = 0;
+ lastZxxParam = 0xFF;
+ isFirstTick = false;
+ triggerNote = false;
+ isPreviewNote = false;
+ isPaused = false;
+ portaTargetReached = false;
+ rowCommand.Clear();
+ }
+
+ if(resetMask & resetSetPosAdvanced)
+ {
+ increment = SamplePosition(0);
+ nPeriod = 0;
+ position.Set(0);
+ nLength = 0;
+ nLoopStart = 0;
+ nLoopEnd = 0;
+ nROfs = nLOfs = 0;
+ pModSample = nullptr;
+ pModInstrument = nullptr;
+ nCutOff = 0x7F;
+ nResonance = 0;
+ nFilterMode = FilterMode::LowPass;
+ rightVol = leftVol = 0;
+ newRightVol = newLeftVol = 0;
+ rightRamp = leftRamp = 0;
+ nVolume = 0; // Needs to be 0 for SMP_NODEFAULTVOLUME flag
+ nVibratoPos = nTremoloPos = nPanbrelloPos = 0;
+ nOldHiOffset = 0;
+ nLeftVU = nRightVU = 0;
+
+ // Custom tuning related
+ m_ReCalculateFreqOnFirstTick = false;
+ m_CalculateFreq = false;
+ m_PortamentoFineSteps = 0;
+ m_PortamentoTickSlide = 0;
+ }
+
+ if(resetMask & resetChannelSettings)
+ {
+ if(sourceChannel < MAX_BASECHANNELS)
+ {
+ dwFlags = sndFile.ChnSettings[sourceChannel].dwFlags;
+ nPan = sndFile.ChnSettings[sourceChannel].nPan;
+ nGlobalVol = sndFile.ChnSettings[sourceChannel].nVolume;
+ if(dwFlags[CHN_MUTE])
+ {
+ dwFlags.reset(CHN_MUTE);
+ dwFlags.set(muteFlag);
+ }
+ } else
+ {
+ dwFlags.reset();
+ nPan = 128;
+ nGlobalVol = 64;
+ }
+ nRestorePanOnNewNote = 0;
+ nRestoreCutoffOnNewNote = 0;
+ nRestoreResonanceOnNewNote = 0;
+ }
+}
+
+
+void ModChannel::Stop()
+{
+ nPeriod = 0;
+ increment.Set(0);
+ position.Set(0);
+ nLeftVU = nRightVU = 0;
+ nVolume = 0;
+ pCurrentSample = nullptr;
+}
+
+
+void ModChannel::UpdateInstrumentVolume(const ModSample *smp, const ModInstrument *ins)
+{
+ nInsVol = 64;
+ if(smp != nullptr)
+ nInsVol = smp->nGlobalVol;
+ if(ins != nullptr)
+ nInsVol = (nInsVol * ins->nGlobalVol) / 64;
+}
+
+
+ModCommand::NOTE ModChannel::GetPluginNote(bool realNoteMapping) const
+{
+ if(nArpeggioLastNote != NOTE_NONE)
+ {
+ // If an arpeggio is playing, this definitely the last playing note, which may be different from the arpeggio base note stored in nNote.
+ return nArpeggioLastNote;
+ }
+ ModCommand::NOTE plugNote = mpt::saturate_cast<ModCommand::NOTE>(nNote - nTranspose);
+ // Caution: When in compatible mode, ModChannel::nNote stores the "real" note, not the mapped note!
+ if(realNoteMapping && pModInstrument != nullptr && plugNote >= NOTE_MIN && plugNote < (std::size(pModInstrument->NoteMap) + NOTE_MIN))
+ {
+ plugNote = pModInstrument->NoteMap[plugNote - NOTE_MIN];
+ }
+ return plugNote;
+}
+
+
+void ModChannel::SetInstrumentPan(int32 pan, const CSoundFile &sndFile)
+{
+ // IT compatibility: Instrument and sample panning does not override channel panning
+ // Test case: PanResetInstr.it
+ if(sndFile.m_playBehaviour[kITDoNotOverrideChannelPan])
+ {
+ nRestorePanOnNewNote = static_cast<uint16>(nPan + 1);
+ if(dwFlags[CHN_SURROUND])
+ nRestorePanOnNewNote |= 0x8000;
+ }
+ nPan = pan;
+}
+
+
+void ModChannel::RestorePanAndFilter()
+{
+ if(nRestorePanOnNewNote > 0)
+ {
+ nPan = (nRestorePanOnNewNote & 0x7FFF) - 1;
+ if(nRestorePanOnNewNote & 0x8000)
+ dwFlags.set(CHN_SURROUND);
+ nRestorePanOnNewNote = 0;
+ }
+ if(nRestoreResonanceOnNewNote > 0)
+ {
+ nResonance = nRestoreResonanceOnNewNote - 1;
+ nRestoreResonanceOnNewNote = 0;
+ }
+ if(nRestoreCutoffOnNewNote > 0)
+ {
+ nCutOff = nRestoreCutoffOnNewNote - 1;
+ nRestoreCutoffOnNewNote = 0;
+ }
+}
+
+
+void ModChannel::RecalcTuningFreq(Tuning::RATIOTYPE vibratoFactor, Tuning::NOTEINDEXTYPE arpeggioSteps, const CSoundFile &sndFile)
+{
+ if(!HasCustomTuning())
+ return;
+
+ ModCommand::NOTE note = ModCommand::IsNote(nNote) ? nNote : nLastNote;
+
+ if(sndFile.m_playBehaviour[kITRealNoteMapping] && note >= NOTE_MIN && note <= NOTE_MAX)
+ note = pModInstrument->NoteMap[note - NOTE_MIN];
+
+ nPeriod = mpt::saturate_round<uint32>(nC5Speed * vibratoFactor * pModInstrument->pTuning->GetRatio(note - NOTE_MIDDLEC + arpeggioSteps, nFineTune + m_PortamentoFineSteps) * (1 << FREQ_FRACBITS));
+}
+
+
+// IT command S73-S7E
+void ModChannel::InstrumentControl(uint8 param, const CSoundFile &sndFile)
+{
+ param &= 0x0F;
+ switch(param)
+ {
+ case 0x3: nNNA = NewNoteAction::NoteCut; break;
+ case 0x4: nNNA = NewNoteAction::Continue; break;
+ case 0x5: nNNA = NewNoteAction::NoteOff; break;
+ case 0x6: nNNA = NewNoteAction::NoteFade; break;
+ case 0x7: VolEnv.flags.reset(ENV_ENABLED); break;
+ case 0x8: VolEnv.flags.set(ENV_ENABLED); break;
+ case 0x9: PanEnv.flags.reset(ENV_ENABLED); break;
+ case 0xA: PanEnv.flags.set(ENV_ENABLED); break;
+ case 0xB: PitchEnv.flags.reset(ENV_ENABLED); break;
+ case 0xC: PitchEnv.flags.set(ENV_ENABLED); break;
+ case 0xD: // S7D: Enable pitch envelope, force to play as pitch envelope
+ case 0xE: // S7E: Enable pitch envelope, force to play as filter envelope
+ if(sndFile.GetType() == MOD_TYPE_MPT)
+ {
+ PitchEnv.flags.set(ENV_ENABLED);
+ PitchEnv.flags.set(ENV_FILTER, param != 0xD);
+ }
+ break;
+ }
+}
+
+
+OPENMPT_NAMESPACE_END