Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix interruptions of real-time playback #1494

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .azure/azure-pipelines-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ jobs:
strategy:
matrix:
x64:
CMAKE_FLAGS:
CMAKE_FLAGS: "-Denable-profiling=1"
platform: x64
gtk-bundle: $(gtk-bundle-x64)
libsndfile-url: $(libsndfile-url-x64)
Expand Down
18 changes: 13 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ unset ( WITH_PROFILING CACHE )
if ( enable-profiling )
set ( WITH_PROFILING 1 )
if ( CMAKE_C_COMPILER_ID STREQUAL "Clang" )
set ( OPT_FLAGS "-Rpass=loop-vectorize" ) # -Rpass-analysis=loop-vectorize" )
set ( OPT_FLAGS "-Rpass=loop-vectorize -Rpass-analysis=loop-vectorize" )
find_program( CLANG_TIDY
NAMES "clang-tidy"
DOC "Path to clang-tidy executable" )
Expand All @@ -452,6 +452,8 @@ if ( enable-profiling )
set ( OPT_FLAGS "-qopt-report=3" )
elseif ( CMAKE_C_COMPILER_ID STREQUAL "GNU" )
set ( OPT_FLAGS "-fopt-info -fopt-info-vec-missed" )
elseif ( CMAKE_C_COMPILER_ID STREQUAL "MSVC" )
set ( OPT_FLAGS "/Qvec-report:2" )
endif ( )

set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPT_FLAGS}" )
Expand Down Expand Up @@ -743,16 +745,22 @@ if ( enable-threads )
endif ( enable-threads )

unset ( HAVE_OPENMP CACHE )
find_package ( OpenMP COMPONENTS C )
find_package ( OpenMP COMPONENTS C CXX )
if (enable-openmp AND ENABLE_UBSAN)
message(WARNING "OpenMP is not supported when UBSan is enabled. Disabling OpenMP.")
elseif (enable-openmp AND OpenMP_C_FOUND )
message(STATUS "Found OpenMP version: ${OpenMP_C_VERSION} date: ${OpenMP_C_SPEC_DATE}")
elseif (enable-openmp AND ( OpenMP_C_FOUND OR OpenMP_CXX_FOUND ))
message(STATUS "Found OpenMP C version: ${OpenMP_C_VERSION} date: ${OpenMP_C_SPEC_DATE}")
message(STATUS "Found OpenMP CXX version: ${OpenMP_CXX_VERSION} date: ${OpenMP_CXX_SPEC_DATE}")
if ( TARGET OpenMP::OpenMP_C AND (( NOT OpenMP_C_SPEC_DATE LESS "201307" ) OR NOT ( OpenMP_C_VERSION VERSION_LESS "4.0" )) )
set ( HAVE_OPENMP 1 )
list ( APPEND PC_LIBS_PRIV ${OpenMP_C_LIBRARIES} )
else()
message(STATUS " OpenMP version is not supported. Feature disabled.")
message(STATUS " OpenMP C version is not supported. Feature disabled.")
endif()
if ( TARGET OpenMP::OpenMP_CXX AND (( NOT OpenMP_CXX_SPEC_DATE LESS "201307" ) OR NOT ( OpenMP_CXX_VERSION VERSION_LESS "4.0" )) )
list ( APPEND PC_LIBS_PRIV ${OpenMP_CXX_LIBRARIES} )
else()
message(STATUS " OpenMP CXX version is not supported. Feature disabled.")
endif()
endif()

