From andre.albsmeier@mchp.siemens.de  Wed Sep  6 00:18:20 2000
Return-Path: <andre.albsmeier@mchp.siemens.de>
Received: from david.siemens.de (david.siemens.de [192.35.17.14])
	by hub.freebsd.org (Postfix) with ESMTP id BADB937B42C
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  6 Sep 2000 00:18:18 -0700 (PDT)
Received: from mail1.siemens.de (mail1.siemens.de [139.23.33.14])
	by david.siemens.de (8.10.1/8.10.1) with ESMTP id e867IHo14401
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 6 Sep 2000 09:18:17 +0200 (MET DST)
Received: from curry.mchp.siemens.de (curry.mchp.siemens.de [139.25.42.7])
	by mail1.siemens.de (8.10.1/8.10.1) with ESMTP id e867IHh26813
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 6 Sep 2000 09:18:17 +0200 (MET DST)
Received: (from localhost)
	by curry.mchp.siemens.de (8.11.0/8.11.0) id e867IHo37512
	for FreeBSD-gnats-submit@freebsd.org; Wed, 6 Sep 2000 09:18:17 +0200 (CEST)
Message-Id: <200009060718.e867IGj45601@curry.mchp.siemens.de>
Date: Wed, 6 Sep 2000 09:18:16 +0200 (CEST)
From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: FreeBSD-gnats-submit@freebsd.org
Subject: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
X-Send-Pr-Version: 3.2

>Number:         21073
>Category:       kern
>Synopsis:       PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    cg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Sep 06 00:20:00 PDT 2000
>Closed-Date:    Mon Feb 12 07:19:49 PST 2001
>Last-Modified:  Mon Feb 12 07:20:14 PST 2001
>Originator:     Andre Albsmeier
>Release:        FreeBSD 4.1-STABLE i386
>Organization:
>Environment:

4.1-STABLE machine using the pcm driver on an AB AWE64:

andre@bali:~>cat /dev/sndstat 
FreeBSD Audio Driver (newpcm) Sep  2 2000 10:33:49
Installed devices:
pcm0: <SB DSP 4.16> at io 0x220 irq 5 drq 1:5 (1p/1r channels duplex)


>Description:

When setting a sound format with SNDCTL_DSP_SETFMT, the system call does not
tell us if an improper format was set.

>How-To-Repeat:

The following program demonstrates the error:

#include <stdio.h>   
#include <ctype.h>
#include <string.h>
#include <machine/soundcard.h>
#include <sys/time.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main( ) {

  int bits;
  int fd;

  if( (fd = open("/dev/dsp", O_RDONLY)) < 0 ) {
    fprintf( stderr, "Can't open /dev/dsp for read\n" );
    exit( 1 );
  }

  if( ioctl(fd, SNDCTL_DSP_GETFMTS, &bits) < 0 ) {
    fprintf( stderr, "SNDCTL_DSP_GETFMTS error\n" );
    exit( 1 );
  }
  
  printf( "GETFMTS: 0x%X\n", bits );
    
  bits = 0x10;
  if( ioctl(fd, SNDCTL_DSP_SETFMT, &bits) < 0 ) {
    fprintf( stderr, "SNDCTL_DSP_SETFMT error\n" );
    exit( 1 );
  }

  printf( "After setting 0x10 with SETFMT: 0x%X\n", bits );

  return( 0 );
}


andre@bali:~>./sndcheck 
GETFMTS: 0x10000008
After setting 0x10 with SETFMT: 0x10

So the AWE64 only supports AFMT_U8 in STEREO. Now we set AFMT_S16_LE
but there is no error returned neither was the bits variable modified
as it was the case in voxware.


>Fix:

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->cg 
Responsible-Changed-By: sheldonh 
Responsible-Changed-When: Wed Sep 6 04:19:11 PDT 2000 
Responsible-Changed-Why:  
Over to maintainer. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=21073 

From: "Cameron Grant" <gandalf@vilnya.demon.co.uk>
To: <freebsd-gnats-submit@FreeBSD.org>,
	<andre.albsmeier@mchp.siemens.de>
Cc:  
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Wed, 6 Sep 2000 15:03:50 +0100

 SNDCTL_DSP_GETFMTS returns the hardware formats supported.
 SNDCTL_DSP_SETFMT is allowed to set other formats using software
 translation, and does so.
 
     -cg
 
 
 

