📄 soundhandler.cpp
字号:
#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 + -