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

📄 snd_dsp.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	{
	default:
	case OP_LEFT:
		while (count--)
		{
			pb->left = DFR_GetNext( pdfr, pb->left );
			pb++;
		}
		return;
	case OP_RIGHT:
		while (count--)
		{
			pb->right = DFR_GetNext( pdfr, pb->right );
			pb++;
		}
		return;
	case OP_LEFT_DUPLICATE:
		while (count--)
		{
			pb->left = pb->right = DFR_GetNext( pdfr, pb->left );
			pb++;
		}
		return;
	}
}

#define DFR_BASEN		2				// base number of series allpass delays

// nominal diffusor delay and feedback values

//float dfrdlys[] = {20,   25,   30,   35,   40,   45,   50,   55,   60,   65,   70,   75,   80,   85,   90,   95};
float dfrdlys[] =   {13,   19,   26,   21,   32,   36,   38,   16,   24,   28,   41,   35,   10,   46,   50,   27};
float dfrfbs[] =  {0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15};


// diffusor parameter order
	
typedef enum
{

// parameter order

	dfr_isize,		
	dfr_idensity,	
	dfr_idecay,		
		
	dfr_cparam				// # of params

} dfr_e;

// diffusor parameter ranges

prm_rng_t dfr_rng[] = {

	{dfr_cparam,	0, 0},			// first entry is # of parameters

	{dfr_isize,		0.0, 1.0},	// 0-1.0 scales all delays
	{dfr_idensity,	0.0, 1.0},	// 0-1.0 controls # of series delays
	{dfr_idecay,	0.0, 1.0},	// 0-1.0 scales all feedback parameters 
};


dfr_t * DFR_Params ( prc_t *pprc )
{
	dfr_t *pdfr;
	int i;
	int s;
	float size =		pprc->prm[dfr_isize];			// 0-1.0 scales all delays
	float density =		pprc->prm[dfr_idensity];		// 0-1.0 controls # of series delays
	float diffusion =	pprc->prm[dfr_idecay];		// 0-1.0 scales all feedback parameters 

	// D array of CRVB_DLYS reverb delay sizes max sample index w[0...D] (ie: D+1 samples)
	// a array of reverb feedback parms for series delays (CRVB_S_DLYS)
	// b gain of each reverb section
	// n - number of series delays

	int D[CDFR_DLYS];
	int a[CDFR_DLYS];
	int b[CDFR_DLYS];
	int n = DFR_BASEN;

	// increase # of series diffusors with increased density

	n += density * 2;
	
	// limit m, n to half max number of delays

	n = min (CDFR_DLYS/2, n);

	// compute delays for diffusors

	for (i = 0; i < n; i++)
	{
		s = (int)( dfrdlys[i] * size );

		// delay of diffusor

		D[i] = MSEC_TO_SAMPS(s);

		// feedback and gain of diffusor

		a[i] = min (0.9 * PMAX, dfrfbs[i] * PMAX * diffusion);
		b[i] = PMAX;
	}

	
	pdfr = DFR_Alloc ( D, a, b, n );

	return pdfr;
}

inline void * DFR_VParams ( void *p ) 
{
	PRC_CheckParams ((prc_t *)p, dfr_rng);
	return (void *) DFR_Params ((prc_t *)p); 
}

inline void DFR_Mod ( void *p, float v ) { return; }


//////////////////////
// LFO wav definitions
//////////////////////

#define CLFOSAMPS		512					// samples per wav table - single cycle only
#define LFOBITS			14					// bits of peak amplitude of lfo wav
#define LFOAMP			((1<<LFOBITS)-1)	// peak amplitude of lfo wav

//types of lfo wavs

#define LFO_SIN			0	// sine wav
#define LFO_TRI			1	// triangle wav
#define LFO_SQR			2	// square wave, 50% duty cycle
#define LFO_SAW			3	// forward saw wav
#define LFO_RND			4	// random wav
#define LFO_LOG_IN		5	// logarithmic fade in
#define LFO_LOG_OUT		6	// logarithmic fade out
#define LFO_LIN_IN		7	// linear fade in 
#define LFO_LIN_OUT		8	// linear fade out
#define LFO_MAX			LFO_LIN_OUT

