Android高级音频应用
说到音频应用,首先想到的就是音乐播放器。有些播放器可以播放流媒体,有些可以播放本地音乐文件。随着Android平台的演变,需要更多高级的音频API。好在谷歌新增了这方面的API,支持低延迟的音频流媒体和录制。
Android音频API提供了一些高级的功能,开发者可以把它们集成到自己的应用中。有了这些API,现在可以更容易地实现VoIP应用程序,构建定制的流媒体音乐客户端,实现低延迟的游戏音效。此外,还有提供文本到语音转换以及语音识别的API,用户可以直接使用音频和应用交互,而不需要使用用户界面或者触控技术。
低延迟音频
Android有四个用来播放音频的API(算上MIDI的话一共五个)和三个用来录音的API。接下来会简要的介绍这些API,以及一些高级用法示例。
①音频播放API
音乐播放默认使用MediaPlayer。该类适合播放音乐或者视频,既能播放流式资源,还可以播放本地文件。每个MediaPlayer都有一个关联的状态机,需要在应用程序中跟踪这些状态。开发者可以使用MediaPlayer类的API在自己应用中嵌入音乐或者视频播放功能,而无需额外处理或者考虑延迟要求。
第二个选择是SoundPool类,它提供了低延迟支持,适合播放音效和其他比较短的音频,比如可以使用SoundPool播放游戏声音。但是,它不支持音频流,所以不适合那些需要实时音频流处理的应用,如VoIP。
第三个选择是AudioTrack类,它允许把音频流缓冲到硬件中,支持低延迟播放,甚至适合流媒体场景。AudioTrack类通常提供足够低的延迟,可在VoIP或类似应用中使用。
下面的代码展示了如何在VoIP应用中使用AudioTrack:
public class AudioTrackDemo {
private final int mMinBufferSize;
private final AudioTrack mAudioTrack;
public AudioTrackDemo() {
this.mMinBufferSize = AudioTrack.getMinBufferSize(, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
this.mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, , AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, this.mMinBufferSize*, AudioTrack.MODE_STREAM);
}
public void playPcmPacket(byte[] pcmData) {
if (this.mAudioTrack != null && this.mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
if (this.mAudioTrack.getPlaybackRate() != AudioTrack.PLAYSTATE_PLAYING) {
this.mAudioTrack.play();
}
this.mAudioTrack.write(pcmData, , pcmData.length);
}
}
public void stopPlayback() {
if (this.mAudioTrack != null) {
this.mAudioTrack.stop();
this.mAudioTrack.release();
}
}
}
首先,确定音频流的最小缓冲区大小。要做到这一点,需要知道采样率,数据是单声道还是立体声,以及是否使用8位或者16位PCM编码。然后以采样率和采样大小作为参数调用AudioTrack.getMinBufferSize(),该方法会以字节形式返回AudioTrack实例的最小缓冲区大小。
接下来,根据需要使用正确参数创建AudioTrack实例。第一个参数为音频的类型,不同的应用使用不同的值。对VoIP应用来说,使用STREAM_VOICE_CALL,而对于流媒体音乐应用则使用STREAM_MUSIC。
具体的选择有:
STREAM_ALARM:手机闹铃的声音
STREAM_MUSIC:手机音乐的声音
STREAM_DTMF:DTMF音调的声音
STREAM_RING:电话铃声的声音
STREAM_NOTFICATION:系统提示的声音
STREAM_SYSTEM:系统的声音
STREAM_VOICE_CALL:语音电话声音
第二,第三,第四个参数根据使用场景会有所不同。这些参数分别表示采样率,立体声或者单声道,以及采样大小。一般而言,一个VoIP应用会使用16KHZ的16位单声道,而常规的音乐CD可能采用44.1KHZ的16位立体声。16位立体声高采样率需要更大的缓冲区以及更多的数据传输,但是音质会更好。所有的Android设备都支持PCM以8KHZ,16KHZ,44.1KHZ的采样率播放8或者16位立体声。
缓冲区大小参数应该是最小缓冲区的倍数,实际取决于具体的需求,有时网络延迟等因素也会影响缓冲区大小。
任何时候都应该避免使用空的缓冲区,因为可能导致播放出现故障。
最后一个参数决定只发送一次音频数据(MODE_STATIC)还是连续发送数据流(MODE_STREAM)。第一种情况需要一次发送整个音频剪辑。对于持续发送音频流的情况,可以发送任大小块的PCM数据,处理流媒体音乐或者VoIP通话可以会使用这种方式。
②录制API
谈到录制音频,首先要考虑的API是MediaRecorder。和MediaPlayer类似,需要在应用代码中跟踪MediaRecorder类的内部状态。由于MediaRecorder只能把录音保存到文件中,所以它不适合录制流媒体。
如果需要录制流媒体,可以使用AudioRecord,和刚才展示的代码非常类似。
下面的示例显示了如何创建AudioRecord实例录制16位单声道16KHZ的音频采样:
public class AudioRecordDemo {
private final AudioRecord mAudioRecord;
private final int mMinBufferSize;
private boolean mDoRecord = false;
public AudioRecordDemo() {
this.mMinBufferSize = AudioTrack.getMinBufferSize(, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
this.mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, , AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, this.mMinBufferSize * );
}
public void writeAudioToStream(OutputStream stream){
this.mDoRecord=true;
this.mAudioRecord.startRecording();
byte[] buffer=new byte[this.mMinBufferSize*];
while(this.mDoRecord){
int byteWritten=this.mAudioRecord.read(buffer,,buffer.length);
try{
stream.write(buffer,,byteWritten);
}catch(IOException e){
this.mDoRecord=false;
}
}
this.mAudioRecord.stop();
this.mAudioRecord.release();
}
public void stopRecording(){
this.mDoRecord=false;
}
}
因为和AudioTrack的创建过程非常类似,在使用VoIP或者类似应用时可以很方便地把它们结合起来。
相信学过多媒体的人对采样率等这些东西并不陌生,如果缺乏这方面的知识,可以适当的补充后在来看这段代码。
如果看的认真的人会发现本文只介绍了三个播放API和两个录制API,说好的四个的三个呢?其实最后一个不是一两句就能说清楚,还需要单独列出一篇文章讲解——OpenSL ES请关注本博客后续会讲解到。
版权声明:本文为博主原创文章,未经博主允许不得转载。
Android高级音频应用的更多相关文章
- Android 高级UI设计笔记07:RecyclerView 的详解
1. 使用RecyclerView 在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...
- Android高级编程笔记(四)深入探讨Activity(转)
在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕.这个主界面一般由多个Fragment组成,并由一组次要Activity支持.要在屏幕之间切换,就必须要启动一个新的Activity.一 ...
- Android高级开发专题晋升班
Android高级开发专题晋升班 适用人群:1-3年以上经验的开发者丨学员平均薪酬20K/月
- 《Android高级进阶》读书笔记
<Android高级进阶>是据我所知的市面上唯一一本技术工具书,比较的高大全,作者的目的是为了对全领域有个初步的概念 No1: 在Android系统中,拥有事件传递处理能力的类有以下三种 ...
- [总]Android高级进阶之路
个人Android高级进阶之路,目前按照这个目录执行,执行完毕再做扩展!!!!! 一.View的绘制 1)setContentView()的源码分析 2)SnackBar的源码分析 3)利用decor ...
- cocos打包到ios与android上音频推荐
首先贴一张官方对于ios与android上音频格式的推荐: 这里只给出了推荐格式,一般我们在实际运用中会使用如下方式: 一.IOS与安卓各一套:音乐:都使用MP3 音效:ios用caf Andr ...
- Android如何实现毛玻璃效果之Android高级模糊技术
自从iOS系统引入了Blur效果,也就是所谓的毛玻璃.模糊化效果,磨砂效果,各大系统就开始竞相模仿,这是怎样的一个效果呢,我们先来看一下,如下面的图片: 效果我们知道了,如何在Android中实现呢, ...
- Android怎样实现毛玻璃效果之Android高级模糊技术
自从iOS系统引入了Blur效果,也就是所谓的毛玻璃.模糊化效果.磨砂效果.各大系统就開始竞相模仿,这是如何的一个效果呢,我们先来看一下,如以下的图片: 效果我们知道了,怎样在Android中实现呢. ...
- 腾讯面试Android高级岗,居然被一个多线程基础面倒了?
前言 一个在深圳从事开发五年的老友一个月前从原公司辞职后,昨天去腾讯总部面试Android高级岗,一面的时候,自我介绍后,陆陆续续问了很多问题,有着五年的从业经验很多项目开发的技术问题都回答的很通顺, ...
随机推荐
- 【转】Android 防破解技术简介
http://www.cnblogs.com/likeandroid/p/4888808.html Android 防破解技术简介 这几年随着互联网的不断发展,Android App 也越来越多!但是 ...
- 无法将类型为 excel.applicationclass 的 com 强制转换为接口类型 的解决方法。
今天碰到客户的电脑在导出EXCEL的时候提示,无法将类型为 excel.applicationclass 的 com 强制转换为接口类型 excel._application 的问题 最后用下面的方法 ...
- C++ 方法隐藏
1.过载:一个类中,方法名相同,形参表不同的方法. 2.重写:子类与父类的virtual方法,方法名,形参表相同. 3.考虑下面的情况,子类与父类方法名相同. 父类是virtual方法 ...
- window.showModalDialog 与window.open传递参数的不同?
简单的说,就是一个在弹出窗口之后可以做其它的事,即window.open 另一个在弹出窗口之后不能做其它的事,只能是关闭了当前的窗口之后才能做其它的事,即window.showModalDialog ...
- Android平台上长连接的实现
Android 平台上长连接的实现 为了不让 NAT 表失效,我们需要定时的发心跳,以刷新 NAT 表项,避免被淘汰. Android 上定时运行任务常用的方法有2种,一种方法用 Timer,另一种是 ...
- js的加载方式
同步加载即<script>标签 异步加载即 动态插入<script>标签,动态修改<script>的src属性. Ajax加载.
- 防止IE缓存jquery ajax 内容
转自:http://blog.163.com/haijun_huang/blog/static/167591377201201235754763/ 解决办法: 方法一:把type改成post,并随便设 ...
- 查询记录时rs.previous()的使用
查询记录时rs.previous()的使用 假如查询一个数据表,假设没有记录就显示提示信息,有就所有显示出来查询结果.这时假设是有查询结果的话就须要进行两次查询,第一次查完记录指针指向最后一条记录,開 ...
- Hello_IOS ios开发transform属性
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutl ...
- 使用NIO提升性能
NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标准. 具有以下特性: 传统Java IO,它是阻塞的,低效的.那么Java NIO和传统Java ...