mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-10 06:51:54 +00:00
Prevent samples accidentally having their loops disabled (#1018)
If a SoundFont sets `loopstart == loopend` and then uses loop-offset-modulators to fix up those loops assigning them with a valid position, the sample was previously switched to unlooped mode erroneously. For the long story, see #1017.
This commit is contained in:
parent
b7a0264459
commit
e3d8b3f2c3
2 changed files with 40 additions and 10 deletions
|
@ -376,6 +376,7 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
|
|||
fluid_sample_t *sample;
|
||||
int sf3_file = (sfdata->version.major == 3);
|
||||
int sample_parsing_result = FLUID_OK;
|
||||
int invalid_loops_were_sanitized = FALSE;
|
||||
|
||||
/* For SF2 files, we load the sample data in one large block */
|
||||
if(!sf3_file)
|
||||
|
@ -404,7 +405,7 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
|
|||
{
|
||||
/* SF3 samples get loaded individually, as most (or all) of them are in Ogg Vorbis format
|
||||
* anyway */
|
||||
#pragma omp task firstprivate(sample,sfdata,defsfont) shared(sample_parsing_result) default(none)
|
||||
#pragma omp task firstprivate(sample,sfdata,defsfont) shared(sample_parsing_result, invalid_loops_were_sanitized) default(none)
|
||||
{
|
||||
if(fluid_defsfont_load_sampledata(defsfont, sfdata, sample) == FLUID_FAILED)
|
||||
{
|
||||
|
@ -416,24 +417,46 @@ int fluid_defsfont_load_all_sampledata(fluid_defsfont_t *defsfont, SFData *sfdat
|
|||
}
|
||||
else
|
||||
{
|
||||
fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
|
||||
int modified = fluid_sample_sanitize_loop(sample, (sample->end + 1) * sizeof(short));
|
||||
if(modified)
|
||||
{
|
||||
#pragma omp critical
|
||||
{
|
||||
invalid_loops_were_sanitized = TRUE;
|
||||
}
|
||||
}
|
||||
fluid_voice_optimize_sample(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma omp task firstprivate(sample, defsfont) default(none)
|
||||
#pragma omp task firstprivate(sample, defsfont) shared(invalid_loops_were_sanitized) default(none)
|
||||
{
|
||||
int modified;
|
||||
/* Data pointers of SF2 samples point to large sample data block loaded above */
|
||||
sample->data = defsfont->sampledata;
|
||||
sample->data24 = defsfont->sample24data;
|
||||
fluid_sample_sanitize_loop(sample, defsfont->samplesize);
|
||||
modified = fluid_sample_sanitize_loop(sample, defsfont->samplesize);
|
||||
if(modified)
|
||||
{
|
||||
#pragma omp critical
|
||||
{
|
||||
invalid_loops_were_sanitized = TRUE;
|
||||
}
|
||||
}
|
||||
fluid_voice_optimize_sample(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(invalid_loops_were_sanitized)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN,
|
||||
"Some invalid sample loops were sanitized! If you experience audible glitches, "
|
||||
"start fluidsynth in verbose mode for detailed information.");
|
||||
}
|
||||
|
||||
return sample_parsing_result;
|
||||
}
|
||||
|
||||
|
|
|
@ -789,12 +789,19 @@ int fluid_sample_sanitize_loop(fluid_sample_t *sample, unsigned int buffer_size)
|
|||
if(sample->loopstart == sample->loopend)
|
||||
{
|
||||
/* Some SoundFonts disable loops by setting loopstart = loopend. While
|
||||
* technically invalid, we decided to accept those samples anyway. Just
|
||||
* ensure that those two pointers are within the sampledata by setting
|
||||
* them to 0. Don't report the modification, as this change has no audible
|
||||
* effect. */
|
||||
sample->loopstart = sample->loopend = 0;
|
||||
return FALSE;
|
||||
* technically invalid, we decided to accept those samples anyway.
|
||||
* Before fluidsynth 2.2.5 we've set those indices to zero, as this
|
||||
* change was believed to be inaudible. This turned out to be an
|
||||
* incorrect assumption, as the loop points may still be modified by
|
||||
* loop offset modulators afterwards.
|
||||
*/
|
||||
if(sample->loopstart != sample->start)
|
||||
{
|
||||
// Many soundfonts set loopstart == loopend == sample->start to disabled to loop.
|
||||
// Only report cases where it's not equal to the sample->start, to avoid spam.
|
||||
FLUID_LOG(FLUID_DBG, "Sample '%s': zero length loop detected: loopstart == loopend == '%d', sample start '%d', using it anyway",
|
||||
sample->name, sample->loopstart, sample->start);
|
||||
}
|
||||
}
|
||||
else if(sample->loopstart > sample->loopend)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue