Subject: port-i386/2581: linux audio emulation not good enough for realaudio
To: None <gnats-bugs@NetBSD.ORG>
From: Bill Sommerfeld <sommerfeld@orchard.medford.ma.us>
List: netbsd-bugs
Date: 06/30/1996 14:49:55
>Number:         2581
>Category:       port-i386
>Synopsis:       linux audio emulation not good enough for realaudio
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 30 11:05:01 1996
>Last-Modified:
>Originator:     Bill Sommerfeld
>Organization:
none
>Release:        current as of 6/29/96
>Environment:
	
System: NetBSD orchard.medford.ma.us 1.2_BETA NetBSD 1.2_BETA (ORCHARD) #17: Sat Jun 29 22:54:07 EDT 1996 sommerfeld@orchard.medford.ma.us:/home/src/netbsd-krb5/sys/arch/i386/compile/ORCHARD i386


>Description:
	the linux realaudio doesn't work on netbsd under emulation
>How-To-Repeat:
	see http://www.realaudio.com for the bits; download the linux bits 
	and try running it on the sample included in the tarfile
>Fix:

The following changes were made while I was attempting to get
realaudio to work on my NetBSD/i386 system.

realaudio also wants to open up /dev/mixer and do a bunch of linux
mixer ioctls, but I haven't implemented those (there appear to be a
lot of them...); the ioctl failure doesn't cause realaudio to give
up..

Note that the following also fixes LINUX_SNDCTL_DSP_SETFMT to return
the actual format set just like what Linux does.  This wasn't
necessary to get realaudio working but I didn't realize that until
*after* I made the change..

I've got an sb pro, which only does 8-bit samples; realaudio asks for
linear 16-bit samples and unfortunately doesn't look at which format
it actually gets back.  You may need to select "8 bit" instead of "16
bit" audio in this case.

I also needed to set the AUMODE_PLAY_ALL bit on /dev/sound using a
separate program in order to avoid silence-stuffing when realaudio got
behind..

Only the 14.4kbit version seems to work OK on my system; I did the
work on a 486/33 which evidently doesn't have the horsepower for the
28.8 coder.

Charles and/or Christos and/or whoever "owns" the linux emulation
code: please let me know if there's a problem with this fix or any
reason why you can't put this into the post-1.2 tree.

					- Bill

===================================================================
RCS file: /usr/cvs/sys/compat/linux/linux_audio.h,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 linux_audio.h
*** linux_audio.h	1996/03/12 00:03:08	1.1.1.1
--- linux_audio.h	1996/06/30 00:00:42
***************
*** 17,22 ****
- --- 17,23 ----
  #define	LINUX_SNDCTL_DSP_STEREO		_LINUX_IOWR('P', 3, int)
  #define	LINUX_SNDCTL_DSP_GETBLKSIZE	_LINUX_IOWR('P', 4, int)
  #define	LINUX_SNDCTL_DSP_SETFMT		_LINUX_IOWR('P', 5, int)
+ #define LINUX_SNDCTL_DSP_WRITE_CHANNELS	_LINUX_IOWR('P', 6, int)
  #define	LINUX_SNDCTL_DSP_POST		_LINUX_IO('P', 8)
  #define	LINUX_SNDCTL_DSP_SETFRAGMENT	_LINUX_IOWR('P', 10, int)
  #define	LINUX_SNDCTL_DSP_GETFMTS	_LINUX_IOR('P', 11, int)

===================================================================
RCS file: /usr/cvs/sys/compat/linux/linux_audio.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 linux_audio.c
*** linux_audio.c	1996/03/12 00:03:08	1.1.1.1
--- linux_audio.c	1996/06/30 14:33:41
***************
*** 71,76 ****
--- 71,91 ----
  		if (error)
  			return error;
  		break;
+ 	case LINUX_SNDCTL_DSP_WRITE_CHANNELS:
+ 		AUDIO_INITINFO(&tmpinfo);
+ 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
+ 		if (error)
+ 			return error;
+ 		tmpinfo.play.channels = idat;
+ 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
+ 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
+ 		if (error)
+ 			return error;
+ 		idat = tmpinfo.play.channels;
+ 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
+ 		if (error)
+ 			return error;
+ 		break;
  	case LINUX_SNDCTL_DSP_STEREO:
  		AUDIO_INITINFO(&tmpinfo);
  		error = copyin(SCARG(uap, data), &idat, sizeof idat);
***************
*** 133,139 ****
  		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
  		if (error)
  			return error;
! 		/*XXXX*/
  		break;
  	case LINUX_SNDCTL_DSP_SETFRAGMENT:
  		AUDIO_INITINFO(&tmpinfo);
--- 148,173 ----
  		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
  		if (error)
  			return error;
! 		switch(tmpinfo.play.encoding) {
! 		case AUDIO_ENCODING_LINEAR:
! 		        if (tmpinfo.play.precision == 8)
! 				idat = LINUX_AFMT_U8;
! 			else if (tmpinfo.play.precision == 16)
! 			  	idat = LINUX_AFMT_S16_LE;
! 		        else return EINVAL;
! 			break;
! 		case AUDIO_ENCODING_ULAW:
! 			idat = LINUX_AFMT_MU_LAW;
! 		        break;
! 		case AUDIO_ENCODING_ALAW:
! 			idat = LINUX_AFMT_A_LAW;
! 		        break;
! 		default:
! 			return EINVAL;
! 		}
! 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
! 		if (error)
! 			return error;
  		break;
  	case LINUX_SNDCTL_DSP_SETFRAGMENT:
  		AUDIO_INITINFO(&tmpinfo);


>Audit-Trail:
>Unformatted: