ALSA编程之libasound2库的使用——controls篇

说明

在Linux环境下,alsa()是用来驱动声卡的相当不错的方案,涉及到声卡参数调节,播放声音,录音等功能,均可以使用libasound很好的解决

预备知识

1. 几个常用的结构体类型

  • snd_ctl_t : CTL类型
  • snd_ctl_card_info_t : CTL 卡类型
  • snd_ctl_elem_list_t: CTL 元素列表类型
  • snd_ctl_elem_t: CTL元素类型
  • snd_ctl_elem_info_t: CTL 元素信息类型
  • snd_ctl_elem_value_t: CTL 元素值类型

2. 几个常用的枚举类型

  • snd_ctl_elem_type_t : CTL元素类别类型
    SND_CTL_ELEM_TYPE_NONE = 0,
    SND_CTL_ELEM_TYPE_INTEGER,
    SND_CTL_ELEM_TYPE_ENUMERATED,
    SND_CTL_ELEM_TYPE_BYTES,
    SND_CTL_ELEM_TYPE_INTEGER64,
    SND_CTL_ELEM_TYPE_LAST = SND_CTL_ELEM_TYPE_INTEGER64

  • snd_ctl_elem_iface_t : CTL元素的 interface类别类型
    SND_CTL_ELEM_IFACE_CARD = 0,
    SND_CTL_ELEM_IFACE_MIXER,
    SND_CTL_ELEM_IFACE_PCM,
    SND_CTL_ELEM_IFACE_RAWMIDI,
    SND_CTL_ELEM_IFACE_SEQUENCER,
    SND_CTL_ELEM_IFACE_LAST = SND_CTL_ELEM_IFACE_SEQUENCER

  • snd_ctl_event_type_t : CTL事件类别类型
    SND_CTL_EVENT_ELEM = 0,
    SND_CTL_EVENT_LAST = SND_CTL_EVENT_ELEM

  • snd_ctl_type_t : CTL类别类型
    SND_CTL_TYPE_HW,
    SND_CTL_TYPE_INET,
    SND_CTL_TYPE_EXT

常用的api

声卡

int snd_card_next(int *card)                    // 查找声卡
int snd_card_load(int card)                     // 加载声卡驱动
int snd_card_get_name(int card, char **name)    // 获取声卡名
int snd_card_get_index(const char *name)        // 根据声卡名获取声卡索引

CTL

int snd_ctl_open(snd_ctl_t **ctl, const char *name, int mode)   // 打开一个CTL并自动分配CTL空间, name大致格式为"hw:0", mode 一般又两个值 SND_CTL_NONBLOCK和SND_CTL_AYSNC
int snd_ctl_close(snd_ctl_t *ctl) // 关闭已打开的CTL

CTL 卡信息

int snd_ctl_card_info_malloc (snd_ctl_card_info_t **ptr) // 申请一个CTL卡信息空间
void snd_ctl_card_info_free (snd_ctl_card_info_t *obj) // 释放掉CTL卡信息的空间
void snd_ctl_card_info_clear (snd_ctl_card_info_t *obj) // 清除掉CTL卡信息中已有的信息
void snd_ctl_card_info_copy (snd_ctl_card_info_t *dst, const snd_ctl_card_info_t *src) // 拷贝
int snd_ctl_card_info_get_card (const snd_ctl_card_info_t *obj) // 获取卡号
const char * snd_ctl_card_info_get_id (const snd_ctl_card_info_t *obj) // 获取卡的id名称
const char * snd_ctl_card_info_get_driver (const snd_ctl_card_info_t *obj) //获取卡的驱动名称
const char * snd_ctl_card_info_get_name (const snd_ctl_card_info_t *obj) // 获取卡名字
const char * snd_ctl_card_info_get_longname (const snd_ctl_card_info_t *obj)// 获取卡名字的较长版本
const char * snd_ctl_card_info_get_mixername (const snd_ctl_card_info_t *obj) //获取卡信息中的mixer名字
const char * snd_ctl_card_info_get_components (const snd_ctl_card_info_t *obj) // 获取卡信息中的组件列表

