control控制接口
控制接口对于许多开关(switch)和调节器(slider)应用广泛,它能被用户空间存取,从而读写Codec相关寄存器。control的主要用于mixer。它用snd_kcontrol_new结构体描述。
snd_kcontrol_new
iface字段定义了control的类型,形式为SNDRV_CTL_ELEM_IFACE_XXX,对于mixer是SNDRV_CTL_ELEM_IFACE_MIXER,对于不属于mixer的全局控制,使用CARD;如果关联到某类设备,则是PCM、RAWMIDI、TIMER或SEQUENCER。在这里,我们主要关注mixer。
name字段是名称标识,这个字段非常重要,因为control的作用由名称来区分,对于名称相同的control,则使用index区分。下面会详细介绍上层应用如何根据name名称标识来找到底层相应的control。
name定义的标准是“SOURCE DIRECTION FUNCTION”即“源 方向 功能”,SOURCE定义了control的源,如“Master”、“PCM”等;DIRECTION 则为“Playback”、“Capture”等,如果DIRECTION忽略,意味着Playback和capture双向;FUNCTION则可以是“Switch”、“Volume”和“Route”等。
【修正】:上层也可以根据numid来找到对应的control,snd_ctl_find_id()也是优先判断上层是否传递了numid,是则直接返回这个numid对应的control。用户层设置numid和control的关联时,可用alsa-lib的snd_mixer_selem_set_enum_item()函数。snd_kcontrol_new结构体并没有numid这个成员,是因为numid是系统自动管理的,原则是该control的注册次序,保存到snd_ctl_elem_value结构体中。
access字段是访问控制权限。SNDRV_CTL_ELEM_ACCESS_READ意味着只读,这时put()函数不必实现;SNDRV_CTL_ELEM_ACCESS_WRITE意味着只写,这时get()函数不必实现。若control值频繁变化,则需定义 VOLATILE标志。当control处于非激活状态时,应设置INACTIVE标志。
private_value字段包含1个长整型值,可以通过它给info()、get()和put()函数传递参数。
kcontrol宏
在早期的ALSA创建一个新的control需要实现snd_kcontrol_new中的info、get和put这三个成员函数。现在较新版本的ALSA均定义了一些宏,如:
这个宏的对象是MIXER,对寄存器reg的位偏移shift可以设置0-max的数值。
又如:
这个宏与刚才类似,但是它是对两个寄存器reg_left和reg_right进行同一操作,Codec芯片中左右声道的寄存器配置一般来说是差不多的,这就是这个宏存在的意义。
例如我们一个Playback Volume的kcontrol接口这样定义:
SOC_DOUBLE_R_TLV("Playback Volume", REG_VOL_L, REG_VOL_R, 0, 192, 0, digital_tlv)
我们仅仅需要将Volume寄存器地址及位偏移,最大值填进去即可,当然这些数据要从Codec的datasheet取得。这里Volume寄存器地址是REG_VOL_L(左声道)和REG_VOL_R(右声道),位偏移为0,DAC Digital Gain范围是0-192(steps)。
为了追根究底,我们看看SOC_DOUBLE_R_TLV的put函数实现:
struct snd_ctl_elem_value *ucontrol:从用户层传递下来的,这个也可以从命名看出来(kcontrol-kernel control,ucontrol-user control);
shift是位偏移,而位掩码mask是通过宏SOC_DOUBLE_R_TLV中的xmax运算得到:unsigned int mask = (1 << fls(max)) - 1;
调用snd_soc_update_bits()->snd_soc_write()将ucontrol的value送到Codec的寄存器上。
snd_soc_put_volsw_2r()作为一个callback函数,用户层要设置某些功能时,如改变Playback Volume:
#amixer cset numid=3,iface=MIXER,name='Playback Volume' 100
到内核层时,会遍历一个节点类型为struct snd_kcontrol *的链表,找到kcontrol.id.numid与3相匹配的kctl(这个过程见snd_ctl_find_id()函数),然后调用kctl.put()函数将100写到Playback Volume寄存器中。
当然如果上层没有提供numid,则可根据name找到kcontrol.id.name相匹配的kctl。
注:amixer相关用法见:http://hi.baidu.com/serial_story/blog/item/c4e826d82a562f3f32fa1c31.html
从上往下的大致流程:
PS:上层如何设置kctl的numid,可参考http://blog.csdn.net/cpuwolf/archive/2009/10/17/4686830.aspx<2011/2/24>
snd_ctl_find_id函数:
分享到:
相关推荐
snd_kcontol,音频ALSA的控制接口
窗口架构,加载文件,图层,要素编辑,制图,导出
mt_soc_snd_init 结构体图
sb16snd_DOS_musicplay_plays_SoundBlaster_源码
串口通讯模拟,模拟计算机的串口通讯功能,实现多个串口通讯
RedGate.SQL.Prompt.5.1.8.2.cracked-SND_2
Headphone_Appln_Note
SND_RESOURCE | SND_ASYNC |SND_LOOP); 停止就顺理成章的写为: PlaySound(NULL, AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC |SND_LOOP); 可实际当中,怎么也不能停止播放。真正可以停止播放的是以下...
该代码为SDK,包括音频采集与播放接口,解决了音频采集直接调用wave api导致应用直接阻塞问题,采用异步线程模式,解决回调函数中调用api阻塞问题;
从电脑声音通道采集数据,存为txt格式文件。大家认为有用的话再传源文件
创建多风格和多分割窗口的多视图窗口,用户可以创建多种的窗口
能够播放声音波形的VC+源代码,用声卡输入信后
AT89C51SND1C 解码芯片做的硬盘MP3,现在只支持一块硬盘,一个分区只支持根目录歌曲播放,不支持文件夹。只支持FAT32文件系统,部分MP3文件不能解码.
函数原型:BOOL PlaySound( LPCSTR pszSound, HMODULE hmod, DWORD ...下面介绍一下SND_ALIAS,SND_FILENAME ,SND_RESOURCE,它们分别对应以下叙述三种声音来源的播放,设置了其中的一个就不能使用其它两个了。
Plays 16-bits sound via DMA on Sound Blaster 16 (DOS application with sources)
GSM发送端普通突发复用部分的dsp程序,汇编语言编写,已在CCS2.0验证正确。内付算法详细说明文档
实现wince下播放声音 ... SND_SYNC = 0x0000, /* play synchronously (default) */ SND_ASYNC = 0x0001, /* play asynchronously */ SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */
AT89C51SND1 SPI原程序,相于USB的。
详细介绍了linux下音频编程的方法,浅显易懂!
精仿 QQ 右下角弹窗 / 广告, VC 语言编写,带原版通知声音,可二次开发,100%一模一样。... PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_ASYNC|SND_RESOURCE|SND_NODEFAULT); return TRUE; }