cocos2dx 音频模块分析(2):背景音乐

前端之家收集整理的这篇文章主要介绍了cocos2dx 音频模块分析(2):背景音乐前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

cocos2dx 音频模块分析(2): 背景音乐部分

  1. 我在(1)已经分析了一些东西,这里接着分析,这一篇我们主要分析背景音乐文件的播放,
  2. 还是基于android平台:
  3.  
  4. 1
  5. 这里只是背景音乐的预加载,为什么要进行预加载呢?
  6. 主要是加载音乐文件是比较耗时的,如果我们没有预加载就直接播放也是可以的,
  7. 但是会有一定的延时,因为如果没有预加载,就直接播放,也是会先进行加载音乐文件
  8. 然后进行播放。
  9. void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
  10. {
  11. std::string fullPath = getFullPathWithoutAssetsPrefix(pszFilePath);
  12. preloadBackgroundMusicJNI(fullPath.c_str());
  13. }
  14.  
  15. 其实加载背景音乐最终调用android端:
  16. public void preloadBackgroundMusic(final String pPath) {
  17. if ((this.mCurrentPath == null) || (!this.mCurrentPath.equals(pPath))) {
  18. // preload new background music
  19.  
  20. // release old resource and create a new one
  21. // 如果我们播放的是一个新的背景音乐文件,那么我们需要先释放旧的播放器,然后创建一个新的
  22. // Releases resources associated with this MediaPlayer object.
  23. if (this.mBackgroundMediaPlayer != null) {
  24. this.mBackgroundMediaPlayer.release();
  25. }
  26. //创建一个播放器即MediaPlayer类的实例
  27. this.mBackgroundMediaPlayer = this.createMediaplayer(pPath);
  28.  
  29. // record the path
  30. // 记录当前播放的背景音乐文件,因为下次如果播放的是同一个音乐
  31. // 文件,那么我们就可以直接进行播放了,不用再重新创建MediaPlayer类的实例
  32. this.mCurrentPath = pPath;
  33. }
  34. }
  35.  
  36. ----->>>
  37. /**
  38. * create mediaplayer for music
  39. *
  40. * @param pPath
  41. * the pPath relative to assets
  42. * @return
  43. */
  44. private MediaPlayer createMediaplayer(final String pPath) {
  45. MediaPlayer mediaPlayer = new MediaPlayer();
  46.  
  47. try {
  48. //对绝对路径和包里的路径进行区分处理,当最终的目的就是设置播放源
  49. if (pPath.startsWith("/")) {
  50. final FileInputStream fis = new FileInputStream(pPath);
  51. mediaPlayer.setDataSource(fis.getFD());
  52. fis.close();
  53. } else {
  54. final AssetFileDescriptor assetFileDescritor = this.mContext.getAssets().openFd(pPath);
  55. mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(),assetFileDescritor.getStartOffset(),assetFileDescritor.getLength());
  56. }
  57. //播放器前需要做些准备工作,这个只是android的api,不明白的话,查下文档。
  58. /**
  59. * Prepares the player for playback,synchronously.
  60. *
  61. * After setting the datasource and the display surface,you need to either
  62. * call prepare() or prepareAsync(). For files,it is OK to call prepare(),* which blocks until MediaPlayer is ready for playback.
  63. *
  64. * @throws IllegalStateException if it is called in an invalid state
  65. */
  66. mediaPlayer.prepare();
  67. //设置声音音量
  68. mediaPlayer.setVolume(this.mLeftVolume,this.mRightVolume);
  69. } catch (final Exception e) {
  70. mediaPlayer = null;
  71. Log.e(Cocos2dxMusic.TAG,"error: " + e.getMessage(),e);
  72. }
  73.  
  74. return mediaPlayer;
  75. }
  76.  
  77. 2
  78. 音乐播放函数
  79. //pszFilePath: 音乐文件
  80. //bLoop: 是否循环播放,音乐文件我们一般设置为循环播放,看具体情况
  81. void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath,bool bLoop)
  82. {
  83. std::string fullPath = getFullPathWithoutAssetsPrefix(pszFilePath);
  84. playBackgroundMusicJNI(fullPath.c_str(),bLoop);
  85. }
  86.  
  87. --->>> 最终都会调用android端的playBackgroundMusic函数,并把文件路径,是否循环播放传进来
  88. public void playBackgroundMusic(final String path,final boolean isLoop) {
  89. if (mCurrentPath == null) {
  90. // it is the first time to play background music or end() was called
  91. // 如果以前没有播放过音乐文件,那么重新创建一个,上面的英文注释很清楚
  92. mBackgroundMediaPlayer = createMediaplayer(path);
  93. mCurrentPath = path;
  94. } else {
  95. if (!mCurrentPath.equals(path)) {
  96. // play new background music
  97. //如果这次播放的音乐文件和上次的不同,即是一个新的音乐文件
  98. //那么就需要先释放掉旧的,然后创建一个新的。
  99. // release old resource and create a new one
  100. if (mBackgroundMediaPlayer != null) {
  101. mBackgroundMediaPlayer.release();
  102. }
  103. mBackgroundMediaPlayer = createMediaplayer(path);
  104.  
  105. // record the path
  106. mCurrentPath = path;
  107. }
  108. }
  109.  
  110. if (mBackgroundMediaPlayer == null) {
  111. Log.e(Cocos2dxMusic.TAG,"playBackgroundMusic: background media player is null");
  112. } else {
  113. try {
  114. // if the music is playing or paused,stop it
  115. // 对playing or paused,stop三种情况进行分别处理
  116. if (mPaused) {
  117. //如果是暂停状态,那么就把播放进度设置到0,然后开始。
  118. //这就意味着,如果我们调用了暂停,然后又调用play,那么
  119. //音乐将会从头开始播放,而不是从暂停的地方接着播放。
  120. /**
  121. * Seeks to specified time position.
  122. *
  123. * @param msec the offset in milliseconds from the start to seek to
  124. * @throws IllegalStateException if the internal player engine has not been
  125. * initialized
  126. */
  127. mBackgroundMediaPlayer.seekTo(0);
  128.  
  129. /**
  130. * Starts(开始) or resumes playback(恢复播放). If playback had prevIoUsly been paused,* playback will continue from where it was paused. If playback had
  131. * been stopped,or never started before,playback will start at the
  132. * beginning.
  133. * start函数两个功能,一个是开始播放,一个是恢复播放
  134. * 1、如果stopped或者never started before(第一次开始),那么就从头开始播放
  135. * 2、如果paused即暂停,那么将会从暂停的地方接着播放。
  136. */
  137. mBackgroundMediaPlayer.start();
  138. } else if (mBackgroundMediaPlayer.isPlaying()) {
  139. //如果处于播放状态,则回到开始,从头播放
  140. mBackgroundMediaPlayer.seekTo(0);
  141. } else {
  142. //如果处于stop状态,则从新播放,上面已经说明了start函数的两个作用
  143. mBackgroundMediaPlayer.start();
  144. }
  145. /*
  146. 总结:其实对上面三种情况分别处理,最终达到的效果都是一样的,
  147. 那就是从头开始播放背景音乐文件
  148. */
  149.  
  150. //设置是否循环播放
  151. mBackgroundMediaPlayer.setLooping(isLoop);
  152.  
  153. //mPaused 表示设为false,表示不处于暂停状态
  154. mPaused = false;
  155.  
  156. //是否循环播放记录
  157. mIsLoop = isLoop;
  158. } catch (final Exception e) {
  159. Log.e(Cocos2dxMusic.TAG,"playBackgroundMusic: error state");
  160. }
  161. }
  162. }
  163.  
  164. 3、总结:
  165. 从上面的分析我们可以知道,如果预先进行加载即先创建一个MediaPlayer
  166. 那么我们播放时可以直接进行播放,如果我们我们没有提前进行预加载
  167. 而是直接调用playBackgroundMusic函数,也可以进行播放,只不过会有一个创建
  168. MediaPlayer的过程,会有一些时间上的延时。

猜你在找的Cocos2d-x相关文章