diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e710f52..284cf19d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -143,6 +143,10 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
   configure_file("${CMAKE_SOURCE_DIR}/cmake/cpack/${CMAKE_PROJECT_NAME}.desktop.in"
     "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.desktop" @ONLY)
 
+elseif(${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+  set(OPENBSD TRUE)
+  set(HAVE_SNDIO TRUE)
+
 elseif(APPLE)
   if("${CMAKE_OSX_DEPLOYMENT_TARGET}" STREQUAL "")
     message(STATUS "Build for macOS target: local version")
@@ -276,6 +280,12 @@ if(LINUX)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_CM108")
   endif()
 
+elseif (HAVE_SNDIO)
+  find_package(sndio REQUIRED)
+  if(SNDIO_FOUND)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_SNDIO")
+  endif()
+
 elseif (NOT WIN32 AND NOT CYGWIN)
   find_package(Portaudio REQUIRED)
   if(PORTAUDIO_FOUND)
@@ -289,6 +299,8 @@ else()
   set(UDEV_LIBRARIES "")
   set(PORTAUDIO_INCLUDE_DIRS "")
   set(PORTAUDIO_LIBRARIES "")
+  set(SNDIO_INCLUDE_DIRS "")
+  set(SNDIO_LIBRARIES "")
 endif()
 
 # manage and fetch new data
diff --git a/cmake/modules/Findsndio.cmake b/cmake/modules/Findsndio.cmake
new file mode 100644
index 00000000..e7292d5d
--- /dev/null
+++ b/cmake/modules/Findsndio.cmake
@@ -0,0 +1,42 @@
+# - Try to find sndio
+#
+#  SNDIO_FOUND - system has sndio
+#  SNDIO_LIBRARIES - location of the library for sndio
+#  SNDIO_INCLUDE_DIRS - location of the include files for sndio
+
+set(SNDIO_ROOT_DIR
+  "${SNDIO_ROOT_DIR}"
+  CACHE
+  PATH
+  "Directory to search for sndio")
+
+# no need to check pkg-config
+
+find_path(SNDIO_INCLUDE_DIRS
+  NAMES
+  sndio.h
+  PATHS
+  /usr/local/include
+  /usr/include
+  /opt/local/include
+  HINTS
+  ${SNDIO_ROOT_DIR}
+  )
+
+find_library(SNDIO_LIBRARIES
+  NAMES
+  sndio
+  PATHS
+  /usr/local/lib
+  /usr/lib
+  /usr/lib64
+  /opt/local/lib
+  HINTS
+  ${SNDIIO_ROOT_DIR}
+  )
+
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SNDIO DEFAULT_MSG SNDIO_INCLUDE_DIRS SNDIO_LIBRARIES)
+
+mark_as_advanced(SNDIO_INCLUDE_DIRS SNDIO_LIBRARIES)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 46d3ac7a..5325e36a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories(
   ${ALSA_INCLUDE_DIRS}
   ${UDEV_INCLUDE_DIRS}
   ${PORTAUDIO_INCLUDE_DIRS}
+  ${SNDIO_INCLUDE_DIRS}
   ${CUSTOM_GEOTRANZ_DIR}
   )
 
@@ -107,7 +108,11 @@ if(LINUX)
     list(REMOVE_ITEM direwolf_SOURCES
       dwgpsd.c
       )
-  else() # macOS freebsd openbsd
+  elseif(HAVE_SNDIO)
+    list(APPEND direwolf_SOURCES
+      audio.c
+      )
+  else() # macOS freebsd
     list(APPEND direwolf_SOURCES
       audio_portaudio.c
       )
@@ -127,6 +132,7 @@ target_link_libraries(direwolf
   ${ALSA_LIBRARIES}
   ${UDEV_LIBRARIES}
   ${PORTAUDIO_LIBRARIES}
+  ${SNDIO_LIBRARIES}
   )
 
 if(WIN32 OR CYGWIN)
diff --git a/src/audio.c b/src/audio.c
index 613be06d..60fcac79 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -75,18 +75,17 @@
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <errno.h>
 
 
 #if USE_ALSA
 #include <alsa/asoundlib.h>
-#else
-#include <errno.h>
-#ifdef __OpenBSD__
-#include <soundcard.h>
+#elif USE_SNDIO
+#include <sndio.h>
+#include <poll.h>
 #else
 #include <sys/soundcard.h>
 #endif
-#endif
 
 
 #include "audio.h"
@@ -111,6 +110,9 @@ static struct adev_s {
 
 	int bytes_per_frame;		/* number of bytes for a sample from all channels. */
 					/* e.g. 4 for stereo 16 bit. */
+#elif USE_SNDIO
+	struct sio_hdl *sndio_in_handle;
+	struct sio_hdl *sndio_out_handle;
 
 #else
 	int oss_audio_device_fd;	/* Single device, both directions. */
@@ -141,6 +143,8 @@ static struct adev_s {
 #if USE_ALSA
 static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *name, char *dir);
 //static void alsa_select_device (char *pick_dev, int direction, char *result);
+#elif USE_SNDIO
+static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname, char *inout);
 #else
 static int set_oss_params (int a, int fd, struct audio_s *pa);
 #endif
@@ -212,7 +216,9 @@ static int calcbufsize(int rate, int chans, int bits)
 
 int audio_open (struct audio_s *pa)
 {
+#if !USE_SNDIO
 	int err;
+#endif
 	int chan;
 	int a;
 	char audio_in_name[30];
@@ -224,7 +230,11 @@ int audio_open (struct audio_s *pa)
 	memset (adev, 0, sizeof(adev));
 
 	for (a=0; a<MAX_ADEVS; a++) {
-#ifndef USE_ALSA
+#if USE_ALSA
+	  adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
+#elif USE_SNDIO
+	  adev[a].sndio_in_handle = adev[a].sndio_out_handle = NULL;
+#else
 	  adev[a].oss_audio_device_fd = -1;
 #endif
 	  adev[a].udp_sock = -1;
@@ -348,6 +358,24 @@ int audio_open (struct audio_s *pa)
 
 	        adev[a].inbuf_size_in_bytes = set_alsa_params (a, adev[a].audio_in_handle, pa, audio_in_name, "input");
 	    
+#elif USE_SNDIO
+		adev[a].sndio_in_handle = sio_open (audio_in_name, SIO_REC, 0);
+		if (adev[a].sndio_in_handle == NULL) {
+		  text_color_set(DW_COLOR_ERROR);
+		  dw_printf ("Could not open audio device %s for input\n",
+			audio_in_name);
+		  return (-1);
+		}
+
+		adev[a].inbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_in_handle, pa, audio_in_name, "input");
+
+		if (!sio_start (adev[a].sndio_in_handle)) {
+		  text_color_set(DW_COLOR_ERROR);
+		  dw_printf ("Could not start audio device %s for input\n",
+			audio_in_name);
+		  return (-1);
+		}
+
 #else // OSS
 	        adev[a].oss_audio_device_fd = open (pa->adev[a].adevice_in, O_RDWR);
 
@@ -439,6 +467,27 @@ int audio_open (struct audio_s *pa)
 	      return (-1);
 	    }
 
+#elif USE_SNDIO
+	    adev[a].sndio_out_handle = sio_open (audio_out_name, SIO_PLAY, 0);
+	    if (adev[a].sndio_out_handle == NULL) {
+	      text_color_set(DW_COLOR_ERROR);
+	      dw_printf ("Could not open audio device %s for output\n",
+			audio_out_name);
+	      return (-1);
+	    }
+
+	    adev[a].outbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_out_handle, pa, audio_out_name, "output");
+
+	    if (adev[a].inbuf_size_in_bytes <= 0 || adev[a].outbuf_size_in_bytes <= 0) {
+	      return (-1);
+	    }
+
+	    if (!sio_start (adev[a].sndio_out_handle)) {
+	      text_color_set(DW_COLOR_ERROR);
+	      dw_printf ("Could not start audio device %s for output\n",
+			audio_out_name);
+	      return (-1);
+	    }
 #endif
 
 /*
@@ -675,6 +724,80 @@ static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *
 } /* end alsa_set_params */
 
 
