123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- #include "stdafx.h"
- #include "Sndfile.h"
- #include "ModInstrument.h"
- OPENMPT_NAMESPACE_BEGIN
- void InstrumentEnvelope::Convert(MODTYPE fromType, MODTYPE toType)
- {
- if(!(fromType & MOD_TYPE_XM) && (toType & MOD_TYPE_XM))
- {
-
- nSustainStart = nSustainEnd;
- dwFlags.reset(ENV_CARRY);
- if(nLoopEnd > nLoopStart && dwFlags[ENV_LOOP])
- {
- for(uint32 node = nLoopEnd; node < size(); node++)
- {
- at(node).tick++;
- }
- }
- } else if((fromType & MOD_TYPE_XM) && !(toType & MOD_TYPE_XM))
- {
- if(nSustainStart > nLoopEnd && dwFlags[ENV_LOOP])
- {
-
-
-
- dwFlags.reset(ENV_SUSTAIN);
- }
-
- if(nLoopEnd > nLoopStart && dwFlags[ENV_LOOP] && nLoopEnd < size())
- {
- if(at(nLoopEnd).tick - 1 > at(nLoopEnd - 1).tick)
- {
-
- EnvelopeNode::tick_t tick = at(nLoopEnd).tick - 1u;
- auto interpolatedValue = static_cast<EnvelopeNode::value_t>(GetValueFromPosition(tick, 64));
- insert(begin() + nLoopEnd, EnvelopeNode(tick, interpolatedValue));
- } else
- {
-
- nLoopEnd--;
- }
- }
- }
- if(toType != MOD_TYPE_MPT)
- {
- nReleaseNode = ENV_RELEASE_NODE_UNSET;
- }
- }
- int32 InstrumentEnvelope::GetValueFromPosition(int position, int32 rangeOut, int32 rangeIn) const
- {
- uint32 pt = size() - 1u;
- const int32 ENV_PRECISION = 1 << 16;
-
- for(uint32 i = 0; i < size() - 1u; i++)
- {
- if (position <= at(i).tick)
- {
- pt = i;
- break;
- }
- }
- int x2 = at(pt).tick;
- int32 value = 0;
- if(position >= x2)
- {
-
- value = at(pt).value * ENV_PRECISION / rangeIn;
- } else
- {
-
- int x1 = 0;
- if(pt)
- {
-
- value = at(pt - 1).value * ENV_PRECISION / rangeIn;
- x1 = at(pt - 1).tick;
- }
- if(x2 > x1 && position > x1)
- {
-
-
- value += Util::muldiv(position - x1, (at(pt).value * ENV_PRECISION / rangeIn - value), x2 - x1);
- }
- }
- Limit(value, int32(0), ENV_PRECISION);
- return (value * rangeOut + ENV_PRECISION / 2) / ENV_PRECISION;
- }
- void InstrumentEnvelope::Sanitize(uint8 maxValue)
- {
- if(!empty())
- {
- front().tick = 0;
- LimitMax(front().value, maxValue);
- for(iterator it = begin() + 1; it != end(); it++)
- {
- it->tick = std::max(it->tick, (it - 1)->tick);
- LimitMax(it->value, maxValue);
- }
- }
- LimitMax(nLoopEnd, static_cast<decltype(nLoopEnd)>(size() - 1));
- LimitMax(nLoopStart, nLoopEnd);
- LimitMax(nSustainEnd, static_cast<decltype(nSustainEnd)>(size() - 1));
- LimitMax(nSustainStart, nSustainEnd);
- if(nReleaseNode != ENV_RELEASE_NODE_UNSET)
- LimitMax(nReleaseNode, static_cast<decltype(nReleaseNode)>(size() - 1));
- }
- ModInstrument::ModInstrument(SAMPLEINDEX sample)
- {
- SetCutoff(0, false);
- SetResonance(0, false);
- pitchToTempoLock.Set(0);
- pTuning = CSoundFile::GetDefaultTuning();
- AssignSample(sample);
- ResetNoteMap();
- }
- void ModInstrument::Convert(MODTYPE fromType, MODTYPE toType)
- {
- MPT_UNREFERENCED_PARAMETER(fromType);
- if(toType & MOD_TYPE_XM)
- {
- ResetNoteMap();
- PitchEnv.dwFlags.reset(ENV_ENABLED | ENV_FILTER);
- dwFlags.reset(INS_SETPANNING);
- SetCutoff(GetCutoff(), false);
- SetResonance(GetResonance(), false);
- filterMode = FilterMode::Unchanged;
- nCutSwing = nPanSwing = nResSwing = nVolSwing = 0;
- nPPC = NOTE_MIDDLEC - 1;
- nPPS = 0;
- nNNA = NewNoteAction::NoteCut;
- nDCT = DuplicateCheckType::None;
- nDNA = DuplicateNoteAction::NoteCut;
- if(nMidiChannel == MidiMappedChannel)
- {
- nMidiChannel = MidiFirstChannel;
- }
-
- midiPWD = static_cast<int8>(std::abs(midiPWD));
- Limit(midiPWD, int8(0), int8(36));
- nGlobalVol = 64;
- nPan = 128;
- LimitMax(nFadeOut, 32767u);
- }
- VolEnv.Convert(fromType, toType);
- PanEnv.Convert(fromType, toType);
- PitchEnv.Convert(fromType, toType);
- if(fromType == MOD_TYPE_XM && (toType & (MOD_TYPE_IT | MOD_TYPE_MPT)))
- {
- if(!VolEnv.dwFlags[ENV_ENABLED])
- {
-
- VolEnv.resize(2);
- VolEnv[0].tick = 0;
- VolEnv[0].value = ENVELOPE_MAX;
- VolEnv[1].tick = 1;
- VolEnv[1].value = ENVELOPE_MIN;
- VolEnv.dwFlags.set(ENV_ENABLED | ENV_SUSTAIN);
- VolEnv.dwFlags.reset(ENV_LOOP);
- VolEnv.nSustainStart = VolEnv.nSustainEnd = 0;
- }
- }
-
- if(toType & MOD_TYPE_IT)
- {
- LimitMax(nFadeOut, 8192u);
- }
-
- if(!(toType & MOD_TYPE_MPT))
- {
- SetTuning(nullptr);
- pitchToTempoLock.Set(0);
- nCutSwing = nResSwing = 0;
- filterMode = FilterMode::Unchanged;
- nVolRampUp = 0;
- }
- }
- std::set<SAMPLEINDEX> ModInstrument::GetSamples() const
- {
- std::set<SAMPLEINDEX> referencedSamples;
- for(const auto sample : Keyboard)
- {
- if(sample)
- {
- referencedSamples.insert(sample);
- }
- }
- return referencedSamples;
- }
- void ModInstrument::GetSamples(std::vector<bool> &referencedSamples) const
- {
- for(const auto sample : Keyboard)
- {
- if(sample != 0 && sample < referencedSamples.size())
- {
- referencedSamples[sample] = true;
- }
- }
- }
- void ModInstrument::Sanitize(MODTYPE modType)
- {
- LimitMax(nFadeOut, 65536u);
- LimitMax(nGlobalVol, 64u);
- LimitMax(nPan, 256u);
- LimitMax(wMidiBank, uint16(16384));
- LimitMax(nMidiProgram, uint8(128));
- LimitMax(nMidiChannel, uint8(17));
- if(nNNA > NewNoteAction::NoteFade) nNNA = NewNoteAction::NoteCut;
- if(nDCT > DuplicateCheckType::Plugin) nDCT = DuplicateCheckType::None;
- if(nDNA > DuplicateNoteAction::NoteFade) nDNA = DuplicateNoteAction::NoteCut;
- LimitMax(nPanSwing, uint8(64));
- LimitMax(nVolSwing, uint8(100));
- Limit(nPPS, int8(-32), int8(32));
- LimitMax(nCutSwing, uint8(64));
- LimitMax(nResSwing, uint8(64));
-
- #ifdef MODPLUG_TRACKER
- MPT_UNREFERENCED_PARAMETER(modType);
- const uint8 range = ENVELOPE_MAX;
- #else
- const uint8 range = modType == MOD_TYPE_AMS ? uint8_max : ENVELOPE_MAX;
- #endif
- VolEnv.Sanitize();
- PanEnv.Sanitize();
- PitchEnv.Sanitize(range);
- for(size_t i = 0; i < std::size(NoteMap); i++)
- {
- if(NoteMap[i] < NOTE_MIN || NoteMap[i] > NOTE_MAX)
- NoteMap[i] = static_cast<uint8>(i + NOTE_MIN);
- }
- if(!Resampling::IsKnownMode(resampling))
- resampling = SRCMODE_DEFAULT;
- if(nMixPlug > MAX_MIXPLUGINS)
- nMixPlug = 0;
- }
- std::map<SAMPLEINDEX, int8> ModInstrument::CanConvertToDefaultNoteMap() const
- {
- std::map<SAMPLEINDEX, int8> transposeMap;
- for(size_t i = 0; i < std::size(NoteMap); i++)
- {
- if(Keyboard[i] == 0)
- continue;
- if(!NoteMap[i] || NoteMap[i] == (i + 1))
- continue;
- const int8 relativeNote = static_cast<int8>(NoteMap[i] - (i + NOTE_MIN));
- if(transposeMap.count(Keyboard[i]) && transposeMap[Keyboard[i]] != relativeNote)
- return {};
- transposeMap[Keyboard[i]] = relativeNote;
- }
- return transposeMap;
- }
- void ModInstrument::Transpose(int8 amount)
- {
- for(auto ¬e : NoteMap)
- {
- note = static_cast<uint8>(Clamp(note + amount, NOTE_MIN, NOTE_MAX));
- }
- }
- uint8 ModInstrument::GetMIDIChannel(const ModChannel &channel, CHANNELINDEX chn) const
- {
-
- if(nMidiChannel == MidiMappedChannel)
- return static_cast<uint8>((channel.nMasterChn ? (channel.nMasterChn - 1u) : chn) % 16u);
- else if(HasValidMIDIChannel())
- return (nMidiChannel - MidiFirstChannel) % 16u;
- else
- return 0;
- }
- OPENMPT_NAMESPACE_END
|