From ba9092ef98e300d9c93b84c4c8dc99db622d267c Mon Sep 17 00:00:00 2001 From: jjceresa <32781294+jjceresa@users.noreply.github.com> Date: Sun, 2 Dec 2018 17:42:51 +0100 Subject: [PATCH 1/9] Reducing defsfont loader code (#480) --- src/sfloader/fluid_defsfont.c | 634 +++++++++++----------------------- 1 file changed, 210 insertions(+), 424 deletions(-) diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 6e19eb71..1931d4ee 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -1105,24 +1105,30 @@ new_fluid_preset_zone(char *name) } /* - * delete_fluid_preset_zone + * delete list of modulators. */ -void -delete_fluid_preset_zone(fluid_preset_zone_t *zone) +static void delete_fluid_list_mod(fluid_mod_t *mod) { - fluid_mod_t *mod, *tmp; - fluid_list_t *list; - - fluid_return_if_fail(zone != NULL); - - mod = zone->mod; - + fluid_mod_t *tmp; while(mod) /* delete the modulators */ { tmp = mod; mod = mod->next; delete_fluid_mod(tmp); } +} + +/* + * delete_fluid_preset_zone + */ +void +delete_fluid_preset_zone(fluid_preset_zone_t *zone) +{ + fluid_list_t *list; + + fluid_return_if_fail(zone != NULL); + + delete_fluid_list_mod(zone->mod); for(list = zone->voice_zone; list != NULL; list = fluid_list_next(list)) { @@ -1187,52 +1193,226 @@ static int fluid_preset_zone_create_voice_zones(fluid_preset_zone_t *preset_zone } /* - * fluid_preset_zone_import_sfont + * fluid_zone_gen_import_sfont + * Imports generators from sfzone to gen and range. + * @param gen, pointer on destination generators table. + * @param range, pointer on destination range generators. + * @param sfzone, pointer on soundfont zone generators. */ -int -fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defsfont) +static void +fluid_zone_gen_import_sfont(fluid_gen_t *gen, fluid_zone_range_t *range, SFZone *sfzone) { fluid_list_t *r; SFGen *sfgen; - SFInst *sfinst; - int count; - for(count = 0, r = sfzone->gen; r != NULL; count++) + for( r = sfzone->gen; r != NULL; ) { sfgen = (SFGen *)fluid_list_get(r); switch(sfgen->id) { case GEN_KEYRANGE: - zone->range.keylo = sfgen->amount.range.lo; - zone->range.keyhi = sfgen->amount.range.hi; + range->keylo = sfgen->amount.range.lo; + range->keyhi = sfgen->amount.range.hi; break; case GEN_VELRANGE: - zone->range.vello = sfgen->amount.range.lo; - zone->range.velhi = sfgen->amount.range.hi; + range->vello = sfgen->amount.range.lo; + range->velhi = sfgen->amount.range.hi; break; case GEN_ATTENUATION: /* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at * preset and instrument level */ - zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; - zone->gen[sfgen->id].flags = GEN_SET; + gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; + gen[sfgen->id].flags = GEN_SET; break; default: /* FIXME: some generators have an unsigne word amount value but i don't know which ones */ - zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; - zone->gen[sfgen->id].flags = GEN_SET; + gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; + gen[sfgen->id].flags = GEN_SET; break; } r = fluid_list_next(r); } +} + +/* + * fluid_zone_mod_source_import_sfont + * Imports source information from sf_source to src and flags. + * @param src, pointer on destination modulator source. + * @param flags, pointer on destination modulator flags. + * @param sf_source, soundfont modulator source. + * @return return TRUE if success, FALSE if source type is unknow. + */ +static int +fluid_zone_mod_source_import_sfont(unsigned char *src, unsigned char *flags, unsigned short sf_source) +{ + int type; + unsigned char flags_dest; /* destination flags */ + + /* sources */ + *src = sf_source & 127; /* index of source, seven-bit value, SF2.01 section 8.2, page 50 */ + + /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ + flags_dest = 0; + if(sf_source & (1 << 7)) + { + flags_dest |= FLUID_MOD_CC; + } + else + { + flags_dest |= FLUID_MOD_GC; + } + + /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ + if(sf_source & (1 << 8)) + { + flags_dest |= FLUID_MOD_NEGATIVE; + } + else + { + flags_dest |= FLUID_MOD_POSITIVE; + } + + /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ + if(sf_source & (1 << 9)) + { + flags_dest |= FLUID_MOD_BIPOLAR; + } + else + { + flags_dest |= FLUID_MOD_UNIPOLAR; + } + + /* modulator source types: SF2.01 section 8.2.1 page 52 */ + type = sf_source >> 10; + type &= 63; /* type is a 6-bit value */ + + if(type == 0) + { + flags_dest |= FLUID_MOD_LINEAR; + } + else if(type == 1) + { + flags_dest |= FLUID_MOD_CONCAVE; + } + else if(type == 2) + { + flags_dest |= FLUID_MOD_CONVEX; + } + else if(type == 3) + { + flags_dest |= FLUID_MOD_SWITCH; + } + else + { + *flags = flags_dest; + /* This shouldn't happen - unknown type! */ + return FALSE; + } + *flags = flags_dest; + return TRUE; +} + +/* + * fluid_zone_mod_import_sfont + * Imports modulators from sfzone to mod list. + * @param mod, pointer on modulator list to return. + * @param sfzone, pointer on soundfont zone. + * @return FLUID_OK if success, FLUID_FAILED otherwise. + */ +static int +fluid_zone_mod_import_sfont(fluid_mod_t **mod, SFZone *sfzone) +{ + fluid_list_t *r; + int count; + + /* Import the modulators (only SF2.1 and higher) */ + for(count = 0, r = sfzone->mod; r != NULL; count++) + { + + SFMod *mod_src = (SFMod *)fluid_list_get(r); + fluid_mod_t *mod_dest = new_fluid_mod(); + + if(mod_dest == NULL) + { + return FLUID_FAILED; + } + + mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ + + /* *** Amount *** */ + mod_dest->amount = mod_src->amount; + + /* *** Source *** */ + if(!fluid_zone_mod_source_import_sfont(&mod_dest->src1, &mod_dest->flags1, mod_src->src)) + { + /* This shouldn't happen - unknown type! + * Deactivate the modulator by setting the amount to 0. */ + mod_dest->amount = 0; + } + /* *** Dest *** */ + mod_dest->dest = mod_src->dest; /* index of controlled generator */ + + /* *** Amount source *** */ + if(!fluid_zone_mod_source_import_sfont(&mod_dest->src2, &mod_dest->flags2, mod_src->amtsrc)) + { + /* This shouldn't happen - unknown type! + * Deactivate the modulator by setting the amount to 0. */ + mod_dest->amount = 0; + } + + /* *** Transform *** */ + /* SF2.01 only uses the 'linear' transform (0). + * Deactivate the modulator by setting the amount to 0 in any other case. + */ + if(mod_src->trans != 0) + { + mod_dest->amount = 0; + } + + /* Store the new modulator in the zone The order of modulators + * will make a difference, at least in an instrument context: The + * second modulator overwrites the first one, if they only differ + * in amount. */ + if(count == 0) + { + *mod = mod_dest; + } + else + { + fluid_mod_t *last_mod = *mod; + + /* Find the end of the list */ + while(last_mod->next != NULL) + { + last_mod = last_mod->next; + } + + last_mod->next = mod_dest; + } + + r = fluid_list_next(r); + } /* foreach modulator */ + + return FLUID_OK; +} + +/* + * fluid_preset_zone_import_sfont + */ +int +fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defsfont) +{ + /* import the generators */ + fluid_zone_gen_import_sfont(zone->gen, &zone->range, sfzone); if((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) { - sfinst = sfzone->instsamp->data; + SFInst *sfinst = sfzone->instsamp->data; zone->inst = find_inst_by_idx(defsfont, sfinst->idx); @@ -1253,182 +1433,7 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_ } /* Import the modulators (only SF2.1 and higher) */ - for(count = 0, r = sfzone->mod; r != NULL; count++) - { - - SFMod *mod_src = (SFMod *)fluid_list_get(r); - fluid_mod_t *mod_dest = new_fluid_mod(); - int type; - - if(mod_dest == NULL) - { - return FLUID_FAILED; - } - - mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ - - /* *** Amount *** */ - mod_dest->amount = mod_src->amount; - - /* *** Source *** */ - mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */ - mod_dest->flags1 = 0; - - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if(mod_src->src & (1 << 7)) - { - mod_dest->flags1 |= FLUID_MOD_CC; - } - else - { - mod_dest->flags1 |= FLUID_MOD_GC; - } - - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if(mod_src->src & (1 << 8)) - { - mod_dest->flags1 |= FLUID_MOD_NEGATIVE; - } - else - { - mod_dest->flags1 |= FLUID_MOD_POSITIVE; - } - - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if(mod_src->src & (1 << 9)) - { - mod_dest->flags1 |= FLUID_MOD_BIPOLAR; - } - else - { - mod_dest->flags1 |= FLUID_MOD_UNIPOLAR; - } - - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type = (mod_src->src) >> 10; - type &= 63; /* type is a 6-bit value */ - - if(type == 0) - { - mod_dest->flags1 |= FLUID_MOD_LINEAR; - } - else if(type == 1) - { - mod_dest->flags1 |= FLUID_MOD_CONCAVE; - } - else if(type == 2) - { - mod_dest->flags1 |= FLUID_MOD_CONVEX; - } - else if(type == 3) - { - mod_dest->flags1 |= FLUID_MOD_SWITCH; - } - else - { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount = 0; - } - - /* *** Dest *** */ - mod_dest->dest = mod_src->dest; /* index of controlled generator */ - - /* *** Amount source *** */ - mod_dest->src2 = mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, p.50 */ - mod_dest->flags2 = 0; - - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if(mod_src->amtsrc & (1 << 7)) - { - mod_dest->flags2 |= FLUID_MOD_CC; - } - else - { - mod_dest->flags2 |= FLUID_MOD_GC; - } - - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if(mod_src->amtsrc & (1 << 8)) - { - mod_dest->flags2 |= FLUID_MOD_NEGATIVE; - } - else - { - mod_dest->flags2 |= FLUID_MOD_POSITIVE; - } - - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if(mod_src->amtsrc & (1 << 9)) - { - mod_dest->flags2 |= FLUID_MOD_BIPOLAR; - } - else - { - mod_dest->flags2 |= FLUID_MOD_UNIPOLAR; - } - - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type = (mod_src->amtsrc) >> 10; - type &= 63; /* type is a 6-bit value */ - - if(type == 0) - { - mod_dest->flags2 |= FLUID_MOD_LINEAR; - } - else if(type == 1) - { - mod_dest->flags2 |= FLUID_MOD_CONCAVE; - } - else if(type == 2) - { - mod_dest->flags2 |= FLUID_MOD_CONVEX; - } - else if(type == 3) - { - mod_dest->flags2 |= FLUID_MOD_SWITCH; - } - else - { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount = 0; - } - - /* *** Transform *** */ - /* SF2.01 only uses the 'linear' transform (0). - * Deactivate the modulator by setting the amount to 0 in any other case. - */ - if(mod_src->trans != 0) - { - mod_dest->amount = 0; - } - - /* Store the new modulator in the zone The order of modulators - * will make a difference, at least in an instrument context: The - * second modulator overwrites the first one, if they only differ - * in amount. */ - if(count == 0) - { - zone->mod = mod_dest; - } - else - { - fluid_mod_t *last_mod = zone->mod; - - /* Find the end of the list */ - while(last_mod->next != NULL) - { - last_mod = last_mod->next; - } - - last_mod->next = mod_dest; - } - - r = fluid_list_next(r); - } /* foreach modulator */ - - return FLUID_OK; + return fluid_zone_mod_import_sfont(&zone->mod, sfzone); } /* @@ -1661,18 +1666,9 @@ new_fluid_inst_zone(char *name) void delete_fluid_inst_zone(fluid_inst_zone_t *zone) { - fluid_mod_t *mod, *tmp; - fluid_return_if_fail(zone != NULL); - mod = zone->mod; - - while(mod) /* delete the modulators */ - { - tmp = mod; - mod = mod->next; - delete_fluid_mod(tmp); - } + delete_fluid_list_mod(zone->mod); FLUID_FREE(zone->name); FLUID_FREE(zone); @@ -1693,43 +1689,8 @@ fluid_inst_zone_next(fluid_inst_zone_t *zone) int fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont) { - fluid_list_t *r; - SFGen *sfgen; - int count; - - for(count = 0, r = sfzone->gen; r != NULL; count++) - { - sfgen = (SFGen *)fluid_list_get(r); - - switch(sfgen->id) - { - case GEN_KEYRANGE: - inst_zone->range.keylo = sfgen->amount.range.lo; - inst_zone->range.keyhi = sfgen->amount.range.hi; - break; - - case GEN_VELRANGE: - inst_zone->range.vello = sfgen->amount.range.lo; - inst_zone->range.velhi = sfgen->amount.range.hi; - break; - - case GEN_ATTENUATION: - /* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at - * preset and instrument level */ - inst_zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword * EMU_ATTENUATION_FACTOR; - inst_zone->gen[sfgen->id].flags = GEN_SET; - break; - - default: - /* FIXME: some generators have an unsigned word amount value but - i don't know which ones */ - inst_zone->gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; - inst_zone->gen[sfgen->id].flags = GEN_SET; - break; - } - - r = fluid_list_next(r); - } + /* import the generators */ + fluid_zone_gen_import_sfont(inst_zone->gen, &inst_zone->range, sfzone); /* FIXME */ /* if (zone->gen[GEN_EXCLUSIVECLASS].flags == GEN_SET) { */ @@ -1743,182 +1704,7 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid } /* Import the modulators (only SF2.1 and higher) */ - for(count = 0, r = sfzone->mod; r != NULL; count++) - { - SFMod *mod_src = (SFMod *)fluid_list_get(r); - int type; - fluid_mod_t *mod_dest; - - mod_dest = new_fluid_mod(); - - if(mod_dest == NULL) - { - return FLUID_FAILED; - } - - mod_dest->next = NULL; /* pointer to next modulator, this is the end of the list now.*/ - - /* *** Amount *** */ - mod_dest->amount = mod_src->amount; - - /* *** Source *** */ - mod_dest->src1 = mod_src->src & 127; /* index of source 1, seven-bit value, SF2.01 section 8.2, page 50 */ - mod_dest->flags1 = 0; - - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if(mod_src->src & (1 << 7)) - { - mod_dest->flags1 |= FLUID_MOD_CC; - } - else - { - mod_dest->flags1 |= FLUID_MOD_GC; - } - - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if(mod_src->src & (1 << 8)) - { - mod_dest->flags1 |= FLUID_MOD_NEGATIVE; - } - else - { - mod_dest->flags1 |= FLUID_MOD_POSITIVE; - } - - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if(mod_src->src & (1 << 9)) - { - mod_dest->flags1 |= FLUID_MOD_BIPOLAR; - } - else - { - mod_dest->flags1 |= FLUID_MOD_UNIPOLAR; - } - - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type = (mod_src->src) >> 10; - type &= 63; /* type is a 6-bit value */ - - if(type == 0) - { - mod_dest->flags1 |= FLUID_MOD_LINEAR; - } - else if(type == 1) - { - mod_dest->flags1 |= FLUID_MOD_CONCAVE; - } - else if(type == 2) - { - mod_dest->flags1 |= FLUID_MOD_CONVEX; - } - else if(type == 3) - { - mod_dest->flags1 |= FLUID_MOD_SWITCH; - } - else - { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount = 0; - } - - /* *** Dest *** */ - mod_dest->dest = mod_src->dest; /* index of controlled generator */ - - /* *** Amount source *** */ - mod_dest->src2 = mod_src->amtsrc & 127; /* index of source 2, seven-bit value, SF2.01 section 8.2, page 50 */ - mod_dest->flags2 = 0; - - /* Bit 7: CC flag SF 2.01 section 8.2.1 page 50*/ - if(mod_src->amtsrc & (1 << 7)) - { - mod_dest->flags2 |= FLUID_MOD_CC; - } - else - { - mod_dest->flags2 |= FLUID_MOD_GC; - } - - /* Bit 8: D flag SF 2.01 section 8.2.2 page 51*/ - if(mod_src->amtsrc & (1 << 8)) - { - mod_dest->flags2 |= FLUID_MOD_NEGATIVE; - } - else - { - mod_dest->flags2 |= FLUID_MOD_POSITIVE; - } - - /* Bit 9: P flag SF 2.01 section 8.2.3 page 51*/ - if(mod_src->amtsrc & (1 << 9)) - { - mod_dest->flags2 |= FLUID_MOD_BIPOLAR; - } - else - { - mod_dest->flags2 |= FLUID_MOD_UNIPOLAR; - } - - /* modulator source types: SF2.01 section 8.2.1 page 52 */ - type = (mod_src->amtsrc) >> 10; - type &= 63; /* type is a 6-bit value */ - - if(type == 0) - { - mod_dest->flags2 |= FLUID_MOD_LINEAR; - } - else if(type == 1) - { - mod_dest->flags2 |= FLUID_MOD_CONCAVE; - } - else if(type == 2) - { - mod_dest->flags2 |= FLUID_MOD_CONVEX; - } - else if(type == 3) - { - mod_dest->flags2 |= FLUID_MOD_SWITCH; - } - else - { - /* This shouldn't happen - unknown type! - * Deactivate the modulator by setting the amount to 0. */ - mod_dest->amount = 0; - } - - /* *** Transform *** */ - /* SF2.01 only uses the 'linear' transform (0). - * Deactivate the modulator by setting the amount to 0 in any other case. - */ - if(mod_src->trans != 0) - { - mod_dest->amount = 0; - } - - /* Store the new modulator in the zone - * The order of modulators will make a difference, at least in an instrument context: - * The second modulator overwrites the first one, if they only differ in amount. */ - if(count == 0) - { - inst_zone->mod = mod_dest; - } - else - { - fluid_mod_t *last_mod = inst_zone->mod; - - /* Find the end of the list */ - while(last_mod->next != NULL) - { - last_mod = last_mod->next; - } - - last_mod->next = mod_dest; - } - - r = fluid_list_next(r); - } /* foreach modulator */ - - return FLUID_OK; + return fluid_zone_mod_import_sfont(&inst_zone->mod, sfzone); } /* From dde52c35ddda5f6e8b23e0613a0d168a8d8e3c2c Mon Sep 17 00:00:00 2001 From: derselbst Date: Sun, 9 Dec 2018 10:35:21 +0100 Subject: [PATCH 2/9] update test_sfont_loading to call fluid_is_soundfont() --- test/test_sfont_loading.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_sfont_loading.c b/test/test_sfont_loading.c index 9f63b0c6..9cac3d07 100644 --- a/test/test_sfont_loading.c +++ b/test/test_sfont_loading.c @@ -21,6 +21,8 @@ int main(void) // no sfont loaded TEST_ASSERT(fluid_synth_sfcount(synth) == 0); + TEST_ASSERT(fluid_is_soundfont(TEST_SOUNDFONT) == TRUE); + // load a sfont to synth TEST_SUCCESS(id = fluid_synth_sfload(synth, TEST_SOUNDFONT, 1)); // one sfont loaded From 73689925da8d33c9ec73d5ead39db5535fe96022 Mon Sep 17 00:00:00 2001 From: derselbst Date: Sat, 1 Dec 2018 13:56:51 +0100 Subject: [PATCH 3/9] disable clang-tidy for normal builds It may cause errors when cross compiling. Keep it for profiling builds though. Fixes #475. --- CMakeLists.txt | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 298199dc..a0445467 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -342,6 +342,18 @@ if ( enable-profiling ) endif ( ) set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OPT_FLAGS}" ) + + if ( CMAKE_VERSION VERSION_GREATER "3.6.0" ) + find_program( CLANG_TIDY + NAMES "clang-tidy" + DOC "Path to clang-tidy executable" ) + + if ( CLANG_TIDY ) + message ( STATUS "Found clang-tidy" ) + set ( CMAKE_C_CLANG_TIDY "clang-tidy" ) + endif ( CLANG_TIDY ) + endif ( CMAKE_VERSION VERSION_GREATER "3.6.0" ) + endif ( enable-profiling ) unset ( ENABLE_TRAPONFPE CACHE ) @@ -375,22 +387,6 @@ if ( CMAKE_BUILD_TYPE MATCHES "Debug" ) set ( DEBUG 1 ) endif ( CMAKE_BUILD_TYPE MATCHES "Debug" ) -if ( CMAKE_VERSION VERSION_GREATER "3.6.0" ) -find_program( CLANG_TIDY - NAMES "clang-tidy" - DOC "Path to clang-tidy executable" ) - - if ( CLANG_TIDY ) - message ( STATUS "Found clang-tidy" ) - # whenever clang-tidy is available, use it to automatically add braces after ever "make" - if ( WITH_PROFILING ) - set ( CMAKE_C_CLANG_TIDY "clang-tidy" ) - else ( WITH_PROFILING ) - set ( CMAKE_C_CLANG_TIDY "clang-tidy;-checks=-*,readability-braces-*;-format-style=file" ) - endif ( WITH_PROFILING ) - endif ( CLANG_TIDY ) -endif ( CMAKE_VERSION VERSION_GREATER "3.6.0" ) - # Additional targets to perform clang-format/clang-tidy # Get all project files file(GLOB_RECURSE From cb485806c3cfdb4b09e670c2a5a925bed26afae1 Mon Sep 17 00:00:00 2001 From: derselbst Date: Sat, 1 Dec 2018 14:03:34 +0100 Subject: [PATCH 4/9] remove unused io.h include --- CMakeLists.txt | 1 - src/config.cmake | 3 --- src/utils/fluidsynth_priv.h | 4 ---- 3 files changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0445467..d1fa324f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,7 +201,6 @@ if ( WIN32 ) # Check presence of MS include files check_include_file ( windows.h HAVE_WINDOWS_H ) - check_include_file ( io.h HAVE_IO_H ) check_include_file ( dsound.h HAVE_DSOUND_H ) check_include_files ( "windows.h;mmsystem.h" HAVE_MMSYSTEM_H ) diff --git a/src/config.cmake b/src/config.cmake index 2d1d786b..ae7c7dbe 100644 --- a/src/config.cmake +++ b/src/config.cmake @@ -43,9 +43,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@ -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_IO_H @HAVE_IO_H@ - /* whether or not we are supporting lash */ #cmakedefine HAVE_LASH @HAVE_LASH@ diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h index d5dbdf7e..79446925 100644 --- a/src/utils/fluidsynth_priv.h +++ b/src/utils/fluidsynth_priv.h @@ -106,10 +106,6 @@ #include #endif -#if HAVE_IO_H -#include -#endif - #if HAVE_SIGNAL_H #include #endif From 4f1f7349dbbd7be8ea55d2451318b09991fdabe6 Mon Sep 17 00:00:00 2001 From: derselbst Date: Fri, 14 Dec 2018 17:47:44 +0100 Subject: [PATCH 5/9] fix cmake not finding make_tables when cross-compiling Fixes #477. --- src/CMakeLists.txt | 2 +- src/gentables/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cf8f3369..a0ba53d1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -367,6 +367,6 @@ ExternalProject_Add(gentables DOWNLOAD_COMMAND "" SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/gentables BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/gentables - INSTALL_COMMAND ${CMAKE_CURRENT_BINARY_DIR}/gentables/make_tables${CMAKE_EXECUTABLE_SUFFIX} "${CMAKE_BINARY_DIR}/" + INSTALL_COMMAND ${CMAKE_CURRENT_BINARY_DIR}/gentables/make_tables.exe "${CMAKE_BINARY_DIR}/" ) add_dependencies(libfluidsynth-OBJ gentables) diff --git a/src/gentables/CMakeLists.txt b/src/gentables/CMakeLists.txt index 437027ae..64ec7b44 100644 --- a/src/gentables/CMakeLists.txt +++ b/src/gentables/CMakeLists.txt @@ -8,6 +8,9 @@ project (gentables C) set ( CMAKE_BUILD_TYPE Debug ) +# hardcode ".exe" as suffix to the binary, else in case of cross-platform cross-compiling the calling cmake will not know the suffix used here and fail to find the binary +set ( CMAKE_EXECUTABLE_SUFFIX ".exe" ) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}) From a9662bf331316807e4bc42e94906a4c53f21f4b3 Mon Sep 17 00:00:00 2001 From: derselbst Date: Fri, 14 Dec 2018 19:42:08 +0100 Subject: [PATCH 6/9] fix gcc8 complaining about stringop-truncation --- src/synth/fluid_synth.c | 5 +++-- src/utils/fluidsynth_priv.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/synth/fluid_synth.c b/src/synth/fluid_synth.c index faadefb2..15e167a1 100644 --- a/src/synth/fluid_synth.c +++ b/src/synth/fluid_synth.c @@ -1902,7 +1902,7 @@ fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len, int bank = 0, prog, channels; double tunedata[128]; int keys[128]; - char name[17]; + char name[17]={0}; int note, frac, frac2; uint8_t chksum; int i, count, index; @@ -1973,7 +1973,8 @@ fluid_synth_sysex_midi_tuning(fluid_synth_t *synth, const char *data, int len, } *resptr++ = prog; - FLUID_STRNCPY(resptr, name, 16); + /* copy 16 ASCII characters (potentially not null terminated) to the sysex buffer */ + FLUID_MEMCPY(resptr, name, 16); resptr += 16; for(i = 0; i < 128; i++) diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h index 79446925..c7ddf546 100644 --- a/src/utils/fluidsynth_priv.h +++ b/src/utils/fluidsynth_priv.h @@ -261,7 +261,7 @@ typedef FILE *fluid_file; #define FLUID_STRNCPY(_dst,_src,_n) \ do { strncpy(_dst,_src,_n); \ - (_dst)[(_n)-1]=0; \ + (_dst)[(_n)-1]='\0'; \ }while(0) #define FLUID_STRCHR(_s,_c) strchr(_s,_c) From b7af84fbd5eece8b93ced75629dfef192ff1e34b Mon Sep 17 00:00:00 2001 From: jjceresa <32781294+jjceresa@users.noreply.github.com> Date: Wed, 19 Dec 2018 14:07:34 +0100 Subject: [PATCH 7/9] optimizing fluid_voice_modulate() (#486) This avoids recalculation of the same generator when several modulators have that generator as destination. --- src/synth/fluid_voice.c | 63 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/synth/fluid_voice.c b/src/synth/fluid_voice.c index 38b4bfe6..66337175 100644 --- a/src/synth/fluid_voice.c +++ b/src/synth/fluid_voice.c @@ -1162,24 +1162,23 @@ fluid_voice_update_param(fluid_voice_t *voice, int gen) * iteration of the audio cycle (which would probably be feasible if * the synth was made in silicon). * - * The update is done in three steps: + * The update is done in two steps: * * - step 1: first, we look for all the modulators that have the changed - * controller as a source. This will yield a list of generators that - * will be changed because of the controller event. + * controller as a source. This will yield a generator that will be changed + * because of the controller event. * - * - step 2: For every changed generator, calculate its new value. This is the + * - step 2: For this generator, calculate its new value. This is the * sum of its original value plus the values of all the attached modulators. * The generator flag is set to indicate the parameters must be updated. - * - * - step 3: We need to avoid the risk to call 'fluid_voice_update_param' several + * This avoid the risk to call 'fluid_voice_update_param' several * times for the same generator if several modulators have that generator as - * destination. So every changed generators are updated only once + * destination. So every changed generators are updated only once. */ /* bit table for each generator being updated. The bits are packed in variables Each variable have NBR_BIT_BY_VAR bits represented by NBR_BIT_BY_VAR_LN2. - The size of the table is the number of variables: SIZE_UPDATED_GEN. + The size of the table is the number of variables: SIZE_UPDATED_GEN_BIT. Note: In this implementation NBR_BIT_BY_VAR_LN2 is set to 5 (convenient for 32 bits cpu) but this could be set to 6 for 64 bits cpu. @@ -1200,7 +1199,7 @@ int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl) uint32_t gen; fluid_real_t modval; - /* registered bits table of updated generators */ + /* Clears registered bits table of updated generators */ uint32_t updated_gen_bit[SIZE_UPDATED_GEN_BIT] = {0}; /* printf("Chan=%d, CC=%d, Src=%d, Val=%d\n", voice->channel->channum, cc, ctrl, val); */ @@ -1210,36 +1209,36 @@ int fluid_voice_modulate(fluid_voice_t *voice, int cc, int ctrl) mod = &voice->mod[i]; /* step 1: find all the modulators that have the changed controller - as input source. When ctrl is -1 all modulators's destination + as input source. When ctrl is -1 all modulators destination are updated */ if(ctrl < 0 || fluid_mod_has_source(mod, cc, ctrl)) { gen = fluid_mod_get_dest(mod); - modval = 0.0; - /* step 2: for every changed modulator, calculate the modulation - * value of its associated generator */ - for(k = 0; k < voice->mod_count; k++) + /* Skip if this generator has already been updated */ + if(!is_gen_updated(updated_gen_bit, gen)) { - if(fluid_mod_has_dest(&voice->mod[k], gen)) - { - modval += fluid_mod_get_value(&voice->mod[k], voice); - } - } + modval = 0.0; - fluid_gen_set_mod(&voice->gen[gen], modval); - /* set the bit that indicates this generator is updated */ - set_gen_updated(updated_gen_bit, gen); - } - } - - /* step 3: now recalculate the parameter values that are derived from the - generator */ - for(gen = 0; gen < GEN_LAST; gen++) - { - if (is_gen_updated(updated_gen_bit, gen)) - { - fluid_voice_update_param(voice, gen); + /* step 2: for every attached modulator, calculate the modulation + * value for the generator gen */ + for(k = 0; k < voice->mod_count; k++) + { + if(fluid_mod_has_dest(&voice->mod[k], gen)) + { + modval += fluid_mod_get_value(&voice->mod[k], voice); + } + } + + fluid_gen_set_mod(&voice->gen[gen], modval); + + /* now recalculate the parameter values that are derived from the + generator */ + fluid_voice_update_param(voice, gen); + + /* set the bit that indicates this generator is updated */ + set_gen_updated(updated_gen_bit, gen); + } } } From c9b8d40fc25bcaacae5ac8a18fccec5f9269e79a Mon Sep 17 00:00:00 2001 From: carlo-bramini <30959007+carlo-bramini@users.noreply.github.com> Date: Wed, 19 Dec 2018 14:09:29 +0100 Subject: [PATCH 8/9] Fourcc support (#482) Have a direct comparison to the fourcc code rather than searching through chunk ids all the time with chunkid() --- src/midi/fluid_midi.c | 37 ++++- src/sfloader/fluid_sffile.c | 263 +++++++++++++++++++++--------------- src/utils/fluid_sys.c | 65 --------- src/utils/fluid_sys.h | 8 ++ 4 files changed, 199 insertions(+), 174 deletions(-) diff --git a/src/midi/fluid_midi.c b/src/midi/fluid_midi.c index 4795fceb..f672124c 100644 --- a/src/midi/fluid_midi.c +++ b/src/midi/fluid_midi.c @@ -81,6 +81,41 @@ static int fluid_midi_file_get_division(fluid_midi_file *midifile); * MIDIFILE */ +/** + * Check if a file is a MIDI file. + * @param filename Path to the file to check + * @return TRUE if it could be a MIDI file, FALSE otherwise + * + * The current implementation only checks for the "MThd" header in the file. + * It is useful only to distinguish between SoundFont and MIDI files. + */ +int fluid_is_midifile(const char *filename) +{ + FILE *fp = FLUID_FOPEN(filename, "rb"); + uint32_t id; + int retcode = 0; + + do + { + if(fp == NULL) + { + break; + } + + if(FLUID_FREAD(&id, sizeof(id), 1, fp) != 1) + { + break; + } + + retcode = (id == FLUID_FOURCC('M', 'T', 'h', 'd')); + } + while(0); + + FLUID_FCLOSE(fp); + + return retcode; +} + /** * Return a new MIDI file handle for parsing an already-loaded MIDI file. * @internal @@ -1597,7 +1632,7 @@ new_fluid_player(fluid_synth_t *synth) fluid_settings_getint(synth->settings, "player.reset-synth", &i); fluid_player_handle_reset_synth(player, NULL, i); - + fluid_settings_callback_int(synth->settings, "player.reset-synth", fluid_player_handle_reset_synth, player); diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index f9382b10..0725e1f3 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -34,76 +34,79 @@ Borrowed from Smurf SoundFont Editor by Josh Green =================================================================*/ -/* - functions for loading data from sfont files, with appropriate byte swapping - on big endian machines. Sfont IDs are not swapped because the ID read is - equivalent to the matching ID list in memory regardless of LE/BE machine -*/ +/* FOURCC definitions */ +#define RIFF_FCC FLUID_FOURCC('R','I','F','F') +#define LIST_FCC FLUID_FOURCC('L','I','S','T') +#define SFBK_FCC FLUID_FOURCC('s','f','b','k') +#define INFO_FCC FLUID_FOURCC('I','N','F','O') +#define SDTA_FCC FLUID_FOURCC('s','d','t','a') +#define PDTA_FCC FLUID_FOURCC('p','d','t','a') /* info/sample/preset */ -/* sf file chunk IDs */ -enum -{ - RIFF_ID, - LIST_ID, - SFBK_ID, - INFO_ID, - SDTA_ID, - PDTA_ID, /* info/sample/preset */ +#define IFIL_FCC FLUID_FOURCC('i','f','i','l') +#define ISNG_FCC FLUID_FOURCC('i','s','n','g') +#define INAM_FCC FLUID_FOURCC('I','N','A','M') +#define IROM_FCC FLUID_FOURCC('i','r','o','m') /* info ids (1st byte of info strings) */ +#define IVER_FCC FLUID_FOURCC('i','v','e','r') +#define ICRD_FCC FLUID_FOURCC('I','C','R','D') +#define IENG_FCC FLUID_FOURCC('I','E','N','G') +#define IPRD_FCC FLUID_FOURCC('I','P','R','D') /* more info ids */ +#define ICOP_FCC FLUID_FOURCC('I','C','O','P') +#define ICMT_FCC FLUID_FOURCC('I','C','M','T') +#define ISFT_FCC FLUID_FOURCC('I','S','F','T') /* and yet more info ids */ - IFIL_ID, - ISNG_ID, - INAM_ID, - IROM_ID, /* info ids (1st byte of info strings) */ - IVER_ID, - ICRD_ID, - IENG_ID, - IPRD_ID, /* more info ids */ - ICOP_ID, - ICMT_ID, - ISFT_ID, /* and yet more info ids */ +#define SNAM_FCC FLUID_FOURCC('s','n','a','m') +#define SMPL_FCC FLUID_FOURCC('s','m','p','l') /* sample ids */ +#define PHDR_FCC FLUID_FOURCC('p','h','d','r') +#define PBAG_FCC FLUID_FOURCC('p','b','a','g') +#define PMOD_FCC FLUID_FOURCC('p','m','o','d') +#define PGEN_FCC FLUID_FOURCC('p','g','e','n') /* preset ids */ +#define IHDR_FCC FLUID_FOURCC('i','n','s','t') +#define IBAG_FCC FLUID_FOURCC('i','b','a','g') +#define IMOD_FCC FLUID_FOURCC('i','m','o','d') +#define IGEN_FCC FLUID_FOURCC('i','g','e','n') /* instrument ids */ +#define SHDR_FCC FLUID_FOURCC('s','h','d','r') /* sample info */ +#define SM24_FCC FLUID_FOURCC('s','m','2','4') - SNAM_ID, - SMPL_ID, /* sample ids */ - PHDR_ID, - PBAG_ID, - PMOD_ID, - PGEN_ID, /* preset ids */ - IHDR_ID, - IBAG_ID, - IMOD_ID, - IGEN_ID, /* instrument ids */ - SHDR_ID, /* sample info */ - SM24_ID, - - UNKN_ID -}; +/* Set when the FCC code is unknown */ +#define UNKN_ID FLUID_N_ELEMENTS(idlist) /* - * This declares a char array containing the SF2 chunk identifiers. This - * array is being accessed like an uint32 below to simplify id comparison. - * To make sure it is suitably aligned for uint32 access, we must wrap it - * inside a union along with a uint32 telling the compiler to align it - * for integer access and avoiding undefined behaviour. - * This basically is the C89 equivalent to what is written in C11 as: - * alignas(uint32_t) static const char idlist[] = {}; - * - * See: EXP36-C. Do not cast pointers into more strictly aligned pointer - * types - SEI CERT C Coding Standard + * This declares a uint32_t array containing the SF2 chunk identifiers. */ -static const union fluid_idlist +static const uint32_t idlist[] = { - /* - * Cannot be char c[ ], because in C89, arrays wraped in unions - * must have a fixed size. Otherwise the size of the union would depend - * on the initialization of its first member, which results in - * different sizes for different instances of the same union type. - */ - char c[116]; - uint32_t i; -} idlist = {"RIFFLISTsfbkINFOsdtapdtaifilisngINAMiromiverICRDIENGIPRD" - "ICOPICMTISFTsnamsmplphdrpbagpmodpgeninstibagimodigenshdrsm24" - }; + RIFF_FCC, + LIST_FCC, + SFBK_FCC, + INFO_FCC, + SDTA_FCC, + PDTA_FCC, + IFIL_FCC, + ISNG_FCC, + INAM_FCC, + IROM_FCC, + IVER_FCC, + ICRD_FCC, + IENG_FCC, + IPRD_FCC, + ICOP_FCC, + ICMT_FCC, + ISFT_FCC, + + SNAM_FCC, + SMPL_FCC, + PHDR_FCC, + PBAG_FCC, + PMOD_FCC, + PGEN_FCC, + IHDR_FCC, + IBAG_FCC, + IMOD_FCC, + IGEN_FCC, + SHDR_FCC, + SM24_FCC +}; /* generator types */ typedef enum @@ -206,8 +209,6 @@ static const unsigned short invalid_preset_gen[] = }; -#define CHNKIDSTR(id) &idlist.c[(id - 1) * 4] - /* sfont file chunk sizes */ #define SF_PHDR_SIZE (38) #define SF_BAG_SIZE (4) @@ -323,6 +324,56 @@ static void delete_zone(SFZone *zone); static int fluid_sffile_read_vorbis(SFData *sf, unsigned int start_byte, unsigned int end_byte, short **data); static int fluid_sffile_read_wav(SFData *sf, unsigned int start, unsigned int end, short **data, char **data24); +/** + * Check if a file is a SoundFont file. + * @param filename Path to the file to check + * @return TRUE if it could be a SoundFont, FALSE otherwise + * + * @note The current implementation only checks for the "RIFF" and "sfbk" headers in + * the file. It is useful to distinguish between SoundFont and other (e.g. MIDI) files. + */ +int fluid_is_soundfont(const char *filename) +{ + FILE *fp = FLUID_FOPEN(filename, "rb"); + uint32_t fcc; + int retcode = 0; + + do + { + if(fp == NULL) + { + break; + } + + if(FLUID_FREAD(&fcc, sizeof(fcc), 1, fp) != 1) + { + break; + } + + if(fcc != RIFF_FCC) + { + break; + } + + if(FLUID_FSEEK(fp, 4, SEEK_CUR)) + { + break; + } + + if(FLUID_FREAD(&fcc, sizeof(fcc), 1, fp) != 1) + { + break; + } + + retcode = (fcc == SFBK_FCC); + } + while(0); + + FLUID_FCLOSE(fp); + + return retcode; +} + /* * Open a SoundFont file and parse it's contents into a SFData structure. * @@ -512,11 +563,10 @@ void fluid_sffile_close(SFData *sf) static int chunkid(uint32_t id) { unsigned int i; - const uint32_t *p = &idlist.i; - for(i = 0; i < sizeof(idlist) / sizeof(idlist.i); i++, p += 1) + for(i = 0; i < FLUID_N_ELEMENTS(idlist); i++) { - if(*p == id) + if(idlist[i] == id) { break; } @@ -532,7 +582,7 @@ static int load_header(SFData *sf) READCHUNK(sf, &chunk); /* load RIFF chunk */ - if(chunkid(chunk.id) != RIFF_ID) + if(chunk.id != RIFF_FCC) { /* error if not RIFF */ FLUID_LOG(FLUID_ERR, "Not a RIFF file"); @@ -541,7 +591,7 @@ static int load_header(SFData *sf) READID(sf, &chunk.id); /* load file ID */ - if(chunkid(chunk.id) != SFBK_ID) + if(chunk.id != SFBK_FCC) { /* error if not SFBK_ID */ FLUID_LOG(FLUID_ERR, "Not a SoundFont file"); @@ -560,7 +610,7 @@ static int load_header(SFData *sf) return FALSE; } - if(chunkid(chunk.id) != INFO_ID) + if(chunk.id != INFO_FCC) { FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting INFO chunk"); return FALSE; @@ -577,7 +627,7 @@ static int load_header(SFData *sf) return FALSE; } - if(chunkid(chunk.id) != SDTA_ID) + if(chunk.id != SDTA_FCC) { FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting SAMPLE chunk"); return FALSE; @@ -594,7 +644,7 @@ static int load_header(SFData *sf) return FALSE; } - if(chunkid(chunk.id) != PDTA_ID) + if(chunk.id != PDTA_FCC) { FLUID_LOG(FLUID_ERR, "Invalid ID found when expecting HYDRA chunk"); return FALSE; @@ -639,7 +689,7 @@ static int read_listchunk(SFData *sf, SFChunk *chunk) { READCHUNK(sf, chunk); /* read list chunk */ - if(chunkid(chunk->id) != LIST_ID) /* error if ! list chunk */ + if(chunk->id != LIST_FCC) /* error if ! list chunk */ { FLUID_LOG(FLUID_ERR, "Invalid chunk id in level 0 parse"); return FALSE; @@ -653,8 +703,11 @@ static int read_listchunk(SFData *sf, SFChunk *chunk) static int process_info(SFData *sf, int size) { SFChunk chunk; - unsigned char id; - char *item; + union + { + char *chr; + uint32_t *fcc; + } item; unsigned short ver; while(size > 0) @@ -662,9 +715,7 @@ static int process_info(SFData *sf, int size) READCHUNK(sf, &chunk); size -= 8; - id = chunkid(chunk.id); - - if(id == IFIL_ID) + if(chunk.id == IFIL_FCC) { /* sound font version chunk? */ if(chunk.size != 4) @@ -705,7 +756,7 @@ static int process_info(SFData *sf, int size) return FALSE; } } - else if(id == IVER_ID) + else if(chunk.id == IVER_FCC) { /* ROM version chunk? */ if(chunk.size != 4) @@ -719,34 +770,35 @@ static int process_info(SFData *sf, int size) READW(sf, ver); sf->romver.minor = ver; } - else if(id != UNKN_ID) + else if(chunkid(chunk.id) != UNKN_ID) { - if((id != ICMT_ID && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2)) + if((chunk.id != ICMT_FCC && chunk.size > 256) || (chunk.size > 65536) || (chunk.size % 2)) { FLUID_LOG(FLUID_ERR, "INFO sub chunk %.4s has invalid chunk size of %d bytes", &chunk.id, chunk.size); return FALSE; } - /* alloc for chunk id and da chunk */ - if(!(item = FLUID_MALLOC(chunk.size + 1))) + /* alloc for chunk fcc and da chunk */ + if(!(item.fcc = FLUID_MALLOC(chunk.size + sizeof(uint32_t) + 1))) { FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } /* attach to INFO list, fluid_sffile_close will cleanup if FAIL occurs */ - sf->info = fluid_list_append(sf->info, item); + sf->info = fluid_list_append(sf->info, item.fcc); - *(unsigned char *)item = id; + /* save chunk fcc and update pointer to data value */ + *item.fcc++ = chunk.id; - if(sf->fcbs->fread(&item[1], chunk.size, sf->sffd) == FLUID_FAILED) + if(sf->fcbs->fread(item.chr, chunk.size, sf->sffd) == FLUID_FAILED) { return FALSE; } - /* force terminate info item (don't forget uint8 info ID) */ - *(item + chunk.size) = '\0'; + /* force terminate info item */ + item.chr[chunk.size] = '\0'; } else { @@ -779,7 +831,7 @@ static int process_sdta(SFData *sf, unsigned int size) READCHUNK(sf, &chunk); size -= 8; - if(chunkid(chunk.id) != SMPL_ID) + if(chunk.id != SMPL_FCC) { FLUID_LOG(FLUID_ERR, "Expected SMPL chunk found invalid id instead"); return FALSE; @@ -812,7 +864,7 @@ static int process_sdta(SFData *sf, unsigned int size) READCHUNK(sf, &chunk); size -= 8; - if(chunkid(chunk.id) == SM24_ID) + if(chunk.id == SM24_FCC) { int sm24size, sdtahalfsize; @@ -852,29 +904,24 @@ ret: static int pdtahelper(SFData *sf, unsigned int expid, unsigned int reclen, SFChunk *chunk, int *size) { - unsigned int id; - const char *expstr; - - expstr = CHNKIDSTR(expid); /* in case we need it */ - READCHUNK(sf, chunk); *size -= 8; - if((id = chunkid(chunk->id)) != expid) + if(chunk->id != expid) { - FLUID_LOG(FLUID_ERR, "Expected PDTA sub-chunk '%.4s' found invalid id instead", expstr); + FLUID_LOG(FLUID_ERR, "Expected PDTA sub-chunk '%.4s' found invalid id instead", &expid); return FALSE; } if(chunk->size % reclen) /* valid chunk size? */ { - FLUID_LOG(FLUID_ERR, "'%.4s' chunk size is not a multiple of %d bytes", expstr, reclen); + FLUID_LOG(FLUID_ERR, "'%.4s' chunk size is not a multiple of %d bytes", &expid, reclen); return FALSE; } if((*size -= chunk->size) < 0) { - FLUID_LOG(FLUID_ERR, "'%.4s' chunk size exceeds remaining PDTA chunk size", expstr); + FLUID_LOG(FLUID_ERR, "'%.4s' chunk size exceeds remaining PDTA chunk size", &expid); return FALSE; } @@ -885,7 +932,7 @@ static int process_pdta(SFData *sf, int size) { SFChunk chunk; - if(!pdtahelper(sf, PHDR_ID, SF_PHDR_SIZE, &chunk, &size)) + if(!pdtahelper(sf, PHDR_FCC, SF_PHDR_SIZE, &chunk, &size)) { return FALSE; } @@ -895,7 +942,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, PBAG_ID, SF_BAG_SIZE, &chunk, &size)) + if(!pdtahelper(sf, PBAG_FCC, SF_BAG_SIZE, &chunk, &size)) { return FALSE; } @@ -905,7 +952,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, PMOD_ID, SF_MOD_SIZE, &chunk, &size)) + if(!pdtahelper(sf, PMOD_FCC, SF_MOD_SIZE, &chunk, &size)) { return FALSE; } @@ -915,7 +962,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, PGEN_ID, SF_GEN_SIZE, &chunk, &size)) + if(!pdtahelper(sf, PGEN_FCC, SF_GEN_SIZE, &chunk, &size)) { return FALSE; } @@ -925,7 +972,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, IHDR_ID, SF_IHDR_SIZE, &chunk, &size)) + if(!pdtahelper(sf, IHDR_FCC, SF_IHDR_SIZE, &chunk, &size)) { return FALSE; } @@ -935,7 +982,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, IBAG_ID, SF_BAG_SIZE, &chunk, &size)) + if(!pdtahelper(sf, IBAG_FCC, SF_BAG_SIZE, &chunk, &size)) { return FALSE; } @@ -945,7 +992,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, IMOD_ID, SF_MOD_SIZE, &chunk, &size)) + if(!pdtahelper(sf, IMOD_FCC, SF_MOD_SIZE, &chunk, &size)) { return FALSE; } @@ -955,7 +1002,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, IGEN_ID, SF_GEN_SIZE, &chunk, &size)) + if(!pdtahelper(sf, IGEN_FCC, SF_GEN_SIZE, &chunk, &size)) { return FALSE; } @@ -965,7 +1012,7 @@ static int process_pdta(SFData *sf, int size) return FALSE; } - if(!pdtahelper(sf, SHDR_ID, SF_SHDR_SIZE, &chunk, &size)) + if(!pdtahelper(sf, SHDR_FCC, SF_SHDR_SIZE, &chunk, &size)) { return FALSE; } diff --git a/src/utils/fluid_sys.c b/src/utils/fluid_sys.c index 3df88fc2..4ac1344b 100644 --- a/src/utils/fluid_sys.c +++ b/src/utils/fluid_sys.c @@ -274,71 +274,6 @@ fluid_error() return fluid_errbuf; } -/** - * Check if a file is a MIDI file. - * @param filename Path to the file to check - * @return TRUE if it could be a MIDI file, FALSE otherwise - * - * The current implementation only checks for the "MThd" header in the file. - * It is useful only to distinguish between SoundFont and MIDI files. - */ -int -fluid_is_midifile(const char *filename) -{ - FILE *fp = fopen(filename, "rb"); - char id[4]; - - if(fp == NULL) - { - return 0; - } - - if(fread((void *) id, 1, 4, fp) != 4) - { - fclose(fp); - return 0; - } - - fclose(fp); - - return FLUID_STRNCMP(id, "MThd", 4) == 0; -} - -/** - * Check if a file is a SoundFont file. - * @param filename Path to the file to check - * @return TRUE if it could be a SoundFont, FALSE otherwise - * - * @note The current implementation only checks for the "RIFF" and "sfbk" headers in - * the file. It is useful to distinguish between SoundFont and other (e.g. MIDI) files. - */ -int -fluid_is_soundfont(const char *filename) -{ - FILE *fp = fopen(filename, "rb"); - char riff_id[4], sfbk_id[4]; - - if(fp == NULL) - { - return 0; - } - - if((fread((void *) riff_id, 1, sizeof(riff_id), fp) != sizeof(riff_id)) || - (fseek(fp, 4, SEEK_CUR) != 0) || - (fread((void *) sfbk_id, 1, sizeof(sfbk_id), fp) != sizeof(sfbk_id))) - { - goto error_rec; - } - - fclose(fp); - return (FLUID_STRNCMP(riff_id, "RIFF", sizeof(riff_id)) == 0) && - (FLUID_STRNCMP(sfbk_id, "sfbk", sizeof(sfbk_id)) == 0); - -error_rec: - fclose(fp); - return 0; -} - /** * Suspend the execution of the current thread for the specified amount of time. * @param milliseconds to wait. diff --git a/src/utils/fluid_sys.h b/src/utils/fluid_sys.h index 47cc95c1..72b32302 100644 --- a/src/utils/fluid_sys.h +++ b/src/utils/fluid_sys.h @@ -77,6 +77,14 @@ #define FLUID_LE32TOH(x) GINT32_FROM_LE(x) #define FLUID_LE16TOH(x) GINT16_FROM_LE(x) +#if FLUID_IS_BIG_ENDIAN +#define FLUID_FOURCC(_a, _b, _c, _d) \ + (uint32_t)(((uint32_t)(_a) << 24) | ((uint32_t)(_b) << 16) | ((uint32_t)(_c) << 8) | (uint32_t)(_d)) +#else +#define FLUID_FOURCC(_a, _b, _c, _d) \ + (uint32_t)(((uint32_t)(_d) << 24) | ((uint32_t)(_c) << 16) | ((uint32_t)(_b) << 8) | (uint32_t)(_a)) +#endif + #define fluid_return_if_fail(cond) \ if(cond) \ From 8da7f11a11f5b1d1a5082991ad3ffe4c882d3cdf Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 15 Dec 2018 20:42:53 +0100 Subject: [PATCH 9/9] Only retrieve modification time once and remove warning if failed This change removes the warning message if retrieving the soundfont file modification time fails in the sample cache loader. The warning made sense while we didn't have mtime support on all platforms, but after switching to GLibs g_stat, it's no longer needed. To reduce the number of calls to fluid_get_file_modification_time and also get rid of a possible race condition, getting the mtime has been moved to fluid_samplecache_load. This change also fixes #483 because it removes the bogus warning messages if a soundfont was loaded from memory by abusing the filename to store a pointer. --- src/sfloader/fluid_samplecache.c | 36 +++++++++++++++----------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/sfloader/fluid_samplecache.c b/src/sfloader/fluid_samplecache.c index 773e19fe..036964f5 100644 --- a/src/sfloader/fluid_samplecache.c +++ b/src/sfloader/fluid_samplecache.c @@ -60,8 +60,10 @@ struct _fluid_samplecache_entry_t static fluid_list_t *samplecache_list = NULL; static fluid_mutex_t samplecache_mutex = FLUID_MUTEX_INIT; -static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, unsigned int sample_start, unsigned int sample_end, int sample_type); -static fluid_samplecache_entry_t *get_samplecache_entry(SFData *sf, unsigned int sample_start, unsigned int sample_end, int sample_type); +static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, unsigned int sample_start, + unsigned int sample_end, int sample_type, time_t mtime); +static fluid_samplecache_entry_t *get_samplecache_entry(SFData *sf, unsigned int sample_start, + unsigned int sample_end, int sample_type, time_t mtime); static void delete_samplecache_entry(fluid_samplecache_entry_t *entry); static int fluid_get_file_modification_time(char *filename, time_t *modification_time); @@ -75,14 +77,20 @@ int fluid_samplecache_load(SFData *sf, { fluid_samplecache_entry_t *entry; int ret; + time_t mtime; fluid_mutex_lock(samplecache_mutex); - entry = get_samplecache_entry(sf, sample_start, sample_end, sample_type); + if(fluid_get_file_modification_time(sf->fname, &mtime) == FLUID_FAILED) + { + mtime = 0; + } + + entry = get_samplecache_entry(sf, sample_start, sample_end, sample_type, mtime); if(entry == NULL) { - entry = new_samplecache_entry(sf, sample_start, sample_end, sample_type); + entry = new_samplecache_entry(sf, sample_start, sample_end, sample_type, mtime); if(entry == NULL) { @@ -180,7 +188,8 @@ unlock_exit: static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, unsigned int sample_start, unsigned int sample_end, - int sample_type) + int sample_type, + time_t mtime) { fluid_samplecache_entry_t *entry; @@ -202,12 +211,6 @@ static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, goto error_exit; } - if(fluid_get_file_modification_time(entry->filename, &entry->modification_time) == FLUID_FAILED) - { - FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file."); - entry->modification_time = 0; - } - entry->sf_samplepos = sf->samplepos; entry->sf_samplesize = sf->samplesize; entry->sf_sample24pos = sf->sample24pos; @@ -215,6 +218,7 @@ static fluid_samplecache_entry_t *new_samplecache_entry(SFData *sf, entry->sample_start = sample_start; entry->sample_end = sample_end; entry->sample_type = sample_type; + entry->modification_time = mtime; entry->sample_count = fluid_sffile_read_sample_data(sf, sample_start, sample_end, sample_type, &entry->sample_data, &entry->sample_data24); @@ -244,18 +248,12 @@ static void delete_samplecache_entry(fluid_samplecache_entry_t *entry) static fluid_samplecache_entry_t *get_samplecache_entry(SFData *sf, unsigned int sample_start, unsigned int sample_end, - int sample_type) + int sample_type, + time_t mtime) { - time_t mtime; fluid_list_t *entry_list; fluid_samplecache_entry_t *entry; - if(fluid_get_file_modification_time(sf->fname, &mtime) == FLUID_FAILED) - { - FLUID_LOG(FLUID_WARN, "Unable to read modificaton time of soundfont file."); - mtime = 0; - } - entry_list = samplecache_list; while(entry_list)