Subject: Re: Propose: improve audio driver
To: None <kent@netbsd.org>
From: Tetsuya Isaki <isaki@par.odn.ne.jp>
List: tech-kern
Date: 03/03/2002 20:46:21
----Next_Part(Sun_Mar__3_20:42:42_2002_542)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

On Sat, 02 Mar 2002 13:02:55 +0900,
In Re: Propose: improve audio driver,
Tetsuya Isaki <isaki@par.odn.ne.jp> wrote:

> > The following patch contains such audio data conversion with
> > padding.
> > 
> > 	http://www.hauN.org/kent/audio-20020227.diff
> 
> I'll check it. thanks.

I remade a patch for your patch. Please review it.
---
Tetsuya Isaki <isaki@par.odn.ne.jp / isaki@NetBSD.org>

----Next_Part(Sun_Mar__3_20:42:42_2002_542)--
Content-Type: Text/Plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="vs-reduce-for-kent-20020303.diff"

Index: audio.c
===================================================================
RCS file: /home/isaki/cvsroot/vs/src/sys/dev/audio.c,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 audio.c
--- audio.c	2002/03/02 05:03:37	1.1.2.1
+++ audio.c	2002/03/03 08:36:33
@@ -187,7 +187,7 @@
 
 /* The default audio mode: 8 kHz mono ulaw */
 struct audio_params audio_default = 
-	{ 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1 };
+	{ 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1, 1 };
 
 struct cfattach audio_ca = {
 	sizeof(struct audio_softc), audioprobe, audioattach, 
@@ -1131,7 +1131,7 @@
 	u_char *outp;
 	int error, s, used, cc, n;
 	const struct audio_params *params;
-	int hw_bytes_per_sample, required;
+	int hw_bits_per_sample, required;
 
 	if (cb->mmapped)
 		return EINVAL;
@@ -1140,6 +1140,7 @@
                     (unsigned long)uio->uio_resid, sc->sc_mode));
 
 	params = &sc->sc_rparams;
+#if 0
 	switch (params->hw_encoding) {
 	case AUDIO_ENCODING_SLINEAR_LE:
 	case AUDIO_ENCODING_SLINEAR_BE:
@@ -1151,8 +1152,12 @@
 	default:
 		hw_bytes_per_sample = 1 * params->factor;
 	}
+#else
+	hw_bits_per_sample = params->hw_channels * params->precision
+		* params->factor;
+#endif
 	required = ((params->hw_sample_rate / params->sample_rate) + 1)
-		* hw_bytes_per_sample;
+		* hw_bits_per_sample / 8;
 	error = 0;
 	/*
 	 * If hardware is half-duplex and currently playing, return
@@ -1232,11 +1237,11 @@
 			if (cc > sc->sc_rconvbuffer_size)
 				cc = sc->sc_rconvbuffer_size;
 			/* cc must be aligned by the sample size */
-			cc = (cc / hw_bytes_per_sample) * hw_bytes_per_sample;
+			cc = (cc * 8 / hw_bits_per_sample) * hw_bits_per_sample / 8;
 #ifdef DIAGNOSTIC
 			if (cc == 0)
 				printf("audio_read: cc=0 hw_sample_size=%d\n",
-				       hw_bytes_per_sample);
+				       hw_bits_per_sample / 8);
 #endif
 
 			/*
@@ -1267,11 +1272,11 @@
 					       ": cc=%d factor=%d\n", cc,
 					       params->factor);
 #endif
-				cc /= params->factor;
+				cc = cc * params->factor_denom / params->factor;
 #ifdef DIAGNOSTIC
 				if (cc == 0)
-					printf("audio_read: cc=0 factor=%d\n",
-					       params->factor);
+					printf("audio_read: cc=0 factor=%d/%d\n",
+					       params->factor, params->factor_denom);
 #endif
 				sc->sc_rconvbuffer_end = cc;
 				params->sw_code(sc->hw_hdl, sc->sc_rconvbuffer,
@@ -1441,7 +1446,7 @@
 	u_char *inp, *einp;
 	int saveerror, error, s, n, cc, used;
 	struct audio_params *params;
-	int samples, hw_bytes_per_sample, user_bytes_per_sample;
+	int samples, hw_bits_per_sample, user_bits_per_sample;
 	int input_remain, space;
 
 	DPRINTFN(2,("audio_write: sc=%p count=%lu used=%d(hi=%d)\n", 
@@ -1484,6 +1489,7 @@
                      sc->sc_pparams.precision, sc->sc_pparams.channels,
                      sc->sc_pparams.sw_code, sc->sc_pparams.factor));
 
+#if 0
 	/*
 	 * For some encodings, $B%5%s%W%k$NBg$-$5$K(B align $B$7$F=hM}$9$k(B
 	 */
