Skip to content

Commit

Permalink
Resolve playback issues for Soundfonts not using zero padding samples (
Browse files Browse the repository at this point in the history
…#1487)

Soundfonts that do not have at least 46 zero-samples at the end of each sample may not sound correctly when `synth.dynamic-sample-loading` is active.

* Add debug output about discovered samples
* Add test cases for dynamic-sample loading
* Do not advance sample endpoint
  • Loading branch information
derselbst authored Feb 15, 2025
1 parent 698c659 commit 1e82bd6
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 18 deletions.
20 changes: 3 additions & 17 deletions src/sfloader/fluid_defsfont.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,25 +317,9 @@ const char *fluid_defsfont_get_name(fluid_defsfont_t *defsfont)
int fluid_defsfont_load_sampledata(fluid_defsfont_t *defsfont, SFData *sfdata, fluid_sample_t *sample)
{
int num_samples;
unsigned int source_end = sample->source_end;

/* For uncompressed samples we want to include the 46 zero sample word area following each sample
* in the Soundfont. Otherwise samples with loopend > end, which we have decided not to correct, would
* be corrected after all in fluid_sample_sanitize_loop */
if(!(sample->sampletype & FLUID_SAMPLETYPE_OGG_VORBIS))
{
source_end += 46; /* Length of zero sample word after each sample, according to SF specs */

/* Safeguard against Soundfonts that are not quite valid and don't include 46 sample words after the
* last sample */
if(source_end >= (defsfont->samplesize / sizeof(short)))
{
source_end = defsfont->samplesize / sizeof(short);
}
}

num_samples = fluid_samplecache_load(
sfdata, sample->source_start, source_end, sample->sampletype,
sfdata, sample->source_start, sample->source_end, sample->sampletype,
defsfont->mlock, &sample->data, &sample->data24);

if(num_samples < 0)
Expand Down Expand Up @@ -2097,6 +2081,8 @@ fluid_sample_import_sfont(fluid_sample_t *sample, SFSample *sfsample, fluid_defs
sample->notify = dynamic_samples_sample_notify;
}

FLUID_LOG(FLUID_DBG, "Discovering sample '%s', src_start %d, loop_start %d, loop_end %d, src_end %d", sample->name, sample->source_start, sample->loopstart, sample->loopend, sample->source_end);

if(fluid_sample_validate(sample, defsfont->samplesize) == FLUID_FAILED)
{
return FLUID_FAILED;
Expand Down
15 changes: 14 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ else()
set(REVERB_RENDER_DIR "${CMAKE_CURRENT_BINARY_DIR}/manual/reverb")
set(EXCL_RENDER_DIR "${CMAKE_CURRENT_BINARY_DIR}/manual/exclusive_class")
set(DSPINTERP_RENDER_DIR "${CMAKE_CURRENT_BINARY_DIR}/manual/dsp_interp")
set(DYNSAM_RENDER_DIR "${CMAKE_CURRENT_BINARY_DIR}/manual/dynamic-sample-loading")

if(LIBSNDFILE_SUPPORT)
set(FEXT "wav")
Expand All @@ -69,7 +70,7 @@ else()
add_custom_target(check_manual)

add_custom_target(create_iir_dir
COMMAND ${CMAKE_COMMAND} -E make_directory ${IIR_FILTER_RENDER_DIR} ${AWE32_NRPN_RENDER_DIR} ${SFSPEC_RENDER_DIR} ${PORTAMENTO_RENDER_DIR} ${REVERB_RENDER_DIR} ${EXCL_RENDER_DIR} ${DSPINTERP_RENDER_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${IIR_FILTER_RENDER_DIR} ${AWE32_NRPN_RENDER_DIR} ${SFSPEC_RENDER_DIR} ${PORTAMENTO_RENDER_DIR} ${REVERB_RENDER_DIR} ${EXCL_RENDER_DIR} ${DSPINTERP_RENDER_DIR} ${DYNSAM_RENDER_DIR}
VERBATIM)

add_custom_target(render1415
Expand Down Expand Up @@ -219,6 +220,15 @@ else()
VERBATIM
)

add_custom_target(render1484
COMMAND fluidsynth -R 0 -C 0 -g 0.6 -o synth.dynamic-sample-loading=1 -F "${DYNSAM_RENDER_DIR}/dynamic-sample-loading_on.${FEXT}" "dynamic-sample-loading_test.mid" "DrTebz.sf2"
COMMAND fluidsynth -R 0 -C 0 -g 0.6 -o synth.dynamic-sample-loading=0 -F "${DYNSAM_RENDER_DIR}/dynamic-sample-loading_off.${FEXT}" "dynamic-sample-loading_test.mid" "DrTebz.sf2"
COMMENT "Rendering dynamic sample loading test"
DEPENDS fluidsynth create_iir_dir
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/manual/dynamic-sample-loading/
VERBATIM
)

# Add a dependency so that rendering targets depends on check_manual
add_dependencies(check_manual render1415)
add_dependencies(check_manual render1417)
Expand All @@ -233,5 +243,8 @@ else()
add_dependencies(check_manual render1455)
add_dependencies(check_manual renderDK64JJU)
add_dependencies(check_manual renderExcl)
add_dependencies(check_manual rendere1m1)
add_dependencies(check_manual renderdspInterp)
add_dependencies(check_manual render1484)

endif()

0 comments on commit 1e82bd6

Please sign in to comment.