Android 4.4 Kitkat 音频实现及简要分析

时间:2022-12-25 20:19:10

版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/jingxia2008/article/details/26701899

在 Android 4.4 上实现录放音

背景

Android 自 ICS 開始,音频系统就有了非常大的变化,先是抛弃了 alsalib。然后是採用了 AIO。各级框架上,都有了自己的特色,与 Linux 的音频应用渐行渐远,形成了自己独特的音频管理和音频配置功能。

总的来说改进还是非常大,至少在用户体验上已经大大的超越了之前的版本号。

我们就从 4.4 的音频实现上来分析当中的一些变化和实现机制。

要求

首先是硬件功能正常,这个不表。 Linux 支持 alsa 驱动。生成 alsa 子系统。最好是能够在 buildroot 等其它文件系统上事先測试音频的播放和录制。

HAL

音频的 HAL 简单实现,參考 device/asus/grouper/audio , 假设没有太复杂的音频配置,基本上能够在这个代码基础上略微改动,主要是一些播放和录制的參数。这个 HAL 已经实现了通用的接口,而且调用的也是标准的 tinyalsa 的接口,移植性非常高。我们这里使用的 wm8904,功能不多。直接使用就可以。

Android 的配置

主要是4个文件 audio_policy.conf  media_profiles.xml media_codecs.xml mixer_paths.xml 參考 asus ,不必大改。基本照抄,全然能够直接使用,开源万岁。
做好文件系统。这个时候系统应该就不使用 default 的 stub 音频 HAL , 而是用我们加入的 audio HAL 了。 可是是否能发声,这个多半还是不能。

调试

audio 系统调用了  libtinyalsa libaudioutils libaudioroute 几个底层库。

这几个移植了一些通用的 alsa 设备打开配置功能,可是详细平台却并不一定都能正常运行,主要是这些库实现都非常easy,没有考虑全面,你的硬件细节可能刚好被他们忽略了。相同以我们的 wm8904 来说,我们不支持 time stamp ,可是 tinyalsa 是默认打开的必须将其关掉。

    disable tstamp for wm8904.

    Change-Id: Ia22aa6ed39ede6214657487344d0488be93e5544

diff --git a/pcm.c b/pcm.c
index 4501777..94cf6ee 100644
--- a/pcm.c
+++ b/pcm.c
@@ -691,7 +691,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, memset(&sparams, 0, sizeof(sparams));
- sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;
+ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
sparams.period_step = 1; if (!config->start_threshold) {

详细哪些參数不正确,或者不合适,就须要 Android 驱动project师依据硬件设计和芯片手冊,逐个查证。配置到一个音频系统工作的最佳状态。

那么用户体验才干最好。

Android 音频系统分析

下面分析基于 4.4.2

audio HAL

tinyalsa 与 audioroute

Android 音频系统基于 Linux 的 ALSA 驱动, tinyalsa 在 alsa 的驱动基础上封装音频接口。提供给 audio HAL。 audio HAL 提供接口给 Android audioflinger 等 framework。
HAL 须要实现 audio 硬件的打开与关闭(这里是 android 觉得的硬件)。
static inline int audio_hw_device_open(const struct hw_module_t* module,
struct audio_hw_device** device)
{
return module->methods->open(module, AUDIO_HARDWARE_INTERFACE,
(struct hw_device_t**)device);
} static inline int audio_hw_device_close(struct audio_hw_device* device)
{
return device->common.close(&device->common);
}

须要实现 in 和 out 的 数据流

struct audio_stream_out   struct audio_stream_in 
in 主要有 read 方法用于读取音频数据。   out 主要有 write 方法,写入数据到设备,分别实现录音和放音。
详见: hardware/libhardware/include/hardware/audio.h
当中的方法又是调用的 tinyalsa 的接口,关于 pcm 的操作:
/* Open and close a stream */
struct pcm *pcm_open(unsigned int card, unsigned int device,
unsigned int flags, struct pcm_config *config);
int pcm_close(struct pcm *pcm);
int pcm_is_ready(struct pcm *pcm); /* Obtain the parameters for a PCM */
struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
unsigned int flags);
void pcm_params_free(struct pcm_params *pcm_params);
unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
enum pcm_param param);
unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
enum pcm_param param); /* Set and get config */
int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
int pcm_set_config(struct pcm *pcm, struct pcm_config *config); /* Returns a human readable reason for the last error */
const char *pcm_get_error(struct pcm *pcm); /* Returns the sample size in bits for a PCM format.
* As with ALSA formats, this is the storage size for the format, whereas the
* format represents the number of significant bits. For example,
* PCM_FORMAT_S24_LE uses 32 bits of storage.
*/
unsigned int pcm_format_to_bits(enum pcm_format format); /* Returns the buffer size (int frames) that should be used for pcm_write. */
unsigned int pcm_get_buffer_size(struct pcm *pcm);
unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames);
unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes); /* Returns the pcm latency in ms */
unsigned int pcm_get_latency(struct pcm *pcm); /* Returns available frames in pcm buffer and corresponding time stamp.
* The clock is CLOCK_MONOTONIC if flag PCM_MONOTONIC was specified in pcm_open,
* otherwise the clock is CLOCK_REALTIME.
* For an input stream, frames available are frames ready for the
* application to read.
* For an output stream, frames available are the number of empty frames available
* for the application to write.
*/
int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
struct timespec *tstamp); /* Write data to the fifo.
* Will start playback on the first write or on a write that
* occurs after a fifo underrun.
*/
int pcm_write(struct pcm *pcm, const void *data, unsigned int count);
int pcm_read(struct pcm *pcm, void *data, unsigned int count); /*
* mmap() support.
*/
int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count);
int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count);
int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
unsigned int *frames);
int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames); /* Start and stop a PCM channel that doesn't transfer data */
int pcm_start(struct pcm *pcm);
int pcm_stop(struct pcm *pcm); /* Interrupt driven API */
int pcm_wait(struct pcm *pcm, int timeout); /* Change avail_min after the stream has been opened with no need to stop the stream.
* Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags
*/
int pcm_set_avail_min(struct pcm *pcm, int avail_min);
值得一提的是 HAL 如今不包括 route 的操作, audio route 交给了 libaudioroute.so , 它也是调用 tinyalsa 的接口,并包括一个 xml 解析器。解析 mixer_paths.xml 里面的 route 配置数据。这样系统就能够对 alsa 的 pcm 和 mixer 进行操作了,理论上应该能够放音了。使用 tinyalsa 提供的工具能够进行測试,当然无法測试 HAL 的接口。
tinycap      tinymix      tinypcminfo  tinyplay
tinyplay 能够播放 wav 格式的纯音频数据。

 tinymix 能够查看和配置音频路径:

