阻止模式下的ALSA'snd_pcm_writei'行为

时间:2019-03-15 11:59:40

标签: c linux alsa audio-player

我对ALSA Project website中的演示进行了稍微修改,以便在笔记本电脑的声卡(Intel PCH ALC3227 Analog,Ubuntu 18.04)上进行测试,该演示卡需要2个通道和16位整数。我还将延迟时间(1 s)加倍,关闭了重采样,并使演示持续了更长的时间。这是代码(为了进行综合,未粘贴运行时错误检查)

#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() & 0xff);
    snd_pcm_open(&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(&hw_params);
    snd_pcm_hw_params_current(handle, hw_params);
    snd_pcm_uframes_t bufferSize;
    snd_pcm_hw_params_get_buffer_size(hw_params, &bufferSize);
    printf("ALSA buffer size = %li\n", 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: %s\n", snd_strerror((int) frames));
            break;
        }
        if (frames > 0 && 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写入的帧少于预期?根据{{​​3}}的了解,我知道必须发生信号,但是我不知道原因和信号是什么。

我还尝试将buffer的大小减半,但结果几乎相同。

1 个答案:

答案 0 :(得分:1)

发生错误时报告了短暂的读取,但是已经成功写入了某些帧。

您应该使用剩余的缓冲区再次调用同一函数;如果错误不是暂时的,则将报告该错误。 (此示例代码是错误的;它只是忽略了缓冲区的其余部分未被写入。)