Expand Down
11 changes: 11 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ set ( libfluidsynth_SOURCES
rvoice/fluid_adsr_env.h
rvoice/fluid_chorus.c
rvoice/fluid_chorus.h
rvoice/fluid_iir_filter.cpp
rvoice/fluid_iir_filter.c
rvoice/fluid_iir_filter.h
rvoice/fluid_lfo.c
Expand Down Expand Up @@ -180,6 +181,12 @@ set ( libfluidsynth_SOURCES
bindings/fluid_ladspa.c
bindings/fluid_ladspa.h
)
if ( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
set_source_files_properties(rvoice/fluid_iir_filter.cpp PROPERTIES COMPILE_FLAGS "-fno-math-errno -ffast-math")
elseif ( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
set_source_files_properties(rvoice/fluid_iir_filter.cpp PROPERTIES COMPILE_FLAGS "/fp:fast")
endif ( )


set ( public_HEADERS
${FluidSynth_SOURCE_DIR}/include/fluidsynth/audio.h
Expand Down Expand Up @@ -352,6 +359,10 @@ if ( TARGET OpenMP::OpenMP_C AND HAVE_OPENMP )
target_link_libraries ( libfluidsynth-OBJ PUBLIC OpenMP::OpenMP_C )
endif()

if ( TARGET OpenMP::OpenMP_CXX AND HAVE_OPENMP )
target_link_libraries ( libfluidsynth-OBJ PUBLIC OpenMP::OpenMP_CXX )
endif()

target_link_libraries ( libfluidsynth-OBJ PUBLIC GLib2::glib-2 GLib2::gthread-2 )

if ( TARGET SndFile::sndfile AND LIBSNDFILE_SUPPORT )
Expand Down
82 changes: 2 additions & 80 deletions src/rvoice/fluid_iir_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ fluid_iir_filter_reset(fluid_iir_filter_t *iir_filter)
iir_filter->last_fres = -1.;
iir_filter->last_q = 0;
iir_filter->filter_startup = 1;
iir_filter->amp = 0;
iir_filter->amp_incr = 0;
}

DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_fres)
Expand Down Expand Up @@ -133,83 +135,3 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_iir_filter_set_q)
iir_filter->target_q = q;
#endif
}

void fluid_iir_filter_calc(fluid_iir_filter_t *iir_filter,
fluid_real_t output_rate,
fluid_real_t fres_mod)
{
unsigned int calc_coeff_flag = FALSE;
fluid_real_t fres, fres_diff;

if(iir_filter->type == FLUID_IIR_DISABLED)
{
return;
}

/* calculate the frequency of the resonant filter in Hz */
fres = fluid_ct2hz(iir_filter->fres + fres_mod);

/* I removed the optimization of turning the filter off when the
* resonance frequency is above the maximum frequency. Instead, the
* filter frequency is set to a maximum of 0.45 times the sampling
* rate. For a 44100 kHz sampling rate, this amounts to 19845
* Hz. The reason is that there were problems with anti-aliasing when the
* synthesizer was run at lower sampling rates. Thanks to Stephan
* Tassart for pointing me to this bug. By turning the filter on and
* clipping the maximum filter frequency at 0.45*srate, the filter
* is used as an anti-aliasing filter. */

if(fres > 0.45f * output_rate)
{
fres = 0.45f * output_rate;
}
else if(fres < 5.f)
{
fres = 5.f;
}

LOG_FILTER("%f + %f = %f cents = %f Hz | Q: %f", iir_filter->fres, fres_mod, iir_filter->fres + fres_mod, fres, iir_filter->last_q);

/* if filter enabled and there is a significant frequency change.. */
fres_diff = fres - iir_filter->last_fres;
if(iir_filter->filter_startup)
{
// The filer was just starting up, make sure to calculate initial coefficients for the initial Q value, even though the fres may not have changed
calc_coeff_flag = TRUE;

iir_filter->fres_incr_count = 0;
iir_filter->last_fres = fres;
iir_filter->filter_startup = (FLUID_FABS(iir_filter->last_q) < Q_MIN); // filter coefficients will not be initialized when Q is small
}
else if(FLUID_FABS(fres_diff) > 0.01f)
{
fluid_real_t fres_incr_count = FLUID_BUFSIZE;
fluid_real_t num_buffers = iir_filter->last_q;
fluid_clip(num_buffers, 1, 5);
// For high values of Q, the phase gets really steep. To prevent clicks when quickly modulating fres in this case, we need to smooth out "slower".
// This is done by simply using Q times FLUID_BUFSIZE samples for the interpolation to complete, capped at 5.
// 5 was chosen because the phase doesn't really get any steeper when continuing to increase Q.
fres_incr_count *= num_buffers;
iir_filter->fres_incr = fres_diff / (fres_incr_count);
iir_filter->fres_incr_count = fres_incr_count;
#ifdef DBG_FILTER
iir_filter->target_fres = fres;
#endif

// The filter coefficients have to be recalculated (filter cutoff has changed).
calc_coeff_flag = TRUE;
}
else
{
// We do not account for any change of Q here - if it was changed q_incro_count will be non-zero and recalculating the coeffs
// will be taken care of in fluid_iir_filter_apply().
}

if (calc_coeff_flag && !iir_filter->filter_startup)
{
fluid_iir_filter_calculate_coefficients(iir_filter, output_rate, &iir_filter->a1, &iir_filter->a2, &iir_filter->b02, &iir_filter->b1);
}

fluid_check_fpe("voice_write DSP coefficients");

}
Loading
Loading