shithub: riscv

Download patch

ref: 86f316987d68dbd92dac0606b8010e9a937f61ce
parent: cd51302616be31e1654dd2ce02d705c079bd537d
author: cinap_lenrek <cinap_lenrek@localhost>
date: Sat Jul 2 23:42:37 EDT 2011

audio: add delay control

--- a/sys/src/9/pc/audioac97.c
+++ b/sys/src/9/pc/audioac97.c
@@ -56,6 +56,7 @@
 	int sis7012;
 
 	/* for probe */
+	Audio *adev;
 	Pcidev *pcidev;
 	Ctlr *next;
 };
@@ -286,6 +287,14 @@
 	return available(&ctlr->outring);
 }
 
+static int
+outrate(void *arg)
+{
+	Ctlr *ctlr = arg;
+	int delay = ctlr->adev->delay*BytesPerSample;
+	return (delay <= 0) || (buffered(&ctlr->outring) <= delay);
+}
+
 static long
 ac97write(Audio *adev, void *vp, long n, vlong)
 {
@@ -312,7 +321,7 @@
 		}
 		p += n;
 	}
-
+	sleep(&ring->r, outrate, ctlr);
 	return p - (uchar*)vp;
 }
 
@@ -383,6 +392,7 @@
 
 Found:
 	adev->ctlr = ctlr;
+	ctlr->adev = adev;
 	if(p->vid == 0x1039 && p->did == 0x7012)
 		ctlr->sis7012 = 1;
 
--- a/sys/src/9/pc/audioac97mix.c
+++ b/sys/src/9/pc/audioac97mix.c
@@ -110,6 +110,7 @@
 	Vrecgain,
 	Vmicgain,
 	Vspeed,
+	Vdelay,
 };
 
 static Volume voltab[] = {
@@ -128,6 +129,7 @@
 	[Vrecgain] "recgain", 0x1c, 15, Stereo, 0,
 	[Vmicgain] "micgain", 0x1e, 15, Right, Capmic,
 	[Vspeed] "speed", 0x2c, 0, Absolute, 0,
+	[Vdelay] "delay", 0, 0, Absolute, 0,
 	0
 };
 
@@ -149,6 +151,10 @@
 	vol = voltab+x;
 	switch(vol->type){
 	case Absolute:
+		if(x == Vdelay){
+			a[0] = adev->delay;
+			break;
+		}
 		a[0] = m->rr(adev, vol->reg);
 		break;
 	default:
@@ -174,7 +180,13 @@
 	vol = voltab+x;
 	switch(vol->type){
 	case Absolute:
-		m->wr(adev, vol->reg, a[0]);
+		if(x == Vdelay){
+			adev->delay = a[0];
+			return 0;
+		}
+		m->wr(adev, vol->reg, a[0]);		
+		if(x == Vspeed)
+			adev->speed = m->rr(adev, vol->reg);
 		break;
 	case Left:
 		v = (vol->range - a[0]) & 0x7f;
--- a/sys/src/9/pc/audiohda.c
+++ b/sys/src/9/pc/audiohda.c
@@ -277,7 +277,8 @@
 	Lock;			/* interrupt lock */
 	QLock;			/* command lock */
 	Rendez outr;
-	
+
+	Audio *adev;
 	Pcidev *pcidev;
 	
 	uchar *mem;
@@ -991,6 +992,14 @@
 }
 
 static int
+outrate(void *arg)
+{
+	Ctlr *ctlr = arg;
+	int delay = ctlr->adev->delay*4;
+	return (delay <= 0) || (ringused(&ctlr->ring) <= delay) || (ctlr->active == 0);
+}
+
+static int
 checkptr(Ctlr *ctlr)
 {
 	Ring *r;
@@ -1082,6 +1091,7 @@
 		}
 	}
 	hdakick(ctlr);
+	sleep(&ctlr->outr, outrate, ctlr);
 	return vn;
 }
 
@@ -1094,26 +1104,57 @@
 	hdakick(ctlr);
 }
 
