Alsaloop: sync mode PLAYSHIFT + Loopback on playback side

Pavel Hofman pavel.hofman at ivitera.com
Fri Oct 1 10:35:34 CEST 2021


Hi,

I added support for "Playback Pitch 1000000" ctl elem to UAC2 gadget 
(not submitted to USB yet) and now I am working on alsaloop support for 
this ctl elem. The changes are simple (tested to work perfectly, patch 
to follow), but during the work I hit the following issue with playback 
Loopback "PCM Rate Shift 100000".

If the snd-aloop device is on playback side (i.e. capture from soundcard 
-> Loopback), the required sync mode is PLAYSHIFT. That means Loopback 
ctl elem "PCM Rate Shift 100000" should be controlled (by a reciprocal). 
That is simple by a patch like this:

diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
index 845ab82..619bf35 100644
--- a/alsaloop/pcmjob.c
+++ b/alsaloop/pcmjob.c
@@ -1061,7 +1061,13 @@ static int set_rate_shift(struct loopback_handle 
*lhandle, double pitch)
         int err;

         if (lhandle->ctl_rate_shift) {
-               snd_ctl_elem_value_set_integer(lhandle->ctl_rate_shift, 
0, pitch * 100000);
+               long value;
+               if (lhandle->loopback->play == lhandle)
+                       // playback => reciprocal
+                       value = 1/(pitch) * 100000;
+               else
+                       value = pitch * 100000;
+               snd_ctl_elem_value_set_integer(lhandle->ctl_rate_shift, 
0, value);
                 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);
@@ -1205,15 +1211,18 @@ static int openctl(struct loopback_handle 
*lhandle, int device, int subdevice)
         int err;

         lhandle->ctl_rate_shift = NULL;
+       // both play and capture
+       openctl_elem(lhandle, device, subdevice, "PCM Notify",
+                       &lhandle->ctl_notify);
+       openctl_elem(lhandle, device, subdevice, "PCM Rate Shift 100000",
+                       &lhandle->ctl_rate_shift);
         if (lhandle->loopback->play == lhandle) {
+               // play only
                 if (lhandle->loopback->controls)
                         goto __events;
                 return 0;
         }
-       openctl_elem(lhandle, device, subdevice, "PCM Notify",
-                       &lhandle->ctl_notify);
-       openctl_elem(lhandle, device, subdevice, "PCM Rate Shift 100000",
-                       &lhandle->ctl_rate_shift);
+       // capture only
         openctl_elem(lhandle, device, subdevice, "Capture Pitch 1000000",
                         &lhandle->capt_pitch);
         set_rate_shift(lhandle, 1);


However, IIUC how the Loopback device works, the "PCM Rate Shift 100000" 
ctl elem applicable to device=0 on playback side is that of the capture 
side, i.e. for device=1. The patch above would pick the playback-side 
device=0 ctl elem in pcmjob.c:openctl_elem. Hard-coding the device=0 -> 
device=1 is possible, but Loopback supports more devices.

Please what solution for picking the correct "PCM Rate Shift 100000" ctl 
elem for the PLAYSHIFT sync mode would you recommend?

Thanks a lot,

Pavel.


More information about the Alsa-devel mailing list