+#elif USE_SNDIO
+
+/*
+ * Set parameters for sound card. (sndio)
+ *
+ * See  /usr/include/sndio.h  for details.
+ */
+
+static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname, char *inout)
+{
+
+	struct sio_par q, r;
+
+	/* Signed 16 bit little endian or unsigned 8 bit. */
+	sio_initpar (&q);
+	q.bits = pa->adev[a].bits_per_sample;
+	q.bps = (q.bits + 7) / 8;
+	q.sig = (q.bits == 8) ? 0 : 1;
+	q.le = 1; /* always little endian */
+	q.msb = 0; /* LSB aligned */
+	q.rchan = q.pchan = pa->adev[a].num_channels;
+	q.rate = pa->adev[a].samples_per_sec;
+	q.xrun = SIO_IGNORE;
+	q.appbufsz = calcbufsize(pa->adev[a].samples_per_sec, pa->adev[a].num_channels, pa->adev[a].bits_per_sample);
+
+
+#if DEBUG
+	text_color_set(DW_COLOR_DEBUG);
+	dw_printf ("suggest buffer size %d bytes for %s %s.\n",
+		q.appbufsz, devname, inout);
+#endif
+
+	/* challenge new setting */
+	if (!sio_setpar (handle, &q)) {
+	  text_color_set(DW_COLOR_ERROR);
+	  dw_printf ("Could not set hardware parameter for %s %s.\n",
+		devname, inout);
+	  return (-1);
+	}
+
+	/* get response */
+	if (!sio_getpar (handle, &r)) {
+	  text_color_set(DW_COLOR_ERROR);
+	  dw_printf ("Could not obtain current hardware setting for %s %s.\n",
+		devname, inout);
+	  return (-1);
+	}
+
+#if DEBUG
+	text_color_set(DW_COLOR_DEBUG);
+	dw_printf ("audio buffer size %d bytes for %s %s.\n",
+		r.appbufsz, devname, inout);
+#endif
+	if (q.rate != r.rate) {
+	  text_color_set(DW_COLOR_INFO);
+	  dw_printf ("Asked for %d samples/sec but got %d for %s %s.",
+		     pa->adev[a].samples_per_sec, r.rate, devname, inout);
+	  pa->adev[a].samples_per_sec = r.rate;
+	}
+
+	/* not supported */
+	if (q.bits != r.bits || q.bps != r.bps || q.sig != r.sig ||
+	    (q.bits > 8 && q.le != r.le) ||
+	    (*inout == 'o' && q.pchan != r.pchan) ||
+	    (*inout == 'i' && q.rchan != r.rchan)) {
+	  text_color_set(DW_COLOR_ERROR);
+	  dw_printf ("Unsupported format for %s %s.\n", devname, inout);
+	  return (-1);
+	}
+
+	return r.appbufsz;
+
+} /* end set_sndio_params */
+
 #else
 
 
@@ -842,7 +965,9 @@ __attribute__((hot))
 int audio_get (int a)
 {
 	int n;
+#if USE_ALSA
 	int retries = 0;
+#endif
 
 #if STATISTICS
 	/* Gather numbers for read from audio device. */
@@ -970,7 +1095,22 @@ int audio_get (int a)
 	    }
 
 
-#else	/* end ALSA, begin OSS */
+#elif USE_SNDIO
+
+	    while (adev[a].inbuf_next >= adev[a].inbuf_len) {
+
+	      assert (adev[a].sndio_in_handle != NULL);
+	      n = sio_read (adev[a].sndio_in_handle, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes);
+	      adev[a].inbuf_len = n;
+	      adev[a].inbuf_next = 0;
+
+	      audio_stats (a,
+			save_audio_config_p->adev[a].num_channels,
+			n / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
+			save_audio_config_p->statistics_interval);
+	    }
+
+#else	/* begin OSS */
 
 	    /* Fixed in 1.2.  This was formerly outside of the switch */
 	    /* so the OSS version did not process stdin or UDP. */
@@ -1250,6 +1390,30 @@ int audio_flush (int a)
 	adev[a].outbuf_len = 0;
 	return (-1);
 
+#elif USE_SNDIO
+
+	int k;
+	unsigned char *ptr;
+	int len;
+
+	ptr = adev[a].outbuf_ptr;
+	len = adev[a].outbuf_len;
+
+	while (len > 0) {
+	  assert (adev[a].sndio_out_handle != NULL);
+	  k = sio_write (adev[a].sndio_out_handle, ptr, len);
+#if DEBUGx
+	  text_color_set(DW_COLOR_DEBUG);
+	  dw_printf ("audio_flush(): write %d returns %d\n", len, k);
+	  fflush (stdout);
+#endif
+	  ptr += k;
+	  len -= k;
+	}
+
+	adev[a].outbuf_len = 0;
+	return (0);
+
 #else		/* OSS */
 
 	int k;
@@ -1351,6 +1515,28 @@ void audio_wait (int a)
 	 * Either way, the caller will now compensate for it.
  	 */
 
+#elif USE_SNDIO
+
+	struct pollfd *pfds;
+	int nfds, revents;
+
+	nfds = sio_nfds (adev[a].sndio_out_handle);
+	pfds = alloca (nfds * sizeof(struct pollfd));
+
+	do {
+	  nfds = sio_pollfd (adev[a].sndio_out_handle, pfds, POLLOUT);
+	  if (nfds < 1) {
+	    /* no need to wait */
+	    break;
+	  }
+	  if (poll (pfds, nfds, -1) < 0) {
+	    text_color_set(DW_COLOR_ERROR);
+	    dw_printf ("poll %d\n", errno);
+	    break;
+	  }
+	  revents = sio_revents (adev[a].sndio_out_handle, pfds);
+	} while (!(revents & (POLLHUP | POLLOUT)));
+
 #else
 
 	assert (adev[a].oss_audio_device_fd > 0);
@@ -1397,6 +1583,21 @@ int audio_close (void)
 	    snd_pcm_close (adev[a].audio_in_handle);
 	    snd_pcm_close (adev[a].audio_out_handle);
 	
+	    adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
+
+#elif USE_SNDIO
+
+	  if (adev[a].sndio_in_handle != NULL && adev[a].sndio_out_handle != NULL) {
+
+	    audio_wait (a);
+
+	    sio_stop (adev[a].sndio_in_handle);
+	    sio_stop (adev[a].sndio_out_handle);
+	    sio_close (adev[a].sndio_in_handle);
+	    sio_close (adev[a].sndio_out_handle);
+
+	    adev[a].sndio_in_handle = adev[a].sndio_out_handle = NULL;
+
 #else
 
 	  if  (adev[a].oss_audio_device_fd > 0) {
diff --git a/src/audio.h b/src/audio.h
index 61dec9d9..48105d8f 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -350,8 +350,8 @@ struct audio_s {
 #define DEFAULT_ADEVICE	""		/* Mac OSX: Empty string = default audio device. */
 #elif USE_ALSA
 #define DEFAULT_ADEVICE	"default"	/* Use default device for ALSA. */
-#elif __OpenBSD__
-#define DEFAULT_ADEVICE	"default"	/* Use default device for OpenBSD-portaudio. */
+#elif USE_SNDIO
+#define DEFAULT_ADEVICE	"default"	/* Use default device for sndio. */
 #else
 #define DEFAULT_ADEVICE	"/dev/dsp"	/* First audio device for OSS.  (FreeBSD) */
 #endif					
diff --git a/src/direwolf.c b/src/direwolf.c
index 456b16f0..4157daf2 100644
--- a/src/direwolf.c
+++ b/src/direwolf.c
@@ -67,9 +67,8 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
-#ifdef __OpenBSD__
-#include <soundcard.h>
-#elif __APPLE__
+#if USE_SNDIO || __APPLE__
+// no need to include <soundcard.h>
 #else
 #include <sys/soundcard.h>
 #endif