[alsa-devel] Non-blocking snd_pcm_drain?
Hello, I'm new to the ALSA API and I have a question:
I've developed a small program that plays audio from a buffer using snd_pcm_writei and snd_pcm_drain but I noticed that the snd_pcm_drain call blocks until the buffer is completely drained. Is there any way to drain the buffer without a block? I've tried calling snd_pcm_nonblock(handle, 1) before the call to snd_pcm_drain but it does not work.
The context is that this is an application that plays a particular WAV sound repeatedly, so I don't want to wait until the sound is played completely before it is played again.
What would be the best way to achieve this?
Thanks,
Daniel Sanz wrote:
I noticed that the snd_pcm_drain call blocks until the buffer is completely drained. Is there any way to drain the buffer without a block?
Try calling snd_pcm_nonblock(handle, 1).
I've tried calling snd_pcm_nonblock(handle, 1) before the call to snd_pcm_drain but it does not work.
How so?
The context is that this is an application that plays a particular WAV sound repeatedly, so I don't want to wait until the sound is played completely before it is played again.
Then why do you drain at all? Just write the new data into the buffer.
Regards, Clemens
If I don't drain the buffer, then I don't hear the entire sound, even though I think I'm writing correctly all the frames.
Here's the relevant code (playback of 2 seconds of a sound file represented by file pointer "fp"):
snd_pcm_hw_params_get_period_size(params, &frames, 0); buffer_size = frames * channels * 2; buffer = (char*)malloc(buffer_size);
snd_pcm_hw_params_get_period_time(params, &period_time, NULL);
for (loops = (2 * 1000000) / period_time; loops > 0; loops--) { fread(buffer, sizeof(char), buffer_size, fp);
if ((err = snd_pcm_writei(handle, buffer, frames)) == -EPIPE) { printf("XRUN.\n"); snd_pcm_prepare(handle); } else if (err < 0) { printf("ERROR. Can't write to the device. %s\n", snd_strerror(err)); } }
snd_pcm_close(handle);
Thanks,
On Sat, Nov 10, 2012 at 6:28 PM, Clemens Ladisch clemens@ladisch.de wrote:
Daniel Sanz wrote:
I noticed that the snd_pcm_drain call blocks until the buffer is completely drained. Is there any way to drain the buffer without a block?
Try calling snd_pcm_nonblock(handle, 1).
I've tried calling snd_pcm_nonblock(handle, 1) before the call to snd_pcm_drain but it does not work.
How so?
The context is that this is an application that plays a particular WAV sound repeatedly, so I don't want to wait until the sound is played completely before it is played again.
Then why do you drain at all? Just write the new data into the buffer.
Regards, Clemens
Removing the last line, snd_pcm_close(handle), plays the entire sound, but I don't think it is a good solution.
It is like there is somewhere a huge latency between the moment I call snd_pcm_writei and the moment I hear sound, but I don't know what's causing this. I've even tried reducing the period size to 32 frames or padding the last buffer with zeros, but no luck either.
I'm out of ideas.
On Sat, Nov 10, 2012 at 6:57 PM, Daniel Sanz daniellsanz2@gmail.com wrote:
If I don't drain the buffer, then I don't hear the entire sound, even though I think I'm writing correctly all the frames.
Here's the relevant code (playback of 2 seconds of a sound file represented by file pointer "fp"):
snd_pcm_hw_params_get_period_size(params, &frames, 0); buffer_size = frames * channels * 2; buffer = (char*)malloc(buffer_size); snd_pcm_hw_params_get_period_time(params, &period_time, NULL); for (loops = (2 * 1000000) / period_time; loops > 0; loops--) { fread(buffer, sizeof(char), buffer_size, fp); if ((err = snd_pcm_writei(handle, buffer, frames)) == -EPIPE) { printf("XRUN.\n"); snd_pcm_prepare(handle); } else if (err < 0) { printf("ERROR. Can't write to the device. %s\n", snd_strerror(err)); } } snd_pcm_close(handle);
Thanks,
On Sat, Nov 10, 2012 at 6:28 PM, Clemens Ladisch clemens@ladisch.de wrote:
Daniel Sanz wrote:
I noticed that the snd_pcm_drain call blocks until the buffer is completely drained. Is there any way to drain the buffer without a block?
Try calling snd_pcm_nonblock(handle, 1).
I've tried calling snd_pcm_nonblock(handle, 1) before the call to snd_pcm_drain but it does not work.
How so?
The context is that this is an application that plays a particular WAV sound repeatedly, so I don't want to wait until the sound is played completely before it is played again.
Then why do you drain at all? Just write the new data into the buffer.
Regards, Clemens
participants (2)
-
Clemens Ladisch
-
Daniel Sanz