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@xxxxxxxxx> --- 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