shithub: sox

Download patch

ref: c08494b8ad75e0e9f964c3257a88fc82138db631
parent: 08cd2f3d04583fc45a3cf2852a940f27adfafede
author: robs <robs>
date: Tue Dec 25 16:34:27 EST 2007

Simple example of using SoX libraries

--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -48,9 +48,12 @@
   getopt                  soxio
   getopt1                 soxstdint
 )
+set(optional_libs /usr/local/lib/libsndfile.so ${optional_libs})
 add_executable(${PROJECT_NAME} ${PROJECT_NAME}.c)
 target_link_libraries(${PROJECT_NAME} lib${PROJECT_NAME} lpc10 ${optional_libs})
 add_executable(sox_sample_test sox_sample_test.c)
+add_executable(example1 example1.c)
+target_link_libraries(example1 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
@@ -12,11 +12,14 @@
 # SoX - the application #
 #########################
 
-bin_PROGRAMS = sox
+bin_PROGRAMS = sox sox_sample_test example1
 lib_LTLIBRARIES = libsox.la libsfx.la
 include_HEADERS = sox.h soxstdint.h
 sox_SOURCES = sox.c
 sox_LDADD = libsox.la libsfx.la
+example1_SOURCES = example1.c
+example1_LDADD = libsox.la libsfx.la
+sox_sample_test_SOURCES = sox_sample_test.c
 
 #############################################
 # libsox Dynamic Libraries for File Formats #
@@ -282,9 +285,9 @@
 #end !HAVE_LIBLTDL
 endif
 
-EXTRA_DIST = tests.sh testall.sh tests.bat testall.bat monkey.au monkey.wav sox_sample_test.c amr-wb-test CMakeLists.txt soxstdint.h.cmake soxconfig.h.cmake
+EXTRA_DIST = tests.sh testall.sh tests.bat testall.bat monkey.au monkey.wav sox_sample_test.c amr-wb-test CMakeLists.txt soxstdint.h.cmake soxconfig.h.cmake example1.c
 
-all: sox$(EXEEXT) play rec
+all: sox$(EXEEXT) play rec sox_sample_test example1
 
 play rec: sox$(EXEEXT)
 	./sox --help > /dev/null
@@ -298,6 +301,7 @@
 clean-local:
 	$(RM) play rec
 	$(RM) sox_sample_test
+	$(RM) example1
 
 distclean-local:
 	$(RM) soxstdint.h
--- a/src/effects.c
+++ b/src/effects.c
@@ -92,6 +92,13 @@
 
 /* Effects chain: */
 
+sox_effects_chain_t * sox_create_effects_chain(void)
+{
+  sox_effects_chain_t * result = xcalloc(1, sizeof(sox_effects_chain_t));
+  result->global_info = sox_effects_globals;
+  return result;
+}
+
 /* Effect can call in start() or flow() to set minimum input size to flow() */
 int sox_effect_set_imin(sox_effect_t * effp, sox_size_t imin)
 {
@@ -364,8 +371,17 @@
 /* Remove all effects from the chain */
 void sox_delete_effects(sox_effects_chain_t * chain)
 {
-  while (chain->length)
-    free(chain->effects[--chain->length]);
+  sox_size_t e, clips;
+
+  for (e = 0; e < chain->length; ++e) {
+    sox_effect_t * effp = chain->effects[e];
+    if ((clips = sox_stop_effect(chain, e)) != 0)
+      sox_warn("%s clipped %u samples; decrease volume?",
+          chain->effects[e][0].handler.name, clips);
+    effp->handler.kill(effp);
+    free(chain->effects[e]);
+  }
+  chain->length = 0;
 }
 
 
--- /dev/null
+++ b/src/example1.c
@@ -1,0 +1,107 @@
+/*
+ * Simple example of using SoX libraries
+ *
+ * Copyright (c) 2007 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, Fifth
+ * Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
+ */
+
+#include "sox.h"
+#include <stdio.h>
+#ifdef NDEBUG /* N.B. assert used with active statements so enable always */
+#undef NDEBUG
+#endif
+#include <assert.h>
+
+static sox_format_t * in, * out;
+
+static int input_drain(sox_effect_t *effp, sox_sample_t * obuf, sox_size_t * osamp)
+{
+  *osamp -= *osamp % effp->outinfo.channels;
+  *osamp = sox_read(in, obuf, *osamp);
+  *osamp -= *osamp % effp->outinfo.channels;
+  if (!*osamp && in->sox_errno)
+    fprintf(stderr, "%s: %s\n", in->filename, in->sox_errstr);
+  return *osamp? SOX_SUCCESS : SOX_EOF;
+}
+
+static int output_flow(sox_effect_t *effp UNUSED, sox_sample_t const * ibuf,
+    sox_sample_t * obuf UNUSED, sox_size_t * isamp, sox_size_t * osamp)
+{
+  size_t len;
+  for (*osamp = *isamp; *osamp; ibuf += len, *osamp -= len) {
+    len = sox_write(out, ibuf, *osamp);
+    if (!len || out->sox_errno) {
+      fprintf(stderr, "%s: %s\n", out->filename, out->sox_errstr);
+      return SOX_EOF;
+    }
+  }
+  return SOX_SUCCESS;
+}
+
+static sox_effect_handler_t const * input_handler(void)
+{
+  static sox_effect_handler_t handler = {
+    "input", NULL, SOX_EFF_MCHAN, NULL, NULL, NULL, input_drain, NULL, NULL
+  };
+  return &handler;
+}
+
+static sox_effect_handler_t const * output_handler(void)
+{
+  static sox_effect_handler_t handler = {
+    "output", NULL, SOX_EFF_MCHAN, NULL, NULL, output_flow, NULL, NULL, NULL
+  };
+  return &handler;
+}
+
+/* 
+ * Reads input file, applies vol & reverb effects, stores in output file.
+ * E.g. example1 monkey.au monkey.aiff
+ */
+int main(int argc, char * argv[])
+{
+  sox_effects_chain_t * chain = sox_create_effects_chain();
+  sox_effect_t e;
+  char * vol[] = {"3dB"};
+
+  assert(argc == 3);
+  assert(sox_format_init() == SOX_SUCCESS);
+
+  assert(in = sox_open_read(argv[1], NULL, NULL));
+  sox_create_effect(&e, input_handler());
+  assert(sox_add_effect(chain, &e, &in->signal, &in->signal) == SOX_SUCCESS);
+
+  sox_create_effect(&e, sox_find_effect("vol"));
+  assert(e.handler.getopts(&e, 1, vol) == SOX_SUCCESS);
+  assert(sox_add_effect(chain, &e, &in->signal, &in->signal) == SOX_SUCCESS);
+
+  sox_create_effect(&e, sox_find_effect("reverb"));
+  assert(e.handler.getopts(&e, 0, NULL) == SOX_SUCCESS);
+  assert(sox_add_effect(chain, &e, &in->signal, &in->signal) == SOX_SUCCESS);
+
+  assert(out = sox_open_write(NULL, argv[2], &in->signal, NULL, NULL, 0, NULL, 0));
+  sox_create_effect(&e, output_handler());
+  assert(sox_add_effect(chain, &e, &in->signal, &in->signal) == SOX_SUCCESS);
+
+  assert(sox_flow_effects(chain, NULL) == SOX_SUCCESS);
+
+  sox_close(out);
+  sox_delete_effects(chain);
+  sox_close(in);
+  sox_format_quit();
+  free(chain);
+  return 0;
+}
--- a/src/sox.c
+++ b/src/sox.c
@@ -17,7 +17,7 @@
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this library. If not, write to the Free Software
+ * along with this program. If not, write to the Free Software
  * Foundation, Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301,
  * USA.
  */
@@ -325,7 +325,6 @@
   for (i = 0; i < input_count; i++) {
     if (files[i]->ft) {
       sox_close(files[i]->ft);
-      free(files[i]->ft);
     }
     free(files[i]);
   }
@@ -343,7 +342,6 @@
 
       /* Assumption: we can unlink a file before sox_closing it. */
       sox_close(ofile->ft);
-      free(ofile->ft);
     }
     free(ofile);
   }
