shithub: sox

Download patch

ref: 902c63082ef28518b49625fbc0a8b6cda97e792d
parent: 52b037beffa79d224930c2b9edb4a1d00fa2cae9
author: robs <robs>
date: Fri Dec 12 16:19:56 EST 2008

changes for GOMP

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -69,6 +69,12 @@
 optional(HAVE_ALSA alsa/asoundlib.h asound snd_pcm_open alsa)
 optional(HAVE_AMRNB amrnb/sp_dec.h amrnb Decoder_Interface_init amr-nb)
 optional(HAVE_AMRWB amrwb/dec.h amrwb D_IF_init amr-wb)
+if(CMAKE_COMPILER_IS_GNUCC)
+  optional(HAVE_OPENMP omp.h gomp omp_get_thread_num "")
+  if(HAVE_OPENMP)
+    add_definitions(-fopenmp)
+  endif(HAVE_OPENMP)
+endif(CMAKE_COMPILER_IS_GNUCC)
 optional(HAVE_ID3TAG id3tag.h id3tag id3_file_open "")
 optional(HAVE_LIBAO ao/ao.h ao ao_play ao)
 optional(HAVE_FLAC FLAC/all.h FLAC FLAC__stream_encoder_new flac)
--- a/configure.ac
+++ b/configure.ac
@@ -183,7 +183,7 @@
 dnl Check for GOMP
 AC_MSG_CHECKING([whether to use GOMP])
 AC_ARG_ENABLE(gomp,
-    AC_HELP_STRING([--enable-gomp], [Use GOMP.]),,enable_gomp=no)
+    AC_HELP_STRING([--disable-gomp], [Don't use GOMP.]),,enable_gomp=yes)
 AC_MSG_RESULT($enable_gomp)
 if test "$enable_gomp" = "yes"; then
     AC_CHECK_HEADERS(omp.h,
@@ -191,10 +191,10 @@
         enable_gomp=no)
 fi
 if test "$enable_gomp" = yes; then
-   AC_DEFINE(HAVE_GOMP, 1, [Define to 1 if you have GOMP.])
+   AC_DEFINE(HAVE_OPENMP, 1, [Define to 1 if you have GOMP.])
    CFLAGS="$CFLAGS -fopenmp"
 fi
-AM_CONDITIONAL(HAVE_GOMP, test x$enable_gomp = xyes)
+AM_CONDITIONAL(HAVE_OPENMP, test x$enable_gomp = xyes)
 AC_SUBST(GOMP_LIBS)
 
 audio_driver_found=no  
--- a/src/8svx.c
+++ b/src/8svx.c
@@ -254,6 +254,7 @@
 static size_t write_samples(sox_format_t * ft, const sox_sample_t *buf, size_t len)
 {
         priv_t * p = (priv_t * ) ft->priv;
+        SOX_SAMPLE_LOCALS;
 
         unsigned char datum;
         size_t done = 0, i;
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -13,9 +13,7 @@
   else(${ver} LESS 403)
     add_definitions(-Wtraditional-conversion)
   endif(${ver} LESS 403)
-  add_definitions(-Werror)
-  add_definitions(-fopenmp)
-  set(optional_libs ${optional_libs} gomp)
+  #add_definitions(-Werror)
 endif(CMAKE_COMPILER_IS_GNUCC)
 
 if (NOT EXTERNAL_GSM)
--- a/src/adpcms.c
+++ b/src/adpcms.c
@@ -251,6 +251,7 @@
   short word;
 
   while (count < length) {
+    SOX_SAMPLE_LOCALS;
     word = SOX_SAMPLE_TO_SIGNED_16BIT(*buffer++, ft->clips);
 
     byte <<= 4;
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -536,6 +536,7 @@
 
 static void sox_ub_write_buf(char* buf1, sox_sample_t const * buf2, size_t len, sox_bool swap UNUSED, size_t * clips)
 {
+    SOX_SAMPLE_LOCALS;
     while (len--)
         *(uint8_t *)buf1++ = SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf2++, *clips);
 }
@@ -542,6 +543,7 @@
 
 static void sox_sb_write_buf(char *buf1, sox_sample_t const * buf2, size_t len, sox_bool swap UNUSED, size_t * clips)
 {
+    SOX_SAMPLE_LOCALS;
     while (len--)
         *(int8_t *)buf1++ = SOX_SAMPLE_TO_SIGNED_8BIT(*buf2++, *clips);
 }
@@ -550,6 +552,7 @@
 {
     while (len--)
     {
+        SOX_SAMPLE_LOCALS;
         uint16_t datum = SOX_SAMPLE_TO_UNSIGNED_16BIT(*buf2++, *clips);
         if (swap)
             datum = lsx_swapw(datum);
@@ -562,6 +565,7 @@
 {
     while (len--)
     {
+        SOX_SAMPLE_LOCALS;
         int16_t datum = SOX_SAMPLE_TO_SIGNED_16BIT(*buf2++, *clips);
         if (swap)
             datum = lsx_swapw(datum);
--- a/src/amr.h
+++ b/src/amr.h
@@ -117,6 +117,7 @@
   size_t done;
 
   for (done = 0; done < len; ++done) {
+    SOX_SAMPLE_LOCALS;
     p->pcm[p->pcm_index++] = SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
     if (p->pcm_index == AMR_FRAME) {
       p->pcm_index = 0;
--- a/src/ao.c
+++ b/src/ao.c
@@ -79,6 +79,7 @@
 {
     while (len--)
     {
+        SOX_SAMPLE_LOCALS;
         uint16_t datum = SOX_SAMPLE_TO_SIGNED_16BIT(*buf2++, *clips);
         if (swap)
             datum = lsx_swapw(datum);
--- a/src/bend.c
+++ b/src/bend.c
@@ -150,6 +150,7 @@
 
   /* main processing loop */
   for (i = 0; i < len; i++) {
+    SOX_SAMPLE_LOCALS;
     ++p->in_pos;
 
     /* As long as we have not yet collected enough data just read in */
--- a/src/coreaudio.c
+++ b/src/coreaudio.c
@@ -213,6 +213,7 @@
   size_t samp_left;
   OSStatus status;
   float *p;
+  SOX_SAMPLE_LOCALS;
 
   if (!ac->device_started)
   {
@@ -263,6 +264,7 @@
   size_t samp_left;
   OSStatus status;
   float *p;
+  SOX_SAMPLE_LOCALS;
 
   if (!ac->device_started)
   {
--- a/src/dat.c
+++ b/src/dat.c
@@ -135,6 +135,7 @@
       sprintf(s," %15.8g ",dat->timevalue);
       lsx_writes(ft, s);
       for (i=0; i<ft->signal.channels; i++) {
+        SOX_SAMPLE_LOCALS;
         sampval = SOX_SAMPLE_TO_FLOAT_64BIT(*buf++, ft->clips);
         sprintf(s," %15.8g", sampval);
         lsx_writes(ft, s);
--- a/src/effects.c
+++ b/src/effects.c
@@ -218,13 +218,15 @@
       for (f = 0; f < (int)effp->flows; ++f)
         chain->ibufc[f][i / effp->flows] = *ibuf++;
 
+#ifdef HAVE_OPENMP
     #pragma omp parallel for
+#endif
     for (f = 0; f < (int)effp->flows; ++f) {
       size_t idonec = idone / effp->flows;
       size_t odonec = obeg / effp->flows;
       int eff_status_c = effp->handler.flow(&chain->effects[n][f],
           chain->ibufc[f], chain->obufc[f], &idonec, &odonec);
-#ifndef HAVE_GOMP
+#ifndef HAVE_OPENMP
       if (f && (idonec != idone_last || odonec != odone_last)) {
         lsx_fail("flowed asymmetrically!");
         effstatus = SOX_EOF;
--- a/src/effects_i.c
+++ b/src/effects_i.c
@@ -397,26 +397,36 @@
 }
 
 #include "fft4g.h"
-int * lsx_fft_br;
+int    * lsx_fft_br;
 double * lsx_fft_sc;
+static int fft_len;
+#ifdef HAVE_OPENMP
+static omp_lock_t fft_cache_lock;
+#endif
 
-static void update_fft_cache(int len)
+static void init_fft_cache(void)
 {
-  static int n;
+  omp_init_lock(&fft_cache_lock);
+}
 
-  if (!len) {
-    free(lsx_fft_br);
-    free(lsx_fft_sc);
-    lsx_fft_sc = NULL;
-    lsx_fft_br = NULL;
-    n = 0;
-    return;
-  }
-  if (len > n) {
-    int old_n = n;
-    n = len;
-    lsx_fft_br = lsx_realloc(lsx_fft_br, dft_br_len(n) * sizeof(*lsx_fft_br));
-    lsx_fft_sc = lsx_realloc(lsx_fft_sc, dft_sc_len(n) * sizeof(*lsx_fft_sc));
+static void clear_fft_cache(void)
+{
+  omp_destroy_lock(&fft_cache_lock);
+  free(lsx_fft_br);
+  free(lsx_fft_sc);
+  lsx_fft_sc = NULL;
+  lsx_fft_br = NULL;
+  fft_len = 0;
+}
+
+static void update_fft_cache(int len)
+{
+  omp_set_lock(&fft_cache_lock);
+  if (len > fft_len) {
+    int old_n = fft_len;
+    fft_len = len;
+    lsx_fft_br = lsx_realloc(lsx_fft_br, dft_br_len(fft_len) * sizeof(*lsx_fft_br));
+    lsx_fft_sc = lsx_realloc(lsx_fft_sc, dft_sc_len(fft_len) * sizeof(*lsx_fft_sc));
     if (!old_n)
       lsx_fft_br[0] = 0;
   }
@@ -432,6 +442,7 @@
   assert(is_power_of_2(len));
   update_fft_cache(len);
   lsx_rdft(len, type, d, lsx_fft_br, lsx_fft_sc);
+  omp_unset_lock(&fft_cache_lock);
 }
 
 void lsx_safe_cdft(int len, int type, double * d)
@@ -439,6 +450,7 @@
   assert(is_power_of_2(len));
   update_fft_cache(len);
   lsx_cdft(len, type, d, lsx_fft_br, lsx_fft_sc);
+  omp_unset_lock(&fft_cache_lock);
 }
 
 void lsx_power_spectrum(int n, double const * in, double * out)
@@ -536,3 +548,14 @@
   }
 }
 
+int lsx_effects_init(void)
+{
+  init_fft_cache();
+  return SOX_SUCCESS;
+}
+
+int lsx_effects_quit(void)
+{
+  clear_fft_cache();
+  return SOX_SUCCESS;
+}
--- a/src/example0.c
+++ b/src/example0.c
@@ -38,7 +38,7 @@
   assert(argc == 3);
 
   /* All libSoX applications must start by initialising the SoX library */
-  assert(sox_format_init() == SOX_SUCCESS);
+  assert(sox_init() == SOX_SUCCESS);
 
   /* Open the input file (with default parameters) */
   assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
--- a/src/example1.c
+++ b/src/example1.c
@@ -110,7 +110,7 @@
   assert(argc == 3);
 
   /* All libSoX applications must start by initialising the SoX library */
-  assert(sox_format_init() == SOX_SUCCESS);
+  assert(sox_init() == SOX_SUCCESS);
 
   /* Open the input file (with default parameters) */
   assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
--- a/src/example2.c
+++ b/src/example2.c
@@ -87,6 +87,7 @@
     int l, r;
 
     for (i = 0; i < block_size; ++i) {
+      SOX_SAMPLE_LOCALS;
       /* convert the sample from SoX's internal format to a `double' for
        * processing in this application: */
       double sample = SOX_SAMPLE_TO_FLOAT_64BIT(buf[i], clips);
--- a/src/ffmpeg.c
+++ b/src/ffmpeg.c
@@ -406,6 +406,7 @@
   do {
     /* If output frame is not full, copy data into it */
     if (ffmpeg->samples_index < ffmpeg->audio_input_frame_size) {
+      SOX_SAMPLE_LOCALS;
       for (; nread < len && ffmpeg->samples_index < ffmpeg->audio_input_frame_size; nread++)
         ffmpeg->samples[ffmpeg->samples_index++] = SOX_SAMPLE_TO_SIGNED_16BIT(buf[nread], ft->clips);
     }
--- a/src/flac.c
+++ b/src/flac.c
@@ -436,6 +436,7 @@
   unsigned i;
 
   for (i = 0; i < len; ++i) {
+    SOX_SAMPLE_LOCALS;
     long pcm = SOX_SAMPLE_TO_SIGNED_32BIT(sampleBuffer[i], ft->clips);
     p->decoded_samples[i] = pcm >> (32 - p->bits_per_sample);
     switch (p->bits_per_sample) {
--- a/src/gsm.c
+++ b/src/gsm.c
@@ -195,6 +195,7 @@
 
         while (done < samp)
         {
+                SOX_SAMPLE_LOCALS;
                 while ((p->samplePtr < p->sampleTop) && (done < samp))
                         *(p->samplePtr)++ =
                             SOX_SAMPLE_TO_SIGNED_16BIT(buf[done++], ft->clips);
--- a/src/hcom.c
+++ b/src/hcom.c
@@ -277,6 +277,7 @@
   }
 
   for (i = 0; i < len; i++) {
+    SOX_SAMPLE_LOCALS;
     datum = *buf++;
     p->data[p->pos++] = SOX_SAMPLE_TO_UNSIGNED_8BIT(datum, ft->clips);
   }
--- a/src/ladspa.c
+++ b/src/ladspa.c
@@ -230,6 +230,7 @@
 
   if (len) {
     LADSPA_Data *buf = lsx_malloc(sizeof(LADSPA_Data) * len);
+    SOX_SAMPLE_LOCALS;
 
     /* Insert input if effect takes it */
     if (l_st->input_port != ULONG_MAX) {
--- a/src/libsox.c
+++ b/src/libsox.c
@@ -85,3 +85,14 @@
 
 #undef SOX_MESSAGE_FUNCTION
 
+int sox_init(void)
+{
+  sox_format_init();
+  return lsx_effects_init();
+}
+
+int sox_quit(void)
+{
+  sox_format_quit();
+  return lsx_effects_quit();
+}
--- a/src/loudness.c
+++ b/src/loudness.c
@@ -161,6 +161,7 @@
   priv_t * p = (priv_t *)effp->priv;
   size_t i, odone = min(*osamp, (size_t)fifo_occupancy(&p->output_fifo));
   double const * s = fifo_read(&p->output_fifo, (int)odone, NULL);
+  SOX_SAMPLE_LOCALS;
 
   for (i = 0; i < odone; ++i)
     *obuf++ = SOX_FLOAT_64BIT_TO_SAMPLE(*s++, effp->clips);
--- a/src/lpc10.c
+++ b/src/lpc10.c
@@ -153,6 +153,7 @@
   size_t nread = 0;
 
   while (nread < len) {
+    SOX_SAMPLE_LOCALS;
     /* Read more data if buffer is empty */
     if (lpc->samples == LPC10_SAMPLES_PER_FRAME) {
       INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
@@ -178,6 +179,7 @@
 
   while (len > 0) {
     while (len > 0 && lpc->samples < LPC10_SAMPLES_PER_FRAME) {
+      SOX_SAMPLE_LOCALS;
       lpc->speech[lpc->samples++] = SOX_SAMPLE_TO_FLOAT_32BIT(buf[nwritten++], ft->clips);
       len--;
     }
--- a/src/mp3.c
+++ b/src/mp3.c
@@ -406,6 +406,7 @@
     int i,j;
     ptrdiff_t done = 0;
     size_t written;
+    SOX_SAMPLE_LOCALS;
 
     /* NOTE: This logic assumes that "short int" is 16-bits
      * on all platforms.  It happens to be for all that I know
@@ -442,9 +443,7 @@
     {
         j=0;
         for (i=0; i<nsamples; i++)
-        {
             buffer_l[i]=SOX_SAMPLE_TO_SIGNED_16BIT(buf[j++], ft->clips);
-        }
     }
 
     mp3buffer_size = 1.25 * nsamples + 7200;
--- a/src/noiseprof.c
+++ b/src/noiseprof.c
@@ -124,6 +124,7 @@
 
   /* Collect data for every channel. */
   for (i = 0; i < chans; i ++) {
+    SOX_SAMPLE_LOCALS;
     chandata_t * chan = &(p->chandata[i]);
     for (j = 0; j < n; j ++)
       chan->window[j + p->bufdata] =
--- a/src/noisered.c
+++ b/src/noisered.c
@@ -230,6 +230,7 @@
     int use = min(len, WINDOWSIZE)-min(len,(WINDOWSIZE/2));
     chandata_t *chan = &(data->chandata[chan_num]);
     int first = (chan->lastwindow == NULL);
+    SOX_SAMPLE_LOCALS;
 
     if ((nextwindow = lsx_calloc(WINDOWSIZE, sizeof(float))) == NULL)
         return SOX_EOF;
@@ -283,6 +284,7 @@
 
     /* Reduce noise on every channel. */
     for (i = 0; i < tracks; i ++) {
+        SOX_SAMPLE_LOCALS;
         chandata_t* chan = &(data->chandata[i]);
         size_t j;
 
--- a/src/normalise.c
+++ b/src/normalise.c
@@ -63,6 +63,7 @@
     return SOX_EOF;
   }
   if (p->balance) for (len = *isamp; len; --len, ++ibuf) {
+    SOX_SAMPLE_LOCALS;
     size_t dummy = 0;
     double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf, dummy);
     p->rms += sqr(d);
--- a/src/overdrive.c
+++ b/src/overdrive.c
@@ -50,6 +50,7 @@
   priv_t * p = (priv_t *)effp->priv;
   size_t dummy = 0, len = *isamp = *osamp = min(*isamp, *osamp);
   while (len--) {
+    SOX_SAMPLE_LOCALS;
     double d = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf++, dummy), d0 = d;
     d *= p->gain;
     d += p->colour;
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -114,6 +114,7 @@
   size_t isamples0 = d->input_frames * channels;
   size_t isamples = isamples0 + *isamp;
   size_t osamples = isamples * (d->src_ratio + 0.01) + 8;
+  SOX_SAMPLE_LOCALS;
 
   if (osamples > *osamp) {
     osamples = *osamp;
--- a/src/rate.c
+++ b/src/rate.c
@@ -623,6 +623,7 @@
 {
   priv_t * p = (priv_t *)effp->priv;
   size_t i, odone = *osamp;
+  SOX_SAMPLE_LOCALS;
 
   sample_t const * s = rate_output(&p->rate, NULL, &odone);
   for (i = 0; i < odone; ++i) *obuf++ = TO_SOX(*s++, effp->clips);
--- a/src/raw.c
+++ b/src/raw.c
@@ -69,6 +69,7 @@
       sox_format_t * ft, sox_sample_t *buf, size_t len) \
   { \
     size_t n, nread; \
+    SOX_SAMPLE_LOCALS; \
     ctype *data = lsx_malloc(sizeof(ctype) * len); \
     nread = lsx_read_ ## type ## _buf(ft, (uctype *)data, len); \
     for (n = 0; n < nread; n++) \
@@ -94,6 +95,7 @@
   static size_t sox_write_ ## sign ## type ## _samples( \
       sox_format_t * ft, sox_sample_t const * buf, size_t len) \
   { \
+    SOX_SAMPLE_LOCALS; \
     size_t n, nwritten; \
     ctype *data = lsx_malloc(sizeof(ctype) * len); \
     for (n = 0; n < len; n++) \
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -219,6 +219,7 @@
 {
   priv_t * p = (priv_t *)effp->priv;
   size_t c, i, w, len = min(*isamp / p->ichannels, *osamp / p->ochannels);
+  SOX_SAMPLE_LOCALS;
 
   *isamp = len * p->ichannels, *osamp = len * p->ochannels;
   for (c = 0; c < p->ichannels; ++c)
--- a/src/silence.c
+++ b/src/silence.c
@@ -280,6 +280,7 @@
     /* Only consider the original bits when looking for silence */
     switch(effp->in_signal.precision)
     {
+        SOX_SAMPLE_LOCALS;
         case 8:
             value = SOX_SAMPLE_TO_SIGNED_8BIT(value, dummy_clipped_count);
             ratio = (double)abs(value) / (double)SOX_INT8_MAX;
--- a/src/skelform.c
+++ b/src/skelform.c
@@ -159,6 +159,7 @@
   switch (ft->encoding.bits_per_sample) {
   case 8:
     switch (ft->encoding.encoding) {
+    SOX_SAMPLE_LOCALS;
     case SOX_ENCODING_UNSIGNED:
       while (done < len && lsx_writeb(ft, SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips)) == SOX_SUCCESS)
         ++done;
--- a/src/smp.c
+++ b/src/smp.c
@@ -368,6 +368,7 @@
         size_t done = 0;
 
         while(done < len) {
+                SOX_SAMPLE_LOCALS;
                 datum = (int) SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
                 lsx_writew(ft, (uint16_t)datum);
                 smp->NoOfSamps++;
--- a/src/sox.c
+++ b/src/sox.c
@@ -20,7 +20,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "soxconfig.h"
+#include "soxomp.h"  /* Make this 1st in list (for soxconfig) */
 #include "sox.h"
 #include "util.h"
 
@@ -169,7 +169,11 @@
 static int success = 0;
 static sox_sample_t omax[2], omin[2];
 
+/* Multi-processing */
 
+static sox_bool single_threaded = sox_false;
+
+
 /* Cleanup atexit() function, hence always called. */
 static void cleanup(void)
 {
@@ -1516,12 +1520,18 @@
 #elif defined __SUNPRO_C
     fprintf(file, "sun c: %x\n", __SUNPRO_C);
 #endif
-    fprintf(file, "arch:  %lu%lu%lu%lu %lu%lu %lu%lu %c\n",
+    fprintf(file, "arch:  %lu%lu%lu%lu %lu%lu %lu%lu %c %s\n",
         (unsigned long)sizeof(char), (unsigned long)sizeof(short),
         (unsigned long)sizeof(long), (unsigned long)sizeof(off_t),
         (unsigned long)sizeof(float), (unsigned long)sizeof(double),
         (unsigned long)sizeof(int *), (unsigned long)sizeof(int (*)(void)),
-        "LB"[MACHINE_IS_BIGENDIAN]);
+        "LB"[MACHINE_IS_BIGENDIAN],
+#ifdef HAVE_OPENMP
+        "OMP"
+#else
+        ""
+#endif
+        );
   }
 }
 
@@ -1818,6 +1828,7 @@
     {"output"          , required_argument, NULL, 0},
     {"effects-file"    , required_argument, NULL, 0},
     {"temp"            , required_argument, NULL, 0},
+    {"single-threaded" ,       no_argument, NULL, 0},
 
     {"bits"            , required_argument, NULL, 'b'},
     {"channels"        , required_argument, NULL, 'c'},
@@ -2006,6 +2017,10 @@
         sox_globals.tmp_path = strdup(optarg);
         break;
 
+      case 17:
+        single_threaded = sox_true;
+        break;
+
       }
       break;
 
@@ -2443,7 +2458,7 @@
   else if (strends(myname, "soxi"))
     sox_mode = sox_soxi;
 
-  if (sox_format_init() != SOX_SUCCESS)
+  if (sox_init() != SOX_SUCCESS)
     exit(1);
 
   if (sox_mode == sox_soxi)
@@ -2469,6 +2484,11 @@
           sox_globals.tmp_path = ".";
     sox_globals.tmp_path = lsx_strdup(sox_globals.tmp_path);
   }
+#endif
+
+#ifdef HAVE_OPENMP
+  if (single_threaded)
+   omp_set_num_threads(1);
 #endif
 
   if (sox_globals.verbosity > 2)
--- a/src/sox.h
+++ b/src/sox.h
@@ -97,9 +97,8 @@
  * the upper-most bit then treating them as signed integers.
  */
 
-/* Temporary variables to prevent multiple evaluation of macro arguments: */
-static sox_sample_t sox_macro_temp_sample UNUSED;
-static double sox_macro_temp_double UNUSED;
+#define SOX_SAMPLE_LOCALS sox_sample_t sox_macro_temp_sample UNUSED; \
+  double sox_macro_temp_double UNUSED
 
 #define SOX_SAMPLE_NEG SOX_INT_MIN(32)
 #define SOX_SAMPLE_TO_UNSIGNED(bits,d,clips) \
@@ -395,7 +394,11 @@
 #define SOX_FILE_BIG_END (SOX_FILE_ENDIAN | SOX_FILE_ENDBIG)
 
 int sox_format_init(void);
+void sox_format_quit(void);
 
+int sox_init(void);
+int sox_quit(void);
+
 typedef const sox_format_handler_t *(*sox_format_fn_t)(void);
 
 typedef struct {
@@ -429,7 +432,6 @@
 int sox_seek(sox_format_t * ft, uint64_t offset, int whence);
 
 sox_format_handler_t const * sox_find_format(char const * name, sox_bool no_dev);
-void sox_format_quit(void);
 
 /*
  * Structures for effects.
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -13,7 +13,7 @@
 #ifndef SOX_I_H
 #define SOX_I_H
 
-#include "soxconfig.h"
+#include "soxomp.h"  /* Make this 1st in list (for soxconfig) */
 #include "sox.h"
 #include "util.h"
 
@@ -265,5 +265,8 @@
 }
 
 int lsx_effect_set_imin(sox_effect_t * effp, size_t imin);
+
+int lsx_effects_init(void);
+int lsx_effects_quit(void);
 
 #endif
--- a/src/sox_sample_test.h
+++ b/src/sox_sample_test.h
@@ -163,6 +163,7 @@
   size_t clips = 0;
 
   double d;
+  SOX_SAMPLE_LOCALS;
 
   TEST_UINT(8)
   TEST_UINT(16)
--- a/src/soxconfig.h.cmake
+++ b/src/soxconfig.h.cmake
@@ -23,6 +23,7 @@
 #cmakedefine HAVE_MKSTEMP             1
 #cmakedefine HAVE_OGG_SPEEX           1
 #cmakedefine HAVE_OGG_VORBIS          1
+#cmakedefine HAVE_OPENMP              1
 #cmakedefine HAVE_POPEN               1
 #cmakedefine HAVE_PNG                 1
 #cmakedefine HAVE_SAMPLERATE_H        1
--- /dev/null
+++ b/src/soxomp.h
@@ -1,0 +1,38 @@
+#include "soxconfig.h"
+
+#ifdef HAVE_OPENMP
+  #include <omp.h>
+#else
+
+typedef int omp_lock_t;
+typedef int omp_nest_lock_t;
+
+#define omp_set_num_threads(int) (void)0
+#define omp_get_num_threads() 1
+#define omp_get_max_threads() 1
+#define omp_get_thread_num() 0
+#define omp_get_num_procs() 1
+#define omp_in_parallel() 1
+
+#define omp_set_dynamic(int) (void)0
+#define omp_get_dynamic() 0
+
+#define omp_set_nested(int) (void)0
+#define omp_get_nested() 0
+
+#define omp_init_lock(omp_lock_t) (void)0
+#define omp_destroy_lock(omp_lock_t) (void)0
+#define omp_set_lock(omp_lock_t) (void)0
+#define omp_unset_lock(omp_lock_t) (void)0
+#define omp_test_lock(omp_lock_t) 0
+
+#define omp_init_nest_lock(omp_nest_lock_t) (void)0
+#define omp_destroy_nest_lock(omp_nest_lock_t) (void)0
+#define omp_set_nest_lock(omp_nest_lock_t) (void)0
+#define omp_unset_nest_lock(omp_nest_lock_t) (void)0
+#define omp_test_nest_lock(omp_nest_lock_t) 0
+
+#define omp_get_wtime() 0
+#define omp_get_wtick() 0
+
+#endif
--- a/src/spectrogram.c
+++ b/src/spectrogram.c
@@ -193,6 +193,7 @@
   *isamp = *osamp = len;
 
   while (sox_true) {
+    SOX_SAMPLE_LOCALS;
     if (p->read == p->step_size) {
       memmove(p->buf, p->buf + p->step_size,
           (p->dft_size - p->step_size) * sizeof(*p->buf));
--- a/src/splice.c
+++ b/src/splice.c
@@ -152,6 +152,7 @@
 {
   priv_t * p = (priv_t *)effp->priv;
   size_t c, idone = 0, odone = 0;
+  SOX_SAMPLE_LOCALS;
   *isamp /= effp->in_signal.channels;
   *osamp /= effp->in_signal.channels;
 
--- a/src/stat.c
+++ b/src/stat.c
@@ -140,6 +140,7 @@
 
     if (stat->fft) {
       for (x = 0; x < len; x++) {
+        SOX_SAMPLE_LOCALS;
         stat->re_in[stat->fft_offset++] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[x], effp->clips);
 
         if (stat->fft_offset >= stat->fft_size) {
--- a/src/tempo.c
+++ b/src/tempo.c
@@ -264,6 +264,7 @@
   priv_t * p = (priv_t *)effp->priv;
   size_t i, odone = *osamp /= effp->in_signal.channels;
   float const * s = tempo_output(p->tempo, NULL, &odone);
+  SOX_SAMPLE_LOCALS;
 
   for (i = 0; i < odone * effp->in_signal.channels; ++i)
     *obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(*s++, effp->clips);
--- a/src/voc.c
+++ b/src/voc.c
@@ -347,6 +347,7 @@
       /* Read the data in the file */
       if (v->size <= 4) {
         if (!v->adpcm.setup.sign) {
+          SOX_SAMPLE_LOCALS;
           if (lsx_readb(ft, &uc) == SOX_EOF) {
             lsx_warn("VOC input: short file");
             v->block_remaining = 0;
@@ -489,6 +490,7 @@
   }
   v->samples += len;
   while (done < len) {
+    SOX_SAMPLE_LOCALS;
     if (ft->encoding.bits_per_sample == 8) {
       uc = SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips);
       lsx_writeb(ft, uc);
--- a/src/wav.c
+++ b/src/wav.c
@@ -331,6 +331,7 @@
     ft->sox_errno = SOX_SUCCESS;
 
     while (done < len) {
+        SOX_SAMPLE_LOCALS;
         while ((wav->gsmindex < 160*2) && (done < len))
             wav->gsmsample[(wav->gsmindex)++] =
                 SOX_SAMPLE_TO_SIGNED_16BIT(buf[done++], ft->clips);
--- a/src/wavpack.c
+++ b/src/wavpack.c
@@ -71,6 +71,7 @@
   priv_t * p = (priv_t *)ft->priv;
   size_t i, actual = WavpackUnpackSamples(p->codec, buf, (uint32_t) len / ft->signal.channels) * ft->signal.channels;
   for (i = 0; i < actual; ++i) switch (ft->encoding.bits_per_sample) {
+    SOX_SAMPLE_LOCALS;
     case  8: buf[i] = SOX_SIGNED_8BIT_TO_SAMPLE(buf[i],); break;
     case 16: buf[i] = SOX_SIGNED_16BIT_TO_SAMPLE(buf[i],); break;
     case 24: buf[i] = SOX_SIGNED_24BIT_TO_SAMPLE(buf[i],); break;
@@ -119,6 +120,7 @@
   int result;
 
   for (i = 0; i < len; ++i) switch (ft->encoding.bits_per_sample) {
+    SOX_SAMPLE_LOCALS;
     case  8: obuf[i] = SOX_SAMPLE_TO_SIGNED_8BIT(buf[i], ft->clips); break;
     case 16: obuf[i] = SOX_SAMPLE_TO_SIGNED_16BIT(buf[i], ft->clips); break;
     case 24: obuf[i] = SOX_SAMPLE_TO_SIGNED_24BIT(buf[i], ft->clips) << 8;