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

📄 streams.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
字号:
#ifdef __RAINE__#include "sasound.h"#else#include "driver.h"#endif#include <math.h>#include "newmem.h"#include "ingame.h"int SampleVol[MAX_STREAM_CHANNELS];static int SamplePan[MAX_STREAM_CHANNELS];static UINT8 init_timer[MAX_STREAM_CHANNELS];static int stream_joined_channels[MAX_STREAM_CHANNELS];static char stream_name[MAX_STREAM_CHANNELS][40];static void *stream_buffer[MAX_STREAM_CHANNELS];static UINT8 counter[MAX_STREAM_CHANNELS]; static int stream_buffer_len[MAX_STREAM_CHANNELS];static int remaining_cycles[MAX_STREAM_CHANNELS];static int base_len; // base length of sample for 1 framestatic int stream_sample_rate[MAX_STREAM_CHANNELS];static int stream_sample_bits[MAX_STREAM_CHANNELS];static int stream_buffer_pos[MAX_STREAM_CHANNELS];static int stream_sample_length[MAX_STREAM_CHANNELS];	/* in usec */static int stream_param[MAX_STREAM_CHANNELS];static void (*stream_callback[MAX_STREAM_CHANNELS])(int param,INT16 *buffer,int length);static void (*stream_callback_multi[MAX_STREAM_CHANNELS])(int param,INT16 **buffer,int length);int (*cpupos)(int len)=NULL;static int memory[MAX_STREAM_CHANNELS];static int r1[MAX_STREAM_CHANNELS];static int r2[MAX_STREAM_CHANNELS];static int r3[MAX_STREAM_CHANNELS];static int c[MAX_STREAM_CHANNELS];void streams_init_timers() {  int n;  // When the emulations pauses, streams are not restarted !!!  // So I need this...  for (n=0; n<MAX_STREAM_CHANNELS; n++){    init_timer[n] = 0;    remaining_cycles[n] = 0;  }}/*signal >--R1--+--R2--+              |      |              C      R3---> amp              |      |             GND    GND*//* R1, R2, R3 in Ohm; C in pF *//* set C = 0 to disable the filter */void set_RC_filter(int channel,int R1,int R2,int R3,int C){	r1[channel] = R1;	r2[channel] = R2;	r3[channel] = R3;	c[channel] = C;}void apply_RC_filter_8(int channel,signed char *buf,int len,int sample_rate){	float R1,R2,R3,C;	float Req;	int K;	int i;	if (c[channel] == 0) return;	/* filter disabled */	R1 = r1[channel];	R2 = r2[channel];	R3 = r3[channel];	C = (float)c[channel] * 1E-12;	/* convert pF to F */	/* Cut Frequency = 1/(2*Pi*Req*C) */	Req = (R1*(R2+R3))/(R1+R2+R3);	K = 0x10000 * exp(-1 / (Req * C) / sample_rate);	buf[0] = buf[0] + (memory[channel] - buf[0]) * K / 0x10000;	for (i = 1;i < len;i++)		buf[i] = buf[i] + (buf[i-1] - buf[i]) * K / 0x10000;	memory[channel] = buf[len-1];}void apply_RC_filter_16(int channel,signed short *buf,int len,int sample_rate){	float R1,R2,R3,C;	float Req;	int K;	int i;	if (c[channel] == 0) return;	/* filter disabled */	R1 = r1[channel];	R2 = r2[channel];	R3 = r3[channel];	C = (float)c[channel] * 1E-12;	/* convert pF to F */	/* Cut Frequency = 1/(2*Pi*Req*C) */	Req = (R1*(R2+R3))/(R1+R2+R3);	K = 0x10000 * exp(-1 / (Req * C) / sample_rate);	buf[0] = buf[0] + (memory[channel] - buf[0]) * K / 0x10000;	for (i = 1;i < len;i++)		buf[i] = buf[i] + (buf[i-1] - buf[i]) * K / 0x10000;	memory[channel] = buf[len-1];}void apply_volume_16( INT16 *buf, UINT32 len, int vol ){  // Normally, now that we have the same values as osd functions,  // we should be abble to simply make a voice_set_volume here...  // I keep this for the end !  if(vol != VOLUME_MAX){	// Add [J3d!]: Small speedup      if( vol != VOLUME_MIN){	// Add [J3d!]: Another speedup      if(len){      do{         *buf = (INT16)((((INT32)*buf) * vol)>>8);         buf++;      }while(--len);      }      }      else{         memset(buf,0x00,len<<1);      }   }}void apply_volume_8( INT8 *buf, UINT32 len, int vol ){   if(vol != VOLUME_MAX){	// Add [J3d!]: Small speedup      if( vol != VOLUME_MIN){	// Add [J3d!]: Another speedup      if(len){      do{         *buf = (INT8)((((INT32)*buf) * vol)>>8);         buf++;      }while(--len);      }      }      else{         memset(buf,0x00,len);      }   }}int streams_sh_start(void){	int i;	for (i = 0;i < MAX_STREAM_CHANNELS;i++)	{		stream_joined_channels[i] = 1;		stream_buffer[i] = 0;	}	return 0;}void streams_sh_stop(void){	int i;	for (i = 0;i < MAX_STREAM_CHANNELS;i++)	{		if(stream_buffer[i]) FreeMem(stream_buffer[i]);		stream_buffer[i] = 0;	}}void streams_sh_update(void){  int channel,i;#ifndef __RAINE__  if (Machine->sample_rate == 0) return;#endif  /* update all the output buffers */  for (channel = 0;channel < MAX_STREAM_CHANNELS;channel += stream_joined_channels[channel]){    if (stream_buffer[channel]){      int newpos;      int buflen;      newpos = stream_buffer_len[channel];	        buflen = newpos - stream_buffer_pos[channel];            if (stream_joined_channels[channel] > 1){	INT16 *buf[MAX_STREAM_CHANNELS];	      	if (buflen > 0){#ifdef USE_8BITS	  if (stream_sample_bits[channel] == 16){#endif	    for (i = 0;i < stream_joined_channels[channel];i++)	      buf[i] = &((short *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]];#ifdef USE_8BITS	  } else {	    for (i = 0;i < stream_joined_channels[channel];i++)	      buf[i] = &((char *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]];	  }#endif		  	  (*stream_callback_multi[channel])(stream_param[channel],buf,buflen);	}	      	for (i = 0;i < stream_joined_channels[channel];i++)	  stream_buffer_pos[channel+i] = 0;	      #if SOFT_VOL	// In hardware mode, no mixing is necessary :	// volume & pan are set at the begining and that's all !	if (stream_sample_bits[channel] == 16){	  for (i = 0;i < stream_joined_channels[channel];i++)#ifndef __RAINE__	    apply_RC_filter_16(channel+i,stream_buffer[channel+i],stream_buffer_len[channel+i],stream_sample_rate[channel+i]);#else	  apply_volume_16( stream_buffer[channel+i], stream_buffer_len[channel+i], SampleVol[channel+i] );#endif	} else {	  for (i = 0;i < stream_joined_channels[channel];i++)#ifndef __RAINE__	    apply_RC_filter_8(channel+i,stream_buffer[channel+i],stream_buffer_len[channel+i],stream_sample_rate[channel+i]);#else	  apply_volume_8( stream_buffer[channel+i], stream_buffer_len[channel+i], SampleVol[channel+i] );#endif	}#endif // SOFT_VOL	            } else { // stream_joinded_channels	if (buflen > 0){	  void *buf;		  	  if (stream_sample_bits[channel] == 16)	    buf = &((short *)stream_buffer[channel])[stream_buffer_pos[channel]];	  else	    buf = &((char *)stream_buffer[channel])[stream_buffer_pos[channel]];	  (*stream_callback[channel])(stream_param[channel],buf,buflen);	}	      	stream_buffer_pos[channel] = 0;#if SOFT_VOL	      if (stream_sample_bits[channel] == 16)#ifndef __RAINE__		apply_RC_filter_16(channel,stream_buffer[channel],stream_buffer_len[channel],stream_sample_rate[channel]);#else	      apply_volume_16( stream_buffer[channel], stream_buffer_len[channel], SampleVol[channel] );#endif	      else#ifndef __RAINE__					apply_RC_filter_8(channel,stream_buffer[channel],stream_buffer_len[channel],stream_sample_rate[channel]);#else	      apply_volume_8( stream_buffer[channel], stream_buffer_len[channel], SampleVol[channel] );#endif#endif      }    }  }    for (channel = 0;channel < MAX_STREAM_CHANNELS;channel += stream_joined_channels[channel]){    if (stream_buffer[channel]){#ifdef USE_8BITS      if (stream_sample_bits[channel] == 16){#endif		for (i = 0;i < stream_joined_channels[channel];i++)	  osd_play_streamed_sample_16(channel+i,stream_buffer[channel+i],				      2*stream_buffer_len[channel+i],				      stream_sample_rate[channel+i],				      255, 128  );#ifdef USE_8BITS      } else {	for (i = 0;i < stream_joined_channels[channel];i++)	  osd_play_streamed_sample(channel+i,stream_buffer[channel+i],				   stream_buffer_len[channel+i],				   stream_sample_rate[channel+i],				   255, 128  );      }#endif          }  }}int stream_init(const char *name,int sample_rate,int sample_bits,		int param,void (*callback)(int param,INT16 *buffer,int length)){  int channel;    channel = get_play_channels(1);  stream_joined_channels[channel] = 1;  strcpy(stream_name[channel],name);#ifndef __RAINE__  stream_buffer_len[channel] = sample_rate / Machine->drv->frames_per_second;  /* adjust sample rate to make it a multiple of buffer_len */  sample_rate = stream_buffer_len[channel] * Machine->drv->frames_per_second;#else  stream_buffer_len[channel] = audio_sample_rate / CPU_FPS;  base_len = audio_sample_rate / CPU_FPS;  // Needs +1 to adjust more precisely to what the result should be !!!  /* adjust sample rate to make it a multiple of buffer_len */  sample_rate = stream_buffer_len[channel] * CPU_FPS;#endif  if ((stream_buffer[channel] = AllocateMem((sample_bits/8)*stream_buffer_len[channel])) == 0)		return -1;	stream_sample_rate[channel] = sample_rate;	stream_sample_bits[channel] = sample_bits;	stream_buffer_pos[channel] = 0;	if (sample_rate)		stream_sample_length[channel] = 1000000 / sample_rate;	else		stream_sample_length[channel] = 0;	stream_param[channel] = param;	stream_callback[channel] = callback;	init_timer[channel] = 0;	return channel;}int stream_init_multi(int channels,const char **name,int sample_rate,int sample_bits,		int param,void (*callback)(int param,INT16 **buffer,int length)){  int channel,i;  channel = get_play_channels(channels);  stream_joined_channels[channel] = channels;  for (i = 0;i < channels;i++)    {      strcpy(stream_name[channel+i],name[i]);#ifndef  __RAINE__      stream_buffer_len[channel+i] = sample_rate / Machine->drv->frames_per_second;      /* adjust sample rate to make it a multiple of buffer_len */      sample_rate = stream_buffer_len[channel+i] * Machine->drv->frames_per_second;#else      stream_buffer_len[channel+i] = audio_sample_rate / CPU_FPS;      base_len = audio_sample_rate / CPU_FPS;            /* adjust sample rate to make it a multiple of buffer_len */      sample_rate = stream_buffer_len[channel+i] * CPU_FPS;#endif       if ((stream_buffer[channel+i] = AllocateMem((sample_bits/8)*stream_buffer_len[channel+i])) == 0)	return -1;      memset(stream_buffer[channel+i],0,(sample_bits/8)*stream_buffer_len[channel+i]);      stream_sample_rate[channel+i] = sample_rate;      stream_sample_bits[channel+i] = sample_bits;      stream_buffer_pos[channel+i] = 0;      if (sample_rate)	stream_sample_length[channel+i] = 1000000 / sample_rate;      else	stream_sample_length[channel+i] = 0;      init_timer[channel+i] = 0;    }  stream_param[channel] = param;  stream_callback_multi[channel] = callback;  return channel;}int stream_initm(const char *name,int mixing_level,int sample_rate,		int param,void (*callback)(int param,INT16 *buffer,int length)){  int stream = stream_init(name,sample_rate,16,param,callback);  stream_set_volume(stream,mixing_level & 0xff);  stream_set_pan(stream,mixing_level >> 8);  return stream;}int stream_init_multim(int channels,const char **name,int *mixing_level,int sample_rate,		       int param,void (*callback)(int param,INT16 **buffer,int length)){  int i,stream = stream_init_multi(channels,name,sample_rate,16,param,callback);  for (i=0; i<channels; i++){    stream_set_volume(stream+i,mixing_level[i] & 0xff);    stream_set_pan(stream+i,mixing_level[i] >> 8);  }  return stream;}    /* min_interval is in usec */void stream_update(int channel,int min_interval){#ifndef __RAINE_ORG__        // int newpos;	int buflen;                //if (stream_buffer[channel] == 0)        //        return;        buflen=0;	/* get current position based on the timer */        if (cpupos) buflen=cpupos(stream_sample_length[channel]);        if (buflen > 0 &&                buflen+stream_buffer_pos[channel]                        < stream_buffer_len[channel]) {                //newpos = sound_scalebufferpos(stream_buffer_len[channel]);        // buflen = newpos - stream_buffer_pos[channel];		if (stream_joined_channels[channel] > 1)		{                        INT16 *buf[MAX_STREAM_CHANNELS];			int i;			if (stream_sample_bits[channel] == 16)			{				for (i = 0;i < stream_joined_channels[channel];i++)					buf[i] = &((short *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]];			}			else			{			  for (i = 0;i < stream_joined_channels[channel];i++)			    buf[i] = (UINT16*)&((char *)stream_buffer[channel+i])[stream_buffer_pos[channel+i]];			}			//osd_profiler(OSD_PROFILE_SOUND);                         (*stream_callback_multi[channel])(stream_param[channel],buf,buflen);			//osd_profiler(OSD_PROFILE_END);			for (i = 0;i < stream_joined_channels[channel];i++)				stream_buffer_pos[channel+i] += buflen;		}		else		{			void *buf;			if (stream_sample_bits[channel] == 16)				buf = &((short *)stream_buffer[channel])[stream_buffer_pos[channel]];			else				buf = &((char *)stream_buffer[channel])[stream_buffer_pos[channel]];			//osd_profiler(OSD_PROFILE_SOUND);                         (*stream_callback[channel])(stream_param[channel],buf,buflen);			//osd_profiler(OSD_PROFILE_END);			stream_buffer_pos[channel] += buflen;		}        }#endif}void stream_set_volume(int channel,int volume){  /* My goal is now to have the same volume/pan values for streams and for     osd low level functions... */  SampleVol[channel] = volume & 0xff;  saSetVolume(channel,volume);}int stream_get_volume(int channel){	return SampleVol[channel];}void stream_set_pan(int channel,int pan){  SamplePan[channel] = pan & 0xff;}int stream_get_pan(int channel){	return SamplePan[channel];}const char *stream_get_name(int channel){	if (stream_buffer[channel])		return stream_name[channel];	else return 0;	/* unused channel */}

⌨️ 快捷键说明

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