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

📄 dsound.cpp

📁 vc写的源程序,是关于游戏类的程序。调用了系统的很多API
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "graphics.h"

LPDIRECTSOUND       lpDS;         // DirectSound对象
LPDIRECTSOUNDBUFFER lpDSBPrimary; // 主声音缓冲区
WAVEFORMATEX         wf;

BOOL sound_init = FALSE;
BOOL sound_on = TRUE, music_on = TRUE; // 音效和音乐开关
long sample_pan, sample_volume; // 音效的均衡和音量
long music_pan, music_volume; // 音乐的均衡和音量
STATICSOUND static_buffer[MAXSAMPLE]; // 音效缓冲区
STREAMSOUND stream_buffer; // 音乐缓冲区
HANDLE sound_event[MAXSAMPLE * 2 + 2]; // 声音缓冲区事件数组
HANDLE DS_Thread = NULL; // DirectSound线程
DWORD DirectSoundThreadID; // DirectSound线程ID

// 初始化DirectSound
BOOL init_directsound()
{
	// 创建DirectSound对象
	if (DirectSoundCreate(NULL, &lpDS, NULL) != DS_OK)
	{
		// 创建DirectSound对象失败
		sound_on = music_on = FALSE;
		return FALSE;
	}
	// 设置DirectSound协作层
	if (lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY) != DD_OK)
	{
		// 设置DirectSound协作层失败
		free_directsound();
		return FALSE;
	}
	DSBUFFERDESC dsbdesc;
	ZeroMemory(&dsbdesc, sizeof(dsbdesc));
	dsbdesc.dwSize = sizeof(dsbdesc);
	dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
	// 建立主声音缓冲区
	if(lpDS->CreateSoundBuffer(&dsbdesc, &lpDSBPrimary,NULL) != DS_OK)
	{
		free_directsound();
		return FALSE;
	}
	// 设置主声音缓冲区格式
	wf.wFormatTag = WAVE_FORMAT_PCM;
	wf.nChannels = 2;
	wf.wBitsPerSample = SOUNDBPS;
	wf.nSamplesPerSec = SOUNDSPS;
	wf.nBlockAlign = (SOUNDBPS * 2) >> 3;
	wf.nAvgBytesPerSec = SOUNDSPS * wf.nBlockAlign;
	wf.cbSize = 0;
	if (lpDSBPrimary->SetFormat(&wf) != DS_OK)
	{
		// 设置主声音缓冲区格式失败
		free_directsound();
		return FALSE;
	}
	lpDSBPrimary->Play(0, 0, DSBPLAY_LOOPING);
	// 建立声音流缓冲区
	dsbdesc.dwSize = sizeof(dsbdesc);
	dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 |
		DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLPAN |
		DSBCAPS_CTRLVOLUME;
	dsbdesc.dwBufferBytes = MUSIC_BUFFER_SIZE;
	dsbdesc.lpwfxFormat = &wf;
	dsbdesc.dwReserved = 0;
	if (lpDS->CreateSoundBuffer(&dsbdesc, &stream_buffer.lpDSB, NULL) != DS_OK)
	{
		// 建立声音流缓冲区失败
		free_directsound();
		return FALSE;
	}
	if (stream_buffer.lpDSB->QueryInterface(IID_IDirectSoundNotify, (void **)&stream_buffer.lpDSN) != DS_OK)
	{
		// 设置声音流缓冲区事件设置失败
		free_directsound();
		return FALSE;
	}
	HANDLE event;
	event = CreateEvent(NULL, FALSE, FALSE, NULL);
	sound_event[MAXSAMPLE*2] = event;
	stream_buffer.dsbpn[0].hEventNotify = event;
	stream_buffer.dsbpn[0].dwOffset = 0;
	event = CreateEvent(NULL, FALSE, FALSE, NULL);
	sound_event[MAXSAMPLE * 2 + 1] = event;
	stream_buffer.dsbpn[1].hEventNotify = event;
	stream_buffer.dsbpn[1].dwOffset = MUSIC_BUFFER_SIZE >> 1;
	stream_buffer.pan = music_pan;
	stream_buffer.volume = music_volume;
	if (stream_buffer.lpDSN->SetNotificationPositions(2, stream_buffer.dsbpn) != DS_OK)
	{
		// 设置声音流缓冲区事件设置失败
		free_directsound();
		return FALSE;
	}
	stream_buffer.music = NULL;

	// 设置缓冲区
	STATICSOUND *ss;
	dsbdesc.dwSize = sizeof(dsbdesc);
	dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 |
		DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLPAN |
		DSBCAPS_CTRLVOLUME;
	dsbdesc.dwBufferBytes = SAMPLE_BUFFER_SIZE;
	dsbdesc.lpwfxFormat = &wf;
	dsbdesc.dwReserved = 0;

	ss = &static_buffer[0];
	for (int i = 0; i < MAXSAMPLE; i++, ss++)
	{
		// 创建缓冲区
		if (lpDS->CreateSoundBuffer(&dsbdesc, &(ss->lpDSB), NULL) != DS_OK)
		{
			// 创建静态声音缓冲区失败
			free_directsound();
			return FALSE;
		}
		if (ss->lpDSB->QueryInterface(IID_IDirectSoundNotify, (void **)&ss->lpDSN) != DS_OK)
		{
			// 设置声音缓冲区失败
			free_directsound();
			return FALSE;
		}
		ss->status = -1;
		event = CreateEvent(NULL, FALSE, FALSE, NULL);
		sound_event[i << 1] = event;
		ss->dsbpn[0].hEventNotify = event;
		ss->dsbpn[0].dwOffset = 0;
		event = CreateEvent(NULL, FALSE, FALSE, NULL);
		sound_event[(i << 1) + 1] = event;
		ss->dsbpn[1].hEventNotify = event;
		ss->dsbpn[1].dwOffset = SAMPLE_BUFFER_SIZE >> 1;
		ss->pan = sample_pan;
		ss->volume = sample_volume;
		if (ss->lpDSN->SetNotificationPositions(2, ss->dsbpn) != DS_OK)
		{
			// 设置声音缓冲区失败
			free_directsound();
			return FALSE;
		}
	}
	// 创建多线程
	if(!(DS_Thread = CreateThread(NULL, 0, DirectSoundThread, NULL, 0, &DirectSoundThreadID)))
	{
		free_directsound();
		put_message(TRUE, "错误,创建声音管理线程失败。");
	}

	return TRUE;
}

