Re: ksh: documented substitution behavior contradicts actual behavior

2022-10-16 Thread Kastus Shchuka
On Sun, Oct 16, 2022 at 11:48:35AM +0100, cho...@jtan.com wrote:
> Kastus Shchuka writes:
> > On Sat, Oct 15, 2022 at 11:42:17PM -0300, Lucas de Sena wrote:
> > > Hi,
> > > 
> > > After trying to split a string into fields delimited with colons and
> > > spaces, I found this bug in how ksh(1) does substitution.  The actual
> > > behavior contradicts what other shells like bash and mksh do and also
> > > contradicts its own manual.
> > > 
> > > Running the following on other shells (say, bash) prints "/foo/bar/".
> > > This command splits the string " foo : bar " into two fields: "foo"
> > > and "bar", considering colon and space as delimiters.
> > > 
> > >   echo " foo : bar " | {
> > >   IFS=": "
> > >   read -r a b
> > >   printf -- "/%s/%s/\n" "$a" "$b"
> > >   }
> > > 
> > > However, running the same command in OpenBSD ksh(1) (or sh(1)) splits
> > > the string into "foo" and ": bar".
> >
> > This is because the last parameter (b) is a concatenation of two fields. 
> > Parsing 
> > is done properly if you add c to the read command:
> >
> > + echo  foo : bar 
> > + IFS=: 
> > + read -r a b c
> > + printf -- /%s/%s/%s/\n foo  bar
> > /foo//bar/
> >
> >
> > > 
> > > The manual ksh(1) provides the following, similar example:
> > > 
> > > > Example: If IFS is set to “:”, and VAR is set to
> > > > “A:B::D”, the substitution for $VAR
> > > > results in four fields: ‘A’, ‘B’, ‘’ (an empty field), and ‘D’.
> > > > Note that if the IFS parameter is set to the NULL string, no field
> > > > splitting is done; if the parameter is unset, the default value of
> > > > space, tab, and newline is used.
> > > 
> > > Let's try it:
> > > 
> > >   echo " A :  B::D" | {
> > >   IFS=" :"
> > >   read -r arg1 arg2 arg3 arg4
> > >   printf -- '1st: "%s"\n' "$arg1"
> > >   printf -- '2nd: "%s"\n' "$arg2"
> > >   printf -- '3rd: "%s"\n' "$arg3"
> > >   printf -- '4th: "%s"\n' "$arg4"
> > >   }
> > > 
> > > bash(1) splits the line into the following fields:
> > > 
> > >   1st: "A"
> > >   2nd: "B"
> > >   3rd: ""
> > >   4th: "D"
> > > 
> > > This is actually the expected output, as described in the manual.
> > > 
> > > However, running the same command in OpenBSD ksh, prints this:
> > > 
> > >   1st: "A"
> > >   2nd: ""
> > >   3rd: "B"
> > >   4th: ":D"
> > > 
> > > A completelly different thing.
> > > The same occurs with OpenBSD sh(1).
> >
> > What you observe is the result of the next paragraph in the man page
> > after the example you quoted:
> >
> >  Also, note that the field splitting applies only to the immediate 
> > result
> >  of the substitution.  Using the previous example, the substitution for
> >  $VAR:E results in the fields: `A', `B', `', and `D:E', not `A', `B', 
> > `',
> >  `D', and `E'.  This behavior is POSIX compliant, but incompatible with
> >  some other shell implementations which do field splitting on the word
> >  which contained the substitution or use IFS as a general whitespace
> >  delimiter.
> 
> Actually you need to look further into the manual since the word
> splitting is performed not by parameter substitution but by read:
> 
>  Reads a line of input from the standard input, separates the line
>  into fields using the IFS parameter (see Substitution above), and
>  assigns each field to the specified parameters.
> 
> This is why adding an extra variable to read above (and here) makes
> it capture the remainder of the string.
> 
> For example:
> 
>   $ alias dump="perl -MData::Dumper -e 'print Dumper @ARGV'"
>   $ dump a b c
>   $VAR1 = 'a';
>   $VAR2 = 'b';
>   $VAR3 = 'c';
> 
>   $ ( IFS=:; dump $PATH )
>   $VAR1 = '/bin';
>   $VAR2 = '/sbin';
>   $VAR3 = '/usr/bin';
>   $VAR4 = '/usr/sbin';
>   $VAR5 = '/usr/X11R6/bin';
>   $VAR6 = '/usr/local/bin';
>   $VAR7 = '/usr/local/sbin';
>   $VAR8 = '/usr/games';
> 
> So given $X:
> 
>   $ X=' A :  B::D'
> 
> Parameter substitution:
> 
>   $ ( IFS=' :'; dump $X )
>   $VAR1 = 'A';
>   $VAR2 = 'B';
>   $VAR3 = '';
>   $VAR4 = 'D';
> 
> Similarly:
> 
>   $ fn() { dump "$@" ); fn $X
>   $VAR1 = 'A';
>   $VAR2 = ':';
>   $VAR3 = 'B::D';
> 
>   $ fn() { dump "$@"; }; ( IFS=' :'; fn $X )
>   $VAR1 = 'A';
>   $VAR2 = 'B';
>   $VAR3 = '';
>   $VAR4 = 'D';
> 
> read substitution:
> 
>   $ echo "$X" | ( IFS=' :'; read a1 a2 a3; dump "$a1" "$a2" "$a3" )
>   $VAR1 = 'A';
>   $VAR2 = '';
>   $VAR3 = 'B::D';
> 
>   $ echo "$X" | ( IFS=' :'; read a1 a2 a3 a4; dump "$a1" "$a2" "$a3" 
> "$a4" )
>   $VAR1 = 'A';
>   $VAR2 = '';
>   $VAR3 = 'B';
>   $VAR4 = ':D';
> 
>   $ echo "$X" | ( IFS=' :'; read a1 a2 a3 a4 a5; dump "$a1" "$a2" "$a3" 
> "$a4" "$a5" )
>   $VAR1 = 'A';
>   $VAR2 = '';
>   $VAR3 = 'B';
>   $VAR4 = '';
>   $VAR5 = 'D';
> 
> It does look like 

