audio/mixfs: implement Tstat to obtain buffer size, better underrun handling
This commit is contained in:
parent
9c4ca0a51c
commit
7d9ae4883d
1 changed files with 51 additions and 13 deletions
|
@ -8,6 +8,7 @@ enum {
|
||||||
NBUF = 8*1024,
|
NBUF = 8*1024,
|
||||||
NDELAY = 2048,
|
NDELAY = 2048,
|
||||||
NCHAN = 2,
|
NCHAN = 2,
|
||||||
|
FREQ = 44100,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Stream Stream;
|
typedef struct Stream Stream;
|
||||||
|
@ -83,21 +84,21 @@ void
|
||||||
audioproc(void *)
|
audioproc(void *)
|
||||||
{
|
{
|
||||||
static uchar buf[NBUF*NCHAN*2];
|
static uchar buf[NBUF*NCHAN*2];
|
||||||
int nsleep, fd, i, j, n, m, v;
|
int sweep, fd, i, j, n, m, v;
|
||||||
Stream *s;
|
Stream *s;
|
||||||
uchar *p;
|
uchar *p;
|
||||||
|
|
||||||
threadsetname("audioproc");
|
threadsetname("audioproc");
|
||||||
|
|
||||||
fd = -1;
|
fd = -1;
|
||||||
nsleep = 0;
|
sweep = 0;
|
||||||
for(;;){
|
for(;;){
|
||||||
m = NBUF;
|
m = NBUF;
|
||||||
for(s = streams; s < streams+nelem(streams); s++){
|
for(s = streams; s < streams+nelem(streams); s++){
|
||||||
qlock(s);
|
qlock(s);
|
||||||
if(s->run){
|
if(s->run){
|
||||||
n = (long)(s->wp - mixrp);
|
n = (long)(s->wp - mixrp);
|
||||||
if(n <= 0 && nsleep > 4)
|
if(n <= 0 && (s->used == 0 || sweep))
|
||||||
s->run = 0;
|
s->run = 0;
|
||||||
else if(n < m)
|
else if(n < m)
|
||||||
m = n;
|
m = n;
|
||||||
|
@ -109,20 +110,34 @@ audioproc(void *)
|
||||||
m %= NBUF;
|
m %= NBUF;
|
||||||
|
|
||||||
if(m == 0){
|
if(m == 0){
|
||||||
sleep(1<<nsleep);
|
int ms;
|
||||||
if(nsleep < 7)
|
|
||||||
nsleep++;
|
ms = 100;
|
||||||
else {
|
if(fd >= 0){
|
||||||
close(fd);
|
if(sweep){
|
||||||
fd = -1;
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
} else {
|
||||||
|
/* attempt to sleep just shortly before buffer underrun */
|
||||||
|
ms = seek(fd, 0, 2);
|
||||||
|
if(ms > 0){
|
||||||
|
ms *= 800;
|
||||||
|
ms /= FREQ*NCHAN*2;
|
||||||
|
} else
|
||||||
|
ms = 4;
|
||||||
|
}
|
||||||
|
sweep = 1;
|
||||||
}
|
}
|
||||||
|
sleep(ms);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
sweep = 0;
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
if((fd = open("/dev/audio", OWRITE)) < 0)
|
if((fd = open("/dev/audio", OWRITE)) < 0){
|
||||||
continue;
|
fprint(2, "%s: open /dev/audio: %r\n", argv0);
|
||||||
|
sleep(1000);
|
||||||
nsleep = 0;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
for(i=0; i<m; i++){
|
for(i=0; i<m; i++){
|
||||||
|
@ -179,6 +194,28 @@ fswrite(Req *r)
|
||||||
srvacquire(srv);
|
srvacquire(srv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fsstat(Req *r)
|
||||||
|
{
|
||||||
|
Stream *s;
|
||||||
|
|
||||||
|
if(r->fid->file == nil){
|
||||||
|
respond(r, "bug");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(strcmp(r->fid->file->name, "audio") == 0 && (s = r->fid->aux) != nil){
|
||||||
|
qlock(s);
|
||||||
|
if(s->run){
|
||||||
|
r->d.length = (long)(s->wp - mixrp);
|
||||||
|
r->d.length *= NCHAN*2;
|
||||||
|
} else {
|
||||||
|
r->d.length = 0;
|
||||||
|
}
|
||||||
|
qunlock(s);
|
||||||
|
}
|
||||||
|
respond(r, nil);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fsstart(Srv *)
|
fsstart(Srv *)
|
||||||
{
|
{
|
||||||
|
@ -200,6 +237,7 @@ fsend(Srv *)
|
||||||
Srv fs = {
|
Srv fs = {
|
||||||
.open= fsopen,
|
.open= fsopen,
|
||||||
.write= fswrite,
|
.write= fswrite,
|
||||||
|
.stat= fsstat,
|
||||||
.destroyfid= fsclunk,
|
.destroyfid= fsclunk,
|
||||||
.start= fsstart,
|
.start= fsstart,
|
||||||
.end= fsend,
|
.end= fsend,
|
||||||
|
|
Loading…
Reference in a new issue