当前位置:首页 » 安卓系统 » android音频时间

android音频时间

发布时间: 2024-09-22 17:53:51

⑴ Android Audio简述

audio是Android系统是比较重要的一个模块,本人也涉足时间不是很长,经验还是很少的,只是把自己在工作中所遇到的问题记录。

Audio 即音频, 也就是控制着手机中的各种声音的输出,比如说,音乐的播放,音量大小,按键音,插入耳机,声音从耳机播放,连接蓝牙,声音从蓝牙耳机中播放。还有一些HiFi播放, offload播放,高清播放。

常见的问题如下:

POP音,漏音,声音卡顿,耳机无法识别,还有一些音频通路等问题,还有一些稳定性的问题如:ANR、CRASH、tombstone。还有一些安全漏洞的问题(主要是核心库那里)。

回归正题

-------华丽的分割线-------

audio分为  应用层,fwk层,native fwk, hal层。

常见的文件有MediaPlayer.java、 AudioSystem.java、 AudioService.java、AudioManager.java 文件路径(framework/base/media)

AudioFlinger.cpp、AudioTrack.cpp、 AudioPolicyManager.cpp、 Threads.cpp、Tracks.cpp、 Engine.cpp、 Audiosystem.cpp  文件路径(framework/av)

audio_hw.c  文件路径(vendor/)

java文件我在这里就不过多的说了,没啥好讲的,主要说一下c++文件吧。

AudioFlinger 是音频策略的执行者, AudioPolicyManager是制作音频策略的,AudioTrack是负责播放从上层传过来的PCM数据,简单的说就是负责播放的。 

audio_hw 是每个HAL层的文件,每个手机厂商自己定制的文件。当然Google也有。

一般呢,我们处理音频相关的问题呢,有一些特定的套路,需要AP 侧的log, 有时还需要kernel 的log,  当然最主要的是需要音频数据。也就是出现问题时,的声音数据,让我们可以快速的定位出现问题的位置。

简单的说下播放一首歌曲的流程:(以Android O 为例)

上层创建一个MediaPlayer对象,然后调用NuPlayer框架(播放器),NuPlayer先将当前歌曲的文件信息读取,采样率,比特率,等之类的东西。然后开始调用audio decoder (音频解码器)  将解码出来的PCM数据传给AudioTrack,  Audiotrack 会创建一个Track,(每一个播放都会创建一个属于自己的track,不用了就销毁,最多可以同时创建32个),经过AudioFlinger重采样之后,送到HAL层,HAL层在经过一些混音,降噪之类的处理,将声音送到Codec,然后送给硬件输出,进行播放。

这个是一个大概的播放流程,如果我们在播放过程中遇到了一些问题,比如说是fwk层的问题,我们就在AudioTrack与AudioFlinger之间寻问题的原因。

比如说,播放无声,我们需要看AudioPolicyManager中的一些策略是不是将当前的track给mute了。或者是一些其他的原因等。

这里只是简单的介绍下Audio,Audio算是一个较为复杂的模块,还需要好好的研究。

⑵ Android绯荤粺涓镄勯煶瑙嗛戞敮鎸佹湁鍝浜