Re: sndio and bit perfect playback

2022-10-16 Thread sub
Hi Misc,

As the OP, i hope you will excuse the top-posting.
Thanks for all the feedback and exciting discussions.

Context/Backstory.. i was using that laptop as its the only system i have with 
a remaining working cd/dvd device, which just happened to have OpenBSD 
installed. 

The 'cdio cdrip' tooling was awesome and just worked, adding a few missing 
physical_2_digital albumns to my collection. (if only cdio cddbinfo was fully 
functional). this allows me to rip a cd, and listen back to it.

So with that i guess i could run sndio with flags matching to cd bit rate of 
44100k. this will be bit-perfect for my purpose, and make the dac light up 
green.
I'll test this later this week.



-SUB




--- Original Message ---
On Sunday, October 16th, 2022 at 4:22 PM, Alexandre Ratchov  
wrote:

> 
> Sure, there is measurable aliasing. My questioning is: is it audible
> in 99% of the cases?
> 
> Remains the question, how to handle the 1% remaining. For now,
> resampling off-line is the least annoying, IMHO.
> 
> AFAIK, sample rate changes in the kernel are OK, at least in uaudio
> driver.
> 
> Now it's all in sndiod (or how to bypass sndiod to get bit-perfect
> audio)



Re: ksh: documented substitution behavior contradicts actual behavior

2022-10-16 Thread chohag
Kastus Shchuka writes:
> On Sat, Oct 15, 2022 at 11:42:17PM -0300, Lucas de Sena wrote:
> > Hi,
> > 
> > After trying to split a string into fields delimited with colons and
> > spaces, I found this bug in how ksh(1) does substitution.  The actual
> > behavior contradicts what other shells like bash and mksh do and also
> > contradicts its own manual.
> > 
> > Running the following on other shells (say, bash) prints "/foo/bar/".
> > This command splits the string " foo : bar " into two fields: "foo"
> > and "bar", considering colon and space as delimiters.
> > 
> > echo " foo : bar " | {
> > IFS=": "
> > read -r a b
> > printf -- "/%s/%s/\n" "$a" "$b"
> > }
> > 
> > However, running the same command in OpenBSD ksh(1) (or sh(1)) splits
> > the string into "foo" and ": bar".
>
> This is because the last parameter (b) is a concatenation of two fields. 
> Parsing 
> is done properly if you add c to the read command:
>
> + echo  foo : bar 
> + IFS=: 
> + read -r a b c
> + printf -- /%s/%s/%s/\n foo  bar
> /foo//bar/
>
>
> > 
> > The manual ksh(1) provides the following, similar example:
> > 
> > > Example: If IFS is set to “:”, and VAR is set to
> > > “A:B::D”, the substitution for $VAR
> > > results in four fields: ‘A’, ‘B’, ‘’ (an empty field), and ‘D’.
> > > Note that if the IFS parameter is set to the NULL string, no field
> > > splitting is done; if the parameter is unset, the default value of
> > > space, tab, and newline is used.
> > 
> > Let's try it:
> > 
> > echo " A :  B::D" | {
> > IFS=" :"
> > read -r arg1 arg2 arg3 arg4
> > printf -- '1st: "%s"\n' "$arg1"
> > printf -- '2nd: "%s"\n' "$arg2"
> > printf -- '3rd: "%s"\n' "$arg3"
> > printf -- '4th: "%s"\n' "$arg4"
> > }
> > 
> > bash(1) splits the line into the following fields:
> > 
> > 1st: "A"
> > 2nd: "B"
> > 3rd: ""
> > 4th: "D"
> > 
> > This is actually the expected output, as described in the manual.
> > 
> > However, running the same command in OpenBSD ksh, prints this:
> > 
> > 1st: "A"
> > 2nd: ""
> > 3rd: "B"
> > 4th: ":D"
> > 
> > A completelly different thing.
> > The same occurs with OpenBSD sh(1).
>
> What you observe is the result of the next paragraph in the man page
> after the example you quoted:
>
>  Also, note that the field splitting applies only to the immediate result
>  of the substitution.  Using the previous example, the substitution for
>  $VAR:E results in the fields: `A', `B', `', and `D:E', not `A', `B', `',
>  `D', and `E'.  This behavior is POSIX compliant, but incompatible with
>  some other shell implementations which do field splitting on the word
>  which contained the substitution or use IFS as a general whitespace
>  delimiter.

