⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resample.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 2 页
字号:
  INTERPVARS;  Voice *vp=&voice[v];  resample_t     *dest=resample_buffer;   sample_t     *src=vp->sample->data;  int32     le=vp->sample->data_length,    ofs=vp->sample_offset,     incr=vp->sample_increment,     count=*countptr;  int     cc=vp->vibrato_control_counter;  /* This has never been tested */  if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */  while (count--)    {      if (!cc--)	{	  cc=vp->vibrato_control_ratio;	  incr=update_vibrato(vp, 0);	}      RESAMPLATION;      ofs += incr;      if (ofs >= le)	{	  FINALINTERP;	  vp->status=VOICE_FREE; 	  ctl->note(v);	  *countptr-=count+1;	  break;	}    }    vp->vibrato_control_counter=cc;  vp->sample_increment=incr;  vp->sample_offset=ofs; /* Update offset */  return resample_buffer;}static resample_t *rs_vib_loop(Voice *vp, int32 count){  /* Play sample until end-of-loop, skip back and continue. */    INTERPVARS;  int32     ofs=vp->sample_offset,     incr=vp->sample_increment,     le=vp->sample->loop_end,    ll=le - vp->sample->loop_start;  resample_t     *dest=resample_buffer;   sample_t     *src=vp->sample->data;  int     cc=vp->vibrato_control_counter;#ifdef PRECALC_LOOPS  int32 i;  int    vibflag=0;  while (count)     {      /* Hopefully the loop is longer than an increment */      if(ofs >= le)	ofs -= ll;      /* Precalc how many times to go through the loop, taking	 the vibrato control ratio into account this time. */      i = (le - ofs) / incr + 1;      if(i > count) i = count;      if(i > cc)	{	  i = cc;	  vibflag = 1;	}       else cc -= i;      count -= i;      while(i--) 	{	  RESAMPLATION;	  ofs += incr;	}      if(vibflag) 	{	  cc = vp->vibrato_control_ratio;	  incr = update_vibrato(vp, 0);	  vibflag = 0;	}    }#else /* PRECALC_LOOPS */  while (count--)    {      if (!cc--)	{	  cc=vp->vibrato_control_ratio;	  incr=update_vibrato(vp, 0);	}      RESAMPLATION;      ofs += incr;      if (ofs>=le)	ofs -= ll; /* Hopefully the loop is longer than an increment. */    }#endif /* PRECALC_LOOPS */  vp->vibrato_control_counter=cc;  vp->sample_increment=incr;  vp->sample_offset=ofs; /* Update offset */  return resample_buffer;}static resample_t *rs_vib_bidir(Voice *vp, int32 count){  INTERPVARS;  int32     ofs=vp->sample_offset,     incr=vp->sample_increment,    le=vp->sample->loop_end,     ls=vp->sample->loop_start;  resample_t     *dest=resample_buffer;   sample_t     *src=vp->sample->data;  int     cc=vp->vibrato_control_counter;#ifdef PRECALC_LOOPS  int32    le2=le<<1,    ls2=ls<<1,    i;  int    vibflag = 0;  /* Play normally until inside the loop region */  while (count && (ofs <= ls))     {      i = (ls - ofs) / incr + 1;      if (i > count) i = count;      if (i > cc) 	{	  i = cc;	  vibflag = 1;	}       else cc -= i;      count -= i;      while (i--) 	{	  RESAMPLATION;	  ofs += incr;	}      if (vibflag) 	{	  cc = vp->vibrato_control_ratio;	  incr = update_vibrato(vp, 0);	  vibflag = 0;	}    }    /* Then do the bidirectional looping */  while (count)     {      /* Precalc how many times we should go through the loop */      i = ((incr > 0 ? le : ls) - ofs) / incr + 1;      if(i > count) i = count;      if(i > cc) 	{	  i = cc;	  vibflag = 1;	}       else cc -= i;      count -= i;      while (i--) 	{	  RESAMPLATION;	  ofs += incr;	}      if (vibflag) 	{	  cc = vp->vibrato_control_ratio;	  incr = update_vibrato(vp, (incr < 0));	  vibflag = 0;	}      if (ofs >= le) 	{	  /* fold the overshoot back in */	  ofs = le2 - ofs;	  incr *= -1;	}       else if (ofs <= ls) 	{	  ofs = ls2 - ofs;	  incr *= -1;	}    }#else /* PRECALC_LOOPS */  /* Play normally until inside the loop region */  if (ofs < ls)    {      while (count--)	{	  if (!cc--)	    {	      cc=vp->vibrato_control_ratio;	      incr=update_vibrato(vp, 0);	    }	  RESAMPLATION;	  ofs += incr;	  if (ofs>=ls)	    break;	}    }  /* Then do the bidirectional looping */  if (count>0)    while (count--)      {	if (!cc--)	  {	    cc=vp->vibrato_control_ratio;	    incr=update_vibrato(vp, (incr < 0));	  }	RESAMPLATION;	ofs += incr;	if (ofs>=le)	  {	    /* fold the overshoot back in */	    ofs = le - (ofs - le);	    incr = -incr;	  }	else if (ofs <= ls)	  {	    ofs = ls + (ls - ofs);	    incr = -incr;	  }      }#endif /* PRECALC_LOOPS */  vp->vibrato_control_counter=cc;  vp->sample_increment=incr;  vp->sample_offset=ofs; /* Update offset */  return resample_buffer;}resample_t *resample_voice(int v, int32 *countptr){  int32 ofs;  uint8 modes;  Voice *vp=&voice[v];    if (!(vp->sample->sample_rate))    {      /* Pre-resampled data -- just update the offset and check if         we're out of data. */      ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use						 FRACTION_BITS here... */      if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs)	{	  /* Note finished. Free the voice. */	  vp->status = VOICE_FREE;	  ctl->note(v);	  	  /* Let the caller know how much data we had left */	  *countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs;	}      else	vp->sample_offset += *countptr << FRACTION_BITS;            return (resample_t *)vp->sample->data+ofs;    }  /* Need to resample. Use the proper function. */  modes=vp->sample->modes;  if (vp->vibrato_control_ratio)    {      if ((modes & MODES_LOOPING) &&	  ((modes & MODES_ENVELOPE) ||	   (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))	{	  if (modes & MODES_PINGPONG)	    return rs_vib_bidir(vp, *countptr);	  else	    return rs_vib_loop(vp, *countptr);	}      else	return rs_vib_plain(v, countptr);    }  else    {      if ((modes & MODES_LOOPING) &&	  ((modes & MODES_ENVELOPE) ||	   (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))	{	  if (modes & MODES_PINGPONG)	    return rs_bidir(vp, *countptr);	  else	    return rs_loop(vp, *countptr);	}      else	return rs_plain(v, countptr);    }}void pre_resample(Sample * sp){  double a, xdiff;  int32 incr, ofs, newlen, count;  int16 *src = (int16 *) sp->data;  resample_t *newdata, *dest;  int16 v1, v2, v3, v4, *vptr;  static const char note_name[12][3] =  {    "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"  };  ctl->cmsg(CMSG_INFO, VERB_NOISY, " * pre-resampling for note %d (%s%d)",	    sp->note_to_use,	    note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12);  a = ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]) /    ((double) (sp->root_freq) * play_mode->rate);  if (a <= 0) return;  newlen = (int32)(sp->data_length / a);  if (newlen < 0 || (newlen >> FRACTION_BITS) > MAX_SAMPLE_SIZE) return;  dest = newdata = safe_malloc(newlen >> (FRACTION_BITS - 1));  count = (newlen >> FRACTION_BITS) - 1;  ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;  if (--count)    *dest++ = src[0];  /* Since we're pre-processing and this doesn't have to be done in     real-time, we go ahead and do the full sliding cubic interpolation. */  while (--count)    {      vptr = src + (ofs >> FRACTION_BITS);      v1 = *(vptr - 1);      v2 = *vptr;      v3 = *(vptr + 1);      v4 = *(vptr + 2);      xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS);      *dest++ = (int16)(v2 + (xdiff / 6.0) * (-2 * v1 - 3 * v2 + 6 * v3 - v4 +      xdiff * (3 * (v1 - 2 * v2 + v3) + xdiff * (-v1 + 3 * (v2 - v3) + v4))));      ofs += incr;    }  if (ofs & FRACTION_MASK)    {      v1 = src[ofs >> FRACTION_BITS];      v2 = src[(ofs >> FRACTION_BITS) + 1];      *dest++ = (resample_t)(v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS));    }  else    *dest++ = src[ofs >> FRACTION_BITS];  sp->data_length = newlen;  sp->loop_start = (int32)(sp->loop_start / a);  sp->loop_end = (int32)(sp->loop_end / a);  free(sp->data);  sp->data = (sample_t *) newdata;  sp->sample_rate = 0;}

⌨️ 快捷键说明

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