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

📄 sound.c

📁 十七种模拟器源代码 非常有用的作课程设计不可缺少的
💻 C
字号:
#ifdef RAINE_DOS#include <dos.h>#include <conio.h>#include <time.h>#endif/* audio related stuff *///HAC hVoice[MIXER_MAX_CHANNELS];//LPAUDIOWAVE lpWave[MIXER_MAX_CHANNELS];static int num_used_opl;int nominal_sample_rate;int soundcard,usestereo;int attenuation = 0;AUDIOINFO info;AUDIOCAPS caps;static int stream_playing[MIXER_MAX_CHANNELS];static void *stream_cache_data[MIXER_MAX_CHANNELS];static int stream_cache_len[MIXER_MAX_CHANNELS];static int stream_cache_freq[MIXER_MAX_CHANNELS];static int stream_cache_volume[MIXER_MAX_CHANNELS];static int stream_cache_pan[MIXER_MAX_CHANNELS];static int stream_cache_bits[MIXER_MAX_CHANNELS];int msdos_init_seal (void){	if (AInitialize() == AUDIO_ERROR_NONE)		return 0;	else		return 1;}int msdos_init_sound(void){	int i;#if 0	/* Ask the user if no soundcard was chosen */	if (soundcard == -1)	{		unsigned int k;		printf("\nSelect the audio device:\n");		for (k = 0;k < AGetAudioNumDevs();k++)		{			/* don't show the AWE32, it's too slow, users must choose Sound Blaster */			if (AGetAudioDevCaps(k,&caps) == AUDIO_ERROR_NONE &&					strcmp(caps.szProductName,"Sound Blaster AWE32"))				printf("  %2d. %s\n",k,caps.szProductName);		}		printf("\n");		if (k < 10)		{			i = getch();			soundcard = i - '0';		}		else			scanf("%d",&soundcard);	}#endif	/* initialize SEAL audio library */	if (soundcard == 0)     /* silence */	{		/* update the Machine structure to show that sound is disabled */		audio_sample_rate = 0;		return 0;	}	/* open audio device */	/*                              info.nDeviceId = AUDIO_DEVICE_MAPPER;*/	info.nDeviceId = soundcard;	/* always use 16 bit mixing if possible - better quality and same speed of 8 bit */	info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_MONO;	/* use stereo output if supported */	if (usestereo)	{		//if (Machine->drv->sound_attributes & SOUND_SUPPORTS_STEREO)			info.wFormat = AUDIO_FORMAT_16BITS | AUDIO_FORMAT_STEREO;	}	info.nSampleRate = audio_sample_rate;	if (AOpenAudio(&info) != AUDIO_ERROR_NONE)	{		print_debug("audio initialization failed\n");		return 1;	}	AGetAudioDevCaps(info.nDeviceId,&caps);	print_debug("Using %s at %d-bit %s %u Hz\n",			caps.szProductName,			info.wFormat & AUDIO_FORMAT_16BITS ? 16 : 8,			info.wFormat & AUDIO_FORMAT_STEREO ? "stereo" : "mono",			info.nSampleRate);	/* open and allocate voices, allocate waveforms */	if (AOpenVoices(MIXER_MAX_CHANNELS) != AUDIO_ERROR_NONE)	{		print_debug("voices initialization failed\n");		return 1;	}	for (i = 0; i < MIXER_MAX_CHANNELS; i++)	{		if (ACreateAudioVoice(&hVoice[i]) != AUDIO_ERROR_NONE)		{			print_debug("voice #%d creation failed\n",i);			return 1;		}		ASetVoicePanning(hVoice[i],128);		lpWave[i] = 0;		stream_playing[i] = 0;		stream_cache_data[0] = 0;		stream_cache_len[0] = 0;		stream_cache_freq[0] = 0;		stream_cache_volume[0] = 0;		stream_cache_pan[0] = 0;		stream_cache_bits[0] = 0;	}	/* update the Machine structure to reflect the actual sample rate */	audio_sample_rate = info.nSampleRate;	print_debug("set sample rate: %d\n",audio_sample_rate);//#if 0	{		uclock_t a,b;		INT32 start,end;		if ((lpWave[0] = (LPAUDIOWAVE)malloc(sizeof(AUDIOWAVE))) == 0)			return 1;		lpWave[0]->wFormat = AUDIO_FORMAT_8BITS | AUDIO_FORMAT_MONO;		lpWave[0]->nSampleRate = audio_sample_rate;		lpWave[0]->dwLength = 3*audio_sample_rate;		lpWave[0]->dwLoopStart = 0;		lpWave[0]->dwLoopEnd = 3*audio_sample_rate;		if (ACreateAudioData(lpWave[0]) != AUDIO_ERROR_NONE)		{			free(lpWave[0]);			lpWave[0] = 0;			return 1;		}		memset(lpWave[0]->lpData,0,3*audio_sample_rate);		/* upload the data to the audio DRAM local memory */		AWriteAudioData(lpWave[0],0,3*audio_sample_rate);		APrimeVoice(hVoice[0],lpWave[0]);		ASetVoiceFrequency(hVoice[0],audio_sample_rate);		ASetVoiceVolume(hVoice[0],0);		AStartVoice(hVoice[0]);		a = uclock();		/* wait some time to let everything stabilize */		do		{			AUpdateAudioEx(audio_sample_rate / CPU_FPS);			b = uclock();		} while (b-a < UCLOCKS_PER_SEC/10);		a = uclock();		AGetVoicePosition(hVoice[0],&start);		do		{			AUpdateAudioEx(audio_sample_rate / CPU_FPS);			b = uclock();		} while (b-a < UCLOCKS_PER_SEC);		AGetVoicePosition(hVoice[0],&end);		nominal_sample_rate = audio_sample_rate;		//audio_sample_rate = end - start;		audio_sample_rate = 22048;		print_debug("actual sample rate: %d\n",audio_sample_rate);		AStopVoice(hVoice[0]);		ADestroyAudioData(lpWave[0]);		free(lpWave[0]);		lpWave[0] = 0;	}//#endif#if 0	{		char *blaster_env;		/* Get Soundblaster base address from environment variabler BLASTER   */		/* Soundblaster OPL base port, at some compatibles this must be 0x388 */		if(!getenv("BLASTER"))		{			printf("\nBLASTER variable not found, disabling fm sound!\n");                        No_OPL = options.no_fm = 1;		}		else		{			blaster_env = getenv("BLASTER");			BaseSb = i = 0;			while ((blaster_env[i] & 0x5f) != 0x41) i++;        /* Look for 'A' char */			while (blaster_env[++i] != 0x20) {				BaseSb = (BaseSb << 4) + (blaster_env[i]-0x30);			}		}	}#endif	num_used_opl = 0;	osd_set_mastervolume(attenuation);	/* set the startup volume */	return 0;}void msdos_shutdown_sound(void){	if (audio_sample_rate != 0)	{		int chip,n;		for(chip=0;chip<num_used_opl;chip++)		{			/* silence the OPL */			for (n = 0x40;n <= 0x55;n++)			{				osd_opl_control(chip,n);				osd_opl_write(chip,0x3f);			}			for (n = 0x60;n <= 0x95;n++)			{				osd_opl_control(chip,n);				osd_opl_write(chip,0xff);			}			for (n = 0xa0;n <= 0xb0;n++)			{				osd_opl_control(chip,n);				osd_opl_write(chip,0);			}		}		/* stop and release voices */		for (n = 0; n < MIXER_MAX_CHANNELS; n++)		{			AStopVoice(hVoice[n]);			ADestroyAudioVoice(hVoice[n]);			if (lpWave[n])			{				ADestroyAudioData(lpWave[n]);				free(lpWave[n]);				lpWave[n] = 0;			}		}		ACloseVoices();		ACloseAudio();	}}static void playsample(int channel,signed char *data,int len,int freq,int volume,int loop,int bits){  if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return;	/* backwards compatibility with old 0-255 volume range */	if (volume > 100) volume = volume * 25 / 255;	if (lpWave[channel] && lpWave[channel]->dwLength != len)	{		AStopVoice(hVoice[channel]);		ADestroyAudioData(lpWave[channel]);		free(lpWave[channel]);		lpWave[channel] = 0;	}	if (lpWave[channel] == 0)	{		if ((lpWave[channel] = (LPAUDIOWAVE)malloc(sizeof(AUDIOWAVE))) == 0)			return;		if (loop) lpWave[channel]->wFormat = (bits == 8 ? AUDIO_FORMAT_8BITS : AUDIO_FORMAT_16BITS)				| AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;		else lpWave[channel]->wFormat = (bits == 8 ? AUDIO_FORMAT_8BITS : AUDIO_FORMAT_16BITS)				| AUDIO_FORMAT_MONO;		lpWave[channel]->nSampleRate = nominal_sample_rate;		lpWave[channel]->dwLength = len;		lpWave[channel]->dwLoopStart = 0;		lpWave[channel]->dwLoopEnd = len;		if (ACreateAudioData(lpWave[channel]) != AUDIO_ERROR_NONE)		{			free(lpWave[channel]);			lpWave[channel] = 0;			return;		}	}	else	{		if (loop) lpWave[channel]->wFormat = (bits == 8 ? AUDIO_FORMAT_8BITS : AUDIO_FORMAT_16BITS)				| AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;		else lpWave[channel]->wFormat = (bits == 8 ? AUDIO_FORMAT_8BITS : AUDIO_FORMAT_16BITS)				| AUDIO_FORMAT_MONO;	}	memcpy(lpWave[channel]->lpData,data,len);	/* upload the data to the audio DRAM local memory */	AWriteAudioData(lpWave[channel],0,len);	APrimeVoice(hVoice[channel],lpWave[channel]);	/* need to cast to double because freq*nominal_sample_rate can exceed the size of an int */	ASetVoiceFrequency(hVoice[channel],(double)freq*nominal_sample_rate/audio_sample_rate);	ASetVoiceVolume(hVoice[channel],volume * 64 / 100);	AStartVoice(hVoice[channel]);}void osd_play_sample(int channel,signed char *data,int len,int freq,int volume,int loop){	playsample(channel,data,len,freq,volume,loop,8);}void osd_play_sample_16(int channel,signed short *data,int len,int freq,int volume,int loop){	playsample(channel,(signed char *)data,len,freq,volume,loop,16);}#define NUM_BUFFERS 3	/* raising this number should improve performance with frameskip, */						/* but also increases the latency. */static int streams_are_playing;static int playstreamedsample(int channel,signed char *data,int len,int freq,int volume,int pan,int bits){	static int c[MIXER_MAX_CHANNELS];	/* backwards compatibility with old 0-255 volume range */	if (volume > 100) volume = volume * 25 / 255;	/* SEAL double volume for panned channels, so we have to compensate */	if (pan != MIXER_PAN_CENTER) volume /= 2;	if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return 1;	if (!stream_playing[channel])	{		if (lpWave[channel])		{			AStopVoice(hVoice[channel]);			ADestroyAudioData(lpWave[channel]);			free(lpWave[channel]);			lpWave[channel] = 0;		}		if ((lpWave[channel] = (LPAUDIOWAVE)malloc(sizeof(AUDIOWAVE))) == 0)			return 1;		lpWave[channel]->wFormat = (bits == 8 ? AUDIO_FORMAT_8BITS : AUDIO_FORMAT_16BITS)				| AUDIO_FORMAT_MONO | AUDIO_FORMAT_LOOP;		lpWave[channel]->nSampleRate = nominal_sample_rate;		lpWave[channel]->dwLength = NUM_BUFFERS*len;		lpWave[channel]->dwLoopStart = 0;		lpWave[channel]->dwLoopEnd = NUM_BUFFERS*len;		if (ACreateAudioData(lpWave[channel]) != AUDIO_ERROR_NONE)		{			free(lpWave[channel]);			lpWave[channel] = 0;			return 1;		}		memset(lpWave[channel]->lpData,0,NUM_BUFFERS*len);		memcpy(lpWave[channel]->lpData,data,len);		/* upload the data to the audio DRAM local memory */		AWriteAudioData(lpWave[channel],0,NUM_BUFFERS*len);		APrimeVoice(hVoice[channel],lpWave[channel]);	/* need to cast to double because freq*nominal_sample_rate can exceed the size of an int */		ASetVoiceFrequency(hVoice[channel],(double)freq*nominal_sample_rate/audio_sample_rate);		AStartVoice(hVoice[channel]);		stream_playing[channel] = 1;		c[channel] = 1;		streams_are_playing = 1;	}	else	{		INT32 pos;		extern int throttle;//#if 0		if (throttle)   /* sync with audio only when speed throttling is on */		{			AGetVoicePosition(hVoice[channel],&pos);			if (bits == 16) pos *= 2;			if (pos >= c[channel] * len && pos < (c[channel]+1)*len) return 0;		}//#endif		memcpy(&lpWave[channel]->lpData[len * c[channel]],data,len);		AWriteAudioData(lpWave[channel],len*c[channel],len);		c[channel] = (c[channel]+1) % NUM_BUFFERS;		streams_are_playing = 1;	}	ASetVoiceVolume(hVoice[channel],volume * 64 / 100);	if (pan == MIXER_PAN_CENTER)		ASetVoicePanning(hVoice[channel],128);	else if (pan == MIXER_PAN_LEFT)		ASetVoicePanning(hVoice[channel],0);	else if (pan == MIXER_PAN_RIGHT)		ASetVoicePanning(hVoice[channel],255);	return 1;}void osd_play_streamed_sample(int channel,signed char *data,int len,int freq,int volume,int pan){	stream_cache_data[channel] = data;	stream_cache_len[channel] = len;	stream_cache_freq[channel] = freq;	stream_cache_volume[channel] = volume;	stream_cache_pan[channel] = pan;	stream_cache_bits[channel] = 8;}void osd_play_streamed_sample_16(int channel,signed short *data,int len,int freq,int volume,int pan){	stream_cache_data[channel] = data;	stream_cache_len[channel] = len;	stream_cache_freq[channel] = freq;	stream_cache_volume[channel] = volume;	stream_cache_pan[channel] = pan;	stream_cache_bits[channel] = 16;}void osd_set_sample_freq(int channel,int freq){	if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return;	/* need to cast to double because freq*nominal_sample_rate can exceed the size of an int */	ASetVoiceFrequency(hVoice[channel],(double)freq*nominal_sample_rate/audio_sample_rate);}void osd_set_sample_volume(int channel,int volume){	if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return;	/* backwards compatibility with old 0-255 volume range */	if (volume > 100) volume = volume * 25 / 255;	ASetVoiceVolume(hVoice[channel],volume * 64 / 100);}void osd_stop_sample(int channel){	if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return;	AStopVoice(hVoice[channel]);}void osd_restart_sample(int channel){	if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return;	AStartVoice(hVoice[channel]);}int osd_get_sample_status(int channel){	int stopped=0;	if (audio_sample_rate == 0 || channel >= MIXER_MAX_CHANNELS) return -1;	AGetVoiceStatus(hVoice[channel], &stopped);	return stopped;}static int update_streams(void){	int channel;	int res = 1;	streams_are_playing = 0;	for (channel = 0;channel < MIXER_MAX_CHANNELS;channel++)	{		if (stream_cache_data[channel])		{			if (playstreamedsample(					channel,					stream_cache_data[channel],					stream_cache_len[channel],					stream_cache_freq[channel],					stream_cache_volume[channel],					stream_cache_pan[channel],					stream_cache_bits[channel]))				stream_cache_data[channel] = 0;			else				res = 0;		}	}	return res;}int msdos_update_audio(void){	if (audio_sample_rate == 0) return 0;	//profiler_mark(PROFILER_SOUND);	AUpdateAudioEx(audio_sample_rate / CPU_FPS);	//profiler_mark(PROFILER_END);	//profiler_mark(PROFILER_IDLE);	while (update_streams() == 0)		AUpdateAudioEx(audio_sample_rate / CPU_FPS);	//profiler_mark(PROFILER_END);	return streams_are_playing;}static int master_volume = 256;/* attenuation in dB */void osd_set_mastervolume(int _attenuation){	float volume;	if (_attenuation > 0) _attenuation = 0;	if (_attenuation < -32) _attenuation = -32;	attenuation = _attenuation; 	volume = 256.0;	/* range is 0-256 */	while (_attenuation++ < 0)		volume /= 1.122018454;	/* = (10 ^ (1/20)) = 1dB */	master_volume = volume;	ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME,master_volume);}int osd_get_mastervolume(void){	return attenuation;}void osd_sound_enable(int enable_it){	if (enable_it)	{		ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME,master_volume);	}	else	{		ASetAudioMixerValue(AUDIO_MIXER_MASTER_VOLUME,0);	}}/* linux sound driver opl3.c does a so called tenmicrosec() delay */static void tenmicrosec(void){    int i;    for (i = 0; i < 16; i++)        inportb(0x80);}//#define MAX_OPLCHIP 2  /* SOUND BLASTER 16 or compatible ?? */#define MAX_OPLCHIP 1  /* SOUND BLASTER pro compatible ??  */void osd_opl_control(int chip,int reg){    if (audio_sample_rate == 0) return;    if (chip >= MAX_OPLCHIP ) return;    tenmicrosec();    outportb(0x388+chip*2,reg);}void osd_opl_write(int chip,int data){    if (audio_sample_rate == 0) return;    if (chip >=MAX_OPLCHIP ) return;    tenmicrosec();    outportb(0x389+chip*2,data);	if(chip >= num_used_opl) num_used_opl = chip+1;}

⌨️ 快捷键说明

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