Calibrate Alsa buffers correctly, weird API

I am currently working on a project that requires me to sample with Alsa. I'm trying to set everything up correctly, but I am fixated on how to read my reading correctly.

There are two primitives that seem interesting to me for my task:

snd_pcm_hw_params_get_period_time
snd_pcm_hw_params_get_buffer_size

The name of the first one assumes that the output will be the duration of the sampling period, however this is strange: if I set the sampling frequency to f = 44100Hz, the sampling period (in nanoseconds) should be T0 = 1e9 / 44100 ~= 22676 nsuntil the function answers T1 = 725 us = 725000 ns.

Meanwhile, even if I was asked to use non-blocking primitives, I try to profile the time required to block the "readi", and it turns out that the sample requires T2 = 8028603 nsat best and T3 = 12436217 nsat worst.

Finally, I cannot understand what the following two mean:

snd_pcm_hw_params_get_buffer_time
snd_pcm_hw_params_get_period_size

I do not understand how I can measure the buffer in time and period in size. However, the former returns the same value as get_buffer_size, while the latter returns the same value as get_period_time.

Any clues?

+3
source share
3 answers

This is my initialization of the sound card.

First of all, I set the necessary parameters

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;

When each parameter is configured correctly, the parameters are applied to the descriptor:

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

After it has been applied, a brave programmer can get the required data as follows:

get_period_size_min () gives the minimum frame size of the buffer that will contain the selection. A buffer having this size is wide enough.

    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;
}
+3

ALSA - ^ W :

  • : (.. , 1 ,...)
  • : , , ( ).

* _size .

+4

, , ALSA, .

snd_pcm_hw_params_get_period_size()

, hw . ,

snd_pcm_hw_params_get_period_time()

(10 ^ -6), . , "" ,

snd_pcm_hw_params_get_period_size()*1000000/snd_pcm_hw_params_get_period_time()
+1

Source: https://habr.com/ru/post/1756766/


All Articles