原文链接:

https://blog.csdn.net/u012899335/article/details/82421115

https://blog.csdn.net/ly601579033/article/details/85112365

https://blog.csdn.net/RadianceBlau/article/details/64125411

https://blog.csdn.net/kangear/article/details/38139669

 

    由于ALSA(Advanced Linux Sound Architecture)架构太过于庞大,对于嵌入式设备而言很多功能用不到,且会增加功耗,所以Android采用了精简后的tinyalsa。ALSA在内核驱动层提供了alsa-driver,在应用层提供了alsa-lib,应用程序只需要调用alsa-lib提供的API就可以完成对底层硬件的操作。Android中使用tinyalsa控制管理所有模式的音频通路,我们也可以使用tinyalsa提供的工具进行查看、调试。tinyalsa相关的底层调试工具常用的有 tinypcminfo ,tinymix,tinyplay,tinycap,下面分别介绍他们的使用方法。

相关概念:
Sample:样本长度,音频数据最基本的单位,常见的有8位和16位。
Channel:声道数,分为单声道mono和立体声stereo。
Frame:帧,构成一个完整的声音单元,Frame = Sample * channel。
Rate:又称Sample rate,采样率,即每秒的采样次数,针对帧而言。
Interleaved:交错模式,一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声),再开始桢2的记录。而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。多数情况下使用交错模式。
Period size:周期,每次硬件中断处理音频数据的帧数,对于音频设备的数据读写,以此为单位。
Buffer size:数据缓冲区大小,这里特指runtime的buffer size,而不是snd_pcm_hardware定义的buffer_bytes_max。一般来说Buffer size =period_size * period_count,period_count相当于处理完一个buffer数据所需的硬件中断次数。

tinymix
tinymix可以查看系统的音频控件,可直接执行tinymix进行查看。
hello_world:/ # tinymix -D 0                                                           
Mixer name: 'AML-TVAUDIO'
Number of controls: 5
ctl     type    num     name                                    value
 
0       INT     2       PGA IN Gain                             9 9
1       INT     2       ADC Digital Capture Volume              80 80
2       INT     1       AMP Master Volume                       175
3       INT     1       AMP Ch1 Volume                          255
4       INT     1       AMP Ch2 Volume                          255
Tinymix有五个成员变量

1,ctl 成员的id号

2,type 类型( INT,BOOL,ENUM字串形式,BYTE 八位十六进制数组)

3,num  num_value(第五个成员value的个数有几个)

4,name

5,value 

实现的源码可以参考: exteral/tinyalsa/tinymix.c

实现过程:

mixer = mixer_open(card);  //通过声卡得到mixer

获取状态信息方法:

// 通过id或者name获取mixer_ctl
 
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)
 
// 获取name,  type,  num_values(value的个数)
 
name = mixer_ctl_get_name(ctl);
 
type = mixer_ctl_get_type_string(ctl);
 
num_values = mixer_ctl_get_num_values(ctl);


//获取value
 
int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id) //获取整型 or BOOL类型
 
//获取enums个数; 获取enum字串
 
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);
 
int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count) //获取BYTE
 
//set value
 
int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count) //set BYTE
 
int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value) //set value
 
int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string) //set enum

驱动中增加tinymix的控制选项一般在codec中进行:

soc_codec_driver->component_driver->controls

对snd_kcontrol_new结构进行填充即可!  
 

tinymix更多的作用的是用来手动设置控件的值,控件可通过tinymix查看,或者通过mixer_paths.xml进行查看。下面以手动设置speaker相关控件为例进行说明tinymix的使用方法:

mixer_paths.xml文件中speaker相关控件如下:

    <path name="speaker">
        <ctl name="RX3 MIX1 INP1" value="RX1" />
        <ctl name="LINE_OUT" value="Switch" />
        <ctl name="SPK" value="Switch" />          
    </path>
下面以手动设置speaker相关控件为例进行说明tinymix的使用方法,如下,第一个参数为控件名,第二个参数为控件值

tinymix "RX3 MIX1 INP1" "RX1"
tinymix "LINE_OUT" "Switch"
tinymix "SPK" "Switch"
tinymix加控件名可以查看控件的值,如想查看"LINE_OUT"的值,可执行tinymix "LINE_OUT"

tinyplay

tinyplay file.wav [-D card] [-d device] [-p period_size] [-n n_periods]
可以使用tinyplay直接进行播放wav格式文件,在播放之前需要先使用tinymix进行相关控件的设置,下面以speaker为例进行说明,注意最后一行需要加上,代表打开I2S的播放控件。

