* [PATCH] alsaloop: reduce cumulative error caused by non-atomic samples calculation
@ 2020-03-09 20:29 Ruslan Bilovol
2020-03-11 8:24 ` Pavel Hofman
2020-03-11 8:45 ` Jaroslav Kysela
0 siblings, 2 replies; 3+ messages in thread
From: Ruslan Bilovol @ 2020-03-09 20:29 UTC (permalink / raw)
To: perex, alsa-devel
When doing loopback between two audio card with
same sampling frequency, I noticed slow increase
of pitch_diff.
When I changed order of get_queued_playback_samples()
vs get_queued_capture_samples(), I noticed same drift
of pitch_diff but if was decreasing this time.
This seems to be caused by non-atomic consecutive
snd_pcm_delay() invocation for playback then for
capture. snd_pcm_delay() measures delay between
read/write call and actual ADC/DAC operation.
So while we get this value for playback path in
get_queued_playback_samples(), next call to
get_queued_capture_samples() will happen a little
bit later so snd_pcm_delay() may return incorrect
value.
Be interleaving get_queued_{playback,capture}_samples()
order, we divide this small error between playback
and capture paths. I do not see any issues anymore
with one-way drift of pitch_diff.
Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com>
---
alsaloop/pcmjob.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
index b252486..1b7925a 100644
--- a/alsaloop/pcmjob.c
+++ b/alsaloop/pcmjob.c
@@ -1951,8 +1951,16 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
}
if (loop->sync != SYNC_TYPE_NONE) {
snd_pcm_sframes_t pqueued, cqueued;
- pqueued = get_queued_playback_samples(loop);
- cqueued = get_queued_capture_samples(loop);
+
+ /* Reduce cumulative error by interleaving playback vs capture reading order */
+ if (loop->total_queued_count & 1) {
+ pqueued = get_queued_playback_samples(loop);
+ cqueued = get_queued_capture_samples(loop);
+ } else {
+ cqueued = get_queued_capture_samples(loop);
+ pqueued = get_queued_playback_samples(loop);
+ }
+
if (verbose > 4)
snd_output_printf(loop->output, "%s: queued %li/%li samples\n", loop->id, pqueued, cqueued);
if (pqueued > 0)
--
1.9.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] alsaloop: reduce cumulative error caused by non-atomic samples calculation
2020-03-09 20:29 [PATCH] alsaloop: reduce cumulative error caused by non-atomic samples calculation Ruslan Bilovol
@ 2020-03-11 8:24 ` Pavel Hofman
2020-03-11 8:45 ` Jaroslav Kysela
1 sibling, 0 replies; 3+ messages in thread
From: Pavel Hofman @ 2020-03-11 8:24 UTC (permalink / raw)
To: Ruslan Bilovol, alsa-devel
Dne 09. 03. 20 v 21:29 Ruslan Bilovol napsal(a):
>
> Be interleaving get_queued_{playback,capture}_samples()
> order, we divide this small error between playback
> and capture paths. I do not see any issues anymore
> with one-way drift of pitch_diff.
Nice simple and effective solution. Thanks a lot!
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] alsaloop: reduce cumulative error caused by non-atomic samples calculation
2020-03-09 20:29 [PATCH] alsaloop: reduce cumulative error caused by non-atomic samples calculation Ruslan Bilovol
2020-03-11 8:24 ` Pavel Hofman
@ 2020-03-11 8:45 ` Jaroslav Kysela
1 sibling, 0 replies; 3+ messages in thread
From: Jaroslav Kysela @ 2020-03-11 8:45 UTC (permalink / raw)
To: Ruslan Bilovol, alsa-devel
Dne 09. 03. 20 v 21:29 Ruslan Bilovol napsal(a):
> When doing loopback between two audio card with
> same sampling frequency, I noticed slow increase
> of pitch_diff.
>
> When I changed order of get_queued_playback_samples()
> vs get_queued_capture_samples(), I noticed same drift
> of pitch_diff but if was decreasing this time.
>
> This seems to be caused by non-atomic consecutive
> snd_pcm_delay() invocation for playback then for
> capture. snd_pcm_delay() measures delay between
> read/write call and actual ADC/DAC operation.
>
> So while we get this value for playback path in
> get_queued_playback_samples(), next call to
> get_queued_capture_samples() will happen a little
> bit later so snd_pcm_delay() may return incorrect
> value.
>
> Be interleaving get_queued_{playback,capture}_samples()
> order, we divide this small error between playback
> and capture paths. I do not see any issues anymore
> with one-way drift of pitch_diff.
>
> Signed-off-by: Ruslan Bilovol <ruslan.bilovol@gmail.com>
Nice catch and implementation. Applied.
Thank you,
Jaroslav
> ---
> alsaloop/pcmjob.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
> index b252486..1b7925a 100644
> --- a/alsaloop/pcmjob.c
> +++ b/alsaloop/pcmjob.c
> @@ -1951,8 +1951,16 @@ int pcmjob_pollfds_handle(struct loopback *loop, struct pollfd *fds)
> }
> if (loop->sync != SYNC_TYPE_NONE) {
> snd_pcm_sframes_t pqueued, cqueued;
> - pqueued = get_queued_playback_samples(loop);
> - cqueued = get_queued_capture_samples(loop);
> +
> + /* Reduce cumulative error by interleaving playback vs capture reading order */
> + if (loop->total_queued_count & 1) {
> + pqueued = get_queued_playback_samples(loop);
> + cqueued = get_queued_capture_samples(loop);
> + } else {
> + cqueued = get_queued_capture_samples(loop);
> + pqueued = get_queued_playback_samples(loop);
> + }
> +
> if (verbose > 4)
> snd_output_printf(loop->output, "%s: queued %li/%li samples\n", loop->id, pqueued, cqueued);
> if (pqueued > 0)
>
--
Jaroslav Kysela <perex@perex.cz>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-03-11 8:46 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-09 20:29 [PATCH] alsaloop: reduce cumulative error caused by non-atomic samples calculation Ruslan Bilovol
2020-03-11 8:24 ` Pavel Hofman
2020-03-11 8:45 ` Jaroslav Kysela
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.