Android音频介绍
这个世界音频设备千变万化,Android也不可能为每种设备都提供支持。Android定义了一个框架,这个框架来适配底层的音频设备。该适配层的定义位于:
hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h
要想视频底层的音频设备必须要继承该文件中定义的AudioStreamOut,AudioStreamIn,AudioHardwareInterface等类,并实现createAudioHardware函数。
下面我们看一下Android创建音频设备的代码,代码位于:
frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp
该文件有如下代码:
AudioHardwareInterface * AudioHardwareInterface::create()
{
/*
*FIXME:This code needs to instantiate thecorrect audio device
*interface.For now-we use compile-timeswitches.
*/
AudioHardwareInterface*hw=0;
char value[PROPERTY_VALUE_MAX];
#ifdef GENERIC_AUDIO
hw=new AudioHardwareGeneric();
#else
//if running in emulation-use the emulatordriver
if(property_get("ro.kernel.qemu",value,0)){
LOGD("Running in emulation-usinggeneric audio driver");
hw=new AudioHardwareGeneric();
}
else{
LOGV("Creating Vendor Specific AudioHardware");
hw=createAudioHardware();
}
#endif
if(hw->initCheck()!=NO_ERROR){
LOGW("Using stubbed audio hardware.Nosound will be produced.");
delete hw;
hw=new AudioHardwareStub();
}
#ifdef WITH_A2DP
hw=new A2dpAudioInterface(hw);
#endif
#ifdef ENABLE_AUDIO_DUMP
//This code adds a record of buffers in afile to write calls made by AudioFlinger.
//It replaces the currentAudioHardwareInterface object by an intermediateone which
//will record buffers in a file(aftersending them to hardware)for testing purpose.
//This feature is enabled by definingsymbol ENABLE_AUDIO_DUMP.
//The output file is set withsetParameters("test_cmd_file_opening PCM dump
interface");
hw=new AudioDumpInterface(hw);//replaceinterface
#endif
return hw;
}
从代码中我们可以看出如果定义了GENERIC_AUDIO的宏,则会创建AudioHardwareGeneric,如果是模拟器的话,AudioHardwareGeneric会不能初始化,进而创建AudioHardwareStub。这两个类都是Audio设备的适配层,是Android默认提供的模拟器都是用AudioHardwareStub,不会有声音输出设备都是用AudioHardwareGeneric,因为默认GENERIC_AUDIO是设置的一般我们只关心AudioHardwareGeneric实现,谁会去给模拟器去调试声音呢,反正我没这个闲心。
首先说明一下这个音频适配层是Android自带的,可以保证你的音频设备正常运行,但是不能发挥设备的最佳性能。
通过后面的描述你将会了解AudioHardwareGeneric的定义位于:
frameworks/base/libs/audioflinger/AudioHardwareGeneric.cpp
查看源码你会发现这个适配层需要实现设备/dev/eac,并且该设备只输出44.1khz采样率的音频数据给/dev/eac设备,如果不是44.1khz的采样率的数据,AudioHardwareGeneric会经过Resample过程把它转换成44.1kHZ的音频数据,然后再输出给音频设备。44.1kHZ音频数据是最普遍的音频采样率,大部分Mp3都是以这个采样率压缩的,所以选择这个采样率做为默认采样率还是有一定的合理性的。
AudioHardwareGeneric是软件实现Resample过程是,效率会比较低。很多音频设备支持不同采样率的数据,可以理解成硬件实现Resample过程。通过上面的描述我们可以知道这个通用音频适配层只是让你的设备可以用而已,不能发挥设备的性能优势,如果你的设备对音频质量有更高的要求,必须要自己实现音频适配层。谷歌只能保证你的音频可以播放,但是不能保证效率(他也没有办法保证效率)。
所支持的音频格式
对于播放,Android支持各种各样的音频文件格式和编解码。对于录音的支持少一些。
以后我们学到录音部分将会讨论这点。
AAC:
高级音频编码(以及其扩展:HEAAC)编解码,.m4a,.3gp文件.AAC是一个流行的标准,IPOD和其他便携式媒体播放器都使用它。Android在MPEG4音频文件和3GP文件内(都是基于MPEG4格式)支持这种音频格式。最近AAC的附加规范HE AAC也被支持了。
MP3:
MPGE-1音频层3,.mp3文件。Android支持MP3,MP3可能是使用最广泛的音频编解码,这允许Android通过各种网站和音乐商店来使用大部分在线音频。
AMR:
自适应多速率编解码(AMR-NB,AMR-WB),.3gp,.amr文件。AMR音频编解码已经被标准化了,主要被3GPP(第三代合作伙伴项目)用于语音音频编解码。3GPP是一个为其合作伙伴创建规范的电信行业机构。换句话说,AMR编解码主要用于现代移动电话的语音呼叫程序,并且手机厂商和手机携带者普遍都支持这个格式。AMR这格式一般对语音编码很有用,但对更复杂的类型表现的不够好,比如音乐。
Ogg:
Ogg Vorbis,.ogg文件。Ogg Vorbis是个开源的,无专利费的音频编解码。其品质可媲美商业性的,需缴纳专利费的编解码比如MP3,AAC它由一群自愿者开发,当前由Xiph.Org基金会负责维护。
PCM:
脉冲编码调制通常被用在WAVE,WAV文件,.wav文件。PCM这技术主要用于音频在电脑和其他电子音频设备上的存储。它通常是个未压缩的音频文件,其数据代表随着时间流逝一段音频的振幅。“采样率”是多长时间一次一个振幅读取被存储起来。“位深度”是指多少位被用来代表一个单独的样本。一段16KHZ采样率,32位位深度的音频数据是指它包含每秒钟16000个的32位的数据用来表示音频振幅。采样率和位深度越高,数字化音频越精准。采样率和位深度也决定了音频文件的大小。Android在WAV文件内支持PCM音频数据。WAV是PC上的一个长期存在的标准音频格式。
通过Intent使用内建的音频播放器
正如使用摄像头,在一个应用程序里提供播放音频文件的能力,最容易的方法就是:使用内建的“音乐”程序的功能。这个程序有个用户熟悉的界面,能播放所有Android支持的格式,并且能通过一个intent,被触发去播放一个指定的文件。普通的android.content.Intent.ACTION_VIEW intent,其数据设置为一个音频文件的Uri,并指定其MIME类型,这样Android会自动选择一个合适的应用程序来播放。这个程序应该是内建的音乐播放程序,但用户可能被提供其他的选项,如果他/她安装了其他的音频播放软件。
1.Intent intent=newIntent(android.content.Intent.ACTION_VIEW);
2.intent.setDataAndType(audioFileUri,"audio/mp3");
3.startActivity(intent);
注解:MIME全称是MultipurposeInternet Mail Extension(s多用途互联网邮件扩展)。它起初专门用来帮助电子邮件客户端发送和接收附件。但它的使用范围从电子邮件极大地扩展到其他的通讯协议,包括HTTP,标准万维网服务。Android使用MIME类型来解析intent,并且用它来决定应该选择哪个应用程序来处理intent.
每个文件类型都有特定的(有时候不止一个)MIME类型。MIME类型通过至少由2部分组成,由斜杠分开的字符来指定。第一部分是更通用的类型,比如“audio”.第二部分是更具体的类型,比如"mpeg".一个通用的类型"audio"和一个更具体的类型"mpeg"将产生一个“audio/mpeg"MIME类型字符,这个MIME类型通常用于MP3文件。
Android音频实例分析
这里有个通过一个intent触发内建的音频播放程序的完整例子。
1.packagecom.apress.proandroidmedia.ch5.intentaudioplayer;
2.import java.io.File;
3.import android.app.Activity;
4.import android.content.Intent;
5.import android.net.Uri;
6.import android.os.Bundle;
7.import android.os.Environment;
8.import android.view.View;
9.importandroid.view.View.OnClickListener;
10.import android.widget.Button;
我们的activity在触发音频播放之前会一直监听一个Botton是否被按下。
1.public class AudioPlayer extendsActivity implements OnClickListener{
2.Button playButton;
3.@Override
4.public void onCreate(BundlesavedInstanceState){
5.super.onCreate(savedInstanceState);
6.setContentView(R.layout.main);
我们将content view设置为我们的XML后,我们能得到一个Button的引用,并将我们的activity(this)设为OnClickListener.
1.playButton=(Button)this.findViewById(R.id.Button01);
2.playButton.setOnClickListener(this);
3.}
当我们的Button被点击,OnClick方法会被调用。在这个方法里,我们用一个普通的android.content.Intent.ACTION_VIEW来构建intent,然后创建一个文件对象,这个对象是SD卡上已经存在的音频文件的索引。这种情况下,这个音频文件被手动放置到SD卡的“Music"目录下,这个目录通常放置和音乐相关的音频文件。
1.public void onClick(View v){
2.Intent intent=new Intent(android.content.Intent.ACTION_VIEW);
3.Filesdcard=Environment.getExternalStorageDirectory();
4.File audioFile=newFile(sdcard.getPath()+"/Music/goodmorningandroid.mp3");
接下来,我们设置intent的数据为来源于音频文件的Uri并将其类型设置为MIME类型,audio/mp3.最后传递我们的intent给startActivity来触发内建的音乐播放程序。
1.intent.setDataAndType(Uri.fromFile(audioFile),"audio/mp3");
2.startActivity(intent);
3.}
下面是一个简单的XML布局文件,其中Button的文本为"Play Audio",前面所述的
activity会用到这个Button.
1.<?xmlversion="1.0"encoding="utf-8"?>
2.<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
3.android:orientation="vertical"
4.android:layout_width="fill_parent"
5.android:layout_height="fill_parent"
6.>
7.<Button android:text="Play Audio"android:id="@+id/Button01"
8.android:layout_width="wrap_content"android:layout_height="wrap_content"
></Button>
9.</LinearLayout>
Android支持的视频格式
先简要说明下Android支持的视频格式,如下:

由于硬件的不同,不同的手机支持的编解码方式有些不一样,在T-Mobile G1实际设备中增加了对WMA,WMV,H.264 AVC格式解码的支持。Android支持的音/视频编码方式仅包括:AMR-NB,H.263,输出的视频格式也只*.3gp或者*.mp4,这点在以后的开发中需要注意。对Android的编解码有了一些了解后,我们再去研究下如何在Android上来播放/录制视频,打开Android SDK中关于媒体方面的说明,摘要其主要部分如下:

首先注意的就是:MediaPlayer,MediaRecoder,主要是用来播放视频与录制视频的类。
来自:http://www.linuxidc.com/Linux/2011-09/42419.htm
Android音频介绍的更多相关文章
- Android音频开发之——如何播放一帧音频
本文重点关注如何在Android平台上播放一帧音频数据.阅读本文之前,建议先读一下<Android音频开发(1):基础知识>,因为音频开发过程中,经常要涉及到这些基础知识,掌握了这些重要的 ...
- Android音频系统之音频框架
1.1 音频框架 转载请注明,From LXS, http://blog.csdn.net/uiop78uiop78/article/details/8796492 Android的音频系统在很长一段 ...
- Android音频焦点详解(上)
转载请注明出处:http://www.cnblogs.com/landptf/p/6384112.html 2017年开年第一篇博客,很早就想总结一下Android音频的相关知识.今天我们先来看一下音 ...
- Android音频处理——通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能
Android音频处理--通过AudioRecord去保存PCM文件进行录制,播放,停止,删除功能 音频这方面很博大精深,我这里肯定讲不了什么高级的东西,最多也只是一些基础类知识,首先,我们要介绍一下 ...
- Android bluetooth介绍(一):基本概念及硬件接口
关键词:蓝牙硬件接口 UART PCM blueZ 版本号:基于android4.2之前版本号 bluez内核:linux/linux3.08系统:android/android4.1.3.4作者 ...
- Android音频开发(1):基础知识
Android音频开发(1):基础知识 导读 人的说话频率基本上为300Hz~3400Hz,但是人耳朵听觉频率基本上为20Hz~20000Hz. 对于人类的语音信号而言,实际处理一般经过以下步骤: 人 ...
- Android音频录制MediaRecorder之简易的录音软件实现代码(转)
原文:http://www.jb51.net/article/46182.htm Android音频录制MediaRecorder之简易的录音软件实现代码 这篇文章主要介绍了Android音频录制Me ...
- android Animation介绍
Animation介绍: 在Android SDK介绍了2种Animation模式: 1. Tween Animation:间动画,通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果,即 ...
- android AsyncTask介绍(转)
android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...
随机推荐
- return和exit函数的区别
在上Linux课的时候,老师提到一句,调用vfork产生的子进程就是为了使用exec族函数来执行其他的代码逻辑. 在子进程退出的时候有两种方式,exit和exec族函数,不能使用return,为什么不 ...
- 基本套接字编程(3) -- select篇
1. I/O复用 我们学习了I/o复用的基本知识,了解到目前支持I/O复用的系统调用有select.pselect.poll.epoll.而epoll技术以其独特的优势被越来越多的应用到各大企业服务器 ...
- hadoop 集群部署ganglia 监控服务与nagios 报警服务
1. 部署ganglia 服务 ganglia 涉及到的组件: 数据监测节点(gmond):这个部件装在需要监测的节点上,用于收集本节点的运行情况,并将这些统计信息传送到gmetad, ...
- 【kd-tree】bzoj4154 [Ipsc2015]Generating Synergy
区间修改的kd-tree,打标记,下传. 每次询问的时候,从询问点向上找到根,然后依次下传下来,再回答询问. #include<cstdio> #include<algorithm& ...
- css多行文本省略号
适用于内核为webkit的浏览器: display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflo ...
- javaweb 乱码---汉字存入mysql数据库中变成乱码
今天郁闷了一天,java程序在向mysql插入数据前不是乱码,数据库安装时也选了编码为utf8(和我程序的编码格式一致).可是插入数据就变成乱码,相当郁闷. 原因:mysql的配置文件中的编码并没有改 ...
- MongoDB中的高级查询(二)
$mod取模运算 查询index对5取模运算等于1的数据. $not $not是元条件句,即可以用在任何其他条件之上.查询index对5取模运算不等于1的数据. $exists判断字段是否存在 查询出 ...
- Windows 8.0上Eclipse 4.4.0 配置CentOS 6.5 上的Hadoop2.2.0开发环境
原文地址:http://www.linuxidc.com/Linux/2014-11/109200.htm 图文详解Windows 8.0上Eclipse 4.4.0 配置CentOS 6.5 上的H ...
- 一致性Hash算法在Redis分布式中的使用
由于redis是单点,但是项目中不可避免的会使用多台Redis缓存服务器,那么怎么把缓存的Key均匀的映射到多台Redis服务器上,且随着缓存服务器的增加或减少时做到最小化的减少缓存Key的命中率呢? ...
- GCC选项
-g: Debugging Option. 提供给GDB的debugging信息的选项: -fno-omit-frame-pointer: Optimization Option: -Wstrict- ...