tinymix "RX3 MIX1 INP1" "RX1"
tinymix "LINE_OUT" "Switch"
tinymix "SPK" "Switch"
    
tinymix "PRI_MI2S_RX Audio Mixer MultiMedia5" "1"
设置好上面控件后,执行tinypaly xxx.wav即可进行音频的播放

tinycap

Usage: tinycap file.wav [-D card] [-d device] [-c channels] [-r rate] [-b bits] [-p period_size] [-n n_periods] [-T capture time]
-D  card        声卡

-d  device     设备

-c  channels  通道

-r  rate   采样率

-b  bits   pcm 位宽

-p  period_size   一次中断的帧数

-n  n_periods     周期数

tinycap是用来录音的,使用之前也需要先设置录音相关的控件,以主mix为例进行过说明,注意最后一行是打开I2S的录音控件

tinymix "ADC1 Volume" "6"
tinymix "DEC1 MUX" "ADC1"
tinymix "IIR1 INP1 MUX" "DEC1"
 
tinymix "MultiMedia1 Mixer TERT_MI2S_TX" "1"
设置好上面控件后,执行tinycap xxx.wav即可以将音频录制到xxx.wav中,Ctrl+C停止录音。

注意,最好使用linux进行测试,使用windows的话,可能没法正常录音。                                                   

例子: tinycap /sdcard/test.pcm -D 0 -d 0 -c 4 -r 48000 -b 32 -p 768 -n 10

声卡0;设备0;四通道;48K采样率;32位位宽;一帧数据存储大小;采样n次
 

编译tinyalsa后生成四个小工具:

tinymix
tinyplay
tinycap
tinypcminfo


编译命令:mmm external/tinyalsa/

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用


下面依次演示一下四个小工具的使用:(以下使用联芯科技的LC1860平台配合LC1160电源+音频芯片,截图及演示效果均来自M7301P5测试机)

1,  tinypcminfo

tinypcminfo用于查看pcm通道的相关信息

输入:

tinypcminfo -D /proc/asound/cards
结果如下:

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用
从上面获得的信息中可以知道PCM的采样率,通道个数,采样点数等信息。

其中 –D 后边跟的参数为声卡文件,一般位于/proc/asound/cards。可以使用
cat /proc/asound/cards
查看当前声卡

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用

2,  tinymix

如下图所示,直接输入tinymix可以得到音频通路相关的各项配置参数。也可以通过添加参数修改其中的配置,如希望提高ADC1 Gain值到110,输入tinymix 12 110即可。

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用
单独查看上述信息比较难以梳理,配合音频通路图会更加清晰。

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用
上图中红色字体标明了LC1160与麦克风、耳机等硬件设备的连接关系。(注:M73xx项目由于内部ClassD不满足要求,喇叭连在了AUX通路上)

各个通路上的增益调节部分使用绿色字体标出了与tinymix中选项的对应关系。

图中加号与Mux是通路选择开关,对应tinymix中的其它的选项,用于在各种模式下切换音频通道。此部分比较多没有在图中一一标出,但根据已知的通路名是比较容易对应的。

图中黄色箭头标出的是通话时下行音频数据流,从PCM接口进入到LC1160,然后经过MonoDAC进行数模转化后送到听筒。

图中紫色箭头标出的是通话时上行音频数据流,从主MIC采集声音后,经过ADC1进行模数转换后由PMC的DO线送出

关于tinymix小结:

        通过观察发现,Android系统的声音音量的调节并没有直接使用tinyalsa,而基于上层软件实现,因为无论上层音量怎么改变,这里看到的都是24(以我采用的设备为例)。通道的切换是真正使用了tinyalsa,当通过不同通道播放音乐的时候可以实时观察到通道的切换。在某个网站上看到Android在没有声音播放的3秒后会关闭alsa,这里也得到了证实,我以前认为Android系统会永久占用音频设备。

当通过蓝牙播放音乐的时候,已经不经过alsa了。tinymix查看得到都处于关闭状态,因为Android4.2的蓝牙协议全部在用户层实现了,直接走uart通道。这样的设计方式一时半会不能理解。
 

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

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用

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音频文件

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用
使用adb pull到本地电脑中,使用goldwave播放、查看。

adb pull /sdcard/Music/l.wav d:\

ALSA音频底层调试工具tinypcminfo ,tinymix,tinyplay,tinycap的使用

另外:

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
 

相关文章: