ref: a6ffb6a8ffefb4806f659ae05d730eaa6f486191
dir: /snd.c/
#include <u.h> #include <libc.h> #include <stdio.h> #include <thread.h> #include "quakedef.h" enum{ Nbuf = 8 }; static int afd; static int stid = -1; static uint wpos; static Channel *schan; static QLock sndlock; static void sproc(void *) { int n; for(;;){ if(recv(schan, nil) < 0) break; if((n = write(afd, shm->buffer, SNBUF)) != SNBUF) break; qlock(&sndlock); wpos += n; qunlock(&sndlock); } } qboolean SNDDMA_Init(void) { if((afd = open("/dev/audio", OWRITE)) < 0){ fprint(2, "open: %r\n"); return 0; } shm = &sn; shm->splitbuffer = 0; shm->submission_chunk = 1; shm->samplebits = SAMPLESZ; shm->speed = RATE; shm->channels = 2; shm->samples = NSAMPLE; shm->samplepos = 0; if((shm->buffer = mallocz(SNBUF, 1)) == nil) sysfatal("mallocz: %r\n"); wpos = 0; if((schan = chancreate(sizeof(int), Nbuf)) == nil) sysfatal("SNDDMA_Init:chancreate: %r"); if((stid = proccreate(sproc, nil, 8192)) < 0) sysfatal("SNDDMA_Init:proccreate: %r"); return 1; } uint SNDDMA_GetDMAPos(void) { if(stid < 0) return 0; qlock(&sndlock); shm->samplepos = wpos / SAMPLEB; qunlock(&sndlock); return shm->samplepos; } void SNDDMA_Shutdown(void) { if(stid < 0) return; threadint(stid); stid = -1; close(afd); free(shm->buffer); if(schan != nil) chanfree(schan); schan = nil; } void SNDDMA_Submit(void) { if(nbsend(schan, nil) < 0){ fprint(2, "SNDDMA_Submit:nbsend: %r\n"); SNDDMA_Shutdown(); } }