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

📄 ay8910.c

📁 著名ARC模拟器源码,包括多个平台
💻 C
📖 第 1 页 / 共 2 页
字号:
	{		if (PSG->CountC <= length*STEP) PSG->CountC += length*STEP;	}	/* for the noise channel we must not touch OutputN - it's also not necessary */	/* since we use outn. */	if ((PSG->Regs[AY_ENABLE] & 0x38) == 0x38)	/* all off */		if (PSG->CountN <= length*STEP) PSG->CountN += length*STEP;	outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);	/* buffering loop */	while (length)	{		int vola,volb,volc;		int left;		/* vola, volb and volc keep track of how long each square wave stays */		/* in the 1 position during the sample period. */		vola = volb = volc = 0;		left = STEP;		do		{			int nextevent;			if (PSG->CountN < left) nextevent = PSG->CountN;			else nextevent = left;			if (outn & 0x08)			{				if (PSG->OutputA) vola += PSG->CountA;				PSG->CountA -= nextevent;				/* PeriodA is the half period of the square wave. Here, in each */				/* loop I add PeriodA twice, so that at the end of the loop the */				/* square wave is in the same status (0 or 1) it was at the start. */				/* vola is also incremented by PeriodA, since the wave has been 1 */				/* exactly half of the time, regardless of the initial position. */				/* If we exit the loop in the middle, OutputA has to be inverted */				/* and vola incremented only if the exit status of the square */				/* wave is 1. */				while (PSG->CountA <= 0)				{					PSG->CountA += PSG->PeriodA;					if (PSG->CountA > 0)					{						PSG->OutputA ^= 1;						if (PSG->OutputA) vola += PSG->PeriodA;						break;					}					PSG->CountA += PSG->PeriodA;					vola += PSG->PeriodA;				}				if (PSG->OutputA) vola -= PSG->CountA;			}			else			{				PSG->CountA -= nextevent;				while (PSG->CountA <= 0)				{					PSG->CountA += PSG->PeriodA;					if (PSG->CountA > 0)					{						PSG->OutputA ^= 1;						break;					}					PSG->CountA += PSG->PeriodA;				}			}			if (outn & 0x10)			{				if (PSG->OutputB) volb += PSG->CountB;				PSG->CountB -= nextevent;				while (PSG->CountB <= 0)				{					PSG->CountB += PSG->PeriodB;					if (PSG->CountB > 0)					{						PSG->OutputB ^= 1;						if (PSG->OutputB) volb += PSG->PeriodB;						break;					}					PSG->CountB += PSG->PeriodB;					volb += PSG->PeriodB;				}				if (PSG->OutputB) volb -= PSG->CountB;			}			else			{				PSG->CountB -= nextevent;				while (PSG->CountB <= 0)				{					PSG->CountB += PSG->PeriodB;					if (PSG->CountB > 0)					{						PSG->OutputB ^= 1;						break;					}					PSG->CountB += PSG->PeriodB;				}			}			if (outn & 0x20)			{				if (PSG->OutputC) volc += PSG->CountC;				PSG->CountC -= nextevent;				while (PSG->CountC <= 0)				{					PSG->CountC += PSG->PeriodC;					if (PSG->CountC > 0)					{						PSG->OutputC ^= 1;						if (PSG->OutputC) volc += PSG->PeriodC;						break;					}					PSG->CountC += PSG->PeriodC;					volc += PSG->PeriodC;				}				if (PSG->OutputC) volc -= PSG->CountC;			}			else			{				PSG->CountC -= nextevent;				while (PSG->CountC <= 0)				{					PSG->CountC += PSG->PeriodC;					if (PSG->CountC > 0)					{						PSG->OutputC ^= 1;						break;					}					PSG->CountC += PSG->PeriodC;				}			}			PSG->CountN -= nextevent;			if (PSG->CountN <= 0)			{				/* Is noise output going to change? */				if ((PSG->RNG + 1) & 2)	/* (bit0^bit1)? */				{					PSG->OutputN = ~PSG->OutputN;					outn = (PSG->OutputN | PSG->Regs[AY_ENABLE]);				}				/* The Random Number Generator of the 8910 is a 17-bit shift */				/* register. The input to the shift register is bit0 XOR bit2 */				/* (bit0 is the output). */				/* The following is a fast way to compute bit 17 = bit0^bit2. */				/* Instead of doing all the logic operations, we only check */				/* bit 0, relying on the fact that after two shifts of the */				/* register, what now is bit 2 will become bit 0, and will */				/* invert, if necessary, bit 16, which previously was bit 18. */				if (PSG->RNG & 1) PSG->RNG ^= 0x28000;				PSG->RNG >>= 1;				PSG->CountN += PSG->PeriodN;			}			left -= nextevent;		} while (left > 0);		/* update envelope */		if (PSG->Holding == 0)		{			PSG->CountE -= STEP;			if (PSG->CountE <= 0)			{				do				{					PSG->CountEnv--;					PSG->CountE += PSG->PeriodE;				} while (PSG->CountE <= 0);				/* check envelope current position */				if (PSG->CountEnv < 0)				{					if (PSG->Hold)					{						if (PSG->Alternate)							PSG->Attack ^= 0x1f;						PSG->Holding = 1;						PSG->CountEnv = 0;					}					else					{						/* if CountEnv has looped an odd number of times (usually 1), */						/* invert the output. */						if (PSG->Alternate && (PSG->CountEnv & 0x20)) 							PSG->Attack ^= 0x1f;						PSG->CountEnv &= 0x1f;					}				}				PSG->VolE = PSG->VolTable[PSG->CountEnv ^ PSG->Attack];				/* reload volume */				if (PSG->EnvelopeA) PSG->VolA = PSG->VolE;				if (PSG->EnvelopeB) PSG->VolB = PSG->VolE;				if (PSG->EnvelopeC) PSG->VolC = PSG->VolE;			}		}		*(buf1++) = (vola * PSG->VolA) / STEP;		*(buf2++) = (volb * PSG->VolB) / STEP;		*(buf3++) = (volc * PSG->VolC) / STEP;		length--;	}}void AY8910_set_clock(int chip,int clock){	struct AY8910 *PSG = &AYPSG[chip];	/* the step clock for the tone and noise generators is the chip clock    */	/* divided by 8; for the envelope generator of the AY-3-8910, it is half */	/* that much (clock/16), but the envelope of the YM2149 goes twice as    */	/* fast, therefore again clock/8.                                        */	/* Here we calculate the number of steps which happen during one sample  */	/* at the given sample rate. No. of events = sample rate / (clock/8).    */	/* STEP is a multiplier used to turn the fraction into a fixed point     */	/* number.                                                               */	PSG->UpdateStep = (unsigned int)(((double)STEP * PSG->SampleRate * 8) / clock);}void AY8910_set_volume(int chip,int channel,int volume){	struct AY8910 *PSG = &AYPSG[chip];	int ch;	for (ch = 0; ch < 3; ch++)		if (channel == ch || channel == ALL_8910_CHANNELS)			stream_set_volume(PSG->Channel + ch, volume);}static void build_mixer_table(int chip){	struct AY8910 *PSG = &AYPSG[chip];	int i;	double out;	/* calculate the volume->voltage conversion table */	/* The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step) */	/* The YM2149 still has 16 levels for the tone generators, but 32 for */	/* the envelope generator (1.5dB per step). */	out = MAX_OUTPUT;	for (i = 31;i > 0;i--)	{		PSG->VolTable[i] = (unsigned int)(out + 0.5);	/* round to nearest */		out /= 1.188502227;	/* = 10 ^ (1.5/20) = 1.5dB */	}	PSG->VolTable[0] = 0;}void AY8910_reset(int chip){	int i;	struct AY8910 *PSG = &AYPSG[chip];	PSG->register_latch = 0;	PSG->RNG = 1;	PSG->OutputA = 0;	PSG->OutputB = 0;	PSG->OutputC = 0;	PSG->OutputN = 0xff;	for (i = 0;i < AY_PORTA;i++)		_AYWriteReg(chip,i,0);	/* AYWriteReg() uses the timer system; we cannot */								/* call it at this time because the timer system */								/* has not been initialized. */}static int AY8910_init(const char *myname,int chip,		int clock,int volume,int sample_rate,		mem_read_handler portAread,mem_read_handler portBread,		mem_write_handler portAwrite,mem_write_handler portBwrite){	int i;	struct AY8910 *PSG = &AYPSG[chip];	char buf[3][40];	const char *name[3];	int vol[3];	memset(PSG,0,sizeof(struct AY8910));	PSG->SampleRate = sample_rate;	PSG->PortAread = portAread;	PSG->PortBread = portBread;	PSG->PortAwrite = portAwrite;	PSG->PortBwrite = portBwrite;	for (i = 0;i < 3;i++)	{		vol[i] = volume;		name[i] = buf[i];		sprintf(buf[i],"%s #%d Ch %c",myname,chip,'A'+i);	}	PSG->Channel = stream_init_multi(3,name,sample_rate,16,chip,AY8910Update);	for (i=0; i<3; i++) {	  stream_set_volume(PSG->Channel+i,vol[i]);	  stream_set_pan(PSG->Channel+i,0x80);	}		if (PSG->Channel == -1)		return 1;	AY8910_set_clock(chip,clock);	AY8910_reset(chip);	return 0;}int AY8910_sh_start_ex(const struct AY8910interface *intf,const char *name){	int chip;	for (chip = 0;chip < intf->num;chip++)	{		if (AY8910_init("AY8910",chip,intf->baseclock,				intf->mixing_level[chip] & 0xffff,				audio_sample_rate,				intf->portAread[chip],intf->portBread[chip],				intf->portAwrite[chip],intf->portBwrite[chip]) != 0)			return 1;		build_mixer_table(chip);	}	return 0;}int AY8910_sh_start(const struct AY8910interface *interface){        return AY8910_sh_start_ex(interface,"AY8910");}int AY8910_get_stream_num( int chip ){  struct AY8910 *PSG = &AYPSG[chip];  return PSG->Channel;}

⌨️ 快捷键说明

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