#define CLFOWAV	9			// number of LFO wav tables

struct lfowav_t		// lfo or envelope wave table
{
	int	type;				// lfo type
	dly_t *pdly;			// delay holds wav values and step pointers
};

lfowav_t lfowavs[CLFOWAV];

// deallocate lfo wave table. Called only when sound engine exits.

void LFOWAV_Free( lfowav_t *plw )
{
	// free delay

	if ( plw )
		DLY_Free( plw->pdly );

	Q_memset( plw, 0, sizeof (lfowav_t) );
}

// deallocate all lfo wave tables. Called only when sound engine exits.

void LFOWAV_FreeAll( void )
{
	for ( int i = 0; i < CLFOWAV; i++ )
		LFOWAV_Free( &lfowavs[i] );
}

// fill lfo array w with count samples of lfo type 'type'
// all lfo wavs except fade out, rnd, and log_out should start with 0 output

void LFOWAV_Fill( int *w, int count, int type )
{
	int i,x;
	switch (type)
	{
	default:
	case LFO_SIN:			// sine wav, all values 0 <= x <= LFOAMP, initial value = 0
			for (i = 0; i < count; i++ )
			{
				x = ( int )( (float)(LFOAMP) * sinf( (2.0 * M_PI_F * (float)i / (float)count ) + (M_PI_F * 1.5) ) );
				w[i] = (x + LFOAMP)/2;
			}
			break;
	case LFO_TRI:			// triangle wav, all values 0 <= x <= LFOAMP, initial value = 0
			for (i = 0; i < count; i++)
				{
				w[i] = ( int ) ( (float)(2 * LFOAMP * i ) / (float)(count) );
				
				if ( i > count / 2 )
					w[i] = ( int ) ( (float) (2 * LFOAMP) - (float)( 2 * LFOAMP * i ) / (float)(count) );
				}
			break;
	case LFO_SQR:			// square wave, 50% duty cycle, all values 0 <= x <= LFOAMP, initial value = 0
			for (i = 0; i < count; i++)
				w[i] = i > count / 2 ? 0 : LFOAMP;
			break;
	case LFO_SAW:			// forward saw wav, aall values 0 <= x <= LFOAMP, initial value = 0
			for (i = 0; i < count; i++)
				w[i] = ( int ) ( (float)(LFOAMP) * (float)i / (float)(count) );
			break;
	case LFO_RND:			// random wav, all values 0 <= x <= LFOAMP
			for (i = 0; i < count; i++)
				w[i] = ( int ) ( g_pSoundServices->RandomLong(0, LFOAMP) );
			break;
	case LFO_LOG_IN:		// logarithmic fade in, all values 0 <= x <= LFOAMP, initial value = 0
			for (i = 0; i < count; i++)
				w[i] = ( int ) ( (float)(LFOAMP) * powf( (float)i / (float)count, 2));
			break;
	case LFO_LOG_OUT:		// logarithmic fade out, all values 0 <= x <= LFOAMP, initial value = LFOAMP
			for (i = 0; i < count; i++)
				w[i] = ( int ) ( (float)(LFOAMP) * powf( 1.0 - ((float)i / (float)count), 2 ));
			break;
	case LFO_LIN_IN:		// linear fade in, all values 0 <= x <= LFOAMP, initial value = 0
			for (i = 0; i < count; i++)
				w[i] = ( int ) ( (float)(LFOAMP) * (float)i / (float)(count) );
			break;
	case LFO_LIN_OUT:		// linear fade out, all values 0 <= x <= LFOAMP, initial value = LFOAMP
			for (i = 0; i < count; i++)
				w[i] = LFOAMP - ( int ) ( (float)(LFOAMP) * (float)i / (float)(count) );
			break;
	}
}

// allocate all lfo wave tables.  Called only when sound engine loads.

void LFOWAV_InitAll()
{
	int i;
	dly_t *pdly;

	Q_memset( lfowavs, 0, sizeof( lfowavs ) );

	// alloc space for each lfo wav type
	
	for (i = 0; i < CLFOWAV; i++)
	{
		pdly = DLY_Alloc( CLFOSAMPS, 0, 0 , DLY_PLAIN);
		
		lfowavs[i].pdly = pdly;
		lfowavs[i].type = i;

		LFOWAV_Fill( pdly->w, CLFOSAMPS, i );
	}
	
	// if any dlys fail to alloc, free all

	for (i = 0; i < CLFOWAV; i++)
	{
		if ( !lfowavs[i].pdly )
			LFOWAV_FreeAll();
	}
}


////////////////////////////////////////
// LFO iterators - one shot and looping
////////////////////////////////////////

#define CLFO	16	// max active lfos (this steals from active delays)

struct lfo_t
{
	bool fused;		// true if slot take

	dly_t *pdly;	// delay points to lfo wav within lfowav_t (don't free this)

	
	float f;		// playback frequency in hz

	pos_t pos;		// current position within wav table, looping
	pos_one_t pos1;	// current position within wav table, one shot

	int foneshot;	// true - one shot only, don't repeat
};

lfo_t lfos[CLFO];

void LFO_Init( lfo_t *plfo ) { if ( plfo ) Q_memset( plfo, 0, sizeof (lfo_t) ); }
void LFO_InitAll( void ) { for (int i = 0; i < CLFO; i++) LFO_Init(&lfos[i]); }
void LFO_Free( lfo_t *plfo ) { if ( plfo ) Q_memset( plfo, 0, sizeof (lfo_t) ); }
void LFO_FreeAll( void ) { for (int i = 0; i < CLFO; i++) LFO_Free(&lfos[i]); }


// get step value given desired playback frequency

inline float LFO_HzToStep ( float freqHz )
{
	float lfoHz;

	// calculate integer and fractional step values,
	// assume an update rate of SOUND_DMA_SPEED samples/sec

	// 1 cycle/CLFOSAMPS * SOUND_DMA_SPEED samps/sec = cycles/sec = current lfo rate
	//
	// lforate * X = freqHz  so X = freqHz/lforate = update rate

	lfoHz = (float)(SOUND_DMA_SPEED) / (float)(CLFOSAMPS);

	return freqHz / lfoHz;
}

// return pointer to new lfo

lfo_t * LFO_Alloc( int wtype, float freqHz, bool foneshot )
{
	int i;
	int type = min ( CLFOWAV - 1, wtype );
	float lfostep;
	
	for (i = 0; i < CLFO; i++)
		if (!lfos[i].fused)
		{
			lfo_t *plfo = &lfos[i];

			LFO_Init( plfo );

			plfo->fused = true;
			plfo->pdly = lfowavs[type].pdly;		// pdly in lfo points to wav table data in lfowavs
			plfo->f = freqHz;
			plfo->foneshot = foneshot;

			lfostep = LFO_HzToStep( freqHz );

			// init positional pointer (ie: fixed point updater for controlling pitch of lfo)

			if ( !foneshot )
				POS_Init(&(plfo->pos), plfo->pdly->D, lfostep );
			else
				POS_ONE_Init(&(plfo->pos1), plfo->pdly->D,lfostep );

			return plfo;
		}
		DevMsg ("DSP: Warning, failed to allocate LFO.\n" );
		return NULL;
}

// get next lfo value
// Value returned is 0..LFOAMP.  can be normalized by shifting right by LFOBITS
// To play back at correct passed in frequency, routien should be
// called once for every output sample (ie: at SOUND_DMA_SPEED)
// x is dummy param

inline int LFO_GetNext( lfo_t *plfo, int x )
{
	int i;

	// get current position

	if ( !plfo->foneshot )
		i = POS_GetNext( &plfo->pos );
	else
		i = POS_ONE_GetNext( &plfo->pos1 );

	// return current sample

	return plfo->pdly->w[i];
}

