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 */