From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: Cameron Grant <gandalf@vilnya.demon.co.uk>
Cc: freebsd-gnats-submit@FreeBSD.org,
	andre.albsmeier@mchp.siemens.de, Randall Hopper <aa8vb@nc.rr.com>
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Wed, 6 Sep 2000 16:13:06 +0200

 [CC'ed to Randall Hopper <aa8vb@nc.rr.com> as well since we
  both are currently lost with this]
 
 On Wed, 06-Sep-2000 at 15:03:50 +0100, Cameron Grant wrote:
 > SNDCTL_DSP_GETFMTS returns the hardware formats supported.
 > SNDCTL_DSP_SETFMT is allowed to set other formats using software
 > translation, and does so.
 
 Hmm, let's see if I understood this correctly:
 
 In case SNDCTL_DSP_GETFMTS returns 8 (don't worry about stereo) which
 is AFMT_U8 and I set 0x10 (AFMT_S16_LE) and get returned 0x10 I can
 assume that:
 
 1. Recording will be done properly (but possibly with a different format)
 2. The output data will conform to the format set with SNDCTL_DSP_SETFMT
    which is AFMT_S16_LE in my example.
 
 Is this correct?
 
 Thanks for looking into this,
 
 	-Andre
 

From: "Cameron Grant" <gandalf@vilnya.demon.co.uk>
To: "Andre Albsmeier" <andre.albsmeier@mchp.siemens.de>
Cc: <freebsd-gnats-submit@FreeBSD.org>,
	<andre.albsmeier@mchp.siemens.de>, "Randall Hopper" <aa8vb@nc.rr.com>
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Wed, 6 Sep 2000 15:28:18 +0100

 > On Wed, 06-Sep-2000 at 15:03:50 +0100, Cameron Grant wrote:
 > > SNDCTL_DSP_GETFMTS returns the hardware formats supported.
 > > SNDCTL_DSP_SETFMT is allowed to set other formats using software
 > > translation, and does so.
 >
 > Hmm, let's see if I understood this correctly:
 >
 > In case SNDCTL_DSP_GETFMTS returns 8 (don't worry about stereo) which
 > is AFMT_U8 and I set 0x10 (AFMT_S16_LE) and get returned 0x10 I can
 > assume that:
 >
 > 1. Recording will be done properly (but possibly with a different format)
 > 2. The output data will conform to the format set with SNDCTL_DSP_SETFMT
 >    which is AFMT_S16_LE in my example.
 >
 > Is this correct?
 
 yes.  in theory at least.  if you get garbage out, there's a bug in the
 code.
 
     -cg
 
 
 

From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: Cameron Grant <gandalf@vilnya.demon.co.uk>
Cc: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>,
	freebsd-gnats-submit@FreeBSD.org, Randall Hopper <aa8vb@nc.rr.com>
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Wed, 6 Sep 2000 16:37:28 +0200

 On Wed, 06-Sep-2000 at 15:28:18 +0100, Cameron Grant wrote:
 > > On Wed, 06-Sep-2000 at 15:03:50 +0100, Cameron Grant wrote:
 > > > SNDCTL_DSP_GETFMTS returns the hardware formats supported.
 > > > SNDCTL_DSP_SETFMT is allowed to set other formats using software
 > > > translation, and does so.
 > >
 > > Hmm, let's see if I understood this correctly:
 > >
 > > In case SNDCTL_DSP_GETFMTS returns 8 (don't worry about stereo) which
 > > is AFMT_U8 and I set 0x10 (AFMT_S16_LE) and get returned 0x10 I can
 > > assume that:
 > >
 > > 1. Recording will be done properly (but possibly with a different format)
 > > 2. The output data will conform to the format set with SNDCTL_DSP_SETFMT
 > >    which is AFMT_S16_LE in my example.
 > >
 > > Is this correct?
 > 
 > yes.  in theory at least.  if you get garbage out, there's a bug in the
 > code.
 
 Thanks. I think the latter is correct :-). I will investigate this a bit
 more...
 
 BTW, is my AWE 64 really not possible to do native 16 Bit recording?
 IIRC, with voxware I could do 16 Bit recording but I might be wrong...
 
 Thanks,
 
 	-Andre
 

From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: Andre Albsmeier <andre@internal.FreeBSD.ORG>
Cc: Cameron Grant <gandalf@vilnya.demon.co.uk>,
	Andre Albsmeier <andre.albsmeier@mchp.siemens.de>,
	freebsd-gnats-submit@FreeBSD.org, Randall Hopper <aa8vb@nc.rr.com>
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Wed, 6 Sep 2000 19:39:06 +0200

 On Wed, 06-Sep-2000 at 16:37:28 +0200, Andre Albsmeier wrote:
 > On Wed, 06-Sep-2000 at 15:28:18 +0100, Cameron Grant wrote:
 > > > On Wed, 06-Sep-2000 at 15:03:50 +0100, Cameron Grant wrote:
 > > > > SNDCTL_DSP_GETFMTS returns the hardware formats supported.
 > > > > SNDCTL_DSP_SETFMT is allowed to set other formats using software
 > > > > translation, and does so.
 > > >
 > > > Hmm, let's see if I understood this correctly:
 > > >
 > > > In case SNDCTL_DSP_GETFMTS returns 8 (don't worry about stereo) which
 > > > is AFMT_U8 and I set 0x10 (AFMT_S16_LE) and get returned 0x10 I can
 > > > assume that:
 > > >
 > > > 1. Recording will be done properly (but possibly with a different format)
 > > > 2. The output data will conform to the format set with SNDCTL_DSP_SETFMT
 > > >    which is AFMT_S16_LE in my example.
 > > >
 > > > Is this correct?
 > > 
 > > yes.  in theory at least.  if you get garbage out, there's a bug in the
 > > code.
 > 
 > Thanks. I think the latter is correct :-). I will investigate this a bit
 > more...
 > 
 > BTW, is my AWE 64 really not possible to do native 16 Bit recording?
 > IIRC, with voxware I could do 16 Bit recording but I might be wrong...
 
 I assume there is really a problem when recording a 16 Bit format 
 with a soundcard that is only capable of doing AFMT_U8...
 
 Randall, can I include your dsp-record.c in a mail for Cameron?
 This would make explaining the problem much easier...
 
 Thanks,
 
 	-Andre
 

From: Randall Hopper <aa8vb@nc.rr.com>
To: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
Cc: Andre Albsmeier <andre@internal.FreeBSD.ORG>,
	Cameron Grant <gandalf@vilnya.demon.co.uk>,
	freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Wed, 6 Sep 2000 17:43:21 -0400

 Andre Albsmeier:
  |On Wed, 06-Sep-2000 at 16:37:28 +0200, Andre Albsmeier wrote:
  |> BTW, is my AWE 64 really not possible to do native 16 Bit recording?
  |> IIRC, with voxware I could do 16 Bit recording but I might be wrong...
  |
  |I assume there is really a problem when recording a 16 Bit format 
  |with a soundcard that is only capable of doing AFMT_U8...
  |
  |Randall, can I include your dsp-record.c in a mail for Cameron?
  |This would make explaining the problem much easier...
 
 Sure.
 
 And yes, with Voxware 16-bit stereo recording is no problem for cards with
 a SB16-compatible DSP (SB16, SB32, AWE32, AWE64, etc.).  Mine is a SB32.
 
 -- 
 Randall Hopper
 aa8vb@nc.rr.com
 

From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: Cameron Grant <gandalf@vilnya.demon.co.uk>
Cc: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>,
	freebsd-gnats-submit@FreeBSD.org, Randall Hopper <aa8vb@nc.rr.com>
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Thu, 7 Sep 2000 06:54:17 +0200

 On Wed, 06-Sep-2000 at 15:28:18 +0100, Cameron Grant wrote:
 > > On Wed, 06-Sep-2000 at 15:03:50 +0100, Cameron Grant wrote:
 > > > SNDCTL_DSP_GETFMTS returns the hardware formats supported.
 > > > SNDCTL_DSP_SETFMT is allowed to set other formats using software
 > > > translation, and does so.
 > >
 > > Hmm, let's see if I understood this correctly:
 > >
 > > In case SNDCTL_DSP_GETFMTS returns 8 (don't worry about stereo) which
 > > is AFMT_U8 and I set 0x10 (AFMT_S16_LE) and get returned 0x10 I can
 > > assume that:
 > >
 > > 1. Recording will be done properly (but possibly with a different format)
 > > 2. The output data will conform to the format set with SNDCTL_DSP_SETFMT
 > >    which is AFMT_S16_LE in my example.
 > >
 > > Is this correct?
 > 
 > yes.  in theory at least.  if you get garbage out, there's a bug in the
 > code.
 
 OK, here is more info: Randall has written a small program dsp-record.c
 (I have just modified it a bit for -Wall):
 
 ------------------------- snip -----------------------
 
 /*  Adapted from short pgm posted by dnelson@emsphone.com by  */
 /*  Randall Hopper (rhh@ct.picker.com)                        */
 
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
 #include <sys/soundcard.h>
 #include <sys/time.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 
 #define ARRAYSIZE(a) ( sizeof(a) / sizeof(a[0]) )
 
 #define DO_IOCTL_SERR(str,arg)                               \
         do { fprintf(stderr, "ioctl(%s, %ld) failed: %s\n",     \
                           str, (long)arg, strerror(errno) ); \
           exit(1);                                           \
         } while (0)
 #define DO_IOCTL_SVALERR(str,v1,v2)                          \
         do { fprintf(stderr, "ioctl(%s) failed: Tried %d, Got %d\n", \
                           str, v1, v2 );                     \
           exit(1);                                           \
         } while (0)
 
 
 void StrLwr( char a[] )
 {
     char *p = a;
 
     while ( *p != '\0' )
         *(p++) = tolower( *p );
 }
 
 
 /*  SampFmt_StrToEnum: Convert sample format string to enum; -1 on failure  */
 int SampFmt_StrToEnum( char str[] )
 {
     static struct {
         char *str;
         int   val;
     } Sfmtcnvt[] = {
         { "mulaw", AFMT_MU_LAW		},
         { "ulaw" , AFMT_MU_LAW		},
         { "alaw" , AFMT_A_LAW		},
         { "adpcm", AFMT_IMA_ADPCM	},
         { "8"    , AFMT_U8		},
         { "u8"   , AFMT_U8		},
         { "16"   , AFMT_S16_LE		},
         { "s16le", AFMT_S16_LE		},
         { "s16be", AFMT_S16_BE		},
         { "s8"   , AFMT_S8		},
         { "u16le", AFMT_U16_LE		},
         { "u16be", AFMT_U16_BE		},
         { "mpeg" , AFMT_MPEG		},
     };
 
     int  i;
     char tmpstr[20];
 
     tmpstr[0] = '\0';
     strncat( tmpstr, str, sizeof(tmpstr)-1 );
     StrLwr( tmpstr );
 
     for ( i = 0; i < ARRAYSIZE( Sfmtcnvt ); i++ )
         if ( strcmp( tmpstr, Sfmtcnvt[i].str ) == 0 )
             break;
 
     if ( i < ARRAYSIZE( Sfmtcnvt ) )
         return Sfmtcnvt[i].val;
     else
         return -1;
 }
 
 
 int main(int argc, char *argv[])
 {
     int fd;
     int rate = 8012;
     int bits = 8;
     int rate_new, bits_new, chan_new;
     char bits_str[80] = "u8";
     int chan = 1;
     int duration = -1,
         elapsed;
     int c;
     int len;
     char buf[1024];
     struct timeval tv1,tv2;
     int  frag, frag_new;
 
     if ( (fd = open("/dev/dsp", O_RDONLY)) < 0 ) {
         fprintf( stderr, "Can't open /dev/dsp for read\n" );
         exit(1);
     }
 
     while ((c = getopt(argc, argv, "hr:b:c:d:")) != EOF)
     {
         switch (c)
         {
             case 'r':
                 rate = atoi(optarg);
                 break;
             case 'b':
                 bits_str[0] = '\0';
                 strncat( bits_str, optarg, sizeof(bits_str)-1 );
                 bits = SampFmt_StrToEnum( bits_str );
                 if ( bits < 0 ) {
                     fprintf( stderr, "Bad sample format\n" );
                     exit(1);
                 }
                 break;
             case 'c':
                 chan = atoi(optarg);
                 break;
             case 'd':
                 duration = atoi(optarg);
                 break;
             case '?':
             case 'h':
                 fprintf( stderr, "dsp-record -r rate -b bits -c channels "
                                  "-d duration(sec)\n");
                 exit(1);
         }
     }
     fprintf( stderr, "Trying    %d Hz %d Channel %s Format\n",
              rate, chan, bits_str );
 
     bits_new = bits;
     if ( ioctl(fd, SNDCTL_DSP_SETFMT, &bits_new) < 0 )
         DO_IOCTL_SERR( "SNDCTL_DSP_SETFMT", bits );
     if ( bits != bits_new )
         DO_IOCTL_SVALERR( "SNDCTL_DSP_SETFMT", bits, bits_new );
 
     rate_new = rate;
     if ( ioctl(fd, SOUND_PCM_WRITE_RATE, &rate_new) < 0 )
         DO_IOCTL_SERR( "SOUND_PCM_WRITE_RATE", rate );
     if ( rate != rate_new )
         DO_IOCTL_SVALERR( "SOUND_PCM_WRITE_RATE", rate, rate_new );
 
     chan_new = chan;
     if ( ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &chan_new) < 0 )
         DO_IOCTL_SERR( "SOUND_PCM_WRITE_CHANNELS", chan );
     ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &chan_new);
     if ( chan != chan_new )
         DO_IOCTL_SVALERR( "SOUND_PCM_WRITE_CHANNELS", chan, chan_new );
 
     fprintf( stderr, "Recording %d Hz %d Channel %s Format\n",
          rate, chan, bits_str );
 
     frag_new = frag = (127 << 16) | 10;
     if ( ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag_new) < 0 )
         DO_IOCTL_SERR( "SNDCTL_DSP_SETFRAGMENT", frag );
     if ( (frag_new & 0xffff) != 10 ) {
 	fprintf( stderr, "SNDCTL_DSP_SETFRAGMENT:  Can't set 1k buffers\n" );
 	exit(1);
     }
 
     gettimeofday( &tv1, NULL );
     tv1.tv_sec--, tv1.tv_usec += 1000000;
 
     while ((len = read(fd, buf, sizeof(buf))) > 0) {
         write(fileno(stdout), buf, len);
         if ( duration > 0 ) {
             gettimeofday( &tv2, NULL );
             elapsed = (tv2.tv_sec  - tv1.tv_sec ) * 1000 +
                       (tv2.tv_usec - tv1.tv_usec) / 1000;
             /*fprintf( stderr, "sec = %d\r", elapsed/1000 );*/
             if ( elapsed/1000 >= duration )
                 break;
         }
     }
     close(fd);
     fprintf( stderr, "\n" );
 
     if ( len <= 0 ) {
         fprintf( stderr, "read() failed; errno = %s\n", strerror(errno) );
         exit(1);
     }
     exit(0);
 }
 
 ------------------------- snip -----------------------
 
 
 Now what we do is following:
 
 We first record 3 seconds of sound in AFMT_U8. Then we transform
 it into a WAV file to make it hearable. Finally, we examine
 the result.
 
 andre@bali:~/try>./dsp-record -r 44100 -b 8 -c 2 -d 3 > 8.raw
 Trying    44100 Hz 2 Channel 8 Format
 Recording 44100 Hz 2 Channel 8 Format
 
 andre@bali:~/try>sox -t raw -r 44100 -u -b 8.raw -t wav -r 44100 -s -w 8.wav
 
 andre@bali:~/try>pcmplay 8.wav
 
 This works great for AFMT_U8 and AFMT_S8.  Now we do the same
 using a 16 Bit format, AFMT_U16_LE:
 
 andre@bali:~/try>./dsp-record -r 44100 -b u16le -c 2 -d 3 > 16.raw
 Trying    44100 Hz 2 Channel u16le Format
 Recording 44100 Hz 2 Channel u16le Format
 
 andre@bali:~/try>sox -t raw -r 44100 -u -w 16.raw -t wav -r 44100 -s -w 16.wav
 
 andre@bali:~/try>pcmplay 16.wav
 
 This could ruin my speakers :-). If this is the correct way of testing
 it, there is something wrong with the PCM driver or its format conversion.
 
 Another thing Randall confirmed is that he also could do 16 Bit recordings with
 his SB32 and voxware. Is this feature known to be missing in the PCM driver
 because it is not implemented or should it work here as well?
 
 Thanks,
 
 	-Andre
 

From: Andre Albsmeier <andre.albsmeier@mchp.siemens.de>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/21073: PCM sound driver silently accepts improper parameters of SNDCTL_DSP_SETFMT
Date: Mon, 12 Feb 2001 15:53:48 +0100

 Please close this one, it is fixed...
 
 	-Andre
 
State-Changed-From-To: open->closed 
State-Changed-By: dwmalone 
State-Changed-When: Mon Feb 12 07:19:49 PST 2001 
State-Changed-Why:  
Closed at submitters request. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=21073 
>Unformatted:
