Skip to content

Search a missing sample from the nearest folder level outwards - #338

Open
douglas-carmichael wants to merge 1 commit into
git-moss:mainfrom
douglas-carmichael:fix-sample-search-nearest
Open

Search a missing sample from the nearest folder level outwards#338
douglas-carmichael wants to merge 1 commit into
git-moss:mainfrom
douglas-carmichael:fix-sample-search-nearest

Conversation

@douglas-carmichael

Copy link
Copy Markdown
Contributor

When a sample is not found next to its preset, AbstractDetector.findLocalFile goes up the configured number of folder levels and searches from there. It jumps all the levels up in one go and then returns whatever the recursive walk finds first:

File startDirectory = folder;
for (int i = 0; i < levels; i++)
{
    final File dir = startDirectory.getParentFile ();
    if (dir.exists () && dir.isDirectory ())
        startDirectory = dir;
}
final Optional<File> found = findFileRecursively (startDirectory, sampleFile.getName ());

So the distance of a match never enters into it. If two libraries sit below that folder and use the same sample names - the norm for the variants of a library - a preset can be handed the sample of the other library, even though its own copy lies one level away.

That is not only the wrong sound. The preset keeps its own loop points, so the loop then wraps at the wrong place inside a differently long sample.

How it turned up. Two Ensoniq libraries in one download folder, both containing a RHODES C3 FF.wav:

DSF_Ensoniq_MR_EXS24/SoundFont Samples/Ensoniq MR Bank 0.Samples/RHODES C3 FF.wav   42384 Hz  5280 frames
DSF_Ensoniq_ZR_EXS24/SoundFont Samples/Ensoniq ZR Bank 0.Samples/RHODES C3 FF.wav   44100 Hz  5469 frames

An MR preset was given the ZR file. Its loop, correct for 5280 frames, was applied to 5469 frames and stepped 94% of the sample peak at every wrap - an audible click roughly once a second on a held note. Measuring the same library at both settings: with the search height one level lower the correct sample is used and the same loop steps 0.4%.

Across the three libraries, 59 zones in 33 presets were given a sample from a neighbouring library this way.

The fix walks up one level at a time and stops at the first level which contains the file, so a nearby sample always wins:

  • Behaviour is unchanged whenever only one file of that name exists - the same file is found, only sooner.
  • A search which finds nothing walks the same top folder as before, so the worst case does not get slower.
  • It also removes an NPE risk: getParentFile () returns null at the filesystem root and the old code dereferenced it straight away.

Verified against the case above. Before, search heights 4 and higher picked the wrong library's sample; after, heights 3, 4 and 6 all resolve to the preset's own copy, and the three affected loops drop from 94.1%, 24.1% and 24.1% of peak to 0.4%, 0.7% and 0.7%.

When a sample is not found next to its preset, the search goes up the
configured number of folder levels and looks for it there. It jumped all
levels up in one go and returned whatever the recursive search happened
to find first. If two libraries sit below that folder and name their
samples alike - which is the norm for the variants of a library - a
preset gets the sample of the other library. It sounds wrong, and since
the preset keeps its own loop points, the loop then wraps at the wrong
place in a differently long sample and clicks.

Found with two Ensoniq libraries below one download folder: both contain
a 'RHODES C3 FF.wav', 42384 Hz/5280 frames in the one and 44100 Hz/5469
frames in the other. A preset of the first library was given the sample
of the second, and its loop - correct for 5280 frames - stepped 94% of
the sample peak on every wrap.

The search now goes up one level at a time and stops at the first level
which contains the file, so a sample which lies close to the preset
always wins over one of the same name further away. A search which finds
nothing costs the same walk as before.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant