Android游戏编程之音频编程(3)

短小的音效很时候放在Android应用程序从操作系统分配到的堆内存中,而包含较长音乐文件的大音频文件就很不适合了。为此,我们就需要将音乐以流的方式输出到音频硬件上,这就意味着每次我们只能读入一小块数据,该数据足于解码成原生的PCM数据并输出到音频芯片上。

这听起来挺吓人的。不过幸运的是,我们有MediaPlayer类,它能处理的所有事情。初始化MediaPlayer类:

MediaPlayer mediaPlayer = new MediaPlayer();

接下来我们需要告诉MediaPlayer播放什么文件,这同样通过AssetFileDescriptor来实现:

AssetFileDescriptor descriptor = assetManager.openFd("music.ogg");

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

这里稍微比SoundPool中复杂一点。MediaPlayer.setDataSource()方法并没有直接获取AssetFileDescriptor,而是使用一个FileDescriptor,通过AssetFileDescriptor().getFileDescriptor()方法获取该描述符,除此之外我们还需要指定音频文件的偏移量和长度。为什么是偏移量?实际上资源是以单个文件形式存储的,为了让MediaPlayer获得文件的起始地址,我们需要将asset文件夹中的文件的偏移量提供给它。

在播放该音乐文件之前,需要再调用一个方法为MediaPlayer的播放做准备:

MediaPlayer.prepare();

这将实际地打开文件,检查它是否可以读取并用MediaPlayer实例来进行播放。从这里开始,我们就可以随意地播放、暂停和停止音频文件,也可以设置循环播放和改变音量。

启动播放可通过调用下面的方法进行:

mediaPlayer.start();

注意,该方法必须在成功调用MediaPlayer.prepare()方法之后才能调用(你将注意到它是否会抛出一个运行时异常)。

开始播放后,我们可以通过调用pause()方法来暂停播放:

MediaPlayer.pause();

只有我们成功准备好MediaPlayer并已启动播放,调用此方法才会生效。为了恢复一个暂停的MediaPlayer,可再次调用MediaPlayer.start()方法而无需任何准备。

通过调用下面的方法可停止播放:

MediaPlayer.stop();

注意,当我们想启动一个停止的MediaPlayer时,需要先再次调用MediaPlayer.prepare()方法。

我们可通过下面方法设置循环播放:

MediaPlayer.setLooping(true);

可通过下面的方法来调整音乐播放的音量:

MediaPlayer.setVolume(1, 1);

这会重新设置左右声道的音量,文档中没有指定这两个参数的设定范围。从多次尝试的结果看,有效值应该是0-1。

最后,我们需要一个方法来检查该播放是否完成,有两种方式可实现这一点。对于第一种方式,可向MediaPlayer注册一个OnCompletionListener,当播放完成时它就会被调用:

mediaPlayer.setOnCompletionListener(listener);

如果我们想轮询MediaPlayer的状态,则可使用下面方法:

boolean isPlaying = mediaPlayer.isPlaying();

注意,如果MediaPlayer被设置成循环播放,前面两个方法都无法指示该MediaPlayer已停止。

最后,如果MediaPlayer实例完成了所有的操作,就需要通过下面的方法来确保它所占用的资源得以释放:

mediaPlayer.release();

在丢弃一个实例前,执行这个操作应是很好的实践。

如果我们没有将MediaPlayer设置成循环且播放已结束,就可以通过MediaPlayer.prepare()和MediaPlayer.start()方法重启MediaPlayer。

大多数这些方法都是异步的,因此当调用MediaPlayer.stop()时,MediaPlayer.isPlaying()方法可能还需要一点时间才能返回。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/9f072f294090b1904fc691b842bc1548.html