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.
This commit is contained in:
Marcus Weseloh 2021-03-27 16:56:24 +01:00
parent 6ca9b21740
commit dfbef11da0
4 changed files with 87 additions and 140 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;
}
@ -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

@ -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 */
}
} /* generator loop */
/* Level 3 means we found an instrument generator, which
* should be the last generator in the list. */
if (level == 3)
{
SLADVREM(z->gen, gen_list); /* zone has inst? */
break;
}
else
} /* 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)
{
/* 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);
}
} /* generator loop */
if (level == 3)
{
SLADVREM(z->gen, gen_list); /* zone has sample? */
break;
}
else
} /* generator loop */
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;

View file

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