Actually you need to look further into the manual since the word
splitting is performed not by parameter substitution but by read:

 Reads a line of input from the standard input, separates the line
 into fields using the IFS parameter (see Substitution above), and
 assigns each field to the specified parameters.

This is why adding an extra variable to read above (and here) makes
it capture the remainder of the string.

For example:

$ alias dump="perl -MData::Dumper -e 'print Dumper @ARGV'"
$ dump a b c
$VAR1 = 'a';
$VAR2 = 'b';
$VAR3 = 'c';

$ ( IFS=:; dump $PATH )
$VAR1 = '/bin';
$VAR2 = '/sbin';
$VAR3 = '/usr/bin';
$VAR4 = '/usr/sbin';
$VAR5 = '/usr/X11R6/bin';
$VAR6 = '/usr/local/bin';
$VAR7 = '/usr/local/sbin';
$VAR8 = '/usr/games';

So given $X:

$ X=' A :  B::D'

Parameter substitution:

$ ( IFS=' :'; dump $X )
$VAR1 = 'A';
$VAR2 = 'B';
$VAR3 = '';
$VAR4 = 'D';

Similarly:

$ fn() { dump "$@" ); fn $X
$VAR1 = 'A';
$VAR2 = ':';
$VAR3 = 'B::D';

$ fn() { dump "$@"; }; ( IFS=' :'; fn $X )
$VAR1 = 'A';
$VAR2 = 'B';
$VAR3 = '';
$VAR4 = 'D';

read substitution:

$ echo "$X" | ( IFS=' :'; read a1 a2 a3; dump "$a1" "$a2" "$a3" )
$VAR1 = 'A';
$VAR2 = '';
$VAR3 = 'B::D';

$ echo "$X" | ( IFS=' :'; read a1 a2 a3 a4; dump "$a1" "$a2" "$a3" 
"$a4" )
$VAR1 = 'A';
$VAR2 = '';
$VAR3 = 'B';
$VAR4 = ':D';

$ echo "$X" | ( IFS=' :'; read a1 a2 a3 a4 a5; dump "$a1" "$a2" "$a3" 
"$a4" "$a5" )
$VAR1 = 'A';
$VAR2 = '';
$VAR3 = 'B';
$VAR4 = '';
$VAR5 = 'D';

It does look like read, which uses its own expansion routine, has
a bug: a2/VAR2 should be 'B' (or 'B::D') not ''.

Matthew



Re: ksh: documented substitution behavior contradicts actual behavior

2022-10-16 Thread Kastus Shchuka
On Sat, Oct 15, 2022 at 11:42:17PM -0300, Lucas de Sena wrote:
> Hi,
> 
> After trying to split a string into fields delimited with colons and
> spaces, I found this bug in how ksh(1) does substitution.  The actual
> behavior contradicts what other shells like bash and mksh do and also
> contradicts its own manual.
> 
> Running the following on other shells (say, bash) prints "/foo/bar/".
> This command splits the string " foo : bar " into two fields: "foo"
> and "bar", considering colon and space as delimiters.
> 
>   echo " foo : bar " | {
>   IFS=": "
>   read -r a b
>   printf -- "/%s/%s/\n" "$a" "$b"
>   }
> 
> However, running the same command in OpenBSD ksh(1) (or sh(1)) splits
> the string into "foo" and ": bar".

This is because the last parameter (b) is a concatenation of two fields. 
Parsing 
is done properly if you add c to the read command:

+ echo  foo : bar 
+ IFS=: 
+ read -r a b c
+ printf -- /%s/%s/%s/\n foo  bar
/foo//bar/


