Android下音频tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)
转载于:http://blog.csdn.net/radianceblau/article/details/64125411
audio代码比较复杂,除了音频参数,我们平时客制化的地方不多。所以没有太深入了解。
建议先抽空看看如下代码:
kernel,Linux alsa 架构:
kernel-3.10/sound/soc/mediatek/
kernel-3.10/Documentation/sound/alsa/soc/
Android 上层alsa接口
external/tinyalsa/
hal:
vendor/mediatek/proprietary/platform/common/hardware/audio/
vendor/mediatek/proprietary/platform/mt6735/hardware/audio/
andorid audio flinger:
frameworks/av/services/audioflinger/
tinyalsa位于Android源码的external/tinyalsa位置。
关于tinyalsa,tinyalsa是Google在Android 4.0之后推的基于alsa内核的用户层音频接口。在Android 4.0之前还一直是使用这alsa-lib接口。Google之所以推出tinyalsa,我认为有可能是因为alsa使用了GPL许可证的缘故,也有可能是因为alsa-lib的库过于复杂繁琐大部分功能在Android平台没有实际实用意义却依然占用屈指可数的内存空间。
/* 对pcm设备节点的操作 */
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);
/* 获取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);
/* 配置pcm设备capture和playback的规格 */
int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
int pcm_set_config(struct pcm *pcm, struct pcm_config *config);
/* 返回调用tinyalsa最后的错误信息 */
const char *pcm_get_error(struct pcm *pcm);
/* 设置pcm设备采集和播放的位数,位数越高越接近真实声音 */
unsigned int pcm_format_to_bits(enum pcm_format format);
/* pcm设备的内置缓冲之间大小、帧数、时间的转换 */
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);
unsigned int pcm_get_latency(struct pcm *pcm); // in ms
/* 返回下一帧的有效帧指针和该帧时间戳,时间戳有CLOCK_MONOTONIC和CLOCK_REALTIME可选,里面使用的是CLOCK_REALTIME */
/* 我认为应该需要两个时间戳,一个用于播放的时间戳(CLOCK_MONOTONIC)不受系统时间的影响,一个用于记录当前音频采集的时间戳(CLOCK_REALTIME) */
int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, struct timespec *tstamp);
/* 通过FIFO把数据写入硬件用于playback或者从硬件中读取capture数据 */
int pcm_write(struct pcm *pcm, const void *data, unsigned int count);
int pcm_read(struct pcm *pcm, void *data, unsigned int count);
/* 这是一个可选的和hardware通信的方式。 */
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);
int pcm_start(struct pcm *pcm);
int pcm_stop(struct pcm *pcm);
int pcm_wait(struct pcm *pcm, int timeout);
int pcm_set_avail_min(struct pcm *pcm, int avail_min);
/* 对mixer设备的操作 */
struct mixer *mixer_open(unsigned int card);
void mixer_close(struct mixer *mixer);
/* 获取mixer设备信息name */
const char *mixer_get_name(struct mixer *mixer);
/* 获取mixer设备的控制句柄 struct mixer_ctl */
unsigned int mixer_get_num_ctls(struct mixer *mixer);
struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id);
struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name);
/* 取mixer设备的控制信息 */
const char *mixer_ctl_get_name(struct mixer_ctl *ctl);
enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl);
const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl);
unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl);
unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl);
const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl, unsigned int enum_id);
/* Some sound cards update their controls due to external events,
* such as HDMI EDID byte data changing when an HDMI cable is
* connected. This API allows the count of elements to be updated.
*/
void mixer_ctl_update(struct mixer_ctl *ctl);
/* 设置和获取可控制的信息,方式有比例、数组、范围、固定值 */
/* id通过mixer_get_num_ctls获得 */
int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id);
int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent);
int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id);
int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count);
int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value);
int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count);
int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string);
int mixer_ctl_get_range_min(struct mixer_ctl *ctl);
int mixer_ctl_get_range_max(struct mixer_ctl *ctl);
// 原始状态
root@pone:/data/local/tmp # tinymix -D 1
Mixer name: 'mixer_name_xx'
Number of controls: 2
ctl type num name value
0 BOOL 1 Mic Capture Switch Off
1 INT 1 Mic Capture Volume 256
// 详细信息
root@pone:/data/local/tmp # tinymix -D 1 0
Mic Capture Switch: Off
root@pone:/data/local/tmp # tinymix -D 1 1
Mic Capture Volume: 256 (range 0->256)
// 设置
root@pone:/data/local/tmp # tinymix -D 1 0 1
root@pone:/data/local/tmp # tinymix -D 1 1 250
// 修改后的状态
root@pone:/data/local/tmp # tinymix -D 1
Mixer name: 'mixer_name_xx'
Number of controls: 2
ctl type num name value
0 BOOL 1 Mic Capture Switch On
1 INT 1 Mic Capture Volume 250
目前Linux中主流的音频体系结构是ALSA(Advanced Linux Sound Architecture),ALSA在内核驱动层提供了alsa-driver,在应用层提供了alsa-lib,应用程序只需要调用alsa-lib提供的API就可以完成对底层硬件的操作。说的这么好,但是Android中没有使用标准的ALSA,而是一个ALSA的简化版叫做tinyalsa。Android中使用tinyalsa控制管理所有模式的音频通路,我们也可以使用tinyalsa提供的工具进行查看、调试。
编译tinyalsa后生成四个小工具:
- tinymix
- tinyplay
- tinycap
- tinypcminfo
编译命令:
- mmm external/tinyalsa/
下面依次演示一下四个小工具的使用:(以下使用联芯科技的LC1860平台配合LC1160电源+音频芯片,截图及演示效果均来自M7301P5测试机)
1, tinypcminfo
tinypcminfo用于查看pcm通道的相关信息
输入:
- tinypcminfo -D /proc/asound/cards
结果如下:
从上面获得的信息中可以知道PCM的采样率,通道个数,采样点数等信息。
其中 –D 后边跟的参数为声卡文件,一般位于/proc/asound/cards。可以使用
- cat /proc/asound/cards
查看当前声卡
2, tinymix
如下图所示,直接输入tinymix可以得到音频通路相关的各项配置参数。也可以通过添加参数修改其中的配置,如希望提高ADC1 Gain值到110,输入tinymix 12 110即可。
单独查看上述信息比较难以梳理,配合音频通路图会更加清晰。
上图中红色字体标明了LC1160与麦克风、耳机等硬件设备的连接关系。(注:M73xx项目由于内部ClassD不满足要求,喇叭连在了AUX通路上)
各个通路上的增益调节部分使用绿色字体标出了与tinymix中选项的对应关系。
图中加号与Mux是通路选择开关,对应tinymix中的其它的选项,用于在各种模式下切换音频通道。此部分比较多没有在图中一一标出,但根据已知的通路名是比较容易对应的。
图中黄色箭头标出的是通话时下行音频数据流,从PCM接口进入到LC1160,然后经过MonoDAC进行数模转化后送到听筒。
图中紫色箭头标出的是通话时上行音频数据流,从主MIC采集声音后,经过ADC1进行模数转换后由PMC的DO线送出
3, tinyplay
tinyplay是一个简易的音乐播放器,一般用于播放测试。tinyplay只能播放wav原始格式的音乐,不能进行Mp3等格式的解码,支持44.1kHz,48kHz采样率的wav音乐。
在调用tinyplay播放音乐之前需要先使用tinymix切换好音频通路:
- tinymix 0 I2SR //选择Stereo DACR的音源为i2s
- tinymix 1 I2SL //选择Stereo DACL的音源为i2s
- tinymix 2 0 0 //将Stereo DAC左右声道的mute关闭
- tinymix 24 1 //开启喇叭的外部PA芯片
- tinymix 40 1 //将Stereo DACR的声音路由到AUX口输出(因为实验机器喇叭挂载AUX接口上)
- tinymix 41 1 //将Stereo DACR的声音路由到AUX口输出(因为实验机器喇叭挂载AUX接口上)
- tinyplay z.wav
4, tinycap
tinycap是一个简易的录音软件,一般用于录音测试。
在调用tinycap录音之前需要先调整好音频通路:
- tinymix 14 30 //mic1 volume
- tinymix 19 1 //mic1 boost on
- tinymix 26 1 //adc1 -> mic1
- tinymix 50 ADC1 //i2sR out -> adc1
- tinymix 51 ADC1 //i2sL out -> adc2
- echo "0xfb 0x01" > /sys/devices/platform/comip_codec/lc1160_reg //bias poweron
- echo "0xad 0x08" > /sys/devices/platform/comip_codec/lc1160_reg //adc1 enable
- echo "0xac 0x01" > /sys/devices/platform/comip_codec/lc1160_reg //mic1 pga enable
- echo "0x3b 0xcc" > /sys/devices/platform/comip_codec/lc1160_reg //ldo
- echo 2 > /sys/bus/i2c/drivers/fm2018/0-0060/mode //bypass 外部的回声消除音频芯片(M730x项目特有)
- tinycap /sdcard/Music/l.wav
录音结束通过ctrl+C强行退出即可,之后在/sdcard/Music/路径下查看到l.wav音频文件
使用adb pull到本地电脑中,使用goldwave播放、查看。
- adb pull /sdcard/Music/l.wav d:\
另外:
LC1160的寄存器是分页的,即同一个地址上存在两个不同含义的寄存器,通过控制0xFC寄存器中的值来切换到第二功能页
- echo "0xfc 0x01" > /sys/devices/platform/comip_codec/lc1160_reg
- cat /sys/devices/platform/comip_codec/lc1160_reg
- echo "0xfc 0x00" > /sys/devices/platform/comip_codec/lc1160_reg
Android下音频tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)相关推荐
- Android下音频tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)--------mark详细
Android下音频tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo) 2017年05月29日 10:02:03 songze_lee 阅读数:10224更多 ...
- linux驱动由浅入深系列:tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)音频子系统之一
linux驱动由浅入深系列:tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)音频子系统之一 linux驱动由浅入深系列:ALSA框架详解 音频子系统之二 目 ...
- linux驱动由浅入深系列:tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)音频子系统之一【转】...
本文转载自:http://blog.csdn.net/radianceblau/article/details/64125411 目前linux中主流的音频体系结构是ALSA(Advanced Lin ...
- linux驱动由浅入深系列:tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)音频子系统之一【转】
本文转载自:http://blog.csdn.net/radianceblau/article/details/64125411 目前linux中主流的音频体系结构是ALSA(Advanced Lin ...
- tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)使用介绍
目前linux中主流的音频体系结构是ALSA(Advanced Linux Sound Architecture),ALSA在内核驱动层提供了alsa-driver,在应用层提供了alsa-lib,应 ...
- tinyalsa(tinymix/tinycap/tinyplay/tinypcminfo)
转自https://blog.csdn.net/radianceblau/article/details/64125411 目前linux中主流的音频体系结构是ALSA(Advanced Linux ...
- Android下音频的测试程序tinyalsa(录音,放音,查看声卡信息)
audio代码比较复杂,除了音频参数,我们平时客制化的地方不多.所以没有太深入了解. 建议先抽空看看如下代码: kernel, linux alsa 架构: kernel-3.10/sound/soc ...
- Andorid音频工具tinymix,tinyplay,tinycap使用
由于ALSA架构太过于庞大,对于嵌入式设备而言很多功能用不到,且会增加功耗,所以Android采用了精简后的tinyalsa,tinyalsa相关的底层调试工具常用的有tinymix,tinyplay ...
- android下音频采集功能,音频采集:Android基于AudioRecord的实现
前言 这篇文章简单详情下手机端Android系统下利使用AudioRecord进行音频采集方法. 开始前先提供一份源码 AudioRecordLib . AudioRecord采集的核心实现在于 Au ...
最新文章
- findcontours函数_opencv轮廓findContoursamp;drawContours
- Oracle查找重复数据
- Java调用Python脚本工具类
- HTML基础入门学习准备篇
- Linux系统监控shell脚本
- 进程间同步(互斥量、信号量)
- 计算基因组学需要计算机知识吗,生物信息学——计算基因组学的一些参考书
- 一些很有意思的JS现象
- 光绘文件 c语言 解析,AltiumDesigner输出光绘文件
- 电力电子、电机控制系统的建模和仿真_电力传动控制系统:运动控制系统
- python数据类型有哪些、分别有什么用途_python数据类型
- 项目管理 : 需求管理的6个流程
- DICOM图像像素值、灰度值与CT值
- 程序员如何成为别人的男朋友
- 华为云OBS创建对象时以HTTP方式通知订阅终端
- python里美元怎么表示_说说 Python 正则表达式中的插入字符、美元字符
- 常用复原reast.css
- php 利用 PHPExcel 导出 导入 Excel 方法介绍(功能介绍)
- 报错error: resource style/Theme.AppCompat.Light.DarkActionBar (aka com.xxx.xxx:style/Theme)not found.
- 【苹果推软件】Apple IOS推送证书 如何创建CSR文件
热门文章
- 条件自动添加taint
- HTML5期末大作业:体育健身运动网页设计——健身俱乐部健身器材网站模板(24页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计
- vue+webpack搭建项目超详细教程
- vijos1404:遭遇战
- 使用SNTP协议获取时间
- 烧写linux系统到开发板中,Mini2440烧写Linux系统
- python3 scrapy实战:爬取拉勾网招聘数据至数据库(反爬虫)
- html添加友情链接,WordPress利用css添加“友情链接”功能
- 图论(最短路,最小生成树,并查集)
- WebBuilder后台JSON处理