"-C,--cdevice capture device\n"
"-X,--pctl playback ctl device\n"
"-Y,--cctl capture ctl device\n"
+"-x,--prateshift playback 'PCM Rate Shift 100000' ascii ctl name\n"
"-l,--latency requested latency in frames\n"
"-t,--tlatency requested latency in usec (1/1000000sec)\n"
"-f,--format sample format\n"
{"cdevice", 1, NULL, 'C'},
{"pctl", 1, NULL, 'X'},
{"cctl", 1, NULL, 'Y'},
+ {"prateshift", 1, NULL, 'x'},
{"latency", 1, NULL, 'l'},
{"tlatency", 1, NULL, 't'},
{"format", 1, NULL, 'f'},
char *arg_cdevice = NULL;
char *arg_pctl = NULL;
char *arg_cctl = NULL;
+ char *arg_prateshift = NULL;
unsigned int arg_latency_req = 0;
unsigned int arg_latency_reqtime = 10000;
snd_pcm_format_t arg_format = SND_PCM_FORMAT_S16_LE;
while (1) {
int c;
if ((c = getopt_long(argc, argv,
- "hdg:P:C:X:Y:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:UW:z",
+ "hdg:P:C:X:Y:x:l:t:F:f:c:r:s:benvA:S:a:m:T:O:w:UW:z",
long_option, NULL)) < 0)
break;
switch (c) {
case 'Y':
arg_cctl = strdup(optarg);
break;
+ case 'x':
+ arg_prateshift = strdup(optarg);
+ break;
case 'l':
err = atoi(optarg);
arg_latency_req = err >= 4 ? err : 4;
logit(LOG_CRIT, "Unable to add ossmixer controls.\n");
exit(EXIT_FAILURE);
}
+ if (arg_prateshift)
+ play->prateshift_name = arg_prateshift;
+
#ifdef USE_SAMPLERATE
loop->src_enable = arg_samplerate > 0;
if (loop->src_enable)
#endif
}
else if (loop->sync == SYNC_TYPE_PLAYRATESHIFT) {
- set_rate_shift(loop->play, pitch);
+ // pitch is capture-based, playback side requires reciprocal
+ set_rate_shift(loop->play, 1 / pitch);
#ifdef USE_SAMPLERATE
if (loop->use_samplerate) {
loop->src_data.src_ratio =
return snd_ctl_elem_value_get_integer(lhandle->ctl_channels, 0);
}
-static void openctl_elem(struct loopback_handle *lhandle,
- int device, int subdevice,
- const char *name,
- snd_ctl_elem_value_t **elem)
+static int openctl_elem_id(struct loopback_handle *lhandle, snd_ctl_elem_id_t *id,
+ snd_ctl_elem_value_t **elem)
{
int err;
if (snd_ctl_elem_value_malloc(elem) < 0) {
*elem = NULL;
+ return -ENOMEM;
+ }
+ snd_ctl_elem_value_set_id(*elem, id);
+ snd_ctl_elem_value_set_interface(*elem, SND_CTL_ELEM_IFACE_PCM);
+ err = snd_ctl_elem_read(lhandle->ctl, *elem);
+ if (err < 0) {
+ snd_ctl_elem_value_free(*elem);
+ *elem = NULL;
+ return err;
} else {
- snd_ctl_elem_value_set_interface(*elem,
- SND_CTL_ELEM_IFACE_PCM);
- snd_ctl_elem_value_set_device(*elem, device);
- snd_ctl_elem_value_set_subdevice(*elem, subdevice);
- snd_ctl_elem_value_set_name(*elem, name);
- err = snd_ctl_elem_read(lhandle->ctl, *elem);
- if (err < 0) {
- snd_ctl_elem_value_free(*elem);
- *elem = NULL;
- } else {
- if (verbose)
- snd_output_printf(lhandle->loopback->output,
- "Opened PCM element %s of %s, device %d, subdevice %d\n",
- name, snd_ctl_name(lhandle->ctl), device, subdevice);
- }
+ snd_output_printf(lhandle->loopback->output,
+ "Opened PCM element %s of %s, device %d, subdevice %d\n",
+ snd_ctl_elem_id_get_name(id), snd_ctl_name(lhandle->ctl),
+ snd_ctl_elem_id_get_device(id),
+ snd_ctl_elem_id_get_subdevice(id));
+ return 0;
+ }
+}
+
+static int openctl_elem(struct loopback_handle *lhandle,
+ int device, int subdevice,
+ const char *name,
+ snd_ctl_elem_value_t **elem)
+{
+ snd_ctl_elem_id_t *id;
+
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_id_set_device(id, device);
+ snd_ctl_elem_id_set_subdevice(id, subdevice);
+ snd_ctl_elem_id_set_name(id, name);
+ return openctl_elem_id(lhandle, id, elem);
+}
+
+static int openctl_elem_ascii(struct loopback_handle *lhandle, char *ascii_name,
+ snd_ctl_elem_value_t **elem)
+{
+ snd_ctl_elem_id_t *id;
+
+ snd_ctl_elem_id_alloca(&id);
+ if (snd_ctl_ascii_elem_id_parse(id, ascii_name)) {
+ fprintf(stderr, "Wrong control identifier: %s\n", ascii_name);
+ return -EINVAL;
}
+ return openctl_elem_id(lhandle, id, elem);
}
static int openctl(struct loopback_handle *lhandle, int device, int subdevice)
lhandle->ctl_rate_shift = NULL;
if (lhandle->loopback->play == lhandle) {
+ // play only
+ if (lhandle->prateshift_name) {
+ err = openctl_elem_ascii(lhandle, lhandle->prateshift_name,
+ &lhandle->ctl_rate_shift);
+ if (err < 0) {
+ logit(LOG_CRIT, "Unable to open playback PCM Rate Shift elem '%s'.\n",
+ lhandle->prateshift_name);
+ exit(EXIT_FAILURE);
+ }
+ }
if (lhandle->loopback->controls)
goto __events;
return 0;
}
+ // capture only
openctl_elem(lhandle, device, subdevice, "PCM Notify",
&lhandle->ctl_notify);
openctl_elem(lhandle, device, subdevice, "PCM Rate Shift 100000",