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 <gkoeh...@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; + }