shithub: sox

Download patch

ref: 3a0a630a4653a609e6b2674c88cf0c361182ca86
parent: b0022bd56982e62203b7332f0fe579f636682630
author: rrt <rrt>
date: Wed Apr 11 19:53:26 EDT 2007

Add libao handler for playing. Sadly libao only handles output. When
available, it's the default output handler, since it can play to a
wide range of devices. To cope, make set_device in sox.c take a mode
parameter indicating whether we're doing input or output. Thus, libao,
if available, is only the default output driver.

Rename sox_format_nothing_{read,write}_io to
sox_format_nothing_{read,write}.

Clarify documentation of ALSA driver slightly.

--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,7 @@
     rec2wav and sndcmp.
   o Added AMR-WB format.  (robs)
   o Added M3U playlist format [FR# 1667341].  (robs)
+  o Added libao support.  (Reuben Thomas)
 
   Effects:
 
--- a/configure.ac
+++ b/configure.ac
@@ -92,6 +92,17 @@
    AC_DEFINE(HAVE_ALSA, 1, [Define to 1 if you have ALSA.])
 fi
 
+dnl Check for libao
+AC_MSG_CHECKING([whether to try building libao sound driver])
+AC_ARG_ENABLE(libao,
+    AC_HELP_STRING([--disable-libao], [Don't build libao sound driver.]),,enable_libao=yes)
+AC_MSG_RESULT($enable_libao)
+if test "$enable_libao" = "yes"; then
+    AC_CHECK_HEADERS(ao/ao.h,
+        AC_CHECK_LIB(ao, ao_play,, enable_libao=no),
+        enable_libao=no)
+fi
+
 dnl Check for OSS
 AC_MSG_CHECKING([whether to try building OSS sound driver])
 AC_ARG_ENABLE(oss,
@@ -228,6 +239,7 @@
 echo
 echo "Debugging build................... $enable_debug"
 echo "ALSA driver....................... $enable_alsa"
+echo "libao driver...................... $enable_libao"
 echo "OSS driver........................ $enable_oss"
 echo "SUN audio driver.................. $enable_sun_audio"
 echo "play and rec symlinks............. $enable_playrec_symlinks"
--- a/sox.1
+++ b/sox.1
@@ -791,7 +791,7 @@
 Note: The input file is currently processed as .aiff.
 .TP
 .B alsa
-ALSA default device driver.
+ALSA device driver.
 This is a pseudo-file type and can be optionally compiled into SoX.  Run
 .EX
 	sox -h
@@ -817,6 +817,18 @@
 option): 0 = 6\*d6 kbit/s, 1 = 8\*d85 kbit/s, 2 = 12\*d65 kbit/s, 3 =
 14\*d25 kbit/s, 4 = 15\*d85 kbit/s 5 = 18\*d25 kbit/s, 6 = 19\*d85
 kbit/s, 7 = 23\*d05 kbit/s, 8 = 23\*d85 kbit/s
+.TP
+.B ao
+libao device driver.
+This is a pseudo-file type and can be optionally compiled into SoX.  Run
+.EX
+	sox -h
+.EE
+to see if you have support for this file type. It works only for
+playing audio files. It can play to a wide range of devices and sound
+systems. See its documentation for the full range. At the moment SoX's
+use of libao cannot be configured directly; you must use libao
+configuration files.
 .TP
 \&\fB.au\fR, \fB.snd\fR \fB(also with \-t sndfile)\fR
 Sun Microsystems AU files.
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,7 +12,7 @@
 lib_LTLIBRARIES = libsox.la
 include_HEADERS = sox.h soxstdint.h
 
-formats = 8svx.c adpcm.c adpcm.h adpcms.c adpcms.h aiff.c au.c auto.c avr.c \
+formats = 8svx.c adpcm.c adpcm.h adpcms.c adpcms.h aiff.c ao.c au.c auto.c avr.c \
 	  cdr.c cvsd.c cvsdfilt.h dat.c flac.c g711.c g711.h g721.c g723_24.c \
 	  g723_40.c g72x.c g72x.h gsm.c hcom.c ima_rw.c ima_rw.h \
 	  maud.c mp3.c nulfile.c prc.c raw.c sf.c sfircam.h skelform.c smp.c \
--- /dev/null
+++ b/src/ao.c
@@ -1,0 +1,110 @@
+/*
+ * libao player support for sox
+ * (c) Reuben Thomas <rrt@sc3d.org> 2007
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, write to the Free Software
+ * Foundation, Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301,
+ * USA.  */
+
+#include "sox_i.h"
+
+#ifdef HAVE_AO_AO_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ao/ao.h>
+
+typedef struct ao_priv
+{
+  int driver_id;
+  ao_device *device;
+  ao_sample_format format;
+} *ao_priv_t;
+
+static int startread(UNUSED ft_t ft)
+{
+  sox_fail("Cannot read from libao driver");
+  return SOX_EOF;
+}
+
+static int startwrite(ft_t ft)
+{
+  ao_priv_t ao = (ao_priv_t)ft->priv;
+
+  ao_initialize();
+  if ((ao->driver_id = ao_default_driver_id()) < 0) {
+    sox_fail("Could not find a default driver");
+    return SOX_EOF;
+  }
+
+  ao->format.bits = SOX_SAMPLE_BITS;
+  ao->format.rate = ft->signal.rate;
+  ao->format.channels = ft->signal.channels;
+  ao->format.byte_format = AO_FMT_NATIVE;
+  if ((ao->device = ao_open_live(ao->driver_id, &ao->format, NULL)) == NULL) {
+    sox_fail("Could not open default device: error %d", errno);
+    return SOX_EOF;
+  }
+
+  return SOX_SUCCESS;
+}
+
+static sox_size_t write(ft_t ft, const sox_sample_t *buf, sox_size_t len)
+{
+  ao_priv_t ao = (ao_priv_t)ft->priv;
+
+  if (ao_play(ao->device, (void *)buf, len * sizeof(sox_sample_t)) == 0)
+    return 0;
+
+  return len;
+}
+
+static int stopwrite(ft_t ft)
+{
+  ao_priv_t ao = (ao_priv_t)ft->priv;
+
+  if (ao_close(ao->device) == 0) {
+    sox_fail("Error closing libao output");
+    return SOX_EOF;
+  }
+  ao_shutdown();
+
+  return SOX_SUCCESS;
+}
+
+/* libao player */
+static const char *aonames[] = {
+  "ao",
+  NULL
+};
+
+static sox_format_t sox_ao_format = {
+  aonames,
+  NULL,
+  SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
+  startread,
+  sox_format_nothing_read,
+  sox_format_nothing,
+  startwrite,
+  write,
+  stopwrite,
+  sox_format_nothing_seek
+};
+
+const sox_format_t *sox_ao_format_fn(void)
+{
+    return &sox_ao_format;
+}
+
+#endif
--- a/src/auto.c
+++ b/src/auto.c
@@ -196,10 +196,10 @@
   NULL,
   SOX_FILE_DEVICE | SOX_FILE_PHONY,
   sox_autostartread,
-  sox_format_nothing_read_io,
+  sox_format_nothing_read,
   sox_format_nothing,
   sox_autostartwrite,
-  sox_format_nothing_write_io,
+  sox_format_nothing_write,
   sox_format_nothing,
   sox_format_nothing_seek
 };
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -22,6 +22,9 @@
   sox_alsa_format_fn,
 #endif
   sox_amr_wb_format_fn,
+#ifdef HAVE_LIBAO
+  sox_ao_format_fn,
+#endif
   sox_au_format_fn,
   sox_auto_format_fn,
   sox_avr_format_fn,
--- a/src/misc.c
+++ b/src/misc.c
@@ -308,8 +308,8 @@
 
 /* dummy format routines for do-nothing functions */
 int sox_format_nothing(ft_t ft UNUSED) { return(SOX_SUCCESS); }
-sox_size_t sox_format_nothing_read_io(ft_t ft UNUSED, sox_sample_t *buf UNUSED, sox_size_t len UNUSED) { return(0); }
-sox_size_t sox_format_nothing_write_io(ft_t ft UNUSED, const sox_sample_t *buf UNUSED, sox_size_t len UNUSED) { return(0); }
+sox_size_t sox_format_nothing_read(ft_t ft UNUSED, sox_sample_t *buf UNUSED, sox_size_t len UNUSED) { return(0); }
+sox_size_t sox_format_nothing_write(ft_t ft UNUSED, const sox_sample_t *buf UNUSED, sox_size_t len UNUSED) { return(0); }
 int sox_format_nothing_seek(ft_t ft UNUSED, sox_size_t offset UNUSED) { sox_fail_errno(ft, SOX_ENOTSUP, "operation not supported"); return(SOX_EOF); }
 
 /* dummy effect routine for do-nothing functions */
--- a/src/sox.c
+++ b/src/sox.c
@@ -227,8 +227,15 @@
   return f;
 }
 
-static void set_device(file_t f)
+static void set_device(file_t f, sox_bool recording)
 {
+#ifdef HAVE_AO_AO_H
+  if (!recording) {
+    f->filetype = "ao";
+    f->filename = xstrdup("default");
+    return;
+  }
+#endif
 #if defined(HAVE_ALSA)
   f->filetype = "alsa";
   f->filename = xstrdup("default");
@@ -412,7 +419,7 @@
     }
 
     f = f? f : new_file();
-    set_device(f);
+    set_device(f, sox_false);
     files[file_count++] = f;
   }
   else if (f) {
@@ -434,7 +441,7 @@
     file_count++;
 
     f = new_file();
-    set_device(f);
+    set_device(f, sox_true);
     files[0] = f;
   }
 }
