Merge pull request #823 from FluidSynth/refactor-and-fix-sffile-defsfont

Refactor of sffile and defsfont code, including some bugfixes
This commit is contained in:
Marcus Weseloh 2021-04-11 00:25:43 +02:00 committed by GitHub
commit aad6288955
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 269 additions and 455 deletions

View file

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

View file

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

View file

@ -112,39 +112,34 @@ static const uint32_t idlist[] =
SM24_FCC
};
#define Gen_MaxValid Gen_Dummy - 1 /* maximum valid generator */
#define Gen_Count Gen_Dummy /* count of generators */
#define GenArrSize sizeof(SFGenAmount) * Gen_Count /* gen array size */
static const unsigned short invalid_inst_gen[] =
{
Gen_Unused1,
Gen_Unused2,
Gen_Unused3,
Gen_Unused4,
Gen_Reserved1,
Gen_Reserved2,
Gen_Reserved3,
0
GEN_UNUSED1,
GEN_UNUSED2,
GEN_UNUSED3,
GEN_UNUSED4,
GEN_RESERVED1,
GEN_RESERVED2,
GEN_RESERVED3,
GEN_INSTRUMENT,
};
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,
0
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,
GEN_SAMPLEID,
};
@ -244,8 +239,6 @@ static int load_ibag(SFData *sf, int size);
static int load_imod(SFData *sf, int size);
extern 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 +622,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);
@ -1024,9 +1007,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)
{
@ -1091,14 +1074,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");
@ -1116,7 +1099,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)
{
@ -1298,37 +1280,33 @@ static int load_pmod(SFData *sf, int size)
* ------------------------------------------------------------------- */
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)
{
@ -1345,7 +1323,7 @@ int load_pgen(SFData *sf, int size)
READW(sf, genid);
if(genid == Gen_KeyRange)
if(genid == GEN_KEYRANGE)
{
/* nothing precedes */
if(level == 0)
@ -1359,7 +1337,7 @@ 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)
@ -1373,13 +1351,11 @@ 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;
READW(sf, genval.uword);
((SFZone *)(zone_list->data))->instsamp = FLUID_INT_TO_POINTER(genval.uword + 1);
break; /* break out of generator loop */
}
else
{
@ -1389,7 +1365,7 @@ 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
{
@ -1433,49 +1409,38 @@ int load_pgen(SFData *sf, int size)
}
else
{
SLADVREM(z->gen, gen_list); /* drop place holder */
SLADVREM(zone->gen, gen_list); /* drop place holder */
}
/* GEN_INSTRUMENT should be the last generator */
if (level == 3)
{
break;
}
} /* 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 != preset->zone))
{
SLADVREM(z->gen, gen_list); /* zone has inst? */
}
else
{
/* 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);
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)
@ -1485,17 +1450,17 @@ 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);
@ -1645,7 +1610,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)
{
@ -1817,37 +1781,34 @@ static int load_imod(SFData *sf, int size)
/* load instrument generators (see load_pgen for loading rules) */
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)
{
@ -1864,7 +1825,7 @@ int load_igen(SFData *sf, int size)
READW(sf, genid);
if(genid == Gen_KeyRange)
if(genid == GEN_KEYRANGE)
{
/* nothing precedes */
if(level == 0)
@ -1878,7 +1839,7 @@ 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)
@ -1892,13 +1853,11 @@ 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;
READW(sf, genval.uword);
((SFZone *)(zone_list->data))->instsamp = FLUID_INT_TO_POINTER(genval.uword + 1);
break; /* break out of generator loop */
}
else
{
@ -1908,7 +1867,7 @@ 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
{
@ -1952,48 +1911,38 @@ 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;
}
} /* 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))
{
SLADVREM(z->gen, gen_list); /* zone has sample? */
}
else
{
/* 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);
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)
@ -2003,7 +1952,7 @@ 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 */
@ -2013,7 +1962,7 @@ 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);
@ -2068,8 +2017,9 @@ 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);
sf->sample = fluid_list_prepend(sf->sample, p);
READSTR(sf, &p->name);
READD(sf, p->start);
READD(sf, p->end);
@ -2087,98 +2037,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;
}
void delete_preset(SFPreset *preset)
{
fluid_list_t *entry;
@ -2304,37 +2162,46 @@ 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_MaxValid)
/* 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;
}
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;
}

View file

@ -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
@ -89,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 */
};
@ -98,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
@ -130,9 +126,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 */
};
@ -183,44 +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 */
unsigned int library; /* just for preserving them */
unsigned int genre; /* Not used */
unsigned int morphology; /* Not used */
};
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);
@ -236,69 +191,4 @@ void delete_preset(SFPreset *preset);
void delete_inst(SFInst *inst);
void delete_zone(SFZone *zone);
/* 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_Dummy
} Gen_Type;
#endif /* _FLUID_SFFILE_H */

View file

@ -92,20 +92,20 @@ static void good_test_1zone_2gen_1termgen(int (*load_func)(SFData *sf, int size)
const SFGen *gen;
static const unsigned char buf[] =
{
Gen_KeyRange, 0, 60, 127, Gen_VelRange, 0, 60, 127, 0, 0, 0, 0
GEN_KEYRANGE, 0, 60, 127, GEN_VELRANGE, 0, 60, 127, 0, 0, 0, 0
};
SET_BUF(buf);
TEST_ASSERT(load_func(sf, FLUID_N_ELEMENTS(buf)));
gen = fluid_list_get(fluid_list_nth(zone->gen, 0));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_KeyRange);
TEST_ASSERT(gen->id == GEN_KEYRANGE);
TEST_ASSERT(gen->amount.range.lo == 60);
TEST_ASSERT(gen->amount.range.hi == 127);
gen = fluid_list_get(fluid_list_nth(zone->gen, 1));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_VelRange);
TEST_ASSERT(gen->id == GEN_VELRANGE);
TEST_ASSERT(gen->amount.range.lo == 60);
TEST_ASSERT(gen->amount.range.hi == 127);
@ -116,22 +116,22 @@ static void good_test_1zone_2gen_1termgen(int (*load_func)(SFData *sf, int size)
// bad case: too few generators in buffer, triggering a chunk size mismatch
static void bad_test_too_short_gen_buffer(int (*load_func)(SFData *sf, int size), SFData *sf, SFZone *zone)
{
const Gen_Type final_gen = (load_func == &load_pgen) ? Gen_Instrument : Gen_SampleId;
const unsigned char final_gen = (load_func == &load_pgen) ? GEN_INSTRUMENT : GEN_SAMPLEID;
SFGen *gen;
unsigned int i;
static const unsigned char buf1[] = { Gen_KeyRange, 0, 0 };
static const unsigned char buf2[] = { Gen_KeyRange, 0 };
static const unsigned char buf3[] = { Gen_KeyRange };
static const unsigned char buf8[] = { Gen_VelRange, 0, 0 };
static const unsigned char buf9[] = { Gen_VelRange, 0 };
static const unsigned char buf10[] = { Gen_VelRange };
static const unsigned char buf4[] = { Gen_VelRange, 0, 0, 127, Gen_CoarseTune, 0, 4 };
static const unsigned char buf5[] = { Gen_VelRange, 0, 0, 127, Gen_CoarseTune, 0 };
static const unsigned char buf6[] = { Gen_VelRange, 0, 0, 127, Gen_CoarseTune };
const unsigned char buf11[] = { Gen_VelRange, 0, 0, 127, final_gen, 0, 4 };
const unsigned char buf12[] = { Gen_VelRange, 0, 0, 127, final_gen, 0 };
const unsigned char buf13[] = { Gen_VelRange, 0, 0, 127, final_gen };
static const unsigned char buf7[] = { Gen_KeyRange, 0, 60, 127, Gen_OverrideRootKey };
static const unsigned char buf1[] = { GEN_KEYRANGE, 0, 0 };
static const unsigned char buf2[] = { GEN_KEYRANGE, 0 };
static const unsigned char buf3[] = { GEN_KEYRANGE };
static const unsigned char buf8[] = { GEN_VELRANGE, 0, 0 };
static const unsigned char buf9[] = { GEN_VELRANGE, 0 };
static const unsigned char buf10[] = { GEN_VELRANGE };
static const unsigned char buf4[] = { GEN_VELRANGE, 0, 0, 127, GEN_COARSETUNE, 0, 4 };
static const unsigned char buf5[] = { GEN_VELRANGE, 0, 0, 127, GEN_COARSETUNE, 0 };
static const unsigned char buf6[] = { GEN_VELRANGE, 0, 0, 127, GEN_COARSETUNE };
const unsigned char buf11[] = { GEN_VELRANGE, 0, 0, 127, final_gen, 0, 4 };
const unsigned char buf12[] = { GEN_VELRANGE, 0, 0, 127, final_gen, 0 };
const unsigned char buf13[] = { GEN_VELRANGE, 0, 0, 127, final_gen };
static const unsigned char buf7[] = { GEN_KEYRANGE, 0, 60, 127, GEN_OVERRIDEROOTKEY };
static const buf_t buf_with_one_gen[] =
{
@ -181,7 +181,7 @@ static void bad_test_too_short_gen_buffer(int (*load_func)(SFData *sf, int size)
TEST_ASSERT(load_func(sf, FLUID_N_ELEMENTS(buf7)) == FALSE);
gen = fluid_list_get(fluid_list_nth(zone->gen, 0));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_KeyRange);
TEST_ASSERT(gen->id == GEN_KEYRANGE);
TEST_ASSERT(gen->amount.range.lo == 60);
TEST_ASSERT(gen->amount.range.hi == 127);
@ -193,14 +193,14 @@ static void bad_test_too_short_gen_buffer(int (*load_func)(SFData *sf, int size)
static void bad_test_duplicate_gen(int (*load_func)(SFData *sf, int size), SFData *sf, SFZone *zone)
{
const SFGen *gen;
static const unsigned char buf[] = { Gen_CoarseTune, 0, 5, 0, Gen_CoarseTune, 0, 10, 0 };
static const unsigned char buf[] = { GEN_COARSETUNE, 0, 5, 0, GEN_COARSETUNE, 0, 10, 0 };
SET_BUF(buf);
TEST_ASSERT(load_func(sf, FLUID_N_ELEMENTS(buf)));
gen = fluid_list_get(fluid_list_nth(zone->gen, 0));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_CoarseTune);
TEST_ASSERT(gen->id == GEN_COARSETUNE);
TEST_ASSERT(gen->amount.range.lo == 10);
TEST_ASSERT(gen->amount.range.hi == 0);
@ -217,36 +217,34 @@ static void bad_test_gen_wrong_order(int (*load_func)(SFData *sf, int size), SFD
const SFGen *gen;
static const unsigned char buf[] =
{
Gen_VelRange, 0, 60, 127,
Gen_KeyRange, 0, 60, 127,
Gen_Instrument, 0, 0xDD, 0xDD
GEN_VELRANGE, 0, 60, 127,
GEN_KEYRANGE, 0, 60, 127,
GEN_INSTRUMENT, 0, 0xDD, 0xDD
};
SET_BUF(buf);
TEST_ASSERT(load_func(sf, FLUID_N_ELEMENTS(buf)));
gen = fluid_list_get(fluid_list_nth(zone->gen, 0));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_VelRange);
TEST_ASSERT(gen->id == GEN_VELRANGE);
TEST_ASSERT(gen->amount.range.lo == 60);
TEST_ASSERT(gen->amount.range.hi == 127);
// The INSTRUMENT generator is mistakenly accepted by load_igen. This will be fixed by Marcus' PR.
// Once merge, this if clause should be removed.
if (load_func != &load_igen)
{
gen = fluid_list_get(fluid_list_nth(zone->gen, 1));
if (load_func == &load_igen)
{
TEST_ASSERT(gen == NULL);
}
else
{
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == GEN_INSTRUMENT);
TEST_ASSERT(gen->amount.uword == 0xDDDDu);
}
gen = fluid_list_get(fluid_list_nth(zone->gen, 2));
TEST_ASSERT(gen == NULL);
if (load_func == &load_pgen)
{
TEST_ASSERT(FLUID_POINTER_TO_UINT(zone->instsamp) == 0xDDDD + 1);
zone->instsamp = NULL;
}
TEST_ASSERT(file_buf == buf + sizeof(buf));
UNSET_BUF;
}
@ -258,14 +256,14 @@ static void bad_test_issue_808(int (*load_func)(SFData *sf, int size), SFData *s
static const unsigned char buf[] =
{
// zone 1
Gen_ReverbSend, 0, 50, 0,
Gen_VolEnvRelease, 0, 206, 249,
GEN_REVERBSEND, 0, 50, 0,
GEN_VOLENVRELEASE, 0, 206, 249,
// zone 2
Gen_KeyRange, 0, 0, 35,
Gen_OverrideRootKey, 0, 43, 0,
Gen_StartAddrCoarseOfs, 0, 0, 0,
Gen_SampleModes, 0, 1, 0,
Gen_StartAddrOfs, 0, 0, 0
GEN_KEYRANGE, 0, 0, 35,
GEN_OVERRIDEROOTKEY, 0, 43, 0,
GEN_STARTADDRCOARSEOFS, 0, 0, 0,
GEN_SAMPLEMODE, 0, 1, 0,
GEN_STARTADDROFS, 0, 0, 0
};
SET_BUF(buf);
@ -273,13 +271,13 @@ static void bad_test_issue_808(int (*load_func)(SFData *sf, int size), SFData *s
gen = fluid_list_get(fluid_list_nth(zone1->gen, 0));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_ReverbSend);
TEST_ASSERT(gen->id == GEN_REVERBSEND);
TEST_ASSERT(gen->amount.range.lo == 50);
TEST_ASSERT(gen->amount.range.hi == 0);
gen = fluid_list_get(fluid_list_nth(zone1->gen, 1));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_VolEnvRelease);
TEST_ASSERT(gen->id == GEN_VOLENVRELEASE);
TEST_ASSERT(gen->amount.range.lo == 206);
TEST_ASSERT(gen->amount.range.hi == 249);
@ -295,48 +293,48 @@ static void bad_test_additional_gens_after_final_gen(int (*load_func)(SFData *sf
{
unsigned int i;
SFGen *gen;
const Gen_Type final_gen = (load_func == &load_pgen) ? Gen_Instrument : Gen_SampleId;
const unsigned char final_gen = (load_func == &load_pgen) ? GEN_INSTRUMENT : GEN_SAMPLEID;
const unsigned char buf1[] =
{
// zone 1
Gen_KeyRange, 0, 60, 127,
Gen_Unused1, 0, 0xFF, 0xFF,
GEN_KEYRANGE, 0, 60, 127,
GEN_UNUSED1, 0, 0xFF, 0xFF,
final_gen, 0, 0xDD, 0xDD,
Gen_KeyRange, 0, 0, 35,
Gen_OverrideRootKey, 0, 43, 0,
GEN_KEYRANGE, 0, 0, 35,
GEN_OVERRIDEROOTKEY, 0, 43, 0,
0, 0, 0, 0 // terminal generator
};
const unsigned char buf2[] =
{
// zone 1
Gen_KeyRange, 0, 60, 127,
Gen_Unused1, 0, 0xFF, 0xFF,
GEN_KEYRANGE, 0, 60, 127,
GEN_UNUSED1, 0, 0xFF, 0xFF,
final_gen, 0, 0xDD, 0xDD,
Gen_KeyRange, 0, 0, 35,
Gen_OverrideRootKey, 0, 43, 0,
GEN_KEYRANGE, 0, 0, 35,
GEN_OVERRIDEROOTKEY, 0, 43, 0,
0, 0, 0 // incomplete terminal generator
};
const unsigned char buf3[] =
{
// zone 1
Gen_KeyRange, 0, 60, 127,
Gen_Unused1, 0, 0xFF, 0xFF,
GEN_KEYRANGE, 0, 60, 127,
GEN_UNUSED1, 0, 0xFF, 0xFF,
final_gen, 0, 0xDD, 0xDD,
Gen_KeyRange, 0, 0, 35,
Gen_OverrideRootKey, 0, 43
GEN_KEYRANGE, 0, 0, 35,
GEN_OVERRIDEROOTKEY, 0, 43
};
const unsigned char buf4[] =
{
// zone 1
Gen_KeyRange, 0, 60, 127,
Gen_Unused1, 0, 0xFF, 0xFF,
GEN_KEYRANGE, 0, 60, 127,
GEN_UNUSED1, 0, 0xFF, 0xFF,
final_gen, 0, 0xDD, 0xDD,
Gen_KeyRange, 0, 0, 35,
Gen_OverrideRootKey, 0
GEN_KEYRANGE, 0, 0, 35,
GEN_OVERRIDEROOTKEY, 0
};
const buf_t buf[] =
@ -357,7 +355,7 @@ static void bad_test_additional_gens_after_final_gen(int (*load_func)(SFData *sf
gen = fluid_list_get(fluid_list_nth(zone1->gen, 0));
TEST_ASSERT(gen != NULL);
TEST_ASSERT(gen->id == Gen_KeyRange);
TEST_ASSERT(gen->id == GEN_KEYRANGE);
TEST_ASSERT(gen->amount.range.lo == 60);
TEST_ASSERT(gen->amount.range.hi == 127);
@ -366,7 +364,19 @@ static void bad_test_additional_gens_after_final_gen(int (*load_func)(SFData *sf
zone1->gen->data = NULL;
gen = fluid_list_get(fluid_list_nth(zone1->gen, 1));
TEST_ASSERT(gen == NULL);
TEST_ASSERT(gen != NULL);
if (load_func == &load_igen)
{
TEST_ASSERT(gen->id == GEN_SAMPLEID);
}
else
{
TEST_ASSERT(gen->id == GEN_INSTRUMENT);
}
TEST_ASSERT(gen->amount.uword == 0xDDDDu);
// delete this generator
FLUID_FREE(gen);
zone1->gen->data = NULL;
gen = fluid_list_get(fluid_list_nth(zone1->gen, 2));
TEST_ASSERT(gen == NULL);
@ -377,9 +387,6 @@ static void bad_test_additional_gens_after_final_gen(int (*load_func)(SFData *sf
gen = fluid_list_get(fluid_list_nth(zone1->gen, 4));
TEST_ASSERT(gen == NULL);
TEST_ASSERT(FLUID_POINTER_TO_UINT(zone1->instsamp) == 0xDDDD + 1);
zone1->instsamp = NULL;
TEST_ASSERT(file_buf == buf[i].end);
UNSET_BUF;