Поведение ALSA ‘snd_pcm_writei’ в режиме блокировки

#c #linux #alsa #audio-player

#c #linux #alsa #аудиоплеер

Вопрос:

Я немного изменил демонстрационную версию, взятую с веб-сайта проекта ALSA, чтобы протестировать ее на звуковой карте моего ноутбука (аналог Intel PCH ALC3227, Ubuntu 18.04), для которой требуется 2 канала и 16-битные целые числа. Я также удвоил задержку (1 с), отключил повторную выборку и увеличил продолжительность демонстрации. Это код (проверка ошибок во время выполнения не вставлена ради синтеза)

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

static char *device = "hw:1,0"; /* playback device */
snd_output_t *output = NULL;
unsigned char buffer[16*1024]; /* some random data */
int main(void) {
    int err;
    unsigned int i;
    snd_pcm_t *handle;
    snd_pcm_sframes_t frames;
    for (i = 0; i < sizeof(buffer); i  )
        buffer[i] = (unsigned char) (rand() amp; 0xff);
    snd_pcm_open(amp;handle, device, SND_PCM_STREAM_PLAYBACK, 0)
    snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE,
            SND_PCM_ACCESS_RW_INTERLEAVED, 2, 48000, 0, 1E6);
    // Print actual buffer size
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_hw_params_malloc(amp;hw_params);
    snd_pcm_hw_params_current(handle, hw_params);
    snd_pcm_uframes_t bufferSize;
    snd_pcm_hw_params_get_buffer_size(hw_params, amp;bufferSize);
    printf("ALSA buffer size = %lin", bufferSize);
    // playback
    for (i = 0; i < 256;   i) {
        frames = snd_pcm_writei(handle, buffer, sizeof(buffer) / 4);
        if (frames < 0)
            frames = snd_pcm_recover(handle, (int) frames, 0);
        if (frames < 0) {
            printf("snd_pcm_writei failed: %sn", snd_strerror((int) frames));
            break;
        }
        if (frames > 0 amp;amp; frames < (long) sizeof(buffer) / 4)
            printf("Short write (expected %li, wrote %li)n",
                    (long) sizeof(buffer) / 4, frames);
    }
    snd_pcm_hw_params_free(hw_params);
    snd_pcm_close(handle);
    return (0);
}
  

Звук работает, но не мог бы кто-нибудь объяснить мне, почему я иногда получаю вывод, подобный следующему

 ALSA buffer size = 16384
Short write (expected 4096, wrote 9)
Short write (expected 4096, wrote 4080)
  

указывает на то, что было записано меньше кадров, чем ожидалось snd_pcm_writei ? Согласно документам ALSA, я понимаю, что должен быть получен сигнал, но я не понимаю причину и что это за сигнал.

Я также пытался уменьшить размер buffer вдвое, но результат практически тот же.

Ответ №1:

При возникновении ошибки сообщается о коротком чтении, но некоторые кадры уже были успешно записаны.

Предполагается, что вы снова вызовете ту же функцию с оставшимся буфером; если ошибка не была временной, о ней будет сообщено позже. (Этот пример кода неверен; он просто игнорирует, что оставшаяся часть буфера не была записана.)

Комментарии:

1. Если произошла ошибка, функция должна была вернуть код ошибки, не так ли? Например, -EPIPE для неполного выполнения.

2. Тогда информация о количестве записанных кадров была бы потеряна. Это поведение для write() задается POSIX.