欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

sfload.c

A GTK sound font editor. Sound font files are used to synthesize instruments from audio samples for
C
第 1 页 / 共 3 页
字号:
	  z->gen = NULL;	/* In case of failure, */	  z->mod = NULL;	/* sfont_close can clean up */	  READW (genndx, fd);	/* READW = possible read failure */	  READW (modndx, fd);	  z->instsamp = NULL;	  if (pz)	    {			/* if not first zone */	      if (genndx < pgenndx)		return (logit (LogFubar,		    _("Instrument generator indices not monotonic")));	      if (modndx < pmodndx)		return (logit (LogFubar,		    _("Instrument 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;	  pmodndx = modndx;	  p2 = g_slist_next (p2);	}      p = g_slist_next (p);    }  size -= SFBAGSIZE;  if (size != 0)    return (logit (LogFubar, _("Instrument chunk size mismatch")));  READW (genndx, fd);  READW (modndx, fd);  if (!pz)    {				/* in case that all are no zoners */      if (genndx > 0)	logit (LogWarn,	  _("No instrument generators and terminal index not 0"));      if (modndx > 0)	logit (LogWarn,	  _("No instrument modulators and terminal index not 0"));      return (OK);    }  if (genndx < pgenndx)    return (logit (LogFubar, _("Instrument generator indices not monotonic")));  if (modndx < pmodndx)    return (logit (LogFubar, _("Instrument 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);}/* instrument modulator loader */static gintload_imod (gint32 size, SFData * sf, FILE * fd){  GSList *p, *p2, *p3;  SFMod *m;  p = sf->inst;  while (p)    {				/* traverse through all inst */      p2 = ((SFInst *) (p->data))->zone;      while (p2)	{			/* traverse this inst's zones */	  p3 = ((SFZone *) (p2->data))->mod;	  while (p3)	    {			/* load zone's modulators */	      if ((size -= SFMODSIZE) < 0)		return (logit (LogFubar,		    _("Instrument 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, _("Instrument modulator chunk size mismatch")));  FSKIP (SFMODSIZE, fd);	/* terminal mod */  return (OK);}/* load instrument generators (see load_pgen for loading rules) */static gintload_igen (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->inst;  while (p)    {				/* traverse through all instruments */      gzone = FALSE;      discarded = FALSE;      p2 = ((SFInst *) (p->data))->zone;      if (p2)	hz = &p2;      while (p2)	{			/* traverse this instrument'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, _("IGEN 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_SampleId)		{		/* sample 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_valid (genid))		    {		/* gen 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);		      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);	    }			/* generator loop */	  if (level == 3)	    SLADVREM (z->gen, p3);	/* zone has sample? */	  else	    {			/* its a global zone */	      if (!gzone)		{		  gzone = TRUE;		  /* if global zone is not 1st zone, relocate */		  if (*hz != p2)		    {		      gpointer save = p2->data;		      logit (LogWarn,			_("Instrument \"%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,		    _("Instrument \"%s\": Discarding invalid global zone"),		    ((SFInst *) (p->data))->name);		  sfont_remove_zone (sf, hz, (SFZone *) (p2->data));		}	    }	  while (p3)	    {			/* Kill any zones following a sample */	      discarded = TRUE;	      if ((size -= SFGENSIZE) < 0)		return (logit (LogFubar,		    _("Instrument generator chunk size mismatch")));	      FSKIP (SFGENSIZE, fd);	      SLADVREM (z->gen, p3);	    }	  p2 = g_slist_next (p2);	/* next zone */	}      if (discarded)	logit (LogWarn,	  _("Instrument \"%s\": Some invalid generators were discarded"),	  ((SFInst *) (p->data))->name);      p = g_slist_next (p);    }  /* for those non-terminal record cases, grr! */  if (size == 0)    return (OK);  size -= SFGENSIZE;  if (size != 0)    return (logit (LogFubar, _("IGEN chunk size mismatch")));  FSKIP (SFGENSIZE, fd);	/* terminal gen */  return (OK);}/* sample header loader */static gintload_shdr (gint32 size, SFData * sf, FILE * fd){  guint32 i;  SFSample *p;  if (size % SFSHDRSIZE || size == 0)	/* size is multiple of SHDR size? */    return (logit (LogFubar, _("Sample header has invalid size")));  size = size / SFSHDRSIZE - 1;  if (size == 0)    {				/* at least one sample + term record? */      logit (LogWarn, _("File contains no samples"));      FSKIP (SFSHDRSIZE, fd);      return (OK);    }  /* load all sample headers */  for (i = 0; i < size; i++)    {      p = sfont_sample_alloc ();      sf->sample = g_slist_append (sf->sample, p);      p->datainfo = sam_datainfo_new ();  /* create new sam data info struct */      p->datainfo->samfile = FALSE;  /* sample is in sound font */      p->datainfo->sf = sf;      p->datainfo->refcount++;  /* update reference count */      READSTR (&p->name, fd);      READD (p->datainfo->start, fd);      READD (p->end, fd);	/* - end, loopstart and loopend */      READD (p->loopstart, fd);	/* - will be checked and turned into */      READD (p->loopend, fd);	/* - offsets in fixup_sample() */      READD (p->samplerate, fd);      READB (p->origpitch, fd);      READB (p->pitchadj, fd);      FSKIPW (fd);		/* skip sample link */      READW (p->sampletype, fd);    }  FSKIP (SFSHDRSIZE, fd);	/* skip terminal shdr */  return (OK);}/* "fixup" (inst # -> inst ptr) instrument references in preset list */static gintfixup_pgen (SFData * sf){  GSList *p, *p2, *p3;  SFZone *z;  gint i;  p = sf->preset;  while (p)    {      p2 = ((SFPreset *) (p->data))->zone;      while (p2)	{			/* traverse this preset's zones */	  z = (SFZone *) (p2->data);	  if ((i = GPOINTER_TO_INT (z->instsamp)))	    {			/* load instrument # */	      p3 = g_slist_nth (sf->inst, i - 1);	      if (!p3)		return (logit (LogFubar,		    _("Preset %03d %03d: Invalid instrument reference"),		    ((SFPreset *) (p->data))->bank,		    ((SFPreset *) (p->data))->prenum));	      z->instsamp = p3;	    }	  else	    z->instsamp = NULL;	  p2 = g_slist_next (p2);	}      p = g_slist_next (p);    }  return (OK);}/* "fixup" (sample # -> sample ptr) sample references in instrument list */static gintfixup_igen (SFData * sf){  GSList *p, *p2, *p3;  SFZone *z;  gint i;  p = sf->inst;  while (p)    {      p2 = ((SFInst *) (p->data))->zone;      while (p2)	{			/* traverse instrument's zones */	  z = (SFZone *) (p2->data);	  if ((i = GPOINTER_TO_INT (z->instsamp)))	    {			/* load sample # */	      p3 = g_slist_nth (sf->sample, i - 1);	      if (!p3)		return (logit (LogFubar,		    _("Instrument \"%s\": Invalid sample reference"),		    ((SFInst *) (p->data))->name));	      z->instsamp = p3;	    }	  p2 = g_slist_next (p2);	}      p = g_slist_next (p);    }  return (OK);}/* convert sample end, loopstart and loopend to offsets and check if valid */static gintfixup_sample (SFData * sf){  GSList *p;  SFSample *sam;  p = sf->sample;  while (p)    {      sam = (SFSample *) (p->data);      /* if sample is not a ROM sample and end is over the sample data chunk         or sam start is greater than 4 less than the end (at least 4 samples) */      if ((!(sam->sampletype & SF_SAMPLETYPE_ROM)	  && sam->end > sdtachunk_size)	  || sam->datainfo->start > (sam->end - 4))	{	  logit (LogWarn, _("Sample '%s' start/end file positions are invalid,"	      " disabling and will not be saved"), sam->name);	  /* disable sample by setting all sample markers to 0 */	  sam->datainfo->start = sam->end = sam->loopstart = sam->loopend = 0;	  return (OK);	}      else if (sam->loopend > sam->end || sam->loopstart >= sam->loopend	|| sam->loopstart <= sam->datainfo->start)	{			/* loop is fowled?? (cluck cluck :) */	  /* can pad loop by 8 samples and ensure at least 4 for loop (2*8+4) */	  if ((sam->end - sam->datainfo->start) >= 20)	    {	      sam->loopstart = sam->datainfo->start + 8;	      sam->loopend = sam->end - 8;	    }	  else	    {			/* loop is fowled, sample is tiny (can't pad 8 samples) */	      sam->loopstart = sam->datainfo->start + 1;	      sam->loopend = sam->end - 1;	    }	}      /* convert sample end, loopstart, loopend to offsets from sam->start */      sam->end -= sam->datainfo->start + 1;	/* marks last sample, contrary to SF spec. (wish I hadn't done this, will change again later) */      sam->loopstart -= sam->datainfo->start;      sam->loopend -= sam->datainfo->start;      sam->datainfo->size = sam->end + 1;  /* update sam data info size */      p = g_slist_next (p);    }  return (OK);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -