从C代码中设置ALSA主音量为dB

5

我似乎无法在我的机器上设置分贝音量。

我在VirtualBox中运行Ubuntu 13.04系统(用于开发)。

我按照这些说明将音量设置为标量控制静音状态,一切都很好。

但是当我尝试使用此函数以dB为单位进行设置:

snd_mixer_selem_set_playback_dB_all(elem, volume, 0)

或使用该函数:

snd_mixer_selem_set_playback_dB(elem, chn, volume, 0)

它总是失败,并显示错误代码-22(无效参数)。

在你问之前:我已经尝试过各种音量级别的设置(从-20000到20000),并且我还将最后一个参数更改为三个定义的值[-1、0、1]。

这是我当前用于测试的完整代码:

#include <alsa/asoundlib.h>
#include <stdbool.h>
#include <stdlib.h>

void SetAlsaMasterVolume(long volume) {
    long min, max;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;
    const char *card = "default";
    const char *selem_name = "Master";
    int x, mute_state;
    long i;
    
    snd_mixer_open(&handle, 0);
    snd_mixer_attach(handle, card);
    snd_mixer_selem_register(handle, NULL, NULL);
    snd_mixer_load(handle);
    
    snd_mixer_selem_id_alloca(&sid);
    snd_mixer_selem_id_set_index(sid, 0);
    snd_mixer_selem_id_set_name(sid, selem_name);
    snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
    
    //snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
    //snd_mixer_selem_set_playback_volume_all(elem, volume * max / 100);

    snd_mixer_selem_get_playback_dB_range(elem, &min, &max);
    printf("min: %ld, max: %ld\n", min, max);

    snd_mixer_selem_channel_id_t chn;
    for (chn = 0; chn < 32; chn++) {
        for (i = -1000; i <= 1000; i++)
            if (x = snd_mixer_selem_set_playback_dB(elem, chn, i, 0)) {
                ;//printf("%d: %d %s\n", chn, x, snd_strerror(x));
            } else {
                printf("Volume successfully set in dB!\n");
            }
    }

    if (snd_mixer_selem_has_playback_switch(elem)) {
        snd_mixer_selem_set_playback_switch_all(elem, true);
        snd_mixer_selem_get_playback_switch(elem, 0, &mute_state);
        if (!mute_state) {
            printf("System Muted.\n");
        } else {
            printf("System unmuted.\n");
        }
    }

    snd_mixer_close(handle);
}

int main() {
    SetAlsaMasterVolume(100);
    return 0;
}

正如您在此示例中看到的,我尝试自己设置每个通道,这与“snd_mixer_selem_set_playback_dB_all”做的事情是一样的,但我想尝试它以查看是否会得到不同的结果。

此示例的输出如下:

最小值:15774463,最大值:191

系统取消静音。

在我扩大dB值范围之前,我测试了输出:

最小值:1,最大值:191

也许我在这里漏掉了什么...... 希望您能帮助我!

编辑:

为了编译此脚本,我使用以下命令:

gcc test.c -lasound -o test


15774463 明显是错误的。检查所有函数的返回值。 - CL.
我还检查了 snd_mixer_selem_get_playback_dB 的值,无论我设置什么音量,它始终返回值15774463。 - user2902196
调用 snd_mixer_selem_get_playback_dB_range返回值(而非输出参数的值)是什么? - CL.
哦。那将是-22(EINVAL):P,所以已经有些问题了...但是那里可能出了什么问题呢? - user2902196
我应该如何准确地做到这一点?我刚刚重新安装了整个虚拟机,但除了新的范围值现在是 min: -1217479904, max: -1075727553 之外,没有任何变化。我现在运行的是 Ubuntu 13.10 的32位版本,而不是之前的64位版本。 - user2902196
显示剩余10条评论
1个回答

2

我遇到了类似的问题。原因似乎是来自pulseaudio的干扰。不过,它有点难以停止。一旦我运行了以下命令:

mkdir -p ~/.pulse
echo autospawn=no > ~/.pulse/client.conf
killall pulseaudio

pulseaudio崩溃了并且一直处于崩溃状态,我正在编写的ALSA程序能够从混音器中获取dB信息。

或者,您可以通过直接与声卡通信来绕过pulseaudio。更改

const char *card = "default";

为了

const char *card = "hw:0";

看看这对你有什么帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接