From: Clemens Ladisch <clemens@ladisch.de>
To: ALSA Development Mailing List <alsa-devel@alsa-project.org>
Subject: Re: Misusing snd_pcm_avail_update()
Date: Tue, 20 Jan 2009 09:29:37 +0100 [thread overview]
Message-ID: <49758B71.8090605@ladisch.de> (raw)
In-Reply-To: <20090120025727.GA30499@tango.0pointer.de>
Lennart Poettering wrote:
> Currently in the 'glitch-free' logic of PulseAudio I use
> snd_pcm_avail_update() to estimate how I need to program my system
> timers for the next wake-up for the next buffer fill-up. For that I
> assume that the current fill level of the hardware buffer is the
> hardware buffer size minus what s_p_a_u() returns. I then convert that
> fill level from sample units to time units, and fix it up by the
> deviation of the sound card time from the system time. Finally I
> substract some extra margin just to make sure.
>
> This I assumed would tell me how much time will pass until an underrun
> happens if I don't write anything.
>
> Mostly this logic works fine. But on some setups and cases it
> doesn't. ALSA will signal an underrun much much earlier than what I
> estimated like this.
>
> I am now wondering why? One possibility of course is that s_p_a_u() is
> not reliable, due to driver issues (there were problems in the HDA
> driver about this, right?).
Some hardware doesn't realiably tell the current position in the buffer.
> Also, s_p_a_u() might simply lag behind quite a bit,
In the case above, when a driver detects that the hardware position is
incorrect, it uses the last known value. Usually, this isn't off more
than a few samples.
There is hardware that does not allow reading the current position.
With such a device, the position you get is computed at every interrupt,
i.e., you get the last period boundary.
> or -- what I think is most likely -- because samples are
> popped in larger blocks form the hw playback buffer we reach the
> underrun much earlier than expected.
This happens, too. Many PCI devices read PCM data in blocks of 32 or
64 bytes. Many wavetable chips (Emu10k1, DS-1, CS46xx) read sample data
in blocks of 256 or 512 samples. USB transfers blocks of at least 1 ms
length, but often a multiple of that to reduce the number of USB
completion interrupts.
After choosing hardware parameters, you can call
snd_pcm_hw_params_is_block_transfer() to determine if the device
transfers samples in comparatively large blocks. (The wavetable and
USB drivers set this flag.) There is currently no function to determine
the block size.
In the worst case, the current position isn't guaranteed to be more
accurate than the last period boundary.
> I do acknowledge that the way i use s_p_a_u() is probably a misuse of
> the API.
The API was primarily designed for applications that are woken up at
period boundaries. Using s_p_a_u() to bypass the synchronization
implied by period interrupts _is_ possible, but it cannot give you more
precision than the hardware supports.
> Now, considering all this I'd like to ask for a new API function that
> tells me how much time I really have before the next underrun.
Well, you could make the "some extra margin" above larger than one period.
Or monitor the device over some time and see what the smallest increment
is you get in successive s_p_a_u() return values.
Best regards,
Clemens
next prev parent reply other threads:[~2009-01-20 8:29 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-20 2:57 Misusing snd_pcm_avail_update() Lennart Poettering
2009-01-20 8:29 ` Clemens Ladisch [this message]
2009-01-20 8:32 ` Clemens Ladisch
2009-01-20 14:26 ` Lennart Poettering
2009-01-20 18:48 ` Clemens Ladisch
2009-01-20 20:29 ` Lennart Poettering
2009-01-21 0:39 ` Takashi Iwai
2009-01-22 22:20 ` Lennart Poettering
2009-01-23 17:13 ` Takashi Iwai
2009-01-23 17:56 ` Clemens Ladisch
2009-01-24 9:52 ` Takashi Iwai
2009-01-28 18:30 ` Lennart Poettering
2009-01-29 8:28 ` Clemens Ladisch
2009-01-28 18:26 ` Lennart Poettering
2009-01-23 18:49 ` James Courtier-Dutton
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=49758B71.8090605@ladisch.de \
--to=clemens@ladisch.de \
--cc=alsa-devel@alsa-project.org \
/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.