@@ -1492,27 +1498,32 @@
 	case AUDIO_ENCODING_SLINEAR_BE:
 	case AUDIO_ENCODING_ULINEAR_LE:
 	case AUDIO_ENCODING_ULINEAR_BE:
-		hw_bytes_per_sample = params->hw_channels * params->precision/8
+		hw_bits_per_sample = params->hw_channels * params->precision
 			* params->factor;
-		user_bytes_per_sample = params->channels * params->precision/8;
+		user_bits_per_sample = params->channels * params->precision;
 		break;
 	default:
-		hw_bytes_per_sample = 1 * params->factor;
-		user_bytes_per_sample = 1;
+		hw_bits_per_sample = 8 * params->factor;
+		user_bits_per_sample = 8;
 	}
+#else
+	hw_bits_per_sample = params->hw_channels * params->precision
+		* params->factor / params->factor_denom;
+	user_bits_per_sample = params->channels * params->precision;
+#endif
 #ifdef DIAGNOSTIC
-	if (hw_bytes_per_sample > MAX_SAMPLE_SIZE) {
+	if (hw_bits_per_sample > MAX_SAMPLE_SIZE * 8) {
 		printf("%s(): Invalid sample size: cur=%d max=%d\n",
-		       __func__, hw_bytes_per_sample, MAX_SAMPLE_SIZE);
+		       __func__, hw_bits_per_sample, MAX_SAMPLE_SIZE);
 	}
 #endif
 	space = ((params->hw_sample_rate / params->sample_rate) + 1)
-		* hw_bytes_per_sample;
+		* hw_bits_per_sample / 8;
 	error = 0;
 	while ((input_remain = uio->uio_resid + sc->sc_input_fragment_length) > 0
 	       && !error) {
 		s = splaudio();
-		if (input_remain < user_bytes_per_sample) {
+		if (input_remain < user_bits_per_sample / 8) {
 			n = uio->uio_resid;
 			DPRINTF(("audio_write: fragment uiomove length=%d\n", n));
 			error = uiomove(sc->sc_input_fragment
@@ -1549,25 +1560,25 @@
 			cc = cb->end - cb->start;
 
 		/* cc: $B%j%s%0%P%C%U%!$KF~$k%P%$%H?t(B */
-		samples = cc / hw_bytes_per_sample;
+		samples = cc * 8 / hw_bits_per_sample;
 		if (samples == 0)
 			printf("a_w: samples(1) == 0\n");
 		/* samples: $B%j%s%0%P%C%U%!$KF~$k%5%s%W%k?t(B */
 		samples = samples * params->sample_rate / params->hw_sample_rate;
 		if (samples == 0)
 			printf("a_w: samples(2) == 0 usedhigh-used=%d cc/hw_bps=%d/%d rate/hw_rate=%ld/%ld space=%d\n",
-			       cb->usedhigh - cb->used, cc, hw_bytes_per_sample, params->sample_rate, params->hw_sample_rate, space);
+			       cb->usedhigh - cb->used, cc, hw_bits_per_sample / 8, params->sample_rate, params->hw_sample_rate, space);
 		/* samples: $B%j%s%0%P%C%U%!$KF~$k!"%=!<%9$G$N%5%s%W%k?t(B */
-		cc = samples * user_bytes_per_sample;
+		cc = samples * user_bits_per_sample / 8;
 		/* cc: $B%j%s%0%P%C%U%!$KF~$k:GBg$N%=!<%9%P%$%H?t(B */
 		if (input_remain < cc)	/* and no more than we have */
-			cc = (input_remain / user_bytes_per_sample)
-				* user_bytes_per_sample;
+			cc = (input_remain * 8 / user_bits_per_sample)
+				* user_bits_per_sample / 8;
 		if (cc == 0)
 			printf("a_w: cc(1) == 0\n");
 		if (cc * params->factor > sc->sc_pconvbuffer_size) {
-			cc = (sc->sc_pconvbuffer_size / params->factor
-			      / user_bytes_per_sample) * user_bytes_per_sample;
+			cc = (sc->sc_pconvbuffer_size * 8 / params->factor
+			      / user_bits_per_sample) * user_bits_per_sample / 8;
 		}
 
 #ifdef DIAGNOSTIC
@@ -1579,8 +1590,8 @@
 			printf("audio_write: cc == 0, swcode=%p, factor=%d "
 			       "remain=%d u_bps=%d hw_bps=%d\n",
 			       sc->sc_pparams.sw_code, sc->sc_pparams.factor,
-			       input_remain, user_bytes_per_sample,
-			       hw_bytes_per_sample);
+			       input_remain, user_bits_per_sample,
+			       hw_bits_per_sample);
 			cb->copying = 0;
 			return EINVAL;
 		}
@@ -1619,7 +1630,7 @@
 			sc->sc_pparams.sw_code(sc->hw_hdl,
 					       sc->sc_pconvbuffer, cc);
 			/* Adjust count after the expansion. */
-			cc *= sc->sc_pparams.factor;
+			cc = cc * sc->sc_pparams.factor / sc->sc_pparams.factor_denom;
 			DPRINTFN(1, ("audio_write: expanded cc=%d\n", cc));
 		}
 		/*
Index: audio_if.h
===================================================================
RCS file: /home/isaki/cvsroot/vs/src/sys/dev/audio_if.h,v
retrieving revision 1.1.2.1
retrieving revision 1.7
diff -u -r1.1.2.1 -r1.7
--- audio_if.h	2002/03/02 05:03:38	1.1.2.1
+++ audio_if.h	2002/03/03 05:32:23	1.7
@@ -51,6 +51,7 @@
 	/* Software en/decode functions, set if SW coding required by HW */
 	void	(*sw_code)(void *, u_char *, int);
 	int	factor;				/* coding space change */
