Merge branch 'master' into 2.1-testing

This commit is contained in:
derselbst 2018-12-19 14:22:40 +01:00
commit 2cef5b0587
14 changed files with 479 additions and 677 deletions

View File

@ -204,7 +204,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 )
@ -350,6 +349,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 )
@ -383,22 +394,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

View File

@ -379,6 +379,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)

View File

@ -43,9 +43,6 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H @HAVE_IO_H@
/* whether or not we are supporting lash */
#cmakedefine HAVE_LASH @HAVE_LASH@

View File

@ -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})

View File

@ -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);

View File

@ -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);
}
/*

View File

@ -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)

View File

@ -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;
}

View File

@ -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++)

View File

@ -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);
}
}
}

View File

@ -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.

View File

@ -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) \

View File

@ -106,10 +106,6 @@
#include <omp.h>
#endif
#if HAVE_IO_H
#include <io.h>
#endif
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
@ -265,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)

View File

@ -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