Правильно измеряющие буферы Alsa, странный API

Я в настоящее время работаю над проектом, который требует, чтобы я сделал некоторую выборку с 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.

Какая-либо подсказка?

6
задан Dacav 6 August 2010 в 08:29
поделиться

2 ответа

Это моя функция инициализации звуковой карты.

Прежде всего, я установил необходимые параметры

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 / частота, как можно подумать. Можно получить период выборки, используя примитив get_period_time ()!

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

    return 0;
}
5
ответ дан 8 December 2019 в 18:30
поделиться

ALSA имеет некоторую странную^W специфическую терминологию:

  • Кадры: сэмплы x каналы (т.е.: стерео кадры состоят из двух сэмплов, моно кадры состоят из 1 сэмпла,...)
  • Период: Количество переданных выборок, после которого устройство подтверждает передачу аппликации (обычно через прерывание).

Функции *_size, похоже, возвращают размеры в кадрах.

HTH

6
ответ дан 8 December 2019 в 18:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: