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(16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        this.mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, this.mMinBufferSize*2, 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, 0, 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(16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        this.mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, this.mMinBufferSize * 2);
    }

    public void writeAudioToStream(OutputStream stream){
        this.mDoRecord=true;
        this.mAudioRecord.startRecording();
        byte[] buffer=new byte[this.mMinBufferSize*2];
        while(this.mDoRecord){
            int byteWritten=this.mAudioRecord.read(buffer,0,buffer.length);
            try{
                stream.write(buffer,0,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请关注本博客后续会讲解到。

时间: 2024-10-08 12:13:31

Android高级音频应用的相关文章

Android 高级面试题及答案

Android 高级面试题及答案 阅读目录 1.如何对 Android 应用进行性能分析 2.什么情况下会导致内存泄露 3.如何避免 OOM 异常 4.Android 中如何捕获未捕获的异常 5.ANR 是什么?怎样避免和解决 ANR(重要) 6.Android 线程间通信有哪几种方式 7.Devik 进程,linux 进程,线程的区别 8.描述一下 android 的系统架构 9.android 应用对内存是如何限制的?我们应该如何合理使用内存? 10. 简述 android 应用程序结构是哪

Android如何实现毛玻璃效果之Android高级模糊技术

自从iOS系统引入了Blur效果,也就是所谓的毛玻璃.模糊化效果,磨砂效果,各大系统就开始竞相模仿,这是怎样的一个效果呢,我们先来看一下,如下面的图片: 效果我们知道了,如何在Android中实现呢,说白了就是对图片进行模糊化处理,小编先给大家讲一下Android高级模糊技术的原理,如下: ·首先我创建了一个空的bitmap,把背景的一部分复制进去,之后我会对这个bitmap进行模糊处理并设置为TextView的背景. ·通过这个bitmap保存Canvas的状态: ·在父布局文件中把Canva

android 高级Canvas绘图

Canvas是图形编程中很实用的一个概念.通常有3个基本部分组成: 1.Canvas 提供了绘图方法,可以向底层的位图绘制基本图形.(我觉得这个解释很好,比解释成画布要好的多) 2.Paint 称为画笔或者刷子,Paint可以指定如何将基本图形绘制到位图上. 3.Bitmap 绘图的表面. Android绘图API支持透明度,渐变填充,圆角矩形和抗锯齿. 1.可以绘制的内容 Canvase类封装了用作绘图表面的位图,它还提供了draw*方法来实现设计. 2.最大限度的利用Paint Pain相当

Android界面编程——Android高级UI组件(三)

Android界面编程 Android高级UI组件 2.4.1适配器组件 适配器的作用 适配器充当适配器控件和该视图数据之间的桥梁.适配器提供访问的数据项,并负责产生数据组中的每个项的视图. 常用的适配器 BaseAdapter:抽象类,具有较高的灵活性. ArrayAdapter:最为简单,智能展示一行文字. SimpleAdapter:有较好的扩充性,可以自定义出各种效果. SimpleCursorAdapter:主要用于操作数据库. 常用的适配器控制 适配器控件扩展自ViewAdapter

android 高级 day01

一. 目标:独立完成Android客户端的开发 做项目,一般规模一般难度的   80% 1. 一般项目规模 15个页面左右 代码量:2~3万 2. 一般难度 稍微复杂的UI 常用的功能 有难度的功能:实时语音或视频通讯 高级职位,项目经理或架构师需要掌握的技能: 1. 精通主流手机平台下的高性能编程及性能调优 2. 熟悉设计模式 3. 有很强的解决,分析,调试技术问题的能力 二. Android项目开发流程和角色 流程:CMM 瀑布模型 大中型公司的人员配备 项目经理 1. 收集需求 售前 2.

如何学习android高级编程

学了android高级编程有前途吗?进入2010年之后,android的应用开发进入了一个爆炸式增长的状态,从去年的不到1万款应用程序增加到现在的9万,而且即将突破10万,这也从开发者这一方面展现了用户不断增多的现象.不过需要注意的是,虽然数值的增长速度很快,开发公司还得做好相关的审查工作,尽快提高 android电子市场整体的应用质量,改善应用的盈利环境. 学了android高级编程有前途吗?随着高配置android手机的上市,全3D手机游戏也将会在更多的手机上运行,而android 2.2版

Android高级编程笔记(四)深入探讨Activity(转)

在应用程序中至少包含一个用来处理应用程序的主UI功能的主界面屏幕.这个主界面一般由多个Fragment组成,并由一组次要Activity支持.要在屏幕之间切换,就必须要启动一个新的Activity.一般的Activity都占据了整个显示屏,但可以创建成半透明或二者浮动的Activity. 一.创建Activity 通过继承Activity类可以创建一个Activity窗口,基本框架如下: 1 public class MyActivity extends Activity { 2 @Overri

Android 高级 Jackson Marshalling(serialize)/Unmarshalling(deserialize)

本文内容 高级 Jackson Marshalling Serialize Only Fields that meet a Custom Criteria with Jackson Serialize Enums as JSON Objects JsonMappingException (No serializer found for class) Jackson – Custom Serializer 高级 Jackson Unmarshalling Unmarshall to Collect

剖析Framework面试 冲击Android高级职位

第1章 学习指南本章会告诉大家为什么应该学习这门课,课程有哪些特色,能给大家带来什么收获,还会讲到课程的整体内容安排,最后还会给出一些学习建议,让大家能更好地学习这门课. 第2章 系统服务相关面试问题本章重点讲解系统核心进程,以及一些关键的系统服务的启动原理和工作原理相关的面试内容. 第3章 应用进程相关面试问题本章主要讲解应用进程的启动,以及伴随进程启动过程中的一些重要机制的初始化原理,比如binder机制,Application,以及Context等方面的面试问题. 第4章 Activity