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

📄 wavegen_engine.cpp

📁 symbian学习音乐播放的源代码
💻 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 + -