Symbian SDK下有个sound的项目,这个例子囊括了Symbian下的音频播放技术。


下面有Symbian中的音频技术:


①     CMdaAudioToneUtility


Description


Generates tones on an audio capable device.


While this class is abstract, the static function constructs, initialises and returns a pointer to


an instance of a concrete class derived from this class. The concrete class is part of the MMF


implementation and is private.


 


从Class的Description中可以看出,这个类是用来播放tone的。


与其相对应的监听类为


MmdaAudioToneObserver


Description


An interface to a set of audio tone player callback functions.


The class is a mixin and is intended to be inherited by the client class which is observing the


audio tone playing operation. The functions encapsulated by this class are called when


specific events occur in the process of configuring the audio tone player utility and the


playing of a tone.


A reference to this object is passed as a parameter when constructing an audio tone player


utility, using the ​​CMdaAudioToneUtility​​ interface.


 


此监听类用来监视tone播放的操作,它封装了一些接口。在设置Player的属性和播放tone的过程中如果有特定的事件发生,就会去调用相应的接口。


在sound项目中对应的封装类如下所示:


先来看看类中声明了那些接口


#ifndef __CTONEADAPTER_H__


#define __CTONEADAPTER_H__


 


// INCLUDES


#include <e32std.h>


#include <MdaAudioTonePlayer.h>


#include "audioadapter.h"


 


// CONSTANTS


// Frequency and duration of the tone to be played


static const TInt KSoundFrequency = 3000;   //声音的播放频率


static const TInt KSoundDuration = 5000000; //声音的播放时间


 


// FORWARD DECLARATIONS


class CSoundAppUi;


 


// CLASS DECLARATION


class CToneAdapter : public CBase,


                     public MAudioAdapter,


                     public MMdaAudioToneObserver


    {


    public:


        static CToneAdapter* NewL( CSoundAppUi& aAppUi );


        static CToneAdapter* NewLC( CSoundAppUi& aAppUi );


        virtual ~CToneAdapter();


 


    public: // from MAudioAdapter


        /**


        * PlayL


        * Begin playback of the tone.


        */


        void PlayL();


        /**


        * RecordL


        * Do nothing. Recording is not supported.


        */


        void RecordL();


        /**


        * StopL


        * Stop playback or recording of the tone.


        * Note that this implementation of the virtual function does not leave.


        */  


        void StopL();


        /**


        * UpdateMenuL


        * Update the menu aMenuPane to reflect the


        * current state of the audio tone utility.


        * Note that this implementation of the virtual function does not leave.


        * @param aMenuPane the menu pane to update


        */


        void UpdateMenuL( CEikMenuPane* aMenuPane );


        /**


        * Identify


        * Return an identifying string


        * @return An identification string


        */


        const TDesC& Identify();


 


    public: // from MMdaAudioToneObserver


 


        /**


        * MatoPrepareComplete


        * Handle the event when a tone utility initialisation


        * operation has completed.


        * @param aError indicates whether an error occurred.


        */


        void MatoPrepareComplete( TInt aError );


 


        /**


        * MatoPlayComplete


        * Handle the event when a tone playing operation has completed.


        * @param aError indicates whether an error occurred.


        */


        void MatoPlayComplete( TInt aError );


   


    private: // Constructors and destructor


        /**


        * CToneAdapter.


        * C++ default constructor.


        * Perform the first phase of two phase construction


        * @param aAppUi the Ui to use


        */


        CToneAdapter( CSoundAppUi& aAppUi );


        /**


        * ConstructL


        * 2nd phase constructor.


        * @param aRect Frame rectangle for container.


        */


        void ConstructL();


    private: // Data


        /**


        * iMdaAudioToneUtility The audio tone utility object.


        * owned by CToneAdapter object.


        */


        CMdaAudioToneUtility* iMdaAudioToneUtility;


        /** iAppUi Reference to the application's UI object. **/


        CSoundAppUi& iAppUi;


        /**


        * itextResourceIdentifier. Textresource for identifier


        * owned by CToneAdapter object.


        */


        HBufC* itextResourceIdentifier;


    };


 


#endif // __CTONEADAPTER_H__


 


