ref: f0724fe5fc30fc597c235b5d6f59e478b10cba0d
parent: 137952b22cdfa5faecb0ae8c04934d95f686a2b3
author: rrt <rrt>
date: Sat Jan 20 15:17:02 EST 2007
Add new formats via libsndfile
--- a/ChangeLog
+++ b/ChangeLog
@@ -90,6 +90,7 @@
o New .ima file format for raw IMA ADPCM. (robs)
o Build system overhaul to use the full set of GNU autotools.
(Reuben Thomas)
+ o New file formats via libsndfile. (Reuben Thomas)
sox-12.18.2
-----------
--- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,19 @@
AC_DEFINE(HAVE_SUN_AUDIO, 1, [Define to 1 if you have Sun /dev/audio.])
fi
+dnl Check for libsndfile
+with_sndfile=yes
+AC_ARG_WITH(sndfile,
+ AC_HELP_STRING([--with-sndfile],
+ [Use libsndfile if present (default is YES)]))
+if test "$with_sndfile" = yes; then
+ SOX_PATH_SNDFILE(,
+ [with_sndfile=no
+ AC_MSG_NOTICE([Could not find a usable libsndfile])])
+fi
+AC_SUBST(SNDFILE_CFLAGS)
+AC_SUBST(SNDFILE_LIBS)
+
dnl Check for Ogg Vorbis libraries
AC_CHECK_HEADER(vorbis/codec.h,
[with_ogg_vorbis=yes
@@ -139,7 +152,7 @@
with_samplerate=yes
AC_ARG_WITH(samplerate,
AC_HELP_STRING([--with-samplerate],
- [Use libsamplerate (aka Rabbit Code) if present (default is YES)]))
+ [Use libsamplerate (aka Secret Rabbit Code) if present (default is YES)]))
if test "$with_samplerate" = yes; then
SOX_PATH_SAMPLERATE(,
[with_samplerate=no
@@ -272,6 +285,7 @@
echo "ALSA Driver....................... $with_alsa"
echo "OSS Driver........................ $with_oss"
echo "SUN /dev/audio.................... $with_sun_audio"
+echo "libsndfile support................ $with_sndfile"
echo "Ogg Vorbis support................ $with_ogg_vorbis"
echo "FLAC support...................... $with_flac"
echo "MAD MP3 Decoder................... $with_mad"
--- /dev/null
+++ b/m4/sndfile.m4
@@ -1,0 +1,70 @@
+dnl SOX_PATH_SNDFILE
+dnl Based off of shout.m4 from xiph package.
+dnl cbagwell@users.sourceforge.net 1-3-2007
+dnl
+dnl Original Authors:
+dnl Jack Moffitt <jack@icecast.org> 08-06-2001
+dnl Rewritten for libshout 2
+dnl Brendan Cully <brendan@xiph.org> 20030612
+dnl
+# SOX_PATH_SNDFILE([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+# Test for libsndfile, and define SNDFILE_CFLAGS and SNDFILE_LIBS
+AC_DEFUN([SOX_PATH_SNDFILE],
+[dnl
+have_sndfile="no"
+SNDFILE_CFLAGS=""
+SNDFILE_LIBS=""
+
+# Step 1: Use pkg-config if available
+m4_ifdef([PKG_CHECK_MODULES],
+ [# PKG_CHECK_MODULES available
+ PKG_CHECK_MODULES([SNDFILE], [sndfile], [$1], [$2])
+ have_sndfile="maybe"],
+ [# PKG_CHECK_MODULES is unavailable, search for pkg-config program
+ AC_PATH_PROG([PKGCONFIG], [pkg-config], [none])
+ if test "$PKGCONFIG" != "none" && `$PKGCONFIG --exists sndfile`
+ then
+ SNDFILE_CFLAGS=`$PKGCONFIG --cflags sndfile`
+ SNDFILE_LIBS=`$PKGCONFIG --libs sndfile`
+ have_sndfile="maybe"
+ else
+ if test "$PKGCONFIG" != "none"
+ then
+ AC_MSG_NOTICE([$PKGCONFIG couldn't find libsndfile. Try adjusting PKG_CONFIG_PATH.])
+ fi
+ # libsndfile doesn't have sndfile-config but other
+ # packages do and so keep around as an example.
+ # Step 2: try sndfile-config
+ #AC_PATH_PROG([SNDFILECONFIG], [sndfile-config], [none])
+ #if test "$SNDFILECONFIG" != "none" && test `$SNDFILECONFIG --package` = "libsndfile"
+ #then
+ # SNDFILE_CFLAGS=`$SNDFILECONFIG --cflags`
+ # SNDFILE_LIBS=`$SNDFILECONFIG --libs`
+ # have_sndfile="maybe"
+ #fi
+ fi
+ ])
+
+# Now try actually using libsndfile
+if test "$have_sndfile" != "no"
+then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $SNDFILE_CFLAGS"
+ LIBS="$LIBS $SNDFILE_LIBS"
+ AC_CHECK_HEADER([sndfile.h], [
+ AC_DEFINE([HAVE_SNDFILE_H], 1, [Define if you have <sndfile.h>])
+ AC_CHECK_FUNC([sf_open], [
+ ifelse([$1], , :, [$1])
+ have_sndfile="yes"
+ ])
+ ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+fi
+
+if test "$have_sndfile" != "yes"
+then
+ ifelse([$2], , :, [$2])
+fi
+])dnl SOX_PATH_SNDFILE
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,7 +3,8 @@
SUBDIRS = libgsm
AM_CPPFLAGS = $(LUA_INCLUDES)
-AM_LDFLAGS = @SAMPLERATE_LIBS@
+AM_CFLAGS = @SNDFILE_CFLAGS@ @SAMPLERATE_CFLAGS@
+AM_LDFLAGS = @SNDFILE_LIBS@ @SAMPLERATE_LIBS@
# Pass flags from --enable-silent-libtool
LIBTOOL = @LIBTOOL@ @LIBTOOLFLAGS@
@@ -17,8 +18,8 @@
formats = 8svx.c adpcm.c adpcm.h adpcms.c adpcms.h aiff.c au.c auto.c avr.c \
cdr.c cvsd.c cvsdfilt.h dat.c flac.c g711.c g711.h g721.c \
g723_16.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 sndrtool.c sphere.c tx16w.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 sndfile.c sndrtool.c sphere.c tx16w.c \
voc.c vorbis.c vox.c wav.c wav.h wve.c xa.c
effects = avg.c band.c bandpass.c biquad.c biquad.h biquadlh.c breject.c \
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -54,6 +54,9 @@
st_sl_format_fn,
st_smp_format_fn,
st_snd_format_fn,
+#ifdef HAVE_SNDFILE_H
+ st_sndfile_format_fn,
+#endif
st_sphere_format_fn,
#ifdef HAVE_SUN_AUDIO
st_sun_format_fn,
--- /dev/null
+++ b/src/sndfile.c
@@ -1,0 +1,242 @@
+/*
+ * Sound Tools libsndfile formats.
+ *
+ * Copyright 2007 Reuben Thomas <rrt@sc3d.org>
+ * Copyright 1999-2005 Erik de Castro Lopo <eridk@mega-nerd.com>
+ *
+ * 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 "st_i.h"
+
+#ifdef HAVE_SNDFILE_H
+
+#include <stdio.h>
+#include <string.h>
+#include <sndfile.h>
+
+/* Private data for sndfile files */
+typedef struct sndfile
+{
+ SNDFILE *sf_file;
+ SF_INFO *sf_info;
+} *sndfile_t;
+
+assert_static(sizeof(struct sndfile) <= ST_MAX_FILE_PRIVSIZE,
+ /* else */ sndfile_PRIVSIZE_too_big);
+
+/*
+ * Open file in sndfile.
+ */
+int st_sndfile_startread(ft_t ft)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+
+ sf->sf_info = (SF_INFO *)xcalloc(1, sizeof(SF_INFO));
+ if ((sf->sf_file = sf_open(ft->filename, SFM_READ, sf->sf_info)) == NULL) {
+ st_fail("sndfile cannot open file for reading: %s %x", sf_strerror(sf->sf_file), sf->sf_info->format);
+ return ST_EOF;
+ }
+
+ /* Copy format info */
+ ft->signal.rate = sf->sf_info->samplerate;
+ ft->signal.size = ST_SIZE_32BIT;
+ ft->signal.encoding = ST_ENCODING_UNSIGNED;
+ ft->signal.channels = sf->sf_info->channels;
+ ft->length = sf->sf_info->frames * sf->sf_info->channels;
+
+ return ST_SUCCESS;
+}
+
+/*
+ * Read up to len samples of type st_sample_t from file into buf[].
+ * Return number of samples read.
+ */
+st_size_t st_sndfile_read(ft_t ft, st_sample_t *buf, st_size_t len)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+
+ /* FIXME: We assume int == st_sample_t here */
+ return (st_size_t)sf_read_int(sf->sf_file, (int *)buf, len);
+}
+
+/*
+ * Close file for libsndfile (this doesn't close the file handle)
+ */
+int st_sndfile_stopread(ft_t ft)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+ sf_close(sf->sf_file);
+ return ST_SUCCESS;
+}
+
+static struct {
+ const char *ext;
+ int len;
+ int format;
+} format_map[] =
+{
+ { "aif", 3, SF_FORMAT_AIFF },
+ { "wav", 0, SF_FORMAT_WAV },
+ { "au", 0, SF_FORMAT_AU },
+ { "caf", 0, SF_FORMAT_CAF },
+ { "flac", 0, SF_FORMAT_FLAC },
+ { "snd", 0, SF_FORMAT_AU },
+ { "svx", 0, SF_FORMAT_SVX },
+ { "paf", 0, SF_ENDIAN_BIG | SF_FORMAT_PAF },
+ { "fap", 0, SF_ENDIAN_LITTLE | SF_FORMAT_PAF },
+ { "gsm", 0, SF_FORMAT_RAW },
+ { "nist", 0, SF_FORMAT_NIST },
+ { "ircam", 0, SF_FORMAT_IRCAM },
+ { "sf", 0, SF_FORMAT_IRCAM },
+ { "voc", 0, SF_FORMAT_VOC },
+ { "w64", 0, SF_FORMAT_W64 },
+ { "raw", 0, SF_FORMAT_RAW },
+ { "mat4", 0, SF_FORMAT_MAT4 },
+ { "mat5", 0, SF_FORMAT_MAT5 },
+ { "mat", 0, SF_FORMAT_MAT4 },
+ { "pvf", 0, SF_FORMAT_PVF },
+ { "sds", 0, SF_FORMAT_SDS },
+ { "sd2", 0, SF_FORMAT_SD2 },
+ { "vox", 0, SF_FORMAT_RAW },
+ { "xi", 0, SF_FORMAT_XI }
+};
+
+static int guess_output_file_type(const char *type, int format)
+{
+ int k;
+
+ format &= SF_FORMAT_SUBMASK;
+
+ if (strcmp(type, "gsm") == 0)
+ return SF_FORMAT_RAW | SF_FORMAT_GSM610;
+
+ if (strcmp(type, "vox") == 0)
+ return SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM;
+
+ for (k = 0; k < (int)(sizeof(format_map) / sizeof(format_map [0])); k++) {
+ if (format_map[k].len > 0 && strncmp(type, format_map[k].ext, format_map[k].len) == 0)
+ return format_map[k].format | format;
+ else if (strcmp(type, format_map[k].ext) == 0)
+ return format_map[k].format | format;
+ }
+
+ return 0;
+}
+
+int st_sndfile_startwrite(ft_t ft)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+ sf->sf_info = (SF_INFO *)xmalloc(sizeof(SF_INFO));
+
+ /* Copy format info */
+ /* FIXME: Need to have a table of suitable default subtypes */
+ sf->sf_info->format = guess_output_file_type(ft->filetype, SF_FORMAT_PCM_16);
+ sf->sf_info->samplerate = ft->signal.rate;
+ sf->sf_info->channels = ft->signal.channels;
+ sf->sf_info->frames = ft->length / ft->signal.channels;
+
+ if (!sf_format_check(sf->sf_info)) {
+ st_fail("invalid sndfile output format");
+ return ST_EOF;
+ }
+
+ if ((sf->sf_file = sf_open(ft->filename, SFM_WRITE, sf->sf_info)) == NULL) {
+ st_fail("sndfile cannot open file for writing: %s", sf_strerror(sf->sf_file));
+ return ST_EOF;
+ }
+
+ return ST_SUCCESS;
+}
+
+/*
+ * Write len samples of type st_sample_t from buf[] to file.
+ * Return number of samples written.
+ */
+st_size_t st_sndfile_write(ft_t ft, const st_sample_t *buf, st_size_t len)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+
+ /* FIXME: We assume int == st_sample_t here */
+ return (st_size_t)sf_write_int(sf->sf_file, (int *)buf, len);
+}
+
+/*
+ * Close file for libsndfile (this doesn't close the file handle)
+ */
+int st_sndfile_stopwrite(ft_t ft)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+ sf_close(sf->sf_file);
+ return ST_SUCCESS;
+}
+
+int st_sndfile_seek(ft_t ft, st_size_t offset)
+{
+ sndfile_t sf = (sndfile_t)ft->priv;
+ sf_seek(sf->sf_file, offset / ft->signal.channels, SEEK_CUR);
+ return ST_SUCCESS;
+}
+
+/* Format file suffixes */
+/* For now, comment out formats built-in to SoX */
+static const char *names[] = {
+ /* "aif", */
+ /* "wav", */
+ /* "au", */
+ "caf",
+ /* "flac", */
+ /* "snd", */
+ /* "svx", */
+ "paf",
+ "fap",
+ /* "gsm", */
+ "nist",
+ /* "ircam", */
+ /* "sf", */
+ /* "voc", */
+ "w64",
+ /* "raw", */
+ "mat4",
+ "mat5",
+ "mat",
+ "pvf",
+ "sds",
+ "sd2",
+ /* "vox", */
+ "xi",
+ NULL
+};
+
+/* Format descriptor */
+static st_format_t st_sndfile_format = {
+ names,
+ NULL,
+ ST_FILE_SEEK,
+ st_sndfile_startread,
+ st_sndfile_read,
+ st_sndfile_stopread,
+ st_sndfile_startwrite,
+ st_sndfile_write,
+ st_sndfile_stopwrite,
+ st_sndfile_seek
+};
+
+const st_format_t *st_sndfile_format_fn(void)
+{
+ return &st_sndfile_format;
+}
+
+#endif
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -242,6 +242,9 @@
extern const st_format_t *st_sf_format_fn(void);
extern const st_format_t *st_smp_format_fn(void);
extern const st_format_t *st_snd_format_fn(void);
+#ifdef HAVE_SNDFILE_H
+extern const st_format_t *st_sndfile_format_fn(void);
+#endif
extern const st_format_t *st_sphere_format_fn(void);
#ifdef HAVE_SUN_AUDIO
extern const st_format_t *st_sun_format_fn(void);
@@ -257,8 +260,7 @@
extern const st_format_t *st_wve_format_fn(void);
extern const st_format_t *st_xa_format_fn(void);
-/* Raw I/O
- */
+/* Raw I/O */
int st_rawstartread(ft_t ft);
st_size_t st_rawread(ft_t ft, st_sample_t *buf, st_size_t nsamp);
int st_rawstopread(ft_t ft);
@@ -266,6 +268,16 @@
st_size_t st_rawwrite(ft_t ft, const st_sample_t *buf, st_size_t nsamp);
int st_rawstopwrite(ft_t ft);
int st_rawseek(ft_t ft, st_size_t offset);
+
+/* libsndfile I/O */
+int st_sndfile_startread(ft_t ft);
+st_size_t st_sndfile_read(ft_t ft, st_sample_t *buf, st_size_t len);
+int st_sndfile_stopread(ft_t ft);
+int st_sndfile_startwrite(ft_t ft);
+st_size_t st_sndfile_write(ft_t ft, const st_sample_t *buf, st_size_t len);
+int st_sndfile_stopwrite(ft_t ft);
+int st_sndfile_seek(ft_t ft, st_size_t offset);
+
/* The following functions can be used to simply return success if
* a file handler or effect doesn't need to do anything special