shithub: sox

Download patch

ref: c9782198d4a5150abd4eb5114d5d8d31433972fd
parent: e06776c324020ab2668729bacd0c8f04d37a5a04
author: robs <robs>
date: Sat Jan 17 03:27:26 EST 2009

New native OpenBSD audio handler for play/recording

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -77,6 +77,7 @@
   endif(HAVE_OPENMP)
 endif(CMAKE_COMPILER_IS_GNUCC)
 optional(HAVE_ID3TAG id3tag.h id3tag id3_file_open "")
+optional(HAVE_SNDIO sndio.h sndio sio_open sndio)
 optional(HAVE_LIBAO ao/ao.h ao ao_play ao)
 optional(HAVE_FLAC FLAC/all.h FLAC FLAC__stream_encoder_new flac)
 optional(HAVE_MAD_H mad.h mad mad_stream_buffer mp3)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,7 +4,8 @@
 This file contains a list of all changes starting after the release of
 sox-11gamma, followed by a list of prior authors and features.
 
-sox-14.x.x	2009-xx-xx
+
+sox-14.3.0	2009-xx-xx
 ----------
 
 Previously deprecated features that have been removed in this release:
@@ -19,6 +20,13 @@
 
   * But interface retained as an alias for `rate'.
 
+Newly deprecated features (to be removed in future):
+
+  Deprec-  Feature    [O(ption)]                           Removal
+  ated in  [F(ormat)] [E(ffect)]   Replacement             due after
+  -------  ----------------------  ----------------------  -------
+  14.3.0   F flac: libFLAC 1.1.2,3 libFLAC > 1.1.3         14.3.0 + 6 months
+
 Previously deprecated features (to be removed in future):
 
   Deprec-  Feature    [O(ption)]                           Removal
@@ -26,9 +34,9 @@
   -------  ----------------------  ----------------------  -------
   14.2.0   E key alias             pitch                   2009-05-29
   14.2.0   E pan                   ~= mixer/remix          2009-05-29
-  14.1.0   E resample alias        rate                    14.x.x + 6 months
-  14.1.0   E polyphase alias       rate                    14.x.x + 6 months
-  14.1.0   E rabbit alias          rate                    14.x.x + 6 months
+  14.1.0   E resample alias        rate                    14.3.0 + 1 year
+  14.1.0   E polyphase alias       rate                    14.3.0 + 1 year
+  14.1.0   E rabbit alias          rate                    14.3.0 + 1 year
   14.1.0   F wve (native)          wve (libsndfile)        2009-07-29
   14.1.0   Behaviour whereby       soxi                    2009-07-29
            sox -V file(s) -n
@@ -41,12 +49,8 @@
 
 File formats:
 
-  o 24-bit support for ALSA driver.  (robs)
-  o Warn if ALSA under/overrun.  (robs)
   o Slight improvement to A-law/u-law conversion accuracy: round LSB
     instead of truncating.  (robs)
-  o New `--ignore-length' option to ignore length in input file
-    header (for simple encodings); instead, read to end of file.  (robs)
   o Fix [2028181] w64 float format incompatibility.  (Tim Munro)
   o Fix reading AIFF files with pad bytes in COMT chunks. (Joe Holt)
   o Fix AIFF file length bug to stop reading trash data on files that
@@ -60,6 +64,7 @@
   o New `overdrive' effect.  (robs)
   o New `pluck' and `tpdf' types for `synth'.  (robs)
   o Can now set common parameters for multiple `synth' channels.  (robs)
