|
From: <man...@us...> - 2015-06-19 19:08:02
|
Revision: 5347
http://sourceforge.net/p/modplug/code/5347
Author: manxorist
Date: 2015-06-19 19:07:56 +0000 (Fri, 19 Jun 2015)
Log Message:
-----------
[Fix] When loading the sample in ReadSampleAsInstrument ultimately failed, the old instrument had been destroyed and cleared already and no failure code was returned after that. Properly handle this error case and avoid clearing the old instrument unless we successfully loaded the new sample.
[Ref] Add an optional keepSample (default SAMPLEINDEX_INVALID) parameter to RemoveInstrumentSamples which is used in ReadSampleAsInstrument in order to avoid removing the just loaded sample, as the sample index returned from GetNextFreeSample may point to a sample index used by the old instrument. Deleting has to be done after loading the new sample in order to be able to bail out without destroying old data in the case when sample loading fails.
[Ref] Checking actual file magic of all known sample formats in ReadSampleAsInstrument makes it infeasable to delegate reading sample formats to any multi-format third-party library that does its own internal format detection. Do not duplicate our known sample format file magic checks in ReadSampleAsInstrument. In order to avoid trying to read actual instrument formats again as a sample (in case parsing as an instrument already had failed), add an explicit parameter to ReadSampleFromFile which tells it to skip instrument formats.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/SampleFormats.cpp
trunk/OpenMPT/soundlib/Sndfile.h
Modified: trunk/OpenMPT/soundlib/SampleFormats.cpp
===================================================================
--- trunk/OpenMPT/soundlib/SampleFormats.cpp 2015-06-19 18:43:50 UTC (rev 5346)
+++ trunk/OpenMPT/soundlib/SampleFormats.cpp 2015-06-19 19:07:56 UTC (rev 5347)
@@ -76,16 +76,16 @@
#endif // NO_MP3_SAMPLES
-bool CSoundFile::ReadSampleFromFile(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize)
-//-------------------------------------------------------------------------------------------
+bool CSoundFile::ReadSampleFromFile(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize, bool includeInstrumentFormats)
+//--------------------------------------------------------------------------------------------------------------------------
{
if(!nSample || nSample >= MAX_SAMPLES) return false;
if(!ReadWAVSample(nSample, file, mayNormalize)
- && !ReadXISample(nSample, file)
- && !ReadITISample(nSample, file)
+ && !(includeInstrumentFormats && ReadXISample(nSample, file))
+ && !(includeInstrumentFormats && ReadITISample(nSample, file))
&& !ReadAIFFSample(nSample, file, mayNormalize)
&& !ReadITSSample(nSample, file)
- && !ReadPATSample(nSample, file)
+ && !(includeInstrumentFormats && ReadPATSample(nSample, file))
&& !ReadIFFSample(nSample, file)
&& !ReadS3ISample(nSample, file)
&& !ReadFLACSample(nSample, file)
@@ -131,56 +131,37 @@
bool CSoundFile::ReadSampleAsInstrument(INSTRUMENTINDEX nInstr, FileReader &file, bool mayNormalize)
//--------------------------------------------------------------------------------------------------
{
- file.Rewind();
+ // Scanning free sample
+ SAMPLEINDEX nSample = GetNextFreeSample(nInstr); // may also return samples which are only referenced by the current instrument
+ if(nSample == SAMPLEINDEX_INVALID)
+ {
+ return false;
+ }
- if(!file.CanRead(80))
+ // Loading Instrument
+ ModInstrument *pIns = new (std::nothrow) ModInstrument(nSample);
+ if(pIns == nullptr)
+ {
return false;
- char psig[80];
- file.ReadArray(psig);
- file.SkipBack(80);
- if( (!memcmp(&psig[0], "RIFF", 4) && !memcmp(&psig[8], "WAVE", 4)) // RIFF....WAVE signature
- || (!memcmp(&psig[0], "LIST", 4) && !memcmp(&psig[8], "wave", 4)) // LIST....wave
- || !memcmp(&psig[76], "SCRS", 4) // S3I signature
- || (!memcmp(&psig[0], "FORM", 4) &&
- (!memcmp(&psig[8], "AIFF", 4) // AIFF signature
- || !memcmp(&psig[8], "AIFC", 4) // AIFF-C signature
- || !memcmp(&psig[8], "8SVX", 4))) // 8SVX signature
- || !memcmp(&psig[0], "IMPS", 4) // ITS signature
-#ifndef NO_FLAC
- || !memcmp(&psig[0], "fLaC", 4) // FLAC signature
- || (!memcmp(&psig[0], "OggS", 4) && !memcmp(&psig[29], "FLAC", 4)) // FLAC in OGG signature
-#endif // NO_FLAC
-#ifndef NO_MP3_SAMPLES
- || IsMPEG(file) // MPEG signature
- || IsID3(file) // MP3 signature
-#endif // NO_MP3_SAMPLES
- )
+ }
+ if(!ReadSampleFromFile(nSample, file, mayNormalize, false))
{
- // Scanning free sample
- SAMPLEINDEX nSample = GetNextFreeSample(nInstr);
- if(nSample == SAMPLEINDEX_INVALID)
- {
- return false;
- }
-
- // Loading Instrument
+ delete pIns;
+ return false;
+ }
- ModInstrument *pIns = new (std::nothrow) ModInstrument(nSample);
- if(pIns == nullptr)
- {
- return false;
- }
-
- DestroyInstrument(nInstr, deleteAssociatedSamples);
- Instruments[nInstr] = pIns;
+ // Remove all samples which are only referenced by the old instrument, except for the one we just loaded our new sample into.
+ RemoveInstrumentSamples(nInstr, nSample);
- ReadSampleFromFile(nSample, file, mayNormalize);
+ // Replace the instrument
+ DestroyInstrument(nInstr, doNoDeleteAssociatedSamples);
+ Instruments[nInstr] = pIns;
+
#if defined(MPT_WITH_FILEIO) && defined(MPT_EXTERNAL_SAMPLES)
- SetSamplePath(nSample, file.GetFileName());
+ SetSamplePath(nSample, file.GetFileName());
#endif
- return true;
- }
- return false;
+
+ return true;
}
@@ -210,9 +191,9 @@
}
-// Removing all unused samples
-bool CSoundFile::RemoveInstrumentSamples(INSTRUMENTINDEX nInstr)
-//--------------------------------------------------------------
+// Remove all unused samples from the given nInstr and keep keepSample if provided
+bool CSoundFile::RemoveInstrumentSamples(INSTRUMENTINDEX nInstr, SAMPLEINDEX keepSample)
+//--------------------------------------------------------------------------------------
{
if(Instruments[nInstr] == nullptr)
{
@@ -226,9 +207,20 @@
for(std::set<SAMPLEINDEX>::const_iterator sample = referencedSamples.begin(); sample != referencedSamples.end(); sample++)
{
if((*sample) <= GetNumSamples())
+ {
keepSamples[*sample] = false;
+ }
}
+ // If we want to keep a specific sample, do so.
+ if(keepSample != SAMPLEINDEX_INVALID)
+ {
+ if(keepSample <= GetNumSamples())
+ {
+ keepSamples[keepSample] = true;
+ }
+ }
+
// Check if any of those samples are referenced by other instruments as well, in which case we want to keep them of course.
for(INSTRUMENTINDEX nIns = 1; nIns <= GetNumInstruments(); nIns++) if (Instruments[nIns] != nullptr && nIns != nInstr)
{
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2015-06-19 18:43:50 UTC (rev 5346)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2015-06-19 19:07:56 UTC (rev 5347)
@@ -894,12 +894,12 @@
bool DestroyInstrument(INSTRUMENTINDEX nInstr, deleteInstrumentSamples removeSamples);
bool IsSampleUsed(SAMPLEINDEX nSample) const;
bool IsInstrumentUsed(INSTRUMENTINDEX nInstr) const;
- bool RemoveInstrumentSamples(INSTRUMENTINDEX nInstr);
+ bool RemoveInstrumentSamples(INSTRUMENTINDEX nInstr, SAMPLEINDEX keepSample = SAMPLEINDEX_INVALID);
SAMPLEINDEX DetectUnusedSamples(std::vector<bool> &sampleUsed) const;
SAMPLEINDEX RemoveSelectedSamples(const std::vector<bool> &keepSamples);
// Samples file I/O
- bool ReadSampleFromFile(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize=false);
+ bool ReadSampleFromFile(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize=false, bool includeInstrumentFormats=true);
bool ReadWAVSample(SAMPLEINDEX nSample, FileReader &file, bool mayNormalize=false, FileReader *wsmpChunk = nullptr);
bool ReadPATSample(SAMPLEINDEX nSample, FileReader &file);
bool ReadS3ISample(SAMPLEINDEX nSample, FileReader &file);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|