Android绯荤粺涓瀹屽杽镄勯煶瑙嗛戞敮鎸
镊浠峣ndroid绯荤粺闂涓栦互𨱒ワ纴瀹冨凡缁忔垚涓轰简绉诲姩璁惧囬嗗烟链涓烘垚锷熺殑镎崭綔绯荤粺涔嬩竴銆傝ョ郴缁熷叿链夊己澶х殑澶氩獟浣揿勭悊锷熻兘锛屽备赴瀵岀殑阔抽戝拰瑙嗛戞敮鎸侊纴鍙璁╁紑鍙戣呰交𨱒惧垱寤哄嚭锷熻兘涓板瘜镄勯煶瑙嗛戝簲鐢ㄧ▼搴忋傛湰鏂囧皢鎺㈣ˋndroid绯荤粺涓浣跨敤镄勫父瑙侀煶瑙嗛戞嗘灦鍜孉PI鎺ュ彛銆
1.OpenMAX缂栬В镰佸櫒锛
OpenMAX缂栬В镰佸櫒鏄涓绉嶅彲鐢ㄤ簬Android璁惧囦腑镄勭‖浠跺姞阃熸妧链銆傝ユ妧链鍙浠ュ府锷╁湪璁惧囦笂鎾鏀鹃珮娓呮垨娴佸獟浣撹嗛戞椂鍑忓皯濯掍綋鏂囦欢镄勫崰鐢ㄧ┖闂淬备綔涓轰竴绉嶅紑鏀炬爣鍑嗭纴OpenMAX鏀鎸佷粠搴旂敤绋嫔簭鍒扮‖浠剁殑鍏ㄩ溃瑙e喅鏂规堛傚湪Android绯荤粺涓锛孙penMAX鏄鐢辩‖浠跺巶鍟嗘彁渚涙敮鎸侊纴骞朵笖瀹冨厑璁镐笉钖岀殑纭浠跺拰杞浠剁粍钖埚簱鐩镐簰鍗忎綔銆
2.Medistore锛
Mediastore鏄疉ndroid绯荤粺镄勪竴涓澶氩獟浣扑腑闂村眰銆傚畠浣跨敤鎴峰彲浠ュ揩阃熸柟渚垮湴銮峰彇銆佸瓨鍌ㄥ拰澶勭悊绉诲姩璁惧囩殑澶氩獟浣撴暟鎹銆傚畠鏀鎸佽稿氭牸寮忓侻P3銆丳NG绛夛纴钥屼笖瀹冨彲浠ラ氲繃URI镄勬柟寮忚块梾鍒扮郴缁熺殑澶氩獟浣撴暟鎹銆傚逛簬寮鍙戜汉锻樻潵璇达纴Mediastore杩樻彁渚涗简璁稿氭帴鍙e拰绫伙纴鍙甯锷╀粬浠绠$悊澶氩獟浣撴暟鎹銆
3.MediaPlayer锛
MediaPlayer鏄疉ndroid绯荤粺涓链甯哥敤镄勫氩獟浣撴挱鏀惧櫒銆傚畠鑳藉熶互娴佺殑鏂瑰纺澶勭悊澶氱嶉煶棰戝拰瑙嗛戞牸寮忥纴濡侻P3銆乄AV绛夐煶棰戞牸寮忥纴浠ュ强MP4銆丠.264绛夎嗛戞牸寮忋侻ediaPlayer杩桦彲浠ヤ笌SurfaceView鍗忓悓宸ヤ綔锛屼互渚挎洿锷犵伒娲诲湴鎺у埗瑙嗛戠殑鎾鏀俱傚湪寮鍙戣繃绋嬩腑锛屽紑鍙戜汉锻桦彲浠ヤ娇鐢∕ediaPlayer绫荤殑璁稿氭柟娉曞拰灞炴ф潵鎺у埗阔抽戝拰瑙嗛戠殑鎾鏀俱佹殏锅滃拰锅沧㈢瓑锷熻兘銆
4.AudioTrack锛
AudioTrack鏄涓涓鍦ˋndroid绯荤粺涓婂勭悊阔抽戞暟鎹镄勭被銆傚畠鏀鎸佷互鏁版嵁缂揿瓨鏂瑰纺鎾鏀鹃煶棰戣В镰佹暟鎹锛屽苟鍏佽稿紑鍙戜汉锻橀氲繃璁稿氭柟娉曞拰灞炴ф潵鎺у埗阔抽戞挱鏀俱侫udioTrack链甯哥敤浜庨煶棰戞祦浼犺緭鍜岄煶棰戞枃浠舵挱鏀撅纴渚嫔侻P3鎴朩AV鏂囦欢銆
镐讳箣锛孉ndroid绯荤粺镄勯煶瑙嗛戝姛鑳藉湪绉诲姩璁惧囦腑宸茬粡寰楀埌浜嗗箍娉涚殑搴旂敤銆傞氲繃瀵逛笉钖岀殑API鎺ュ彛鍜屾嗘灦镄勪简瑙o纴寮鍙戜汉锻桦彲浠ヨ交𨱒惧垱寤洪珮璐ㄩ噺镄勯煶瑙嗛戝簲鐢ㄧ▼搴忋

⑶ Android音频播放

最近需要在Android的客户端中使用PCM声音播放和录制,简单学习了一下。有不正确的地方还请指出。

