From ce05208085fe09a53113a99cf709459bfa2d37d4 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Tue, 27 Jul 2021 23:52:30 +0800 Subject: [PATCH] alsaloop: Support "Capture Pitch 1000000" rate shift In Linux 5.14, a new feedback mechanism for USB Audio Gadget is introduced (commit e89bb428), along with a new control element "Capture Pitch 1000000". This patch adds support for this feature. Note that this property seems to be the reverse of PCM Rate Shift, so we have to take reciprocal of pitch. Signed-off-by: Yunhao Tian Signed-off-by: Jaroslav Kysela --- alsaloop/alsaloop.h | 1 + alsaloop/pcmjob.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/alsaloop/alsaloop.h b/alsaloop/alsaloop.h index c4aa618..1dbcefe 100644 --- a/alsaloop/alsaloop.h +++ b/alsaloop/alsaloop.h @@ -122,6 +122,7 @@ struct loopback_handle { unsigned int ctl_pollfd_count; snd_ctl_elem_value_t *ctl_notify; snd_ctl_elem_value_t *ctl_rate_shift; + snd_ctl_elem_value_t *capt_pitch; snd_ctl_elem_value_t *ctl_active; snd_ctl_elem_value_t *ctl_format; snd_ctl_elem_value_t *ctl_rate; diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c index 4efdd63..8b72af4 100644 --- a/alsaloop/pcmjob.c +++ b/alsaloop/pcmjob.c @@ -1060,10 +1060,15 @@ static int set_rate_shift(struct loopback_handle *lhandle, double pitch) { int err; - if (lhandle->ctl_rate_shift == NULL) + if (lhandle->ctl_rate_shift) { + snd_ctl_elem_value_set_integer(lhandle->ctl_rate_shift, 0, pitch * 100000); + err = snd_ctl_elem_write(lhandle->ctl, lhandle->ctl_rate_shift); + } else if (lhandle->capt_pitch) { + snd_ctl_elem_value_set_integer(lhandle->capt_pitch, 0, (1 / pitch) * 1000000); + err = snd_ctl_elem_write(lhandle->ctl, lhandle->capt_pitch); + } else { return 0; - snd_ctl_elem_value_set_integer(lhandle->ctl_rate_shift, 0, pitch * 100000); - err = snd_ctl_elem_write(lhandle->ctl, lhandle->ctl_rate_shift); + } if (err < 0) { logit(LOG_CRIT, "Cannot set PCM Rate Shift element for %s: %s\n", lhandle->id, snd_strerror(err)); return err; @@ -1204,6 +1209,8 @@ static int openctl(struct loopback_handle *lhandle, int device, int subdevice) &lhandle->ctl_notify); openctl_elem(lhandle, device, subdevice, "PCM Rate Shift 100000", &lhandle->ctl_rate_shift); + openctl_elem(lhandle, device, subdevice, "Capture Pitch 1000000", + &lhandle->capt_pitch); set_rate_shift(lhandle, 1); openctl_elem(lhandle, device, subdevice, "PCM Slave Active", &lhandle->ctl_active); @@ -1289,6 +1296,9 @@ static int closeit(struct loopback_handle *lhandle) if (lhandle->ctl_rate_shift) snd_ctl_elem_value_free(lhandle->ctl_rate_shift); lhandle->ctl_rate_shift = NULL; + if (lhandle->capt_pitch) + snd_ctl_elem_value_free(lhandle->capt_pitch); + lhandle->capt_pitch = NULL; if (lhandle->ctl) err = snd_ctl_close(lhandle->ctl); lhandle->ctl = NULL; @@ -1334,7 +1344,7 @@ int pcmjob_init(struct loopback *loop) snprintf(id, sizeof(id), "%s/%s", loop->play->id, loop->capt->id); id[sizeof(id)-1] = '\0'; loop->id = strdup(id); - if (loop->sync == SYNC_TYPE_AUTO && loop->capt->ctl_rate_shift) + if (loop->sync == SYNC_TYPE_AUTO && (loop->capt->ctl_rate_shift || loop->capt->capt_pitch)) loop->sync = SYNC_TYPE_CAPTRATESHIFT; if (loop->sync == SYNC_TYPE_AUTO && loop->play->ctl_rate_shift) loop->sync = SYNC_TYPE_PLAYRATESHIFT;