// batch version for performance

inline void LFO_GetNextN( lfo_t *plfo, portable_samplepair_t *pbuffer, int SampleCount, int op )
{
	int count = SampleCount;
	portable_samplepair_t *pb = pbuffer;
	
	switch (op)
	{
	default:
	case OP_LEFT:
		while (count--)
		{
			pb->left = LFO_GetNext( plfo, pb->left );
			pb++;
		}
		return;
	case OP_RIGHT:
		while (count--)
		{
			pb->right = LFO_GetNext( plfo, pb->right );
			pb++;
		}
		return;
	case OP_LEFT_DUPLICATE:
		while (count--)
		{
			pb->left = pb->right = LFO_GetNext( plfo, pb->left );
			pb++;
		}
		return;
	}
}

// uses lfowav, rate, foneshot
	
typedef enum
{

// parameter order

	lfo_iwav,		
	lfo_irate,		
	lfo_ifoneshot,	
		
	lfo_cparam			// # of params

} lfo_e;

// parameter ranges

prm_rng_t lfo_rng[] = {

	{lfo_cparam,	0, 0},			// first entry is # of parameters

	{lfo_iwav,		0.0, LFO_MAX},	// lfo type to use (LFO_SIN, LFO_RND...)
	{lfo_irate,		0.0, 16000.0},	// modulation rate in hz. for MDY, 1/rate = 'glide' time in seconds
	{lfo_ifoneshot,	0.0, 1.0},		// 1.0 if lfo is oneshot
};


lfo_t * LFO_Params ( prc_t *pprc )
{
	lfo_t *plfo;
	bool foneshot = pprc->prm[lfo_ifoneshot] > 0 ? true : false;

	plfo = LFO_Alloc ( pprc->prm[lfo_iwav], pprc->prm[lfo_irate], foneshot );

	return plfo;
}

void LFO_ChangeVal ( lfo_t *plfo, float fhz )
{
	float fstep = LFO_HzToStep( fhz );

	// change lfo playback rate to new frequency fhz

	if ( plfo->foneshot )
		POS_ChangeVal( &plfo->pos, fstep );
	else
		POS_ChangeVal( &plfo->pos1.p, fstep );
}

inline void * LFO_VParams ( void *p ) 
{
	PRC_CheckParams ( (prc_t *)p, lfo_rng ); 
	return (void *) LFO_Params ((prc_t *)p); 
}

// v is +/- 0-1.0
// v changes current lfo frequency up/down by +/- v%

inline void LFO_Mod ( lfo_t *plfo, float v ) 
{ 
	float fhz;
	float fhznew;

	fhz = plfo->f;
	fhznew = fhz * (1.0 + v);

	LFO_ChangeVal ( plfo, fhznew );

	return; 
}


/////////////////////////////////////////////////////////////////////////////
// Ramp - used for varying smoothly between int parameters ie: modulation delays
/////////////////////////////////////////////////////////////////////////////


struct rmp_t
{
	int initval;					// initial ramp value
	int target;						// final ramp value
	int sign;						// increasing (1) or decreasing (-1) ramp
	
	int yprev;						// previous output value
	bool fhitend;					// true if hit end of ramp

	pos_one_t ps;					// current ramp output
};

// ramp smoothly between initial value and target value in approx 'ramptime' seconds.
// (initial value may be greater or less than target value)
// never changes output by more than +1 or -1 (which can cause the ramp to take longer to complete than ramptime)
// called once per sample while ramping
// ramptime - duration of ramp in seconds
// initval - initial ramp value
// targetval - target ramp value

void RMP_Init( rmp_t *prmp, float ramptime, int initval, int targetval ) 
{
	int rise;
	int run;

	if (prmp)
		Q_memset( prmp, 0, sizeof (rmp_t) ); 

			
	run = (int) (ramptime * SOUND_DMA_SPEED);		// 'samples' in ramp
	rise = (targetval - initval);					// height of ramp

	// init fixed poi

⌨️ 快捷键说明

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