ref: 9b9baca20eb6f5b86c460b5e7c0d3733fd5c6983
parent: ceb1c5733da57a554d3e06098eb0d26dc631f684
author: Jacob Moody <moody@posixcafe.org>
date: Sun Feb 12 02:07:20 EST 2023
refactor mixer
--- a/include/npe/SDL2/SDL_mixer.h
+++ b/include/npe/SDL2/SDL_mixer.h
@@ -40,6 +40,7 @@
int Mix_HaltMusic(void);
int Mix_PlayMusic(Mix_Music *music, int loops);
Mix_Music* Mix_LoadMUS_RW(SDL_RWops *src, int freesrc);
+Mix_Music* Mix_LoadMUS(char *filename);
enum {MIX_INIT_MID = 1,
--- a/libnpe_sdl2/mixer.c
+++ b/libnpe_sdl2/mixer.c
@@ -18,14 +18,42 @@
/* FIXME proper chains per channel */
Mix_EffectFunc_t effunc = nil;
+static int doneinit = 0;
+static int devopen = 0;
+
+enum { Maxchan = 16 };+SDL_AudioSpec channels[Maxchan];
+int nchannels = 0;
+
int
-Mix_OpenAudio(int freq, Uint16 format, int channels, int chunk)
+Mix_OpenAudio(int freq, Uint16 format, int nch, int chunk)
{- USED(freq);
- USED(format);
- USED(channels);
- USED(chunk);
+ SDL_AudioSpec *as;
+ int sz;
+ if(devopen)
+ return 0;
+
+ switch(format){+ case 1:
+ case 2:
+ sz = 1;
+ break;
+ case 3:
+ case 4:
+ sz = 2;
+ break;
+ default:
+ werrstr("unsupported format");+ return -1;
+ }
+
+ as = &channels[nchannels++];
+ assert(nchannels < Maxchan);
+ as->freq = freq;
+ as->format = format;
+ as->channels = nch;
+ as->samples = chunk / sz;
return 0;
}
@@ -35,14 +63,33 @@
return "";
}
+static void
+translate(void *arg, Uint8 *buf, int len)
+{+ Mix_EffectFunc_t f;
+
+ f = (Mix_EffectFunc_t)arg;
+
+ f(0, buf, len, nil);
+}
+
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;
+ SDL_AudioSpec *as;
+ int n;
+
+ USED(arg); USED(d);
+ as = channels + chan;
+ as->userdata = f;
+ as->callback = translate;
+ if(devopen){+ werrstr("device already open");+ return -1;
+ }
+ n = SDL_OpenAudioDevice(nil, 0, as, nil, 0);
+ SDL_PauseAudioDevice(2, 0);
+
return 1;
}
@@ -87,11 +134,15 @@
int
Mix_Init(int flags)
{- audiofd = open("/dev/audio", OWRITE);- if(audiofd < 0)
- return -1;
-
- audiopid = proccreate(audioproc, nil, 4096);
+ if(doneinit)
+ return flags;
+ doneinit = 1;
+ memset(channels, 0, sizeof channels);
+ rfork(RFNAMEG);
+ if(rfork(RFPROC|RFFDG) == 0){+ execl("/bin/audio/mixfs", "mixfs", nil);+ sysfatal("exec: %r\n");+ }
return flags;
}
@@ -132,16 +183,10 @@
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;
}
@@ -149,13 +194,50 @@
int
Mix_PlayMusic(Mix_Music *music, int loops)
{- music->loops = loops;
- pipe(musicpipe);
- forkerpid = procrfork(audioforker, music, 4096, RFNOTEG);
- return 0;
+ Waitmsg *wm;
+ int n;
+
+ if(forkerpid > 0)
+ Mix_HaltMusic();
+
+ if((forkerpid = rfork(RFPROC|RFNOTEG)) != 0)
+ return 0;
+
+ n = loops;
+ while(loops == -1 || n-- > 0){+ switch(rfork(RFPROC|RFFDG)){+ case 0:
+ execl("/bin/games/midi", "midi", music->loc, nil);+ sysfatal("exec: %r");+ break;
+ default:
+ wm = wait();
+ if(wm->msg != nil && wm->msg[0] != '\0'){+ fprint(2, "playmusic: %s\n", wm->msg);
+ threadexits(nil);
+ }
+ free(wm);
+ break;
+ }
+ }
+ threadexits(nil);
+ return -1;
}
Mix_Music*
+Mix_LoadMUS(char *filename)
+{+ Mix_Music *m;
+
+ m = calloc(1, sizeof(*m));
+ m->loc = strdup(filename);
+ m->fd = open(filename, OREAD);
+ if(m->fd < 0)
+ sysfatal("LoadMUS: %r");+ return m;
+}
+
+Mix_Music*
Mix_LoadMUS_RW(SDL_RWops *src, int freesrc)
{Mix_Music *m;
@@ -163,90 +245,13 @@
int n;
m = calloc(1, sizeof(*m));
- m->loc = smprint("/tmp/duke3d.mus.%d", getpid());+ m->loc = smprint("/tmp/npesdl.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);
+ seek(m->fd, 0, 0);
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);
- }
}
--
⑨