From 16d2f43509e237cd458d31bf590b982dcfaa6d57 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Thu, 25 Mar 2021 21:22:10 +0100 Subject: [PATCH 01/11] Remove unused library, genre and morphology fields Those fields are not used anywhere, so let's simply remove them. --- src/sfloader/fluid_sffile.c | 6 +++--- src/sfloader/fluid_sffile.h | 6 ------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index a4b05569..6f4bf797 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -1094,9 +1094,9 @@ static int load_phdr(SFData *sf, unsigned int size) READW(sf, preset->prenum); READW(sf, preset->bank); READW(sf, pbag_idx); - READD(sf, preset->libr); - READD(sf, preset->genre); - READD(sf, preset->morph); + FSKIP(sf, 4); /* library ignored */ + FSKIP(sf, 4); /* genre ignored */ + FSKIP(sf, 4); /* morphology ignored */ if(prev_preset) { diff --git a/src/sfloader/fluid_sffile.h b/src/sfloader/fluid_sffile.h index 8dc53c79..0f03ac08 100644 --- a/src/sfloader/fluid_sffile.h +++ b/src/sfloader/fluid_sffile.h @@ -130,9 +130,6 @@ struct _SFPreset char name[21]; /* preset name */ unsigned short prenum; /* preset number */ unsigned short bank; /* bank number */ - unsigned int libr; /* Not used (preserved) */ - unsigned int genre; /* Not used (preserved) */ - unsigned int morph; /* Not used (preserved) */ fluid_list_t *zone; /* list of preset zones */ }; @@ -189,9 +186,6 @@ struct _SFPhdr unsigned short preset; /* preset number */ unsigned short bank; /* bank number */ unsigned short pbagndx; /* index into preset bag */ - unsigned int library; /* just for preserving them */ - unsigned int genre; /* Not used */ - unsigned int morphology; /* Not used */ }; struct _SFBag From b61abdd9075ffc515458d3f74b6b93f30b8aada4 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 15:03:29 +0100 Subject: [PATCH 02/11] Remove unused structs in sffile code --- src/sfloader/fluid_sffile.h | 39 ------------------------------------- 1 file changed, 39 deletions(-) diff --git a/src/sfloader/fluid_sffile.h b/src/sfloader/fluid_sffile.h index 0f03ac08..b2f0d4c6 100644 --- a/src/sfloader/fluid_sffile.h +++ b/src/sfloader/fluid_sffile.h @@ -45,10 +45,6 @@ typedef struct _SFInst SFInst; typedef struct _SFPreset SFPreset; typedef struct _SFData SFData; typedef struct _SFChunk SFChunk; -typedef struct _SFPhdr SFPhdr; -typedef struct _SFBag SFBag; -typedef struct _SFIhdr SFIhdr; -typedef struct _SFShdr SFShdr; struct _SFVersion @@ -180,41 +176,6 @@ struct _SFChunk unsigned int size; /* size of the following chunk */ }; -struct _SFPhdr -{ - unsigned char name[20]; /* preset name */ - unsigned short preset; /* preset number */ - unsigned short bank; /* bank number */ - unsigned short pbagndx; /* index into preset bag */ -}; - -struct _SFBag -{ - unsigned short genndx; /* index into generator list */ - unsigned short modndx; /* index into modulator list */ -}; - -struct _SFIhdr -{ - char name[20]; /* Name of instrument */ - unsigned short ibagndx; /* Instrument bag index */ -}; - -struct _SFShdr -{ - /* Sample header loading struct */ - char name[20]; /* Sample name */ - unsigned int start; /* Offset to start of sample */ - unsigned int end; /* Offset to end of sample */ - unsigned int loopstart; /* Offset to start of loop */ - unsigned int loopend; /* Offset to end of loop */ - unsigned int samplerate; /* Sample rate recorded at */ - unsigned char origpitch; /* root midi key number */ - signed char pitchadj; /* pitch correction in cents */ - unsigned short samplelink; /* Not used */ - unsigned short sampletype; /* 1 mono,2 right,4 left,linked 8,0x8000=ROM */ -}; - /* Public functions */ SFData *fluid_sffile_open(const char *fname, const fluid_file_callbacks_t *fcbs); void fluid_sffile_close(SFData *sf); From 359af770a378ec9864837489a3274528299b9200 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 15:22:28 +0100 Subject: [PATCH 03/11] Rename Gen_Dummy to Gen_last to clarify the purpose --- src/sfloader/fluid_sffile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 6f4bf797..c62c37a6 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -174,11 +174,11 @@ typedef enum Gen_ScaleTune, Gen_ExclusiveClass, Gen_OverrideRootKey, - Gen_Dummy + Gen_Last /* Sentinel value, not a valid generator */ } Gen_Type; -#define Gen_MaxValid Gen_Dummy - 1 /* maximum valid generator */ -#define Gen_Count Gen_Dummy /* count of generators */ +#define Gen_MaxValid Gen_Last - 1 /* maximum valid generator */ +#define Gen_Count Gen_Last /* count of generators */ #define GenArrSize sizeof(SFGenAmount) * Gen_Count /* gen array size */ From 84704ea440ed9e2c3980143578f427514ad64e1c Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 15:23:59 +0100 Subject: [PATCH 04/11] Remove Gen_MaxValid macro Not really necessary, checking against Gen_Last is just as understandable and removes a macro. --- src/sfloader/fluid_sffile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index c62c37a6..09ea6c26 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -177,7 +177,6 @@ typedef enum Gen_Last /* Sentinel value, not a valid generator */ } Gen_Type; -#define Gen_MaxValid Gen_Last - 1 /* maximum valid generator */ #define Gen_Count Gen_Last /* count of generators */ #define GenArrSize sizeof(SFGenAmount) * Gen_Count /* gen array size */ @@ -2376,7 +2375,7 @@ static int valid_inst_genid(unsigned short genid) { int i = 0; - if(genid > Gen_MaxValid) + if(genid >= Gen_Last) { return FALSE; } From 259aecedf29351f9c204f5af32db4be8a0c4d1d7 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 15:25:03 +0100 Subject: [PATCH 05/11] Remove unused macros --- src/sfloader/fluid_sffile.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 09ea6c26..677b0cfd 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -177,9 +177,6 @@ typedef enum Gen_Last /* Sentinel value, not a valid generator */ } Gen_Type; -#define Gen_Count Gen_Last /* count of generators */ -#define GenArrSize sizeof(SFGenAmount) * Gen_Count /* gen array size */ - static const unsigned short invalid_inst_gen[] = { From c4d38a7125679d693430c0f17c40d05d9541ad51 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 15:49:41 +0100 Subject: [PATCH 06/11] Fix preset generator validity checks The previous implementation used 0 as end-of-list sentinel value. But 0 is also the id of the first generator in the invalid_preset_gen list. This effectively prevented checks for invalid preset generators. Also contains some code cleanup to make the check for invalid instrument generators similar to invalid preset generators. Fixes #821 --- src/sfloader/fluid_sffile.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 677b0cfd..191f09c0 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -187,7 +187,6 @@ static const unsigned short invalid_inst_gen[] = Gen_Reserved1, Gen_Reserved2, Gen_Reserved3, - 0 }; static const unsigned short invalid_preset_gen[] = @@ -205,7 +204,6 @@ static const unsigned short invalid_preset_gen[] = Gen_SampleModes, Gen_ExclusiveClass, Gen_OverrideRootKey, - 0 }; @@ -2370,37 +2368,43 @@ static fluid_list_t *find_gen_by_id(int gen, fluid_list_t *genlist) /* check validity of instrument generator */ static int valid_inst_genid(unsigned short genid) { - int i = 0; + size_t i; if(genid >= Gen_Last) { return FALSE; } - while(invalid_inst_gen[i] && invalid_inst_gen[i] != genid) + for(i = 0; i < FLUID_N_ELEMENTS(invalid_inst_gen); i++) { - i++; + if (invalid_inst_gen[i] == genid) + { + return FALSE; + } } - return (invalid_inst_gen[i] == 0); + return TRUE; } /* check validity of preset generator */ static int valid_preset_genid(unsigned short genid) { - int i = 0; + size_t i; if(!valid_inst_genid(genid)) { return FALSE; } - while(invalid_preset_gen[i] && invalid_preset_gen[i] != genid) + for(i = 0; i < FLUID_N_ELEMENTS(invalid_preset_gen); i++) { - i++; + if (invalid_preset_gen[i] == genid) + { + return FALSE; + } } - return (invalid_preset_gen[i] == 0); + return TRUE; } From 6b63c80d3d7cb3e5eb50ef8b1e494147d20f540e Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 16:09:47 +0100 Subject: [PATCH 07/11] Remove code duplication by re-using enum from fluid_gen.h We already have an enum for all generator values, so there is no need to define another list in the loader code. --- src/sfloader/fluid_sffile.c | 123 +++++++++--------------------------- 1 file changed, 30 insertions(+), 93 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 191f09c0..15ba9344 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -112,98 +112,32 @@ static const uint32_t idlist[] = SM24_FCC }; -/* generator types */ -typedef enum -{ - Gen_StartAddrOfs, - Gen_EndAddrOfs, - Gen_StartLoopAddrOfs, - Gen_EndLoopAddrOfs, - Gen_StartAddrCoarseOfs, - Gen_ModLFO2Pitch, - Gen_VibLFO2Pitch, - Gen_ModEnv2Pitch, - Gen_FilterFc, - Gen_FilterQ, - Gen_ModLFO2FilterFc, - Gen_ModEnv2FilterFc, - Gen_EndAddrCoarseOfs, - Gen_ModLFO2Vol, - Gen_Unused1, - Gen_ChorusSend, - Gen_ReverbSend, - Gen_Pan, - Gen_Unused2, - Gen_Unused3, - Gen_Unused4, - Gen_ModLFODelay, - Gen_ModLFOFreq, - Gen_VibLFODelay, - Gen_VibLFOFreq, - Gen_ModEnvDelay, - Gen_ModEnvAttack, - Gen_ModEnvHold, - Gen_ModEnvDecay, - Gen_ModEnvSustain, - Gen_ModEnvRelease, - Gen_Key2ModEnvHold, - Gen_Key2ModEnvDecay, - Gen_VolEnvDelay, - Gen_VolEnvAttack, - Gen_VolEnvHold, - Gen_VolEnvDecay, - Gen_VolEnvSustain, - Gen_VolEnvRelease, - Gen_Key2VolEnvHold, - Gen_Key2VolEnvDecay, - Gen_Instrument, - Gen_Reserved1, - Gen_KeyRange, - Gen_VelRange, - Gen_StartLoopAddrCoarseOfs, - Gen_Keynum, - Gen_Velocity, - Gen_Attenuation, - Gen_Reserved2, - Gen_EndLoopAddrCoarseOfs, - Gen_CoarseTune, - Gen_FineTune, - Gen_SampleId, - Gen_SampleModes, - Gen_Reserved3, - Gen_ScaleTune, - Gen_ExclusiveClass, - Gen_OverrideRootKey, - Gen_Last /* Sentinel value, not a valid generator */ -} Gen_Type; - - static const unsigned short invalid_inst_gen[] = { - Gen_Unused1, - Gen_Unused2, - Gen_Unused3, - Gen_Unused4, - Gen_Reserved1, - Gen_Reserved2, - Gen_Reserved3, + GEN_UNUSED1, + GEN_UNUSED2, + GEN_UNUSED3, + GEN_UNUSED4, + GEN_RESERVED1, + GEN_RESERVED2, + GEN_RESERVED3, }; static const unsigned short invalid_preset_gen[] = { - Gen_StartAddrOfs, - Gen_EndAddrOfs, - Gen_StartLoopAddrOfs, - Gen_EndLoopAddrOfs, - Gen_StartAddrCoarseOfs, - Gen_EndAddrCoarseOfs, - Gen_StartLoopAddrCoarseOfs, - Gen_Keynum, - Gen_Velocity, - Gen_EndLoopAddrCoarseOfs, - Gen_SampleModes, - Gen_ExclusiveClass, - Gen_OverrideRootKey, + GEN_STARTADDROFS, + GEN_ENDADDROFS, + GEN_STARTLOOPADDROFS, + GEN_ENDLOOPADDROFS, + GEN_STARTADDRCOARSEOFS, + GEN_ENDADDRCOARSEOFS, + GEN_STARTLOOPADDRCOARSEOFS, + GEN_KEYNUM, + GEN_VELOCITY, + GEN_ENDLOOPADDRCOARSEOFS, + GEN_SAMPLEMODE, + GEN_EXCLUSIVECLASS, + GEN_OVERRIDEROOTKEY, }; @@ -1409,7 +1343,7 @@ static int load_pgen(SFData *sf, int size) READW(sf, genid); - if(genid == Gen_KeyRange) + if(genid == GEN_KEYRANGE) { /* nothing precedes */ if(level == 0) @@ -1423,7 +1357,7 @@ static int load_pgen(SFData *sf, int size) skip = TRUE; } } - else if(genid == Gen_VelRange) + else if(genid == GEN_VELRANGE) { /* only KeyRange precedes */ if(level <= 1) @@ -1437,7 +1371,7 @@ static int load_pgen(SFData *sf, int size) skip = TRUE; } } - else if(genid == Gen_Instrument) + else if(genid == GEN_INSTRUMENT) { /* inst is last gen */ level = 3; @@ -1928,7 +1862,7 @@ static int load_igen(SFData *sf, int size) READW(sf, genid); - if(genid == Gen_KeyRange) + if(genid == GEN_KEYRANGE) { /* nothing precedes */ if(level == 0) @@ -1942,7 +1876,7 @@ static int load_igen(SFData *sf, int size) skip = TRUE; } } - else if(genid == Gen_VelRange) + else if(genid == GEN_VELRANGE) { /* only KeyRange precedes */ if(level <= 1) @@ -1956,7 +1890,7 @@ static int load_igen(SFData *sf, int size) skip = TRUE; } } - else if(genid == Gen_SampleId) + else if(genid == GEN_SAMPLEID) { /* sample is last gen */ level = 3; @@ -2370,7 +2304,10 @@ static int valid_inst_genid(unsigned short genid) { size_t i; - if(genid >= Gen_Last) + /* OVERRIDEROOTKEY is the last official generator, everything + * following it are generators internal to FluidSynth and will + * never appear in a SoundFont file. */ + if(genid > GEN_OVERRIDEROOTKEY) { return FALSE; } From 6ca9b21740a90ed574a21cd3dad0907ef205ed49 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 16:10:57 +0100 Subject: [PATCH 08/11] Add more invalid generators for presets and instruments Presets should not contain sampleid generators, instruments should not contain instrument generators. --- src/sfloader/fluid_sffile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 15ba9344..20cee8f2 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -121,6 +121,7 @@ static const unsigned short invalid_inst_gen[] = GEN_RESERVED1, GEN_RESERVED2, GEN_RESERVED3, + GEN_INSTRUMENT, }; static const unsigned short invalid_preset_gen[] = @@ -138,6 +139,7 @@ static const unsigned short invalid_preset_gen[] = GEN_SAMPLEMODE, GEN_EXCLUSIVECLASS, GEN_OVERRIDEROOTKEY, + GEN_SAMPLEID, }; From dfbef11da088b737dde7616d012bc783768821f8 Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 16:56:24 +0100 Subject: [PATCH 09/11] Remove instsamp hack This change removes the need for the instsamp hack in instrument and preset zones. The sampleid and instrument generators are treated as any other generator and simply passed to the defsfont import functions. Those read the two generators and use the index to look up valid samples and instruments. Both generators are then reset to GEN_UNUSED again, just to make sure that the rest of FluidSynth doesn't get confused. But that might not be necessary. --- src/sfloader/fluid_defsfont.c | 80 ++++++++++++++++---- src/sfloader/fluid_defsfont.h | 8 +- src/sfloader/fluid_sffile.c | 137 +++++----------------------------- src/sfloader/fluid_sffile.h | 2 +- 4 files changed, 87 insertions(+), 140 deletions(-) diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 9f4a2d78..36acf85c 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -533,7 +533,7 @@ int fluid_defsfont_load(fluid_defsfont_t *defsfont, const fluid_file_callbacks_t goto err_exit; } - if(fluid_defpreset_import_sfont(defpreset, sfpreset, defsfont) != FLUID_OK) + if(fluid_defpreset_import_sfont(defpreset, sfpreset, defsfont, sfdata) != FLUID_OK) { goto err_exit; } @@ -1028,7 +1028,8 @@ fluid_defpreset_set_global_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_ int fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset, SFPreset *sfpreset, - fluid_defsfont_t *defsfont) + fluid_defsfont_t *defsfont, + SFData *sfdata) { fluid_list_t *p; SFZone *sfzone; @@ -1061,7 +1062,7 @@ fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset, return FLUID_FAILED; } - if(fluid_preset_zone_import_sfont(zone, sfzone, defsfont) != FLUID_OK) + if(fluid_preset_zone_import_sfont(zone, sfzone, defsfont, sfdata) != FLUID_OK) { delete_fluid_preset_zone(zone); return FLUID_FAILED; @@ -1424,8 +1425,13 @@ fluid_zone_gen_import_sfont(fluid_gen_t *gen, fluid_zone_range_t *range, SFZone gen[sfgen->id].flags = GEN_SET; break; + case GEN_INSTRUMENT: + case GEN_SAMPLEID: + gen[sfgen->id].val = (fluid_real_t) sfgen->amount.uword; + gen[sfgen->id].flags = GEN_SET; + break; + default: - /* FIXME: some generators have an unsigne word amount value but i don't know which ones */ gen[sfgen->id].val = (fluid_real_t) sfgen->amount.sword; gen[sfgen->id].flags = GEN_SET; break; @@ -1630,24 +1636,27 @@ fluid_zone_mod_import_sfont(char *zone_name, fluid_mod_t **mod, SFZone *sfzone) * fluid_preset_zone_import_sfont */ int -fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defsfont) +fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defsfont, SFData *sfdata) { /* import the generators */ fluid_zone_gen_import_sfont(zone->gen, &zone->range, sfzone); - if((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) + if(zone->gen[GEN_INSTRUMENT].flags == GEN_SET) { - SFInst *sfinst = sfzone->instsamp->data; + int inst_idx = (int) zone->gen[GEN_INSTRUMENT].val; - zone->inst = find_inst_by_idx(defsfont, sfinst->idx); + zone->inst = find_inst_by_idx(defsfont, inst_idx); if(zone->inst == NULL) { - zone->inst = fluid_inst_import_sfont(sfinst, defsfont); + zone->inst = fluid_inst_import_sfont(inst_idx, defsfont, sfdata); } if(zone->inst == NULL) { + + FLUID_LOG(FLUID_ERR, "Preset zone %s: Invalid instrument reference", + zone->name); return FLUID_FAILED; } @@ -1655,6 +1664,9 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_ { return FLUID_FAILED; } + + /* We don't need this generator anymore */ + zone->gen[GEN_INSTRUMENT].flags = GEN_UNUSED; } /* Import the modulators (only SF2.1 and higher) */ @@ -1735,15 +1747,30 @@ fluid_inst_set_global_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone) * fluid_inst_import_sfont */ fluid_inst_t * -fluid_inst_import_sfont(SFInst *sfinst, fluid_defsfont_t *defsfont) +fluid_inst_import_sfont(int inst_idx, fluid_defsfont_t *defsfont, SFData *sfdata) { fluid_list_t *p; + fluid_list_t *inst_list; fluid_inst_t *inst; SFZone *sfzone; + SFInst *sfinst; fluid_inst_zone_t *inst_zone; char zone_name[256]; int count; + for (inst_list = sfdata->inst; inst_list; inst_list = fluid_list_next(inst_list)) + { + sfinst = fluid_list_get(inst_list); + if (sfinst->idx == inst_idx) + { + break; + } + } + if (inst_list == NULL) + { + return NULL; + } + inst = (fluid_inst_t *) new_fluid_inst(); if(inst == NULL) @@ -1781,7 +1808,7 @@ fluid_inst_import_sfont(SFInst *sfinst, fluid_defsfont_t *defsfont) return NULL; } - if(fluid_inst_zone_import_sfont(inst_zone, sfzone, defsfont) != FLUID_OK) + if(fluid_inst_zone_import_sfont(inst_zone, sfzone, defsfont, sfdata) != FLUID_OK) { delete_fluid_inst_zone(inst_zone); return NULL; @@ -1913,7 +1940,8 @@ fluid_inst_zone_next(fluid_inst_zone_t *zone) * fluid_inst_zone_import_sfont */ int -fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont) +fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont, + SFData *sfdata) { /* import the generators */ fluid_zone_gen_import_sfont(inst_zone->gen, &inst_zone->range, sfzone); @@ -1923,10 +1951,32 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid /* FLUID_LOG(FLUID_DBG, "ExclusiveClass=%d\n", (int) zone->gen[GEN_EXCLUSIVECLASS].val); */ /* } */ - /* fixup sample pointer */ - if((sfzone->instsamp != NULL) && (sfzone->instsamp->data != NULL)) + if (inst_zone->gen[GEN_SAMPLEID].flags == GEN_SET) { - inst_zone->sample = ((SFSample *)(sfzone->instsamp->data))->fluid_sample; + fluid_list_t *list; + SFSample *sfsample; + int sample_idx = (int) inst_zone->gen[GEN_SAMPLEID].val; + + /* find the SFSample by index */ + for(list = sfdata->sample; list; list = fluid_list_next(list)) + { + sfsample = fluid_list_get(list); + if (sfsample->idx == sample_idx) + { + break; + } + } + if (list == NULL) + { + FLUID_LOG(FLUID_ERR, "Instrument zone '%s': Invalid sample reference", + inst_zone->name); + return FLUID_FAILED; + } + + inst_zone->sample = sfsample->fluid_sample; + + /* we don't need this generator anymore, mark it as unused */ + inst_zone->gen[GEN_SAMPLEID].flags = GEN_UNUSED; } /* Import the modulators (only SF2.1 and higher) */ diff --git a/src/sfloader/fluid_defsfont.h b/src/sfloader/fluid_defsfont.h index fce4eea3..b5129936 100644 --- a/src/sfloader/fluid_defsfont.h +++ b/src/sfloader/fluid_defsfont.h @@ -154,7 +154,7 @@ struct _fluid_defpreset_t fluid_defpreset_t *new_fluid_defpreset(void); void delete_fluid_defpreset(fluid_defpreset_t *defpreset); fluid_defpreset_t *fluid_defpreset_next(fluid_defpreset_t *defpreset); -int fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset, SFPreset *sfpreset, fluid_defsfont_t *defsfont); +int fluid_defpreset_import_sfont(fluid_defpreset_t *defpreset, SFPreset *sfpreset, fluid_defsfont_t *defsfont, SFData *sfdata); int fluid_defpreset_set_global_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone); int fluid_defpreset_add_zone(fluid_defpreset_t *defpreset, fluid_preset_zone_t *zone); fluid_preset_zone_t *fluid_defpreset_get_zone(fluid_defpreset_t *defpreset); @@ -182,7 +182,7 @@ fluid_preset_zone_t *new_fluid_preset_zone(char *name); void delete_fluid_list_mod(fluid_mod_t *mod); void delete_fluid_preset_zone(fluid_preset_zone_t *zone); fluid_preset_zone_t *fluid_preset_zone_next(fluid_preset_zone_t *zone); -int fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defssfont); +int fluid_preset_zone_import_sfont(fluid_preset_zone_t *zone, SFZone *sfzone, fluid_defsfont_t *defssfont, SFData *sfdata); fluid_inst_t *fluid_preset_zone_get_inst(fluid_preset_zone_t *zone); /* @@ -197,7 +197,7 @@ struct _fluid_inst_t }; fluid_inst_t *new_fluid_inst(void); -fluid_inst_t *fluid_inst_import_sfont(SFInst *sfinst, fluid_defsfont_t *defsfont); +fluid_inst_t *fluid_inst_import_sfont(int inst_idx, fluid_defsfont_t *defsfont, SFData *sfdata); void delete_fluid_inst(fluid_inst_t *inst); int fluid_inst_set_global_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone); int fluid_inst_add_zone(fluid_inst_t *inst, fluid_inst_zone_t *zone); @@ -221,7 +221,7 @@ struct _fluid_inst_zone_t fluid_inst_zone_t *new_fluid_inst_zone(char *name); void delete_fluid_inst_zone(fluid_inst_zone_t *zone); fluid_inst_zone_t *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); +int fluid_inst_zone_import_sfont(fluid_inst_zone_t *inst_zone, SFZone *sfzone, fluid_defsfont_t *defsfont, SFData *sfdata); fluid_sample_t *fluid_inst_zone_get_sample(fluid_inst_zone_t *zone); diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 20cee8f2..a4252832 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -239,8 +239,6 @@ static int load_ibag(SFData *sf, int size); static int load_imod(SFData *sf, int size); static int load_igen(SFData *sf, int size); static int load_shdr(SFData *sf, unsigned int size); -static int fixup_pgen(SFData *sf); -static int fixup_igen(SFData *sf); static int chunkid(uint32_t id); static int read_listchunk(SFData *sf, SFChunk *chunk); @@ -629,16 +627,6 @@ static int load_body(SFData *sf) return FALSE; } - if(!fixup_pgen(sf)) - { - return FALSE; - } - - if(!fixup_igen(sf)) - { - return FALSE; - } - /* sort preset list by bank, preset # */ sf->preset = fluid_list_sort(sf->preset, (fluid_compare_func_t)preset_compare_func); @@ -1116,7 +1104,6 @@ static int load_pbag(SFData *sf, int size) z->mod = NULL; /* to ensure proper cleanup (fluid_sffile_close) */ READW(sf, genndx); /* possible read failure ^ */ READW(sf, modndx); - z->instsamp = NULL; if(pz) { @@ -1378,8 +1365,6 @@ static int load_pgen(SFData *sf, int size) /* inst is last gen */ level = 3; READW(sf, genval.uword); - ((SFZone *)(zone_list->data))->instsamp = FLUID_INT_TO_POINTER(genval.uword + 1); - break; /* break out of generator loop */ } else { @@ -1436,13 +1421,18 @@ static int load_pgen(SFData *sf, int size) SLADVREM(z->gen, gen_list); /* drop place holder */ } + /* Level 3 means we found an instrument generator, which + * should be the last generator in the list. */ + if (level == 3) + { + break; + } + } /* generator loop */ - if(level == 3) - { - SLADVREM(z->gen, gen_list); /* zone has inst? */ - } - else + /* Level 3 means we found an instrument generator, so any zone + * with a lower level is by definition a global zone */ + if(level < 3) { /* congratulations its a global zone */ if(!gzone) @@ -1645,7 +1635,6 @@ static int load_ibag(SFData *sf, int size) z->mod = NULL; /* fluid_sffile_close can clean up */ READW(sf, genndx); /* READW = possible read failure */ READW(sf, modndx); - z->instsamp = NULL; if(pz) { @@ -1897,8 +1886,6 @@ static int load_igen(SFData *sf, int size) /* sample is last gen */ level = 3; READW(sf, genval.uword); - ((SFZone *)(zone_list->data))->instsamp = FLUID_INT_TO_POINTER(genval.uword + 1); - break; /* break out of generator loop */ } else { @@ -1955,13 +1942,14 @@ static int load_igen(SFData *sf, int size) SLADVREM(z->gen, gen_list); } + if (level == 3) + { + break; + } + } /* generator loop */ - if(level == 3) - { - SLADVREM(z->gen, gen_list); /* zone has sample? */ - } - else + if (level < 3) { /* its a global zone */ if(!gzone) @@ -2068,6 +2056,7 @@ static int load_shdr(SFData *sf, unsigned int size) FLUID_LOG(FLUID_ERR, "Out of memory"); return FALSE; } + p->idx = i; sf->sample = fluid_list_append(sf->sample, p); READSTR(sf, &p->name); @@ -2087,98 +2076,6 @@ static int load_shdr(SFData *sf, unsigned int size) return TRUE; } -/* "fixup" (inst # -> inst ptr) instrument references in preset list */ -static int fixup_pgen(SFData *sf) -{ - fluid_list_t *p; - fluid_list_t *zone_list; - fluid_list_t *inst_list; - SFZone *z; - int i; - - p = sf->preset; - - while(p) - { - zone_list = ((SFPreset *)(p->data))->zone; - - while(zone_list) - { - /* traverse this preset's zones */ - z = (SFZone *)(zone_list->data); - - if((i = FLUID_POINTER_TO_INT(z->instsamp))) - { - /* load instrument # */ - inst_list = fluid_list_nth(sf->inst, i - 1); - - if(!inst_list) - { - FLUID_LOG(FLUID_ERR, "Preset %03d %03d: Invalid instrument reference", - ((SFPreset *)(p->data))->bank, ((SFPreset *)(p->data))->prenum); - return FALSE; - } - - z->instsamp = inst_list; - } - else - { - z->instsamp = NULL; - } - - zone_list = fluid_list_next(zone_list); - } - - p = fluid_list_next(p); - } - - return TRUE; -} - -/* "fixup" (sample # -> sample ptr) sample references in instrument list */ -static int fixup_igen(SFData *sf) -{ - fluid_list_t *p; - fluid_list_t *zone_list; - fluid_list_t *inst_list; - SFZone *z; - int i; - - p = sf->inst; - - while(p) - { - zone_list = ((SFInst *)(p->data))->zone; - - while(zone_list) - { - /* traverse instrument's zones */ - z = (SFZone *)(zone_list->data); - - if((i = FLUID_POINTER_TO_INT(z->instsamp))) - { - /* load sample # */ - inst_list = fluid_list_nth(sf->sample, i - 1); - - if(!inst_list) - { - FLUID_LOG(FLUID_ERR, "Instrument '%s': Invalid sample reference", - ((SFInst *)(p->data))->name); - return FALSE; - } - - z->instsamp = inst_list; - } - - zone_list = fluid_list_next(zone_list); - } - - p = fluid_list_next(p); - } - - return TRUE; -} - static void delete_preset(SFPreset *preset) { fluid_list_t *entry; diff --git a/src/sfloader/fluid_sffile.h b/src/sfloader/fluid_sffile.h index b2f0d4c6..f2332c45 100644 --- a/src/sfloader/fluid_sffile.h +++ b/src/sfloader/fluid_sffile.h @@ -85,7 +85,6 @@ struct _SFGen struct _SFZone { /* Sample/instrument zone structure */ - fluid_list_t *instsamp; /* instrument/sample pointer for zone */ fluid_list_t *gen; /* list of generators */ fluid_list_t *mod; /* list of modulators */ }; @@ -94,6 +93,7 @@ struct _SFSample { /* Sample structure */ char name[21]; /* Name of sample */ + int idx; /* Index of this instrument in the Soundfont */ unsigned int start; /* Offset in sample area to start of sample */ unsigned int end; /* Offset from start to end of sample, this is the last point of the From 0f8e2c7fde47272ad3b2bc52f1c66cb50f45bd3c Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sat, 27 Mar 2021 22:23:32 +0100 Subject: [PATCH 10/11] Refactor load_igen and load_pgen Cleanup of the code structure and fix of the ineffective check for global zones that are not first in list. Fixes #813 --- src/sfloader/fluid_sffile.c | 164 ++++++++++++++---------------------- 1 file changed, 65 insertions(+), 99 deletions(-) diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index a4252832..2ef72761 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -1079,14 +1079,14 @@ static int load_pbag(SFData *sf, int size) preset_list = sf->preset; + /* traverse through presets */ while(preset_list) { - /* traverse through presets */ zone_list = ((SFPreset *)(preset_list->data))->zone; + /* traverse preset's zones */ while(zone_list) { - /* traverse preset's zones */ if((size -= SF_BAG_SIZE) < 0) { FLUID_LOG(FLUID_ERR, "Preset bag chunk size mismatch"); @@ -1285,37 +1285,33 @@ static int load_pmod(SFData *sf, int size) * ------------------------------------------------------------------- */ static int load_pgen(SFData *sf, int size) { - fluid_list_t *dup, **hz = NULL; + fluid_list_t *dup; fluid_list_t *preset_list; fluid_list_t *zone_list; fluid_list_t *gen_list; - fluid_list_t *start_of_zone_list; - SFZone *z; + SFZone *zone; SFGen *g; + SFPreset *preset; SFGenAmount genval; unsigned short genid; - int level, skip, drop, gzone, discarded; + int level, skip, drop, discarded; preset_list = sf->preset; while(preset_list) { + preset = fluid_list_get(preset_list); + /* traverse through all presets */ - gzone = FALSE; discarded = FALSE; - start_of_zone_list = zone_list = ((SFPreset *)(preset_list->data))->zone; - - if(zone_list) - { - hz = &zone_list; - } + zone_list = preset->zone; + /* traverse preset's zones */ while(zone_list) { - /* traverse preset's zones */ + zone = fluid_list_get(zone_list); level = 0; - z = (SFZone *)(zone_list->data); - gen_list = z->gen; + gen_list = zone->gen; while(gen_list) { @@ -1374,7 +1370,7 @@ static int load_pgen(SFData *sf, int size) { /* generator valid? */ READW(sf, genval.sword); - dup = find_gen_by_id(genid, z->gen); + dup = find_gen_by_id(genid, zone->gen); } else { @@ -1418,11 +1414,10 @@ static int load_pgen(SFData *sf, int size) } else { - SLADVREM(z->gen, gen_list); /* drop place holder */ + SLADVREM(zone->gen, gen_list); /* drop place holder */ } - /* Level 3 means we found an instrument generator, which - * should be the last generator in the list. */ + /* GEN_INSTRUMENT should be the last generator */ if (level == 3) { break; @@ -1430,42 +1425,27 @@ static int load_pgen(SFData *sf, int size) } /* generator loop */ - /* Level 3 means we found an instrument generator, so any zone - * with a lower level is by definition a global zone */ - if(level < 3) + /* Anything below level 3 means it's a global zone. The global zone + * should always be the first zone in the list, so discard any + * other global zones we encounter */ + if(level < 3 && (zone_list != preset->zone)) { - /* congratulations its a global zone */ - if(!gzone) - { - /* Prior global zones? */ - gzone = TRUE; + /* advance to next zone before deleting the current list element */ + zone_list = fluid_list_next(zone_list); - /* if global zone is not 1st zone, relocate */ - if(*hz != zone_list) - { - void *save = zone_list->data; - FLUID_LOG(FLUID_WARN, "Preset '%s': Global zone is not first zone", - ((SFPreset *)(preset_list->data))->name); - SLADVREM(*hz, zone_list); - *hz = fluid_list_prepend(*hz, save); - continue; - } - } - else - { - zone_list = fluid_list_next(zone_list); /* advance to next zone before deleting the current list element */ - /* previous global zone exists, discard */ - FLUID_LOG(FLUID_WARN, "Preset '%s': Discarding invalid global zone", - ((SFPreset *)(preset_list->data))->name); - fluid_list_remove(start_of_zone_list, z); - delete_zone(z); - continue; - } + FLUID_LOG(FLUID_WARN, "Preset '%s': Discarding invalid global zone", + preset->name); + preset->zone = fluid_list_remove(preset->zone, zone); + delete_zone(zone); + + /* we have already advanced the zone_list pointer, so continue with next zone */ + continue; } + /* All remaining generators are invalid and should be discarded + * (because they come after an instrument generator) */ while(gen_list) { - /* Kill any zones following an instrument */ discarded = TRUE; if((size -= SF_GEN_SIZE) < 0) @@ -1475,17 +1455,17 @@ static int load_pgen(SFData *sf, int size) } FSKIP(sf, SF_GEN_SIZE); - SLADVREM(z->gen, gen_list); + SLADVREM(zone->gen, gen_list); } - zone_list = fluid_list_next(zone_list); /* next zone */ + zone_list = fluid_list_next(zone_list); } if(discarded) { FLUID_LOG(FLUID_WARN, "Preset '%s': Some invalid generators were discarded", - ((SFPreset *)(preset_list->data))->name); + preset->name); } preset_list = fluid_list_next(preset_list); @@ -1806,37 +1786,34 @@ static int load_imod(SFData *sf, int size) /* load instrument generators (see load_pgen for loading rules) */ static int load_igen(SFData *sf, int size) { - fluid_list_t *dup, **hz = NULL; + fluid_list_t *dup; fluid_list_t *inst_list; fluid_list_t *zone_list; fluid_list_t *gen_list; - fluid_list_t *start_of_zone_list; - SFZone *z; + SFZone *zone; SFGen *g; + SFInst *inst; SFGenAmount genval; unsigned short genid; - int level, skip, drop, gzone, discarded; + int level, skip, drop, discarded; inst_list = sf->inst; + /* traverse through all instruments */ while(inst_list) { - /* traverse through all instruments */ - gzone = FALSE; + inst = fluid_list_get(inst_list); + discarded = FALSE; - start_of_zone_list = zone_list = ((SFInst *)(inst_list->data))->zone; - - if(zone_list) - { - hz = &zone_list; - } + zone_list = inst->zone; + /* traverse this instrument's zones */ while(zone_list) { - /* traverse this instrument's zones */ + zone = fluid_list_get(zone_list); + level = 0; - z = (SFZone *)(zone_list->data); - gen_list = z->gen; + gen_list = zone->gen; while(gen_list) { @@ -1895,7 +1872,7 @@ static int load_igen(SFData *sf, int size) { /* gen valid? */ READW(sf, genval.sword); - dup = find_gen_by_id(genid, z->gen); + dup = find_gen_by_id(genid, zone->gen); } else { @@ -1939,9 +1916,10 @@ static int load_igen(SFData *sf, int size) } else { - SLADVREM(z->gen, gen_list); + SLADVREM(zone->gen, gen_list); } + /* GEN_SAMPLEID should be last generator */ if (level == 3) { break; @@ -1949,39 +1927,27 @@ static int load_igen(SFData *sf, int size) } /* generator loop */ - if (level < 3) + /* Anything below level 3 means it's a global zone. The global zone + * should always be the first zone in the list, so discard any + * other global zones we encounter */ + if(level < 3 && (zone_list != inst->zone)) { - /* its a global zone */ - if(!gzone) - { - gzone = TRUE; + /* advance to next zone before deleting the current list element */ + zone_list = fluid_list_next(zone_list); - /* if global zone is not 1st zone, relocate */ - if(*hz != zone_list) - { - void *save = zone_list->data; - FLUID_LOG(FLUID_WARN, "Instrument '%s': Global zone is not first zone", - ((SFPreset *)(inst_list->data))->name); - SLADVREM(*hz, zone_list); - *hz = fluid_list_prepend(*hz, save); - continue; - } - } - else - { - zone_list = fluid_list_next(zone_list); /* advance to next zone before deleting the current list element */ - /* previous global zone exists, discard */ - FLUID_LOG(FLUID_WARN, "Instrument '%s': Discarding invalid global zone", - ((SFInst *)(inst_list->data))->name); - fluid_list_remove(start_of_zone_list, z); - delete_zone(z); - continue; - } + FLUID_LOG(FLUID_WARN, "Instrument '%s': Discarding invalid global zone", + inst->name); + inst->zone = fluid_list_remove(inst->zone, zone); + delete_zone(zone); + + /* we have already advanced the zone_list pointer, so continue with next zone */ + continue; } + /* All remaining generators must be invalid and should be discarded + * (because they come after a sampleid generator) */ while(gen_list) { - /* Kill any zones following a sample */ discarded = TRUE; if((size -= SF_GEN_SIZE) < 0) @@ -1991,7 +1957,7 @@ static int load_igen(SFData *sf, int size) } FSKIP(sf, SF_GEN_SIZE); - SLADVREM(z->gen, gen_list); + SLADVREM(zone->gen, gen_list); } zone_list = fluid_list_next(zone_list); /* next zone */ @@ -2001,7 +1967,7 @@ static int load_igen(SFData *sf, int size) { FLUID_LOG(FLUID_WARN, "Instrument '%s': Some invalid generators were discarded", - ((SFInst *)(inst_list->data))->name); + inst->name); } inst_list = fluid_list_next(inst_list); From 5ebd4d3d267762bb7c598d8ead989597c3d45a6a Mon Sep 17 00:00:00 2001 From: Marcus Weseloh Date: Sun, 28 Mar 2021 15:00:25 +0200 Subject: [PATCH 11/11] Speedup SF2 loading by using prepend instead of append on samples Using prepend both in sffile and defsfont reduces insert complexity to O(1) and does not affect the final order of the sample list, as the reversed order of the samples in sffile is reversed again in defsfont. --- src/sfloader/fluid_defsfont.c | 2 +- src/sfloader/fluid_sffile.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 36acf85c..c45696fc 100644 --- a/src/sfloader/fluid_defsfont.c +++ b/src/sfloader/fluid_defsfont.c @@ -562,7 +562,7 @@ err_exit: */ int fluid_defsfont_add_sample(fluid_defsfont_t *defsfont, fluid_sample_t *sample) { - defsfont->sample = fluid_list_append(defsfont->sample, sample); + defsfont->sample = fluid_list_prepend(defsfont->sample, sample); return FLUID_OK; } diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 2ef72761..44a4dfa3 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -2024,7 +2024,7 @@ static int load_shdr(SFData *sf, unsigned int size) } p->idx = i; - sf->sample = fluid_list_append(sf->sample, p); + sf->sample = fluid_list_prepend(sf->sample, p); READSTR(sf, &p->name); READD(sf, p->start); READD(sf, p->end);