音频audio播放两种方式:MediaPlayer和AudioTrack对比
背景:
播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供应用开发者使用。虽然都可以播放声音,但两者还是有很大的区别的。
在我们的audio子系统相关课程中讲解的一般都是AudioTrack进行直接播放pcm的音频数据,大概原理流程图:
二者播放音频代码:
MediaPlayer播放音频代码:
准备mp3文件
创建对应的MediaPlayer
//准备播放的mp3文件words.add(new Word("Come here.", "әnni'nem", R.raw.phrase_come_here));// We have audio focus now.// Create and setup the {@link MediaPlayer} for the audio resource associated// with the current wordmMediaPlayer = MediaPlayer.create(PhrasesActivity.this, word.getAudioResourceId());// Start the audio filemMediaPlayer.start();// Setup a listener on the media player, so that we can stop and release the// media player once the sound has finished playing.mMediaPlayer.setOnCompletionListener(mCompletionListener);
AudioTrack播放音频代码:
// 初始化
AudioTrack mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, // 指定在流的类型 // STREAM_ALARM:警告声 // STREAM_MUSCI:音乐声,例如music等 // STREAM_RING:铃声 // STREAM_SYSTEM:系统声音 // STREAM_VOCIE_CALL:电话声音 samplerate,// 设置音频数据的采样率 AudioFormat.CHANNEL_CONFIGURATION_STEREO,// 设置输出声道为双声道立体声 AudioFormat.ENCODING_PCM_16BIT,// 设置音频数据块是8位还是16位 mAudioMinBufSize, AudioTrack.MODE_STREAM);// 设置模式类型,在这里设置为流类型 // AudioTrack中有MODE_STATIC和MODE_STREAM两种分类。 // STREAM方式表示由用户通过write方式把数据一次一次得写到audiotrack中。 // 这种方式的缺点就是JAVA层和Native层不断地交换数据,效率损失较大。 // 而STATIC方式表示是一开始创建的时候,就把音频数据放到一个固定的buffer,然后直接传给audiotrack, // 后续就不用一次次得write了。AudioTrack会自己播放这个buffer中的数据。 // 这种方法对于铃声等体积较小的文件比较合适。 mAudioTrack.play(); // 启动
//这里的data就是pcm数据
mAudioTrack.write(data,0,len);// 停止与释放资源
mAudioTrack.stop();
mAudioTrack.release();
区别对比:
最大的区别是MediaPlayer可以播放多种格式的声音文件,例如MP3,AAC,WAV,OGG,MIDI等,MediaPlayer会在创建对应的音频解码器。
而AudioTrack只能播放已经解码的PCM流,如果是文件的话只支持wav格式的音频文件,因为wav格式的音频文件大部分都是PCM流。AudioTrack不创建解码器,所以只能播放不需要解码的wav文件。
当然两者之间还是有紧密的联系的,MediaPlayer在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack,注意这里的AudioTrack不是app进程创建的,而是MediaPlayer对应的服务端mediaserver进程创建的AudioTrack,AudioTrack再传递给AudioFlinger进行混音,然后才传递给硬件播放,所以是MediaPlaye内部r包含了AudioTrack。
总结区别如下:
即MediaPlayer其实只是多了对一些封装压缩格式的音频多了相关的解码过程,最后MediaPlayer还是构造AudioTrack来进行播放,AudioTrack的数据也还是pcm数据,pcm数据是MediaPlayer解码出来的。
systrace/perfetto对比
app进程使用MediaPlayer播放音频,是在mediaserver进程创建AudioTrack,而不是app进程创建
app进程直接使用AudioTrack播放音频
MeidaPlayer播放数据总结流图如下:
适用场景
MediaPlayer:
适合播放本地/网络音频文件(如MP3、FLAC、WAV等格式),支持多种格式且操作简单,但延迟较高。
AudioTrack:
直接播放解码后的PCM数据流,延迟低,cpu耗费少(因为不需要解码),适用于对实时性要求高的场景(如游戏音效、实时语音交互),但仅支持WAV格式文件或已解码的PCM流。
MediaPlayer:自动解码MP3、FLAC、WAV等格式,并将解码后的PCM流通过AudioTrack输出。
AudioTrack:仅支持解码后的PCM数据流(如WAV文件转换的PCM数据),需开发者手动处理音频解码环节。
原文参考:
https://mp.weixin.qq.com/s/3t4PbpZE93SQPs5rpGAKWA