All of lore.kernel.org
 help / color / mirror / Atom feed
From: Theo Veenker <Theo.Veenker@let.uu.nl>
To: ALSA-devel <alsa-devel@lists.sourceforge.net>
Subject: assertion failure in snd_pcm_plugin_mmap_commit
Date: Wed, 24 Sep 2003 17:59:13 +0200	[thread overview]
Message-ID: <3F71BF51.80209@let.uu.nl> (raw)

[-- Attachment #1: Type: text/plain, Size: 1103 bytes --]

Hi all,

I'm trying to play sampled data on my RME Digi96/8 PAD card using
the plughw:0,0 plugin. It works (of course it does) but not with
a sampling rate that is not supported by the hardware. My test
program (see attachment) bombs out due to an assertion failure:
pcm_plugin.c:525: snd_pcm_plugin_mmap_commit: Assertion `size == 0' failed.

This is the snd_pcm_plugin_mmap_commit() routine in alsa-lib
pcm_plugin.c:

snd_pcm_sframes_t snd_pcm_plugin_mmap_commit(pcm, offset, size)
{
	.
	.
	slave_size = snd_pcm_avail_update(slave);
	while (size > 0 && slave_size > 0) {
		.
		.
		.
		size -= frames;
		slave_size -= frames;
	}
	assert(size == 0);
}

After studying this routine I decided to uncomment the assert()
because to it seems to me the assertion will always fail if
size and slave_size are not the same before entering the while
loop.

After commenting out the assert() the test program runs fine, as
far as I can tell. I presume however there is a reason for this
assertion and probably it shouldn't be removed. But in that case
I would like to know what else could be wrong.

Regards,
Theo

[-- Attachment #2: prob.c --]
[-- Type: text/plain, Size: 6676 bytes --]

/*
    prob.c

    This test program bombs out with assertion failure
      pcm_plugin.c:525: snd_pcm_plugin_mmap_commit: Assertion `size == 0' failed.
    when sample rate is set to a value not supported by the card (32000,
    48000 OK, 16000, 11025 etc not OK).

    Sound card RME Digi96/8 PAD
    ALSA 0.9.6
    plugin plughw:0,0
    
    gcc -o prob prob.c -lasound
*/

#include <stdio.h>
#include <math.h>
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#include <alsa/asoundlib.h>

#define BUFFER_TIME 		500	// [ms]

snd_pcm_t* handle;
unsigned int nchannels;
unsigned int samplerate;
unsigned int periodsize;
unsigned int buffersize;
unsigned int nperiods;

int setHWParams(snd_pcm_hw_params_t* hwparams, unsigned int nch, unsigned int rate)
{
    int err;
    snd_pcm_uframes_t val;

    // Choose all hardware parameters.
    err = snd_pcm_hw_params_any(handle, hwparams);
    if (err < 0) {
    	fprintf(stderr, "No playback configurations available: %s\n", snd_strerror(err));
	return -1;
    }

    // Set access type: interleaved
    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
    	fprintf(stderr, "Interleaved access not available: %s\n", snd_strerror(err));
	return -1;
    }

    // Set sample format: float
    err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_FLOAT);
    if (err < 0) {
	fprintf(stderr, "Float sample format not available: %s\n", snd_strerror(err));
	return -1;
    }

    // Set number of channels: nch
    nchannels = nch;
    err = snd_pcm_hw_params_set_channels(handle, hwparams, nch);
    if (err < 0) {
	fprintf(stderr, "Unsupported number of channels (%u): %s\n", nch, snd_strerror(err));
	return -1;
    }

    // Set sampling rate: rate
    samplerate = rate;
    err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0);
    if (err < 0) {
    	fprintf(stderr, "Unsupported sampling rate (%u Hz): %s\n", rate, snd_strerror(err));
	return -1;
    }
    if (rate != samplerate) {
	fprintf(stderr, "Requested sampling rate %u Hz, got %u Hz.\n", samplerate, rate);
    }
    samplerate = rate;

    // Set period size: lowest supported value
    snd_pcm_hw_params_get_period_size_min(hwparams, &val, 0);
    err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &val, 0);
    if (err < 0) {
	fprintf(stderr, "Unable to set period size to %u: %s\n", (int)val, snd_strerror(err));
	return -1;
    }
    err = snd_pcm_hw_params_get_period_size(hwparams, &val, 0);
    if (err > 0) {
	fprintf(stderr, "Unable to get period size: %s\n", snd_strerror(err));
	return -1;
    }
    periodsize = val;

    // Set number of periods: about BUFFER_TIME / periodtime
    nperiods = (BUFFER_TIME * samplerate / 1000) / periodsize;
    err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &nperiods, 0);
    if (err < 0) {
	fprintf(stderr, "Unable to set number of periods to %u: %s\n", nperiods, snd_strerror(err));
	return -1;
    }
    err = snd_pcm_hw_params_get_periods(hwparams, &nperiods, 0);
    if (err > 0) {
	fprintf(stderr, "Unable to get number of periods: %s\n", snd_strerror(err));
	return -1;
    }

    // Get buffer size.
    err = snd_pcm_hw_params_get_buffer_size(hwparams, &val);
    if (err < 0) {
	fprintf(stderr, "Unable to get buffer size: %s\n", snd_strerror(err));
	return -1;
    }
    buffersize = val;

    // Write hardware parameters to device.
    err = snd_pcm_hw_params(handle, hwparams);
    if (err < 0) {
	fprintf(stderr, "Unable to set hardware parameters: %s\n", snd_strerror(err));
	return -1;
    }

    printf("num channels: %u\n", nchannels);
    printf("sample rate:  %u\n", samplerate);
    printf("buffer size:  %u\n", buffersize);
    printf("period size:  %u\n", periodsize);
    printf("num periods:  %u\n", nperiods);

    return 0;
}

