sfload.c
字号:
static gintload_phdr (gint32 size, SFData * sf, FILE * fd){ gint i, i2; SFPreset *p, *pr = NULL; /* ptr to current & previous preset */ guint16 zndx, pzndx; if (size % SFPHDRSIZE || size == 0) return (logit (LogFubar, _("Preset header chunk size is invalid"))); i = size / SFPHDRSIZE - 1; if (i == 0) { /* at least one preset + term record */ logit (LogWarn, _("File contains no presets")); FSKIP (SFPHDRSIZE, fd); return (OK); } for (; i > 0; i--) { /* load all preset headers */ p = sfont_preset_alloc (); sf->preset = g_slist_append (sf->preset, p); READSTR (&p->name, fd); READW (p->prenum, fd); READW (p->bank, fd); READW (zndx, fd); READD (p->libr, fd); READD (p->genre, fd); READD (p->morph, fd); if (pr) { /* not first preset? */ if (zndx < pzndx) return (logit (LogFubar, _("Preset header indices not monotonic"))); i2 = zndx - pzndx; while (i2--) { pr->zone = g_slist_prepend (pr->zone, NULL); } } else if (zndx > 0) /* 1st preset, warn if ofs >0 */ logit (LogWarn, _("%d preset zones not referenced, discarding"), zndx); pr = p; /* update preset ptr */ pzndx = zndx; } FSKIP (24, fd); READW (zndx, fd); /* Read terminal generator index */ FSKIP (12, fd); if (zndx < pzndx) return (logit (LogFubar, _("Preset header indices not monotonic"))); i2 = zndx - pzndx; while (i2--) { pr->zone = g_slist_prepend (pr->zone, NULL); } return (OK);}/* preset bag loader */static gintload_pbag (gint32 size, SFData * sf, FILE * fd){ GSList *p, *p2; SFZone *z, *pz = NULL; guint16 genndx, modndx; guint16 pgenndx, pmodndx; guint16 i; if (size % SFBAGSIZE || size == 0) /* size is multiple of SFBAGSIZE? */ return (logit (LogFubar, _("Preset bag chunk size is invalid"))); p = sf->preset; while (p) { /* traverse through presets */ p2 = ((SFPreset *) (p->data))->zone; while (p2) { /* traverse preset's zones */ if ((size -= SFBAGSIZE) < 0) return (logit (LogFubar, _("Preset bag chunk size mismatch"))); z = sfont_zone_alloc (); p2->data = z; z->gen = NULL; /* Init gen and mod before possible failure, */ z->mod = NULL; /* to ensure proper cleanup (sfont_close) */ READW (genndx, fd); /* possible read failure ^ */ READW (modndx, fd); z->instsamp = NULL; if (pz) { /* if not first zone */ if (genndx < pgenndx) return (logit (LogFubar, _("Preset bag generator indices not monotonic"))); if (modndx < pmodndx) return (logit (LogFubar, _("Preset bag modulator indices not monotonic"))); i = genndx - pgenndx; while (i--) pz->gen = g_slist_prepend (pz->gen, NULL); i = modndx - pmodndx; while (i--) pz->mod = g_slist_prepend (pz->mod, NULL); } pz = z; /* update previous zone ptr */ pgenndx = genndx; /* update previous zone gen index */ pmodndx = modndx; /* update previous zone mod index */ p2 = g_slist_next (p2); } p = g_slist_next (p); } size -= SFBAGSIZE; if (size != 0) return (logit (LogFubar, _("Preset bag chunk size mismatch"))); READW (genndx, fd); READW (modndx, fd); if (!pz) { if (genndx > 0) logit (LogWarn, _("No preset generators and terminal index not 0")); if (modndx > 0) logit (LogWarn, _("No preset modulators and terminal index not 0")); return (OK); } if (genndx < pgenndx) return (logit (LogFubar, _("Preset bag generator indices not monotonic"))); if (modndx < pmodndx) return (logit (LogFubar, _("Preset bag modulator indices not monotonic"))); i = genndx - pgenndx; while (i--) pz->gen = g_slist_prepend (pz->gen, NULL); i = modndx - pmodndx; while (i--) pz->mod = g_slist_prepend (pz->mod, NULL); return (OK);}/* preset modulator loader */static gintload_pmod (gint32 size, SFData * sf, FILE * fd){ GSList *p, *p2, *p3; SFMod *m; p = sf->preset; while (p) { /* traverse through all presets */ p2 = ((SFPreset *) (p->data))->zone; while (p2) { /* traverse this preset's zones */ p3 = ((SFZone *) (p2->data))->mod; while (p3) { /* load zone's modulators */ if ((size -= SFMODSIZE) < 0) return (logit (LogFubar, _("Preset modulator chunk size mismatch"))); m = sfont_mod_alloc (); p3->data = m; READW (m->src, fd); READW (m->dest, fd); READW (m->amount, fd); READW (m->amtsrc, fd); READW (m->trans, fd); p3 = g_slist_next (p3); } p2 = g_slist_next (p2); } p = g_slist_next (p); } /* If there isn't even a terminal record Hmmm, the specs say there should be one, but.. */ if (size == 0) return (OK); size -= SFMODSIZE; if (size != 0) return (logit (LogFubar, _("Preset modulator chunk size mismatch"))); FSKIP (SFMODSIZE, fd); /* terminal mod */ return (OK);}/* ------------------------------------------------------------------- * preset generator loader * generator (per preset) loading rules: * Zones with no generators or modulators shall be annihilated * Global zone must be 1st zone, discard additional ones (instrumentless zones) * * generator (per zone) loading rules (in order of decreasing precedence): * KeyRange is 1st in list (if exists), else discard * if a VelRange exists only preceded by a KeyRange, else discard * if a generator follows an instrument discard it * if a duplicate generator exists replace previous one * ------------------------------------------------------------------- */static gintload_pgen (gint32 size, SFData * sf, FILE * fd){ GSList *p, *p2, *p3, *dup, **hz; SFZone *z; SFGen *g; SFGenAmount genval; guint16 genid; gint level, skip, drop, gzone, discarded; p = sf->preset; while (p) { /* traverse through all presets */ gzone = FALSE; discarded = FALSE; p2 = ((SFPreset *) (p->data))->zone; if (p2) hz = &p2; while (p2) { /* traverse preset's zones */ level = 0; z = (SFZone *) (p2->data); p3 = z->gen; while (p3) { /* load zone's generators */ dup = NULL; skip = FALSE; drop = FALSE; if ((size -= SFGENSIZE) < 0) return (logit (LogFubar, _("Preset generator chunk size mismatch"))); READW (genid, fd); if (genid == Gen_KeyRange) { /* nothing precedes */ if (level == 0) { level = 1; READB (genval.range.lo, fd); READB (genval.range.hi, fd); } else skip = TRUE; } else if (genid == Gen_VelRange) { /* only KeyRange precedes */ if (level <= 1) { level = 2; READB (genval.range.lo, fd); READB (genval.range.hi, fd); } else skip = TRUE; } else if (genid == Gen_Instrument) { /* inst is last gen */ level = 3; READW (genval.uword, fd); GPOINTER_TO_INT (((SFZone *) (p2->data))->instsamp) = genval.uword + 1; break; /* break out of generator loop */ } else { level = 2; if (gen_validp (genid)) { /* generator valid? */ READW (genval.sword, fd); dup = gen_inlist (genid, z->gen); } else skip = TRUE; } if (!skip) { if (!dup) { /* if gen ! dup alloc new */ g = sfont_gen_alloc (); p3->data = g; g->id = genid; } else { g = (SFGen *) (dup->data); /* ptr to orig gen */ drop = TRUE; } g->amount = genval; } else { /* Skip this generator */ discarded = TRUE; drop = TRUE; FSKIPW (fd); } if (!drop) p3 = g_slist_next (p3); /* next gen */ else SLADVREM (z->gen, p3); /* drop place holder */ } /* generator loop */ if (level == 3) SLADVREM (z->gen, p3); /* zone has inst? */ else { /* congratulations its a global zone */ if (!gzone) { /* Prior global zones? */ gzone = TRUE; /* if global zone is not 1st zone, relocate */ if (*hz != p2) { gpointer save = p2->data; logit (LogWarn, _("Preset \"%s\": Global zone is not first zone"), ((SFPreset *) (p->data))->name); SLADVREM (*hz, p2); *hz = g_slist_prepend (*hz, save); continue; } } else { /* previous global zone exists, discard */ logit (LogWarn, _("Preset \"%s\": Discarding invalid global zone"), ((SFPreset *) (p->data))->name); sfont_remove_zone (sf, hz, (SFZone *) (p2->data)); } } while (p3) { /* Kill any zones following an instrument */ discarded = TRUE; if ((size -= SFGENSIZE) < 0) return (logit (LogFubar, _("Preset generator chunk size mismatch"))); FSKIP (SFGENSIZE, fd); SLADVREM (z->gen, p3); } p2 = g_slist_next (p2); /* next zone */ } if (discarded) logit (LogWarn, _("Preset \"%s\": Some invalid generators were discarded"), ((SFPreset *) (p->data))->name); p = g_slist_next (p); } /* in case there isn't a terminal record */ if (size == 0) return (OK); size -= SFGENSIZE; if (size != 0) return (logit (LogFubar, _("Preset generator chunk size mismatch"))); FSKIP (SFGENSIZE, fd); /* terminal gen */ return (OK);}/* instrument header loader */static gintload_ihdr (gint32 size, SFData * sf, FILE * fd){ gint i, i2; SFInst *p, *pr = NULL; /* ptr to current & previous instrument */ guint16 zndx, pzndx; if (size % SFIHDRSIZE || size == 0) /* chunk size is valid? */ return (logit (LogFubar, _("Instrument header has invalid size"))); size = size / SFIHDRSIZE - 1; if (size == 0) { /* at least one preset + term record */ logit (LogWarn, _("File contains no instruments")); FSKIP (SFIHDRSIZE, fd); return (OK); } for (i = 0; i < size; i++) { /* load all instrument headers */ p = sfont_inst_alloc (); sf->inst = g_slist_append (sf->inst, p); READSTR (&p->name, fd); READW (zndx, fd); if (pr) { /* not first instrument? */ if (zndx < pzndx) return (logit (LogFubar, _("Instrument header indices not monotonic"))); i2 = zndx - pzndx; while (i2--) pr->zone = g_slist_prepend (pr->zone, NULL); } else if (zndx > 0) /* 1st inst, warn if ofs >0 */ logit (LogWarn, _("%d instrument zones not referenced, discarding"), zndx); pzndx = zndx; pr = p; /* update instrument ptr */ } FSKIP (20, fd); READW (zndx, fd); if (zndx < pzndx) return (logit (LogFubar, _("Instrument header indices not monotonic"))); i2 = zndx - pzndx; while (i2--) pr->zone = g_slist_prepend (pr->zone, NULL); return (OK);}/* instrument bag loader */static gintload_ibag (gint32 size, SFData * sf, FILE * fd){ GSList *p, *p2; SFZone *z, *pz = NULL; guint16 genndx, modndx, pgenndx, pmodndx; gint i; if (size % SFBAGSIZE || size == 0) /* size is multiple of SFBAGSIZE? */ return (logit (LogFubar, _("Instrument bag chunk size is invalid"))); p = sf->inst; while (p) { /* traverse through inst */ p2 = ((SFInst *) (p->data))->zone; while (p2) { /* load this inst's zones */ if ((size -= SFBAGSIZE) < 0) return (logit (LogFubar, _("Instrument bag chunk size mismatch"))); z = sfont_zone_alloc (); p2->data = z;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -