6

我目前正在开展一个项目,该项目需要我使用 Alsa 进行一些采样。我正在尝试正确配置所有内容,但我一直坚持如何正确调整我的阅读量。

有两个原语似乎对我的任务很有趣:

snd_pcm_hw_params_get_period_time
snd_pcm_hw_params_get_buffer_size

第一个名称表明输出将是采样周期的时间长度,但这很奇怪:如果我在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

我不明白如何及时测量缓冲区和大小的周期,但是前者返回与 相同的值get_buffer_size,而后者返回与 相同的值get_period_time

有什么提示吗?

4

3 回答 3

6

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

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

*_size 函数似乎以帧为单位返回大小。

高温高压

于 2010-07-27T15:32:39.603 回答
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;

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

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

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

get_period_size_min() 给出将包含采样的缓冲区的最小帧大小。具有这种大小的缓冲区足够宽。

    err = snd_pcm_hw_params_get_period_size_min(hwparams, nframes, NULL);
    if (err < 0) return err;

这是非常违反直觉的,但正确的采样周期并不是像人们想象的那样由 1/rate 给出。可以使用 get_period_time() 原语获得采样周期!

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

    return 0;
}
于 2010-08-06T08:30:23.890 回答
2

根据我使用和阅读 ALSA 库的理解,这段时间与正在发生的硬件中断有关。如果你使用

snd_pcm_hw_params_get_period_size()

它将返回您通过中断传递给硬件的帧数。同样,如果您使用

snd_pcm_hw_params_get_period_time()

您将获得插入这些帧的时间 (10^-6)。因此,如果

snd_pcm_hw_params_get_period_size()*1000000/snd_pcm_hw_params_get_period_time()
于 2016-06-28T14:24:56.003 回答