+enum {
+	Vmaster,
+	Vspeed,
+	Vdelay,
+	Nvol,
+};
+
 static Volume voltab[] = {
-	[0] "master", 0, 0x7f, Stereo, 0,
+	[Vmaster] "master", 0, 0x7f, Stereo, 0,
+	[Vspeed] "speed", 0, 0, Absolute, 0,
+	[Vdelay] "delay", 0, 0, Absolute, 0,
 	0
 };
 
 static int
-hdagetvol(Audio *adev, int, int a[2])
+hdagetvol(Audio *adev, int x, int a[2])
 {
 	Ctlr *ctlr = adev->ctlr;
-	if(ctlr->amp != nil)
-		getoutamp(ctlr->amp, a);
+
+	switch(x){
+	case Vmaster:
+		if(ctlr->amp != nil)
+			getoutamp(ctlr->amp, a);
+		break;
+	case Vspeed:
+		a[0] = adev->speed;
+		break;
+	case Vdelay:
+		a[0] = adev->delay;
+		break;
+	}
 	return 0;
 }
 
 static int
-hdasetvol(Audio *adev, int, int a[2])
+hdasetvol(Audio *adev, int x, int a[2])
 {
 	Ctlr *ctlr = adev->ctlr;
-	if(ctlr->amp != nil)
-		setoutamp(ctlr->amp, 0, a);
+
+	switch(x){
+	case Vmaster:
+		if(ctlr->amp != nil)
+			setoutamp(ctlr->amp, 0, a);
+		break;
+	case Vspeed:
+		adev->speed = a[0];
+		break;
+	case Vdelay:
+		adev->delay = a[0];
+		break;
+	}
 	return 0;
 }
 
@@ -1122,13 +1163,13 @@
 {
 	memmove(vt, voltab, sizeof(voltab));
 	if(ctlr->amp != nil)
-		vt[0].range = getoutamprange(ctlr->amp);
+		vt[Vmaster].range = getoutamprange(ctlr->amp);
 }
 
 static long
 hdavolread(Audio *adev, void *a, long n, vlong)
 {
-	Volume voltab[2];
+	Volume voltab[Nvol+1];
 	fillvoltab(adev->ctlr, voltab);
 	return genaudiovolread(adev, a, n, 0, voltab, hdagetvol, 0);
 }
@@ -1136,7 +1177,7 @@
 static long
 hdavolwrite(Audio *adev, void *a, long n, vlong)
 {
-	Volume voltab[2];
+	Volume voltab[Nvol+1];
 	fillvoltab(adev->ctlr, voltab);
 	return genaudiovolwrite(adev, a, n, 0, voltab, hdasetvol, 0);
 }
@@ -1342,6 +1383,7 @@
 
 Found:
 	adev->ctlr = ctlr;
+	ctlr->adev = adev;
 
 	irq = p->intl;
 	tbdf = p->tbdf;
--- a/sys/src/9/pc/audiosb16.c
+++ b/sys/src/9/pc/audiosb16.c
@@ -28,6 +28,7 @@
 	Vigain,
 	Vogain,
 	Vspeed,
+	Vdelay,
 	Nvol,
 
 	Blocksize	= 4096,
@@ -94,6 +95,7 @@
 	[Vigain] "recgain", 0x3f, 0xff, Stereo, 0,
 	[Vogain] "outgain", 0x41, 0xff, Stereo, 0,
 	[Vspeed] "speed", 0, 0, Absolute, 0,
+	[Vdelay] "delay", 0, 0, Absolute, 0,
 	0,
 };
 
@@ -239,15 +241,21 @@
 	Ctlr *ctlr = adev->ctlr;
 	Volume *vol;
 