root@sama5d3:/ # tinymix
Mixer name: 'wm8904 @ SAMA5D3EK'
Number of controls: 41
ctl type num name value
0 INT 1 EQ1 Volume 12
1 INT 1 EQ2 Volume 12
2 INT 1 EQ3 Volume 12
3 INT 1 EQ4 Volume 12
4 INT 1 EQ5 Volume 12
5 INT 2 Digital Capture Volume 96 96
6 ENUM 1 Left Caputure Mode Single-Ended
7 ENUM 1 Right Capture Mode Single-Ended
8 INT 2 Capture Volume 5 5
9 BOOL 2 Capture Switch Off Off
10 BOOL 1 High Pass Filter Switch On
11 ENUM 1 High Pass Filter Mode Hi-fi
12 BOOL 1 ADC 128x OSR Switch On
13 INT 1 Digital Playback Boost Volume 0
14 INT 2 Digital Playback Volume 96 96
15 INT 2 Headphone Volume 45 45
16 BOOL 2 Headphone Switch On On
17 BOOL 2 Headphone ZC Switch On On
18 INT 2 Line Output Volume 57 57
19 BOOL 2 Line Output Switch On On
20 BOOL 2 Line Output ZC Switch On On
21 BOOL 1 EQ Switch Off
22 BOOL 1 DRC Switch Off
23 ENUM 1 DRC Path ADC
24 BOOL 1 DAC OSRx2 Switch Off
25 BOOL 1 DAC Deemphasis Switch Off
26 INT 2 Digital Sidetone Volume 0 0
27 ENUM 1 LINER Mux DAC
28 ENUM 1 LINEL Mux DAC
29 ENUM 1 HPR Mux DAC
30 ENUM 1 HPL Mux DAC
31 ENUM 1 Right Sidetone None
32 ENUM 1 Left Sidetone None
33 ENUM 1 DACR Mux Right
34 ENUM 1 DACL Mux Left
35 ENUM 1 AIFOUTR Mux Right
36 ENUM 1 AIFOUTL Mux Left
37 ENUM 1 Right Capture Inverting Mux IN1R
38 ENUM 1 Right Capture Mux IN2R
39 ENUM 1 Left Capture Inverting Mux IN1L
40 ENUM 1 Left Capture Mux IN2L