// 读取音效文件
SAMPLE *load_sample(char *filename)
{
	FILE *fp;
	SAMPLE *sample;
	sample = new SAMPLE;
	put_message(sample == NULL, "错误,没有足够的内存。");
	sample->number = -1;
	fp = fopen(filename, "rb");
	put_message(fp == NULL, "错误,读取文件%s失败。", filename);
	DWORD riff = 0, size = 0, type = 0, entry = 0, filesize = 0, data_size = 0;
	fseek(fp, 0, SEEK_END);
	filesize = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	fread(&riff, sizeof(DWORD), 1, fp);
	fread(&size, sizeof(DWORD), 1, fp);
	fread(&type, sizeof(DWORD), 1, fp);
	BOOL format_read = FALSE, data_read = FALSE;
	if (riff != mmioFOURCC('R', 'I', 'F', 'F') ||
		type != mmioFOURCC('W', 'A', 'V', 'E'))
	{
		fclose(fp);
		return NULL;
	}
	entry += 12;
	while(entry < filesize)
	{
		fread(&type, sizeof(DWORD), 1, fp);
		fread(&size, sizeof(DWORD), 1, fp);
		entry += 8;
		switch(type)
		{
		case mmioFOURCC('f', 'm', 't', ' '):
			if (size < sizeof(WAVEFORMAT))
			{
				fclose(fp);
				return FALSE;
			}
			fseek(fp, sizeof(WAVEFORMAT), SEEK_CUR);
			entry += sizeof(WAVEFORMAT);
			if (format_read && data_read)
				return sample;
			format_read = TRUE;
			break;
		case mmioFOURCC('d', 'a', 't', 'a'):
			sample->bit = new char [size];
			put_message(sample->bit == NULL, "错误,没有足够的内存。");
			fread(sample->bit, size, 1, fp);
			entry += size;
			sample->size = size;
			data_read = TRUE;
			if (format_read)
				return sample;
			break;
		}
	}
	fclose(fp);
	return sample;
}

