[alsa-devel] Audio passthrough on Pandaboard using ALSA API

Vadim Izmalkov Vadimi at wavesglobal.com
Fri Feb 28 09:47:27 CET 2014


Hello

I created simple application that makes audio pass-through (from analog input to analog output),

After 2-10 seconds get error like:
AlsaPassthrough: pcm.c:693: snd_pcm_close: Assertion `pcm' failed.
or
write to audio interface failed (Broken pipe)

Seems I have problem with buffer size/time or somethink like that.
Parameters used:
Buffer - 100 ms / 4800 frames / 19200 bytes
Period - 10 ms / 480 frames / 1920 bytes

Buffer length used 19200 bytes.
char buffer[19200];

Write/read function used as follow
snd_pcm_readi(pcm, buffer, frames);
snd_pcm_writei(pcm, buffer, frames);

Have somebody any suggestion?





Segments of the code you can find bellow.

Alsamixer settings:
amixer cset name='Analog Left Capture Route' 'Headset Mic'
amixer cset name='Analog Right Capture Route' 'Headset Mic'
amixer cset name='MUX_UL00' 'AMic0'
amixer cset name='MUX_UL01' 'AMic1'
amixer cset name='Headset Left Playback' 'HS DAC'
amixer cset name='Headset Right Playback' 'HS DAC'
amixer cset name='Headset Playback Volume' 100
amixer cset name='DL1 Media' 120

Structure for the devices:
typedef struct
{
    char *deviceName;

    snd_pcm_t *pcm;
    snd_pcm_hw_params_t *hwParams;
    snd_pcm_stream_t stream;
    snd_pcm_access_t access;
    snd_pcm_format_t format;
    snd_pcm_uframes_t frames;

    int mode;

    unsigned int sampleRate;

    unsigned int bufferTime;
    unsigned int periodTime;
    unsigned int channels;

} pcmDevice_t;

Parameters for capture:
pcmDevice_t* initRecordDevice()
{
    pcmDevice_t *device;

    device = malloc(sizeof(pcmDevice_t));

    device->deviceName = strdup("plughw:0,0");

    device->stream = SND_PCM_STREAM_CAPTURE;
    device->access = SND_PCM_ACCESS_RW_INTERLEAVED;
    device->format = SND_PCM_FORMAT_S16_LE;
    device->mode = 0; //SND_PCM_ASYNC; //SND_PCM_NONBLOCK;

    device->sampleRate = 48000;
    device->bufferTime = 100 * 1000; // 100 ms
    device->periodTime = 10 * 1000; // 20ms
    device->channels = 2;

    return device;
}

Parameters for playback:
pcmDevice_t* initPlaybackDevice()
{
    pcmDevice_t *device;

    device = malloc(sizeof(pcmDevice_t));

    device->deviceName = strdup("plughw:0,0");

    device->stream = SND_PCM_STREAM_PLAYBACK;
    device->access = SND_PCM_ACCESS_RW_INTERLEAVED;
    device->format = SND_PCM_FORMAT_S16_LE;
    device->mode = 0; //SND_PCM_ASYNC; //SND_PCM_NONBLOCK;

    device->sampleRate = 48000;
    device->bufferTime = 100 * 1000; // 100 ms
    device->periodTime = 10 * 1000; // 20ms
    device->channels = 2;

    return device;
}

Setup devices:
int setupDevice(pcmDevice_t *device)
{
    int err;
    /* Open PCM. The last parameter of this function is the mode. */
    /* If this is set to 0, the standard mode is used. Possible   */
    /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC.       */
    /* If SND_PCM_NONBLOCK is used, read / write access to the    */
    /* PCM device will return immediately. If SND_PCM_ASYNC is    */
    /* specified, SIGIO will be emitted whenever a period has     */
    /* been completely processed by the soundcard.                */
    if ((err = snd_pcm_open(&device->pcm, device->deviceName, device->stream, device->mode)) < 0) {
        fprintf (stderr, "cannot open audio device %s (%s)\n", device->deviceName, snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_malloc (&device->hwParams)) < 0) {
        fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_any (device->pcm, device->hwParams)) < 0) {
        fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_access (device->pcm, device->hwParams, device->access)) < 0) {
        fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_format (device->pcm, device->hwParams, device->format)) < 0) {
        fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_buffer_time_near (device->pcm, device->hwParams, &device->bufferTime, NULL)) < 0) {
        fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err));
        exit (1);
    } else {
        /* Set buffer size (in frames). The resulting latency is given by */
        /* latency = periodsize * periods / (rate * bytes_per_frame)      */
        snd_pcm_hw_params_get_buffer_size(device->hwParams, &device->frames);
    }

    if ((err = snd_pcm_hw_params_set_period_time_near (device->pcm, device->hwParams, &device->periodTime, NULL)) < 0) {
        fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_rate_near (device->pcm, device->hwParams, &device->sampleRate, NULL)) < 0) {
        fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_channels (device->pcm, device->hwParams, device->channels)) < 0) {
        fprintf (stderr, "cannot set channel count (%s)\n",     snd_strerror (err));
        exit (1);
    }

    /* Apply HW parameter settings to */
    /* PCM device and prepare device  */
    if ((err = snd_pcm_hw_params (device->pcm, device->hwParams)) < 0) {
        fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err));
        exit (1);
    }

    snd_pcm_hw_params_free (device->hwParams);

    if ((err = snd_pcm_prepare (device->pcm)) < 0) {
        fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err));
        exit (1);
    }

    return 0;
}

Main:
main (int argc, char *argv[])
{
    int i;
    int err;

    char buf[4800*4];

    snd_pcm_t *capture_handle;
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_uframes_t frames;

    pcmDevice_t *pcmRecord;
    pcmDevice_t *pcmPlayback;

    pcmRecord    = initRecordDevice();
    pcmPlayback = initPlaybackDevice();

    printf("\n----------- RECORD DEVICE -----------\n");
    setupDevice(pcmRecord);
    showConfig(pcmRecord);

    printf("\n---------- PLAYBACK DEVICE ----------\n");
    setupDevice(pcmPlayback);
    showConfig(pcmPlayback);

    for (i = 0; i < 100; ++i) {
        /* Read num_frames frames from the PCM device  */
        /* pointed to by pcm_handle to buffer capdata. */
        /* Returns the number of frames actually read. */
        //if((err = snd_pcm_readi (pcmRecord->pcm, buf, pcmRecord->frames)) != pcmRecord->frames) {
        if((err = snd_pcm_readi (pcmRecord->pcm, buf, 480)) != 480) {
            fprintf (stderr, "read from audio interface failed (%s)\n", snd_strerror (err));
            exit (1);
        }

        /* Write num_frames frames from buffer data to    */
        /* the PCM device pointed to by pcm_handle.       */
        /* Returns the number of frames actually written. */
        if((err = snd_pcm_writei (pcmPlayback->pcm, buf, pcmRecord->frames)) != pcmRecord->frames) {
            fprintf (stderr, "write to audio interface failed (%s)\n", snd_strerror (err));
            exit (1);
        }
    }

    snd_pcm_close (capture_handle);
    exit (0);

}?


Best


More information about the Alsa-devel mailing list