JtTest
JtTest

Reputation: 187

ALSA 'snd_pcm_writei' behavior in blocking mode

I slightly modified the demo taken from ALSA Project website in order to test it on my laptop's sound card (Intel PCH ALC3227 Analog, Ubuntu 18.04), which requires 2 channels and 16 bit integers. I also doubled the latency (1 s), switched off resampling and made the demo lasts longer. This is the code (runtime error checking not pasted for sake of synthesis)

#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);
}

Audio works but could someone explain me why I sometimes get output like the following

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

indicating that less frames than expected have been written by snd_pcm_writei? According to the ALSA docs, I understand that a signal has to be occurred, but I don't get the reason and which signal is.

I also tried to halve the buffer's size, but the result is pretty the same.

Upvotes: 0

Views: 2079

Answers (1)

CL.
CL.

Reputation: 180020

A short read is reported when an error happens, but some frames were already written successfully.

You are supposed to call the same function again, with the remaining buffer; if the error was not transient, it will be reported then. (This example code is wrong; it just ignores that the remaining part of the buffer was not written.)

Upvotes: 2

Related Questions