audioflinger

audioflinger 是 audio 音频server。它会载入 audio hal ,并处理 audio 应用发出音频请求。这个分析的有非常多,參考下面:

Android 4.4 Kitkat 音频实现及简要分析的更多相关文章

  1. Android 关于 OnScrollListener 事件顺序次数的简要分析

    在 Android 的 OnScrollListener 整个事件我主要分析下他的执行顺序: 实现滚动事件的监听接口 new AbsListView.OnScrollListener(){ @Over ...

  2. Android 4.4 KitKat 新特性

    New in Android 4.4 KitKat 本文是一个概览,关于KitKat,也即Android4.4的新东西,先是功能型的,之后是设计上的. 很多特性本文并没有提到,很多提到的特性也只是简短 ...

  3. [转]Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划

    转自:Android系统Surface机制的SurfaceFlinger服务简要介绍和学习计划 前面我们从Android应用程序与SurfaceFlinger服务的关系出发,从侧面简单学习了Surfa ...

  4. Android 4.4 KitKat, the browser and the Chrome WebView

    Having V8 as the JavaScript engine for the new web view, the JavaScript performance if much better, ...

  5. 让你的短信应用迎接Android 4.4(KitKat)

    原文地址:Getting Your SMS Apps Ready for KitKat 发送和接收短信是手机最基本的功能,很多的开发者也开发了很多成功的应用来增强Android这一方面的体验.你们当中 ...

  6. Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 10

    今天编译一个project,我设置为api 14,可是编译报错: Using 1.7 requires compiling with Android 4.4 (KitKat); currently u ...

  7. Android 4.4(KitKat)中VSync信号的虚拟化

    原文地址:http://blog.csdn.net/jinzhuojun/article/details/17293325 Android 4.1(Jelly Bean)引入了Vsync(Vertic ...

  8. Android应用程序的Activity启动过程简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...

  9. Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程

    本文来自http://blog.csdn.net/yihongyuelan 转载请务必注明出处 本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. ...

随机推荐

  1. spring spring data jpa save操作事务

    整合spring spring data jpa的时候,在save方法上加了@Transactional注解.此时调用springdatajpa save方法并不会真的把数据提交给数据库,而是缓存起来 ...

  2. Nexus3.0.0+Maven的使用(一)

    1.Nexus介绍 Nexus是一个强大的Maven仓库管理器,它极大地简化了自己内部仓库的维护和外部仓库的访问.利用Nexus你可以只在一个地方就能够完全控制访问 和部署在你所维护仓库中的每个Art ...

  3. 【CodeVS 3160】最长公共子串

    http://codevs.cn/problem/3160/ 看了好久的后缀自动机_(:з」∠)_ 对A串建立SAM,用B串去匹配A串SAM,如果在当前节点走不下去,就跳到当前节点的parent(类似 ...

  4. $.ajax所犯的错误。success后面不执行

    $.ajax({ type: 'post', url: '../AshxHandler/HandlerAddPhoto.ashx', data: { clientPath: photoName }, ...

  5. Oracle的SOME,ANY和ALL操作

    平时很少用的这几个操作,今天遇到了.于是又看了一下文档. SOME和ANY一样,是比较宽松的,类似于OR.满足其中任何一个都可以. ALL要求严格一些,类似于AND,必须全部满足才可以. 不能单独使用 ...

  6. directX视频播放------手动连接

    IGraphBuilder *pigb = NULL; IMediaControl *pimc = NULL; IMediaEventEx *pimex = NULL; IVideoWindow *p ...

  7. linux 中数据库的常用操作

    1-连接数据库: mysql -h localhost -u jiangbiao -p xxxxx@xxx:~$ mysql -h localhost -u jiangbiao -p Enter pa ...

  8. jQuery 查找属性

    jQuery 查找属性 示例: <div xsk='123' > <div xsk='456' > // 具有xsk属性的所有标签 $('[xsk]') // xsk属性等于1 ...

  9. 阿里云centos5升级yum源为6

    升级后出现Errno -3] Error performing checksum 需要安装 python-hashlib Python 2.4 安装 hashlib 2012年11月13日 14:29 ...

  10. 一款易搭建,运行快的Git服务器:Gitea安装教程

    说明:Gitea是从Gogs发展而来,同样的拥有极易安装,运行快速的特点,而且更新比Gogs频繁很多,维护的人也多,个人认为Gitea还是更好一些的,这里就说下安装方法. 截图 简介 Gitea是一个 ...