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
This commit is contained in:
Marcus Weseloh 2021-03-27 22:23:32 +01:00
parent dfbef11da0
commit 0f8e2c7fde

View file

@ -1079,14 +1079,14 @@ static int load_pbag(SFData *sf, int size)
preset_list = sf->preset; preset_list = sf->preset;
/* traverse through presets */
while(preset_list) while(preset_list)
{ {
/* traverse through presets */
zone_list = ((SFPreset *)(preset_list->data))->zone; zone_list = ((SFPreset *)(preset_list->data))->zone;
/* traverse preset's zones */
while(zone_list) while(zone_list)
{ {
/* traverse preset's zones */
if((size -= SF_BAG_SIZE) < 0) if((size -= SF_BAG_SIZE) < 0)
{ {
FLUID_LOG(FLUID_ERR, "Preset bag chunk size mismatch"); 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) 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 *preset_list;
fluid_list_t *zone_list; fluid_list_t *zone_list;
fluid_list_t *gen_list; fluid_list_t *gen_list;
fluid_list_t *start_of_zone_list; SFZone *zone;
SFZone *z;
SFGen *g; SFGen *g;
SFPreset *preset;
SFGenAmount genval; SFGenAmount genval;
unsigned short genid; unsigned short genid;
int level, skip, drop, gzone, discarded; int level, skip, drop, discarded;
preset_list = sf->preset; preset_list = sf->preset;
while(preset_list) while(preset_list)
{ {
preset = fluid_list_get(preset_list);
/* traverse through all presets */ /* traverse through all presets */
gzone = FALSE;
discarded = FALSE; discarded = FALSE;
start_of_zone_list = zone_list = ((SFPreset *)(preset_list->data))->zone; zone_list = preset->zone;
if(zone_list)
{
hz = &zone_list;
}
/* traverse preset's zones */
while(zone_list) while(zone_list)
{ {
/* traverse preset's zones */ zone = fluid_list_get(zone_list);
level = 0; level = 0;
z = (SFZone *)(zone_list->data); gen_list = zone->gen;
gen_list = z->gen;
while(gen_list) while(gen_list)
{ {
@ -1374,7 +1370,7 @@ static int load_pgen(SFData *sf, int size)
{ {
/* generator valid? */ /* generator valid? */
READW(sf, genval.sword); READW(sf, genval.sword);
dup = find_gen_by_id(genid, z->gen); dup = find_gen_by_id(genid, zone->gen);
} }
else else
{ {
@ -1418,11 +1414,10 @@ static int load_pgen(SFData *sf, int size)
} }
else 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 /* GEN_INSTRUMENT should be the last generator */
* should be the last generator in the list. */
if (level == 3) if (level == 3)
{ {
break; break;
@ -1430,42 +1425,27 @@ static int load_pgen(SFData *sf, int size)
} /* generator loop */ } /* generator loop */
/* Level 3 means we found an instrument generator, so any zone /* Anything below level 3 means it's a global zone. The global zone
* with a lower level is by definition a global zone */ * should always be the first zone in the list, so discard any
if(level < 3) * other global zones we encounter */
if(level < 3 && (zone_list != preset->zone))
{ {
/* congratulations its a global zone */ /* advance to next zone before deleting the current list element */
if(!gzone) zone_list = fluid_list_next(zone_list);
{
/* Prior global zones? */
gzone = TRUE;
/* if global zone is not 1st zone, relocate */ FLUID_LOG(FLUID_WARN, "Preset '%s': Discarding invalid global zone",
if(*hz != zone_list) preset->name);
{ preset->zone = fluid_list_remove(preset->zone, zone);
void *save = zone_list->data; delete_zone(zone);
FLUID_LOG(FLUID_WARN, "Preset '%s': Global zone is not first zone",
((SFPreset *)(preset_list->data))->name); /* we have already advanced the zone_list pointer, so continue with next zone */
SLADVREM(*hz, zone_list); continue;
*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;
}
} }
/* All remaining generators are invalid and should be discarded
* (because they come after an instrument generator) */
while(gen_list) while(gen_list)
{ {
/* Kill any zones following an instrument */
discarded = TRUE; discarded = TRUE;
if((size -= SF_GEN_SIZE) < 0) if((size -= SF_GEN_SIZE) < 0)
@ -1475,17 +1455,17 @@ static int load_pgen(SFData *sf, int size)
} }
FSKIP(sf, SF_GEN_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) if(discarded)
{ {
FLUID_LOG(FLUID_WARN, FLUID_LOG(FLUID_WARN,
"Preset '%s': Some invalid generators were discarded", "Preset '%s': Some invalid generators were discarded",
((SFPreset *)(preset_list->data))->name); preset->name);
} }
preset_list = fluid_list_next(preset_list); 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) */ /* load instrument generators (see load_pgen for loading rules) */
static int load_igen(SFData *sf, int size) 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 *inst_list;
fluid_list_t *zone_list; fluid_list_t *zone_list;
fluid_list_t *gen_list; fluid_list_t *gen_list;
fluid_list_t *start_of_zone_list; SFZone *zone;
SFZone *z;
SFGen *g; SFGen *g;
SFInst *inst;
SFGenAmount genval; SFGenAmount genval;
unsigned short genid; unsigned short genid;
int level, skip, drop, gzone, discarded; int level, skip, drop, discarded;
inst_list = sf->inst; inst_list = sf->inst;
/* traverse through all instruments */
while(inst_list) while(inst_list)
{ {
/* traverse through all instruments */ inst = fluid_list_get(inst_list);
gzone = FALSE;
discarded = FALSE; discarded = FALSE;
start_of_zone_list = zone_list = ((SFInst *)(inst_list->data))->zone; zone_list = inst->zone;
if(zone_list)
{
hz = &zone_list;
}
/* traverse this instrument's zones */
while(zone_list) while(zone_list)
{ {
/* traverse this instrument's zones */ zone = fluid_list_get(zone_list);
level = 0; level = 0;
z = (SFZone *)(zone_list->data); gen_list = zone->gen;
gen_list = z->gen;
while(gen_list) while(gen_list)
{ {
@ -1895,7 +1872,7 @@ static int load_igen(SFData *sf, int size)
{ {
/* gen valid? */ /* gen valid? */
READW(sf, genval.sword); READW(sf, genval.sword);
dup = find_gen_by_id(genid, z->gen); dup = find_gen_by_id(genid, zone->gen);
} }
else else
{ {
@ -1939,9 +1916,10 @@ static int load_igen(SFData *sf, int size)
} }
else else
{ {
SLADVREM(z->gen, gen_list); SLADVREM(zone->gen, gen_list);
} }
/* GEN_SAMPLEID should be last generator */
if (level == 3) if (level == 3)
{ {
break; break;
@ -1949,39 +1927,27 @@ static int load_igen(SFData *sf, int size)
} /* generator loop */ } /* 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 */ /* advance to next zone before deleting the current list element */
if(!gzone) zone_list = fluid_list_next(zone_list);
{
gzone = TRUE;
/* if global zone is not 1st zone, relocate */ FLUID_LOG(FLUID_WARN, "Instrument '%s': Discarding invalid global zone",
if(*hz != zone_list) inst->name);
{ inst->zone = fluid_list_remove(inst->zone, zone);
void *save = zone_list->data; delete_zone(zone);
FLUID_LOG(FLUID_WARN, "Instrument '%s': Global zone is not first zone",
((SFPreset *)(inst_list->data))->name); /* we have already advanced the zone_list pointer, so continue with next zone */
SLADVREM(*hz, zone_list); continue;
*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;
}
} }
/* All remaining generators must be invalid and should be discarded
* (because they come after a sampleid generator) */
while(gen_list) while(gen_list)
{ {
/* Kill any zones following a sample */
discarded = TRUE; discarded = TRUE;
if((size -= SF_GEN_SIZE) < 0) if((size -= SF_GEN_SIZE) < 0)
@ -1991,7 +1957,7 @@ static int load_igen(SFData *sf, int size)
} }
FSKIP(sf, SF_GEN_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); /* next zone */
@ -2001,7 +1967,7 @@ static int load_igen(SFData *sf, int size)
{ {
FLUID_LOG(FLUID_WARN, FLUID_LOG(FLUID_WARN,
"Instrument '%s': Some invalid generators were discarded", "Instrument '%s': Some invalid generators were discarded",
((SFInst *)(inst_list->data))->name); inst->name);
} }
inst_list = fluid_list_next(inst_list); inst_list = fluid_list_next(inst_list);