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

📄 resample.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    TiMidity -- Experimental MIDI to WAVE converter    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    resample.c*/#include <math.h>#include <stdio.h>#include <stdlib.h>#include "config.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "output.h"#include "ctrlmode.h"#include "tables.h"#include "resample.h"#ifdef LINEAR_INTERPOLATION# if defined(LOOKUP_HACK) && defined(LOOKUP_INTERPOLATION)#   define RESAMPLATION \       v1=src[ofs>>FRACTION_BITS];\       v2=src[(ofs>>FRACTION_BITS)+1];\       *dest++ = (resample_t)(v1 + (iplookup[(((v2-v1)<<5) & 0x03FE0) | \           ((ofs & FRACTION_MASK) >> (FRACTION_BITS-5))]));# else#   define RESAMPLATION \      v1=src[ofs>>FRACTION_BITS];\      v2=src[(ofs>>FRACTION_BITS)+1];\      *dest++ = (resample_t)(v1 + (((v2-v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS));# endif#  define INTERPVARS sample_t v1, v2#else/* Earplugs recommended for maximum listening enjoyment */#  define RESAMPLATION *dest++ = src[ofs>>FRACTION_BITS];#  define INTERPVARS#endif#define FINALINTERP if (ofs == le) *dest++=src[ofs>>FRACTION_BITS];/* So it isn't interpolation. At least it's final. */extern resample_t *resample_buffer;/*************** resampling with fixed increment *****************/static resample_t *rs_plain(int v, int32 *countptr){  /* Play sample until end, then free the voice. */  INTERPVARS;  Voice     *vp=&voice[v];  resample_t     *dest=resample_buffer;  sample_t     *src=vp->sample->data;  int32     ofs=vp->sample_offset,    incr=vp->sample_increment,    le=vp->sample->data_length,    count=*countptr;#ifdef PRECALC_LOOPS  int32 i, j;  if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */  /* Precalc how many times we should go through the loop.     NOTE: Assumes that incr > 0 and that ofs <= le */  i = (le - ofs) / incr + 1;  if (i > count)    {      i = count;      count = 0;    }   else count -= i;  for(j = 0; j < i; j++)    {      RESAMPLATION;      ofs += incr;    }  if (ofs >= le)     {      FINALINTERP;      vp->status=VOICE_FREE;      ctl->note(v);      *countptr-=count+1;    }#else /* PRECALC_LOOPS */    while (count--)    {      RESAMPLATION;      ofs += incr;      if (ofs >= le)	{	  FINALINTERP;	  vp->status=VOICE_FREE; 	  ctl->note(v);	  *countptr-=count+1;	  break;	}    }#endif /* PRECALC_LOOPS */    vp->sample_offset=ofs; /* Update offset */  return resample_buffer;}static resample_t *rs_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;#ifdef PRECALC_LOOPS  int32 i;   if (ofs < 0 || le < 0) return resample_buffer;  while (count)     {      if (ofs >= le)	/* NOTE: Assumes that ll > incr and that incr > 0. */	ofs -= ll;      /* Precalc how many times we should go through the loop */      i = (le - ofs) / incr + 1;      if (i > count) 	{	  i = count;	  count = 0;	}       else count -= i;      if (i > 0)      while (i--) 	{	  RESAMPLATION;	  ofs += incr;	}    }#else  while (count--)    {      RESAMPLATION;      ofs += incr;      if (ofs>=le)	ofs -= ll; /* Hopefully the loop is longer than an increment. */    }#endif  vp->sample_offset=ofs; /* Update offset */  return resample_buffer;}static resample_t *rs_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;#ifdef PRECALC_LOOPS  int32    le2 = le<<1,     ls2 = ls<<1,    i;  /* Play normally until inside the loop region */  if (ofs <= ls)     {      /* NOTE: Assumes that incr > 0, which is NOT always the case	 when doing bidirectional looping.  I have yet to see a case	 where both ofs <= ls AND incr < 0, however. */      i = (ls - ofs) / incr + 1;      if (i > count) 	{	  i = count;	  count = 0;	}       else count -= i;      while (i--) 	{	  RESAMPLATION;	  ofs += incr;	}    }  /* 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;	  count = 0;	}       else count -= i;      while (i--) 	{	  RESAMPLATION;	  ofs += incr;	}      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--)	{	  RESAMPLATION;	  ofs += incr;	  if (ofs>=ls)	    break;	}    }  /* Then do the bidirectional looping */  if (count>0)    while (count--)      {	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->sample_increment=incr;  vp->sample_offset=ofs; /* Update offset */  return resample_buffer;}/*********************** vibrato versions ***************************//* We only need to compute one half of the vibrato sine cycle */static int vib_phase_to_inc_ptr(int phase){  if (phase < VIBRATO_SAMPLE_INCREMENTS/2)    return VIBRATO_SAMPLE_INCREMENTS/2-1-phase;  else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)    return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;  else    return phase-VIBRATO_SAMPLE_INCREMENTS/2;}static int32 update_vibrato(Voice *vp, int sign){  int32 depth;  int phase, pb;  double a;  if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1)    vp->vibrato_phase=0;  phase=vib_phase_to_inc_ptr(vp->vibrato_phase);    if (vp->vibrato_sample_increment[phase])    {      if (sign)	return -vp->vibrato_sample_increment[phase];      else	return vp->vibrato_sample_increment[phase];    }  /* Need to compute this sample increment. */      depth=vp->sample->vibrato_depth<<7;  if (vp->vibrato_sweep)    {      /* Need to update sweep */      vp->vibrato_sweep_position += vp->vibrato_sweep;      if (vp->vibrato_sweep_position >= (1<<SWEEP_SHIFT))	vp->vibrato_sweep=0;      else	{	  /* Adjust depth */	  depth *= vp->vibrato_sweep_position;	  depth >>= SWEEP_SHIFT;	}    }  a = FSCALE(((double)(vp->sample->sample_rate) *	      (double)(vp->frequency)) /	     ((double)(vp->sample->root_freq) *	      (double)(play_mode->rate)),	     FRACTION_BITS);  pb=(int)((sine(vp->vibrato_phase * 		 (SINE_CYCLE_LENGTH/(2*VIBRATO_SAMPLE_INCREMENTS)))	    * (double)(depth) * VIBRATO_AMPLITUDE_TUNING));  if (pb<0)    {      pb=-pb;      a /= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];    }  else    a *= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];    /* If the sweep's over, we can store the newly computed sample_increment */  if (!vp->vibrato_sweep)    vp->vibrato_sample_increment[phase]=(int32) a;  if (sign)    a = -a; /* need to preserve the loop direction */  return (int32) a;}static resample_t *rs_vib_plain(int v, int32 *countptr){  /* Play sample until end, then free the voice. */

⌨️ 快捷键说明

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