首先有几个概念需要了解一下:采样频率、声道数、采样位数。

采样频率一般是sample rate, 代表的是数字化音频时每秒采样的次数。常见的有44.1KHz(CD品质)、48KHz等。

这个很好理解,单声道Mono就是声音从一个方向传出来;双声道Stereo也叫立体声,声音是从两个方向传来。通常的流行音乐中,仔细听能发现每个声道可能侧重不同的乐曲声部,比如左声道吉他,右声道钢琴,人声似乎两个声道都有,听起来就像站在中间一样。(这里没有考证,随便举例)

每一个采样都是一个数据点,采样位数是指这个数据点使用了几位来记录。AudioTrack类只支持8位和16位的PCM音频。8位就是2的8次方,即256个值;而16位则是2的16次方,有65536个值。

这个在音频的编解码中还是比较常用的。在PCM格式中,1秒钟音频的数据大小是SampleRate×Channel×Bit/8,单位是byte字节。由于PCM本身没有音频帧的概念,所以通过这个公式就能计算出任意时长音频的大小,或者得到任意大小音频的时长。如果规定1个音频帧是“每个声道256个采样”,双声道下就是512个采样,那么1帧的数据量就是256×Channel×Bit/8,同理可以推断出1秒钟有多少音频帧等等。音频帧的概念在各种编解码中各有不同,但计算公式大同小异,这里不展开。

Android中音频的播放使用的是AudioTrack类,具体用法非常简单。
首先设置buffer大小。AudioTrack播放时需要先写入buffer,如果这个buffer没有写满,那么这部分是不会播放的。所以buffer不能设置太小,这样会导致播放不连贯;而buffer也不能设置太小,这样不间断写入会消耗许多CPU资源。AudioTrack自带了getMinBufferSize方法可以给出一个最小buffer,一般用这个值就可以。getMinBufferSize方法三个参数分别是sample rate、channel和bit。

设置完buffer size就可以实例化一个AudioTrack。其中第一个参数streamType是指不同的音频流类型,包括STREAM_MUSIC、STREAM_ALARM、STREAM_VOICE_CALL、STREAM_RING等,是Android对不同音频的分类。中间三个参数很好理解,第四个是buffer size,刚刚计算出来了。最后一个参数mode有两种:MODE_STREAM和MODE_STATIC。前者是以流形式播放,后者则是一次性全部写入然后播放。

调用实例的play()方法就可以开始播放了。不过播放得要有数据吧?要填写数据就要用到write()方法。write方法中第一个参数是一个byte[]类型,是要写入的数据源,可以是从文件流中读取出来的;第二个参数offset是初始位移,即从source的哪个位置开始;第三个参数则是输入长度。

当write方法写满一个AudioTrack的buffer时,就会有声音播放出来了。
当播放完成后记得要把AudioTrack停止并释放。

⑷ Android的MediaRecorder怎么显示音频记录的时间期限

解决卜困枯方法 :
在记录开始的 System.currentTimeMillis(); 方法中设置 start_time 方法。
然后使用 Runnable 可型洞以执行一个循环,直到停止记录。

final Handler handler = new Handler();
Runnable update_runnable = new Runnable() {
public void run() {
updateTextView();
}
};
Then with the updateTextView() you'd do something like this:

long ration = (int) ((System.currentTimeMillis() - start_time) / 1000);
// ... set TextView with ration value
handler.postDelayed(update_runnable, 1000); /尺羡

热点内容
linux工程师证书 发布:2024-09-22 20:07:37 浏览:412
如何快速调整安卓手机桌面 发布:2024-09-22 20:06:26 浏览:683
GDC服务器怎么做IP 发布:2024-09-22 19:44:54 浏览:466
c语言longlongprintf 发布:2024-09-22 19:16:48 浏览:13
oracleraclinux 发布:2024-09-22 19:03:54 浏览:51
我的世界服务器v指令是什么 发布:2024-09-22 19:03:52 浏览:431
UE编译器网盘下载 发布:2024-09-22 19:01:48 浏览:827
linux下远程 发布:2024-09-22 18:56:10 浏览:234
python类单例 发布:2024-09-22 18:45:52 浏览:278
打游戏要看手机的什么配置 发布:2024-09-22 18:40:06 浏览:974