int setSWParams(snd_pcm_sw_params_t* swparams)
{
    int err;

    // Get current software parameters.
    err = snd_pcm_sw_params_current(handle, swparams);
    if (err < 0) {
	fprintf(stderr, "Unable to determine current software parameters: %s\n", snd_strerror(err));
	return -1;
    }

    // Start transfer when one complete period is available.
    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, periodsize);
    if (err < 0) {
	fprintf(stderr, "Unable to set start threshold: %s\n", snd_strerror(err));
	return -1;
    }

    // Allow transfer when at least one period is available.
    err = snd_pcm_sw_params_set_avail_min(handle, swparams, periodsize);
    if (err < 0) {
	fprintf(stderr, "Unable to set min avail: %s\n", snd_strerror(err));
	return -1;
    }

    // Align all transfers to 1 sample.
    err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
    if (err < 0) {
    	fprintf(stderr, "Unable to set transfer align: %s\n", snd_strerror(err));
	return -1;
    }

    // Write software parameters to device.
    err = snd_pcm_sw_params(handle, swparams);
    if (err < 0) {
	fprintf(stderr, "Unable to set software parameters: %s\n", snd_strerror(err));
	return -1;
    }

    return 0;
}

int openPCM(unsigned int nch, unsigned int rate)
{
    int err;
    snd_pcm_hw_params_t* hwparams;
    snd_pcm_sw_params_t* swparams;

    if ((err = snd_pcm_open(&handle, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
	fprintf(stderr, "Playback open error: %s\n", snd_strerror(err));
	return err;
    }

    snd_pcm_hw_params_malloc(&hwparams);
    err = setHWParams(hwparams, nch, rate);
    snd_pcm_hw_params_free(hwparams);
    if (err) {
    	snd_pcm_close(handle);
	return err;
    }

    snd_pcm_sw_params_malloc(&swparams);
    err = setSWParams(swparams);
    snd_pcm_sw_params_free(swparams);
    if (err) {
    	snd_pcm_close(handle);
	return err;
    }

    return 0;
}

void play(const float* data, unsigned int nframes)
{
    int xrun = 0;
    while (nframes > 0) {
    	int cnt = snd_pcm_writei(handle, data, nframes);
//	printf("cnt = %d\n", cnt);
    	if (cnt < 0) {
	    if (cnt == -EAGAIN) continue;
	    if (cnt == -EPIPE) {
	    	snd_pcm_prepare(handle);
		if (++xrun <= 1) continue;
	    }
	    fprintf(stderr, "Error playing sampled data: %s.\n", snd_strerror(cnt));
	    break;
    	}
	data += cnt * nchannels;
	nframes -= cnt;
    }
}

int main(void)
{
    double Fs, Ts, t = 0.0, amp = 0.9;
    int NS, n;
    float* s;

    if (openPCM(1, 16000) != 0) return -1;

    Fs = samplerate;
    Ts = 1.0 / Fs;
    NS = (int)(1.0 * Fs + 0.5);
    s = (float*)malloc(NS * sizeof(float));

    for (n = 0; n < NS; n++) {
        s[n] = amp * sin(2.0 * M_PI * 1000.0 * t);
	t = t + Ts;
    }

    play(s, NS);

    snd_pcm_drain(handle);
    snd_pcm_close(handle);

    return 0;
}

                 reply	other threads:[~2003-09-24 15:59 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3F71BF51.80209@let.uu.nl \
    --to=theo.veenker@let.uu.nl \
    --cc=alsa-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.