Message ID | 1583785794-5173-1-git-send-email-ruslan.bilovol@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | alsaloop: reduce cumulative error caused by non-atomic samples calculation | expand |
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!
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) >
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)
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(-)