跳转至

常用接口说明

4 常用接口说明

这里主要介绍alsa-lib中的常用接口

4.1 4.1 control接口

为了方便操作访问,alsa-lib中封装了相关接口,通过control节点(/dev/snd/controlCX)去获取、设置control elements

主要涉及到的接口:

snd_ctl_open
snd_ctl_elem_info_get_id
snd_ctl_elem_info_set_id
snd_ctl_elem_info
snd_ctl_ascii_value_parse
snd_ctl_elem_read
snd_ctl_elem_write
snd_ctl_close

详细control接口说明请查阅:

https://www.alsa-project.org/alsa-doc/alsa-lib/control.html

https://www.alsa-project.org/alsa-doc/alsa-lib/group___control.html

下面是一个设置音量接口的例子:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <alsa/asoundlib.h>
#define DEV_NAME "hw:audiocodec"
#define VOLUME_CONTROL "name='LINEOUT volume'"
/* Fuction to convert from percentage to volume. val = volume */
static int convert_volume(int percent, long min, long max)
{
    long range = max - min;
    if (range == 0)
        return 0;
    return (int)((range * percent / 100) + min);
}

bool controlVolume(int volume_percent)
{
    int err = -1;
    snd_ctl_t *handle = NULL;
    char *card = DEV_NAME;
    char *volume_control = VOLUME_CONTROL;
    char volume_string[4];
    long min, max, raw;
    snd_ctl_elem_info_t *info = NULL;
    snd_ctl_elem_id_t *id = NULL;
    snd_ctl_elem_value_t *control = NULL;
    if (volume_percent > 100 || volume_percent < 0)
        return false;
    snd_ctl_elem_info_alloca(&info);
    snd_ctl_elem_id_alloca(&id);
    snd_ctl_elem_value_alloca(&control);
    err = snd_ctl_ascii_elem_id_parse(id, volume_control);
    if (err < 0) {
        fprintf(stderr, "Wrong control identifier: %s\n", volume_control);
        goto failed;
    }
    err = snd_ctl_open(&handle, card, 0);
    if (err < 0) {
        fprintf(stderr, "Control device %s open error:%s\n", card, snd_strerror(err));
        goto failed;
    }
    snd_ctl_elem_info_set_id(info, id);
    err = snd_ctl_elem_info(handle, info);
    if (err < 0) {
        fprintf(stderr, "Cannot find the given element from control %s\n", card);
        goto failed;
    }
    snd_ctl_elem_info_get_id(info, id);
    snd_ctl_elem_value_set_id(control, id);
    err = snd_ctl_elem_read(handle, control);
    if (err < 0) {
        fprintf(stderr, "Cannot read the given element from control %s\n", card);
        goto failed;
    }
    min = snd_ctl_elem_info_get_min(info);
    max = snd_ctl_elem_info_get_max(info);
    snprintf(volume_string, sizeof(volume_string), "%d", convert_volume(volume_percent, min
    , max));
    /*printf("set volume %s, [%u%%]\n", volume_string, volume_percent);*/
    err = snd_ctl_ascii_value_parse(handle, control, info, volume_string);
    if (err < 0) {
        fprintf(stderr, "Control %s parse error: %s\n", card, snd_strerror(err));
        goto failed;
    }
    err = snd_ctl_elem_write(handle, control);
    if (err < 0) {
        fprintf(stderr, "Control %s write error: %s\n", card, snd_strerror(err));
        goto failed;
    }
failed:
    if (info)
        snd_ctl_elem_info_free(info);
    if (id)
        snd_ctl_elem_id_free(id);
    if (control)
        snd_ctl_elem_value_free(control);
    if (handle)
        snd_ctl_close(handle);
    return ((err < 0)? false : true);
}

4.2 4.2 PCM接口

为了方便操作访问,alsa-lib中封装了相关接口,通过pcmCXDXp/pcmCXDXc节点(/dev/s-nd/pcmCXDXx)去实现播放、录音功能。

主要涉及到的接口:

snd_pcm_open
snd_pcm_info
snd_pcm_hw_params_any
snd_pcm_hw_params_set_access
snd_pcm_hw_params_set_format
snd_pcm_hw_params_set_channels
snd_pcm_hw_params_set_rate_near
snd_pcm_hw_params_set_buffer_size_near
snd_pcm_hw_params
snd_pcm_sw_params_current
snd_pcm_sw_params
snd_pcm_readi
snd_pcm_writei
snd_pcm_close

详细pcm接口说明请查阅:

https://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html

https://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html

接口使用例子可以参考aplay,arecord的实现,代码可以在alsa-utils中找到(dl/alsa-utils-1.1.0.tar.bz2)