mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-12-11 13:21:03 +00:00
Merge pull request #818 from FluidSynth/defsfont-integration-test
Add defsfont integration test
This commit is contained in:
commit
487156c3ed
10 changed files with 38214 additions and 63 deletions
|
@ -27,6 +27,53 @@ macro ( ADD_FLUID_TEST _test )
|
|||
|
||||
endmacro ( ADD_FLUID_TEST )
|
||||
|
||||
macro ( ADD_FLUID_TEST_UTIL _util )
|
||||
ADD_EXECUTABLE(${_util} ${_util}.c $<TARGET_OBJECTS:libfluidsynth-OBJ> )
|
||||
|
||||
# only build this unit test when explicitly requested by "make check"
|
||||
set_target_properties(${_util} PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
# append no-op generator expression to avoid VS or XCode from adding per-config subdirectories
|
||||
set_target_properties(${_util} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/utils/$<0:>)
|
||||
|
||||
# import necessary compile flags and dependency libraries
|
||||
if ( FLUID_CPPFLAGS )
|
||||
set_target_properties ( ${_util} PROPERTIES COMPILE_FLAGS ${FLUID_CPPFLAGS} )
|
||||
endif ( FLUID_CPPFLAGS )
|
||||
TARGET_LINK_LIBRARIES(${_util} $<TARGET_PROPERTY:libfluidsynth,INTERFACE_LINK_LIBRARIES>)
|
||||
|
||||
# use the local include path to look for fluidsynth.h, as we cannot be sure fluidsynth is already installed
|
||||
target_include_directories(${_util}
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include> # include auto generated headers
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include> # include "normal" public (sub-)headers
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src> # include private headers
|
||||
$<TARGET_PROPERTY:libfluidsynth,INCLUDE_DIRECTORIES> # include all other header search paths needed by libfluidsynth (esp. glib)
|
||||
)
|
||||
|
||||
# append the current unit test to check-target as dependency
|
||||
add_dependencies(check ${_util})
|
||||
|
||||
endmacro ( ADD_FLUID_TEST_UTIL )
|
||||
|
||||
# This macro adds a test that writes its output to a file called
|
||||
# <test>.output (in the current working dir) and then compares
|
||||
# the content with the file given in _expected_output
|
||||
macro ( ADD_FLUID_SF_DUMP_TEST _sfname)
|
||||
|
||||
set( test_args "${CMAKE_SOURCE_DIR}/sf2/${_sfname} ${_sfname}.yml" )
|
||||
|
||||
ADD_TEST(${_sfname}_dump_test
|
||||
${CMAKE_COMMAND}
|
||||
-Dtest_cmd=${CMAKE_BINARY_DIR}/test/utils/dump_sfont${CMAKE_EXECUTABLE_SUFFIX}
|
||||
-Dtest_args=${test_args}
|
||||
-Dtest_output=${_sfname}.yml
|
||||
-Dexpected_output=${CMAKE_SOURCE_DIR}/sf2/${_sfname}.yml
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake_admin/RunOutputTest.cmake
|
||||
)
|
||||
|
||||
endmacro ( ADD_FLUID_SF_DUMP_TEST )
|
||||
|
||||
macro ( ADD_FLUID_DEMO _demo )
|
||||
ADD_EXECUTABLE(${_demo} ${_demo}.c )
|
||||
|
||||
|
|
31
cmake_admin/RunOutputTest.cmake
Normal file
31
cmake_admin/RunOutputTest.cmake
Normal file
|
@ -0,0 +1,31 @@
|
|||
if( NOT test_cmd )
|
||||
message( FATAL_ERROR "test_cmd not defined" )
|
||||
endif( NOT test_cmd )
|
||||
|
||||
if( NOT test_output )
|
||||
message( FATAL_ERROR "test_output not defined" )
|
||||
endif( NOT test_output )
|
||||
|
||||
if( NOT expected_output )
|
||||
message( FATAL_ERROR "expected_output not defined" )
|
||||
endif( NOT expected_output )
|
||||
|
||||
separate_arguments( test_args )
|
||||
|
||||
execute_process(
|
||||
COMMAND ${test_cmd} ${test_args}
|
||||
RESULT_VARIABLE test_not_successful
|
||||
)
|
||||
|
||||
if( test_not_successful )
|
||||
message( FATAL_ERROR "${test_cmd} ${test_args} returned error ${test_not_successful}!" )
|
||||
endif( test_not_successful )
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E compare_files ${expected_output} ${test_output}
|
||||
RESULT_VARIABLE compare_not_successful
|
||||
)
|
||||
|
||||
if( compare_not_successful )
|
||||
message( SEND_ERROR "${test_output} does not match ${expected_output}!" )
|
||||
endif( compare_not_successful )
|
18805
sf2/VintageDreamsWaves-v2.sf2.yml
Normal file
18805
sf2/VintageDreamsWaves-v2.sf2.yml
Normal file
File diff suppressed because it is too large
Load diff
18805
sf2/VintageDreamsWaves-v2.sf3.yml
Normal file
18805
sf2/VintageDreamsWaves-v2.sf3.yml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -23,73 +23,76 @@
|
|||
#include "fluid_chan.h"
|
||||
|
||||
|
||||
#define _GEN(_name) GEN_ ## _name, #_name
|
||||
|
||||
|
||||
/* See SFSpec21 $8.1.3 */
|
||||
static const fluid_gen_info_t fluid_gen_info[] =
|
||||
{
|
||||
/* number/name init nrpn-scale min max def */
|
||||
{ GEN_STARTADDROFS, 1, 1, 0.0f, 1e10f, 0.0f },
|
||||
{ GEN_ENDADDROFS, 1, 1, -1e10f, 0.0f, 0.0f },
|
||||
{ GEN_STARTLOOPADDROFS, 1, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ GEN_ENDLOOPADDROFS, 1, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ GEN_STARTADDRCOARSEOFS, 0, 1, 0.0f, 1e10f, 0.0f },
|
||||
{ GEN_MODLFOTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ GEN_VIBLFOTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ GEN_MODENVTOPITCH, 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ GEN_FILTERFC, 1, 2, 1500.0f, 13500.0f, 13500.0f },
|
||||
{ GEN_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f },
|
||||
{ GEN_MODLFOTOFILTERFC, 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ GEN_MODENVTOFILTERFC, 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ GEN_ENDADDRCOARSEOFS, 0, 1, -1e10f, 0.0f, 0.0f },
|
||||
{ GEN_MODLFOTOVOL, 1, 1, -960.0f, 960.0f, 0.0f },
|
||||
{ GEN_UNUSED1, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_CHORUSSEND, 1, 1, 0.0f, 1000.0f, 0.0f },
|
||||
{ GEN_REVERBSEND, 1, 1, 0.0f, 1000.0f, 0.0f },
|
||||
{ GEN_PAN, 1, 1, -500.0f, 500.0f, 0.0f },
|
||||
{ GEN_UNUSED2, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_UNUSED3, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_UNUSED4, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_MODLFODELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ GEN_MODLFOFREQ, 1, 4, -16000.0f, 4500.0f, 0.0f },
|
||||
{ GEN_VIBLFODELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ GEN_VIBLFOFREQ, 1, 4, -16000.0f, 4500.0f, 0.0f },
|
||||
{ GEN_MODENVDELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ GEN_MODENVATTACK, 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ GEN_MODENVHOLD, 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ GEN_MODENVDECAY, 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ GEN_MODENVSUSTAIN, 0, 1, 0.0f, 1000.0f, 0.0f },
|
||||
{ GEN_MODENVRELEASE, 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ GEN_KEYTOMODENVHOLD, 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ GEN_KEYTOMODENVDECAY, 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ GEN_VOLENVDELAY, 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ GEN_VOLENVATTACK, 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ GEN_VOLENVHOLD, 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ GEN_VOLENVDECAY, 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ GEN_VOLENVSUSTAIN, 0, 1, 0.0f, 1440.0f, 0.0f },
|
||||
{ GEN_VOLENVRELEASE, 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ GEN_KEYTOVOLENVHOLD, 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ GEN_KEYTOVOLENVDECAY, 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ GEN_INSTRUMENT, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_RESERVED1, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_KEYRANGE, 0, 0, 0.0f, 127.0f, 0.0f },
|
||||
{ GEN_VELRANGE, 0, 0, 0.0f, 127.0f, 0.0f },
|
||||
{ GEN_STARTLOOPADDRCOARSEOFS, 0, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ GEN_KEYNUM, 1, 0, 0.0f, 127.0f, -1.0f },
|
||||
{ GEN_VELOCITY, 1, 1, 0.0f, 127.0f, -1.0f },
|
||||
{ GEN_ATTENUATION, 1, 1, 0.0f, 1440.0f, 0.0f },
|
||||
{ GEN_RESERVED2, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_ENDLOOPADDRCOARSEOFS, 0, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ GEN_COARSETUNE, 0, 1, -120.0f, 120.0f, 0.0f },
|
||||
{ GEN_FINETUNE, 0, 1, -99.0f, 99.0f, 0.0f },
|
||||
{ GEN_SAMPLEID, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_SAMPLEMODE, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_RESERVED3, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_SCALETUNE, 0, 1, 0.0f, 1200.0f, 100.0f },
|
||||
{ GEN_EXCLUSIVECLASS, 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ GEN_OVERRIDEROOTKEY, 1, 0, 0.0f, 127.0f, -1.0f },
|
||||
{ GEN_PITCH, 1, 0, 0.0f, 127.0f, 0.0f },
|
||||
{ GEN_CUSTOM_BALANCE, 1, 0, -960.0f, 960.0f, 0.0f },
|
||||
{ GEN_CUSTOM_FILTERFC, 1, 2, 0.0f, 22050.0f, 0.0f },
|
||||
{ GEN_CUSTOM_FILTERQ, 1, 1, 0.0f, 960.0f, 0.0f }
|
||||
{ _GEN(STARTADDROFS), 1, 1, 0.0f, 1e10f, 0.0f },
|
||||
{ _GEN(ENDADDROFS), 1, 1, -1e10f, 0.0f, 0.0f },
|
||||
{ _GEN(STARTLOOPADDROFS), 1, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ _GEN(ENDLOOPADDROFS), 1, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ _GEN(STARTADDRCOARSEOFS), 0, 1, 0.0f, 1e10f, 0.0f },
|
||||
{ _GEN(MODLFOTOPITCH), 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ _GEN(VIBLFOTOPITCH), 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ _GEN(MODENVTOPITCH), 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ _GEN(FILTERFC), 1, 2, 1500.0f, 13500.0f, 13500.0f },
|
||||
{ _GEN(FILTERQ), 1, 1, 0.0f, 960.0f, 0.0f },
|
||||
{ _GEN(MODLFOTOFILTERFC), 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ _GEN(MODENVTOFILTERFC), 1, 2, -12000.0f, 12000.0f, 0.0f },
|
||||
{ _GEN(ENDADDRCOARSEOFS), 0, 1, -1e10f, 0.0f, 0.0f },
|
||||
{ _GEN(MODLFOTOVOL), 1, 1, -960.0f, 960.0f, 0.0f },
|
||||
{ _GEN(UNUSED1), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(CHORUSSEND), 1, 1, 0.0f, 1000.0f, 0.0f },
|
||||
{ _GEN(REVERBSEND), 1, 1, 0.0f, 1000.0f, 0.0f },
|
||||
{ _GEN(PAN), 1, 1, -500.0f, 500.0f, 0.0f },
|
||||
{ _GEN(UNUSED2), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(UNUSED3), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(UNUSED4), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(MODLFODELAY), 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ _GEN(MODLFOFREQ), 1, 4, -16000.0f, 4500.0f, 0.0f },
|
||||
{ _GEN(VIBLFODELAY), 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ _GEN(VIBLFOFREQ), 1, 4, -16000.0f, 4500.0f, 0.0f },
|
||||
{ _GEN(MODENVDELAY), 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ _GEN(MODENVATTACK), 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ _GEN(MODENVHOLD), 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ _GEN(MODENVDECAY), 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ _GEN(MODENVSUSTAIN), 0, 1, 0.0f, 1000.0f, 0.0f },
|
||||
{ _GEN(MODENVRELEASE), 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ _GEN(KEYTOMODENVHOLD), 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ _GEN(KEYTOMODENVDECAY), 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ _GEN(VOLENVDELAY), 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ _GEN(VOLENVATTACK), 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ _GEN(VOLENVHOLD), 1, 2, -12000.0f, 5000.0f, -12000.0f },
|
||||
{ _GEN(VOLENVDECAY), 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ _GEN(VOLENVSUSTAIN), 0, 1, 0.0f, 1440.0f, 0.0f },
|
||||
{ _GEN(VOLENVRELEASE), 1, 2, -12000.0f, 8000.0f, -12000.0f },
|
||||
{ _GEN(KEYTOVOLENVHOLD), 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ _GEN(KEYTOVOLENVDECAY), 0, 1, -1200.0f, 1200.0f, 0.0f },
|
||||
{ _GEN(INSTRUMENT), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(RESERVED1), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(KEYRANGE), 0, 0, 0.0f, 127.0f, 0.0f },
|
||||
{ _GEN(VELRANGE), 0, 0, 0.0f, 127.0f, 0.0f },
|
||||
{ _GEN(STARTLOOPADDRCOARSEOFS), 0, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ _GEN(KEYNUM), 1, 0, 0.0f, 127.0f, -1.0f },
|
||||
{ _GEN(VELOCITY), 1, 1, 0.0f, 127.0f, -1.0f },
|
||||
{ _GEN(ATTENUATION), 1, 1, 0.0f, 1440.0f, 0.0f },
|
||||
{ _GEN(RESERVED2), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(ENDLOOPADDRCOARSEOFS), 0, 1, -1e10f, 1e10f, 0.0f },
|
||||
{ _GEN(COARSETUNE), 0, 1, -120.0f, 120.0f, 0.0f },
|
||||
{ _GEN(FINETUNE), 0, 1, -99.0f, 99.0f, 0.0f },
|
||||
{ _GEN(SAMPLEID), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(SAMPLEMODE), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(RESERVED3), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(SCALETUNE), 0, 1, 0.0f, 1200.0f, 100.0f },
|
||||
{ _GEN(EXCLUSIVECLASS), 0, 0, 0.0f, 0.0f, 0.0f },
|
||||
{ _GEN(OVERRIDEROOTKEY), 1, 0, 0.0f, 127.0f, -1.0f },
|
||||
{ _GEN(PITCH), 1, 0, 0.0f, 127.0f, 0.0f },
|
||||
{ _GEN(CUSTOM_BALANCE), 1, 0, -960.0f, 960.0f, 0.0f },
|
||||
{ _GEN(CUSTOM_FILTERFC), 1, 2, 0.0f, 22050.0f, 0.0f },
|
||||
{ _GEN(CUSTOM_FILTERQ), 1, 1, 0.0f, 960.0f, 0.0f }
|
||||
};
|
||||
|
||||
/* fluid_gen_init
|
||||
|
@ -122,3 +125,9 @@ fluid_real_t fluid_gen_scale_nrpn(int gen, int data)
|
|||
fluid_clip(data, -8192, 8192);
|
||||
return (fluid_real_t)(data * fluid_gen_info[gen].nrpn_scale);
|
||||
}
|
||||
|
||||
|
||||
const char *fluid_gen_name(int gen)
|
||||
{
|
||||
return fluid_gen_info[gen].name;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
typedef struct _fluid_gen_info_t
|
||||
{
|
||||
char num; /* Generator number */
|
||||
char *name;
|
||||
char init; /* Does the generator need to be initialized (not used) */
|
||||
char nrpn_scale; /* The scale to convert from NRPN (cfr. fluid_gen_map_nrpn()) */
|
||||
float min; /* The minimum value */
|
||||
|
@ -60,6 +61,7 @@ enum fluid_gen_flags
|
|||
fluid_real_t fluid_gen_scale(int gen, float value);
|
||||
fluid_real_t fluid_gen_scale_nrpn(int gen, int nrpn);
|
||||
void fluid_gen_init(fluid_gen_t *gen, fluid_channel_t *channel);
|
||||
const char *fluid_gen_name(int gen);
|
||||
|
||||
|
||||
#endif /* _FLUID_GEN_H */
|
||||
|
|
|
@ -319,3 +319,19 @@ fluid_list_str_compare_func(void *a, void *b)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fluid_list_idx(fluid_list_t *list, void *data)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while(list)
|
||||
{
|
||||
if (list->data == data)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ fluid_list_t *fluid_list_remove_link(fluid_list_t *list, fluid_list_t *llink);
|
|||
fluid_list_t *fluid_list_nth(fluid_list_t *list, int n);
|
||||
fluid_list_t *fluid_list_last(fluid_list_t *list);
|
||||
fluid_list_t *fluid_list_insert_at(fluid_list_t *list, int n, void *data);
|
||||
int fluid_list_idx(fluid_list_t *list, void *data);
|
||||
int fluid_list_size(fluid_list_t *list);
|
||||
|
||||
#define fluid_list_next(slist) ((slist) ? (((fluid_list_t *)(slist))->next) : NULL)
|
||||
|
|
|
@ -30,6 +30,11 @@ ADD_FLUID_TEST(test_seq_event_queue_remove)
|
|||
ADD_FLUID_TEST(test_jack_obtaining_synth)
|
||||
ADD_FLUID_TEST(test_utf8_open)
|
||||
|
||||
ADD_FLUID_TEST_UTIL(dump_sfont)
|
||||
|
||||
ADD_FLUID_SF_DUMP_TEST(VintageDreamsWaves-v2.sf2)
|
||||
|
||||
if ( LIBSNDFILE_HASVORBIS )
|
||||
ADD_FLUID_TEST(test_sf3_sfont_loading)
|
||||
ADD_FLUID_SF_DUMP_TEST(VintageDreamsWaves-v2.sf3)
|
||||
endif ( LIBSNDFILE_HASVORBIS )
|
||||
|
|
430
test/dump_sfont.c
Normal file
430
test/dump_sfont.c
Normal file
|
@ -0,0 +1,430 @@
|
|||
#include "test.h"
|
||||
#include "fluidsynth.h"
|
||||
#include "fluid_sfont.h"
|
||||
#include "fluid_defsfont.h"
|
||||
#include "fluid_sys.h"
|
||||
|
||||
static void dump_sample(fluid_sample_t *sample);
|
||||
static void dump_gens(const fluid_gen_t gen[]);
|
||||
static void dump_mod(const fluid_mod_t *mod);
|
||||
static void dump_preset_zone(fluid_preset_zone_t *zone);
|
||||
static void dump_preset(fluid_preset_t *preset);
|
||||
static void dump_inst_zone(fluid_inst_zone_t *zone);
|
||||
static void dump_inst(fluid_inst_t *inst);
|
||||
static void dump_defsfont(fluid_defsfont_t *defsfont);
|
||||
static int inst_compare_func(void *a, void *b);
|
||||
static fluid_list_t *collect_preset_insts(fluid_preset_t *preset, fluid_list_t *inst_list);
|
||||
|
||||
#define FMT_BUFSIZE (4096)
|
||||
static int indent_level = 0;
|
||||
static FILE *output = NULL;
|
||||
|
||||
static void fmt(const char *format, ...);
|
||||
static void indent(void);
|
||||
static void outdent(void);
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = FLUID_FAILED;
|
||||
int id;
|
||||
fluid_sfont_t *sfont;
|
||||
fluid_defsfont_t *defsfont;
|
||||
fluid_settings_t *settings;
|
||||
fluid_synth_t *synth;
|
||||
const char *adrivers[1] = { NULL };
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, " dump_sfont <input_soundfont> [output_file]\n");
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
fluid_audio_driver_register(adrivers);
|
||||
|
||||
settings = new_fluid_settings();
|
||||
if (settings == NULL)
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
synth = new_fluid_synth(settings);
|
||||
if (synth == NULL)
|
||||
{
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
id = fluid_synth_sfload(synth, argv[1], 1);
|
||||
if (id < 0)
|
||||
{
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
sfont = fluid_synth_get_sfont_by_id(synth, id);
|
||||
if (sfont == NULL)
|
||||
{
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
if (sfont->free != &fluid_defsfont_sfont_delete)
|
||||
{
|
||||
fprintf(stderr, "This tool only supports SoundFonts loaded by the default loader\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
defsfont = (fluid_defsfont_t *)fluid_sfont_get_data(sfont);
|
||||
if (defsfont == NULL)
|
||||
{
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
output = stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
output = fopen(argv[2], "w");
|
||||
if (output == NULL)
|
||||
{
|
||||
fprintf(stderr, "Unable to open output file %s", argv[2]);
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
dump_defsfont(defsfont);
|
||||
|
||||
ret = FLUID_OK;
|
||||
|
||||
EXIT:
|
||||
if (output && output != stdout)
|
||||
{
|
||||
fclose(output);
|
||||
}
|
||||
delete_fluid_synth(synth);
|
||||
delete_fluid_settings(settings);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dump_sample(fluid_sample_t *sample)
|
||||
{
|
||||
fmt("name: %s", sample->name);
|
||||
fmt("source_start: %u", sample->source_start);
|
||||
fmt("source_end: %u", sample->source_end);
|
||||
fmt("source_loopstart: %u", sample->source_loopstart);
|
||||
fmt("source_loopend: %u", sample->source_loopend);
|
||||
|
||||
fmt("start: %u", sample->start);
|
||||
fmt("end: %u", sample->end);
|
||||
fmt("loopstart: %u", sample->loopstart);
|
||||
fmt("loopend: %u", sample->loopend);
|
||||
|
||||
fmt("samplerate: %u", sample->samplerate);
|
||||
fmt("origpitch: %u", sample->origpitch);
|
||||
fmt("pitchadj: %u", sample->pitchadj);
|
||||
fmt("sampletype: %u", sample->sampletype);
|
||||
}
|
||||
|
||||
static void dump_gens(const fluid_gen_t gen[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* only dump generators if at least one is set */
|
||||
for (i = 0; i < GEN_LAST; i++)
|
||||
{
|
||||
if (gen[i].flags)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == GEN_LAST)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fmt("generators:");
|
||||
indent();
|
||||
for (i = 0; i < GEN_LAST; i++)
|
||||
{
|
||||
if (gen[i].flags)
|
||||
{
|
||||
fmt("%s: %.2f", fluid_gen_name(i), gen[i].val);
|
||||
}
|
||||
}
|
||||
outdent();
|
||||
}
|
||||
|
||||
static void dump_mod(const fluid_mod_t *mod)
|
||||
{
|
||||
fmt("dest: %s", fluid_gen_name(mod->dest));
|
||||
fmt("src1: %u", mod->src1);
|
||||
fmt("flags1: %u", mod->flags1);
|
||||
fmt("src2: %u", mod->src2);
|
||||
fmt("flags2: %u", mod->flags2);
|
||||
fmt("amount: %.2f", mod->amount);
|
||||
}
|
||||
|
||||
static void dump_preset_zone(fluid_preset_zone_t *zone)
|
||||
{
|
||||
int i;
|
||||
fluid_mod_t *mod;
|
||||
|
||||
fmt("name: %s", zone->name);
|
||||
if (zone->inst)
|
||||
{
|
||||
fmt("instrument: %s (index %d)", zone->inst->name, zone->inst->source_idx);
|
||||
}
|
||||
fmt("key_range: %d - %d", zone->range.keylo, zone->range.keyhi);
|
||||
fmt("vel_range: %d - %d", zone->range.vello, zone->range.velhi);
|
||||
dump_gens(zone->gen);
|
||||
|
||||
if (zone->mod)
|
||||
{
|
||||
fmt("modulators:");
|
||||
for (i = 0, mod = zone->mod; mod; mod = mod->next, i++)
|
||||
{
|
||||
fmt("- modulator: %d", i);
|
||||
indent();
|
||||
dump_mod(mod);
|
||||
outdent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_preset(fluid_preset_t *preset)
|
||||
{
|
||||
int i;
|
||||
fluid_preset_zone_t *zone;
|
||||
|
||||
fluid_defpreset_t *defpreset = fluid_preset_get_data(preset);
|
||||
if (defpreset == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fmt("name: %s", defpreset->name);
|
||||
fmt("bank: %u", defpreset->bank);
|
||||
fmt("num: %u", defpreset->num);
|
||||
|
||||
if (defpreset->global_zone)
|
||||
{
|
||||
fmt("global_zone:");
|
||||
indent();
|
||||
dump_preset_zone(defpreset->global_zone);
|
||||
outdent();
|
||||
}
|
||||
|
||||
fmt("zones:");
|
||||
for (i = 0, zone = defpreset->zone; zone; zone = fluid_preset_zone_next(zone), i++)
|
||||
{
|
||||
fmt("- zone: %d", i);
|
||||
if (zone == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
indent();
|
||||
dump_preset_zone(zone);
|
||||
outdent();
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_inst_zone(fluid_inst_zone_t *zone)
|
||||
{
|
||||
int i;
|
||||
fluid_mod_t *mod;
|
||||
|
||||
fmt("name: %s", zone->name);
|
||||
if (zone->sample)
|
||||
{
|
||||
fmt("sample: %s", zone->sample->name);
|
||||
}
|
||||
fmt("key_range: %d - %d", zone->range.keylo, zone->range.keyhi);
|
||||
fmt("vel_range: %d - %d", zone->range.vello, zone->range.velhi);
|
||||
dump_gens(zone->gen);
|
||||
if (zone->mod)
|
||||
{
|
||||
fmt("modulators:");
|
||||
for (i = 0, mod = zone->mod; mod; mod = mod->next, i++)
|
||||
{
|
||||
fmt("- modulator: %d", i);
|
||||
indent();
|
||||
dump_mod(mod);
|
||||
outdent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_inst(fluid_inst_t *inst)
|
||||
{
|
||||
int i;
|
||||
fluid_inst_zone_t *zone;
|
||||
|
||||
fmt("name: %s", inst->name);
|
||||
|
||||
if (inst->global_zone)
|
||||
{
|
||||
fmt("global_zone:");
|
||||
indent();
|
||||
dump_inst_zone(inst->global_zone);
|
||||
outdent();
|
||||
}
|
||||
|
||||
fmt("zones:");
|
||||
for (i = 0, zone = inst->zone; zone; zone = fluid_inst_zone_next(zone), i++)
|
||||
{
|
||||
fmt("- zone: %d", i);
|
||||
if (zone == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
indent();
|
||||
dump_inst_zone(zone);
|
||||
outdent();
|
||||
}
|
||||
}
|
||||
|
||||
static int inst_compare_func(void *a, void *b)
|
||||
{
|
||||
const fluid_inst_t *inst_a = a;
|
||||
const fluid_inst_t *inst_b = b;
|
||||
|
||||
return inst_a->source_idx - inst_b->source_idx;
|
||||
}
|
||||
|
||||
static fluid_list_t *collect_preset_insts(fluid_preset_t *preset, fluid_list_t *inst_list)
|
||||
{
|
||||
fluid_preset_zone_t *zone;
|
||||
fluid_defpreset_t *defpreset = fluid_preset_get_data(preset);
|
||||
if (defpreset == NULL)
|
||||
{
|
||||
return inst_list;
|
||||
}
|
||||
|
||||
if (defpreset->global_zone && defpreset->global_zone->inst &&
|
||||
fluid_list_idx(inst_list, defpreset->global_zone->inst) == -1)
|
||||
{
|
||||
inst_list = fluid_list_prepend(inst_list, defpreset->global_zone->inst);
|
||||
}
|
||||
|
||||
for (zone = defpreset->zone; zone; zone = fluid_preset_zone_next(zone))
|
||||
{
|
||||
if (zone->inst && (fluid_list_idx(inst_list, zone->inst) == -1))
|
||||
{
|
||||
inst_list = fluid_list_prepend(inst_list, zone->inst);
|
||||
}
|
||||
}
|
||||
|
||||
return inst_list;
|
||||
}
|
||||
|
||||
|
||||
static void dump_defsfont(fluid_defsfont_t *defsfont)
|
||||
{
|
||||
int i;
|
||||
fluid_list_t *list;
|
||||
fluid_sample_t *sample;
|
||||
fluid_preset_t *preset;
|
||||
fluid_inst_t *inst;
|
||||
fluid_list_t *inst_list = NULL;
|
||||
|
||||
fmt("samplepos: %u", defsfont->samplepos);
|
||||
fmt("samplesize: %u", defsfont->samplesize);
|
||||
fmt("sample24pos: %u", defsfont->sample24pos);
|
||||
fmt("sample24size: %u", defsfont->sample24size);
|
||||
|
||||
fmt("presets:");
|
||||
for (i = 0, list = defsfont->preset; list; list = fluid_list_next(list), i++)
|
||||
{
|
||||
preset = (fluid_preset_t *)fluid_list_get(list);
|
||||
fmt("- preset: %d", i);
|
||||
if (preset == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
indent();
|
||||
dump_preset(preset);
|
||||
outdent();
|
||||
fmt("");
|
||||
|
||||
inst_list = collect_preset_insts(preset, inst_list);
|
||||
}
|
||||
|
||||
inst_list = fluid_list_sort(inst_list, (fluid_compare_func_t)inst_compare_func);
|
||||
|
||||
fmt("instruments:");
|
||||
for (list = inst_list; list; list = fluid_list_next(list))
|
||||
{
|
||||
inst = (fluid_inst_t *)fluid_list_get(list);
|
||||
fmt("- instrument: %d", inst->source_idx);
|
||||
indent();
|
||||
dump_inst(inst);
|
||||
outdent();
|
||||
fmt("");
|
||||
}
|
||||
|
||||
delete_fluid_list(inst_list);
|
||||
|
||||
fmt("samples:");
|
||||
for (i = 0, list = defsfont->sample; list; list = fluid_list_next(list), i++)
|
||||
{
|
||||
sample = (fluid_sample_t *)fluid_list_get(list);
|
||||
fmt("- sample: %d", i);
|
||||
if (sample == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
indent();
|
||||
dump_sample(sample);
|
||||
outdent();
|
||||
fmt("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fmt(const char *format, ...)
|
||||
{
|
||||
char buf[FMT_BUFSIZE];
|
||||
va_list args;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
va_start(args, format);
|
||||
len = FLUID_VSNPRINTF(buf, FMT_BUFSIZE, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "max buffer size exceeded");
|
||||
return;
|
||||
}
|
||||
|
||||
buf[FMT_BUFSIZE - 1] = '\0';
|
||||
|
||||
for (i = 0; i < indent_level; i++)
|
||||
{
|
||||
fprintf(output, " ");
|
||||
}
|
||||
|
||||
fwrite(buf, 1, FLUID_STRLEN(buf), output);
|
||||
fprintf(output, "\n");
|
||||
}
|
||||
|
||||
static void indent(void)
|
||||
{
|
||||
indent_level += 1;
|
||||
}
|
||||
|
||||
static void outdent(void)
|
||||
{
|
||||
if (indent_level > 0)
|
||||
{
|
||||
indent_level -= 1;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue