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

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4ef4360
Move IIR filter out of dsp_interpolation again
derselbst Feb 21, 2025
ec2fd57
Move switch to C++ world
derselbst Feb 21, 2025
5cc6db7
Start amplify impl
derselbst Feb 21, 2025
a97675f
Move envelope gain to IIR filter
derselbst Feb 21, 2025
cb7d438
Merge branch 'master' into cpu-opt
derselbst Feb 22, 2025
1c92fa5
Auto-Vectorize IIR filter coefficient calculations
derselbst Feb 22, 2025
c7ce44b
Fix build on Windows
derselbst Feb 23, 2025
ff5d5b3
Fix a few type truncation warnings
derselbst Feb 23, 2025
b052ef2
Add vectorization report for MSVC
derselbst Feb 23, 2025
ed53eeb
Enable profiling for MinGW CI build
derselbst Feb 23, 2025
530f0e0
Try ffast-math to convince MinGW to auto-vectorize
derselbst Feb 23, 2025
f83368b
First test with sin / cos lookup table
derselbst Feb 23, 2025
40bf22c
Remove vectorization again, fix lookup table
derselbst Feb 23, 2025
2c322d8
Optimize away unnecessary inverse sqrt
derselbst Feb 23, 2025
3292e3f
Revert "Optimize away unnecessary inverse sqrt"
derselbst Feb 23, 2025
53ef2d5
disable sample rate change test
derselbst Feb 23, 2025
23035e2
Linear interpolation (fine tuning) of sin cos coefficients
derselbst Mar 1, 2025
8a5c2f7
diff by zero
derselbst Mar 1, 2025
163d0fc
oops
derselbst Mar 1, 2025
8bf6152
Revert "Linear interpolation (fine tuning) of sin cos coefficients"
derselbst Mar 8, 2025
30082a7
Merge branch 'master' into cpu-opt
derselbst Mar 8, 2025
d42a6aa
typo
derselbst Mar 8, 2025
44f237f
one sin cos coeff every cent
derselbst Mar 8, 2025
bbee05d
make it work with any sample rate
derselbst Mar 9, 2025
a36bbde
less magic numbers
derselbst Mar 9, 2025
1f41684
make gcc happy
derselbst Mar 9, 2025
bc76e47
revert a few changes that are no longer needed
derselbst Mar 9, 2025
88491a3
missed one
derselbst Mar 9, 2025
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