从类声明的接口中我们可以看出,这个类封装了MAudioAdapterMMdaAudioToneObserver中的接口,MmdaAudioToneObserver没什么好说的,是Symbian音频框架提供的一个接口,用来监听音频播放中的各种事件。



而MaudioAdapter是项目中的另外一个接口,其声明如下


#ifndef __MAUDIOADAPTER_H__


#define __MAUDIOADAPTER_H__


#include <e32std.h>


class CEikMenuPane;


class MAudioAdapter


    {


    public: // New functions


        /**


        * PlayL


        * Play the audio utility.


        */       


        virtual void PlayL() = 0;


        /**


        * StopL


        * Stop the audio utility.


        */ 


        virtual void StopL() = 0;


        /**


        * RecordL


        * Record using the audio utility ( if supported ).


        */


        virtual void RecordL() = 0;


        /**


        * UpdateMenuL


        * Update the menu aMenuPane to reflect the current


        * state of the audio utility.


        * @param aMenuPane the menu pane to update


        */


        virtual void UpdateMenuL( CEikMenuPane* aMenuPane ) = 0;


        /**


        * Identify


        * Return an identifying string


        * @return an identifier


        */


        virtual const TDesC& Identify() = 0;


 


    };


#endif // __MAUDIOADAPTER_H__


可以看出这是一个纯接口,抽象出了音频播放的一些共性的东西,然后“委托”给具体的播放类来实现。其中CtoneAdapter就是一个具体的实现。



下面来具体看看CtoneAdapter的实现


#include <eikmenup.h>


#include <sound.rsg>


 


#include "sound.pan"


#include "sound.hrh"


#include "toneadapter.h"


#include "soundappui.h"


 


// C++ default constructor can NOT contain any code, that might leave.


CToneAdapter::CToneAdapter( CSoundAppUi& aAppUi ) : iAppUi( aAppUi )


    {


    // No implementation required


    }


 


// Two-phased constructor.


CToneAdapter* CToneAdapter::NewL( CSoundAppUi& aAppUi )


    {


    CToneAdapter* self = NewLC( aAppUi );


    CleanupStack::Pop( self );


    return self;


    }


 


// Two-phased constructor.


CToneAdapter* CToneAdapter::NewLC( CSoundAppUi& aAppUi )


    {


    CToneAdapter* self = new( ELeave )CToneAdapter( aAppUi );


    CleanupStack::PushL( self );


    self->ConstructL();


    return self;


    }


 


// Symbian 2nd phase constructor can leave.


void CToneAdapter::ConstructL()


    {


 


    // Load a string from the resource file.


    // Identifying string for this audio utility.


     itextResourceIdentifier = CCoeEnv::Static()->AllocReadResourceL(


                                                            R_SOUN_MODE_TONER );


 


    iMdaAudioToneUtility = CMdaAudioToneUtility::NewL( *this );


 


    // Configure the audio tone utility to play a single tone


    // causes MMdaAudioToneObserver::MatoPrepareComplete to be called


    iMdaAudioToneUtility->PrepareToPlayTone( KSoundFrequency,


                                   TTimeIntervalMicroSeconds( KSoundDuration ) );


    }


 


// Destructor.


CToneAdapter::~CToneAdapter()


    {


    delete iMdaAudioToneUtility;   


    iMdaAudioToneUtility = NULL;


 


    // Delete private HBuf member for indetify


    delete itextResourceIdentifier;


    }


 


// Update Menu


void CToneAdapter::UpdateMenuL( CEikMenuPane* aMenuPane )


    {


    aMenuPane->SetItemDimmed( ESoundCmdPlay,   ETrue );


    aMenuPane->SetItemDimmed( ESoundCmdRecord, ETrue );


    aMenuPane->SetItemDimmed( ESoundCmdStop,   ETrue );


    aMenuPane->SetItemDimmed( ESoundCmdChange, ETrue );


   


    switch ( iMdaAudioToneUtility->State() )


        {


        case EMdaAudioToneUtilityNotReady:


            aMenuPane->SetItemDimmed( ESoundCmdChange, EFalse );


            break;


 


        case EMdaAudioToneUtilityPrepared:


            aMenuPane->SetItemDimmed( ESoundCmdPlay, EFalse );


            aMenuPane->SetItemDimmed( ESoundCmdChange, EFalse );


            break;


 


        case EMdaAudioToneUtilityPlaying:


            aMenuPane->SetItemDimmed( ESoundCmdStop, EFalse );


            break;


 


        default:


            User::Panic( KToneAdapter, KSoundPanicInvalidMdaState );


            break;


        }


    }


 