@@ -708,13 +706,9 @@
   if (combine_method == sox_sequence) do {
     if (ofile->ft)
       sox_close(ofile->ft);
-    free(ofile->ft);
   } while (process() != SOX_EOF && !user_abort && current_input < input_count);
   else process();
 
-  while (nuser_effects--)
-    user_efftab[nuser_effects].handler.kill(&user_efftab[nuser_effects]);
-
   for (i = 0; i < file_count; ++i)
     if (files[i]->ft->clips != 0)
       sox_warn(i < input_count?"%s: input clipped %u samples" :
@@ -1147,12 +1141,29 @@
     files[i]->ft->signal.rate     == files[i - 1]->ft->signal.rate;
 }
 
+static void display_error(sox_format_t * ft)
+{
+  static char const * const sox_strerror[] = {
+    "Invalid Audio Header",
+    "Unsupported data format",
+    "Unsupported rate for format",
+    "Can't alloc memory",
+    "Operation not permitted",
+    "Operation not supported",
+    "Invalid argument",
+    "Unsupported file format",
+  };
+  sox_fail("%s: %s (%s)", ft->filename, ft->sox_errstr,
+      ft->sox_errno < SOX_EHDR?
+      strerror(ft->sox_errno) : sox_strerror[ft->sox_errno - SOX_EHDR]);
+}
+
 static sox_size_t sox_read_wide(sox_format_t * ft, sox_sample_t * buf, sox_size_t max)
 {
   sox_size_t len = max / combiner.channels;
   len = sox_read(ft, buf, len * ft->signal.channels) / ft->signal.channels;
   if (!len && ft->sox_errno)
-    sox_fail("%s: %s (%s)", ft->filename, ft->sox_errstr, strerror(ft->sox_errno));
+    display_error(ft);
   return len;
 }
 
