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

📄 sound.cpp

📁 过程的c++编译器 里面有超级玛丽的源代码 还有一个 管理系统的源代码
💻 CPP
字号:
/*********************************************
程序设计:罗穆峰  2008-11-20
http://lmf.biaotian.com
E-mail: lmf@biaotian.com
QQ: 16324942 [模范英雄]
*********************************************/

#include <windows.h>

#include "Sound.h"

static HWAVEOUT s_hWave=NULL;
static char s_Buffer[2][1024];
static WAVEHDR s_WaveHdr[2];
static CRITICAL_SECTION s_DataSection;
static CRITICAL_SECTION s_WaveSection;
static bool s_Stop;
static std::vector<int> s_TempBuf;

CSound * s_pSound;

void CALLBACK WaveCallBack(HWAVEOUT hwo,UINT uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2)
{
	if(WOM_DONE==uMsg)
	{
		if(!s_Stop)
		{//已停止播放,则不要再读数据了
			s_pSound->ReadData(((WAVEHDR*)dwParam1)->lpData,1024);
			EnterCriticalSection(&s_WaveSection);
			waveOutWrite(hwo,(WAVEHDR*)dwParam1,sizeof(WAVEHDR));
			LeaveCriticalSection(&s_WaveSection);
		}
	}
}

bool CSound::Init()
{
/*
	初始化声音设备。
	返回值:
		true		成功。
		false		失败。
*/
	s_pSound=this;
	s_Stop=false;

	WAVEFORMATEX wf;
	wf.cbSize=0;
	wf.nChannels=1;
	wf.nSamplesPerSec=11025;
	wf.wBitsPerSample=8;
	wf.wFormatTag=WAVE_FORMAT_PCM;
	wf.nBlockAlign=wf.wBitsPerSample/8*wf.nChannels;
	wf.nAvgBytesPerSec=wf.nBlockAlign*wf.nSamplesPerSec;
	if(MMSYSERR_NOERROR!=waveOutOpen(&s_hWave,WAVE_MAPPER,&wf,(DWORD)WaveCallBack,0,CALLBACK_FUNCTION))
	{
		s_hWave=NULL;
		return false;
	}

	InitializeCriticalSection(&s_DataSection);
	InitializeCriticalSection(&s_WaveSection);

	s_WaveHdr[0].dwBufferLength=1024;
	s_WaveHdr[0].dwBytesRecorded=0;
	s_WaveHdr[0].dwFlags=0;
	s_WaveHdr[0].dwLoops=1;
	s_WaveHdr[0].dwUser=0;
	s_WaveHdr[0].lpData=s_Buffer[0];
	s_WaveHdr[0].lpNext=0;
	s_WaveHdr[0].reserved=0;
	s_WaveHdr[1]=s_WaveHdr[0];
	s_WaveHdr[1].lpData=s_Buffer[1];
	waveOutPrepareHeader(s_hWave,s_WaveHdr,sizeof(WAVEHDR));
	waveOutPrepareHeader(s_hWave,s_WaveHdr+1,sizeof(WAVEHDR));
	memset(s_Buffer,0x80,sizeof s_Buffer);
	EnterCriticalSection(&s_WaveSection);
	waveOutWrite(s_hWave,&s_WaveHdr[0],sizeof(WAVEHDR));
	waveOutWrite(s_hWave,&s_WaveHdr[1],sizeof(WAVEHDR));
	LeaveCriticalSection(&s_WaveSection);
	return true;
}

void * CSound::AddChannel(const void * Data,size_t Len,bool Loop)
{
/*
	增加一个声音通道。
	参数:
		[i]Data		该通道的音频数据。数据格式为11025Hz,8位单声道。
		[i]Len		数据的长度。必须大于0。
		[i]Loop		是否循环播放。若不是,则播放完后自动删除该通道。
	返回值:
		返回新通道的指针。
*/
	if(!s_hWave)return NULL;//未初始化成功
	
	SOUNDCHANNEL * psc;
	EnterCriticalSection(&s_DataSection);
	m_ChannelList.push_back(SOUNDCHANNEL());
	psc=&m_ChannelList.back();
	psc->Data.resize(Len);
	memcpy(&psc->Data[0],Data,Len);
	psc->CurPos=0;
	psc->Loop=Loop;
	LeaveCriticalSection(&s_DataSection);
	return psc;
}

