void ResetSamples(CSoundFile &sndFile, ResetFlag resetflag, SAMPLEINDEX minSample, SAMPLEINDEX maxSample) //------------------------------------------------------------------------------------------------------- { if(minSample == SAMPLEINDEX_INVALID) { minSample = 1; } if(maxSample == SAMPLEINDEX_INVALID) { maxSample = sndFile.GetNumSamples(); } Limit(minSample, SAMPLEINDEX(1), SAMPLEINDEX(MAX_SAMPLES - 1)); Limit(maxSample, SAMPLEINDEX(1), SAMPLEINDEX(MAX_SAMPLES - 1)); if(minSample > maxSample) { std::swap(minSample, maxSample); } for(SAMPLEINDEX i = minSample; i <= maxSample; i++) { ModSample &sample = sndFile.GetSample(i); switch(resetflag) { case SmpResetInit: strcpy(sndFile.m_szNames[i], ""); strcpy(sample.filename, ""); sample.nC5Speed = 8363; // note: break is left out intentionally. keep this order or c&p the stuff from below if you change anything! MPT_FALLTHROUGH; case SmpResetCompo: sample.nPan = 128; sample.nGlobalVol = 64; sample.nVolume = 256; sample.nVibDepth = 0; sample.nVibRate = 0; sample.nVibSweep = 0; sample.nVibType = 0; sample.uFlags.reset(CHN_PANNING); break; case SmpResetVibrato: sample.nVibDepth = 0; sample.nVibRate = 0; sample.nVibSweep = 0; sample.nVibType = 0; break; default: break; } } }
static void ReadDIGIPatternEntry(FileReader &file, ModCommand &m, CSoundFile &sndFile) //------------------------------------------------------------------------------------ { sndFile.ReadMODPatternEntry(file, m); sndFile.ConvertModCommand(m); if(m.command == CMD_MODCMDEX) { switch(m.param & 0xF0) { case 0x30: // E30 / E31: Play sample backwards (with some weird parameters that we won't support for now) if(m.param <= 0x31) { m.command = CMD_S3MCMDEX; m.param = 0x9F; } break; case 0x40: // E40: Stop playing sample if(m.param == 0x40) { m.note = NOTE_NOTECUT; m.command = CMD_NONE; } break; case 0x80: // E8x: High sample offset m.command = CMD_S3MCMDEX; m.param = 0xA0 | (m.param & 0x0F); } } else if(m.command == CMD_PANNING8) { // 8xx "Robot" effect (not supported) m.command = CMD_NONE; } }
Echo::Echo(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct) : IMixPlugin(factory, sndFile, mixStruct) , m_bufferSize(0) , m_writePos(0) , m_sampleRate(sndFile.GetSampleRate()) , m_initialFeedback(0.0f) { m_param[kEchoWetDry] = 0.5f; m_param[kEchoFeedback] = 0.5f; m_param[kEchoLeftDelay] = 0.25f; m_param[kEchoRightDelay] = 0.25f; m_param[kEchoPanDelay] = 0.0f; m_mixBuffer.Initialize(2, 2); InsertIntoFactoryList(); }
DMOPlugin::DMOPlugin(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct, IMediaObject *pMO, IMediaObjectInPlace *pMOIP, uint32 uid) : IMixPlugin(factory, sndFile, mixStruct) , m_pMediaObject(pMO) , m_pMediaProcess(pMOIP) , m_pParamInfo(nullptr) , m_pMediaParams(nullptr) , m_nSamplesPerSec(sndFile.GetSampleRate()) , m_uid(uid) //-------------------------------------------------------------------------------------------------------------------------------------------------- { if(FAILED(m_pMediaObject->QueryInterface(IID_IMediaParamInfo, (void **)&m_pParamInfo))) m_pParamInfo = nullptr; if (FAILED(m_pMediaObject->QueryInterface(IID_IMediaParams, (void **)&m_pMediaParams))) m_pMediaParams = nullptr; m_alignedBuffer.f32 = (float *)((((intptr_t)m_interleavedBuffer.f32) + 15) & ~15); m_mixBuffer.Initialize(2, 2); InsertIntoFactoryList(); }
OPENMPT_NAMESPACE_BEGIN void ModChannel::Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel) //------------------------------------------------------------------------------------------------- { 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); //IT compatibility 15. Retrigger if(sndFile.IsCompatibleMode(TRK_IMPULSETRACKER)) { nRetrigParam = 1; nRetrigCount = 0; } nTremorCount = 0; nEFxSpeed = 0; proTrackerOffset = 0; isFirstTick = false; } if(resetMask & resetSetPosAdvanced) { nPeriod = 0; nPos = 0; nPosLo = 0; nLength = 0; nLoopStart = 0; nLoopEnd = 0; nROfs = nLOfs = 0; pModSample = nullptr; pModInstrument = nullptr; nCutOff = 0x7F; nResonance = 0; nFilterMode = 0; rightVol = leftVol = 0; newRightVol = newLeftVol = 0; rightRamp = leftRamp = 0; nVolume = 256; nVibratoPos = nTremoloPos = nPanbrelloPos = 0; nOldHiOffset = 0; //-->Custom tuning related m_ReCalculateFreqOnFirstTick = false; m_CalculateFreq = false; m_PortamentoFineSteps = 0; m_PortamentoTickSlide = 0; m_Freq = 0; m_VibratoDepth = 0; //<--Custom tuning related. } if(resetMask & resetChannelSettings) { if(sourceChannel < MAX_BASECHANNELS) { dwFlags = sndFile.ChnSettings[sourceChannel].dwFlags; nPan = sndFile.ChnSettings[sourceChannel].nPan; nGlobalVol = sndFile.ChnSettings[sourceChannel].nVolume; } else { dwFlags.reset(); nPan = 128; nGlobalVol = 64; } nRestorePanOnNewNote = 0; nRestoreCutoffOnNewNote = 0; nRestoreResonanceOnNewNote = 0; } }
// Read AMS or AMS2 (newVersion = true) pattern. At least this part of the format is more or less identical between the two trackers... static void ReadAMSPattern(CPattern &pattern, bool newVersion, FileReader &patternChunk, CSoundFile &sndFile) //----------------------------------------------------------------------------------------------------------- { enum { emptyRow = 0xFF, // No commands on row endOfRowMask = 0x80, // If set, no more commands on this row noteMask = 0x40, // If set, no note+instr in this command channelMask = 0x1F, // Mask for extracting channel // Note flags readNextCmd = 0x80, // One more command follows noteDataMask = 0x7F, // Extract note // Command flags volCommand = 0x40, // Effect is compressed volume command commandMask = 0x3F, // Command or volume mask }; // Effect translation table for extended (non-Protracker) effects static const ModCommand::COMMAND effTrans[] = { CMD_S3MCMDEX, // Forward / Backward CMD_PORTAMENTOUP, // Extra fine slide up CMD_PORTAMENTODOWN, // Extra fine slide up CMD_RETRIG, // Retrigger CMD_NONE, CMD_TONEPORTAVOL, // Toneporta with fine volume slide CMD_VIBRATOVOL, // Vibrato with fine volume slide CMD_NONE, CMD_PANNINGSLIDE, CMD_NONE, CMD_VOLUMESLIDE, // Two times finder volume slide than Axx CMD_NONE, CMD_CHANNELVOLUME, // Channel volume (0...127) CMD_PATTERNBREAK, // Long pattern break (in hex) CMD_S3MCMDEX, // Fine slide commands CMD_NONE, // Fractional BPM CMD_KEYOFF, // Key off at tick xx CMD_PORTAMENTOUP, // Porta up, but uses all octaves (?) CMD_PORTAMENTODOWN, // Porta down, but uses all octaves (?) CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_NONE, CMD_GLOBALVOLSLIDE, // Global volume slide CMD_NONE, CMD_GLOBALVOLUME, // Global volume (0... 127) }; static ModCommand dummy; for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++) { PatternRow baseRow = pattern.GetRow(row); while(patternChunk.AreBytesLeft()) { const uint8 flags = patternChunk.ReadUint8(); if(flags == emptyRow) { break; } const CHANNELINDEX chn = (flags & channelMask); ModCommand &m = chn < pattern.GetNumChannels() ? baseRow[chn] : dummy; bool moreCommands = true; if(!(flags & noteMask)) { // Read note + instr uint8 note = patternChunk.ReadUint8(); moreCommands = (note & readNextCmd) != 0; note &= noteDataMask; if(note == 1) { m.note = NOTE_KEYOFF; } else if(note >= 2 && note <= 121 && newVersion) { m.note = note - 2 + NOTE_MIN; } else if(note >= 12 && note <= 108 && !newVersion) { m.note = note + 12 + NOTE_MIN; } m.instr = patternChunk.ReadUint8(); } while(moreCommands) { // Read one more effect command ModCommand origCmd = m; const uint8 command = patternChunk.ReadUint8(), effect = (command & commandMask); moreCommands = (command & readNextCmd) != 0; if(command & volCommand) { m.volcmd = VOLCMD_VOLUME; m.vol = effect; } else { m.param = patternChunk.ReadUint8(); if(effect < 0x10) { // PT commands m.command = effect; sndFile.ConvertModCommand(m); // Post-fix some commands switch(m.command) { case CMD_PANNING8: // 4-Bit panning m.command = CMD_PANNING8; m.param = (m.param & 0x0F) * 0x11; break; case CMD_VOLUME: m.command = CMD_NONE; m.volcmd = VOLCMD_VOLUME; m.vol = static_cast<ModCommand::VOL>(std::min((m.param + 1) / 2, 64)); break; case CMD_MODCMDEX: if(m.param == 0x80) { // Break sample loop (cut after loop) m.command = CMD_NONE; } else { m.ExtendedMODtoS3MEffect(); } break; } } else if(effect - 0x10 < (int)CountOf(effTrans)) { // Extended commands m.command = effTrans[effect - 0x10]; // Post-fix some commands switch(effect) { case 0x10: // Play sample forwards / backwards if(m.param <= 0x01) { m.param |= 0x9E; } else { m.command = CMD_NONE; } break; case 0x11: case 0x12: // Extra fine slides m.param = static_cast<ModCommand::PARAM>(std::min(uint8(0x0F), m.param) | 0xE0); break; case 0x15: case 0x16: // Fine slides m.param = static_cast<ModCommand::PARAM>((std::min(0x10, m.param + 1) / 2) | 0xF0); break; case 0x1E: // More fine slides switch(m.param >> 4) { case 0x1: // Fine porta up m.command = CMD_PORTAMENTOUP; m.param |= 0xF0; break; case 0x2: // Fine porta down m.command = CMD_PORTAMENTODOWN; m.param |= 0xF0; break; case 0xA: // Extra fine volume slide up m.command = CMD_VOLUMESLIDE; m.param = ((((m.param & 0x0F) + 1) / 2) << 4) | 0x0F; break; case 0xB: // Extra fine volume slide down m.command = CMD_VOLUMESLIDE; m.param = (((m.param & 0x0F) + 1) / 2) | 0xF0; break; default: m.command = CMD_NONE; break; } break; case 0x1C: // Adjust channel volume range m.param = static_cast<ModCommand::PARAM>(std::min((m.param + 1) / 2, 64)); break; } } // Try merging commands first ModCommand::CombineEffects(m.command, m.param, origCmd.command, origCmd.param); if(ModCommand::GetEffectWeight(origCmd.command) > ModCommand::GetEffectWeight(m.command)) { if(m.volcmd == VOLCMD_NONE && ModCommand::ConvertVolEffect(m.command, m.param, true)) { // Volume column to the rescue! m.volcmd = m.command; m.vol = m.param; } m.command = origCmd.command; m.param = origCmd.param; } } } if(flags & endOfRowMask) { // End of row break; } } }
static void ReadTuningMap(std::istream& iStrm, CSoundFile& csf, const size_t = 0) //------------------------------------------------------------------------------- { typedef std::map<WORD, std::string> MAP; typedef MAP::iterator MAP_ITER; MAP shortToTNameMap; ReadTuningMapTemplate<uint16, uint8>(iStrm, shortToTNameMap); //Read & set tunings for instruments std::list<std::string> notFoundTunings; for(UINT i = 1; i<=csf.GetNumInstruments(); i++) { uint16 ui; iStrm.read(reinterpret_cast<char*>(&ui), sizeof(ui)); MAP_ITER iter = shortToTNameMap.find(ui); if(csf.Instruments[i] && iter != shortToTNameMap.end()) { const std::string str = iter->second; if(str == std::string("->MPT_ORIGINAL_IT<-")) { csf.Instruments[i]->pTuning = nullptr; continue; } csf.Instruments[i]->pTuning = csf.GetTuneSpecificTunings().GetTuning(str); if(csf.Instruments[i]->pTuning) continue; #ifdef MODPLUG_TRACKER csf.Instruments[i]->pTuning = csf.GetLocalTunings().GetTuning(str); if(csf.Instruments[i]->pTuning) continue; #endif csf.Instruments[i]->pTuning = csf.GetBuiltInTunings().GetTuning(str); if(csf.Instruments[i]->pTuning) continue; if(str == "TET12" && csf.GetBuiltInTunings().GetNumTunings() > 0) csf.Instruments[i]->pTuning = &csf.GetBuiltInTunings().GetTuning(0); if(csf.Instruments[i]->pTuning) continue; //Checking if not found tuning already noticed. std::list<std::string>::iterator iter; iter = find(notFoundTunings.begin(), notFoundTunings.end(), str); if(iter == notFoundTunings.end()) { notFoundTunings.push_back(str); std::string erm = std::string("Tuning ") + str + std::string(" used by the module was not found."); csf.AddToLog(erm); #ifdef MODPLUG_TRACKER if(csf.GetpModDoc() != nullptr) { csf.GetpModDoc()->SetModified(); //The tuning is changed so the modified flag is set. } #endif // MODPLUG_TRACKER } csf.Instruments[i]->pTuning = csf.GetDefaultTuning(); } else //This 'else' happens probably only in case of corrupted file. { if(csf.Instruments[i]) csf.Instruments[i]->pTuning = csf.GetDefaultTuning(); } } //End read&set instrument tunings }