ref: 80d7f985cb1d0b8aa8702a95edfa71dd9ec10a37
dir: /libnpe_sdl2/mixer.c/
#include "_sdl.h" #include <SDL2/SDL_mixer.h> int audiofd = -1; int musicpipe[2] = {-1, -1}; static int forkerpid = -1; static int audiopid = -1; void audioexec(void *); void audioforker(void *); void audioproc(void *); static int musicvol = 128; static int musicpaused = 0; /* FIXME proper chains per channel */ Mix_EffectFunc_t effunc = nil; int Mix_OpenAudio(int freq, Uint16 format, int channels, int chunk) { USED(freq); USED(format); USED(channels); USED(chunk); return 0; } char* Mix_GetError(void) { return ""; } int Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void *arg) { USED(chan); USED(f); USED(d); USED(arg); effunc = f; return 1; } Mix_Chunk* Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len) { USED(mem); USED(len); return nil; } int Mix_PlayChannel(int chan, Mix_Chunk *chunk, int loops) { USED(chan); USED(chunk); USED(loops); return -1; } int Mix_HaltChannel(int channel) { USED(channel); return 0; } void Mix_FreeChunk(Mix_Chunk *c) { USED(c); } void Mix_CloseAudio(void) { if(audiopid > 0) postnote(PNPROC, audiopid, "quit"); audiopid = -1; } int Mix_Init(int flags) { audiofd = open("/dev/audio", OWRITE); if(audiofd < 0) return -1; audiopid = proccreate(audioproc, nil, 4096); return flags; } int Mix_VolumeMusic(int vol) { if(vol < 0) vol = 0; else if(vol > 128) vol = 128; musicvol = vol; return 0; } int Mix_PlayingMusic(void) { return forkerpid > 0 && !musicpaused; } int Mix_PausedMusic(void) { return musicpaused; } void Mix_ResumeMusic(void) { musicpaused = 0; } void Mix_PauseMusic(void) { musicpaused = 1; } int Mix_HaltMusic(void) { int x, y; if(forkerpid < 0) return 0; postnote(PNGROUP, forkerpid, "halt"); x = musicpipe[0]; y = musicpipe[1]; musicpipe[0] = -1; musicpipe[1] = -1; close(x); close(y); forkerpid = -1; return 0; } int Mix_PlayMusic(Mix_Music *music, int loops) { music->loops = loops; pipe(musicpipe); forkerpid = procrfork(audioforker, music, 4096, RFNOTEG); return 0; } Mix_Music* Mix_LoadMUS_RW(SDL_RWops *src, int freesrc) { Mix_Music *m; char buf[1024]; int n; m = calloc(1, sizeof(*m)); m->loc = smprint("/tmp/duke3d.mus.%d", getpid()); m->fd = create(m->loc, ORDWR|ORCLOSE, 0666); while((n = SDL_RWread(src, buf, 1, sizeof buf)) > 0) write(m->fd, buf, n); if(freesrc) SDL_RWclose(src); return m; } void audioexec(void *arg) { Mix_Music *m; int i; m = arg; seek(m->fd, 0, 0); dup(musicpipe[0], 1); dup(m->fd, 0); close(musicpipe[1]); procexecl(nil, "/bin/games/midi", "midi", "-c", nil); } void audioforker(void *arg) { Mix_Music *m; Waitmsg *wm; Channel *c; m = arg; c = threadwaitchan(); while(m->loops-- != 0){ procrfork(audioexec, m, 4096, RFFDG); wm = recvp(c); if(wm->msg != nil){ fprint(2, "err %s\n", wm->msg); free(wm); break; } free(wm); } } void audioproc(void *) { static uchar buf[1024]; static uchar sounds[1024]; s16int *mu; s16int *so; int i, n; long v; mu = (s16int*)buf; so = (s16int*)sounds; for(;;){ memset(buf, 0, sizeof buf); if(musicpipe[1] > 0 && !musicpaused){ n = read(musicpipe[1], buf, sizeof buf); if(n < 0) continue; for(i = 0; i < n/sizeof(*mu); i++) mu[i] = ((long)mu[i] * musicvol)/128; } else { n = 0; } if(effunc != nil){ effunc(0, sounds, sizeof sounds, nil); for(i = 0; i < sizeof sounds/sizeof(*so); i++){ v = mu[i] + so[i]; if(v > 0x7fff) v = 0x7fff; else if(v < -0x8000) v = -0x8000; mu[i] = v; } n = sizeof sounds; } write(audiofd, buf, n); } }