-	if(x == Vspeed){
-		ctlr->lvol[x] = ctlr->rvol[x] = a[0];
-		return 0;
-	}
-
 	vol = voltab+x;
 	blaster = &ctlr->blaster;
 	ilock(blaster);
 	switch(vol->type){
+	case Absolute:
+		switch(x){
+		case Vdelay:
+			adev->delay = a[0];
+			break;
+		case Vspeed:
+			adev->speed = a[0];
+			break;
+		}
+		ctlr->lvol[x] = ctlr->rvol[x] = a[0];
+		break;
 	case Stereo:
 		ctlr->rvol[x] = a[1];
 		mxcmd(blaster, vol->reg+1, a[1]);
@@ -314,7 +322,7 @@
 		sbcmd(blaster, 0x42);	/* input sampling rate */
 	else
 		sbcmd(blaster, 0x41);	/* output sampling rate */
-	speed = ctlr->lvol[Vspeed];
+	speed = ctlr->adev->speed;
 	sbcmd(blaster, speed>>8);
 	sbcmd(blaster, speed);
 
@@ -380,7 +388,7 @@
 	/*
 	 * Set the speed.
 	 */
-	speed = ctlr->lvol[Vspeed];
+	speed = ctlr->adev->speed;
 	if(speed < 4000)
 		speed = 4000;
 	else if(speed > 48000)
@@ -524,6 +532,14 @@
 	return available(&ctlr->ring) || inactive(ctlr);
 }
 
+static int
+ratebuf(void *arg)
+{
+	Ctlr *ctlr = arg;
+	int delay = ctlr->adev->delay*4;
+	return (delay <= 0) || (buffered(&ctlr->ring) <= delay) || inactive(ctlr);
+}
+
 static long
 audiowrite(Audio *adev, void *vp, long n, vlong)
 {
@@ -546,6 +562,7 @@
 		}
 		p += n;
 	}
+	sleep(&ctlr->vous, ratebuf, ctlr);
 	return p - (uchar*)vp;
 }
 
--- a/sys/src/9/port/audioif.h
+++ b/sys/src/9/port/audioif.h
@@ -21,6 +21,9 @@
 	long (*status)(Audio *, void *, long, vlong);
 	long (*buffered)(Audio *);
 
+	int delay;
+	int speed;
+
 	int ctlrno;
 	Audio *next;
 };
--- a/sys/src/9/port/devaudio.c
+++ b/sys/src/9/port/devaudio.c
@@ -38,7 +38,7 @@
 static Dirtab audiodir[] = {
 	".",	{Qdir, 0, QTDIR},	0,	DMDIR|0555,
 	"audio",	{Qaudio},	0,	0666,
-	"audioctl",	{Qaudioctl},	0,	0666,
+	"audioctl",	{Qaudioctl},	0,	0222,
 	"audiostat",	{Qaudiostatus},	0,	0444,
 	"volume",	{Qvolume},	0,	0666,
 };
@@ -140,28 +140,22 @@
 
 	i = 1<<adev->ctlrno;
 	if((attached & i) == 0 && adev->volwrite){
-		attached |= i;
+		static char *settings[] = {
+			"speed 44100",
+			"delay 882",	/* 20 ms */
+			"master 100",
+			"audio 100",
+			"head 100",
+		};
 
-		strcpy(ac->buf, "speed 44100");
-		if(!waserror()){
-			adev->volwrite(adev, ac->buf, strlen(ac->buf), 0);
-			poperror();
+		attached |= i;
+		for(i=0; i<nelem(settings); i++){
+			strcpy(ac->buf, settings[i]);
+			if(!waserror()){
+				adev->volwrite(adev, ac->buf, strlen(ac->buf), 0);
+				poperror();
+			}
 		}
-		strcpy(ac->buf, "master 100");
-		if(!waserror()){
-			adev->volwrite(adev, ac->buf, strlen(ac->buf), 0);
-			poperror();
-		}
-		strcpy(ac->buf, "audio 100");
-		if(!waserror()){
-			adev->volwrite(adev, ac->buf, strlen(ac->buf), 0);
-			poperror();
-		}
-		strcpy(ac->buf, "head 100");
-		if(!waserror()){
-			adev->volwrite(adev, ac->buf, strlen(ac->buf), 0);
-			poperror();
-		}
 	}
 
 	return c;
@@ -202,9 +196,6 @@
 	case Qaudio:
 		fn = adev->read;
 		break;
-	case Qaudioctl:
-		fn = adev->ctl;
-		break;
 	case Qaudiostatus:
 		fn = adev->status;
 		break;
@@ -221,7 +212,6 @@
 		nexterror();
 	}
 	switch((ulong)c->qid.path){
-	case Qaudioctl:
 	case Qaudiostatus:
 	case Qvolume:
 		/* generate the text on first read */