shithub: sox

Download patch

ref: 1ae149575634c0639342e96b0353e010d3fe621f
parent: 075f3b16097b7e12791ddcb236a5b3d0ceb088c0
author: robs <robs>
date: Sat Sep 12 18:32:09 EDT 2009

file IO in memory

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,7 @@
 check_include_files("termios.h"          HAVE_TERMIOS_H)
 check_include_files("unistd.h"           HAVE_UNISTD_H)
 
+check_function_exists("fmemopen"         HAVE_FMEMOPEN)
 check_function_exists("fseeko"           HAVE_FSEEKO)
 check_function_exists("gettimeofday"     HAVE_GETTIMEOFDAY)
 check_function_exists("mkstemp"          HAVE_MKSTEMP)
--- a/ChangeLog
+++ b/ChangeLog
@@ -29,7 +29,8 @@
 
 LibSoX interface changes:
 
-  None.
+  o Added new variants of sox_open to allow read/write from/to memory
+    buffers (in POSIX 200x environment); see example5.c  (robs)
 
 File formats:
 
--- a/configure.ac
+++ b/configure.ac
@@ -156,7 +156,7 @@
 AC_CHECK_HEADERS(fcntl.h unistd.h byteswap.h sys/time.h sys/timeb.h sys/types.h sys/utsname.h termios.h glob.h)
 
 dnl Checks for library functions.
-AC_CHECK_FUNCS(strcasecmp strdup popen vsnprintf gettimeofday mkstemp)
+AC_CHECK_FUNCS(strcasecmp strdup popen vsnprintf gettimeofday mkstemp fmemopen)
 
 dnl Check if math library is needed.
 AC_CHECK_FUNC(pow)
--- a/src/.cvsignore
+++ b/src/.cvsignore
@@ -1,6 +1,6 @@
 Makefile Makefile.in
 sox_sample_test
-example0 example1 example2 example3 example4
+example?
 soxconfig.h.in soxconfig.h soxstdint.h
 .deps
 stamp-h1
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -78,6 +78,8 @@
 target_link_libraries(example3 lib${PROJECT_NAME} lpc10 ${optional_libs})
 add_executable(example4 example4.c)
 target_link_libraries(example4 lib${PROJECT_NAME} lpc10 ${optional_libs})
+add_executable(example5 example5.c)
+target_link_libraries(example5 lib${PROJECT_NAME} lpc10 ${optional_libs})
 find_program(LN ln)
 if (LN)
   add_custom_target(rec ALL ${LN} -sf sox rec DEPENDS sox)
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,7 @@
 #########################
 
 bin_PROGRAMS = sox
-EXTRA_PROGRAMS = example0 example1 example2 example3 example4 sox_sample_test
+EXTRA_PROGRAMS = example0 example1 example2 example3 example4 example5 sox_sample_test
 lib_LTLIBRARIES = libsox.la
 include_HEADERS = sox.h
 nodist_include_HEADERS = soxstdint.h
@@ -41,6 +41,7 @@
 example2_SOURCES = example2.c
 example3_SOURCES = example3.c
 example4_SOURCES = example4.c
+example5_SOURCES = example5.c
 sox_sample_test_SOURCES = sox_sample_test.c sox_sample_test.h
 
 
@@ -123,12 +124,13 @@
 example2_LDADD = ${sox_LDADD}
 example3_LDADD = ${sox_LDADD}
 example4_LDADD = ${sox_LDADD}
+example5_LDADD = ${sox_LDADD}
 
 EXTRA_DIST = monkey.au monkey.wav optional-fmts.in \
 	     CMakeLists.txt soxstdint.h.cmake soxconfig.h.cmake \
 	     tests.sh testall.sh tests.bat testall.bat test-comments
 
-all: sox$(EXEEXT) play rec soxi sox_sample_test$(EXEEXT) example0$(EXEEXT) example1$(EXEEXT) example2$(EXEEXT) example3$(EXEEXT) example4$(EXEEXT)
+all: sox$(EXEEXT) play rec soxi sox_sample_test$(EXEEXT) example0$(EXEEXT) example1$(EXEEXT) example2$(EXEEXT) example3$(EXEEXT) example4$(EXEEXT) example5$(EXEEXT)
 
 play rec: sox$(EXEEXT)
 	if test "$(PLAYRECLINKS)" = "yes"; then	\
@@ -159,7 +161,7 @@
 clean-local:
 	$(RM) play rec soxi
 	$(RM) sox_sample_test$(EXEEXT)