+	int factor_denom;		/* coding space change smaller */
 	/*
 	 * The following four members represent what format is used in a
 	 * hardware.  If hw_sample_rate != sample_rate || hw_channels !=
Index: msm6258.c
===================================================================
RCS file: /home/isaki/cvsroot/vs/src/sys/dev/ic/msm6258.c,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -r1.1.1.2 -r1.4
--- msm6258.c	2001/11/17 12:00:28	1.1.1.2
+++ msm6258.c	2002/03/02 14:11:54	1.4
@@ -44,8 +44,8 @@
 #include <sys/audioio.h>
 
 #include <dev/audio_if.h>
-#include <dev/audiovar.h>
 #include <dev/auconv.h>
+#include <dev/audiovar.h>
 #include <dev/mulaw.h>
 #include <dev/ic/msm6258var.h>
 
@@ -135,11 +135,12 @@
 	char *x = &(mc->mc_estim);
 	short *y = &(mc->mc_amp);
 	register int i;
+	u_char *d = p;
 	u_char f;
 
-	for (i = 0; i < cc; i++) {
-		f = pcm2adpcm_step(p[i], y, x);
-		p[i] = f + (pcm2adpcm_step(p[i], y, x) << 4);
+	for (i = 0; i < cc; ) {
+		f = pcm2adpcm_step(p[i++], y, x);
+		*d++ = f + (pcm2adpcm_step(p[i++], y, x) << 4);
 	}
 }
 
Index: msm6258var.h
===================================================================
RCS file: /home/isaki/cvsroot/vs/src/sys/dev/ic/msm6258var.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- msm6258var.h	2001/11/04 13:28:49	1.1.1.1
+++ msm6258var.h	2002/03/02 14:11:54	1.2
@@ -34,8 +34,6 @@
  * OKI MSM6258 ADPCM voice synthesizer codec.
  */
 
-#include <dev/auconv.h>
-
 void *msm6258_codec_init (void);
 void msm6258_ulinear8_to_adpcm (void *, u_char *, int);
 void msm6258_mulaw_to_adpcm (void *, u_char *, int);
Index: vs.c
===================================================================
RCS file: /home/isaki/cvsroot/vs/src/sys/arch/x68k/dev/vs.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 vs.c
--- vs.c	2001/12/24 09:31:20	1.1.1.3
+++ vs.c	2002/03/03 08:33:17
@@ -388,14 +388,18 @@
 
 		rate = p->sample_rate;
 		p->sw_code = NULL;
-		p->factor = 1;
+		p->factor = p->factor_denom = 1;
+		p->hw_precision = 4;
+		p->hw_encoding = AUDIO_ENCODING_ADPCM;
+		DPRINTF(1, ("vs_set_params: encoding=%d, precision=%d\n",
+			p->encoding, p->precision));
 		switch (p->encoding) {
 		case AUDIO_ENCODING_ULAW:
 			if (p->precision != 8)
 				return EINVAL;
 			if (mode == AUMODE_PLAY) {
 				p->sw_code = msm6258_mulaw_to_adpcm;
-				rate = p->sample_rate * 2;
+				p->factor_denom = 2;
 			} else {
 				p->sw_code = msm6258_adpcm_to_mulaw;
 				p->factor = 2;
@@ -407,7 +411,7 @@
 				return EINVAL;
 			if (mode == AUMODE_PLAY) {
 				p->sw_code = msm6258_ulinear8_to_adpcm;
-				rate = p->sample_rate * 2;
+				p->factor_denom = 2;
 			} else {
 				p->sw_code = msm6258_adpcm_to_ulinear8;
 				p->factor = 2;

----Next_Part(Sun_Mar__3_20:42:42_2002_542)----