On Mon, 6 Jan 2020 07:43:12 +0100
Alexandre Ratchov <[email protected]> wrote:
> The number of channels on the device is restricted by the
> s->opt->{pmin,pmax} variables. It is the number of channels common to
> the [0 : dev->pchan - 1] and [s->opt->pmin : s->opt->pmax] ranges.
>
> Note that there may be no overlap if s->opt->pmin >= dev->pchan, there
> are no audible channels in this case. For instance this may happen for
> a program playing on channels 2:3 of a 4-channel device which is
> dynamically replaced by a 2-channel device.
>
> In this case s->mix.cmap.nch == 0.
Is this the same as might be achieved by the following?
$ sndiod -ddd -c 0:1 -j on &
$ aucat -i /dev/random -c 2:3
If so, is the expected behavior that channels 2 and 3 play on the
subdevice's channels 0 and 1?
>
> > Index: dev.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/sndiod/dev.c,v
> > retrieving revision 1.62
> > diff -u -p -r1.62 dev.c
> > --- dev.c 21 Sep 2019 04:42:46 -0000 1.62
> > +++ dev.c 4 Jan 2020 01:01:20 -0000
> > @@ -1501,9 +1501,14 @@ dev_mmcloc(struct dev *d, unsigned int o
> > void
> > slot_initconv(struct slot *s)
> > {
> > + unsigned int target_nch;
> > struct dev *d = s->dev;
> >
> > if (s->mode & MODE_PLAY) {
> > + target_nch = d->pchan < (s->opt->pmax - s->opt->pmin + 1)
> > + ? d->pchan
> > + : (s->opt->pmax - s->opt->pmin + 1);
> > +
>
> AFAIU this works only if s->opt->pmin == 0. As s->opt->pmin >= 0, the
> number of device channels is:
>
> target_nch = (d->pchan < s->opt->pmax + 1) ?
> d->pchan - s->opt->pmin : s->opt->pmax - s->opt->pmin + 1;
I probably need to play with it some more to understand why this is; are
we trying to determine the number of channels with the same number both
in the stream and on the device? If so, should that be factored into the
logic in a different way such that we output something in my example
above? (I *think* what happens with my example and this logic is that we
decide the device has no channels which we can expand to, and we therefore
output nothing...)
> which is valid only if there are audible channels, i.e. if
> s->mix.cmap.nch > 0, so this could be handled by changing below
> condition to:
>
> if (s->opt->dup && s->mix.cmap.nch > 0)
>
> and moving the target_nch calculation inside the "true" conditional
> code block.
If I understand correctly, this also will cause the join logic to be
skipped if we have no overlap between the stream and the device.
> Last point, do you mind renaming target_nch to dev_nch ?
Of course not. :) I used this name only because I personally thought
"target" made more sense if "dev" was shorthand for the hardware device,
as opposed to a subdevice of it.
>
> > cmap_init(&s->mix.cmap,
> > s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
> > s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
> > @@ -1519,14 +1524,18 @@ slot_initconv(struct slot *s)
> > s->mix.join = 1;
> > s->mix.expand = 1;
> > if (s->opt->dup) {
> > - if (s->mix.cmap.nch > s->mix.nch)
> > - s->mix.expand = s->mix.cmap.nch / s->mix.nch;
> > - else if (s->mix.cmap.nch > 0)
> > - s->mix.join = s->mix.nch / s->mix.cmap.nch;
> > + if (target_nch > s->mix.nch)
> > + s->mix.expand = target_nch / s->mix.nch;
> > + else if (s->mix.cmap.nch > target_nch)
> > + s->mix.join = s->mix.nch / target_nch;
> > }
> > }
> >
> > if (s->mode & MODE_RECMASK) {
> > + target_nch = d->rchan < (s->opt->rmax - s->opt->rmin + 1)
> ^^^^^^^^
> d->pchan in the (s->mode & MODE_MON) case.
This requires another conditional, then?
> > + ? d->rchan
> > + : (s->opt->pmax - s->opt->pmin + 1);
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> rmin and rmax
>
Dammit, I thought I found all of those :)
> > +
> > cmap_init(&s->sub.cmap,
> > 0, ((s->mode & MODE_MON) ? d->pchan : d->rchan) - 1,
> > s->opt->rmin, s->opt->rmax,
> > @@ -1542,10 +1551,10 @@ slot_initconv(struct slot *s)
> > s->sub.join = 1;
> > s->sub.expand = 1;
> > if (s->opt->dup) {
> > - if (s->sub.cmap.nch > s->sub.nch)
> > - s->sub.join = s->sub.cmap.nch / s->sub.nch;
> > - else if (s->sub.cmap.nch > 0)
> > - s->sub.expand = s->sub.nch / s->sub.cmap.nch;
> > + if (target_nch > s->sub.nch)
> > + s->sub.join = target_nch / s->sub.nch;
> > + else if (s->sub.nch > target_nch)
> > + s->sub.expand = s->sub.nch / target_nch;
> > }