// Play the tone


void CToneAdapter::PlayL()


    {


    iMdaAudioToneUtility->Play();


    }


 


// CMdaAudioToneUtility is not able to record


void CToneAdapter::RecordL()


    {


    // No implementation required


}


 


// Stop the toneplay


void CToneAdapter::StopL()


    {


    iMdaAudioToneUtility->CancelPlay();


    }


 


// Identify mode


const TDesC& CToneAdapter::Identify()


    {


     return *itextResourceIdentifier;


    }


 


// Prepare to Complete


void CToneAdapter::MatoPrepareComplete( TInt /*aError*/ )


    {


    iMdaAudioToneUtility->SetVolume( iMdaAudioToneUtility->MaxVolume() );


}


 


// Play Complete


void CToneAdapter::MatoPlayComplete( TInt /*aError*/ )


    {


    // No implementation required


}


 


这个项目也体现了如何实现“动态菜单”,下面是和“动态菜单”相关的代码:


// This function is called by the EIKON framework just before it displays


// a menu pane. Its default implementation is empty, and by overriding it,


// the application can set the state of menu items dynamically according


// to the state of application data.


void CSoundAppUi::DynInitMenuPaneL( TInt aResourceId,


                                    CEikMenuPane* aMenuPane)


    {


    if ( aResourceId == R_SOUND_MENU )


        {


        iAudioAdapter->UpdateMenuL( aMenuPane );


        }


}


通过在AppUi中重写DynInitMenuPaneL()方法,然后在每次显示“菜单”之前,EIKON框架都会调用此方法,而此方法把“动态变化”的任务“委托”给各个播放类,从而实现了菜单的动态变化。


 


②     CmdaAudioPlayerUtility



Description


Plays sampled audio data.


The class offers a simple interface to open, play and obtain information from, sampled audio data. The audio data can supplied either in a file, a descriptor or a URL (since version 7.0s).


While this class is abstract, the four static functions construct, initialise and return pointers to instances of concrete classes derived from this abstract class. This concrete class is part of the MMF implementation and is private.



从类的Description中可以看出,这个类是用来播放audio data的。


Audio data可以是一个文件,也可以是一个描述符(Descriptor)或者是一个URL。


但是URL只使用于7.0S以后的版本!


 


这个应该是我们在程序中用的最多的一个音频播放接口。


其对应的监听接口为MmdaAudioPlayerCallback,作用和其它监听接口一样。


 


class CPlayerAdapter : public CBase,


                       public MAudioAdapter,


public MmdaAudioPlayerCallback


可以看出CPlayerAdapter和CtoneAdapter一样,实现了MaudioAdapter和自己响应的监听接口。


 


下面是它的具体实现


#include <eikmenup.h>


#include <eikapp.h>


#include <sound.rsg>


 


#include "sound.pan"


#include "sound.hrh"


#include "playeradapter.h"


#include "soundappui.h"


 


CPlayerAdapter::CPlayerAdapter( CSoundAppUi& aAppUi )


: iState( ENotReady ), iAppUi( aAppUi )


    {


    // No implementation required


}


 


CPlayerAdapter* CPlayerAdapter::NewL( const TDesC& aFileName,


                                      CSoundAppUi& aAppUi )


    {


    CPlayerAdapter* self = NewLC( aFileName, aAppUi );


    CleanupStack::Pop( self ); 


    return self;


}


 


CPlayerAdapter* CPlayerAdapter::NewLC( const TDesC& aFileName,


                                       CSoundAppUi& aAppUi )


    {


    CPlayerAdapter* self = new ( ELeave ) CPlayerAdapter( aAppUi );


    CleanupStack::PushL( self );


    self->ConstructL( aFileName );


    return self;


}


 