void CSound::DeleteChannel(void * Chn)
{
/*
	删除一个通道。
	参数:
		[i]Chn		要删除的通道的指针。必须是一个有效的指针。
*/
	std::list<SOUNDCHANNEL>::iterator it;
	EnterCriticalSection(&s_DataSection);
	for(it=m_ChannelList.begin();;++it)
	{
		if(&*it==Chn)
		{
			m_ChannelList.erase(it);
			break;
		}
	}
	LeaveCriticalSection(&s_DataSection);
}

void CSound::ReadData(void * Buf,int Len)
{
/*
	读取音频数据进行播放。
	参数:
		[o]Buf		读取的数据存在该缓存中。如果缺少数据,则缺少的数据填为128。
		[i]Len		缓存的长度。
*/
	int n;
	int * p;
	int i;

	EnterCriticalSection(&s_DataSection);

	//混合各个声道的数据
	s_TempBuf.resize(Len);//混合时数据可能超出范围,先用整形保存
	memset(&s_TempBuf[0],0,sizeof(int)*Len);//未填充时全部为0
	std::list<SOUNDCHANNEL>::iterator it=m_ChannelList.begin();
	while(it!=m_ChannelList.end())
	{
		n=Len;
		p=&s_TempBuf[0];
		while(n)
		{
			int cnt=it->Data.size()-it->CurPos;
			unsigned char * p2=reinterpret_cast<unsigned char*>(&it->Data[0]+it->CurPos);
			if(cnt>n)cnt=n;
			for(i=0;i<cnt;i++)
			{
				*p+=*p2-128;
				p++;
				p2++;
			}
			n-=cnt;
			it->CurPos=reinterpret_cast<char*>(p2)-&it->Data[0];
			if(it->Data.size()==it->CurPos)
			{//已放到缓存尾
				if(!it->Loop)break;//不循环
				it->CurPos=0;//从头开始播放
			}
		}
		if(it->Data.size()==it->CurPos)
		{//已放到缓存尾且未绕回开头的,一定是不循环的,要删除该通道
			it=m_ChannelList.erase(it);
		}
		else
		{
			++it;
		}
	}
	LeaveCriticalSection(&s_DataSection);

	//将数值限定在0~255之间
	for(i=0;i<Len;i++)
	{
		if(s_TempBuf[i]>=127)
			reinterpret_cast<char*>(Buf)[i]=static_cast<unsigned char>(255);
		else if(s_TempBuf[i]<=-128)
			reinterpret_cast<char*>(Buf)[i]=0;
		else
			reinterpret_cast<char*>(Buf)[i]=s_TempBuf[i]+128;
	}
}

void CSound::Stop()
{
/*
	停止播放并清除所有通道。
*/
	s_Stop=true;
	EnterCriticalSection(&s_WaveSection);
	waveOutReset(s_hWave);
	waveOutClose(s_hWave);
	waveOutUnprepareHeader(s_hWave,s_WaveHdr,sizeof(WAVEHDR));
	waveOutUnprepareHeader(s_hWave,s_WaveHdr+1,sizeof(WAVEHDR));
	LeaveCriticalSection(&s_WaveSection);

	EnterCriticalSection(&s_DataSection);
	m_ChannelList.clear();
	LeaveCriticalSection(&s_DataSection);

	s_hWave=NULL;
	DeleteCriticalSection(&s_WaveSection);
	DeleteCriticalSection(&s_DataSection);
}

CSound::~CSound()
{
	if(s_hWave)Stop();
}

⌨️ 快捷键说明

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