@@ -1439,16 +1450,6 @@
   return user_abort? SOX_EOF : SOX_SUCCESS;
 }
 
-static void sox_stop_effects(sox_effects_chain_t * chain)
-{
-  sox_size_t e, clips;
-
-  for (e = 0; e < chain->length; ++e)
-    if ((clips = sox_stop_effect(chain, e)) != 0)
-      sox_warn("%s clipped %u samples; decrease volume?",
-          chain->effects[e][0].handler.name, clips);
-}
-
 /*
  * Process:   Input(s) -> Balancing -> Combiner -> Effects -> Output
  */
@@ -1530,7 +1531,6 @@
   
   flowstatus = sox_flow_effects(&ofile_effects_chain, update_status);
 
-  sox_stop_effects(&ofile_effects_chain);
   sox_delete_effects(&ofile_effects_chain);
   return flowstatus;
 }
--- a/src/sox.h
+++ b/src/sox.h
@@ -433,6 +433,7 @@
 
 struct sox_effects_chain;
 typedef struct sox_effects_chain sox_effects_chain_t;
+sox_effects_chain_t * sox_create_effects_chain(void);
 
 int sox_add_effect(sox_effects_chain_t *, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out);
 int sox_flow_effects(sox_effects_chain_t *, int (* callback)(sox_bool all_done));
--- a/src/soxio.c
+++ b/src/soxio.c
@@ -15,8 +15,18 @@
   #include <ltdl.h>
 #endif
 
-sox_globals_t sox_globals = {2, 8192, NULL, NULL, NULL, NULL};
+static void output_message(unsigned level, const char *filename, const char *fmt, va_list ap);
 
+sox_globals_t sox_globals = {2, 8192, NULL, NULL, output_message, NULL};
+
+static void output_message(unsigned level, const char *filename, const char *fmt, va_list ap)
+{
+  if (sox_globals.verbosity >= level) {
+    sox_output_message(stderr, filename, fmt, ap);
+    fprintf(stderr, "\n");
+  }
+}
+
 /* Plugins */
 
 #ifdef HAVE_LIBLTDL
@@ -179,6 +189,10 @@
 {
     sox_format_t * ft = xcalloc(sizeof(*ft), 1);
 
+    ft->signal.reverse_bytes =
+    ft->signal.reverse_nibbles =
+    ft->signal.reverse_bits = SOX_OPTION_DEFAULT;
+
     ft->filename = xstrdup(path);
 
     /* Let auto type do the work if user is not overriding. */
@@ -307,7 +321,7 @@
         else {
           struct stat st;
           if (!stat(ft->filename, &st) && (st.st_mode & S_IFMT) == S_IFREG &&
-              !overwrite_permitted(ft->filename)) {
+              (overwrite_permitted && !overwrite_permitted(ft->filename))) {
             sox_fail("Permission to overwrite '%s' denied", ft->filename);
             goto output_error;
           }
@@ -513,6 +527,7 @@
     if (ft->mode == 'w')
         free(ft->comment);
 
+    free(ft);
     return rc;
 }