CTL元素列表

int snd_ctl_elem_list_malloc (snd_ctl_elem_list_t **ptr) // 申请一个列表空间
void snd_ctl_elem_list_free (snd_ctl_elem_list_t *obj) // 给已申请空间的列表释放空间
void snd_ctl_elem_list_clear (snd_ctl_elem_list_t *obj) // 清楚列表中的信息
void snd_ctl_elem_list_copy (snd_ctl_elem_list_t *dst, const snd_ctl_elem_list_t *src) // 拷贝列表
void snd_ctl_elem_list_set_offset (snd_ctl_elem_list_t *obj, unsigned int val) // 设置第一个元素的索引偏移
unsigned int snd_ctl_elem_list_get_used (const snd_ctl_elem_list_t *obj) // 获取已使用的元素数量
unsigned int snd_ctl_elem_list_get_count (const snd_ctl_elem_list_t *obj) // 获取实际存在的CTL元素总数量
void snd_ctl_elem_list_get_id (const snd_ctl_elem_list_t *obj, unsigned int idx, snd_ctl_elem_id_t *ptr) // 获取CTL元素的ID
unsigned int snd_ctl_elem_list_get_numid (const snd_ctl_elem_list_t *obj, unsigned int idx) // 获取CTL元素列表中指定索引元素的numid
snd_ctl_elem_iface_t snd_ctl_elem_list_get_interface (const snd_ctl_elem_list_t *obj, unsigned int idx) // 获取CTL元素列表指定索引的元素的interface类型
unsigned int snd_ctl_elem_list_get_device (const snd_ctl_elem_list_t *obj, unsigned int idx) // 获取CTL元素列表指定索引元素的设备
unsigned int snd_ctl_elem_list_get_subdevice (const snd_ctl_elem_list_t *obj, unsigned int idx) // 获取CTL元素列表指定索引元素的子设备
const char * snd_ctl_elem_list_get_name (const snd_ctl_elem_list_t *obj, unsigned int idx) // 获取CTL元素列表指定索引元素的名字
unsigned int snd_ctl_elem_list_get_index (const snd_ctl_elem_list_t *obj, unsigned int idx) // 获取CTL元素列表指定索引元素的索引

CTL元素信息

