audio: add delay control
This commit is contained in:
parent
cd51302616
commit
86f316987d
6 changed files with 119 additions and 45 deletions
|
@ -56,6 +56,7 @@ struct Ctlr {
|
|||
int sis7012;
|
||||
|
||||
/* for probe */
|
||||
Audio *adev;
|
||||
Pcidev *pcidev;
|
||||
Ctlr *next;
|
||||
};
|
||||
|
@ -286,6 +287,14 @@ outavail(void *arg)
|
|||
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 @@ ac97write(Audio *adev, void *vp, long n, vlong)
|
|||
}
|
||||
p += n;
|
||||
}
|
||||
|
||||
sleep(&ring->r, outrate, ctlr);
|
||||
return p - (uchar*)vp;
|
||||
}
|
||||
|
||||
|
@ -383,6 +392,7 @@ ac97reset(Audio *adev)
|
|||
|
||||
Found:
|
||||
adev->ctlr = ctlr;
|
||||
ctlr->adev = adev;
|
||||
if(p->vid == 0x1039 && p->did == 0x7012)
|
||||
ctlr->sis7012 = 1;
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ enum {
|
|||
Vrecgain,
|
||||
Vmicgain,
|
||||
Vspeed,
|
||||
Vdelay,
|
||||
};
|
||||
|
||||
static Volume voltab[] = {
|
||||
|
@ -128,6 +129,7 @@ static Volume voltab[] = {
|
|||
[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 @@ ac97volget(Audio *adev, int x, int a[2])
|
|||
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 @@ ac97volset(Audio *adev, int x, int a[2])
|
|||
vol = voltab+x;
|
||||
switch(vol->type){
|
||||
case Absolute:
|
||||
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;
|
||||
|
|
|
@ -278,6 +278,7 @@ struct Ctlr {
|
|||
QLock; /* command lock */
|
||||
Rendez outr;
|
||||
|
||||
Audio *adev;
|
||||
Pcidev *pcidev;
|
||||
|
||||
uchar *mem;
|
||||
|
@ -990,6 +991,14 @@ outavail(void *arg)
|
|||
return ringavail(arg) > 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1082,6 +1091,7 @@ hdawrite(Audio *adev, void *vp, long vn, vlong)
|
|||
}
|
||||
}
|
||||
hdakick(ctlr);
|
||||
sleep(&ctlr->outr, outrate, ctlr);
|
||||
return vn;
|
||||
}
|
||||
|
||||
|
@ -1094,26 +1104,57 @@ hdaclose(Audio *adev)
|
|||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 @@ fillvoltab(Ctlr *ctlr, Volume *vt)
|
|||
{
|
||||
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 @@ hdavolread(Audio *adev, void *a, long n, vlong)
|
|||
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 @@ hdareset(Audio *adev)
|
|||
|
||||
Found:
|
||||
adev->ctlr = ctlr;
|
||||
ctlr->adev = adev;
|
||||
|
||||
irq = p->intl;
|
||||
tbdf = p->tbdf;
|
||||
|
|
|
@ -28,6 +28,7 @@ enum
|
|||
Vigain,
|
||||
Vogain,
|
||||
Vspeed,
|
||||
Vdelay,
|
||||
Nvol,
|
||||
|
||||
Blocksize = 4096,
|
||||
|
@ -94,6 +95,7 @@ static Volume voltab[] = {
|
|||
[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 @@ mxsetvol(Audio *adev, int x, int a[2])
|
|||
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 @@ sb16startdma(Ctlr *ctlr)
|
|||
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 @@ ess1688startdma(Ctlr *ctlr)
|
|||
/*
|
||||
* Set the speed.
|
||||
*/
|
||||
speed = ctlr->lvol[Vspeed];
|
||||
speed = ctlr->adev->speed;
|
||||
if(speed < 4000)
|
||||
speed = 4000;
|
||||
else if(speed > 48000)
|
||||
|
@ -524,6 +532,14 @@ anybuf(void *arg)
|
|||
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 @@ audiowrite(Audio *adev, void *vp, long n, vlong)
|
|||
}
|
||||
p += n;
|
||||
}
|
||||
sleep(&ctlr->vous, ratebuf, ctlr);
|
||||
return p - (uchar*)vp;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ struct Audio
|
|||
long (*status)(Audio *, void *, long, vlong);
|
||||
long (*buffered)(Audio *);
|
||||
|
||||
int delay;
|
||||
int speed;
|
||||
|
||||
int ctlrno;
|
||||
Audio *next;
|
||||
};
|
||||
|
|
|
@ -38,7 +38,7 @@ enum {
|
|||
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,27 +140,21 @@ audioattach(char *spec)
|
|||
|
||||
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");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,9 +196,6 @@ audioread(Chan *c, void *a, long n, vlong off)
|
|||
case Qaudio:
|
||||
fn = adev->read;
|
||||
break;
|
||||
case Qaudioctl:
|
||||
fn = adev->ctl;
|
||||
break;
|
||||
case Qaudiostatus:
|
||||
fn = adev->status;
|
||||
break;
|
||||
|
@ -221,7 +212,6 @@ audioread(Chan *c, void *a, long n, vlong off)
|
|||
nexterror();
|
||||
}
|
||||
switch((ulong)c->qid.path){
|
||||
case Qaudioctl:
|
||||
case Qaudiostatus:
|
||||
case Qvolume:
|
||||
/* generate the text on first read */
|
||||
|
|
Loading…
Reference in a new issue