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

📄 soundhandler.cpp

📁 Source code (C++) of the Icebloxx game for Symbian OS UIQ3.x
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "SoundHandler.h"
#include <f32file.h>
const TInt KSoundTimerValue = 50; // in ms

CSoundSample* CSoundSample::NewL(const TFileName& aFileName)
{
	CSoundSample* self = new (ELeave) CSoundSample;
	CleanupStack::PushL(self);
	self->ConstructL(aFileName);
	CleanupStack::Pop(self);
	return self;
}

CSoundSample::~CSoundSample()
{
	delete iSampleData;
	
}

CSoundSample::CSoundSample():iSamplePtr(0,0)
{
}

struct RiffChunkHeader
{
	TUint32    ckID;       // Four-character chunk ID
	TUint32    ckSize;     // Length of data in chunk
};

struct WavChunkHeader
{
	TUint16    formatTag;       
	TUint16	  channels;
	TUint32	  sampleFreq;
	TUint32	  bytesPerSec;
	TUint16	  blockAlign;
	TUint16	  bitsPerSample;
};

void CSoundSample::ConstructL(const TFileName& aFileName)
{
	RFs fs ;
	fs.Connect();
	CleanupClosePushL(fs);
	RFile file;
	if(file.Open(fs,aFileName,0)== KErrNone)
	{
		CleanupClosePushL(file);
		TPckgBuf<RiffChunkHeader> riffheader;
		file.Read(riffheader,8);
		
		if(riffheader.Length()==8)
		{
			TBuf8<4> waveheader;
			file.Read(waveheader,4);
			
			if(waveheader == _L8("WAVE"))
			{
				TPckgBuf<RiffChunkHeader> wavheaderBuf;
				file.Read(wavheaderBuf,8);
				
				RiffChunkHeader wavHeader = wavheaderBuf();
				
				TPckgBuf<WavChunkHeader> wavChunkHeaderBuf;
				file.Read(wavChunkHeaderBuf,sizeof(WavChunkHeader));
				WavChunkHeader wavChunkHeader = wavChunkHeaderBuf();
				iSampleRate = wavChunkHeader.sampleFreq;
				iNoBits = wavChunkHeader.bitsPerSample;
				iNoChannels = wavChunkHeader.channels;
				iStepRate = wavChunkHeader.blockAlign;
				TInt leftToRead = wavHeader.ckSize-sizeof(WavChunkHeader);
				if(leftToRead!=0)
				{
					file.Seek(ESeekCurrent,leftToRead);
				}
				file.Read(waveheader,4);
				if(waveheader == _L8("fact"))
				{
					TBuf8<8> facthdr;
					file.Read(facthdr,8); // skip fact header 
				}
				else
				{
					TInt seekval = -4;
					file.Seek(ESeekCurrent,seekval);
				}
				
				TPckgBuf<RiffChunkHeader> dataheaderBuf;
				file.Read(dataheaderBuf,8);
				
				RiffChunkHeader dataHeader = dataheaderBuf();
				iSampleData = HBufC8::NewL(dataHeader.ckSize);
				iSamplePtr.Set(iSampleData->Des());
				iSampleLength = dataHeader.ckSize/iStepRate;
				TPtr8 ptr (iSampleData->Des());
				file.Read(ptr,(TInt)dataHeader.ckSize);
				
			}
		}
		CleanupStack::PopAndDestroy();//close file
	}
	
	CleanupStack::PopAndDestroy(1);//close fs
}

CSoundChannel::CSoundChannel()	
{
}

CSoundChannel::~CSoundChannel()
{
}



CSoundHandler* CSoundHandler::NewL(TInt aNoOfSoundChannels,TInt aMixFreq,TInt aChannels,const TDesC& aDefaultMusicZip)
{
	CSoundHandler* self = new (ELeave) CSoundHandler(aNoOfSoundChannels,aMixFreq,aChannels);
	CleanupStack::PushL(self);
	self->ConstructL(aDefaultMusicZip);
	CleanupStack::Pop(self);
	return self;
}

CSoundHandler::~CSoundHandler()
{
	if(iThreadWatcher)
	{
		iThreadWatcher->Cancel();
	}
	
	delete iThreadWatcher;
	iThreadWatcher = NULL;
	if(iSndThread)
	{
		if(!iSoundOn)
		{
			StartSound();//To be able to exit properly
		}
		iExitSnd = ETrue;
		while(iExitSnd) // Shut down secondary thread first
		{
			User::After(20000); // Wait for sound thread to close
		}
		iSndThread->Kill(0);
		iSndThread->Close();
		delete iSndThread;
	}
	
	if(iSoundChannels)
	{
		iSoundChannels->ResetAndDestroy(); 
		iSoundChannels->Close();
		delete iSoundChannels;
	}
	
	if(iSoundSamples)
	{
		iSoundSamples->ResetAndDestroy(); 
		iSoundSamples->Close();
		delete iSoundSamples;
	}
	delete iMusicSample;
	iThreadMutex.Close();
}

TInt CSoundHandler::AddSoundSampleL(const TFileName& aSampleName)
{
	CSoundSample* sample = CSoundSample::NewL(aSampleName);
	iSoundSamples->Append(sample);
	return iSoundSamples->Count()-1;
}

TBool CSoundHandler::PlayingSample()
{
	for(TInt loop=0;loop<iNoOfSoundChannels;loop++)
		{
			if((*iSoundChannels)[loop]->iIsPlaying)
			{
				return ETrue;
			}
		}
	return EFalse;
}

