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__
从类声明的接口中我们可以看出,这个类封装了MAudioAdapter和MMdaAudioToneObserver中的接口,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. |
这个是关于“录音”的音频接口,其原理和上面两个也一样,略去!