// 读取音乐文件
MUSIC *load_music(char *filename)
{
	MUSIC *music;
	music = new MUSIC;
	put_message(music == NULL, "错误,没有足够的内存。");
	music->source = MUSIC_IN_FILE;
	music->fp = fopen(filename, "rb");
	put_message(music->fp == NULL, "错误,读取文件%s失败。", filename);
	DWORD riff = 0, size = 0, type = 0, entry = 0, filesize = 0, data_size = 0;
	fseek(music->fp, 0, SEEK_END);
	filesize = ftell(music->fp);
	fseek(music->fp, 0, SEEK_SET);
	fread(&riff, sizeof(DWORD), 1, music->fp);
	fread(&size, sizeof(DWORD), 1, music->fp);
	fread(&type, sizeof(DWORD), 1, music->fp);
	BOOL format_read = FALSE, data_read = FALSE;
	if (riff != mmioFOURCC('R', 'I', 'F', 'F') ||
		type != mmioFOURCC('W', 'A', 'V', 'E'))
	{
		fclose(music->fp);
		return NULL;
	}
	entry += 12;
	while(entry < filesize)
	{
		fread(&type, sizeof(DWORD), 1, music->fp);
		fread(&size, sizeof(DWORD), 1, music->fp);
		entry += 8;
		switch(type)
		{
		case mmioFOURCC('f', 'm', 't', ' '):
			if (size < sizeof(WAVEFORMAT))
			{
				fclose(music->fp);
				return FALSE;
			}
			fseek(music->fp, sizeof(WAVEFORMAT), SEEK_CUR);
			entry += sizeof(WAVEFORMAT);
			if (format_read && data_read)
				return music;
			format_read = TRUE;
			break;
		case mmioFOURCC('d', 'a', 't', 'a'):
			music->size = size;
			music->pos = ftell(music->fp);
			data_read = TRUE;
			if (format_read)
				return music;
			break;
		}
	}
	fclose(music->fp);
	return music;
}

// 释放音效文件所占的内存
void free_sample(SAMPLE **sample)
{
	SAMPLE *s = *sample;
	if (s == NULL)
		return;
	if (s->bit != NULL)
		free(s->bit);
	free(s);
	*sample = NULL;
}

// 释放音效文件所占的内存
void free_music(MUSIC **music)
{
	MUSIC *m = *music;
	free(m);
	*music = NULL;
}

// 释放DirectSound对象
void free_directsound()
{
	// 关闭声音管理线程
	if (DS_Thread)
	{
		TerminateThread(DS_Thread, 0);
		Sleep(200);
	}
	// 释放静态缓冲区
	for (int i = 0; i < MAXSAMPLE; i++)
	{
		if (static_buffer[i].lpDSB != NULL)
		{
			static_buffer[i].lpDSB->Release();
			static_buffer[i].lpDSB = NULL;
			static_buffer[i].lpDSN->Release();
			static_buffer[i].lpDSN = NULL;
			CloseHandle(sound_event[i << 1]);
			CloseHandle(sound_event[i << 1 + 1]);
		}
	}
	// 释放流缓冲区
	if (stream_buffer.lpDSN != NULL)
	{
		stream_buffer.lpDSN->Release();
		stream_buffer.lpDSN = NULL;
	}
	if (stream_buffer.lpDSB != NULL)
	{
		stream_buffer.lpDSB->Release();
		stream_buffer.lpDSB = NULL;
	}
	CloseHandle(sound_event[MAXSAMPLE * 2]);
	CloseHandle(sound_event[MAXSAMPLE * 2 + 1]);

⌨️ 快捷键说明

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