Index | Thread | Search

From:
George Koehler <kernigh@gmail.com>
Subject:
emulators/minivmac: add sndio for sound
To:
ports@openbsd.org
Cc:
Jag Talon <jag@aangat.lahat.computer>
Date:
Mon, 22 Jul 2024 00:31:00 -0400

Download raw body.

Thread
This diff adds sound to Mini vMac, with files/SGLUSNIO.h using sndio.

The emulator passes sound samples via MySound_BeginWrite and
MySound_EndWrite to the X11 glue OSGLUXWN.c, which collects them into
a ring of 16 buffers of 512 samples each.  The other sound glues (for
ALSA and /dev/dsp) use non-blocking writes in a weird way.  I tried to
use non-blocking writes for sndio, but that caused the sound to go
silent after 3 seconds (at the 3rd call to MySound_SecondNotify).
This diff uses blocking writes.

I have not contacted upstream.  When I do, I plan to change the
license of files/GLUSNIO.h to Mini vMac's license.

Does it work?  Is it ok to commit?
--gkoehler

Index: Makefile
===================================================================
RCS file: /cvs/ports/emulators/minivmac/Makefile,v
diff -u -p -r1.1.1.1 Makefile
--- Makefile	18 Jul 2024 01:58:15 -0000	1.1.1.1
+++ Makefile	22 Jul 2024 03:45:27 -0000
@@ -2,6 +2,7 @@ ONLY_FOR_ARCHS =	i386 amd64 powerpc
 
 COMMENT =		early macintosh emulator
 V =			36.04
+REVISION =		0
 DISTNAME =		minivmac-${V}
 
 CATEGORIES =		emulators
@@ -10,7 +11,7 @@ HOMEPAGE = 		https://gryphel.com/c/miniv
 
 MAINTAINER =		Jag Talon <jag@aangat.lahat.computer>
 
-WANTLIB =		X11 c
+WANTLIB =		X11 c sndio
 
 # GPLv2
 PERMIT_PACKAGE =	Yes
@@ -31,6 +32,9 @@ ALL_TARGET =		minivmac
 SETUP_FLAGS-amd64 = 	-t ob64
 SETUP_FLAGS-i386 = 	-t obsd
 SETUP_FLAGS-powerpc = 	-t obsd -cpu ppc
+
+post-extract:
+	cp ${FILESDIR}/SGLUSNIO.h ${WRKSRC}/src
 
 do-gen:
 	cd ${WRKSRC}; cc setup/tool.c -o setup_t && \
