diff --git a/src/sfloader/fluid_defsfont.c b/src/sfloader/fluid_defsfont.c index 9f4a2d78..c45696fc 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; } @@ -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) */ 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 931da8f9..72ac9e1e 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -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); - 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) @@ -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); - 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) @@ -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; } diff --git a/src/sfloader/fluid_sffile.h b/src/sfloader/fluid_sffile.h index b1574c3f..5275c625 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 @@ -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 */ diff --git a/test/test_sfont_zone.c b/test/test_sfont_zone.c index b65c7c64..297d4f83 100644 --- a/test/test_sfont_zone.c +++ b/test/test_sfont_zone.c @@ -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) { - gen = fluid_list_get(fluid_list_nth(zone->gen, 1)); 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;