展会信息港展会大全

cocos2dx 音频模块分析:背景音乐
来源:互联网   发布日期:2015-09-28 11:08:45   浏览:2407次  

导读: 我在(1)已经分析了一些东西,这里接着分析,这一篇我们主要分析背景音乐文件的播放, 还是基于android平台: 1、 这里只是背景音乐的预加载,为什么要进行预加载呢? 主要是加载音...

我在(1)已经分析了一些东西,这里接着分析,这一篇我们主要分析背景音乐文件的播放,

还是基于android平台:

1、

这里只是背景音乐的预加载,为什么要进行预加载呢?

主要是加载音乐文件是比较耗时的,如果我们没有预加载就直接播放也是可以的,

但是会有一定的延时,因为如果没有预加载,就直接播放,也是会先进行加载音乐文件,

然后进行播放。

void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)

{

std::string fullPath = getFullPathWithoutAssetsPrefix(pszFilePath);

preloadBackgroundMusicJNI(fullPath.c_str());

}

其实加载背景音乐最终调用android端:

public void preloadBackgroundMusic(final String pPath) {

if ((this.mCurrentPath == null) || (!this.mCurrentPath.equals(pPath))) {

// preload new background music

// release old resource and create a new one

// 如果我们播放的是一个新的背景音乐文件,那么我们需要先释放旧的播放器,然后创建一个新的

// Releases resources associated with this MediaPlayer object.

if (this.mBackgroundMediaPlayer != null) {

this.mBackgroundMediaPlayer.release();

}

//创建一个播放器即MediaPlayer类的实例

this.mBackgroundMediaPlayer = this.createMediaplayer(pPath);

// record the path

// 记录当前播放的背景音乐文件,因为下次如果播放的是同一个音乐

// 文件,那么我们就可以直接进行播放了,不用再重新创建MediaPlayer类的实例

this.mCurrentPath = pPath;

}

}

----->>>

/**

* create mediaplayer for music

*

* @param pPath

*the pPath relative to assets

* @return

*/

private MediaPlayer createMediaplayer(final String pPath) {

MediaPlayer mediaPlayer = new MediaPlayer();

try {

//对绝对路径和包里的路径进行区分处理,当最终的目的就是设置播放源

if (pPath.startsWith("/")) {

final FileInputStream fis = new FileInputStream(pPath);

mediaPlayer.setDataSource(fis.getFD());

fis.close();

} else {

final AssetFileDescriptor assetFileDescritor = this.mContext.getAssets().openFd(pPath);

mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(), assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());

}

//播放器前需要做些准备工作,这个只是android的api,不明白的话,查下文档。

/**

* Prepares the player for playback, synchronously.

*

* After setting the datasource and the display surface, you need to either

* call prepare() or prepareAsync(). For files, it is OK to call prepare(),

* which blocks until MediaPlayer is ready for playback.

*

* @throws IllegalStateException if it is called in an invalid state

*/

mediaPlayer.prepare();

//设置声音音量

mediaPlayer.setVolume(this.mLeftVolume, this.mRightVolume);

} catch (final Exception e) {

mediaPlayer = null;

Log.e(Cocos2dxMusic.TAG, "error: " + e.getMessage(), e);

}

return mediaPlayer;

}

2、

音乐播放函数

//pszFilePath: 音乐文件名

//bLoop: 是否循环播放,音乐文件我们一般设置为循环播放,看具体情况

void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)

{

std::string fullPath = getFullPathWithoutAssetsPrefix(pszFilePath);

playBackgroundMusicJNI(fullPath.c_str(), bLoop);

}

--->>> 最终都会调用到android端的playBackgroundMusic函数,并把文件路径,是否循环播放传进来

public void playBackgroundMusic(final String path, final boolean isLoop) {

if (mCurrentPath == null) {

// it is the first time to play background music or end() was called

// 如果以前没有播放过音乐文件,那么重新创建一个,上面的英文注释很清楚

mBackgroundMediaPlayer = createMediaplayer(path);

mCurrentPath = path;

} else {

if (!mCurrentPath.equals(path)) {

// play new background music

//如果这次播放的音乐文件和上次的不同,即是一个新的音乐文件,

//那么就需要先释放掉旧的,然后创建一个新的。

// release old resource and create a new one

if (mBackgroundMediaPlayer != null) {

mBackgroundMediaPlayer.release();

}

mBackgroundMediaPlayer = createMediaplayer(path);

// record the path

mCurrentPath = path;

}

}

if (mBackgroundMediaPlayer == null) {

Log.e(Cocos2dxMusic.TAG, "playBackgroundMusic: background media player is null");

} else {

try {

// if the music is playing or paused, stop it

// 对playing or paused, stop三种情况进行分别处理

if (mPaused) {

//如果是暂停状态,那么就把播放进度设置到0,然后开始。

//这就意味着,如果我们调用了暂停,然后又调用play,那么

//音乐将会从头开始播放,而不是从暂停的地方接着播放。

/**

* Seeks to specified time position.

*

* @param msec the offset in milliseconds from the start to seek to

* @throws IllegalStateException if the internal player engine has not been

* initialized

*/

mBackgroundMediaPlayer.seekTo(0);

/**

* Starts(开始) or resumes playback(恢复播放). If playback had previously been paused,

* playback will continue from where it was paused. If playback had

* been stopped, or never started before, playback will start at the

* beginning.

* start函数两个功能,一个是开始播放,一个是恢复播放

* 1、如果stopped或者never started before(第一次开始),那么就从头开始播放

* 2、如果paused即暂停,那么将会从暂停的地方接着播放。

*/

mBackgroundMediaPlayer.start();

} else if (mBackgroundMediaPlayer.isPlaying()) {

//如果处于播放状态,则回到开始,从头播放

mBackgroundMediaPlayer.seekTo(0);

} else {

//如果处于stop状态,则从新播放,上面已经说明了start函数的两个作用

mBackgroundMediaPlayer.start();

}

/*

总结:其实对上面三种情况分别处理,最终达到的效果都是一样的,

那就是从头开始播放背景音乐文件。

*/

//设置是否循环播放

mBackgroundMediaPlayer.setLooping(isLoop);

//mPaused 表示设为false,表示不处于暂停状态

mPaused = false;

//是否循环播放记录

mIsLoop = isLoop;

} catch (final Exception e) {

Log.e(Cocos2dxMusic.TAG, "playBackgroundMusic: error state");

}

}

}

3、总结:

从上面的分析我们可以知道,如果预先进行加载即先创建一个MediaPlayer,

那么我们播放时可以直接进行播放,如果我们我们没有提前进行预加载,

而是直接调用playBackgroundMusic函数,也可以进行播放,只不过会有一个创建

MediaPlayer的过程,会有一些时间上的延时。

赞助本站

人工智能实验室
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港