shithub: npe

Download patch

ref: 481982eca1360fc710e240f6b7757572a1cf8c74
parent: aeecf799ccb7461d436e3c3a07357ca0fff73180
author: Jacob Moody <moody@posixcafe.org>
date: Thu Feb 9 22:01:17 EST 2023

jank mixer

--- a/include/npe/SDL2/SDL_mixer.h
+++ b/include/npe/SDL2/SDL_mixer.h
@@ -13,6 +13,9 @@
 
 typedef struct Mix_Music {
 	int type;
+	int loops;
+	int fd;
+	char *loc;
 } Mix_Music;
 
 typedef void (*Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata);
--- a/libnpe_sdl2/mixer.c
+++ b/libnpe_sdl2/mixer.c
@@ -2,6 +2,22 @@
 
 #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)
 {
@@ -10,7 +26,7 @@
 	USED(channels);
 	USED(chunk);
 
-	return 0; //lies
+	return 0;
 }
 
 char*
@@ -26,6 +42,7 @@
 	USED(f);
 	USED(d);
 	USED(arg);
+	effunc = f;
 	return 1;
 }
 
@@ -62,20 +79,30 @@
 void
 Mix_CloseAudio(void)
 {
-
+	if(audiopid > 0)
+		postnote(PNPROC, audiopid, "quit");
+	audiopid = -1;
 }
 
 int
 Mix_Init(int flags)
 {
-	USED(flags);
-	return 0;
+	audiofd = open("/dev/audio", OWRITE);
+	if(audiofd < 0)
+		return -1;
+
+	audiopid = proccreate(audioproc, nil, 4096);
+	return flags;
 }
 
 int
 Mix_VolumeMusic(int vol)
 {
-	USED(vol);
+	if(vol < 0)
+		vol = 0;
+	else if(vol > 128)
+		vol = 128;
+	musicvol = vol;
 	return 0;
 }
 
@@ -82,28 +109,40 @@
 int
 Mix_PlayingMusic(void)
 {
-	return 0;
+	return forkerpid > 0 && !musicpaused;
 }
 
 int
 Mix_PausedMusic(void)
 {
-	return 0;
+	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;
 }
 
@@ -110,8 +149,9 @@
 int
 Mix_PlayMusic(Mix_Music *music, int loops)
 {
-	USED(music);
-	USED(loops);
+	music->loops = loops;
+	pipe(musicpipe);
+	forkerpid = procrfork(audioforker, music, 4096, RFNOTEG);
 	return 0;
 }
 
@@ -118,7 +158,95 @@
 Mix_Music*
 Mix_LoadMUS_RW(SDL_RWops *src, int freesrc)
 {
-	USED(src);
-	USED(freesrc);
-	return nil;
+	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);
+	}
 }