> 
> The manual ksh(1) provides the following, similar example:
> 
> > Example: If IFS is set to “:”, and VAR is set to
> > “A:B::D”, the substitution for $VAR
> > results in four fields: ‘A’, ‘B’, ‘’ (an empty field), and ‘D’.
> > Note that if the IFS parameter is set to the NULL string, no field
> > splitting is done; if the parameter is unset, the default value of
> > space, tab, and newline is used.
> 
> Let's try it:
> 
>   echo " A :  B::D" | {
>   IFS=" :"
>   read -r arg1 arg2 arg3 arg4
>   printf -- '1st: "%s"\n' "$arg1"
>   printf -- '2nd: "%s"\n' "$arg2"
>   printf -- '3rd: "%s"\n' "$arg3"
>   printf -- '4th: "%s"\n' "$arg4"
>   }
> 
> bash(1) splits the line into the following fields:
> 
>   1st: "A"
>   2nd: "B"
>   3rd: ""
>   4th: "D"
> 
> This is actually the expected output, as described in the manual.
> 
> However, running the same command in OpenBSD ksh, prints this:
> 
>   1st: "A"
>   2nd: ""
>   3rd: "B"
>   4th: ":D"
> 
> A completelly different thing.
> The same occurs with OpenBSD sh(1).

What you observe is the result of the next paragraph in the man page
after the example you quoted:

 Also, note that the field splitting applies only to the immediate result
 of the substitution.  Using the previous example, the substitution for
 $VAR:E results in the fields: `A', `B', `', and `D:E', not `A', `B', `',
 `D', and `E'.  This behavior is POSIX compliant, but incompatible with
 some other shell implementations which do field splitting on the word
 which contained the substitution or use IFS as a general whitespace
 delimiter.

> 
> I could not understand how OpenBSD does the spliting, but the way it
> does is clearly a bug: it does not only contradicts its own manual,
> but also differs from other implementations.

I do not see contradictions in the man page. It does say that behavior
is incompatible with other shells.

> 
> Thank you,
> Lucas de Sena.
> 



Re: sndio and bit perfect playback

2022-10-16 Thread Alexandre Ratchov
On Fri, Oct 14, 2022 at 04:01:45PM -0400, Geoff Steckel wrote:
> > 
> > I did simple A/B tests with music from CDs and my ears couldn't hear
> > the aliasing noise. Try it.
> Good a/b >x< tests for audio require extreme care to get accurate results.
> Simple sine sweeps don't show IM distortion well.
> In most cases numerically equal amounts of IM distortion are far more easily
> noticed than harmonic distortions or simple noise (white, pink, etc.)

Sure, there is measurable aliasing. My questioning is: is it audible
in 99% of the cases?

Remains the question, how to handle the 1% remaining. For now,
resampling off-line is the least annoying, IMHO.

> > Sometimes you just don't want to think about it (ex., when you debug
> > audio stuff), so resampling off-line (or switching the device rate)
> > still makes sense in certain cases.
> This is the classic "why would you ever want to do that?"
> "Just as good" is an opinion.
> Other OSs can and do provide controls which allow setting the device
> sample rate to whatever the device can do.
> This user wants that to work.
> 
> This means compiling a kernel with AUDIO_DEBUG Real Soon Now
> and inserting a few more DPRINTFs.

AFAIK, sample rate changes in the kernel are OK, at least in uaudio
driver.

Now it's all in sndiod (or how to bypass sndiod to get bit-perfect
audio)



Re: sndio and bit perfect playback

2022-10-16 Thread Alexandre Ratchov
On Sat, Oct 15, 2022 at 10:03:52PM +0200, Åke Nordin wrote:
> On 10/14/22 11:21, Alexandre Ratchov wrote:
> > Here are the measures of the aliasing noise using sine sweeps. Check
> > the figure for the 44.1kHz to 48kH conversion, the sndiod column:
> > 
> > https://arverb.com/pub/src/
> 
> Those are interesting results, indeed. Is there a write-up about the
> testing method somewhere where I can read how to reproduce such tests?
> 

Sorry, no detailed write-up, but I did the aliasing measurement
roughly as follows. Example for 44.1kHz to 48kHz:

First generate a sine sweep at 44.1kHz, up to half the sample rate:

sox -V -r 44100 -n sweep-44100.aif synth 30 sin 0+22050 gain -6

the gain must be slightly reduced to avoid filter over-shoots which
would clip and show the clipping distortion. Then, resample the file
to 48kHz using aucat (it uses the same algorithm as sndiod):

aucat -n -i sweep-44100.aif -r 48000 -c 0:0 -o sweep-44100-48000.aif

And plot the spectrogram:

sox sweep-44100-48000.aif -n spectrogram -o sweep-44100-48000.png

sxiv sweep-44100-48000.png

The column with the "linear" method is obtained by resampling using
the old aucat version. The column with the "offline" method is
obtained by resampling with sox instead of aucat.

Let me know if you need more information or have suggestions.