/**
* @returns Channel Index
*/
TInt CSoundHandler::PlaySampleL(TInt aSampleIndex,TReal aFactor,TBool aIsLooping)
{
	if(!iSoundOn)
		return 0;
	TInt foundIndex = -1;
	if(aSampleIndex<iSoundSamples->Count() && (*iSoundSamples)[aSampleIndex]->iSampleData!= NULL)
	{
		for(TInt loop=0;loop<iNoOfSoundChannels;loop++)
		{
			if(!(*iSoundChannels)[loop]->iIsPlaying)
			{
				CSoundChannel* channel= (*iSoundChannels)[loop];
				channel->iSample = (*iSoundSamples)[aSampleIndex];
				channel->iIsPlaying = ETrue;
				channel->iStepRate = ((TReal)(channel->iSample->iSampleRate*aFactor)/iSampleFreq);
				channel->iPlayPosition = 0;
				channel->iIsLooping = aIsLooping;
				TTime now;
				now.HomeTime();
				channel->iStartedPlayAt  = now;
				foundIndex = loop;
				break;
			}
		}
	}
	return foundIndex;
}

void CSoundHandler::StopPlayingChannelL(TInt aChannelIndex)
{
	(*iSoundChannels)[aChannelIndex]->iIsPlaying = EFalse;
}

void CSoundHandler::StopAll()
{
	for(TInt loop=0;loop<iNoOfSoundChannels;loop++)
	{
		(*iSoundChannels)[loop]->iIsPlaying = EFalse;
	}
}

void CSoundHandler::MixChannels()
{
	// Now try to fill some buffers.. ehhh just simple copy at first
	iThreadMutex.Wait();
	TInt nochan= iNoOfSoundChannels;

	
	TUint16*  ptr = (TUint16*) iMixBuffer->Des().Ptr();
	if(iChannels == 1)
	{
		for(TInt sampleNo=0;sampleNo<iBufferLength;sampleNo++)
		{
			TInt32 sample =0;
		
			TInt activechannels =0;
			for(TInt channel=0;channel<nochan;channel++)
			{
				if((*iSoundChannels)[channel]->iIsPlaying)
				{
					activechannels++;
					CSoundChannel* sndChannel = (*iSoundChannels)[channel];
					if(sndChannel->iSample->iNoBits >= 16 && sndChannel->iSample->iNoChannels == 1)
					{
						sample+=((const TInt16*)sndChannel->iSample->iSamplePtr.Ptr())[(TInt)sndChannel->iPlayPosition];
					}
					else if(sndChannel->iSample->iNoBits >= 16) // 16 bit stereo
					{
						TUint32 smp =((const TInt32*)sndChannel->iSample->iSamplePtr.Ptr())[(TInt)sndChannel->iPlayPosition];
						TInt16 smp1 = smp&65535;
						TInt16 smp2 = smp>>16;
						sample+=smp1;
						sample+=smp2;
						sample = sample>>1;
						
					} 
					else if (sndChannel->iSample->iNoChannels ==2) // 8 BIT HANDLING stereo
					{
						TInt16 smp = ((const TInt16*)sndChannel->iSample->iSamplePtr.Ptr())[(TInt)sndChannel->iPlayPosition];
						TInt16 smp2 = (((TUint16)smp)>>8);
						smp=smp&255;
						sample+=(smp-128)<<8;;
						sample+=(smp2-128)<<8;;
						sample=sample>>1;
					}
					else // 8 BIT HANDLING mono
					{
						TInt16 smp = sndChannel->iSample->iSamplePtr.Ptr()[(TInt)sndChannel->iPlayPosition];
						sample+=(smp-128)<<8;;
					}
					
					sndChannel->iPlayPosition+=sndChannel->iStepRate;
					
					if(sndChannel->iPlayPosition>=sndChannel->iSample->iSampleLength)
					{
						if(!sndChannel->iIsLooping)
						{
							sndChannel->iIsPlaying = EFalse;
							if(iObserver != NULL)
							{
								iObserver->ChannelStopped(channel);
							}
						}
						else
						{
							sndChannel->iPlayPosition = 0;
						}
					}
					
				}
			}
			//sample = sample>>1;	
			if(sample>32767)
			{
				sample = 32767;
			}
			else if(sample<-32767)
			{
				sample = -32767;
			}
			
			*ptr= sample;
			ptr++;
		}
	}
	else // Stereo mixing..
	{
		for(TInt sampleNo=0;sampleNo<iBufferLength;sampleNo++)
		{
			TInt32 sampleL = 0; 
			TInt32 sampleR = 0;

			TInt activechannels = 0;			
			for(TInt channel=0;channel<nochan;channel++)
			{
				
				if((*iSoundChannels)[channel]->iIsPlaying)
				{
					activechannels++;
					CSoundChannel* sndChannel = (*iSoundChannels)[channel];
					if(sndChannel->iSample->iNoBits >= 16 && sndChannel->iSample->iNoChannels == 1)
					{
						TInt val = ((const TInt16*)sndChannel->iSample->iSamplePtr.Ptr())[(TInt)sndChannel->iPlayPosition];
						sampleL+=val;
						sampleR+=val;
					}
					else if(sndChannel->iSample->iNoBits >= 16) // 16 bit stereo
					{
						TUint32 smp =((const TInt32*)sndChannel->iSample->iSamplePtr.Ptr())[(TInt)sndChannel->iPlayPosition];
						TInt16 smp1 = smp&65535;
						TInt16 smp2 = smp>>16;

⌨️ 快捷键说明

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