int snd_ctl_elem_info_malloc (snd_ctl_elem_info_t **ptr) // 申请一个CTL元素信息空间
void snd_ctl_elem_info_free (snd_ctl_elem_info_t *obj) // 释放已申请的CTL元素空间
void snd_ctl_elem_info_clear (snd_ctl_elem_info_t *obj)// 清除掉CTL元素已有的信息
void snd_ctl_elem_info_copy (snd_ctl_elem_info_t *dst, const snd_ctl_elem_info_t *src) // 拷贝一个CTL元素信息
snd_ctl_elem_type_t snd_ctl_elem_info_get_type (const snd_ctl_elem_info_t *obj) // 从CTL元素信息中获取元素类别
int snd_ctl_elem_info_is_readable (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素是否可读 
int snd_ctl_elem_info_is_writable (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素是否可写
int snd_ctl_elem_info_is_volatile (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素是否可以通知
int snd_ctl_elem_info_is_inactive (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素状态是否活跃
int snd_ctl_elem_info_is_locked (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素是否上锁
int snd_ctl_elem_info_is_owner (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素是否所属当前用户
int snd_ctl_elem_info_is_user (const snd_ctl_elem_info_t *obj) // 判断某个CTL元素是否是用户元素
pid_t   snd_ctl_elem_info_get_owner (const snd_ctl_elem_info_t *obj) // 获取某个CTL元素的当前PID
unsigned int snd_ctl_elem_info_get_count (const snd_ctl_elem_info_t *obj) // 获取某个CTL元素的值个数
long snd_ctl_elem_info_get_min (const snd_ctl_elem_info_t *obj) // 当某个CTL元素值为整数时的最小值
long snd_ctl_elem_info_get_max (const snd_ctl_elem_info_t *obj) // 当某个CTL元素值为整数时的最大值
long snd_ctl_elem_info_get_step (const snd_ctl_elem_info_t *obj) // 当某个CTL元素值为整数时的步进值
long long snd_ctl_elem_info_get_min64 (const snd_ctl_elem_info_t *obj) //获取某个值为64位整数的CTL元素最小值
long long snd_ctl_elem_info_get_max64 (const snd_ctl_elem_info_t *obj) //获取某个值为64位整数的CTL元素最大值
long long snd_ctl_elem_info_get_step64 (const snd_ctl_elem_info_t *obj) // 获取某个值为64位整数的CTL元素步进值
unsigned int snd_ctl_elem_info_get_items (const snd_ctl_elem_info_t *obj) // 获取某个值为SND_CTL_ELEM_TYPE_ENUMERATED类型的CTL元素的item数量
void    snd_ctl_elem_info_set_item (snd_ctl_elem_info_t *obj, unsigned int val) // 设置某个值为SND_CTL_ELEM_TYPE_ENUMERATED类型的CTL元素的item
const char * snd_ctl_elem_info_get_item_name (const snd_ctl_elem_info_t *obj) // 获取某个值为SND_CTL_ELEM_TYPE_ENUMERATED类型的CTL元素的名称 
int snd_ctl_elem_info_get_dimensions (const snd_ctl_elem_info_t *obj) // 获取某个值为SND_CTL_ELEM_TYPE_ENUMERATED类型的CTL元素的dimensions
int snd_ctl_elem_info_get_dimension (const snd_ctl_elem_info_t *obj, unsigned int idx) // 获取某个值为SND_CTL_ELEM_TYPE_ENUMERATED类型的CTL元素指定索引的dimension
int snd_ctl_elem_info_set_dimension (snd_ctl_elem_info_t *info, const int dimension[4])  // 设置某个值为SND_CTL_ELEM_TYPE_ENUMERATED类型的CTL元素的dimension
void snd_ctl_elem_info_get_id (const snd_ctl_elem_info_t *obj, snd_ctl_elem_id_t *ptr) // 获取CTL元素的CTL元素ID
unsigned int snd_ctl_elem_info_get_numid (const snd_ctl_elem_info_t *obj) // 获取CTL元素的numid
snd_ctl_elem_iface_t snd_ctl_elem_info_get_interface (const snd_ctl_elem_info_t *obj) //获取CTL元素的interface类型
unsigned int snd_ctl_elem_info_get_device (const snd_ctl_elem_info_t *obj) // 获取CTL元素的设备
unsigned int snd_ctl_elem_info_get_subdevice (const snd_ctl_elem_info_t *obj) // 获取CTL元素的子设备
const char * snd_ctl_elem_info_get_name (const snd_ctl_elem_info_t *obj) // 获取CTL元素的名称
unsigned int snd_ctl_elem_info_get_index (const snd_ctl_elem_info_t *obj) // 获取CTL元素的索引
void snd_ctl_elem_info_set_id (snd_ctl_elem_info_t *obj, const snd_ctl_elem_id_t *ptr) // 获取CTL元素的ID
void snd_ctl_elem_info_set_numid (snd_ctl_elem_info_t *obj, unsigned int val) // 设置CTL元素的numid
void snd_ctl_elem_info_set_interface (snd_ctl_elem_info_t *obj, snd_ctl_elem_iface_t val) // 设置CTL元素的numid
void snd_ctl_elem_info_set_device (snd_ctl_elem_info_t *obj, unsigned int val) //设置CTL元素的设备
void snd_ctl_elem_info_set_subdevice (snd_ctl_elem_info_t *obj, unsigned int val) //设置CTL元素的子设备
void snd_ctl_elem_info_set_name (snd_ctl_elem_info_t *obj, const char *val) //设置CTL元素的名称
void snd_ctl_elem_info_set_index (snd_ctl_elem_info_t *obj, unsigned int val) // 设置CTL元素的索引

CTL元素值

int snd_ctl_elem_value_malloc (snd_ctl_elem_value_t **ptr) // 申请一个CTL元素值空间
void snd_ctl_elem_value_free (snd_ctl_elem_value_t *obj) // 是放一个已申请空间的CTL元素值
void snd_ctl_elem_value_clear (snd_ctl_elem_value_t *obj) // 清除一个已用的CTL元素值的内容
void snd_ctl_elem_value_copy (snd_ctl_elem_value_t *dst, const snd_ctl_elem_value_t *src) // 拷贝一个CTL元素值 
int snd_ctl_elem_value_compare (snd_ctl_elem_value_t *left, const snd_ctl_elem_value_t *right) // 比较两个CTL元素值
void snd_ctl_elem_value_get_id (const snd_ctl_elem_value_t *obj, snd_ctl_elem_id_t *ptr) // 获取CTL元素ID
unsigned int snd_ctl_elem_value_get_numid (const snd_ctl_elem_value_t *obj) // 获取numid
snd_ctl_elem_iface_t snd_ctl_elem_value_get_interface (const snd_ctl_elem_value_t *obj) // 获取interface类型
unsigned int snd_ctl_elem_value_get_device (const snd_ctl_elem_value_t *obj) // 获取设备
unsigned int snd_ctl_elem_value_get_subdevice (const snd_ctl_elem_value_t *obj) //获取子设备
const char * snd_ctl_elem_value_get_name (const snd_ctl_elem_value_t *obj) // 获取名称
unsigned int snd_ctl_elem_value_get_index (const snd_ctl_elem_value_t *obj) // 获取索引值
void snd_ctl_elem_value_set_id (snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr) // 设置ID
void snd_ctl_elem_value_set_numid (snd_ctl_elem_value_t *obj, unsigned int val) // 设置numid
void snd_ctl_elem_value_set_interface (snd_ctl_elem_value_t *obj, snd_ctl_elem_iface_t val) //设置interface类型
void snd_ctl_elem_value_set_device (snd_ctl_elem_value_t *obj, unsigned int val) // 设置设备
void snd_ctl_elem_value_set_subdevice (snd_ctl_elem_value_t *obj, unsigned int val) //设置子设备
void snd_ctl_elem_value_set_name (snd_ctl_elem_value_t *obj, const char *val) // 设置名字
void snd_ctl_elem_value_set_index (snd_ctl_elem_value_t *obj, unsigned int val) // 设置索引
int snd_ctl_elem_value_get_boolean (const snd_ctl_elem_value_t *obj, unsigned int idx) // 获取布尔值
long snd_ctl_elem_value_get_integer (const snd_ctl_elem_value_t *obj, unsigned int idx) // 获取整数值
long long snd_ctl_elem_value_get_integer64 (const snd_ctl_elem_value_t *obj, unsigned int idx) // 获取64位整数值
unsigned int snd_ctl_elem_value_get_enumerated (const snd_ctl_elem_value_t *obj, unsigned int idx) // 获取枚举值 
unsigned char snd_ctl_elem_value_get_byte (const snd_ctl_elem_value_t *obj, unsigned int idx) // 获取字节值
void snd_ctl_elem_value_set_boolean (snd_ctl_elem_value_t *obj, unsigned int idx, long val) // 设置布尔值
void snd_ctl_elem_value_set_integer (snd_ctl_elem_value_t *obj, unsigned int idx, long val) // 设置整数值
void snd_ctl_elem_value_set_integer64 (snd_ctl_elem_value_t *obj, unsigned int idx, long long val)// 设置64位整数值
void snd_ctl_elem_value_set_enumerated (snd_ctl_elem_value_t *obj, unsigned int idx, unsigned int val) // 设置枚举值
void snd_ctl_elem_value_set_byte (snd_ctl_elem_value_t *obj, unsigned int idx, unsigned char val) //设置字节值
void snd_ctl_elem_set_bytes (snd_ctl_elem_value_t *obj, void *data, size_t size) // 同时设置多个字节值
const void * snd_ctl_elem_value_get_bytes (const snd_ctl_elem_value_t *obj) //获取多个字节值
void snd_ctl_elem_value_get_iec958 (const snd_ctl_elem_value_t *obj, snd_aes_iec958_t *ptr) // 获取aes_iec958值
void snd_ctl_elem_value_set_iec958 (snd_ctl_elem_value_t *obj, const snd_aes_iec958_t *ptr) //设置 aes_iec958值

大致使用流程

流程鱼骨图

ALSA编程之libasound2库的使用——controls篇_第1张图片

示例代码

#include 
#include 
#include 
#include 
#include 
#include 

void snd_main();

int main(int argc, char **argv)
{
    snd_main();
    return 0;
}
void snd_main()
{
    int card = -1;
    snd_card_next(&card);
    while(card != -1) {
        snd_ctl_t *ctl;
        char ctrlName[16];
        sprintf(ctrlName, "hw:%d", card);
        std::cout << "open ret: " << snd_ctl_open(&ctl, ctrlName, SND_CTL_NONBLOCK) << std::endl;
        std::cout << "control name: " << snd_ctl_name(ctl) << std::endl;

        snd_ctl_card_info_t *info;
        snd_ctl_card_info_alloca(&info);

        snd_ctl_card_info(ctl, info);

        std::cout << "card name: " << snd_ctl_card_info_get_name(info) <<std::endl;



        snd_ctl_elem_list_t *list;
        snd_ctl_elem_list_malloc(&list);
        snd_ctl_elem_list_alloc_space(list, 100);

        snd_ctl_elem_list(ctl, list);

        auto used = snd_ctl_elem_list_get_used(list);

        std::cout << "list used: " << used << std::endl << std::endl;

        snd_ctl_elem_info_t *elem_info = nullptr;
        snd_ctl_elem_info_malloc(&elem_info);

        snd_ctl_elem_value_t *value;
        snd_ctl_elem_value_malloc(&value);

        for(int i = 0; i < used; ++i) {

            auto numid = snd_ctl_elem_list_get_numid(list, i);

            std::cout << "numid: " << numid << std::endl;

            snd_ctl_elem_info_set_numid(elem_info, numid);

            snd_ctl_elem_info(ctl, elem_info);

            auto iface = snd_ctl_elem_info_get_interface(elem_info);
            auto type = snd_ctl_elem_info_get_type(elem_info);



            auto count = snd_ctl_elem_info_get_count(elem_info);
            std::cout << "name: " << snd_ctl_elem_info_get_name(elem_info)<< std::endl;
            std::cout << "iface: " <<  snd_ctl_elem_iface_name(iface) << std::endl;
            std::cout << "type: " << snd_ctl_elem_type_name(type) << std::endl;
            std::cout << "count: " << count << std::endl;




            snd_ctl_elem_value_set_numid(value, numid);
            snd_ctl_elem_read(ctl, value);

            switch(type) {
                case SND_CTL_ELEM_TYPE_INTEGER: {
                    auto min = snd_ctl_elem_info_get_min(elem_info);
                    auto max = snd_ctl_elem_info_get_max(elem_info);
                    std::cout << "min: " <<  min << std::endl;
                    std::cout << "max: " << max << std::endl;
                    for(int i = 0; i < count; ++i) {
                        std::cout << "value " << i << " : " << snd_ctl_elem_value_get_integer(value, i) << std::endl;
                        if(numid == 2) {
                            snd_ctl_elem_value_set_integer(value, i, max);
                            snd_ctl_elem_write(ctl, value);
                        }
                    }
                }
                break;
            case SND_CTL_ELEM_TYPE_BOOLEAN:
                for(int i = 0; i < count; ++i) std::cout << "value " << i << " : " << (snd_ctl_elem_value_get_boolean(value, i) ? "true" : "false") << std::endl;
                break;
            default:
                break;
            }

            std::cout << "==========================================" << std::endl;

        }
        snd_ctl_elem_info_free(elem_info);

        snd_ctl_elem_list_free(list);

        snd_card_next(&card);
    }
}

你可能感兴趣的:(Linux,C++,嵌入式开发)