--- a/src/sox.h
+++ b/src/sox.h
@@ -14,6 +14,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <limits.h>
 #include "soxstdint.h"
 
 /* The following is the API version of libSoX.  It is not meant
@@ -147,6 +148,7 @@
 typedef uint32_t sox_size_t;
 /* Maximum value size type can hold. (Minimum is 0). */
 #define SOX_SIZE_MAX 0xffffffff
+#define SOX_SAMPLE_BITS (sizeof(sox_size_t) * CHAR_BIT)
 
 typedef int32_t sox_ssize_t;
 /* Minimum and maximum value signed size type can hold. */
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -226,6 +226,9 @@
 extern const sox_format_t *sox_alsa_format_fn(void);
 #endif
 extern const sox_format_t *sox_amr_wb_format_fn(void);
+#ifdef HAVE_AO_AO_H
+extern const sox_format_t *sox_ao_format_fn(void);
+#endif
 extern const sox_format_t *sox_au_format_fn(void);
 extern const sox_format_t *sox_auto_format_fn(void);
 extern const sox_format_t *sox_avr_format_fn(void);
@@ -302,8 +305,8 @@
  * a file handler or effect doesn't need to do anything special
  */
 int sox_format_nothing(ft_t ft);
-sox_size_t sox_format_nothing_read_io(ft_t ft, sox_sample_t *buf, sox_size_t len);
-sox_size_t sox_format_nothing_write_io(ft_t ft, const sox_sample_t *buf, sox_size_t len);
+sox_size_t sox_format_nothing_read(ft_t ft, sox_sample_t *buf, sox_size_t len);
+sox_size_t sox_format_nothing_write(ft_t ft, const sox_sample_t *buf, sox_size_t len);
 int sox_format_nothing_seek(ft_t ft, sox_size_t offset);
 int sox_effect_nothing(eff_t effp);
 int sox_effect_nothing_flow(eff_t effp, const sox_sample_t *ibuf, sox_sample_t *obuf, sox_size_t *isamp, sox_size_t *osamp);