Index: files/SGLUSNIO.h
===================================================================
RCS file: files/SGLUSNIO.h
diff -N files/SGLUSNIO.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/SGLUSNIO.h	22 Jul 2024 03:45:27 -0000
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024 George Koehler <gkoehler@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+	Sound GLUe for SNdIO, https://man.openbsd.org/sio_open.3
+*/
+
+LOCALVAR struct sio_hdl *audio_hdl;
+LOCALVAR int audio_samples_pending;
+
+LOCALPROC MySound_Moved(void *arg, int delta)
+{
+	audio_samples_pending -= delta;
+}
+
+LOCALPROC MySound_Start(void)
+{
+	if (audio_hdl) {
+		MySound_Start0();
+		audio_samples_pending = 0;
+		sio_start(audio_hdl);
+	}
+}
+
+LOCALPROC MySound_Stop(void)
+{
+	if (audio_hdl) {
+		sio_flush(audio_hdl);
+	}
+}
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	struct sio_par par;
+
+	audio_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0 /* blocking */);
+	if (audio_hdl == NULL) {
+		fprintf(stderr, "Cannot open sndio.\n");
+		return trueblnr;
+	}
+
+	sio_initpar(&par);
+	par.bits = 1 << kLn2SoundSampSz;
+	par.sig = 0; /* unsigned samples */
+	par.le = SIO_LE_NATIVE; /* byte order */
+	par.pchan = 1;
+	par.rate = SOUND_SAMPLERATE;
+	par.round = kOneBuffLen;
+	if (!sio_setpar(audio_hdl, &par) ||
+		!sio_getpar(audio_hdl, &par) ||
+		par.bits != 1 << kLn2SoundSampSz || par.sig != 0 ||
+		par.le != SIO_LE_NATIVE || par.pchan != 1 ||
+		par.rate < SOUND_SAMPLERATE * 995 / 1000 ||
+		par.rate > SOUND_SAMPLERATE * 1005 / 1000)
+	{
+		fprintf(stderr, "Cannot set sndio parameters.\n");
+		goto init_error;
+	}
+
+	sio_onmove(audio_hdl, MySound_Moved, NULL);
+	return trueblnr;
+
+init_error:
+	sio_close(audio_hdl);
+	audio_hdl = NULL;
+	return trueblnr;
+}
+
+LOCALPROC MySound_UnInit(void)
+{
+	if (audio_hdl) {
+		sio_close(audio_hdl);
+		audio_hdl = NULL;
+	}
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	tpSoundSamp PlayPtr;
+	ui4b TotPendBuffs;
+
+	if (!MySound_EndWrite0(actL) || !audio_hdl) {
+		return;
+	}
+
+	/* sio_write will call MySound_Moved. */
+	audio_samples_pending += kOneBuffLen;
+
+	/*
+		Play one buffer (of kOneBuffSz bytes).
+		Don't leave part of the buffer for later.
+	*/
+	PlayPtr = TheSoundBuffer + (ThePlayOffset & kAllBuffMask);
+	if (sio_write(audio_hdl, PlayPtr, kOneBuffSz) != kOneBuffSz) {
+		fprintf(stderr, "Error from sndio playing audio!\n");
+		sio_close(audio_hdl);
+		audio_hdl = NULL;
+	}
+	ThePlayOffset += kOneBuffLen;
+
+	TotPendBuffs = audio_samples_pending >> kLnOneBuffLen;
+	if (TotPendBuffs < MinFilledSoundBuffs) {
+		MinFilledSoundBuffs = TotPendBuffs;
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (audio_hdl) {
+		MySound_SecondNotify0();
+	}
+}
Index: patches/patch-setup_SPBLDOPT_i
===================================================================
RCS file: patches/patch-setup_SPBLDOPT_i
diff -N patches/patch-setup_SPBLDOPT_i
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-setup_SPBLDOPT_i	22 Jul 2024 03:45:27 -0000
@@ -0,0 +1,42 @@
+- enable sndio on OpenBSD
+
+Index: setup/SPBLDOPT.i
+--- setup/SPBLDOPT.i.orig
++++ setup/SPBLDOPT.i
+@@ -542,7 +542,8 @@ LOCALFUNC blnr dfo_SoundEnabled(void)
+ 		|| ((gbk_apifam_xwn == gbo_apifam)
+ 			&& ((gbo_targfam == gbk_targfam_linx)
+ 				|| (gbo_targfam == gbk_targfam_fbsd)
+-				|| (gbo_targfam == gbk_targfam_nbsd)));
++				|| (gbo_targfam == gbk_targfam_nbsd)
++				|| (gbo_targfam == gbk_targfam_obsd)));
+ 
+ 	return v;
+ }
+@@ -568,6 +569,7 @@ enum {
+ 	gbk_sndapi_none,
+ 	gbk_sndapi_alsa,
+ 	gbk_sndapi_ddsp,
++	gbk_sndapi_sndio,
+ 	kNumSndApiLevels
+ };
+ 
+@@ -594,6 +596,9 @@ LOCALFUNC char * GetSndApiName(int i)
+ 		case gbk_sndapi_ddsp:
+ 			s = "ddsp";
+ 			break;
++		case gbk_sndapi_sndio:
++			s = "sndio";
++			break;
+ 		default:
+ 			s = "(unknown sound api)";
+ 			break;
+@@ -617,6 +622,8 @@ LOCALFUNC int dfo_sndapi(void)
+ 		v = gbk_sndapi_none;
+ 	} else if (gbo_targfam == gbk_targfam_linx) {
+ 		v = gbk_sndapi_alsa;
++	} else if (gbo_targfam == gbk_targfam_obsd) {
++		v = gbk_sndapi_sndio;
+ 	} else {
+ 		v = gbk_sndapi_ddsp;
+ 	}
Index: patches/patch-setup_SPFILDEF_i
===================================================================
RCS file: patches/patch-setup_SPFILDEF_i
diff -N patches/patch-setup_SPFILDEF_i
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-setup_SPFILDEF_i	22 Jul 2024 03:45:27 -0000
@@ -0,0 +1,15 @@
+- add sndio
+
+Index: setup/SPFILDEF.i
+--- setup/SPFILDEF.i.orig
++++ setup/SPFILDEF.i
+@@ -88,6 +88,9 @@ static void DoMYOSGLUEdepends(tDoOneDepends p)
+ 				case gbk_sndapi_ddsp:
+ 					s = "SGLUDDSP.h";
+ 					break;
++				case gbk_sndapi_sndio:
++					s = "SGLUSNIO.h";
++					break;
+ 			}
+ 
+ 			if (nullpr != s) {
Index: patches/patch-setup_SPOTHRCF_i
===================================================================
RCS file: patches/patch-setup_SPOTHRCF_i
diff -N patches/patch-setup_SPOTHRCF_i
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-setup_SPOTHRCF_i	22 Jul 2024 03:45:27 -0000
@@ -0,0 +1,15 @@
+- add sndio
+
+Index: setup/SPOTHRCF.i
+--- setup/SPOTHRCF.i.orig
++++ setup/SPOTHRCF.i
+@@ -555,6 +555,9 @@ LOCALPROC WriteAppSOUNDGLUcontents(void)
+ 		case gbk_sndapi_ddsp:
+ 			s = "DDSP";
+ 			break;
++		case gbk_sndapi_sndio:
++			s = "SNIO";
++			break;
+ 		default:
+ 			s = "???";
+ 			break;
Index: patches/patch-setup_WRBGCFLS_i
===================================================================
RCS file: patches/patch-setup_WRBGCFLS_i
diff -N patches/patch-setup_WRBGCFLS_i
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-setup_WRBGCFLS_i	22 Jul 2024 03:45:27 -0000
@@ -0,0 +1,14 @@
+- add sndio
+
+Index: setup/WRBGCFLS.i
+--- setup/WRBGCFLS.i.orig
++++ setup/WRBGCFLS.i
+@@ -357,6 +357,8 @@ LOCALPROC WriteBashGccMakeFile(void)
+ 					{
+ 						WriteCStrToDestFile(" -lossaudio");
+ 					}
++				} else if (gbk_sndapi_sndio == gbo_sndapi) {
++					WriteCStrToDestFile(" -lsndio");
+ 				}
+ #endif
+ #if 0
Index: patches/patch-setup_WRCNFGAP_i
===================================================================
RCS file: patches/patch-setup_WRCNFGAP_i
diff -N patches/patch-setup_WRCNFGAP_i
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-setup_WRCNFGAP_i	22 Jul 2024 03:45:27 -0000
@@ -0,0 +1,15 @@
+- add sndio
+
+Index: setup/WRCNFGAP.i
+--- setup/WRCNFGAP.i.orig
++++ setup/WRCNFGAP.i
+@@ -194,6 +194,9 @@ LOCALPROC WriteCommonCNFGRAPIContents(void)
+ 						WriteDestFileLn("#include <sys/soundcard.h>");
+ 					}
+ 					break;
++				case gbk_sndapi_sndio:
++					WriteDestFileLn("#include <sndio.h>");
++					break;
+ 				default:
+ 					break;
+ 			}