正确调整Alsa缓冲区的大小,奇怪的API

Dac*_*cav 6 c api alsa

我目前正在开展一个项目,要求我对Alsa进行一些采样.我正在尝试正确配置所有内容,但我仍然坚持如何正确调整我的阅读量.

我的任务似乎有两个基本原则:

snd_pcm_hw_params_get_period_time
snd_pcm_hw_params_get_buffer_size
Run Code Online (Sandbox Code Playgroud)

第一个的名称表明输出将是采样周期的时间长度,但这很奇怪:如果我f = 44100Hz在采样周期(以纳秒为单位)设置采样率应该是T0 = 1e9 / 44100 ~= 22676 ns函数将应答的时间T1 = 725 us = 725000 ns.

同时,即使我被要求使用非锁定原语,我也试图分析锁定'readi'所需的时间,结果证明样本需要T2 = 8028603 ns在最好的情况下时间和T3 = 12436217 ns最坏的情况.

最后我无法弄清楚以下两个是什么意思:

snd_pcm_hw_params_get_buffer_time
snd_pcm_hw_params_get_period_size
Run Code Online (Sandbox Code Playgroud)

我不知道如何测量缓冲区的时间和周期大小,但前者返回相同的值get_buffer_size,而后者返回相同的值get_period_time.

任何提示?

nin*_*alj 6

ALSA有一些奇怪的特定术语:

  • 帧:样本x通道(即:立体帧由两个样本组成,单帧由1个样本组成,......)
  • 周期:设备确认转移到应用程序之后转移的样本数(通常通过中断).

*_size函数似乎返回帧中的大小.

HTH


Dac*_*cav 5

这是我的声卡初始化功能。

首先,我设置所需的参数

static
int init_soundcard (snd_pcm_t *handle, unsigned *rate, uint8_t channels,
                    snd_pcm_uframes_t *nframes, unsigned *period)
{
    snd_pcm_hw_params_t *hwparams;
    int err;

    snd_pcm_hw_params_alloca(&hwparams);

    err = snd_pcm_hw_params_any(handle, hwparams);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_rate_near(handle, hwparams, rate, NULL);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_access(handle, hwparams,
                                       SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_format(handle, hwparams,
                                       SND_PCM_FORMAT_S16_LE);
    if (err < 0) return err;

    err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
    if (err < 0) return err;
Run Code Online (Sandbox Code Playgroud)

正确设置每个参数后,这些参数将应用于手柄:

    err = snd_pcm_hw_params(handle, hwparams);
    if (err < 0) return err;
Run Code Online (Sandbox Code Playgroud)

后已应用于它的勇敢的程序员可以如下获得所需的数据:

get_period_size_min()给出包含采样的缓冲区的最小大小(以帧为单位)。具有此大小的缓冲区足够宽。

    err = snd_pcm_hw_params_get_period_size_min(hwparams, nframes, NULL);
    if (err < 0) return err;
Run Code Online (Sandbox Code Playgroud)

这是很违反直觉的,但是正确的采样周期并不是人们可能认为的1 /速率。可以使用get_period_time()原语来获取采样周期!

    err = snd_pcm_hw_params_get_period_time(hwparams, period, NULL);
    if (err < 0) return err;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)