+  o Fix [2487589] `dither' clipping detection & handling.  (robs)
   o Fix `repeat' sometimes stopping repeating too soon.  (robs)
   o Fix `repeat' sometimes repeating wrong audio segments.  (robs)
   o Fix [2332343] 'silence' segfault with certain lengths. (cbagwell)
@@ -70,10 +75,15 @@
 
 Other new features:
 
-  o New bitrate, time in seconds, & total options for soxi.  (robs)
+  o New native OpenBSD audio handler for play/recording.  (Alexandre Ratchov)
+  o 24-bit support for ALSA handler.  (robs)
+  o Warn if ALSA under/overrun.  (robs)
+  o New `--ignore-length' option to ignore length in input file
+    header (for simple encodings); instead, read to end of file.  (robs)
   o Added ability to create shared DLL's on cygwin (cbagwell)
   o Grouped files, e.g. play -r 6k "*.vox" plays all at 6k.  (robs)
   o New `--temp DIRECTORY' option.  (robs)
+  o New bitrate, time in seconds, & total options for soxi.  (robs)
 
 Other bug fixes:
 
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 
-AC_INIT(SoX, 14.2.0, sox-devel@lists.sourceforge.net)
+AC_INIT(SoX, 14.3.0, sox-devel@lists.sourceforge.net)
 
 m4_ifdef([AC_CONFIG_MACRO_DIR], [AC_CONFIG_MACRO_DIR([m4])])
 
@@ -251,6 +251,23 @@
 AM_CONDITIONAL(HAVE_OSS, test x$enable_oss = xyes)
 AC_SUBST(OSS_LIBS)
 
+dnl Check for sndio
+AC_MSG_CHECKING([whether to try building sndio sound driver])
+AC_ARG_ENABLE(sndio,
+    AC_HELP_STRING([--disable-sndio], [Don't build sndio sound driver.]),,enable_sndio=yes)
+AC_MSG_RESULT($enable_sndio)
+if test "$enable_sndio" = "yes"; then
+    AC_CHECK_HEADERS(sndio.h,
+        [AC_CHECK_LIB(sndio, sio_open, SNDIO_LIBS="$SNDIO_LIBS -lsndio")],
+        enable_sndio=no)
+fi
+if test "$enable_sndio" = yes; then
+   AC_DEFINE(HAVE_SNDIO, 1, [Define to 1 if you have sndio.])
+   audio_driver_found=yes
+fi
+AM_CONDITIONAL(HAVE_SNDIO, test x$enable_sndio = xyes)
+AC_SUBST(SNDIO_LIBS)
+
 dnl Check for Sun audio
 AC_MSG_CHECKING([whether to try building Sun audio driver])
 AC_ARG_ENABLE(sun-audio,
@@ -635,6 +652,7 @@
 echo "ALSA driver....................... $enable_alsa"
 echo "libao driver...................... $enable_libao"
 echo "OSS driver........................ $enable_oss"
+echo "sndio driver...................... $enable_sndio"
 echo "SUN audio driver.................. $enable_sun_audio"
 echo "CoreAudio driver.................. $enable_coreaudio"
 echo "Pulse Audio driver................ $enable_pulseaudio"
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -244,6 +244,11 @@
 libsox_fmt_oss_la_LIBADD = libsox.la @OSS_LIBS@
 pkglib_LTLIBRARIES += libsox_fmt_oss.la
 endif
+if HAVE_SNDIO
+libsox_fmt_sndio_la_SOURCES = sndio.c
+libsox_fmt_sndio_la_LIBADD = libsox.la @SNDIO_LIBS@
+pkglib_LTLIBRARIES += libsox_fmt_sndio.la
+endif
 if HAVE_SUN_AUDIO
 libsox_fmt_sunau_la_SOURCES = sunaudio.c
 libsox_fmt_sunau_la_LIBADD = libsox.la
@@ -373,6 +378,11 @@
     libsox_la_SOURCES += oss.c
     libsox_la_LIBADD += @OSS_LIBS@
     sox_LDADD += @OSS_LIBS@
+endif
+if HAVE_SNDIO
+    libsox_la_SOURCES += sndio.c
+    libsox_la_LIBADD += @SNDIO_LIBS@
+    sox_LDADD += @SNDIO_LIBS@
 endif
 if HAVE_SUN_AUDIO
     libsox_la_SOURCES += sunaudio.c
--- a/src/formats.h
+++ b/src/formats.h
@@ -87,6 +87,9 @@
 #if defined(HAVE_SYS_SOUNDCARD_H) || defined(HAVE_MACHINE_SOUNDCARD_H)
   FORMAT(oss)
 #endif
+#if defined HAVE_SNDIO
+  FORMAT(sndio)
+#endif
 #if defined HAVE_SNDFILE
   FORMAT(sndfile)
   #if defined HAVE_SNDFILE_1_0_12
--- /dev/null
+++ b/src/sndio.c
@@ -1,0 +1,242 @@
+/*
+ * libsndio sound handler
+ *
+ * Copyright (c) 2009 Alexandre Ratchov <alex@caoua.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.
+ */
+#include <string.h>
+#include <sndio.h>
+#include "sox_i.h"
+
+struct sndio_priv {
+  struct sio_hdl *hdl;             /* handle to speak to libsndio */
+  struct sio_par par;              /* current device parameters */
+#define SNDIO_BUFSZ 0x1000
+  unsigned char buf[SNDIO_BUFSZ];  /* temp buffer for converions */
+};
+
+/*
+ * convert ``count'' samples from sox encoding to sndio encoding
+ */
+static void encode(struct sio_par *par,
+    sox_sample_t *idata, unsigned char *odata, unsigned count)
+{
+  int obnext, osnext, s, osigbit;
+  unsigned oshift, obps, i;
+
+  obps = par->bps;
+  osigbit = par->sig ? 0 : 1 << (par->bits - 1);
+  oshift = 32 - (par->msb ? par->bps * 8 : par->bits);
+  if (par->le) {
+    obnext = 1;
+    osnext = 0;
+  } else {
+    odata += par->bps - 1;
+    obnext = -1;
+    osnext = 2 * par->bps;
+  }
+  for (; count > 0; count--) {
+    s = (*idata++ >> oshift) ^ osigbit;
+    for (i = obps; i > 0; i--) {
+      *odata = (unsigned char)s;
+      s >>= 8;
+      odata += obnext;
+    }
+    odata += osnext;
+  }
+}
+
+/*
+ * convert ``count'' samples from sndio encoding to sox encoding
+ */
+static void decode(struct sio_par *par,
+    unsigned char *idata, sox_sample_t *odata, unsigned count)
+{
+  unsigned ishift, ibps, i;
+  int s = 0xdeadbeef, ibnext, isnext, isigbit;
+
+  ibps = par->bps;
+  isigbit = par->sig ? 0 : 1 << (par->bits - 1);
+  ishift = 32 - (par->msb ? par->bps * 8 : par->bits);
+  if (par->le) {
+    idata += par->bps - 1;
+    ibnext = -1;
+    isnext = 2 * par->bps;
+  } else {
+    ibnext = 1;
+    isnext = 0;
+  }
+  for (; count > 0; count--) {
+    for (i = ibps; i > 0; i--) {
+      s <<= 8;
+      s |= *idata;
+      idata += ibnext;
+    }
+    idata += isnext;
+    *odata++ = (s ^ isigbit) << ishift;
+  }
+}
+
+static int startany(struct sox_format *ft, unsigned mode)
+{
+  struct sndio_priv *p = (struct sndio_priv *)ft->priv;
+  struct sio_par reqpar;
+  char *device;
+
+  device = ft->filename;
+  if (strcmp("default", device) == 0)
+    device = NULL;
+
+  p->hdl = sio_open(device, mode, 0);
+  if (p->hdl == NULL)
+    return SOX_EOF;
+  /*
+   * set specified parameters, leaving others to the defaults
+   */
+  sio_initpar(&reqpar);
+  if (ft->signal.rate > 0)
+    reqpar.rate = ft->signal.rate;
+  if (ft->signal.channels > 0) {
+    if (mode == SIO_PLAY)
+      reqpar.pchan = ft->signal.channels;
+    else
+      reqpar.rchan = ft->signal.channels;
+  }
+  if (ft->signal.precision > 0)
+    reqpar.bits = ft->signal.precision;
+  switch (ft->encoding.encoding) {
+  case SOX_ENCODING_SIGN2:
+    reqpar.sig = 1;
+    break;
+  case SOX_ENCODING_UNSIGNED:
+    reqpar.sig = 0;
+    break;
+  default:
+    break;  /* use device default */
+  }
+  if (ft->encoding.bits_per_sample > 0)
+    reqpar.bits = ft->encoding.bits_per_sample;
+  if (ft->encoding.reverse_bytes != SOX_OPTION_DEFAULT) {
+    reqpar.le = SIO_LE_NATIVE;
+    if (ft->encoding.reverse_bytes)
+      reqpar.le = !reqpar.le;
+  }
+  if (!sio_setpar(p->hdl, &reqpar) ||
+      !sio_getpar(p->hdl, &p->par))
+    goto failed;
+  ft->signal.channels = (mode == SIO_PLAY) ? p->par.pchan : p->par.rchan;
+  ft->signal.precision = p->par.bits;
+  ft->signal.rate = p->par.rate;
+  ft->encoding.encoding = p->par.sig ? SOX_ENCODING_SIGN2 : SOX_ENCODING_UNSIGNED;
+  ft->encoding.bits_per_sample = p->par.bps * 8;
+  ft->encoding.reverse_bytes = SIO_LE_NATIVE ? !p->par.le : p->par.le;
+  ft->encoding.reverse_nibbles = SOX_OPTION_NO;
+  ft->encoding.reverse_bits = SOX_OPTION_NO;
+
+  if (!sio_start(p->hdl))
+    goto failed;
+  return SOX_SUCCESS;
+ failed:
+  sio_close(p->hdl);
+  return SOX_EOF;
+}
+
+static int stopany(struct sox_format *ft)
+{
+  sio_close(((struct sndio_priv *)ft->priv)->hdl);
+  return SOX_SUCCESS;
+}
+
+static int startread(struct sox_format *ft)
+{
+  return startany(ft, SIO_REC);
+}
+
+static int startwrite(struct sox_format *ft)
+{
+  return startany(ft, SIO_PLAY);
+}
+
+static size_t readsamples(sox_format_t *ft, sox_sample_t *buf, size_t len)
+{
+  struct sndio_priv *p = (struct sndio_priv *)ft->priv;
+  unsigned char partial[4];
+  unsigned cpb, cc, pc;
+  size_t todo, n;
+
+  pc = 0;
+  todo = len * p->par.bps;
+  cpb = SNDIO_BUFSZ - (SNDIO_BUFSZ % p->par.bps);
+  while (todo > 0) {
+    memcpy(p->buf, partial, pc);
+    cc = cpb - pc;
+    if (cc > todo)
+      cc = todo;
+    n = sio_read(p->hdl, p->buf + pc, cc);
+    if (n == 0 && sio_eof(p->hdl))
+      break;
+    n += pc;
+    pc = n % p->par.bps;
+    n -= pc;
+    memcpy(partial, p->buf + n, pc);
+    decode(&p->par, p->buf, buf, n / p->par.bps);
+    buf += n / p->par.bps;
+    todo -= n;
+  }
+  return len - todo / p->par.bps;
+}
+
+static size_t writesamples(sox_format_t *ft, const sox_sample_t *buf, size_t len)
+{
+  struct sndio_priv *p = (struct sndio_priv *)ft->priv;
+  unsigned sc, spb;
+  size_t n, todo;
+
+  todo = len;
+  spb = SNDIO_BUFSZ / p->par.bps;
+  while (todo > 0) {
+    sc = spb;
+    if (sc > todo)
+      sc = todo;
+    encode(&p->par, buf, p->buf, sc);
+    n = sio_write(p->hdl, p->buf, sc * p->par.bps);
+    if (n == 0 && sio_eof(p->hdl))
+      break;
+    n /= p->par.bps;
+    todo -= n;
+    buf += n;
+  }
+  return len - todo;
+}
+
+SOX_FORMAT_HANDLER(sndio)
+{
+  static char const * const names[] = {"sndio", NULL};
+  static unsigned const write_encodings[] = {
+    SOX_ENCODING_SIGN2, 32, 24, 16, 8, 0,
+    SOX_ENCODING_UNSIGNED, 32, 24, 16, 8, 0,
+    0
+  };
+  static sox_format_handler_t const handler = {
+    SOX_LIB_VERSION_CODE,
+    "libsndio device driver",
+    names,
+    SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
+    startread, readsamples, stopany,
+    startwrite, writesamples, stopany,
+    NULL, write_encodings, NULL,
+    sizeof(struct sndio_priv)
+  };
+  return &handler;
+}
--- a/src/sox.c
+++ b/src/sox.c
@@ -2258,9 +2258,15 @@
 
   if (!type)
     return NULL;
-  if (!strcmp(type, "sunau")) name = "/dev/audio";
-  else if (!strcmp(type, "oss" ) || !strcmp(type, "ossdsp")) name = "/dev/dsp";
-  else if (!strcmp(type, "alsa") || !strcmp(type, "ao") || !strcmp(type, "coreaudio") || !strcmp(type, "pulseaudio")) name = "default";
+
+  if (!strcmp(type, "sunau"))
+    name = "/dev/audio";
+  else if (!strcmp(type, "oss" ) || !strcmp(type, "ossdsp"))
+    name = "/dev/dsp";
+  else if (!strcmp(type, "alsa") || !strcmp(type, "ao") || !strcmp(type,"sndio")
+        || !strcmp(type, "coreaudio") || !strcmp(type, "pulseaudio"))
+    name = "default";
+  
   return name? from_env? from_env : name : NULL;
 }
 
@@ -2273,6 +2279,7 @@
   if (!f->filetype && sox_find_format("oss" , sox_false)) f->filetype = "oss";
   if (!f->filetype && sox_find_format("pulseaudio" , sox_false)) f->filetype = "pulseaudio";
   if (!f->filetype && sox_find_format("sunau",sox_false)) f->filetype = "sunau";
+  if (!f->filetype && sox_find_format("sndio", sox_false)) f->filetype = "sndio";
   if (!f->filetype && sox_find_format("ao"  , sox_false) && file_count) /*!rec*/
     f->filetype = "ao";
 
--- a/src/sox.h
+++ b/src/sox.h
@@ -32,7 +32,7 @@
  * Please do not count on these numbers being in sync.
  */
 #define SOX_LIB_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#define SOX_LIB_VERSION_CODE SOX_LIB_VERSION(14, 2, 0)
+#define SOX_LIB_VERSION_CODE SOX_LIB_VERSION(14, 3, 0)
 
 const char *sox_version(void);   /* Returns version number */
 
--- a/src/soxconfig.h.cmake
+++ b/src/soxconfig.h.cmake
@@ -1,4 +1,4 @@
-#define PACKAGE_VERSION "14.2.0"
+#define PACKAGE_VERSION "14.3.0"
 
 #cmakedefine EXTERNAL_GSM             1
 #cmakedefine HAVE_ALSA                1
@@ -28,6 +28,7 @@
 #cmakedefine HAVE_PNG                 1
 #cmakedefine HAVE_SNDFILE_1_0_12      1
 #cmakedefine HAVE_SNDFILE             1
+#cmakedefine HAVE_SNDIO               1
 #cmakedefine HAVE_STDINT_H            1
 #cmakedefine HAVE_STRCASECMP          1
 #cmakedefine HAVE_STRINGS_H           1