void CPlayerAdapter::ConstructL( const TDesC& aFileName )


    {


 


     // Load a string from the resource file.


     // Identifying string for this audio utility.


     itextResourceIdentifier = CCoeEnv::Static()->AllocReadResourceL(


                                                            R_SOUN_MODE_PLAYER );


 


 


   #ifdef __WINS__


        // on emulator, the sound files used by application are


        // deployed onto c: drive


         _LIT( tFullPath,"c:\\system\\apps\\sound\\" );


        TParse parse;


   


    #else


 


        // on real phone, application can be installed to the memory


        // card ( non-"C:" drive ),


        // this part of code evaluates current application path:


       


        // find the instance of EikonEnv


        CEikonEnv& ee = *CEikonEnv::Static();  


       


        // derive the instance of EikonAppUi


        CEikAppUi& ea = *( ee.EikAppUi() );    


 


        // fetch the application full filename


        TFileName tAppFullName = ea.Application()->AppFullName();


        TParse parse;


 


        // form parse object containing full app name


        parse.Set( tAppFullName, NULL, NULL );


       


        // get application path with drive letter


        TFileName tFullPath = parse.DriveAndPath();


 


    #endif


 


 


    // use tparse to get the full path to sound file


    parse.Set( tFullPath, &aFileName, NULL ); 


    TFileName tFullFileName = parse.FullName();


 


    // Create an audio player utility instance for playing


    // sample data from a file,


    // causes MMdaAudioPlayerCallback::MapcInitComplete to be called


    iMdaAudioPlayerUtility = CMdaAudioPlayerUtility::NewFilePlayerL( tFullFileName, *this );


}


 


CPlayerAdapter::~CPlayerAdapter()


    {


    delete iMdaAudioPlayerUtility;   


 


    // Delete private HBuf member for indetify


    delete itextResourceIdentifier;


}


 


// Update Menu


void CPlayerAdapter::UpdateMenuL( CEikMenuPane* aMenuPane )


    {


    aMenuPane->SetItemDimmed( ESoundCmdPlay,   ETrue );


    aMenuPane->SetItemDimmed( ESoundCmdRecord, ETrue );


    aMenuPane->SetItemDimmed( ESoundCmdStop,   ETrue );


    aMenuPane->SetItemDimmed( ESoundCmdChange, ETrue );


 


    switch ( iState )


        {


        case ENotReady:


            aMenuPane->SetItemDimmed( ESoundCmdChange, EFalse );


            break;


 


        case EReadyToPlay:


            aMenuPane->SetItemDimmed( ESoundCmdPlay, EFalse );


            aMenuPane->SetItemDimmed( ESoundCmdChange, EFalse );


            break;


 


        case EPlaying:


            aMenuPane->SetItemDimmed( ESoundCmdStop, EFalse );


            break;


 


        default:


            User::Panic( KPlayerAdapter, KSoundPanicInvalidMdaState );


            break;


        }


}


 


// Play the wav


void CPlayerAdapter::PlayL()


    {


    iMdaAudioPlayerUtility->Play();


    iState = EPlaying;


}


 


// Record the wav, not available in Player mode.


void CPlayerAdapter::RecordL()


    {


    // No implementation required


}


 


// Stop the play


void CPlayerAdapter::StopL()


    {


    iMdaAudioPlayerUtility->Stop();


    iState = EReadyToPlay;


}


 


// Identify mode


const TDesC& CPlayerAdapter::Identify()


    {


     return *itextResourceIdentifier;


}


 


// Mapc Init Complete


void CPlayerAdapter::MapcInitComplete( TInt aError,


                                 const TTimeIntervalMicroSeconds& /*aDuration*/ )


    {


    iState = aError ? ENotReady : EReadyToPlay;


}


 


// Mapc Play Complete


void CPlayerAdapter::MapcPlayComplete( TInt aError )


    {


    iState = aError ? ENotReady : EReadyToPlay;


    }


// End of File


 


③    CmdaAudioRecorderUtility



Description


Plays back, records and edits audio sample data.


The class offers an interface to play, record and edit audio sample data. This data can be supplied either in a file or as a descriptor. The functions that start and stop playback and recording are defined in the base class CMdaAudioClipUtility.


While this class is abstract, the static NewL() function constructs, initialises and returns a pointer to an instance of a concrete class derived from this abstract class. This concrete class is part of the MMF implementation and is private.



这个是关于“录音”的音频接口,其原理和上面两个也一样,略去!