Subject: kern/20620: add emuxki support for recording formats
To: None <gnats-bugs@gnats.netbsd.org>
From: None <yh@metroweb.co.za>
List: netbsd-bugs
Date: 03/08/2003 16:42:40
>Number:         20620
>Category:       kern
>Synopsis:       add additional formats for emuxki recording
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Mar 08 06:44:00 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     Yorick Hardy
>Release:        NetBSD 1.6_STABLE
>Organization:
>Environment:
System: NetBSD Yorick 1.6_STABLE NetBSD 1.6_STABLE (YORICK) #277: Sat Mar 8 14:53:36 SAST 2003 yorick@Yorick:/usr/src/sys/arch/i386/compile/YORICK i386
Architecture: i386
Machine: i386
>Description:
The emu10k1 only supports 16 bit signed linear format, so add software
conversion for other recording formats.
>How-To-Repeat:
Not applicable.
>Fix:
Apply the following patch (against revision 1.20 of emuxki.c).
Also remove the comment about single source recording as it is now supported.

--- sys/dev/pci/emuxki.c.orig	Sat Mar  8 14:08:17 2003
+++ sys/dev/pci/emuxki.c	Sat Mar  8 14:50:51 2003
@@ -49,7 +49,6 @@
  * TODO:
  * - Digital Outputs
  * - (midi/mpu),joystick support
- * - Single source recording
  * - Multiple voices play (problem with /dev/audio architecture)
  * - Multiple sources recording (Pb with audio(4))
  * - Independant modification of each channel's parameters (via mixer ?)
@@ -1524,10 +1523,6 @@
 			voice->dataloc.chan[0]->loop.start);
 	else
 		/* returns number of bytes */
-		/*
-		 * XXX Linux driver suggests something special is needed
-		 * XXX when precision == 8.
-		 */
 		return (emuxki_read(voice->sc, 0,
 		    emuxki_recsrc_idxreg[voice->dataloc.source]) &
 		    EMU_RECIDX_MASK);
@@ -1839,10 +1834,22 @@
 	mode = (voice->use & EMU_VOICE_USE_PLAY) ?
 		AUMODE_PLAY : AUMODE_RECORD;
 	p->factor = 1;
+	p->factor_denom = 1;
 	p->sw_code = NULL;
 	if (p->channels != 1 && p->channels != 2)
 		return (EINVAL);/* Will change when streams come in use */
 
+	if (mode == AUMODE_RECORD)
+	{
+		if (emuxki_recsrc_rate_to_index(p->sample_rate) < 0)
+			return (EINVAL);
+		p->hw_sample_rate = p->sample_rate;
+		p->hw_channels = p->channels;
+		p->hw_encoding = AUDIO_ENCODING_SLINEAR_LE;
+		p->hw_precision = 16;
+		b16 = 1;
+	}
+
 	switch (p->encoding) {
 	case AUDIO_ENCODING_ULAW:
 		if (mode == AUMODE_PLAY) {
@@ -1850,8 +1857,8 @@
 			p->sw_code = mulaw_to_slinear16_le;
 			b16 = 1;
 		} else {
-			p->sw_code = ulinear8_to_mulaw;
-			b16 = 0;
+			p->factor = 2;
+			p->sw_code = slinear16_to_mulaw_le;
 		}
 		break;
 
@@ -1861,39 +1868,69 @@
 			p->sw_code = alaw_to_slinear16_le;
 			b16 = 1;
 		} else {
-			p->sw_code = ulinear8_to_alaw;
-			b16 = 0;
+			p->factor = 2;
+			p->sw_code = slinear16_to_alaw_le;
 		}
 		break;
 
 	case AUDIO_ENCODING_SLINEAR_LE:
-		if (p->precision == 8)
-			p->sw_code = change_sign8;
-		b16 = (p->precision == 16);
+		if (mode == AUMODE_PLAY) {
+			if (p->precision == 8)
+				p->sw_code = change_sign8;
+			b16 = (p->precision == 16);
+		} else {
+			if (p->precision == 8) {
+				p->factor = 2;
+				p->sw_code = linear16_to_linear8_le;
+			}
+		}
 		break;
 
 	case AUDIO_ENCODING_ULINEAR_LE:
-		if (p->precision == 16)
-			p->sw_code = change_sign16_le;
-		b16 = (p->precision == 16);
+		if (mode == AUMODE_PLAY) {
+			if (p->precision == 16)
+				p->sw_code = change_sign16_le;
+			b16 = (p->precision == 16);
+		} else {
+			if (p->precision == 8) {
+				p->factor = 2;
+				p->sw_code = slinear16_to_ulinear8_le;
+			}
+			else
+				p->sw_code = change_sign16_le;
+		}
 		break;
 
 	case AUDIO_ENCODING_SLINEAR_BE:
-		if (p->precision == 16)
-			p->sw_code = swap_bytes;
-		else
-			p->sw_code = change_sign8;
-		b16 = (p->precision == 16);
+		if (mode == AUMODE_PLAY) {
+			if (p->precision == 16)
+				p->sw_code = swap_bytes;
+			else
+				p->sw_code = change_sign8;
+			b16 = (p->precision == 16);
+		} else {
+			if (p->precision == 8) {
+				p->factor = 2;
+				p->sw_code = linear16_to_linear8_le;
+			}
+			else
+				p->sw_code = swap_bytes;
+		}
 		break;
 
 	case AUDIO_ENCODING_ULINEAR_BE:
-		if (p->precision == 16) {
-			if (mode == AUMODE_PLAY)
+		if (mode == AUMODE_PLAY) {
+			if (p->precision == 16)
 				p->sw_code = swap_bytes_change_sign16_le;
+			b16 = (p->precision == 16);
+		} else {
+			if (p->precision == 8) {
+				p->factor = 2;
+				p->sw_code = slinear16_to_ulinear8_le;
+			}
 			else
 				p->sw_code = change_sign16_swap_bytes_le;
 		}
-		b16 = (p->precision == 16);
 		break;
 
 	default:
>Release-Note:
>Audit-Trail:
>Unformatted: