📄 wavegen_engine.cpp
字号:
//
// wavegen_engine.cpp
//
// Copyright (C) 2005 Nokia Corporation. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
#include <aknnotewrappers.h> // for CAknInformationNote
#include <eikenv.h> // for CEikonEnv
#include <eikdef.h>
#include <e32math.h>
#include "wavegen_engine.h"
#include "wavegen.hrh"
#include <wavegen.rsg>
// LITERALS
// path and name for the pcm sound file
#if defined __SERIES60_30__
_LIT(KPCMFilename, "\\resource\\apps\\sound1.pcm");
#else
_LIT(KPCMFilename, "\\system\\apps\\wavegen\\sound1.pcm");
#endif
//
// CStreamAudioEngine class
//
/*
-------------------------------------------------------------------------------
CStreamAudioEngine
Description: Constructor
Return value: N/A
-------------------------------------------------------------------------------
*/
CStreamAudioEngine::CStreamAudioEngine()
:iForm(KInitialWaveform),
iFreq(KInitialFreq),
iVolume(KInitialVolume),
iVolStep(0),
iFileSize(0),
iFileOK(EFalse),
iStatus(EEngineNotReady),
iPlayFile(ETrue),
iDescBuf(0,0)
{
}
/*
-------------------------------------------------------------------------------
~CStreamAudioEngine
Description: Destructor
Return value: N/A
-------------------------------------------------------------------------------
*/
CStreamAudioEngine::~CStreamAudioEngine()
{
delete iStream;
delete iGenBuffer;
delete iPCMBuffer;
delete iWaveGen;
}
/*
-------------------------------------------------------------------------------
NewL
Description: static NewL function for creating a new instance of the engine
Return value: CStreamAudioEngine*
-------------------------------------------------------------------------------
*/
CStreamAudioEngine* CStreamAudioEngine::NewL()
{
CStreamAudioEngine* self = new (ELeave) CStreamAudioEngine();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(); // self
return self;
}
/*
-------------------------------------------------------------------------------
ConstructL
Description: 2nd phase constructor for the engine
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::ConstructL()
{
// get the Eikon environment
iEnv = CEikonEnv::Static();
// load the pcm file to buffer
LoadFileL();
// create new wave generator object and a buffer for it
iWaveGen = new (ELeave) CWaveGenerator();
iGenBuffer = new (ELeave) TUint8[KBufferSize];
// create and initialize output stream
iStream = CMdaAudioOutputStream::NewL(*this);
iStream->Open(&iSettings);
}
/*
-------------------------------------------------------------------------------
MaoscOpenComplete
Description: implementation for MaoscOpenComplete callback function. called
when the audio streaming object in the server has been opened.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::MaoscOpenComplete(TInt aError)
{
if (aError==KErrNone)
{
// set stream properties to 16bit,8KHz mono
iStream->SetAudioPropertiesL(TMdaAudioDataSettings::ESampleRate8000Hz,
TMdaAudioDataSettings::EChannelsMono);
// set the appropriate volume step. values for the target
// device are scaled down to get the optimal volume level
#if defined(__WINS__)
// for emulator (MaxVolume == 65535)
iVolStep = iStream->MaxVolume() / KVolSliderLength;
#else
// for target device (MaxVolume == 9)
iVolStep = iStream->MaxVolume() / (KVolSliderLength-1);
#endif
iStream->SetVolume(iVolStep * KInitialVolume);
iStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceNone);
iStatus = EEngineReady;
}
else
ShowErrorMsg(R_WAVEGEN_ERROR_OPENCOMPLETE, aError);
// display error msg if opening the pcm file failed
if(!iFileOK)
{
iPlayFile = EFalse;
ShowErrorMsg(R_WAVEGEN_ERROR_PCM_FILE, KErrNotFound);
}
// select the correct buffer
SwitchBuffer(iPlayFile);
}
/*
-------------------------------------------------------------------------------
MaoscBufferCopied
Description: implementation for MaoscBufferCopied callback function. called
when the buffer has been copied to the server.
Parameters: error value that will indicate if the copy succeeded and a
reference to the buffer that has been copied.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::MaoscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
{
// if a single file (buffer) is played, return immediately
if(iPlayFile)
{
return;
}
// a continuous wave is being played: fill the buffer and write it to
// stream. the error value will be KErrNone only if the previous buffer was
// successfully copied (if Stop has been called, aError is KErrAbort)
if (aError==KErrNone)
{
iWaveGen->Generate((CWaveGenerator::EWaveform)iForm, iFreq, iDescBuf);
iStream->WriteL(iDescBuf);
}
}
/*
-------------------------------------------------------------------------------
MaoscPlayComplete
Description: implementation for MaoscPlayComplete callback function. called
when the end of the sound data has been reached (or the
playing has stopped for some other reason).
Parameters: error value that will indicate if the buffer was successfully
copied and the end of the sound data was reached
(KErrUnderFlow).
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::MaoscPlayComplete(TInt /*aError*/)
{
iStatus = EEngineReady;
}
/*
-------------------------------------------------------------------------------
PlayL
Description: starts playing the sound by writing the buffer to server.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::PlayL()
{
if(iStatus == EEngineReady)
{
iStatus = EEnginePlaying;
// if we're playing a pcm from a file, the buffer already
// contains the sound data. Otherwise, fill the buffer with
// generated waveform.
if(!iPlayFile)
iWaveGen->Generate((CWaveGenerator::EWaveform)iForm, iFreq, iDescBuf);
// write the buffer to server. the playing starts immediately.
iStream->WriteL(iDescBuf);
}
}
/*
-------------------------------------------------------------------------------
StopL
Description: stops the stream from playing. any data in the buffers will
be discarded. the buffer copied call backs will all be called
with the error value indicating the buffer was not copied, and
then the play complete call back will be called.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::StopL()
{
iStream->Stop();
}
/*
-------------------------------------------------------------------------------
SetVolume
Description: sets the volume. the CMdaAudioOutputStream::SetVolume() can
be used to change the volume both before or during playback.
the parameter should be between 0 and the value returned by
CMdaAudioOutputStream::MaxVolume()
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::SetVolume(TInt aVol)
{
iVolume = aVol;
// if value has changed, pass it directly to audiostream object.
if((iVolume * iVolStep) != iStream->Volume())
iStream->SetVolume(iVolume * iVolStep);
}
/*
-------------------------------------------------------------------------------
LoadFileL
Description: allocates a new buffer and reads a pcm sound data into it from
a file.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::LoadFileL()
{
RFs fs;
RFile file;
CleanupClosePushL(fs);
User::LeaveIfError(fs.Connect());
CleanupClosePushL(file);
TInt fileErr = file.Open(fs,KPCMFilename,EFileRead|EFileShareReadersOnly);
if(fileErr == KErrNone)
{
file.Size(iFileSize);
iPCMBuffer=new (ELeave) TUint8[iFileSize];
iDescBuf.Set(iPCMBuffer,iFileSize,iFileSize);
file.Read(iDescBuf);
iFileOK = ETrue;
}
CleanupStack::PopAndDestroy(2); // fs, file
}
/*
-------------------------------------------------------------------------------
SwitchBuffer
Description: switches the buffer between wave generator and pcm file buffer
Return value: TBool (ETrue if successful, EFalse if failed)
-------------------------------------------------------------------------------
*/
TBool CStreamAudioEngine::SwitchBuffer(TBool aFileBuf)
{
if(aFileBuf)
{
if(!iFileOK)
return EFalse;
iDescBuf.Set(iPCMBuffer,iFileSize,iFileSize);
}
else
iDescBuf.Set(iGenBuffer,KBufferSize,KBufferSize);
iPlayFile = aFileBuf;
return ETrue;
}
/*
-------------------------------------------------------------------------------
ShowErrorMsg
Description: shows the aError error value along with a text from resource
file.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CStreamAudioEngine::ShowErrorMsg(TInt aResourceBuf, TInt aError)
{
TBuf<16> errorNum;
TBuf<128> rDes;
errorNum.Num(aError);
iEnv->ReadResource(rDes, aResourceBuf);
rDes.Append(errorNum);
CAknInformationNote* dlg = new(ELeave)CAknInformationNote();
dlg->ExecuteLD(rDes);
}
//
// CWaveGenerator class
//
/*
-------------------------------------------------------------------------------
CWaveGenerator
Description: Constructor
Return value: N/A
-------------------------------------------------------------------------------
*/
CWaveGenerator::CWaveGenerator()
:iPhase(0), iSign(1)
{
}
/*
-------------------------------------------------------------------------------
~CWaveGenerator
Description: Destructor
Return value: N/A
-------------------------------------------------------------------------------
*/
CWaveGenerator::~CWaveGenerator()
{
}
/*
-------------------------------------------------------------------------------
Generate
Description: fills the buffer with the selected waveform and frequency
Return value: N/A
-------------------------------------------------------------------------------
*/
void CWaveGenerator::Generate(EWaveform aForm, TInt aFreq, TDes8& aDescBuf)
{
switch(aForm)
{
case ERandom:
// random noise (frequency value has no effect)
Random(aDescBuf);
break;
case ESquare:
// square (pulse) waveform with a certain frequency
Square(aFreq, aDescBuf);
default:
break;
}
}
/*
-------------------------------------------------------------------------------
Random
Description: fills the buffer with random noise.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CWaveGenerator::Random(TDes8& aDescBuf)
{
TUint32 randVal;
TInt len = aDescBuf.Length();
for(TInt i=0; i<len; i+=2)
{
randVal = Math::Random();
WriteToBuf(aDescBuf,i,randVal);
}
}
/*
-------------------------------------------------------------------------------
Square
Description: fills the buffer with square wave of selected frequency.
the aFreq parameter is the value of the frequency slider
control.
Return value: N/A
-------------------------------------------------------------------------------
*/
void CWaveGenerator::Square(TInt aFreq, TDes8& aDescBuf)
{
TInt i=0, wave;
TInt len = aDescBuf.Length();
TInt halfWave = (KFreqSliderLength - aFreq) * 10;
if(!halfWave) halfWave = 4;
//complete the last wave if needed to prevent skipping
if(iPhase)
{
for(;iPhase>0; i+=2, iPhase--)
WriteToBuf(aDescBuf,i,KPulseAmplitude * iSign);
iSign *= -1;
}
for(wave = halfWave; i<len; i+=2)
{
WriteToBuf(aDescBuf,i,KPulseAmplitude * iSign);
if(!(--wave))
{
wave = halfWave;
iSign *= -1;
}
}
// store the remainder of last wave
iPhase = wave % halfWave;
}
// eof
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -