Permalink
Browse files

-Add: add Open Sound System (OSS) support

OSS is the prefered sound API under FreeBSD
ALSA is prefered under Linux
  • Loading branch information...
miniupnp committed Feb 12, 2017
1 parent 131598b commit 227981308b224431891a51203f68357be783fc7c
Showing with 177 additions and 1 deletion.
  1. +11 −0 config.lib
  2. +2 −1 configure
  3. +4 −0 source.list
  4. +160 −0 src/audio/dsp_oss.c
View
@@ -42,6 +42,7 @@ set_default() {
with_sdlimage="1"
with_sdl2="1"
with_asound="1"
+ with_oss="1"
with_pulse="1"
with_munt="1"
enable_builtin_depend="1"
@@ -79,6 +80,7 @@ set_default() {
with_sdlimage
with_sdl2
with_asound
+ with_oss
with_pulse
with_munt
enable_builtin_depend
@@ -188,6 +190,9 @@ detect_params() {
--without-alsa) with_asound="0";;
--with-alsa=*) with_asound="$optarg";;
+ --with-oss) with_oss="2";;
+ --without-oss) with_oss="0";;
+
--with-pulse) with_pulse="2";;
--without-pulse) with_pulse="0";;
--with-pulse=*) with_pulse="$optarg";;
@@ -439,9 +444,14 @@ check_params() {
with_sdl2="0"
with_sdl="0"
with_asound="0"
+ with_oss="0"
with_pulse="0"
with_munt="0"
fi
+ if [ "$os" = "FREEBSD" ] && [ "$with_oss" != "0" ] && [ "$with_asound" = "1" ] ; then
+ # prefers OSS to ALSA under FreeBSD
+ with_asound="0"
+ fi
detect_sdl2
detect_sdl
detect_asound
@@ -2037,6 +2047,7 @@ showhelp() {
echo " --with-sdl[=sdl-config] enables SDL video driver support"
echo " --with-sdl2[=sdl2-config] enables SDL2 video driver support"
echo " --with-asound[=libasound.a] enables ALSA support"
+ echo " --with-oss enables Open Sound System"
echo " --with-munt enables MUNT support"
echo " --with-pulse[=libpulse.a] enables PulseAudio support"
echo " --disable-builtin-depend disable use of builtin deps finder"
View
@@ -95,7 +95,8 @@ AWKCOMMAND='
if ($0 == "SDL2" && "'$sdl2_config'" == "") { next; }
if ($0 == "SDL" && "'$sdl_config'" == "") { next; }
if ($0 == "ALSA" && "'$with_asound'" == "0") { next; }
- if ($0 == "MUNT" && "'$with_munt'" == "0") { next; }
+ if ($0 == "OSS" && "'$with_oss'" == "0") { next; }
+ if ($0 == "MUNT" && "'$with_munt'" == "0") { next; }
if ($0 == "PULSE" && "'$with_pulse'" == "0") { next; }
if ($0 == "OSX" && "'$os'" != "OSX") { next; }
if ($0 == "TOS" && "'$os'" != "TOS") { next; }
View
@@ -16,6 +16,9 @@ audio/midi_atari.c
#else
#if ALSA
audio/dsp_alsa.c
+ #else
+ #if OSS
+ audio/dsp_oss.c
#else
#if SDL
audio/dsp_sdl.c
@@ -27,6 +30,7 @@ audio/midi_atari.c
#endif
#endif
#endif
+ #endif
#endif
# MIDI
#if MUNT
View
@@ -0,0 +1,160 @@
+/** @file src/audio/dsp_oss.c OSS (Open Sound System) implementation of the DSP. */
+/* OSS is deprecated under linux, but still used in *BSD world */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/soundcard.h>
+#include "types.h"
+#include "../timer.h"
+#include "../os/error.h"
+#include "../os/endian.h"
+
+#include "dsp.h"
+
+#define AUDIO_DEVICE "/dev/dsp"
+
+static void oss_tick(void);
+
+static int s_oss_fd = -1;
+
+static const uint8 * s_data_to_play = NULL;
+static size_t s_bytes_to_play = 0;
+
+void DSP_Stop(void)
+{
+ if(s_oss_fd >= 0) {
+ close(s_oss_fd);
+ s_oss_fd = -1;
+ }
+}
+
+void DSP_Uninit(void)
+{
+ DSP_Stop();
+ Timer_Remove(oss_tick);
+}
+
+bool DSP_Init(void)
+{
+ s_oss_fd = open(AUDIO_DEVICE, O_WRONLY);
+ if(s_oss_fd < 0) {
+ Error("DSP_Init() OSS : open(%s) : %s\n", AUDIO_DEVICE, strerror(errno));
+ return false;
+ }
+#ifdef SNDCTL_SYSINFO
+ {
+ struct oss_sysinfo info;
+ if(ioctl(s_oss_fd, SNDCTL_SYSINFO, &info) < 0) {
+ Warning("ioctl(SNDCTL_SYSINFO) Failed : %s\n", strerror(errno));
+ } else {
+ Debug("DSP_Init() : %s version %s %d dsp devices\n",
+ info.product, info.version, info.numaudios);
+ }
+ }
+#endif
+ close(s_oss_fd);
+ s_oss_fd = -1;
+ Timer_Add(oss_tick, 1000000 / 10, true);
+ return true;
+}
+
+void DSP_Play(const uint8 *data)
+{
+ int i;
+ uint32 len;
+ int freq;
+ ssize_t n;
+
+ DSP_Stop();
+
+ data += READ_LE_UINT16(data + 20); /* skip Create Voice File header */
+
+ /* first byte is Block Type :
+ * 0x00: Terminator
+ * 0x01: Sound data
+ * 0x02: Sound data continuation
+ * 0x03: Silence
+ * 0x04: Marker
+ * 0x05: Text
+ * 0x06: Repeat start
+ * 0x07: Repeat end
+ * 0x08: Extra info
+ * 0x09: Sound data (New format) */
+ if (*data != 1) return;
+
+ /* next 3 bytes are block size (not including the 1 block type and size 4 bytes) */
+ len = (READ_LE_UINT32(data) >> 8) - 2;
+ data += 4;
+ /* byte 0 frequency divisor
+ * byte 1 codec id : 0 is "8bits unsigned PCM"
+ * bytes 2..n audio data */
+
+ freq = 1000000 / (256 - data[0]);
+ if (data[1] != 0) Warning("Unsupported VOC codec 0x%02x\n", (int)data[1]);
+
+ s_oss_fd = open(AUDIO_DEVICE, O_WRONLY);
+ if(s_oss_fd < 0) {
+ Error("open(%s) : %s\n", AUDIO_DEVICE, strerror(errno));
+ return;
+ }
+ i = AFMT_U8; /* Unsigned 8bit samples */
+ if(ioctl(s_oss_fd, SNDCTL_DSP_SETFMT, &i) < 0) {
+ Error("Failed to set unsigned 8bit format\n");
+ }
+ i = 0; /* MONO */
+ if(ioctl(s_oss_fd, SNDCTL_DSP_STEREO, &i) < 0) {
+ Error("Failed to set mono\n");
+ }
+ /*Debug("Setting sample rate = %d\n", freq);*/
+ if(ioctl(s_oss_fd, SNDCTL_DSP_SPEED, &freq) < 0) {
+ Error("Failed to set sample rate\n");
+ }
+ /*Debug("Real sample rate = %d\n", freq);*/
+
+ n = write(s_oss_fd, data + 2, len);
+ Debug("write() returned %d (len=%d)\n", (int)n, (int)len);
+ if(n < 0) {
+ if(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) {
+ s_data_to_play = data + 2;
+ s_bytes_to_play = len;
+ } else {
+ Error("DSP_Play() write() : %s\n", strerror(errno));
+ }
+ } else if((int)n < (int)len) {
+ s_data_to_play = data + 2 + n;
+ s_bytes_to_play = len - n;
+ }
+}
+
+#define DELAY_THRESHOLD (16)
+
+uint8 DSP_GetStatus(void)
+{
+ int delay;
+ if(s_oss_fd < 0) return 0;
+ if(s_bytes_to_play > 0) return 2;
+ if(ioctl(s_oss_fd, SNDCTL_DSP_GETODELAY, &delay) < 0) {
+ Warning("ioctl SNDCTL_DSP_GETODELAY : %s\n", strerror(errno));
+ return 0;
+ }
+ if(delay < DELAY_THRESHOLD) return 0;
+ /*Debug("DSP_GetStatus() : delay=%d\n", delay);*/
+ return 2; /* playing */
+}
+
+static void oss_tick(void)
+{
+ ssize_t n;
+ if(s_oss_fd >= 0 && s_bytes_to_play > 0) {
+ n = write(s_oss_fd, s_data_to_play, s_bytes_to_play);
+ /*Debug(" write() returned %d (len=%d)\n", (int)n, (int)s_bytes_to_play);*/
+ if(n < 0) {
+ Error("oss_tick() write() : %s\n", strerror(errno));
+ } else {
+ s_data_to_play += n;
+ s_bytes_to_play -= n;
+ }
+ }
+}

0 comments on commit 2279813

Please sign in to comment.