From: <sv...@op...> - 2024-12-01 11:57:02
|
Author: sagamusix Date: Sun Dec 1 12:56:55 2024 New Revision: 22394 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=22394 Log: Merged revision(s) 22170 from trunk/OpenMPT: [Fix] IT: Ignore sample data in slots that don't have the "sample data present" flag set, if the file vaguely looks IT-made. There's a bug in IT that sometimes doesn't reset the sample length after deleting a sample (presumably). For most files this does not make an audible difference, because such sample slots are typically unused, or the sample offset pointer points at the end of the file anyway. However, a small handful of files references these deleted samples in pattern data, so a lot of unwanted noise can be heard. See https://www.un4seen.com/forum/?topic=20542.0 for reference. ........ Modified: branches/OpenMPT-1.30/ (props changed) branches/OpenMPT-1.30/soundlib/ITTools.cpp branches/OpenMPT-1.30/soundlib/Load_it.cpp Modified: branches/OpenMPT-1.30/soundlib/ITTools.cpp ============================================================================== --- branches/OpenMPT-1.30/soundlib/ITTools.cpp Sun Dec 1 12:55:42 2024 (r22393) +++ branches/OpenMPT-1.30/soundlib/ITTools.cpp Sun Dec 1 12:56:55 2024 (r22394) @@ -530,10 +530,9 @@ // Convert an ITSample to OpenMPT's internal sample representation. uint32 ITSample::ConvertToMPT(ModSample &mptSmp) const { - if(memcmp(id, "IMPS", 4)) - { - return 0; - } + // IT does not check for the IMPS magic, and some bad XM->IT converter out there doesn't write the magic bytes for empty sample slots. + //if(memcmp(id, "IMPS", 4)) + // return 0; mptSmp.Initialize(MOD_TYPE_IT); mptSmp.SetDefaultCuePoints(); // For old IT/MPTM files Modified: branches/OpenMPT-1.30/soundlib/Load_it.cpp ============================================================================== --- branches/OpenMPT-1.30/soundlib/Load_it.cpp Sun Dec 1 12:55:42 2024 (r22393) +++ branches/OpenMPT-1.30/soundlib/Load_it.cpp Sun Dec 1 12:56:55 2024 (r22394) @@ -767,6 +767,19 @@ bool possibleXMconversion = false; + // There's a bug in IT somewhere that resets the "sample data present" flag in sample headers, but keeps the sample length + // of a previously deleted sample (presumably). + // As old ModPlug versions didn't set this flag under some circumstances (if a sample wasn't referenced by any instruments in instrument mode), + // and because there appear to be some external tools that forget to set this flag at all, we only respect the flag if the file + // vaguely looks like it was saved with IT. Some files that play garbage data if we don't do this: + // astral projection.it by Lord Jon Ray + // classic illusions.it by Blackstar + // deep in dance.it by Simply DJ + // There are many more such files but they don't reference the broken samples in their pattern data, or the sample data pointer + // points right to the end of the file, so in both cases no audible problem can be observed. + const bool muteBuggySamples = !interpretModPlugMade && fileHeader.cwtv >= 0x0100 && fileHeader.cwtv <= 0x0217 + && (fileHeader.cwtv < 0x0207 || fileHeader.reserved != 0); + // Reading Samples m_nSamples = std::min(static_cast<SAMPLEINDEX>(fileHeader.smpnum), static_cast<SAMPLEINDEX>(MAX_SAMPLES - 1)); bool lastSampleCompressed = false; @@ -775,9 +788,10 @@ ITSample sampleHeader; if(smpPos[i] > 0 && file.Seek(smpPos[i]) && file.ReadStruct(sampleHeader)) { - // IT does not check for the IMPS magic, and some bad XM->IT converter out there doesn't write the magic bytes for empty sample slots. ModSample &sample = Samples[i + 1]; size_t sampleOffset = sampleHeader.ConvertToMPT(sample); + if(muteBuggySamples && !(sampleHeader.flags & ITSample::sampleDataPresent)) + sample.nLength = 0; m_szNames[i + 1] = mpt::String::ReadBuf(mpt::String::spacePadded, sampleHeader.name); |