-	$(RM) example0$(EXEEXT) example1$(EXEEXT) example2$(EXEEXT) example3$(EXEEXT) example4$(EXEEXT)
+	$(RM) example0$(EXEEXT) example1$(EXEEXT) example2$(EXEEXT) example3$(EXEEXT) example4$(EXEEXT) example5$(EXEEXT)
 
 distclean-local:
 	$(RM) soxstdint.h
@@ -173,6 +175,7 @@
 	$(example2_SOURCES) \
 	$(example3_SOURCES) \
 	$(example4_SOURCES) \
+	$(example5_SOURCES) \
 	$(sox_sample_test_SOURCES) \
 	$(libsox_la_SOURCES)
 
--- /dev/null
+++ b/src/example5.c
@@ -1,0 +1,83 @@
+/* Simple example of using SoX libraries
+ *
+ * Copyright (c) 2009 robs@users.sourceforge.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program 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 General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef NDEBUG /* N.B. assert used with active statements so enable always. */
+#undef NDEBUG /* Must undef above assert.h or other that might include it. */
+#endif
+
+#include "sox.h"
+#include "util.h"
+#include <stdio.h>
+#include <assert.h>
+
+/* Example of reading and writing audio files stored in memory buffers
+ * rather than actual files.
+ *
+ * Usage: example5 input output
+ */
+
+/* Uncomment following line for fixed instead of malloc'd buffer: */
+/*#define FIXED_BUFFER */
+
+#if defined FIXED_BUFFER
+#define buffer_size 123456
+static char buffer[buffer_size];
+#endif
+
+int main(int argc, char * argv[])
+{
+  static sox_format_t * in, * out; /* input and output files */
+  #define MAX_SAMPLES (size_t)2048
+  sox_sample_t samples[MAX_SAMPLES]; /* Temporary store whilst copying. */
+#if !defined FIXED_BUFFER
+  char * buffer;
+  size_t buffer_size;
+#endif
+  size_t number_read;
+
+  assert(argc == 3);
+
+  /* All libSoX applications must start by initialising the SoX library */
+  assert(sox_init() == SOX_SUCCESS);
+
+  /* Open the input file (with default parameters) */
+  assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
+#if defined FIXED_BUFFER
+  assert(out = sox_open_mem_write(buffer, buffer_size, &in->signal, NULL, "sox", NULL));
+#else
+  assert(out = sox_open_memstream_write(&buffer, &buffer_size, &in->signal, NULL, "sox", NULL));
+#endif
+  while ((number_read = sox_read(in, samples, MAX_SAMPLES)))
+    assert(sox_write(out, samples, number_read) == number_read);
+  sox_close(out);
+  sox_close(in);
+
+  assert(in = sox_open_mem_read(buffer, buffer_size, NULL, NULL, NULL));
+  assert(out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL));
+  while ((number_read = sox_read(in, samples, MAX_SAMPLES)))
+    assert(sox_write(out, samples, number_read) == number_read);
+  sox_close(out);
+  sox_close(in);
+#if !defined FIXED_BUFFER
+  free(buffer);
+#endif
+
+  sox_quit();
+  return 0;
+}
--- a/src/formats.c
+++ b/src/formats.c
@@ -412,8 +412,10 @@
 #endif
 }
 
-sox_format_t * sox_open_read(
+static sox_format_t * open_read(
     char               const * path,
+    void                     * buffer,
+    size_t                     buffer_size,
     sox_signalinfo_t   const * signal,
     sox_encodinginfo_t const * encoding,
     char               const * filetype)
@@ -444,7 +446,11 @@
       ft->fp = stdin;
     }
     else {
-      ft->fp = xfopen(path, "rb", &ft->io_type);
+      ft->fp =
+#ifdef HAVE_FMEMOPEN
+        buffer? fmemopen(buffer, buffer_size, "rb") :
+#endif
+        xfopen(path, "rb", &ft->io_type);
       type = io_types[ft->io_type];
       if (ft->fp == NULL) {
         lsx_fail("can't open input %s `%s': %s", type, path, strerror(errno));
@@ -554,6 +560,25 @@
   return NULL;
 }
 
+sox_format_t * sox_open_read(
+    char               const * path,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype)
+{
+  return open_read(path, NULL, 0, signal, encoding, filetype);
+}
+
+sox_format_t * sox_open_mem_read(
+    void                     * buffer,
+    size_t                     buffer_size,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype)
+{
+  return open_read("", buffer, buffer_size, signal,encoding,filetype);
+}
+
 sox_bool sox_format_supports_encoding(
     char               const * path,
     char               const * filetype,
@@ -776,8 +801,12 @@
   return handler;
 }
 
-sox_format_t * sox_open_write(
+static sox_format_t * open_write(
     char               const * path,
+    void                     * buffer,
+    size_t                     buffer_size,
+    char                     * * buffer_ptr,
+    size_t                   * buffer_size_ptr,
     sox_signalinfo_t   const * signal,
     sox_encodinginfo_t const * encoding,
     char               const * filetype,
@@ -814,7 +843,13 @@
         lsx_fail("permission to overwrite `%s' denied", path);
         goto error;
       }
-      if ((ft->fp = fopen(path, "w+b")) == NULL) {
+      ft->fp =
+#ifdef HAVE_FMEMOPEN
+        buffer? fmemopen(buffer, buffer_size, "w+b") :
+        buffer_ptr? open_memstream(buffer_ptr, buffer_size_ptr) :
+#endif
+        fopen(path, "w+b");
+      if (ft->fp == NULL) {
         lsx_fail("can't open output file `%s': %s", path, strerror(errno));
         goto error;
       }
@@ -884,6 +919,39 @@
   free(ft->filetype);
   free(ft);
   return NULL;
+}
+
+sox_format_t * sox_open_write(
+    char               const * path,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype,
+    sox_oob_t          const * oob,
+    sox_bool           (*overwrite_permitted)(const char *filename))
+{
+  return open_write(path, NULL, 0, NULL, NULL, signal, encoding, filetype, oob, overwrite_permitted);
+}
+
+sox_format_t * sox_open_mem_write(
+    void                     * buffer,
+    size_t                     buffer_size,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype,
+    sox_oob_t          const * oob)
+{
+  return open_write("", buffer, buffer_size, NULL, NULL, signal, encoding, filetype, oob, NULL);
+}
+
+sox_format_t * sox_open_memstream_write(
+    char                     * * buffer_ptr,
+    size_t                   * buffer_size_ptr,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype,
+    sox_oob_t          const * oob)
+{
+  return open_write("", NULL, 0, buffer_ptr, buffer_size_ptr, signal, encoding, filetype, oob, NULL);
 }
 
 size_t sox_read(sox_format_t * ft, sox_sample_t * buf, size_t len)
--- a/src/sox.h
+++ b/src/sox.h
@@ -412,6 +412,12 @@
     sox_signalinfo_t   const * signal,
     sox_encodinginfo_t const * encoding,
     char               const * filetype);
+sox_format_t * sox_open_mem_read(
+    void                     * buffer,
+    size_t                     buffer_size,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype);
 sox_bool sox_format_supports_encoding(
     char               const * path,
     char               const * filetype,
@@ -427,6 +433,20 @@
     char               const * filetype,
     sox_oob_t          const * oob,
     sox_bool           (*overwrite_permitted)(const char *filename));
+sox_format_t * sox_open_mem_write(
+    void                     * buffer,
+    size_t                     buffer_size,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype,
+    sox_oob_t          const * oob);
+sox_format_t * sox_open_memstream_write(
+    char                     * * buffer_ptr,
+    size_t                   * buffer_size_ptr,
+    sox_signalinfo_t   const * signal,
+    sox_encodinginfo_t const * encoding,
+    char               const * filetype,
+    sox_oob_t          const * oob);
 size_t sox_read(sox_format_t * ft, sox_sample_t *buf, size_t len);
 size_t sox_write(sox_format_t * ft, const sox_sample_t *buf, size_t len);
 int sox_close(sox_format_t * ft);
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -14,6 +14,9 @@
 #define SOX_I_H
 
 #include "soxomp.h"  /* Make this 1st in list (for soxconfig) */
+#if defined HAVE_FMEMOPEN
+#define _GNU_SOURCE
+#endif
 #include "sox.h"
 #include "util.h"
 
--- a/src/soxconfig.h.cmake
+++ b/src/soxconfig.h.cmake
@@ -10,6 +10,7 @@
 #cmakedefine HAVE_COREAUDIO           1
 #cmakedefine HAVE_FFMPEG              1
 #cmakedefine HAVE_FLAC                1
+#cmakedefine HAVE_FMEMOPEN            1
 #cmakedefine HAVE_FSEEKO              1
 #cmakedefine HAVE_GETTIMEOFDAY        1
 #cmakedefine HAVE_GLOB_H              1