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 <t123yh@outlook.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Yunhao Tian 2021-07-27 23:52:30 +08:00 committed by Jaroslav Kysela
parent 2b9bfacca7
commit ce05208085
2 changed files with 15 additions and 4 deletions

View file

@ -122,6 +122,7 @@ struct loopback_handle {
unsigned int ctl_pollfd_count; unsigned int ctl_pollfd_count;
snd_ctl_elem_value_t *ctl_notify; snd_ctl_elem_value_t *ctl_notify;
snd_ctl_elem_value_t *ctl_rate_shift; 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_active;
snd_ctl_elem_value_t *ctl_format; snd_ctl_elem_value_t *ctl_format;
snd_ctl_elem_value_t *ctl_rate; snd_ctl_elem_value_t *ctl_rate;

View file

@ -1060,10 +1060,15 @@ static int set_rate_shift(struct loopback_handle *lhandle, double pitch)
{ {
int err; 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; 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) { if (err < 0) {
logit(LOG_CRIT, "Cannot set PCM Rate Shift element for %s: %s\n", lhandle->id, snd_strerror(err)); logit(LOG_CRIT, "Cannot set PCM Rate Shift element for %s: %s\n", lhandle->id, snd_strerror(err));
return err; return err;
@ -1204,6 +1209,8 @@ static int openctl(struct loopback_handle *lhandle, int device, int subdevice)
&lhandle->ctl_notify); &lhandle->ctl_notify);
openctl_elem(lhandle, device, subdevice, "PCM Rate Shift 100000", openctl_elem(lhandle, device, subdevice, "PCM Rate Shift 100000",
&lhandle->ctl_rate_shift); &lhandle->ctl_rate_shift);
openctl_elem(lhandle, device, subdevice, "Capture Pitch 1000000",
&lhandle->capt_pitch);
set_rate_shift(lhandle, 1); set_rate_shift(lhandle, 1);
openctl_elem(lhandle, device, subdevice, "PCM Slave Active", openctl_elem(lhandle, device, subdevice, "PCM Slave Active",
&lhandle->ctl_active); &lhandle->ctl_active);
@ -1289,6 +1296,9 @@ static int closeit(struct loopback_handle *lhandle)
if (lhandle->ctl_rate_shift) if (lhandle->ctl_rate_shift)
snd_ctl_elem_value_free(lhandle->ctl_rate_shift); snd_ctl_elem_value_free(lhandle->ctl_rate_shift);
lhandle->ctl_rate_shift = NULL; lhandle->ctl_rate_shift = NULL;
if (lhandle->capt_pitch)
snd_ctl_elem_value_free(lhandle->capt_pitch);
lhandle->capt_pitch = NULL;
if (lhandle->ctl) if (lhandle->ctl)
err = snd_ctl_close(lhandle->ctl); err = snd_ctl_close(lhandle->ctl);
lhandle->ctl = NULL; 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); snprintf(id, sizeof(id), "%s/%s", loop->play->id, loop->capt->id);
id[sizeof(id)-1] = '\0'; id[sizeof(id)-1] = '\0';
loop->id = strdup(id); 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; loop->sync = SYNC_TYPE_CAPTRATESHIFT;
if (loop->sync == SYNC_TYPE_AUTO && loop->play->ctl_rate_shift) if (loop->sync == SYNC_TYPE_AUTO && loop->play->ctl_rate_shift)
loop->sync = SYNC_TYPE_PLAYRATESHIFT; loop->sync = SYNC_TYPE_PLAYRATESHIFT;