Symbian音频技术探究

Symbian音频技术解析
本文详细介绍了Symbian系统中的音频技术,包括播放音调、音频数据播放及录音等核心功能的实现方式。文中通过具体示例展示了如何利用Symbian SDK中的CMdaAudioToneUtility和CMdaAudioPlayerUtility类进行音调播放和音频数据处理。
 
Author: 孙东风
 
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
#include
#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 中的接口,Mm daAudioToneObserver没什么好说的,是Symbian音频框架提供的一个接口,用来监听音频播放中的各种事件。
而MaudioAdapter是项目中的另外一个接口,其声明如下
#ifndef __MAUDIOADAPTER_H__
#define __MAUDIOADAPTER_H__
#include
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
#include
 
#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
#include
#include
 
#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.
这个是关于“录音”的音频接口,其原理和上面两个也一样,略去!
 

Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1501283


内容概要:本文介绍了基于贝叶斯优化的CNN-LSTM混合神经网络在时间序列预测中的应用,并提供了完整的Matlab代码实现。该模型结合了卷积神经网络(CNN)在特征提取方面的优势与长短期记忆网络(LSTM)在处理时序依赖问题上的强大能力,形成一种高效的混合预测架构。通过贝叶斯优化算法自动调参,提升了模型的预测精度与泛化能力,适用于风电、光伏、负荷、交通流等多种复杂非线性系统的预测任务。文中还展示了模型训练流程、参数优化机制及实际预测效果分析,突出其在科研与工程应用中的实用性。; 适合人群:具备一定机器学习基基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)础和Matlab编程经验的高校研究生、科研人员及从事预测建模的工程技术人员,尤其适合关注深度学习与智能优化算法结合应用的研究者。; 使用场景及目标:①解决各类时间序列预测问题,如能源出力预测、电力负荷预测、环境数据预测等;②学习如何将CNN-LSTM模型与贝叶斯优化相结合,提升模型性能;③掌握Matlab环境下深度学习模型搭建与超参数自动优化的技术路线。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注贝叶斯优化模块与混合神经网络结构的设计逻辑,通过调整数据集和参数加深对模型工作机制的理解,同时可将其框架迁移至其他预测场景中验证效果。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值