[hamradio-commits] [liquid-dsp] 01/10: New upstream version 1.3.1

Andreas E. Bombe aeb at moszumanska.debian.org
Sun Oct 29 00:54:27 UTC 2017


This is an automated email from the git hooks/post-receive script.

aeb pushed a commit to annotated tag debian/1.3.1-1
in repository liquid-dsp.

commit b9daffa35f70910d37c5ca24611d670af44e2372
Author: Andreas Bombe <aeb at debian.org>
Date:   Sat Oct 28 19:57:04 2017 +0200

    New upstream version 1.3.1
---
 configure.ac                                 |  28 +-
 examples/agc_crcf_squelch_example.c          | 166 +++++++
 examples/asgramcf_example.c                  |  18 +-
 examples/firdespm_callback_example.c         |  95 ++++
 examples/firdespm_example.c                  |  76 +---
 examples/firdespm_lowpass_example.c          |  89 ++++
 examples/spgramcf_waterfall_example.c        |   2 +-
 examples/spwaterfallcf_example.c             |  78 ++++
 examples/symtrack_cccf_example.c             |  23 +-
 include/liquid.h                             | 656 +++++++++++++++++----------
 include/liquid.internal.h                    |  68 +--
 makefile.in                                  |  62 +--
 scripts/ax_ext.m4                            |  11 +-
 scripts/config.guess                         | 565 ++++++++++-------------
 scripts/config.sub                           | 313 ++++++++-----
 src/agc/src/agc.c                            | 127 +++++-
 src/agc/tests/agc_crcf_autotest.c            |  55 +++
 src/equalization/tests/eqlms_cccf_autotest.c |   8 +-
 src/fec/src/fec.c                            | 100 +++-
 src/fec/src/fec_conv.c                       |   3 +
 src/fec/src/fec_conv_punctured.c             |   3 +
 src/fec/src/fec_rs.c                         |   4 +-
 src/fec/src/packetizer.c                     |  10 +-
 src/fft/src/asgram.c                         | 131 +++---
 src/fft/src/spgram.c                         |  25 +-
 src/fft/src/spgramcf.c                       |   2 +
 src/fft/src/spgramf.c                        |   2 +
 src/fft/src/spwaterfall.c                    | 363 +++++++++++++++
 src/filter/src/firdespm.c                    | 233 ++++++++--
 src/filter/src/firpfb.c                      |   4 +-
 src/filter/src/iirdes.pll.c                  |   6 +-
 src/filter/src/iirfilt.c                     |  37 +-
 src/filter/src/iirfiltsos.c                  |  60 ++-
 src/filter/src/resamp.c                      |  36 +-
 src/filter/src/symsync.c                     |  19 +-
 src/framing/bench/qdetector_benchmark.c      |  97 ++++
 src/framing/src/detector_cccf.c              |   4 +
 src/framing/src/flexframegen.c               |   4 +-
 src/framing/src/flexframesync.c              |   9 +-
 src/framing/src/framegen64.c                 |   4 +-
 src/framing/src/framesync64.c                |   4 +-
 src/framing/src/gmskframesync.c              |  91 ++--
 src/framing/src/ofdmflexframesync.c          |   5 +
 src/framing/src/symtrack.c                   |  10 +-
 src/multichannel/src/ofdmframesync.c         |   5 +
 45 files changed, 2673 insertions(+), 1038 deletions(-)

diff --git a/configure.ac b/configure.ac
index 100cdd7..1445de9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 - 2016 Joseph Gaeddert
+# Copyright (c) 2007 - 2017 Joseph Gaeddert
 # 
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -33,6 +33,9 @@ AC_CONFIG_AUX_DIR(scripts/)
 # Specify 'C' language
 AC_LANG(C)
 
+# uncomment the following line to reset "CFLAGS" variable; it defaults to '-g -O2'
+#: ${CFLAGS=""}
+
 # Autoheader
 AH_TEMPLATE([LIQUID_FFTOVERRIDE],  [Force internal FFT even if libfftw is available])
 AH_TEMPLATE([LIQUID_SIMDOVERRIDE], [Force overriding of SIMD (use portable C code)])
@@ -48,10 +51,10 @@ AH_BOTTOM([
 
 # Configure options
 
-AC_ARG_ENABLE(debug,
-    AS_HELP_STRING([--enable-debug],[debug]),
-    [DEBUG_OPTION="-DDEBUG"],
-    [DEBUG_OPTION=""]
+AC_ARG_ENABLE(debug-messages,
+    AS_HELP_STRING([--enable-debug-messages],[enable verbose debug messages (-DDEBUG)]),
+    [DEBUG_MSG_OPTION="-DDEBUG"],
+    [DEBUG_MSG_OPTION=""]
 )
 
 AC_ARG_ENABLE(simdoverride,
@@ -72,6 +75,10 @@ AC_PROG_SED
 AC_PROG_GREP
 AC_PROG_INSTALL
 AC_PROG_RANLIB
+AN_MAKEVAR([AR], [AC_PROG_AR])
+AN_PROGRAM([ar], [AC_PROG_AR])
+AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL(AR, ar, :)])
+AC_PROG_AR
 
 # Check for necessary libraries, library functions
 AC_FUNC_ERROR_AT_LINE
@@ -161,12 +168,21 @@ else
                            src/dotprod/src/dotprod_crcf.mmx.o \
                            src/dotprod/src/dotprod_rrrf.mmx.o \
                            src/dotprod/src/sumsq.mmx.o"
+            ARCH_OPTION='-msse4.1'
+        elif [ test "$ax_cv_have_sse3_ext" = yes && test "$ac_cv_header_pmmintrin_h" = yes ]; then
+            # SSE3 extensions
+            MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.mmx.o \
+                           src/dotprod/src/dotprod_crcf.mmx.o \
+                           src/dotprod/src/dotprod_rrrf.mmx.o \
+                           src/dotprod/src/sumsq.mmx.o"
+            ARCH_OPTION='-msse3'
         elif [ test "$ax_cv_have_sse2_ext" = yes && test "$ac_cv_header_emmintrin_h" = yes ]; then
             # SSE2 extensions
             MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.mmx.o \
                            src/dotprod/src/dotprod_crcf.mmx.o \
                            src/dotprod/src/dotprod_rrrf.mmx.o \
                            src/dotprod/src/sumsq.mmx.o"
+            ARCH_OPTION='-msse2'
         else
             # portable C version
             MLIBS_DOTPROD="src/dotprod/src/dotprod_cccf.o \
@@ -242,7 +258,7 @@ AC_SUBST(SH_LIB)                    # output shared library target
 AC_SUBST(REBIND)                    # rebinding tool (e.g. ldconfig)
 AC_SUBST(ARCH_OPTION)               # compiler architecture option
 
-AC_SUBST(DEBUG_OPTION)              # debug option
+AC_SUBST(DEBUG_MSG_OPTION)          # debug messages option (.e.g -DDEBUG)
 AC_SUBST(CLIB)                      # C library linkage (e.g. '-lc')
 
 AC_CONFIG_FILES([makefile])
diff --git a/examples/agc_crcf_squelch_example.c b/examples/agc_crcf_squelch_example.c
new file mode 100644
index 0000000..5585b4c
--- /dev/null
+++ b/examples/agc_crcf_squelch_example.c
@@ -0,0 +1,166 @@
+//
+// agc_crcf_example.c
+//
+// Automatic gain control example demonstrating its transient
+// response.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <complex.h>
+#include <getopt.h>
+#include "liquid.h"
+
+#define OUTPUT_FILENAME "agc_crcf_squelch_example.m"
+
+// print usage/help message
+void usage()
+{
+    printf("agc_crcf_squelch_example [options]\n");
+    printf("  -h             : print usage\n");
+    printf("  -b <bandwidth> : AGC bandwidth, b >=  0, default: 0.25\n");
+}
+
+
+int main(int argc, char*argv[])
+{
+    // options
+    float bt = 0.25f;   // agc loop bandwidth
+
+    int dopt;
+    while((dopt = getopt(argc,argv,"hn:N:s:b:")) != EOF){
+        switch (dopt) {
+        case 'h': usage();           return 0;
+        case 'b': bt = atof(optarg); break;
+        default:
+            exit(1);
+        }
+    }
+
+    // validate input
+    if (bt < 0.0f) {
+        fprintf(stderr,"error: %s, bandwidth must be positive\n", argv[0]);
+        exit(1);
+    }
+    unsigned int i;
+
+    // create agc object, set loop bandwidth, and initialize parameters
+    agc_crcf q = agc_crcf_create();
+    agc_crcf_set_bandwidth(q, bt);
+    agc_crcf_set_signal_level(q,1e-3f);     // initial guess at starting signal level
+
+    // initialize squelch functionality
+    agc_crcf_squelch_enable(q);             // enable squelch
+    agc_crcf_squelch_set_threshold(q, -50); // threshold for detection [dB]
+    agc_crcf_squelch_set_timeout  (q, 100); // timeout for hysteresis
+
+    // initialize arrays
+    unsigned int  num_samples = 2000;       // total number of samples to run
+    float complex x   [num_samples];        // input
+    float complex y   [num_samples];        // output
+    float         rssi[num_samples];        // received signal strength
+    int           mode[num_samples];        // squelch mode
+
+    // print info
+    printf("automatic gain control // loop bandwidth: %4.2e\n",bt);
+
+    // generate signal, applying tapering window appropriately
+    for (i=0; i<num_samples; i++) {
+        float gamma = 0.0f;
+        if      (i <  500) gamma = 1e-3f;
+        else if (i <  550) gamma = 1e-3f + (1e-2f - 1e-3f)*(0.5f - 0.5f*cosf(M_PI*(float)(i- 500)/50.0f));
+        else if (i < 1450) gamma = 1e-2f;
+        else if (i < 1500) gamma = 1e-3f + (1e-2f - 1e-3f)*(0.5f + 0.5f*cosf(M_PI*(float)(i-1450)/50.0f));
+        else               gamma = 1e-3f;
+
+        // apply window to signal
+        x[i] = gamma * cexpf(_Complex_I*2*M_PI*0.0193f*i);
+    }
+
+    // run agc
+    for (i=0; i<num_samples; i++) {
+        // apply gain
+        agc_crcf_execute(q, x[i], &y[i]);
+
+        // retrieve signal level [dB]
+        rssi[i] = agc_crcf_get_rssi(q);
+
+        // get squelch mode
+        mode[i] = agc_crcf_squelch_get_status(q);
+
+        // print status every so often
+        if ( (i % 100)==0 || i==num_samples-1 || mode[i] == LIQUID_AGC_SQUELCH_RISE || mode[i] == LIQUID_AGC_SQUELCH_FALL) {
+            char mode_str[20] = "";
+            switch (mode[i]) {
+            case LIQUID_AGC_SQUELCH_ENABLED:  sprintf(mode_str,"squelch enabled");  break;
+            case LIQUID_AGC_SQUELCH_RISE:     sprintf(mode_str,"signal detected");  break;
+            case LIQUID_AGC_SQUELCH_SIGNALHI: sprintf(mode_str,"signal high");      break;
+            case LIQUID_AGC_SQUELCH_FALL:     sprintf(mode_str,"signal falling");   break;
+            case LIQUID_AGC_SQUELCH_SIGNALLO: sprintf(mode_str,"signal low");       break;
+            case LIQUID_AGC_SQUELCH_TIMEOUT:  sprintf(mode_str,"signal timed out"); break;
+            case LIQUID_AGC_SQUELCH_DISABLED: sprintf(mode_str,"squelch disabled"); break;
+            default:                          sprintf(mode_str,"(unknown)");        break;
+            }
+            printf("%4u : %18s (%1u), rssi = %8.2f dB\n", i, mode_str, mode[i], rssi[i]);
+        }
+    }
+
+    // destroy AGC object
+    agc_crcf_destroy(q);
+
+    // 
+    // export results
+    //
+    FILE* fid = fopen(OUTPUT_FILENAME,"w");
+    if (!fid) {
+        fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], OUTPUT_FILENAME);
+        exit(1);
+    }
+    fprintf(fid,"%% %s: auto-generated file\n\n",OUTPUT_FILENAME);
+    fprintf(fid,"clear all;\nclose all;\n\n");
+    fprintf(fid,"n = %u;\n", num_samples);
+
+    for (i=0; i<num_samples; i++) {
+        fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));
+        fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));
+        fprintf(fid,"rssi(%4u)  = %12.4e;\n", i+1, rssi[i]);
+        fprintf(fid,"mode(%4u)  = %d;\n", i+1, mode[i]);
+    }
+
+    // plot results
+    fprintf(fid,"\n");
+    fprintf(fid,"figure('position',[100 100 1200 900]);\n");
+    fprintf(fid,"t = 0:(n-1);\n");
+    fprintf(fid,"subplot(4,1,1);\n");
+    fprintf(fid,"  plot(t, real(x), '-', 'LineWidth',1.2, 'Color',[0 0.2 0.5],...\n");
+    fprintf(fid,"       t, imag(x), '-', 'LineWidth',1.2, 'Color',[0 0.5 0.2]);\n");
+    fprintf(fid,"  grid on;\n");
+    fprintf(fid,"  xlabel('sample index');\n");
+    fprintf(fid,"  ylabel('input');\n");
+    fprintf(fid,"  axis([0 %u -0.011 0.011]);\n", num_samples);
+    fprintf(fid,"subplot(4,1,2);\n");
+    fprintf(fid,"  plot(t, real(y), '-', 'LineWidth',1.2, 'Color',[0 0.2 0.5],...\n");
+    fprintf(fid,"       t, imag(y), '-', 'LineWidth',1.2, 'Color',[0 0.5 0.2]);\n");
+    fprintf(fid,"  grid on;\n");
+    fprintf(fid,"  xlabel('sample index');\n");
+    fprintf(fid,"  ylabel('output');\n");
+    fprintf(fid,"subplot(4,1,3);\n");
+    fprintf(fid,"  plot(t,rssi,'-','LineWidth',1.2,'Color',[0.5 0 0]);\n");
+    fprintf(fid,"  grid on;\n");
+    fprintf(fid,"  xlabel('sample index');\n");
+    fprintf(fid,"  ylabel('rssi [dB]');\n");
+    fprintf(fid,"subplot(4,1,4);\n");
+    fprintf(fid,"  plot(t,mode,'-s','LineWidth',1.2,'MarkerSize',4,'Color',[0.5 0 0]);\n");
+    fprintf(fid,"  grid on;\n");
+    fprintf(fid,"  xlabel('sample index');\n");
+    fprintf(fid,"  ylabel('squelch mode');\n");
+    fprintf(fid,"  axis([0 %u 0 8]);\n", num_samples);
+
+    fclose(fid);
+    printf("results written to %s\n", OUTPUT_FILENAME);
+
+    printf("done.\n");
+    return 0;
+}
+
diff --git a/examples/asgramcf_example.c b/examples/asgramcf_example.c
index 67fd505..3453937 100644
--- a/examples/asgramcf_example.c
+++ b/examples/asgramcf_example.c
@@ -33,8 +33,6 @@ int main() {
     float dphi   = 0.003f;  // frequency of sinusoidal frequency drift
 
     float complex x[nfft];
-    float maxval;
-    float maxfreq;
     char ascii[nfft+1];
     ascii[nfft] = '\0'; // append null character to end of string
     float nstd = powf(10.0f,noise_floor/20.0f);  // noise standard deviation
@@ -56,20 +54,8 @@ int main() {
         // write block of samples to the spectrogram object
         asgramcf_write(q, x, nfft);
 
-        // execute the spectrogram
-        asgramcf_execute(q, ascii, &maxval, &maxfreq);
-
-        // print the spectrogram to stdout
-        printf(" > %s < pk%5.1f dB [%5.2f]\n", ascii, maxval, maxfreq);
-
-        // optional: find peak and print arrow pointing to peak
-        int peak_index = (int)( (maxfreq+0.5) * nfft );
-        peak_index = peak_index < 0      ? 0      : peak_index;
-        peak_index = peak_index > nfft-1 ? nfft-1 : peak_index;
-        memset(ascii, ' ', nfft);   // clear ascii array with spaces
-        ascii[peak_index] = '^';    // set peak index to caret character
-        printf(" > %s < peak location\r", ascii);
-        fflush(stdout);
+        // print result to screen
+        asgramcf_print(q);
 
         // sleep for some time before generating the next frame
         usleep(msdelay*1000);
diff --git a/examples/firdespm_callback_example.c b/examples/firdespm_callback_example.c
new file mode 100644
index 0000000..595f894
--- /dev/null
+++ b/examples/firdespm_callback_example.c
@@ -0,0 +1,95 @@
+//
+// firdespm_callback_example.c
+//
+// This example demonstrates finite impulse response filter design
+// using the Parks-McClellan algorithm with callback function for
+// arbitrary response and weighting function.
+//
+// SEE ALSO: firdes_kaiser_example.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "liquid.h"
+
+#define OUTPUT_FILENAME "firdespm_callback_example.m"
+
+// user-defined callback function defining response and weights
+int callback(double   _frequency,
+             void   * _userdata,
+             double * _desired,
+             double * _weight)
+{
+    // de-reference pointer as floating-point value
+    unsigned int n  = *((unsigned int*)_userdata);
+    double       v  = sincf(n*_frequency);
+    double       fc = 1.0f / (float)n;
+
+    // inverse sinc
+    if (_frequency < fc) {
+        *_desired = 1.0f / v;   // inverse of sinc
+        *_weight  = 4.0f;
+    } else {
+        *_desired = 0.0f;       // stop-band
+        *_weight  = 10*fabs(v) * exp(4.0*_frequency);
+    }
+    return 0;
+}
+
+int main(int argc, char*argv[])
+{
+    // filter design parameters
+    unsigned int n     =  8;    // sinc filter length
+    unsigned int h_len = 81;    // inverse sinc filter length
+    liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS;
+    unsigned int num_bands = 2;
+    float        bands[4]  = {0.00f, 0.75f/(float)n, // pass-band
+                              1.05f/(float)n, 0.5f}; // stop-band
+
+    // design filter
+    float h[h_len];
+    firdespm q = firdespm_create_callback(h_len,num_bands,bands,btype,callback,&n);
+    firdespm_execute(q,h);
+    firdespm_destroy(q);
+
+    // print coefficients
+    unsigned int i;
+    for (i=0; i<h_len; i++)
+        printf("h(%4u) = %16.12f;\n", i+1, h[i]);
+
+    // open output file
+    FILE*fid = fopen(OUTPUT_FILENAME,"w");
+    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
+    fprintf(fid,"clear all;\n");
+    fprintf(fid,"close all;\n\n");
+    fprintf(fid,"n=%u;\n", n);
+    fprintf(fid,"h_len=%u;\n", h_len);
+
+    for (i=0; i<h_len; i++)
+        fprintf(fid,"h(%4u) = %20.8e;\n", i+1, h[i]);
+
+    fprintf(fid,"nfft=1024;\n");
+    fprintf(fid,"H0=20*log10(abs(fftshift(fft(ones(1,n)/n,nfft))));\n");
+    fprintf(fid,"H1=20*log10(abs(fftshift(fft(h,          nfft))));\n");
+    fprintf(fid,"Hc=H0+H1;\n");
+    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
+    fprintf(fid,"figure;\n");
+    fprintf(fid,"hold on;\n");
+    fprintf(fid,"plot(f,H0,'Color',[0.5 0.5 0.5],'LineWidth',1);\n");
+    fprintf(fid,"plot(f,H1,'Color',[0.0 0.2 0.5],'LineWidth',1);\n");
+    fprintf(fid,"plot(f,Hc,'Color',[0.0 0.5 0.2],'LineWidth',2);\n");
+    fprintf(fid,"hold off;\n");
+    fprintf(fid,"grid on;\n");
+    fprintf(fid,"xlabel('normalized frequency');\n");
+    fprintf(fid,"ylabel('PSD [dB]');\n");
+    fprintf(fid,"legend('sinc','inverse sinc','composite');\n");
+    fprintf(fid,"title('Filter design (firdespm), inverse sinc');\n");
+    fprintf(fid,"axis([-0.5 0.5 -80 20]);\n");
+
+    fclose(fid);
+    printf("results written to %s.\n", OUTPUT_FILENAME);
+
+    printf("done.\n");
+    return 0;
+}
+
diff --git a/examples/firdespm_example.c b/examples/firdespm_example.c
index 1def3e8..9e9e2c5 100644
--- a/examples/firdespm_example.c
+++ b/examples/firdespm_example.c
@@ -3,76 +3,37 @@
 //
 // This example demonstrates finite impulse response filter design
 // using the Parks-McClellan algorithm.
-// SEE ALSO: firdes_kaiser_example.c
 //
+// SEE ALSO: firdes_kaiser_example.c
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <math.h>
-
 #include "liquid.h"
 
 #define OUTPUT_FILENAME "firdespm_example.m"
 
-// print usage/help message
-void usage()
+int main(int argc, char*argv[])
 {
-    printf("firdespm_example:\n");
-    printf("  u/h   : print usage/help\n");
-    printf("  f     : filter cutoff frequency,       0 < f < 0.5, default: 0.2\n");
-    printf("  t     : filter transition bandwidth,   0 < t < 0.5, default: 0.1\n");
-    printf("  s     : stop-band attenuation [dB],    0 < s,       default: 60\n");
-}
-
-int main(int argc, char*argv[]) {
-    // options
-    float fc=0.2f;          // filter cutoff frequency
-    float ft=0.1f;          // filter transition
-    float As=60.0f;         // stop-band attenuation [dB]
-
-    int dopt;
-    while ((dopt = getopt(argc,argv,"uhf:t:s:")) != EOF) {
-        switch (dopt) {
-        case 'u':
-        case 'h': usage();                      return 0;
-        case 'f': fc = atof(optarg);            break;
-        case 't': ft = atof(optarg);            break;
-        case 's': As = atof(optarg);            break;
-        default:
-            exit(1);
-        }
-    }
-    printf("filter design parameters\n");
-    printf("    cutoff frequency            :   %12.8f\n", fc);
-    printf("    transition bandwidth        :   %12.8f\n", ft);
-    printf("    stop-band attenuation [dB]  :   %12.8f\n", As);
-
-    // derived values
-    unsigned int h_len = estimate_req_filter_len(ft,As);
-    printf("h_len : %u\n", h_len);
-    float fp = fc - 0.5*ft;     // pass-band cutoff frequency
-    float fs = fc + 0.5*ft;     // stop-band cutoff frequency
+    // filter design parameters
+    unsigned int h_len = 91;
     liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS;
-
-    // derived values
-    unsigned int num_bands = 2;
-    float bands[4]   = {0.0f, fp, fs, 0.5f};
-    float des[2]     = {1.0f, 0.0f};
-    float weights[2] = {1.0f, 1.0f};
-    liquid_firdespm_wtype wtype[2] = {LIQUID_FIRDESPM_FLATWEIGHT,
+    unsigned int num_bands = 4;
+    float bands[8]   = {0.00f, 0.10f,
+                        0.12f, 0.18f,
+                        0.20f, 0.30f,
+                        0.31f, 0.50f};
+
+    float des[4]     = {1.0f, 0.0f, 0.1f, 0.0f};
+    float weights[4] = {1.0f, 4.0f, 8.0f, 4.0f};
+    liquid_firdespm_wtype wtype[4] = {LIQUID_FIRDESPM_FLATWEIGHT,
+                                      LIQUID_FIRDESPM_FLATWEIGHT,
+                                      LIQUID_FIRDESPM_FLATWEIGHT,
                                       LIQUID_FIRDESPM_EXPWEIGHT};
 
     unsigned int i;
     float h[h_len];
-#if 0
-    firdespm q = firdespm_create(n,num_bands,bands,des,weights,wtype,btype);
-    firdespm_print(q);
-    firdespm_execute(q,h);
-    firdespm_destroy(q);
-#else
     firdespm_run(h_len,num_bands,bands,des,weights,wtype,btype,h);
-#endif
 
     // print coefficients
     for (i=0; i<h_len; i++)
@@ -84,8 +45,6 @@ int main(int argc, char*argv[]) {
     fprintf(fid,"clear all;\n");
     fprintf(fid,"close all;\n\n");
     fprintf(fid,"h_len=%u;\n", h_len);
-    fprintf(fid,"fc=%12.4e;\n",fc);
-    fprintf(fid,"As=%12.4e;\n",As);
 
     for (i=0; i<h_len; i++)
         fprintf(fid,"h(%4u) = %20.8e;\n", i+1, h[i]);
@@ -97,9 +56,8 @@ int main(int argc, char*argv[]) {
     fprintf(fid,"grid on;\n");
     fprintf(fid,"xlabel('normalized frequency');\n");
     fprintf(fid,"ylabel('PSD [dB]');\n");
-    fprintf(fid,"title(['Filter design/Kaiser window f_c: %f, S_L: %f, h: %u']);\n",
-            fc, -As, h_len);
-    fprintf(fid,"axis([-0.5 0.5 -As-40 10]);\n");
+    fprintf(fid,"title('Filter design (firdespm)');\n");
+    fprintf(fid,"axis([-0.5 0.5 -60 5]);\n");
 
     fclose(fid);
     printf("results written to %s.\n", OUTPUT_FILENAME);
diff --git a/examples/firdespm_lowpass_example.c b/examples/firdespm_lowpass_example.c
new file mode 100644
index 0000000..ce0e355
--- /dev/null
+++ b/examples/firdespm_lowpass_example.c
@@ -0,0 +1,89 @@
+//
+// firdespm_lowpass_example.c
+//
+// This example demonstrates a low-pass finite impulse response filter
+// design using the Parks-McClellan algorithm.
+//
+// SEE ALSO: firdes_kaiser_example.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <math.h>
+
+#include "liquid.h"
+
+#define OUTPUT_FILENAME "firdespm_lowpass_example.m"
+
+// print usage/help message
+void usage()
+{
+    printf("firdespm_lowpass_example:\n");
+    printf("  -h        : print usage/help\n");
+    printf("  -n <len>  : filter length,              1 < n        default: 57\n");
+    printf("  -f <freq> : filter cutoff frequency,    0 < f < 0.5, default: 0.2\n");
+    printf("  -s <atten>: stop-band attenuation [dB], 0 < s,       default: 60\n");
+}
+
+int main(int argc, char*argv[]) {
+    // options
+    unsigned int n  =  57;      // filter cutoff frequency
+    float        fc = 0.2f;     // filter cutoff frequency
+    float        As = 60.0f;    // stop-band attenuation [dB]
+
+    int dopt;
+    while ((dopt = getopt(argc,argv,"hn:f:s:")) != EOF) {
+        switch (dopt) {
+        case 'h': usage();           return 0;
+        case 'n': n  = atoi(optarg); break;
+        case 'f': fc = atof(optarg); break;
+        case 's': As = atof(optarg); break;
+        default: return -1;
+        }
+    }
+    unsigned int i;
+    printf("filter design parameters\n");
+    printf("  length                : %12u\n",      n);
+    printf("  cutoff frequency      : %12.8f Fs\n", fc);
+    printf("  stop-band attenuation : %12.3f dB\n", As);
+
+    // design the filter
+    float h[n];
+    firdespm_lowpass(n,fc,As,0,h);
+
+#if 0
+    // print coefficients
+    for (i=0; i<n; i++)
+        printf("h(%4u) = %16.12f;\n", i+1, h[i]);
+#endif
+
+    // open output file
+    FILE*fid = fopen(OUTPUT_FILENAME,"w");
+    fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
+    fprintf(fid,"clear all;\n");
+    fprintf(fid,"close all;\n\n");
+    fprintf(fid,"h_len=%u;\n", n);
+    fprintf(fid,"fc=%12.4e;\n",fc);
+    fprintf(fid,"As=%12.4e;\n",As);
+
+    for (i=0; i<n; i++)
+        fprintf(fid,"h(%4u) = %20.8e;\n", i+1, h[i]);
+
+    fprintf(fid,"nfft=1024;\n");
+    fprintf(fid,"H=20*log10(abs(fftshift(fft(h,nfft))));\n");
+    fprintf(fid,"f=[0:(nfft-1)]/nfft-0.5;\n");
+    fprintf(fid,"figure; plot(f,H,'Color',[0 0.5 0.25],'LineWidth',2);\n");
+    fprintf(fid,"grid on;\n");
+    fprintf(fid,"xlabel('normalized frequency');\n");
+    fprintf(fid,"ylabel('PSD [dB]');\n");
+    fprintf(fid,"title(['Filter design (firdespm) f_c: %.3f, S_L: %.3f, h: %u']);\n",
+            fc, -As, n);
+    fprintf(fid,"axis([-0.5 0.5 -As-20 10]);\n");
+
+    fclose(fid);
+    printf("results written to %s.\n", OUTPUT_FILENAME);
+
+    printf("done.\n");
+    return 0;
+}
+
diff --git a/examples/spgramcf_waterfall_example.c b/examples/spgramcf_waterfall_example.c
index 62e25b2..e4049e1 100644
--- a/examples/spgramcf_waterfall_example.c
+++ b/examples/spgramcf_waterfall_example.c
@@ -83,7 +83,7 @@ int main()
             fwrite(psd, sizeof(float), nfft, fid);
 
             // soft reset of internal state, counters
-            spgramcf_reset(periodogram);
+            spgramcf_clear(periodogram);
 
             // update counter for total number of PSD estimates taken
             total_estimates++;
diff --git a/examples/spwaterfallcf_example.c b/examples/spwaterfallcf_example.c
new file mode 100644
index 0000000..036c0ad
--- /dev/null
+++ b/examples/spwaterfallcf_example.c
@@ -0,0 +1,78 @@
+// waterfall example
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "liquid.h"
+
+#define OUTPUT_FILENAME "spwaterfallcf_waterfall_example.gnu"
+
+int main()
+{
+    // spectral periodogram options
+    unsigned int nfft        = 1200;    // spectral periodogram FFT size
+    unsigned int time        =  250;    // minimum time buffer
+    unsigned int num_samples = 20e6;    // number of samples
+
+    // create time-varying multi-path channel object
+    unsigned int buf_len = 64;
+    float complex buf[buf_len];
+
+    // create spectral periodogram
+    spwaterfallcf periodogram = spwaterfallcf_create_default(nfft,time);
+    spwaterfallcf_print(periodogram);
+
+    // create stream generator
+    msourcecf gen = msourcecf_create();
+    
+    // add noise source (narrow-band)
+    int id_noise = msourcecf_add_noise(gen, 0.10f);
+    msourcecf_set_frequency(gen, id_noise, 0.4*2*M_PI);
+    msourcecf_set_gain     (gen, id_noise, -20.0f);
+
+    // add tone
+    int id_tone = msourcecf_add_tone(gen);
+    msourcecf_set_frequency(gen, id_tone, -0.4*2*M_PI);
+    msourcecf_set_gain     (gen, id_tone, -10.0f);
+
+    // add modulated data
+    int id_modem = msourcecf_add_modem(gen,LIQUID_MODEM_QPSK,4,12,0.30f);
+    msourcecf_set_frequency(gen, id_modem, -0.1*2*M_PI);
+    msourcecf_set_gain     (gen, id_modem, 0.0f);
+
+    unsigned int total_samples   = 0;
+    int state = 1;
+    while (total_samples < num_samples) {
+        // write samples to buffer
+        msourcecf_write_samples(gen, buf, buf_len);
+
+        // push resulting sample through periodogram
+        spwaterfallcf_write(periodogram, buf, buf_len);
+
+        // accumulated samples
+        total_samples += buf_len;
+
+        // update state for noise source
+        if (state == 0 && randf() < 1e-4f) {
+            state = 1;
+            msourcecf_enable(gen, id_noise);
+            //printf("turning noise on\n");
+        } else if (state == 1 && randf() < 3e-4f) {
+            state = 0;
+            msourcecf_disable(gen, id_noise);
+            //printf("turning noise off\n");
+        }
+    }
+    // export output files
+    spwaterfallcf_export(periodogram,"spwaterfallcf_example");
+
+    // destroy objects
+    msourcecf_destroy(gen);
+    spwaterfallcf_destroy(periodogram);
+
+    printf("done.\n");
+    return 0;
+}
+
+
diff --git a/examples/symtrack_cccf_example.c b/examples/symtrack_cccf_example.c
index bedc504..7f8257c 100644
--- a/examples/symtrack_cccf_example.c
+++ b/examples/symtrack_cccf_example.c
@@ -32,14 +32,13 @@ void usage()
     printf("  s     : signal-to-noise ratio,   default: 30 dB\n");
     printf("  w     : timing pll bandwidth,    default: 0.02\n");
     printf("  n     : number of symbols,       default: 4000\n");
-    printf("  t     : timing phase offset [%% symbol], t in [-0.5,0.5], default: -0.2\n");
 }
 
 int main(int argc, char*argv[])
 {
     // options
     int          ftype       = LIQUID_FIRFILT_ARKAISER;
-    int          ms          = LIQUID_MODEM_QPSK;
+    int          ms          = LIQUID_MODEM_QAM16;
     unsigned int k           = 2;       // samples per symbol
     unsigned int m           = 7;       // filter delay (symbols)
     float        beta        = 0.20f;   // filter excess bandwidth factor
@@ -47,17 +46,15 @@ int main(int argc, char*argv[])
     unsigned int hc_len      =   4;     // channel filter length
     float        noise_floor = -60.0f;  // noise floor [dB]
     float        SNRdB       = 30.0f;   // signal-to-noise ratio [dB]
-    float        bandwidth   =  0.02f;  // loop filter bandwidth
-    float        tau         = -0.2f;   // fractional symbol offset
-    float        rate        = 1.001f;  // sample rate offset
-    float        dphi        =  0.01f;  // carrier frequency offset [radians/sample]
+    float        bandwidth   =  0.10f;  // loop filter bandwidth
+    float        dphi        =  0.02f;  // carrier frequency offset [radians/sample]
     float        phi         =  2.1f;   // carrier phase offset [radians]
 
     unsigned int nfft        =   2400;  // spectral periodogram FFT size
     unsigned int num_samples = 200000;  // number of samples
 
     int dopt;
-    while ((dopt = getopt(argc,argv,"hk:m:b:s:w:n:t:r:")) != EOF) {
+    while ((dopt = getopt(argc,argv,"hk:m:b:s:w:n:")) != EOF) {
         switch (dopt) {
         case 'h':   usage();                        return 0;
         case 'k':   k           = atoi(optarg);     break;
@@ -66,8 +63,6 @@ int main(int argc, char*argv[])
         case 's':   SNRdB       = atof(optarg);     break;
         case 'w':   bandwidth   = atof(optarg);     break;
         case 'n':   num_symbols = atoi(optarg);     break;
-        case 't':   tau         = atof(optarg);     break;
-        case 'r':   rate        = atof(optarg);     break;
         default:
             exit(1);
         }
@@ -89,18 +84,12 @@ int main(int argc, char*argv[])
     } else if (num_symbols == 0) {
         fprintf(stderr,"error: number of symbols must be greater than 0\n");
         exit(1);
-    } else if (tau < -1.0f || tau > 1.0f) {
-        fprintf(stderr,"error: timing phase offset must be in [-1,1]\n");
-        exit(1);
-    } else if (rate > 1.02f || rate < 0.98f) {
-        fprintf(stderr,"error: timing rate offset must be in [1.02,0.98]\n");
-        exit(1);
     }
 
     unsigned int i;
 
     // buffers
-    unsigned int    buf_len = 400;      // buffer size
+    unsigned int    buf_len = 800;      // buffer size
     float complex   x   [buf_len];      // original signal
     float complex   y   [buf_len];      // channel output
     float complex   syms[buf_len];      // recovered symbols
@@ -118,7 +107,7 @@ int main(int argc, char*argv[])
 
     // create symbol tracking synchronizer
     symtrack_cccf symtrack = symtrack_cccf_create(ftype,k,m,beta,ms);
-    symtrack_cccf_set_bandwidth(symtrack,0.05f);
+    symtrack_cccf_set_bandwidth(symtrack,bandwidth);
 
     // create spectral periodogram for estimating spectrum
     spgramcf periodogram = spgramcf_create_default(nfft);
diff --git a/include/liquid.h b/include/liquid.h
index db36819..6e19b93 100644
--- a/include/liquid.h
+++ b/include/liquid.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2016 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -49,8 +49,8 @@ extern "C" {
 // LIQUID_VERSION = "X.Y.Z"
 // LIQUID_VERSION_NUMBER = (X*1000000 + Y*1000 + Z)
 //
-#define LIQUID_VERSION          "1.2.0"
-#define LIQUID_VERSION_NUMBER   1002000
+#define LIQUID_VERSION          "1.3.0"
+#define LIQUID_VERSION_NUMBER   1003000
 
 //
 // Run-time library version numbers
@@ -94,8 +94,20 @@ LIQUID_DEFINE_COMPLEX(double, liquid_double_complex);
 // MODULE : agc (automatic gain control)
 //
 
-#define AGC_MANGLE_CRCF(name)   LIQUID_CONCAT(agc_crcf, name)
-#define AGC_MANGLE_RRRF(name)   LIQUID_CONCAT(agc_rrrf, name)
+// available squelch modes
+typedef enum {
+    LIQUID_AGC_SQUELCH_UNKNOWN=0,   // unknown/unavailable squelch mode
+    LIQUID_AGC_SQUELCH_ENABLED,     // squelch enabled but signal not detected
+    LIQUID_AGC_SQUELCH_RISE,        // signal first hit/exceeded threshold
+    LIQUID_AGC_SQUELCH_SIGNALHI,    // signal level high (above threshold)
+    LIQUID_AGC_SQUELCH_FALL,        // signal first dropped below threshold
+    LIQUID_AGC_SQUELCH_SIGNALLO,    // signal level low (below threshold)
+    LIQUID_AGC_SQUELCH_TIMEOUT,     // signal level low (below threshold for a certain time)
+    LIQUID_AGC_SQUELCH_DISABLED,    // squelch not enabled
+} agc_squelch_mode;
+
+#define LIQUID_AGC_MANGLE_CRCF(name) LIQUID_CONCAT(agc_crcf, name)
+#define LIQUID_AGC_MANGLE_RRRF(name) LIQUID_CONCAT(agc_rrrf, name)
 
 // large macro
 //   AGC    : name-mangling macro
@@ -161,10 +173,40 @@ void  AGC(_set_gain)(AGC() _q, float _gain);                    \
 void AGC(_init)(AGC()        _q,                                \
                 TC *         _x,                                \
                 unsigned int _n);                               \
+                                                                \
+/* enable squelch mode                                      */  \
+void AGC(_squelch_enable)(AGC() _q);                            \
+                                                                \
+/* disable squelch mode                                     */  \
+void AGC(_squelch_disable)(AGC() _q);                           \
+                                                                \
+/* is squelch enabled?                                      */  \
+int  AGC(_squelch_is_enabled)(AGC() _q);                        \
+                                                                \
+/* set squelch threshold                                    */  \
+/*  _q          :   automatic gain control object           */  \
+/*  _thresh_dB  :   threshold for enabling squelch [dB]     */  \
+void AGC(_squelch_set_threshold)(AGC() _q,                      \
+                                 T     _threshold);             \
+                                                                \
+/* get squelch threshold [dB]                               */  \
+T    AGC(_squelch_get_threshold)(AGC() _q);                     \
+                                                                \
+/* set squelch timeout                                      */  \
+/*  _q       : automatic gain control object                */  \
+/*  _timeout : timeout before enabling squelch [samples]    */  \
+void AGC(_squelch_set_timeout)(AGC()        _q,                 \
+                               unsigned int _timeout);          \
+                                                                \
+/* get squelch timeout [samples]                            */  \
+unsigned int AGC(_squelch_get_timeout)(AGC() _q);               \
+                                                                \
+/* get squelch status                                       */  \
+int AGC(_squelch_get_status)(AGC() _q);                         \
 
 // Define agc APIs
-LIQUID_AGC_DEFINE_API(AGC_MANGLE_CRCF, float, liquid_float_complex)
-LIQUID_AGC_DEFINE_API(AGC_MANGLE_RRRF, float, float)
+LIQUID_AGC_DEFINE_API(LIQUID_AGC_MANGLE_CRCF, float, liquid_float_complex)
+LIQUID_AGC_DEFINE_API(LIQUID_AGC_MANGLE_RRRF, float, float)
 
 
 
@@ -204,8 +246,8 @@ void cvsd_decode8(cvsd _q, unsigned char _data, float * _audio);
 //
 
 // circular buffer
-#define CBUFFER_MANGLE_FLOAT(name)  LIQUID_CONCAT(cbufferf,  name)
-#define CBUFFER_MANGLE_CFLOAT(name) LIQUID_CONCAT(cbuffercf, name)
+#define LIQUID_CBUFFER_MANGLE_FLOAT(name)  LIQUID_CONCAT(cbufferf,  name)
+#define LIQUID_CBUFFER_MANGLE_CFLOAT(name) LIQUID_CONCAT(cbuffercf, name)
 
 // large macro
 //   CBUFFER : name-mangling macro
@@ -214,11 +256,14 @@ void cvsd_decode8(cvsd _q, unsigned char _data, float * _audio);
 typedef struct CBUFFER(_s) * CBUFFER();                         \
                                                                 \
 /* create circular buffer object of a particular size       */  \
+/*  _max_size  : maximum buffer size, _max_size > 0         */  \
 CBUFFER() CBUFFER(_create)(unsigned int _max_size);             \
                                                                 \
 /* create circular buffer object of a particular size and   */  \
 /* specify the maximum number of elements that can be read  */  \
 /* at any given time.                                       */  \
+/*  _max_size  : maximum buffer size, _max_size > 0         */  \
+/*  _max_read  : maximum size that will be read from buffer */  \
 CBUFFER() CBUFFER(_create_max)(unsigned int _max_size,          \
                                unsigned int _max_read);         \
                                                                 \
@@ -273,25 +318,27 @@ void CBUFFER(_pop)(CBUFFER() _q,                                \
 /*  _q              : circular buffer object                */  \
 /*  _num_requested  : number of elements requested          */  \
 /*  _v              : output pointer                        */  \
-/*  _nr             : number of elements referenced by _v   */  \
+/*  _num_read       : number of elements referenced by _v   */  \
 void CBUFFER(_read)(CBUFFER()      _q,                          \
                     unsigned int   _num_requested,              \
                     T **           _v,                          \
                     unsigned int * _num_read);                  \
                                                                 \
 /* release _n samples from the buffer                       */  \
+/*  _q : circular buffer object                             */  \
+/*  _n : number of elements to release                      */  \
 void CBUFFER(_release)(CBUFFER()    _q,                         \
                        unsigned int _n);                        \
 
 // Define buffer APIs
-LIQUID_CBUFFER_DEFINE_API(CBUFFER_MANGLE_FLOAT,  float)
-LIQUID_CBUFFER_DEFINE_API(CBUFFER_MANGLE_CFLOAT, liquid_float_complex)
+LIQUID_CBUFFER_DEFINE_API(LIQUID_CBUFFER_MANGLE_FLOAT,  float)
+LIQUID_CBUFFER_DEFINE_API(LIQUID_CBUFFER_MANGLE_CFLOAT, liquid_float_complex)
 
 
 
 // Windowing functions
-#define WINDOW_MANGLE_FLOAT(name)  LIQUID_CONCAT(windowf,  name)
-#define WINDOW_MANGLE_CFLOAT(name) LIQUID_CONCAT(windowcf, name)
+#define LIQUID_WINDOW_MANGLE_FLOAT(name)  LIQUID_CONCAT(windowf,  name)
+#define LIQUID_WINDOW_MANGLE_CFLOAT(name) LIQUID_CONCAT(windowcf, name)
 
 // large macro
 //   WINDOW : name-mangling macro
@@ -348,16 +395,16 @@ void WINDOW(_write)(WINDOW()     _q,                            \
                     unsigned int _n);                           \
 
 // Define window APIs
-LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_FLOAT,  float)
-LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_CFLOAT, liquid_float_complex)
-//LIQUID_WINDOW_DEFINE_API(WINDOW_MANGLE_UINT,   unsigned int)
+LIQUID_WINDOW_DEFINE_API(LIQUID_WINDOW_MANGLE_FLOAT,  float)
+LIQUID_WINDOW_DEFINE_API(LIQUID_WINDOW_MANGLE_CFLOAT, liquid_float_complex)
+//LIQUID_WINDOW_DEFINE_API(LIQUID_WINDOW_MANGLE_UINT,   unsigned int)
 
 
 // wdelay functions : windowed-delay
 // Implements an efficient z^-k delay with minimal memory
-#define WDELAY_MANGLE_FLOAT(name)   LIQUID_CONCAT(wdelayf,  name)
-#define WDELAY_MANGLE_CFLOAT(name)  LIQUID_CONCAT(wdelaycf, name)
-#define WDELAY_MANGLE_UINT(name)    LIQUID_CONCAT(wdelayui, name)
+#define LIQUID_WDELAY_MANGLE_FLOAT(name)  LIQUID_CONCAT(wdelayf,  name)
+#define LIQUID_WDELAY_MANGLE_CFLOAT(name) LIQUID_CONCAT(wdelaycf, name)
+//#define LIQUID_WDELAY_MANGLE_UINT(name)   LIQUID_CONCAT(wdelayui, name)
 
 // large macro
 //   WDELAY : name-mangling macro
@@ -396,9 +443,9 @@ void WDELAY(_push)(WDELAY() _q,                                 \
                    T        _v);                                \
 
 // Define wdelay APIs
-LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_FLOAT,  float)
-LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_CFLOAT, liquid_float_complex)
-//LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_UINT,   unsigned int)
+LIQUID_WDELAY_DEFINE_API(LIQUID_WDELAY_MANGLE_FLOAT,  float)
+LIQUID_WDELAY_DEFINE_API(LIQUID_WDELAY_MANGLE_CFLOAT, liquid_float_complex)
+//LIQUID_WDELAY_DEFINE_API(LIQUID_WDELAY_MANGLE_UINT,   unsigned int)
 
 
 
@@ -406,7 +453,7 @@ LIQUID_WDELAY_DEFINE_API(WDELAY_MANGLE_CFLOAT, liquid_float_complex)
 // MODULE : channel
 //
 
-#define CHANNEL_MANGLE_CCCF(name)   LIQUID_CONCAT(channel_cccf,name)
+#define LIQUID_CHANNEL_MANGLE_CCCF(name) LIQUID_CONCAT(channel_cccf,name)
 
 // large macro
 //   CHANNEL    : name-mangling macro
@@ -427,16 +474,16 @@ void CHANNEL(_destroy)(CHANNEL() _q);                           \
 void CHANNEL(_print)(CHANNEL() _q);                             \
                                                                 \
 /* apply additive white Gausss noise impairment             */  \
-/*  _q              : channel object                        */  \
-/*  _noise_floor_dB : noise floor power spectral density    */  \
-/*  _SNR_dB         : signal-to-noise ratio [dB]            */  \
+/*  _q          : channel object                            */  \
+/*  _N0dB       : noise floor power spectral density [dB]   */  \
+/*  _SNRdB      : signal-to-noise ratio [dB]                */  \
 void CHANNEL(_add_awgn)(CHANNEL() _q,                           \
-                        float     _noise_floor_dB,              \
+                        float     _N0dB,                        \
                         float     _SNRdB);                      \
                                                                 \
 /* apply carrier offset impairment                          */  \
 /*  _q          : channel object                            */  \
-/*  _frequency  : carrier frequency offse [radians/sample   */  \
+/*  _frequency  : carrier frequency offset [radians/sample] */  \
 /*  _phase      : carrier phase offset    [radians]         */  \
 void CHANNEL(_add_carrier_offset)(CHANNEL() _q,                 \
                                   float     _frequency,         \
@@ -468,15 +515,15 @@ void CHANNEL(_execute)(CHANNEL()      _q,                       \
                                                                 \
 /* apply channel impairments on block of samples            */  \
 /*  _q      : channel object                                */  \
-/*  _x      : input array [size: _n x 1]                    */  \
-/*  _n      : input array length                            */  \
-/*  _y      : output array [size: _n x 1]                   */  \
+/*  _x      : input array, [size: _n x 1]                   */  \
+/*  _n      : input array, length                           */  \
+/*  _y      : output array, [size: _n x 1]                  */  \
 void CHANNEL(_execute_block)(CHANNEL()      _q,                 \
                              TI *           _x,                 \
                              unsigned int   _n,                 \
                              TO *           _y);                \
 
-LIQUID_CHANNEL_DEFINE_API(CHANNEL_MANGLE_CCCF,
+LIQUID_CHANNEL_DEFINE_API(LIQUID_CHANNEL_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
@@ -485,7 +532,7 @@ LIQUID_CHANNEL_DEFINE_API(CHANNEL_MANGLE_CCCF,
 //
 // time-varying multi-path channel
 //
-#define TVMPCH_MANGLE_CCCF(name)    LIQUID_CONCAT(tvmpch_cccf,name)
+#define LIQUID_TVMPCH_MANGLE_CCCF(name) LIQUID_CONCAT(tvmpch_cccf,name)
 
 // large macro
 //   TVMPCH    : name-mangling macro
@@ -536,7 +583,7 @@ void TVMPCH(_execute_block)(TVMPCH()     _q,                    \
                             unsigned int _nx,                   \
                             TO *         _y);                   \
 
-LIQUID_TVMPCH_DEFINE_API(TVMPCH_MANGLE_CCCF,
+LIQUID_TVMPCH_DEFINE_API(LIQUID_TVMPCH_MANGLE_CCCF,
                          liquid_float_complex,
                          liquid_float_complex,
                          liquid_float_complex)
@@ -546,9 +593,9 @@ LIQUID_TVMPCH_DEFINE_API(TVMPCH_MANGLE_CCCF,
 // MODULE : dotprod (vector dot product)
 //
 
-#define DOTPROD_MANGLE_RRRF(name)   LIQUID_CONCAT(dotprod_rrrf,name)
-#define DOTPROD_MANGLE_CCCF(name)   LIQUID_CONCAT(dotprod_cccf,name)
-#define DOTPROD_MANGLE_CRCF(name)   LIQUID_CONCAT(dotprod_crcf,name)
+#define LIQUID_DOTPROD_MANGLE_RRRF(name) LIQUID_CONCAT(dotprod_rrrf,name)
+#define LIQUID_DOTPROD_MANGLE_CCCF(name) LIQUID_CONCAT(dotprod_cccf,name)
+#define LIQUID_DOTPROD_MANGLE_CRCF(name) LIQUID_CONCAT(dotprod_crcf,name)
 
 // large macro
 //   DOTPROD    : name-mangling macro
@@ -595,17 +642,17 @@ void DOTPROD(_execute)(DOTPROD() _q,                            \
                        TI *      _x,                            \
                        TO *      _y);                           \
 
-LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_RRRF,
+LIQUID_DOTPROD_DEFINE_API(LIQUID_DOTPROD_MANGLE_RRRF,
                           float,
                           float,
                           float)
 
-LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_CCCF,
+LIQUID_DOTPROD_DEFINE_API(LIQUID_DOTPROD_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
 
-LIQUID_DOTPROD_DEFINE_API(DOTPROD_MANGLE_CRCF,
+LIQUID_DOTPROD_DEFINE_API(LIQUID_DOTPROD_MANGLE_CRCF,
                           liquid_float_complex,
                           float,
                           liquid_float_complex)
@@ -626,8 +673,8 @@ float liquid_sumsqcf(liquid_float_complex * _v,
 //
 
 // least mean-squares (LMS)
-#define EQLMS_MANGLE_RRRF(name)     LIQUID_CONCAT(eqlms_rrrf,name)
-#define EQLMS_MANGLE_CCCF(name)     LIQUID_CONCAT(eqlms_cccf,name)
+#define LIQUID_EQLMS_MANGLE_RRRF(name) LIQUID_CONCAT(eqlms_rrrf,name)
+#define LIQUID_EQLMS_MANGLE_CCCF(name) LIQUID_CONCAT(eqlms_cccf,name)
 
 // large macro
 //   EQLMS  : name-mangling macro
@@ -745,13 +792,13 @@ void EQLMS(_train)(EQLMS()      _q,                             \
                    T *          _d,                             \
                    unsigned int _n);                            \
 
-LIQUID_EQLMS_DEFINE_API(EQLMS_MANGLE_RRRF, float);
-LIQUID_EQLMS_DEFINE_API(EQLMS_MANGLE_CCCF, liquid_float_complex);
+LIQUID_EQLMS_DEFINE_API(LIQUID_EQLMS_MANGLE_RRRF, float)
+LIQUID_EQLMS_DEFINE_API(LIQUID_EQLMS_MANGLE_CCCF, liquid_float_complex)
 
 
 // recursive least-squares (RLS)
-#define EQRLS_MANGLE_RRRF(name)     LIQUID_CONCAT(eqrls_rrrf,name)
-#define EQRLS_MANGLE_CCCF(name)     LIQUID_CONCAT(eqrls_cccf,name)
+#define LIQUID_EQRLS_MANGLE_RRRF(name) LIQUID_CONCAT(eqrls_rrrf,name)
+#define LIQUID_EQRLS_MANGLE_CCCF(name) LIQUID_CONCAT(eqrls_cccf,name)
 
 // large macro
 //   EQRLS  : name-mangling macro
@@ -817,10 +864,10 @@ void EQRLS(_train)(EQRLS()      _q,                             \
                    T *          _w,                             \
                    T *          _x,                             \
                    T *          _d,                             \
-                   unsigned int _n);
+                   unsigned int _n);                            \
 
-LIQUID_EQRLS_DEFINE_API(EQRLS_MANGLE_RRRF, float);
-LIQUID_EQRLS_DEFINE_API(EQRLS_MANGLE_CCCF, liquid_float_complex);
+LIQUID_EQRLS_DEFINE_API(LIQUID_EQRLS_MANGLE_RRRF, float)
+LIQUID_EQRLS_DEFINE_API(LIQUID_EQRLS_MANGLE_CCCF, liquid_float_complex)
 
 
 
@@ -1190,7 +1237,7 @@ typedef enum {
     LIQUID_FFT_IMDCT    =  31,  // IMDCT
 } liquid_fft_type;
 
-#define LIQUID_FFT_MANGLE_FLOAT(name)   LIQUID_CONCAT(fft,name)
+#define LIQUID_FFT_MANGLE_FLOAT(name) LIQUID_CONCAT(fft,name)
 
 // Macro    :   FFT
 //  FFT     :   name-mangling macro
@@ -1292,7 +1339,7 @@ typedef struct SPGRAM(_s) * SPGRAM();                           \
                                                                 \
 /* create spgram object                                     */  \
 /*  _nfft       : FFT size                                  */  \
-/*  _window     : window [size: _window_len x 1]            */  \
+/*  _wtype      : window type, e.g. LIQUID_WINDOW_HAMMING   */  \
 /*  _window_len : window length, _window_len in [1,_nfft]   */  \
 /*  _delay      : delay between transforms, _delay > 0      */  \
 SPGRAM() SPGRAM(_create)(unsigned int _nfft,                    \
@@ -1306,7 +1353,11 @@ SPGRAM() SPGRAM(_create_default)(unsigned int _nfft);           \
 /* destroy spgram object                                    */  \
 void SPGRAM(_destroy)(SPGRAM() _q);                             \
                                                                 \
-/* resets the internal state of the spgram object           */  \
+/* clears the internal state of the spgram object, but not  */  \
+/* the internal buffer                                      */  \
+void SPGRAM(_clear)(SPGRAM() _q);                               \
+                                                                \
+/* reset the spgram object to its original state completely */  \
 void SPGRAM(_reset)(SPGRAM() _q);                               \
                                                                 \
 /* print internal state of the spgram object                */  \
@@ -1401,11 +1452,17 @@ void ASGRAM(_reset)(ASGRAM() _q);                               \
                                                                 \
 /* set scale and offset for spectrogram                     */  \
 /*  _q      :   asgram object                               */  \
-/*  _offset :   signal offset level [dB]                    */  \
-/*  _scale  :   signal scale [dB]                           */  \
+/*  _ref    :   signal reference level [dB]                 */  \
+/*  _div    :   signal division [dB]                        */  \
 void ASGRAM(_set_scale)(ASGRAM() _q,                            \
-                        float    _offset,                       \
-                        float    _scale);                       \
+                        float    _ref,                          \
+                        float    _div);                         \
+                                                                \
+/* set display characters for output string                 */  \
+/*  _q      :   asgram object                               */  \
+/*  _ascii  :   10-character display, default: " .,-+*&NM#" */  \
+void ASGRAM(_set_display)(ASGRAM()     _q,                      \
+                          const char * _ascii);                 \
                                                                 \
 /* push a single sample into the asgram object              */  \
 /*  _q      :   asgram object                               */  \
@@ -1446,6 +1503,83 @@ LIQUID_ASGRAM_DEFINE_API(LIQUID_ASGRAM_MANGLE_FLOAT,
                          liquid_float_complex,
                          float)
 
+// 
+// spectral periodogram waterfall
+//
+
+#define LIQUID_SPWATERFALL_MANGLE_CFLOAT(name) LIQUID_CONCAT(spwaterfallcf,name)
+#define LIQUID_SPWATERFALL_MANGLE_FLOAT(name)  LIQUID_CONCAT(spwaterfallf, name)
+
+// Macro        :   SPWATERFALL
+//  SPWATERFALL :   name-mangling macro
+//  T           :   primitive data type
+//  TC          :   primitive data type (complex)
+//  TI          :   primitive data type (input)
+#define LIQUID_SPWATERFALL_DEFINE_API(SPWATERFALL,T,TC,TI)      \
+                                                                \
+typedef struct SPWATERFALL(_s) * SPWATERFALL();                 \
+                                                                \
+/* create spgram object                                     */  \
+/*  _nfft       : FFT size                                  */  \
+/*  _wtype      : window type, e.g. LIQUID_WINDOW_HAMMING   */  \
+/*  _window_len : window length, _window_len in [1,_nfft]   */  \
+/*  _delay      : delay between transforms, _delay > 0      */  \
+/*  _time       : number of aggregated transforms, _time > 0*/  \
+SPWATERFALL() SPWATERFALL(_create)(unsigned int _nfft,          \
+                                   int          _wtype,         \
+                                   unsigned int _window_len,    \
+                                   unsigned int _delay,         \
+                                   unsigned int _time);         \
+                                                                \
+/* create default spgram object (Kaiser-Bessel window)      */  \
+SPWATERFALL() SPWATERFALL(_create_default)(unsigned int _nfft,  \
+                                           unsigned int _time); \
+                                                                \
+/* destroy spgram object                                    */  \
+void SPWATERFALL(_destroy)(SPWATERFALL() _q);                   \
+                                                                \
+/* clears the internal state of the spgram object, but not  */  \
+/* the internal buffer                                      */  \
+void SPWATERFALL(_clear)(SPWATERFALL() _q);                     \
+                                                                \
+/* reset the spgram object to its original state completely */  \
+void SPWATERFALL(_reset)(SPWATERFALL() _q);                     \
+                                                                \
+/* print internal state of the spgram object                */  \
+void SPWATERFALL(_print)(SPWATERFALL() _q);                     \
+                                                                \
+/* push a single sample into the spgram object              */  \
+/*  _q      :   spgram object                               */  \
+/*  _x      :   input sample                                */  \
+void SPWATERFALL(_push)(SPWATERFALL() _q,                       \
+                        TI            _x);                      \
+                                                                \
+/* write a block of samples to the spgram object            */  \
+/*  _q      :   spgram object                               */  \
+/*  _x      :   input buffer [size: _n x 1]                 */  \
+/*  _n      :   input buffer length                         */  \
+void SPWATERFALL(_write)(SPWATERFALL() _q,                      \
+                         TI *          _x,                      \
+                         unsigned int  _n);                     \
+                                                                \
+/* export files for plotting                                */  \
+/*  _q             : spgram object                          */  \
+/*  _filename_base : base filename (will export files with  */  \
+/*                   .gnu, .bin, and .png extensions)       */  \
+int SPWATERFALL(_export)(SPWATERFALL() _q,                      \
+                         const char *  _filename_base);         \
+
+
+LIQUID_SPWATERFALL_DEFINE_API(LIQUID_SPWATERFALL_MANGLE_CFLOAT,
+                              float,
+                              liquid_float_complex,
+                              liquid_float_complex)
+
+LIQUID_SPWATERFALL_DEFINE_API(LIQUID_SPWATERFALL_MANGLE_FLOAT,
+                              float,
+                              liquid_float_complex,
+                              float)
+
 
 //
 // MODULE : filter
@@ -1546,14 +1680,36 @@ typedef enum {
 //  _wtype      :   weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
 //  _btype      :   band type (e.g. LIQUID_FIRDESPM_BANDPASS)
 //  _h          :   output coefficients array [size: _h_len x 1]
-void firdespm_run(unsigned int _h_len,
-                  unsigned int _num_bands,
-                  float * _bands,
-                  float * _des,
-                  float * _weights,
+void firdespm_run(unsigned int            _h_len,
+                  unsigned int            _num_bands,
+                  float *                 _bands,
+                  float *                 _des,
+                  float *                 _weights,
                   liquid_firdespm_wtype * _wtype,
-                  liquid_firdespm_btype _btype,
-                  float * _h);
+                  liquid_firdespm_btype   _btype,
+                  float *                 _h);
+
+// run filter design for basic low-pass filter
+//  _n      : filter length, _n > 0
+//  _fc     : cutoff frequency, 0 < _fc < 0.5
+//  _As     : stop-band attenuation [dB], _As > 0
+//  _mu     : fractional sample offset, -0.5 < _mu < 0.5 [ignored]
+//  _h      : output coefficient buffer, [size: _n x 1]
+void firdespm_lowpass(unsigned int _n,
+                      float        _fc,
+                      float        _As,
+                      float        _mu,
+                      float *      _h);
+
+// firdespm response callback function
+//  _frequency  : normalized frequency
+//  _userdata   : pointer to userdata
+//  _desired    : (return) desired response
+//  _weight     : (return) weight
+typedef int (*firdespm_callback)(double   _frequency,
+                                 void   * _userdata,
+                                 double * _desired,
+                                 double * _weight);
 
 // structured object
 typedef struct firdespm_s * firdespm;
@@ -1566,13 +1722,27 @@ typedef struct firdespm_s * firdespm;
 //  _weights    :   response weighting [size: _num_bands x 1]
 //  _wtype      :   weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
 //  _btype      :   band type (e.g. LIQUID_FIRDESPM_BANDPASS)
-firdespm firdespm_create(unsigned int _h_len,
-                         unsigned int _num_bands,
-                         float * _bands,
-                         float * _des,
-                         float * _weights,
+firdespm firdespm_create(unsigned int            _h_len,
+                         unsigned int            _num_bands,
+                         float *                 _bands,
+                         float *                 _des,
+                         float *                 _weights,
                          liquid_firdespm_wtype * _wtype,
-                         liquid_firdespm_btype _btype);
+                         liquid_firdespm_btype   _btype);
+
+// create firdespm object with user-defined callback
+//  _h_len      :   length of filter (number of taps)
+//  _num_bands  :   number of frequency bands
+//  _bands      :   band edges, f in [0,0.5], [size: _num_bands x 2]
+//  _btype      :   band type (e.g. LIQUID_FIRDESPM_BANDPASS)
+//  _callback   :   user-defined callback for specifying desired response & weights
+//  _userdata   :   user-defined data structure for callback function
+firdespm firdespm_create_callback(unsigned int          _h_len,
+                                  unsigned int          _num_bands,
+                                  float *               _bands,
+                                  liquid_firdespm_btype _btype,
+                                  firdespm_callback     _callback,
+                                  void *                _userdata);
 
 // destroy firdespm object
 void firdespm_destroy(firdespm _q);
@@ -1954,8 +2124,8 @@ void liquid_levinson(float * _r,
 // auto-correlator (delay cross-correlation)
 //
 
-#define AUTOCORR_MANGLE_CCCF(name)  LIQUID_CONCAT(autocorr_cccf,name)
-#define AUTOCORR_MANGLE_RRRF(name)  LIQUID_CONCAT(autocorr_rrrf,name)
+#define LIQUID_AUTOCORR_MANGLE_CCCF(name) LIQUID_CONCAT(autocorr_cccf,name)
+#define LIQUID_AUTOCORR_MANGLE_RRRF(name) LIQUID_CONCAT(autocorr_rrrf,name)
 
 // Macro:
 //   AUTOCORR   : name-mangling macro
@@ -2003,12 +2173,12 @@ void AUTOCORR(_execute_block)(AUTOCORR()   _q,                  \
 /* return sum of squares of buffered samples                */  \
 float AUTOCORR(_get_energy)(AUTOCORR() _q);                     \
 
-LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_CCCF,
+LIQUID_AUTOCORR_DEFINE_API(LIQUID_AUTOCORR_MANGLE_CCCF,
                            liquid_float_complex,
                            liquid_float_complex,
                            liquid_float_complex)
 
-LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_RRRF,
+LIQUID_AUTOCORR_DEFINE_API(LIQUID_AUTOCORR_MANGLE_RRRF,
                            float,
                            float,
                            float)
@@ -2018,9 +2188,9 @@ LIQUID_AUTOCORR_DEFINE_API(AUTOCORR_MANGLE_RRRF,
 // Finite impulse response filter
 //
 
-#define FIRFILT_MANGLE_RRRF(name)  LIQUID_CONCAT(firfilt_rrrf,name)
-#define FIRFILT_MANGLE_CRCF(name)  LIQUID_CONCAT(firfilt_crcf,name)
-#define FIRFILT_MANGLE_CCCF(name)  LIQUID_CONCAT(firfilt_cccf,name)
+#define LIQUID_FIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(firfilt_rrrf,name)
+#define LIQUID_FIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(firfilt_crcf,name)
+#define LIQUID_FIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(firfilt_cccf,name)
 
 // Macro:
 //   FIRFILT : name-mangling macro
@@ -2118,17 +2288,17 @@ void FIRFILT(_freqresponse)(FIRFILT()              _q,          \
 float FIRFILT(_groupdelay)(FIRFILT() _q,                        \
                            float     _fc);                      \
 
-LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_RRRF,
+LIQUID_FIRFILT_DEFINE_API(LIQUID_FIRFILT_MANGLE_RRRF,
                           float,
                           float,
                           float)
 
-LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CRCF,
+LIQUID_FIRFILT_DEFINE_API(LIQUID_FIRFILT_MANGLE_CRCF,
                           liquid_float_complex,
                           float,
                           liquid_float_complex)
 
-LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CCCF,
+LIQUID_FIRFILT_DEFINE_API(LIQUID_FIRFILT_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
@@ -2139,8 +2309,8 @@ LIQUID_FIRFILT_DEFINE_API(FIRFILT_MANGLE_CCCF,
 //  1:2 complex-to-real interpolator
 //
 
-#define FIRHILB_MANGLE_FLOAT(name)  LIQUID_CONCAT(firhilbf, name)
-//#define FIRHILB_MANGLE_DOUBLE(name) LIQUID_CONCAT(firhilb, name)
+#define LIQUID_FIRHILB_MANGLE_FLOAT(name)  LIQUID_CONCAT(firhilbf, name)
+//#define LIQUID_FIRHILB_MANGLE_DOUBLE(name) LIQUID_CONCAT(firhilb, name)
 
 // NOTES:
 //   Although firhilb is a placeholder for both decimation and
@@ -2217,17 +2387,17 @@ void FIRHILB(_interp_execute_block)(FIRHILB()    _q,            \
                                     unsigned int _n,            \
                                     T *          _y);           \
 
-LIQUID_FIRHILB_DEFINE_API(FIRHILB_MANGLE_FLOAT, float, liquid_float_complex)
-//LIQUID_FIRHILB_DEFINE_API(FIRHILB_MANGLE_DOUBLE, double, liquid_double_complex)
+LIQUID_FIRHILB_DEFINE_API(LIQUID_FIRHILB_MANGLE_FLOAT, float, liquid_float_complex)
+//LIQUID_FIRHILB_DEFINE_API(LIQUID_FIRHILB_MANGLE_DOUBLE, double, liquid_double_complex)
 
 
 //
 // FFT-based finite impulse response filter
 //
 
-#define FFTFILT_MANGLE_RRRF(name)  LIQUID_CONCAT(fftfilt_rrrf,name)
-#define FFTFILT_MANGLE_CRCF(name)  LIQUID_CONCAT(fftfilt_crcf,name)
-#define FFTFILT_MANGLE_CCCF(name)  LIQUID_CONCAT(fftfilt_cccf,name)
+#define LIQUID_FFTFILT_MANGLE_RRRF(name) LIQUID_CONCAT(fftfilt_rrrf,name)
+#define LIQUID_FFTFILT_MANGLE_CRCF(name) LIQUID_CONCAT(fftfilt_crcf,name)
+#define LIQUID_FFTFILT_MANGLE_CCCF(name) LIQUID_CONCAT(fftfilt_cccf,name)
 
 // Macro:
 //   FFTFILT : name-mangling macro
@@ -2269,17 +2439,17 @@ void FFTFILT(_execute)(FFTFILT() _q,                            \
 /* return length of filter object's internal coefficients   */  \
 unsigned int FFTFILT(_get_length)(FFTFILT() _q);                \
 
-LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_RRRF,
+LIQUID_FFTFILT_DEFINE_API(LIQUID_FFTFILT_MANGLE_RRRF,
                           float,
                           float,
                           float)
 
-LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CRCF,
+LIQUID_FFTFILT_DEFINE_API(LIQUID_FFTFILT_MANGLE_CRCF,
                           liquid_float_complex,
                           float,
                           liquid_float_complex)
 
-LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CCCF,
+LIQUID_FFTFILT_DEFINE_API(LIQUID_FFTFILT_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
@@ -2289,9 +2459,9 @@ LIQUID_FFTFILT_DEFINE_API(FFTFILT_MANGLE_CCCF,
 // Infinite impulse response filter
 //
 
-#define IIRFILT_MANGLE_RRRF(name)  LIQUID_CONCAT(iirfilt_rrrf,name)
-#define IIRFILT_MANGLE_CRCF(name)  LIQUID_CONCAT(iirfilt_crcf,name)
-#define IIRFILT_MANGLE_CCCF(name)  LIQUID_CONCAT(iirfilt_cccf,name)
+#define LIQUID_IIRFILT_MANGLE_RRRF(name) LIQUID_CONCAT(iirfilt_rrrf,name)
+#define LIQUID_IIRFILT_MANGLE_CRCF(name) LIQUID_CONCAT(iirfilt_crcf,name)
+#define LIQUID_IIRFILT_MANGLE_CCCF(name) LIQUID_CONCAT(iirfilt_cccf,name)
 
 // Macro:
 //   IIRFILT : name-mangling macro
@@ -2323,7 +2493,7 @@ IIRFILT() IIRFILT(_create_sos)(TC *         _B,                 \
 /*  _ftype  : filter type (e.g. LIQUID_IIRDES_BUTTER)       */  \
 /*  _btype  : band type (e.g. LIQUID_IIRDES_BANDPASS)       */  \
 /*  _format : coefficients format (e.g. LIQUID_IIRDES_SOS)  */  \
-/*  _n      : filter order                                  */  \
+/*  _order  : filter order                                  */  \
 /*  _fc     : low-pass prototype cut-off frequency          */  \
 /*  _f0     : center frequency (band-pass, band-stop)       */  \
 /*  _Ap     : pass-band ripple in dB                        */  \
@@ -2339,7 +2509,7 @@ IIRFILT() IIRFILT(_create_prototype)(                           \
             float _As);                                         \
                                                                 \
 /* create simplified low-pass Butterworth IIR filter */         \
-/*  _n      : filter order                                  */  \
+/*  _order  : filter order                                  */  \
 /*  _fc     : low-pass prototype cut-off frequency          */  \
 IIRFILT() IIRFILT(_create_lowpass)(                             \
             unsigned int _order,                                \
@@ -2406,17 +2576,17 @@ void IIRFILT(_freqresponse)(IIRFILT()              _q,          \
 /*  _fc     : frequency to evaluate                         */  \
 float IIRFILT(_groupdelay)(IIRFILT() _q, float _fc);            \
 
-LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_RRRF,
+LIQUID_IIRFILT_DEFINE_API(LIQUID_IIRFILT_MANGLE_RRRF,
                           float,
                           float,
                           float)
 
-LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CRCF,
+LIQUID_IIRFILT_DEFINE_API(LIQUID_IIRFILT_MANGLE_CRCF,
                           liquid_float_complex,
                           float,
                           liquid_float_complex)
 
-LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CCCF,
+LIQUID_IIRFILT_DEFINE_API(LIQUID_IIRFILT_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
@@ -2425,9 +2595,9 @@ LIQUID_IIRFILT_DEFINE_API(IIRFILT_MANGLE_CCCF,
 //
 // FIR Polyphase filter bank
 //
-#define FIRPFB_MANGLE_RRRF(name)  LIQUID_CONCAT(firpfb_rrrf,name)
-#define FIRPFB_MANGLE_CRCF(name)  LIQUID_CONCAT(firpfb_crcf,name)
-#define FIRPFB_MANGLE_CCCF(name)  LIQUID_CONCAT(firpfb_cccf,name)
+#define LIQUID_FIRPFB_MANGLE_RRRF(name) LIQUID_CONCAT(firpfb_rrrf,name)
+#define LIQUID_FIRPFB_MANGLE_CRCF(name) LIQUID_CONCAT(firpfb_crcf,name)
+#define LIQUID_FIRPFB_MANGLE_CCCF(name) LIQUID_CONCAT(firpfb_cccf,name)
 
 // Macro:
 //   FIRPFB : name-mangling macro
@@ -2527,17 +2697,17 @@ void FIRPFB(_execute_block)(FIRPFB()     _q,                    \
                             unsigned int _n,                    \
                             TO *         _y);                   \
 
-LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_RRRF,
+LIQUID_FIRPFB_DEFINE_API(LIQUID_FIRPFB_MANGLE_RRRF,
                          float,
                          float,
                          float)
 
-LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CRCF,
+LIQUID_FIRPFB_DEFINE_API(LIQUID_FIRPFB_MANGLE_CRCF,
                          liquid_float_complex,
                          float,
                          liquid_float_complex)
 
-LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CCCF,
+LIQUID_FIRPFB_DEFINE_API(LIQUID_FIRPFB_MANGLE_CCCF,
                          liquid_float_complex,
                          liquid_float_complex,
                          liquid_float_complex)
@@ -2547,9 +2717,9 @@ LIQUID_FIRPFB_DEFINE_API(FIRPFB_MANGLE_CCCF,
 //
 
 // firinterp : finite impulse response interpolator
-#define FIRINTERP_MANGLE_RRRF(name)  LIQUID_CONCAT(firinterp_rrrf,name)
-#define FIRINTERP_MANGLE_CRCF(name)  LIQUID_CONCAT(firinterp_crcf,name)
-#define FIRINTERP_MANGLE_CCCF(name)  LIQUID_CONCAT(firinterp_cccf,name)
+#define LIQUID_FIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(firinterp_rrrf,name)
+#define LIQUID_FIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(firinterp_crcf,name)
+#define LIQUID_FIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(firinterp_cccf,name)
 
 #define LIQUID_FIRINTERP_DEFINE_API(FIRINTERP,TO,TC,TI)         \
                                                                 \
@@ -2610,25 +2780,25 @@ void FIRINTERP(_execute_block)(FIRINTERP()  _q,                 \
                                unsigned int _n,                 \
                                TO *         _y);                \
 
-LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_RRRF,
+LIQUID_FIRINTERP_DEFINE_API(LIQUID_FIRINTERP_MANGLE_RRRF,
                             float,
                             float,
                             float)
 
-LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_CRCF,
+LIQUID_FIRINTERP_DEFINE_API(LIQUID_FIRINTERP_MANGLE_CRCF,
                             liquid_float_complex,
                             float,
                             liquid_float_complex)
 
-LIQUID_FIRINTERP_DEFINE_API(FIRINTERP_MANGLE_CCCF,
+LIQUID_FIRINTERP_DEFINE_API(LIQUID_FIRINTERP_MANGLE_CCCF,
                             liquid_float_complex,
                             liquid_float_complex,
                             liquid_float_complex)
 
 // iirinterp : infinite impulse response interpolator
-#define IIRINTERP_MANGLE_RRRF(name)  LIQUID_CONCAT(iirinterp_rrrf,name)
-#define IIRINTERP_MANGLE_CRCF(name)  LIQUID_CONCAT(iirinterp_crcf,name)
-#define IIRINTERP_MANGLE_CCCF(name)  LIQUID_CONCAT(iirinterp_cccf,name)
+#define LIQUID_IIRINTERP_MANGLE_RRRF(name) LIQUID_CONCAT(iirinterp_rrrf,name)
+#define LIQUID_IIRINTERP_MANGLE_CRCF(name) LIQUID_CONCAT(iirinterp_crcf,name)
+#define LIQUID_IIRINTERP_MANGLE_CCCF(name) LIQUID_CONCAT(iirinterp_cccf,name)
 
 #define LIQUID_IIRINTERP_DEFINE_API(IIRINTERP,TO,TC,TI)         \
 typedef struct IIRINTERP(_s) * IIRINTERP();                     \
@@ -2694,17 +2864,17 @@ void IIRINTERP(_execute_block)(IIRINTERP()  _q,                 \
 /* get system group delay at frequency _fc                  */  \
 float IIRINTERP(_groupdelay)(IIRINTERP() _q, float _fc);        \
 
-LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_RRRF,
+LIQUID_IIRINTERP_DEFINE_API(LIQUID_IIRINTERP_MANGLE_RRRF,
                             float,
                             float,
                             float)
 
-LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CRCF,
+LIQUID_IIRINTERP_DEFINE_API(LIQUID_IIRINTERP_MANGLE_CRCF,
                             liquid_float_complex,
                             float,
                             liquid_float_complex)
 
-LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CCCF,
+LIQUID_IIRINTERP_DEFINE_API(LIQUID_IIRINTERP_MANGLE_CCCF,
                             liquid_float_complex,
                             liquid_float_complex,
                             liquid_float_complex)
@@ -2714,9 +2884,9 @@ LIQUID_IIRINTERP_DEFINE_API(IIRINTERP_MANGLE_CCCF,
 //
 
 // firdecim : finite impulse response decimator
-#define FIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(firdecim_rrrf,name)
-#define FIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(firdecim_crcf,name)
-#define FIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(firdecim_cccf,name)
+#define LIQUID_FIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(firdecim_rrrf,name)
+#define LIQUID_FIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(firdecim_crcf,name)
+#define LIQUID_FIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(firdecim_cccf,name)
 
 #define LIQUID_FIRDECIM_DEFINE_API(FIRDECIM,TO,TC,TI)           \
 typedef struct FIRDECIM(_s) * FIRDECIM();                       \
@@ -2776,26 +2946,26 @@ void FIRDECIM(_execute_block)(FIRDECIM()   _q,                  \
                               unsigned int _n,                  \
                               TO *         _y);                 \
 
-LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_RRRF,
+LIQUID_FIRDECIM_DEFINE_API(LIQUID_FIRDECIM_MANGLE_RRRF,
                            float,
                            float,
                            float)
 
-LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_CRCF,
+LIQUID_FIRDECIM_DEFINE_API(LIQUID_FIRDECIM_MANGLE_CRCF,
                            liquid_float_complex,
                            float,
                            liquid_float_complex)
 
-LIQUID_FIRDECIM_DEFINE_API(FIRDECIM_MANGLE_CCCF,
+LIQUID_FIRDECIM_DEFINE_API(LIQUID_FIRDECIM_MANGLE_CCCF,
                            liquid_float_complex,
                            liquid_float_complex,
                            liquid_float_complex)
 
 
 // iirdecim : infinite impulse response decimator
-#define IIRDECIM_MANGLE_RRRF(name)  LIQUID_CONCAT(iirdecim_rrrf,name)
-#define IIRDECIM_MANGLE_CRCF(name)  LIQUID_CONCAT(iirdecim_crcf,name)
-#define IIRDECIM_MANGLE_CCCF(name)  LIQUID_CONCAT(iirdecim_cccf,name)
+#define LIQUID_IIRDECIM_MANGLE_RRRF(name) LIQUID_CONCAT(iirdecim_rrrf,name)
+#define LIQUID_IIRDECIM_MANGLE_CRCF(name) LIQUID_CONCAT(iirdecim_crcf,name)
+#define LIQUID_IIRDECIM_MANGLE_CCCF(name) LIQUID_CONCAT(iirdecim_cccf,name)
 
 #define LIQUID_IIRDECIM_DEFINE_API(IIRDECIM,TO,TC,TI)           \
 typedef struct IIRDECIM(_s) * IIRDECIM();                       \
@@ -2869,17 +3039,17 @@ void IIRDECIM(_execute_block)(IIRDECIM()   _q,                  \
 /* get system group delay at frequency _fc                  */  \
 float IIRDECIM(_groupdelay)(IIRDECIM() _q, float _fc);          \
 
-LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_RRRF,
+LIQUID_IIRDECIM_DEFINE_API(LIQUID_IIRDECIM_MANGLE_RRRF,
                            float,
                            float,
                            float)
 
-LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CRCF,
+LIQUID_IIRDECIM_DEFINE_API(LIQUID_IIRDECIM_MANGLE_CRCF,
                            liquid_float_complex,
                            float,
                            liquid_float_complex)
 
-LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CCCF,
+LIQUID_IIRDECIM_DEFINE_API(LIQUID_IIRDECIM_MANGLE_CCCF,
                            liquid_float_complex,
                            liquid_float_complex,
                            liquid_float_complex)
@@ -2889,9 +3059,9 @@ LIQUID_IIRDECIM_DEFINE_API(IIRDECIM_MANGLE_CCCF,
 // 
 // Half-band resampler
 //
-#define RESAMP2_MANGLE_RRRF(name)   LIQUID_CONCAT(resamp2_rrrf,name)
-#define RESAMP2_MANGLE_CRCF(name)   LIQUID_CONCAT(resamp2_crcf,name)
-#define RESAMP2_MANGLE_CCCF(name)   LIQUID_CONCAT(resamp2_cccf,name)
+#define LIQUID_RESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(resamp2_rrrf,name)
+#define LIQUID_RESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(resamp2_crcf,name)
+#define LIQUID_RESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(resamp2_cccf,name)
 
 #define LIQUID_RESAMP2_DEFINE_API(RESAMP2,TO,TC,TI)             \
 typedef struct RESAMP2(_s) * RESAMP2();                         \
@@ -2968,17 +3138,17 @@ void RESAMP2(_interp_execute)(RESAMP2() _q,                     \
                               TI        _x,                     \
                               TO *      _y);                    \
 
-LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_RRRF,
+LIQUID_RESAMP2_DEFINE_API(LIQUID_RESAMP2_MANGLE_RRRF,
                           float,
                           float,
                           float)
 
-LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CRCF,
+LIQUID_RESAMP2_DEFINE_API(LIQUID_RESAMP2_MANGLE_CRCF,
                           liquid_float_complex,
                           float,
                           liquid_float_complex)
 
-LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CCCF,
+LIQUID_RESAMP2_DEFINE_API(LIQUID_RESAMP2_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
@@ -2987,9 +3157,9 @@ LIQUID_RESAMP2_DEFINE_API(RESAMP2_MANGLE_CCCF,
 // 
 // Arbitrary resampler
 //
-#define RESAMP_MANGLE_RRRF(name)    LIQUID_CONCAT(resamp_rrrf,name)
-#define RESAMP_MANGLE_CRCF(name)    LIQUID_CONCAT(resamp_crcf,name)
-#define RESAMP_MANGLE_CCCF(name)    LIQUID_CONCAT(resamp_cccf,name)
+#define LIQUID_RESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(resamp_rrrf,name)
+#define LIQUID_RESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(resamp_crcf,name)
+#define LIQUID_RESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(resamp_cccf,name)
 
 #define LIQUID_RESAMP_DEFINE_API(RESAMP,TO,TC,TI)               \
 typedef struct RESAMP(_s) * RESAMP();                           \
@@ -3008,10 +3178,10 @@ RESAMP() RESAMP(_create)(float        _rate,                    \
                                                                 \
 /* create arbitrary resampler object with a specified input */  \
 /* resampling rate and default parameters                   */  \
-/*  m (filter semi-length) = 7                              */  \
-/*  fc (filter cutoff frequency) = 0.25                     */  \
-/*  As (filter stop-band attenuation) = 60 dB               */  \
-/*  npfb (number of filters in the bank) = 64               */  \
+/*  m    : (filter semi-length) = 7                         */  \
+/*  fc   : (filter cutoff frequency) = 0.25                 */  \
+/*  As   : (filter stop-band attenuation) = 60 dB           */  \
+/*  npfb : (number of filters in the bank) = 64             */  \
 RESAMP() RESAMP(_create_default)(float _rate);                  \
                                                                 \
 /* destroy arbitrary resampler object                       */  \
@@ -3027,10 +3197,28 @@ void RESAMP(_reset)(RESAMP() _q);                               \
 unsigned int RESAMP(_get_delay)(RESAMP() _q);                   \
                                                                 \
 /* set rate of arbitrary resampler                          */  \
-void RESAMP(_set_rate)(RESAMP() _q, float _rate);               \
+/*  _q      : resampling object                             */  \
+/*  _rate   : new sampling rate, _rate > 0                  */  \
+void RESAMP(_set_rate)(RESAMP() _q,                             \
+                       float    _rate);                         \
                                                                 \
 /* adjust rate of arbitrary resampler                       */  \
-void RESAMP(_adjust_rate)(RESAMP() _q, float _delta);           \
+/*  _q      : resampling object                             */  \
+/*  _delta  : rate adjustment; _rate <- _rate + _delta      */  \
+void RESAMP(_adjust_rate)(RESAMP() _q,                          \
+                          float    _delta);                     \
+                                                                \
+/* set resampling timing phase                              */  \
+/*  _q      : resampling object                             */  \
+/*  _tau    : sample timing                                 */  \
+void RESAMP(_set_timing_phase)(RESAMP() _q,                     \
+                               float    _tau);                  \
+                                                                \
+/* adjust resampling timing phase                           */  \
+/*  _q      : resampling object                             */  \
+/*  _delta  : sample timing adjustment                      */  \
+void RESAMP(_adjust_timing_phase)(RESAMP() _q,                  \
+                                  float    _delta);             \
                                                                 \
 /* execute arbitrary resampler                              */  \
 /*  _q              :   resamp object                       */  \
@@ -3054,17 +3242,17 @@ void RESAMP(_execute_block)(RESAMP()       _q,                  \
                             TO *           _y,                  \
                             unsigned int * _ny);                \
 
-LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_RRRF,
+LIQUID_RESAMP_DEFINE_API(LIQUID_RESAMP_MANGLE_RRRF,
                          float,
                          float,
                          float)
 
-LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_CRCF,
+LIQUID_RESAMP_DEFINE_API(LIQUID_RESAMP_MANGLE_CRCF,
                          liquid_float_complex,
                          float,
                          liquid_float_complex)
 
-LIQUID_RESAMP_DEFINE_API(RESAMP_MANGLE_CCCF,
+LIQUID_RESAMP_DEFINE_API(LIQUID_RESAMP_MANGLE_CCCF,
                          liquid_float_complex,
                          liquid_float_complex,
                          liquid_float_complex)
@@ -3080,9 +3268,9 @@ typedef enum {
     LIQUID_RESAMP_DECIM,    // decimator
 } liquid_resamp_type;
 
-#define MSRESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp2_rrrf,name)
-#define MSRESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp2_crcf,name)
-#define MSRESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp2_cccf,name)
+#define LIQUID_MSRESAMP2_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp2_rrrf,name)
+#define LIQUID_MSRESAMP2_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp2_crcf,name)
+#define LIQUID_MSRESAMP2_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp2_cccf,name)
 
 #define LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2,TO,TC,TI)         \
 typedef struct MSRESAMP2(_s) * MSRESAMP2();                     \
@@ -3121,17 +3309,17 @@ void MSRESAMP2(_execute)(MSRESAMP2() _q,                        \
                          TI *        _x,                        \
                          TO *        _y);                       \
 
-LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_RRRF,
+LIQUID_MSRESAMP2_DEFINE_API(LIQUID_MSRESAMP2_MANGLE_RRRF,
                             float,
                             float,
                             float)
 
-LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CRCF,
+LIQUID_MSRESAMP2_DEFINE_API(LIQUID_MSRESAMP2_MANGLE_CRCF,
                             liquid_float_complex,
                             float,
                             liquid_float_complex)
 
-LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CCCF,
+LIQUID_MSRESAMP2_DEFINE_API(LIQUID_MSRESAMP2_MANGLE_CCCF,
                             liquid_float_complex,
                             liquid_float_complex,
                             liquid_float_complex)
@@ -3140,9 +3328,9 @@ LIQUID_MSRESAMP2_DEFINE_API(MSRESAMP2_MANGLE_CCCF,
 // 
 // Multi-stage arbitrary resampler
 //
-#define MSRESAMP_MANGLE_RRRF(name)    LIQUID_CONCAT(msresamp_rrrf,name)
-#define MSRESAMP_MANGLE_CRCF(name)    LIQUID_CONCAT(msresamp_crcf,name)
-#define MSRESAMP_MANGLE_CCCF(name)    LIQUID_CONCAT(msresamp_cccf,name)
+#define LIQUID_MSRESAMP_MANGLE_RRRF(name) LIQUID_CONCAT(msresamp_rrrf,name)
+#define LIQUID_MSRESAMP_MANGLE_CRCF(name) LIQUID_CONCAT(msresamp_crcf,name)
+#define LIQUID_MSRESAMP_MANGLE_CCCF(name) LIQUID_CONCAT(msresamp_cccf,name)
 
 #define LIQUID_MSRESAMP_DEFINE_API(MSRESAMP,TO,TC,TI)           \
 typedef struct MSRESAMP(_s) * MSRESAMP();                       \
@@ -3177,17 +3365,17 @@ void MSRESAMP(_execute)(MSRESAMP()     _q,                      \
                         TO *           _y,                      \
                         unsigned int * _ny);                    \
 
-LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_RRRF,
+LIQUID_MSRESAMP_DEFINE_API(LIQUID_MSRESAMP_MANGLE_RRRF,
                            float,
                            float,
                            float)
 
-LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CRCF,
+LIQUID_MSRESAMP_DEFINE_API(LIQUID_MSRESAMP_MANGLE_CRCF,
                            liquid_float_complex,
                            float,
                            liquid_float_complex)
 
-LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CCCF,
+LIQUID_MSRESAMP_DEFINE_API(LIQUID_MSRESAMP_MANGLE_CCCF,
                            liquid_float_complex,
                            liquid_float_complex,
                            liquid_float_complex)
@@ -3196,8 +3384,8 @@ LIQUID_MSRESAMP_DEFINE_API(MSRESAMP_MANGLE_CCCF,
 // 
 // Symbol timing recovery (symbol synchronizer)
 //
-#define SYMSYNC_MANGLE_RRRF(name)   LIQUID_CONCAT(symsync_rrrf,name)
-#define SYMSYNC_MANGLE_CRCF(name)   LIQUID_CONCAT(symsync_crcf,name)
+#define LIQUID_SYMSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(symsync_rrrf,name)
+#define LIQUID_SYMSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(symsync_crcf,name)
 
 #define LIQUID_SYMSYNC_DEFINE_API(SYMSYNC,TO,TC,TI)             \
                                                                 \
@@ -3276,12 +3464,12 @@ void SYMSYNC(_execute)(SYMSYNC()      _q,                       \
                        TO *           _y,                       \
                        unsigned int * _ny);                     \
 
-LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_RRRF,
+LIQUID_SYMSYNC_DEFINE_API(LIQUID_SYMSYNC_MANGLE_RRRF,
                           float,
                           float,
                           float)
 
-LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_CRCF,
+LIQUID_SYMSYNC_DEFINE_API(LIQUID_SYMSYNC_MANGLE_CRCF,
                           liquid_float_complex,
                           float,
                           liquid_float_complex)
@@ -3291,9 +3479,9 @@ LIQUID_SYMSYNC_DEFINE_API(SYMSYNC_MANGLE_CRCF,
 // Finite impulse response Farrow filter
 //
 
-#define FIRFARROW_MANGLE_RRRF(name)     LIQUID_CONCAT(firfarrow_rrrf,name)
-#define FIRFARROW_MANGLE_CRCF(name)     LIQUID_CONCAT(firfarrow_crcf,name)
-//#define FIRFARROW_MANGLE_CCCF(name)     LIQUID_CONCAT(firfarrow_cccf,name)
+#define LIQUID_FIRFARROW_MANGLE_RRRF(name) LIQUID_CONCAT(firfarrow_rrrf,name)
+#define LIQUID_FIRFARROW_MANGLE_CRCF(name) LIQUID_CONCAT(firfarrow_crcf,name)
+//#define LIQUID_FIRFARROW_MANGLE_CCCF(name) LIQUID_CONCAT(firfarrow_cccf,name)
 
 // Macro:
 //   FIRFARROW  : name-mangling macro
@@ -3375,12 +3563,12 @@ void FIRFARROW(_freqresponse)(FIRFARROW()            _q,        \
 float FIRFARROW(_groupdelay)(FIRFARROW() _q,                    \
                              float       _fc);                  \
 
-LIQUID_FIRFARROW_DEFINE_API(FIRFARROW_MANGLE_RRRF,
+LIQUID_FIRFARROW_DEFINE_API(LIQUID_FIRFARROW_MANGLE_RRRF,
                             float,
                             float,
                             float)
 
-LIQUID_FIRFARROW_DEFINE_API(FIRFARROW_MANGLE_CRCF,
+LIQUID_FIRFARROW_DEFINE_API(LIQUID_FIRFARROW_MANGLE_CRCF,
                             liquid_float_complex,
                             float,
                             liquid_float_complex)
@@ -3738,6 +3926,9 @@ void flexframesync_print(flexframesync _q);
 // reset frame synchronizer internal state
 void flexframesync_reset(flexframesync _q);
 
+// has frame been detected?
+int flexframesync_is_frame_open(flexframesync _q);
+
 // push samples through frame synchronizer
 //  _q      :   frame synchronizer object
 //  _x      :   input samples [size: _n x 1]
@@ -3885,6 +4076,7 @@ gmskframesync gmskframesync_create(framesync_callback _callback,
 void gmskframesync_destroy(gmskframesync _q);
 void gmskframesync_print(gmskframesync _q);
 void gmskframesync_reset(gmskframesync _q);
+int  gmskframesync_is_frame_open(gmskframesync _q);
 void gmskframesync_execute(gmskframesync _q,
                            liquid_float_complex * _x,
                            unsigned int _n);
@@ -3989,6 +4181,7 @@ ofdmflexframesync ofdmflexframesync_create(unsigned int       _M,
 void ofdmflexframesync_destroy(ofdmflexframesync _q);
 void ofdmflexframesync_print(ofdmflexframesync _q);
 void ofdmflexframesync_reset(ofdmflexframesync _q);
+int  ofdmflexframesync_is_frame_open(ofdmflexframesync _q);
 void ofdmflexframesync_execute(ofdmflexframesync _q,
                                liquid_float_complex * _x,
                                unsigned int _n);
@@ -4010,9 +4203,9 @@ void ofdmflexframesync_debug_print(ofdmflexframesync _q,
 //
 // Binary P/N synchronizer
 //
-#define BSYNC_MANGLE_RRRF(name)     LIQUID_CONCAT(bsync_rrrf,name)
-#define BSYNC_MANGLE_CRCF(name)     LIQUID_CONCAT(bsync_crcf,name)
-#define BSYNC_MANGLE_CCCF(name)     LIQUID_CONCAT(bsync_cccf,name)
+#define LIQUID_BSYNC_MANGLE_RRRF(name) LIQUID_CONCAT(bsync_rrrf,name)
+#define LIQUID_BSYNC_MANGLE_CRCF(name) LIQUID_CONCAT(bsync_crcf,name)
+#define LIQUID_BSYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bsync_cccf,name)
 
 // Macro:
 //   BSYNC  : name-mangling macro
@@ -4033,17 +4226,17 @@ void BSYNC(_destroy)(BSYNC() _fs);                              \
 void BSYNC(_print)(BSYNC() _fs);                                \
 void BSYNC(_correlate)(BSYNC() _fs, TI _sym, TO * _y);
 
-LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_RRRF,
+LIQUID_BSYNC_DEFINE_API(LIQUID_BSYNC_MANGLE_RRRF,
                         float,
                         float,
                         float)
 
-LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CRCF,
+LIQUID_BSYNC_DEFINE_API(LIQUID_BSYNC_MANGLE_CRCF,
                         liquid_float_complex,
                         float,
                         liquid_float_complex)
 
-LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CCCF,
+LIQUID_BSYNC_DEFINE_API(LIQUID_BSYNC_MANGLE_CCCF,
                         liquid_float_complex,
                         liquid_float_complex,
                         liquid_float_complex)
@@ -4052,8 +4245,8 @@ LIQUID_BSYNC_DEFINE_API(BSYNC_MANGLE_CCCF,
 //
 // Pre-demodulation synchronizers (binary and otherwise)
 //
-#define  PRESYNC_MANGLE_CCCF(name)  LIQUID_CONCAT( presync_cccf,name)
-#define BPRESYNC_MANGLE_CCCF(name)  LIQUID_CONCAT(bpresync_cccf,name)
+#define  LIQUID_PRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT( presync_cccf,name)
+#define LIQUID_BPRESYNC_MANGLE_CCCF(name) LIQUID_CONCAT(bpresync_cccf,name)
 
 // Macro:
 //   PRESYNC   : name-mangling macro
@@ -4097,13 +4290,13 @@ void PRESYNC(_correlate)(PRESYNC() _q,                          \
                          float *   _dphi_hat);                  \
 
 // non-binary pre-demodulation synchronizer
-LIQUID_PRESYNC_DEFINE_API(PRESYNC_MANGLE_CCCF,
+LIQUID_PRESYNC_DEFINE_API(LIQUID_PRESYNC_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
 
 // binary pre-demodulation synchronizer
-LIQUID_PRESYNC_DEFINE_API(BPRESYNC_MANGLE_CCCF,
+LIQUID_PRESYNC_DEFINE_API(LIQUID_BPRESYNC_MANGLE_CCCF,
                           liquid_float_complex,
                           liquid_float_complex,
                           liquid_float_complex)
@@ -4213,7 +4406,7 @@ int detector_cccf_correlate(detector_cccf        _q,
 // 
 // symbol streaming for testing (no meaningful data, just symbols)
 //
-#define SYMSTREAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(symstreamcf,name)
+#define LIQUID_SYMSTREAM_MANGLE_CFLOAT(name) LIQUID_CONCAT(symstreamcf,name)
 
 #define LIQUID_SYMSTREAM_DEFINE_API(SYMSTREAM,TO)               \
                                                                 \
@@ -4252,14 +4445,14 @@ void SYMSTREAM(_write_samples)(SYMSTREAM()  _q,                 \
                                TO *         _buf,               \
                                unsigned int _buf_len);          \
     
-LIQUID_SYMSTREAM_DEFINE_API(SYMSTREAM_MANGLE_CFLOAT, liquid_float_complex)
+LIQUID_SYMSTREAM_DEFINE_API(LIQUID_SYMSTREAM_MANGLE_CFLOAT, liquid_float_complex)
 
 
 
 //
 // multi-signal source for testing (no meaningful data, just signals)
 //
-#define MSOURCE_MANGLE_CFLOAT(name) LIQUID_CONCAT(msourcecf,name)
+#define LIQUID_MSOURCE_MANGLE_CFLOAT(name) LIQUID_CONCAT(msourcecf,name)
 
 #define LIQUID_MSOURCE_DEFINE_API(MSOURCE,TO)                   \
                                                                 \
@@ -4317,7 +4510,7 @@ void MSOURCE(_write_samples)(MSOURCE()    _q,                   \
                              TO *         _buf,                 \
                              unsigned int _buf_len);            \
     
-LIQUID_MSOURCE_DEFINE_API(MSOURCE_MANGLE_CFLOAT, liquid_float_complex)
+LIQUID_MSOURCE_DEFINE_API(LIQUID_MSOURCE_MANGLE_CFLOAT, liquid_float_complex)
 
 
 
@@ -4325,8 +4518,8 @@ LIQUID_MSOURCE_DEFINE_API(MSOURCE_MANGLE_CFLOAT, liquid_float_complex)
 // 
 // Symbol tracking: AGC > symsync > EQ > carrier recovery
 //
-#define SYMTRACK_MANGLE_RRRF(name) LIQUID_CONCAT(symtrack_rrrf,name)
-#define SYMTRACK_MANGLE_CCCF(name) LIQUID_CONCAT(symtrack_cccf,name)
+#define LIQUID_SYMTRACK_MANGLE_RRRF(name) LIQUID_CONCAT(symtrack_rrrf,name)
+#define LIQUID_SYMTRACK_MANGLE_CCCF(name) LIQUID_CONCAT(symtrack_cccf,name)
 
 // large macro
 //   SYMTRACK   : name-mangling macro
@@ -4393,13 +4586,13 @@ void SYMTRACK(_execute_block)(SYMTRACK()     _q,                \
                               TO *           _y,                \
                               unsigned int * _ny);              \
     
-LIQUID_SYMTRACK_DEFINE_API(SYMTRACK_MANGLE_RRRF,
+LIQUID_SYMTRACK_DEFINE_API(LIQUID_SYMTRACK_MANGLE_RRRF,
                            float,
                            float,
                            float,
                            float)
 
-LIQUID_SYMTRACK_DEFINE_API(SYMTRACK_MANGLE_CCCF,
+LIQUID_SYMTRACK_DEFINE_API(LIQUID_SYMTRACK_MANGLE_CCCF,
                            float,
                            liquid_float_complex,
                            liquid_float_complex,
@@ -4574,11 +4767,11 @@ float liquid_rcostaper_windowf(unsigned int _n,
 // polynomials
 
 
-#define POLY_MANGLE_DOUBLE(name)    LIQUID_CONCAT(poly,   name)
-#define POLY_MANGLE_FLOAT(name)     LIQUID_CONCAT(polyf,  name)
+#define LIQUID_POLY_MANGLE_DOUBLE(name)  LIQUID_CONCAT(poly,   name)
+#define LIQUID_POLY_MANGLE_FLOAT(name)   LIQUID_CONCAT(polyf,  name)
 
-#define POLY_MANGLE_CDOUBLE(name)   LIQUID_CONCAT(polyc,  name)
-#define POLY_MANGLE_CFLOAT(name)    LIQUID_CONCAT(polycf, name)
+#define LIQUID_POLY_MANGLE_CDOUBLE(name) LIQUID_CONCAT(polyc,  name)
+#define LIQUID_POLY_MANGLE_CFLOAT(name)  LIQUID_CONCAT(polycf, name)
 
 // large macro
 //   POLY   : name-mangling macro
@@ -4688,19 +4881,19 @@ void POLY(_mul)(T *          _a,                                \
                 unsigned int _order_b,                          \
                 T *          _c);                               \
 
-LIQUID_POLY_DEFINE_API(POLY_MANGLE_DOUBLE,
+LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_DOUBLE,
                        double,
                        liquid_double_complex)
 
-LIQUID_POLY_DEFINE_API(POLY_MANGLE_FLOAT,
+LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_FLOAT,
                        float,
                        liquid_float_complex)
 
-LIQUID_POLY_DEFINE_API(POLY_MANGLE_CDOUBLE,
+LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_CDOUBLE,
                        liquid_double_complex,
                        liquid_double_complex)
 
-LIQUID_POLY_DEFINE_API(POLY_MANGLE_CFLOAT,
+LIQUID_POLY_DEFINE_API(LIQUID_POLY_MANGLE_CFLOAT,
                        liquid_float_complex,
                        liquid_float_complex)
 
@@ -4759,11 +4952,11 @@ unsigned int liquid_totient(unsigned int _n);
 // MODULE : matrix
 //
 
-#define MATRIX_MANGLE_DOUBLE(name)  LIQUID_CONCAT(matrix,   name)
-#define MATRIX_MANGLE_FLOAT(name)   LIQUID_CONCAT(matrixf,  name)
+#define LIQUID_MATRIX_MANGLE_DOUBLE(name)  LIQUID_CONCAT(matrix,   name)
+#define LIQUID_MATRIX_MANGLE_FLOAT(name)   LIQUID_CONCAT(matrixf,  name)
 
-#define MATRIX_MANGLE_CDOUBLE(name) LIQUID_CONCAT(matrixc,  name)
-#define MATRIX_MANGLE_CFLOAT(name)  LIQUID_CONCAT(matrixcf, name)
+#define LIQUID_MATRIX_MANGLE_CDOUBLE(name) LIQUID_CONCAT(matrixc,  name)
+#define LIQUID_MATRIX_MANGLE_CFLOAT(name)  LIQUID_CONCAT(matrixcf, name)
 
 // large macro
 //   MATRIX : name-mangling macro
@@ -5075,16 +5268,16 @@ void MATRIX(_chol)(T *          _A,                             \
 #define matrixf_access(X,R,C,r,c)   matrix_access(X,R,C,r,c)
 #define matrixcf_access(X,R,C,r,c)  matrix_access(X,R,C,r,c)
 
-LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_FLOAT,   float)
-LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_DOUBLE,  double)
+LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_FLOAT,   float)
+LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_DOUBLE,  double)
 
-LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_CFLOAT,  liquid_float_complex)
-LIQUID_MATRIX_DEFINE_API(MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
+LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_CFLOAT,  liquid_float_complex)
+LIQUID_MATRIX_DEFINE_API(LIQUID_MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
 
 
-#define SMATRIX_MANGLE_BOOL(name)   LIQUID_CONCAT(smatrixb,  name)
-#define SMATRIX_MANGLE_FLOAT(name)  LIQUID_CONCAT(smatrixf,  name)
-#define SMATRIX_MANGLE_INT(name)    LIQUID_CONCAT(smatrixi,  name)
+#define LIQUID_SMATRIX_MANGLE_BOOL(name)  LIQUID_CONCAT(smatrixb,  name)
+#define LIQUID_SMATRIX_MANGLE_FLOAT(name) LIQUID_CONCAT(smatrixf,  name)
+#define LIQUID_SMATRIX_MANGLE_INT(name)   LIQUID_CONCAT(smatrixi,  name)
 
 // sparse 'alist' matrix type (similar to MacKay, Davey Lafferty convention)
 // large macro
@@ -5116,9 +5309,11 @@ void SMATRIX(_size)(SMATRIX()      _q,                          \
                     unsigned int * _m,                          \
                     unsigned int * _n);                         \
                                                                 \
-/* zero all elements */                                         \
-void SMATRIX(_clear)(SMATRIX() _q); /* zero and keep memory  */ \
-void SMATRIX(_reset)(SMATRIX() _q); /* zero and clear memory */ \
+/* zero all elements and keep memory                        */  \
+void SMATRIX(_clear)(SMATRIX() _q);                             \
+                                                                \
+/* zero all elements and clear memory                       */  \
+void SMATRIX(_reset)(SMATRIX() _q);                             \
                                                                 \
 /* determine if value has been set (allocated memory) */        \
 int SMATRIX(_isset)(SMATRIX()    _q,                            \
@@ -5159,9 +5354,9 @@ void SMATRIX(_vmul)(SMATRIX() _q,                               \
                     T *       _x,                               \
                     T *       _y);                              \
 
-LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_BOOL,  unsigned char)
-LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_FLOAT, float)
-LIQUID_SMATRIX_DEFINE_API(SMATRIX_MANGLE_INT,   short int)
+LIQUID_SMATRIX_DEFINE_API(LIQUID_SMATRIX_MANGLE_BOOL,  unsigned char)
+LIQUID_SMATRIX_DEFINE_API(LIQUID_SMATRIX_MANGLE_FLOAT, float)
+LIQUID_SMATRIX_DEFINE_API(LIQUID_SMATRIX_MANGLE_INT,   short int)
 
 // 
 // smatrix cross methods
@@ -5321,8 +5516,6 @@ void liquid_unpack_soft_bits(unsigned int _sym_in,
 //  T       :   primitive data type
 //  TC      :   primitive data type (complex)
 #define LIQUID_MODEM_DEFINE_API(MODEM,T,TC)                     \
-                                                                \
-/* define struct pointer */                                     \
 typedef struct MODEM(_s) * MODEM();                             \
                                                                 \
 /* create digital modem object                              */  \
@@ -5611,8 +5804,6 @@ float fskdem_get_frequency_error(fskdem _q);
 //  T       :   primitive data type
 //  TC      :   primitive data type (complex)
 #define LIQUID_FREQMOD_DEFINE_API(FREQMOD,T,TC)                 \
-                                                                \
-/* define struct pointer */                                     \
 typedef struct FREQMOD(_s) * FREQMOD();                         \
                                                                 \
 /* create freqmod object (frequency modulator)              */  \
@@ -5660,8 +5851,6 @@ LIQUID_FREQMOD_DEFINE_API(LIQUID_FREQMOD_MANGLE_FLOAT,float,liquid_float_complex
 //  T       :   primitive data type
 //  TC      :   primitive data type (complex)
 #define LIQUID_FREQDEM_DEFINE_API(FREQDEM,T,TC)                 \
-                                                                \
-/* define struct pointer */                                     \
 typedef struct FREQDEM(_s) * FREQDEM();                         \
                                                                 \
 /* create freqdem object (frequency modulator)              */  \
@@ -5764,8 +5953,8 @@ void ampmodem_demodulate_block(ampmodem _q,
 // Finite impulse response polyphase filterbank channelizer
 //
 
-#define FIRPFBCH_MANGLE_CRCF(name)  LIQUID_CONCAT(firpfbch_crcf,name)
-#define FIRPFBCH_MANGLE_CCCF(name)  LIQUID_CONCAT(firpfbch_cccf,name)
+#define LIQUID_FIRPFBCH_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch_crcf,name)
+#define LIQUID_FIRPFBCH_MANGLE_CCCF(name) LIQUID_CONCAT(firpfbch_cccf,name)
 
 // Macro:
 //   FIRPFBCH   : name-mangling macro
@@ -5836,12 +6025,12 @@ void FIRPFBCH(_analyzer_execute)(FIRPFBCH() _q,                 \
                                  TO *       _y);                \
 
 
-LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CRCF,
+LIQUID_FIRPFBCH_DEFINE_API(LIQUID_FIRPFBCH_MANGLE_CRCF,
                            liquid_float_complex,
                            float,
                            liquid_float_complex)
 
-LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CCCF,
+LIQUID_FIRPFBCH_DEFINE_API(LIQUID_FIRPFBCH_MANGLE_CCCF,
                            liquid_float_complex,
                            liquid_float_complex,
                            liquid_float_complex)
@@ -5852,7 +6041,7 @@ LIQUID_FIRPFBCH_DEFINE_API(FIRPFBCH_MANGLE_CCCF,
 // with output rate 2 Fs / M
 //
 
-#define FIRPFBCH2_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch2_crcf,name)
+#define LIQUID_FIRPFBCH2_MANGLE_CRCF(name) LIQUID_CONCAT(firpfbch2_crcf,name)
 
 // Macro:
 //   FIRPFBCH2  : name-mangling macro
@@ -5901,7 +6090,7 @@ void FIRPFBCH2(_execute)(FIRPFBCH2() _q,                        \
                          TO *        _y);                       \
 
 
-LIQUID_FIRPFBCH2_DEFINE_API(FIRPFBCH2_MANGLE_CRCF,
+LIQUID_FIRPFBCH2_DEFINE_API(LIQUID_FIRPFBCH2_MANGLE_CRCF,
                             liquid_float_complex,
                             float,
                             liquid_float_complex)
@@ -6015,6 +6204,7 @@ ofdmframesync ofdmframesync_create(unsigned int           _M,
 void ofdmframesync_destroy(ofdmframesync _q);
 void ofdmframesync_print(ofdmframesync _q);
 void ofdmframesync_reset(ofdmframesync _q);
+int  ofdmframesync_is_frame_open(ofdmframesync _q);
 void ofdmframesync_execute(ofdmframesync _q,
                            liquid_float_complex * _x,
                            unsigned int _n);
@@ -6041,7 +6231,7 @@ typedef enum {
     LIQUID_VCO
 } liquid_ncotype;
 
-#define NCO_MANGLE_FLOAT(name)  LIQUID_CONCAT(nco_crcf, name)
+#define LIQUID_NCO_MANGLE_FLOAT(name) LIQUID_CONCAT(nco_crcf, name)
 
 // large macro
 //   NCO    : name-mangling macro
@@ -6105,7 +6295,7 @@ void NCO(_mix_block_down)(NCO() _q,                             \
                           unsigned int _N);                     \
 
 // Define nco APIs
-LIQUID_NCO_DEFINE_API(NCO_MANGLE_FLOAT, float, liquid_float_complex)
+LIQUID_NCO_DEFINE_API(LIQUID_NCO_MANGLE_FLOAT, float, liquid_float_complex)
 
 
 // nco utilities
@@ -6386,8 +6576,8 @@ typedef enum {
     LIQUID_COMPANDER_ALAW
 } liquid_compander_type;
 
-#define QUANTIZER_MANGLE_FLOAT(name)    LIQUID_CONCAT(quantizerf,  name)
-#define QUANTIZER_MANGLE_CFLOAT(name)   LIQUID_CONCAT(quantizercf, name)
+#define LIQUID_QUANTIZER_MANGLE_FLOAT(name)  LIQUID_CONCAT(quantizerf,  name)
+#define LIQUID_QUANTIZER_MANGLE_CFLOAT(name) LIQUID_CONCAT(quantizercf, name)
 
 // large macro
 //   QUANTIZER  : name-mangling macro
@@ -6404,10 +6594,10 @@ void QUANTIZER(_execute_adc)(QUANTIZER() _q,                    \
                              unsigned int * _sample);           \
 void QUANTIZER(_execute_dac)(QUANTIZER() _q,                    \
                              unsigned int _sample,              \
-                             T * _x);
+                             T * _x);                           \
 
-LIQUID_QUANTIZER_DEFINE_API(QUANTIZER_MANGLE_FLOAT,  float)
-LIQUID_QUANTIZER_DEFINE_API(QUANTIZER_MANGLE_CFLOAT, liquid_float_complex)
+LIQUID_QUANTIZER_DEFINE_API(LIQUID_QUANTIZER_MANGLE_FLOAT,  float)
+LIQUID_QUANTIZER_DEFINE_API(LIQUID_QUANTIZER_MANGLE_CFLOAT, liquid_float_complex)
 
 
 //
@@ -6793,8 +6983,8 @@ unsigned int  liquid_reverse_uint32(unsigned int  _x);
 // MODULE : vector
 //
 
-#define VECTOR_MANGLE_RF(name)  LIQUID_CONCAT(liquid_vectorf, name)
-#define VECTOR_MANGLE_CF(name)  LIQUID_CONCAT(liquid_vectorcf,name)
+#define LIQUID_VECTOR_MANGLE_RF(name) LIQUID_CONCAT(liquid_vectorf, name)
+#define LIQUID_VECTOR_MANGLE_CF(name) LIQUID_CONCAT(liquid_vectorcf,name)
 
 // large macro
 //   VECTOR     : name-mangling macro
@@ -6860,8 +7050,8 @@ void VECTOR(_normalize)(T *          _x,                        \
                         unsigned int _n,                        \
                         T *          _y);                       \
 
-LIQUID_VECTOR_DEFINE_API(VECTOR_MANGLE_RF, float,                float);
-LIQUID_VECTOR_DEFINE_API(VECTOR_MANGLE_CF, liquid_float_complex, float);
+LIQUID_VECTOR_DEFINE_API(LIQUID_VECTOR_MANGLE_RF, float,                float)
+LIQUID_VECTOR_DEFINE_API(LIQUID_VECTOR_MANGLE_CF, liquid_float_complex, float)
 
 // 
 // mixed types
diff --git a/include/liquid.internal.h b/include/liquid.internal.h
index 32547cd..8d6d4f1 100644
--- a/include/liquid.internal.h
+++ b/include/liquid.internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2016 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -570,6 +570,7 @@ unsigned int fec_rs_get_enc_msg_len(unsigned int _dec_msg_len,
 
 
 fec fec_rs_create(fec_scheme _fs);
+void fec_rs_destroy(fec _q);
 void fec_rs_init_p8(fec _q);
 void fec_rs_setlength(fec _q,
                       unsigned int _dec_msg_len);
@@ -802,12 +803,12 @@ float estimate_req_filter_len_Herrmann(float _df,
 #define LIQUID_FIRFARROW_DEFINE_INTERNAL_API(FIRFARROW,TO,TC,TI)  \
 void FIRFARROW(_genpoly)(FIRFARROW() _q);
 
-LIQUID_FIRFARROW_DEFINE_INTERNAL_API(FIRFARROW_MANGLE_RRRF,
+LIQUID_FIRFARROW_DEFINE_INTERNAL_API(LIQUID_FIRFARROW_MANGLE_RRRF,
                                      float,
                                      float,
                                      float)
 
-LIQUID_FIRFARROW_DEFINE_INTERNAL_API(FIRFARROW_MANGLE_CRCF,
+LIQUID_FIRFARROW_DEFINE_INTERNAL_API(LIQUID_FIRFARROW_MANGLE_CRCF,
                                      liquid_float_complex,
                                      float,
                                      liquid_float_complex)
@@ -817,24 +818,13 @@ LIQUID_FIRFARROW_DEFINE_INTERNAL_API(FIRFARROW_MANGLE_CRCF,
 // 
 // iirfiltsos : infinite impulse respone filter (second-order sections)
 //
-#define IIRFILTSOS_MANGLE_RRRF(name)  LIQUID_CONCAT(iirfiltsos_rrrf,name)
-#define IIRFILTSOS_MANGLE_CRCF(name)  LIQUID_CONCAT(iirfiltsos_crcf,name)
-#define IIRFILTSOS_MANGLE_CCCF(name)  LIQUID_CONCAT(iirfiltsos_cccf,name)
+#define LIQUID_IIRFILTSOS_MANGLE_RRRF(name)  LIQUID_CONCAT(iirfiltsos_rrrf,name)
+#define LIQUID_IIRFILTSOS_MANGLE_CRCF(name)  LIQUID_CONCAT(iirfiltsos_crcf,name)
+#define LIQUID_IIRFILTSOS_MANGLE_CCCF(name)  LIQUID_CONCAT(iirfiltsos_cccf,name)
 
 #define LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(IIRFILTSOS,TO,TC,TI)  \
 typedef struct IIRFILTSOS(_s) * IIRFILTSOS();                   \
                                                                 \
-/* filter structure */                                          \
-struct IIRFILTSOS(_s) {                                         \
-    TC b[3];    /* feed-forward coefficients                */  \
-    TC a[3];    /* feed-back coefficients                   */  \
-                                                                \
-    /* internal buffering                                   */  \
-    TI x[3];    /* Direct form I  buffer (input)            */  \
-    TO y[3];    /* Direct form I  buffer (output)           */  \
-    TO v[3];    /* Direct form II buffer                    */  \
-};                                                              \
-                                                                \
 /* create 2nd-order infinite impulse reponse filter         */  \
 /*  _b      : feed-forward coefficients [size: _3 x 1]      */  \
 /*  _a      : feed-back coefficients    [size: _3 x 1]      */  \
@@ -888,17 +878,17 @@ void IIRFILTSOS(_execute_df2)(IIRFILTSOS() _q,                  \
 float IIRFILTSOS(_groupdelay)(IIRFILTSOS() _q,                  \
                               float        _fc);                \
 
-LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(IIRFILTSOS_MANGLE_RRRF,
+LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(LIQUID_IIRFILTSOS_MANGLE_RRRF,
                                       float,
                                       float,
                                       float)
 
-LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(IIRFILTSOS_MANGLE_CRCF,
+LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(LIQUID_IIRFILTSOS_MANGLE_CRCF,
                                       liquid_float_complex,
                                       float,
                                       liquid_float_complex)
 
-LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(IIRFILTSOS_MANGLE_CCCF,
+LIQUID_IIRFILTSOS_DEFINE_INTERNAL_API(LIQUID_IIRFILTSOS_MANGLE_CCCF,
                                       liquid_float_complex,
                                       liquid_float_complex,
                                       liquid_float_complex)
@@ -988,28 +978,6 @@ void liquid_firdes_farcsech_freqresponse(unsigned int _k,
                                          float        _beta,
                                          float *      _H);
 
-
-
-// initialize the frequency grid on the disjoint bounded set
-void firdespm_init_grid(firdespm _q);
-
-// compute interpolating polynomial
-void firdespm_compute_interp(firdespm _q);
-
-// compute error signal from actual response (interpolator
-// output), desired response, and weights
-void firdespm_compute_error(firdespm _q);
-
-// search error curve for _r+1 extremal indices
-void firdespm_iext_search(firdespm _q);
-
-// evaluates result to determine if Remez exchange algorithm
-// has converged
-int firdespm_is_search_complete(firdespm _q);
-
-// compute filter taps (coefficients) from result
-void firdespm_compute_taps(firdespm _q, float * _h);
-
 // iirdes : infinite impulse response filter design
 
 // Sorts array _z of complex numbers into complex conjugate pairs to
@@ -1219,11 +1187,11 @@ T    MATRIX(_det2x2)(T * _x,                                    \
                      unsigned int _cx);
 
 
-LIQUID_MATRIX_DEFINE_INTERNAL_API(MATRIX_MANGLE_FLOAT,   float)
-LIQUID_MATRIX_DEFINE_INTERNAL_API(MATRIX_MANGLE_DOUBLE,  double)
+LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_FLOAT,   float)
+LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_DOUBLE,  double)
 
-LIQUID_MATRIX_DEFINE_INTERNAL_API(MATRIX_MANGLE_CFLOAT,  liquid_float_complex)
-LIQUID_MATRIX_DEFINE_INTERNAL_API(MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
+LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_CFLOAT,  liquid_float_complex)
+LIQUID_MATRIX_DEFINE_INTERNAL_API(LIQUID_MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
 
 
 // sparse 'alist' matrix type (similar to MacKay, Davey Lafferty convention)
@@ -1235,9 +1203,9 @@ LIQUID_MATRIX_DEFINE_INTERNAL_API(MATRIX_MANGLE_CDOUBLE, liquid_double_complex)
 void SMATRIX(_reset_max_mlist)(SMATRIX() _q);                   \
 void SMATRIX(_reset_max_nlist)(SMATRIX() _q);                   \
 
-LIQUID_SMATRIX_DEFINE_INTERNAL_API(SMATRIX_MANGLE_BOOL,  unsigned char)
-LIQUID_SMATRIX_DEFINE_INTERNAL_API(SMATRIX_MANGLE_FLOAT, float)
-LIQUID_SMATRIX_DEFINE_INTERNAL_API(SMATRIX_MANGLE_INT,   short int)
+LIQUID_SMATRIX_DEFINE_INTERNAL_API(LIQUID_SMATRIX_MANGLE_BOOL,  unsigned char)
+LIQUID_SMATRIX_DEFINE_INTERNAL_API(LIQUID_SMATRIX_MANGLE_FLOAT, float)
+LIQUID_SMATRIX_DEFINE_INTERNAL_API(LIQUID_SMATRIX_MANGLE_INT,   short int)
 
 // search for index placement in list
 unsigned short int smatrix_indexsearch(unsigned short int * _list,
@@ -1559,7 +1527,7 @@ void NCO(_compute_sincos_vco)(NCO() _q);                        \
 void NCO(_pll_reset)(NCO() _q);                                 \
 
 // Define nco internal APIs
-LIQUID_NCO_DEFINE_INTERNAL_API(NCO_MANGLE_FLOAT,
+LIQUID_NCO_DEFINE_INTERNAL_API(LIQUID_NCO_MANGLE_FLOAT,
                                float,
                                float complex)
 
diff --git a/makefile.in b/makefile.in
index 5ab57c4..ac47bc2 100644
--- a/makefile.in
+++ b/makefile.in
@@ -59,15 +59,16 @@ MV		:= mv -f
 RM		:= rm -f
 SED		:= @SED@
 GREP		:= @GREP@
-AR		:= ar
-RANLIB		:= ranlib
+AR		:= @AR@
+RANLIB		:= @RANLIB@
 
 # flags
-INCLUDE_CFLAGS	= $(addprefix -I ,$(include_dirs))
-CONFIG_CFLAGS	= @CFLAGS@ @DEBUG_OPTION@ @ARCH_OPTION@
-# -g : debugging info
-CFLAGS		+= $(INCLUDE_CFLAGS) -Wall -fPIC $(CONFIG_CFLAGS)
-LDFLAGS		+= @LDFLAGS@ @LIBS@
+INCLUDE_CFLAGS	= $(addprefix -I,$(include_dirs))
+CONFIG_CFLAGS	= @CFLAGS@ @DEBUG_MSG_OPTION@ @ARCH_OPTION@
+CPPFLAGS	= @CPPFLAGS@ $(INCLUDE_CFLAGS)
+CFLAGS		= $(CONFIG_CFLAGS) -Wall -fPIC
+LDFLAGS		= @LDFLAGS@
+LIBS		= @LIBS@
 ARFLAGS		= r
 PATHSEP		= /
 
@@ -340,8 +341,8 @@ src/fft/src/dct.o           : %.o : %.c $(include_headers)
 src/fft/src/fftf.o          : %.o : %.c $(include_headers)
 src/fft/src/fft_utilities.o : %.o : %.c $(include_headers)
 src/fft/src/mdct.o          : %.o : %.c $(include_headers)
-src/fft/src/spgramcf.o      : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c
-src/fft/src/spgramf.o       : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c
+src/fft/src/spgramcf.o      : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c
+src/fft/src/spgramf.o       : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c
 
 # fft autotest scripts
 fft_autotests :=						\
@@ -650,6 +651,7 @@ framing_benchmarks :=						\
 	src/framing/bench/flexframesync_benchmark.c		\
 	src/framing/bench/framesync64_benchmark.c		\
 	src/framing/bench/gmskframesync_benchmark.c		\
+	src/framing/bench/qdetector_benchmark.c			\
 
 
 # 
@@ -1162,11 +1164,11 @@ libliquid.a: $(objects)
 #
 # gcc -dynamiclib -install_name libliquid.dylib -o libliquid.dylib libmodem.a libutility.a 
 libliquid.dylib: $(objects)
-	$(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS)
+	$(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS) $(LIBS)
 
 # linux, et al
 libliquid.so: libliquid.a
-	$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LDFLAGS)
+	$(CC) $(CFLAGS) $(LDFLAGS) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LIBS)
 
 all: libliquid.a $(SHARED_LIB)
 
@@ -1222,10 +1224,10 @@ uninstall:
 autoscript : scripts/autoscript
 
 scripts/autoscript.o scripts/main.o : %.o : %.c
-	$(CC) $(CFLAGS) -c -o $@ $<
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
 
 scripts/autoscript : scripts/autoscript.o scripts/main.o
-	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 clean-autoscript :
 	$(RM) scripts/autoscript.o scripts/main.o scripts/autoscript
@@ -1251,23 +1253,23 @@ autotest_include.h : scripts/autoscript $(autotest_sources) $(include_headers)
 #       the '-x c' flag
 autotest_obj = $(patsubst %.c,%.o,$(autotest_sources))
 $(autotest_obj) : %.o : %.c $(include_headers)
-	$(CC) $(CFLAGS) $< -c -o $@
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
 
 # additional autotest objects
 $(autotest_extra_obj) : %.o : %.c $(include_headers)
 
 # compile the autotest internal library functions without linking
 autotest/autotestlib.o : autotest/autotestlib.c autotest/autotest.h
-	$(CC) $(CFLAGS) $< -c -o $@
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
 
 # compile the autotest program without linking
 $(autotest_prog).o : autotest/autotest.c autotest/autotest.h autotest_include.h
-	$(CC) $(CFLAGS) $< -c -o $@
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
 
 # link the autotest program with the objects
 # NOTE: linked libraries must come _after_ the target program
 $(autotest_prog): $(autotest_prog).o $(autotest_obj) $(autotest_extra_obj) autotest/autotestlib.o libliquid.a
-	$(CC) $^ -o $@ $(LDFLAGS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
 
 # run the autotest program
 check: $(autotest_prog)
@@ -1292,8 +1294,10 @@ clean-check:
 # on the target platform.
 .PHONY: bench
 bench_prog	= benchmark
-BENCH_CFLAGS	= -Wall $(INCLUDE_CFLAGS) $(CONFIG_CFLAGS)
+BENCH_CPPFLAGS	= $(CPPFLAGS)
+BENCH_CFLAGS	= -Wall $(CFLAGS)
 BENCH_LDFLAGS	= $(LDFLAGS)
+BENCH_LIBS	= $(LIBS)
 
 # run the benchmark generator script to create benchmark_include.h
 benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers)
@@ -1305,19 +1309,19 @@ benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers)
 #       the '-x c' flag
 benchmark_obj = $(patsubst %.c,%.o,$(benchmark_sources))
 $(benchmark_obj) : %.o : %.c $(include_headers)
-	$(CC) $(BENCH_CFLAGS) $< -c -o $@
+	$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@
 
 # additional benchmark objects
 $(benchmark_extra_obj) : %.o : %.c $(include_headers)
 
 # compile the benchmark program without linking
 $(bench_prog).o: bench/bench.c benchmark_include.h bench/bench.c
-	$(CC) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o
+	$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o
 
 # link the benchmark program with the library objects
 # NOTE: linked libraries must come _after_ the target program
 $(bench_prog): $(bench_prog).o $(benchmark_obj) $(benchmark_extra_obj) libliquid.a
-	$(CC) $^ -o $(bench_prog) $(BENCH_LDFLAGS)
+	$(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $(bench_prog) $(BENCH_LIBS)
 
 # run the benchmark program
 bench: $(bench_prog)
@@ -1325,14 +1329,14 @@ bench: $(bench_prog)
 
 # benchmark compare script
 scripts/benchmark_compare : % : %.c
-	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
 
 # fftbench program
 bench/fftbench.o : %.o : %.c
-	$(CC) $(BENCH_CFLAGS) $< -c -o $@
+	$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@
 
 bench/fftbench : % : %.o libliquid.a
-	$(CC) $^ -o $@ $(BENCH_LDFLAGS)
+	$(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $@ $(BENCH_LIBS)
 
 # clean up the generated files
 clean-bench:
@@ -1350,6 +1354,7 @@ clean-bench:
 .PHONY: examples
 example_programs :=						\
 	examples/agc_crcf_example				\
+	examples/agc_crcf_squelch_example			\
 	examples/agc_crcf_qpsk_example				\
 	examples/agc_rrrf_example				\
 	examples/ampmodem_example				\
@@ -1389,7 +1394,9 @@ example_programs :=						\
 	examples/firfilt_crcf_example				\
 	examples/firfilt_rrrf_example				\
 	examples/firdes_kaiser_example				\
+	examples/firdespm_callback_example			\
 	examples/firdespm_example				\
+	examples/firdespm_lowpass_example			\
 	examples/firhilb_example				\
 	examples/firhilb_decim_example				\
 	examples/firhilb_interp_example				\
@@ -1466,6 +1473,7 @@ example_programs :=						\
 	examples/spgramcf_example				\
 	examples/spgramcf_waterfall_example			\
 	examples/spgramf_example				\
+	examples/spwaterfallcf_example				\
 	examples/symsync_crcf_example				\
 	examples/symsync_crcf_full_example			\
 	examples/symsync_crcf_kaiser_example			\
@@ -1482,13 +1490,11 @@ example_programs :=						\
 example_objects	= $(patsubst %,%.o,$(example_programs))
 examples: $(example_programs)
 
-EXAMPLES_LDFLAGS = $(LDFLAGS)
-
 # NOTE: linked libraries must come _after_ the target program
 $(example_objects): %.o : %.c
 
 $(example_programs): % : %.o libliquid.a
-	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
 
 # clean examples
 clean-examples:
@@ -1610,7 +1616,7 @@ SANDBOX_LDFLAGS = $(LDFLAGS) -lfftw3f
 $(sandbox_objects): %.o : %.c
 
 $(sandbox_programs): % : %.o libliquid.a
-	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
+	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(LIBS)
 
 # clean sandbox
 clean-sandbox:
diff --git a/scripts/ax_ext.m4 b/scripts/ax_ext.m4
index a946c88..78ad90b 100644
--- a/scripts/ax_ext.m4
+++ b/scripts/ax_ext.m4
@@ -50,9 +50,14 @@ AC_DEFUN([AX_EXT],
   AC_REQUIRE([AX_GCC_X86_CPUID])
 
   AX_GCC_X86_CPUID(0x00000001)
-  ecx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3`
-  edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4`
- 
+  ecx=0
+  edx=0
+  if test "$ax_cv_gcc_x86_cpuid_0x00000001" != "unknown";
+  then
+     ecx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3`
+     edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4`
+  fi
+
  AC_CHECK_HEADERS(mmintrin.h xmmintrin.h emmintrin.h pmmintrin.h tmmintrin.h smmintrin.h immintrin.h)
 
  AC_CACHE_CHECK([whether mmx is supported], [ax_cv_have_mmx_ext],
diff --git a/scripts/config.guess b/scripts/config.guess
index c2246a4..6c32c86 100755
--- a/scripts/config.guess
+++ b/scripts/config.guess
@@ -1,14 +1,12 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-#   Free Software Foundation, Inc.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
 
-timestamp='2009-12-30'
+timestamp='2014-11-04'
 
 # This file 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
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 #
 # This program is distributed in the hope that it will be useful, but
@@ -17,26 +15,22 @@ timestamp='2009-12-30'
 # 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.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-
-# Originally written by Per Bothner.  Please send patches (context
-# diff format) to <config-patches at gnu.org> and include a ChangeLog
-# entry.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 #
-# This script attempts to guess a canonical system name similar to
-# config.sub.  If it succeeds, it prints the system name on stdout, and
-# exits with 0.  Otherwise, it exits with 1.
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
 # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to <config-patches at gnu.org>.
+
 
 me=`echo "$0" | sed -e 's,.*/,,'`
 
@@ -56,9 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
-Software Foundation, Inc.
+Copyright 1992-2014 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -140,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:NetBSD:*:*)
 	# NetBSD (nbsd) targets should (where applicable) match one or
-	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
 	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
 	# switched to ELF, *-*-netbsd* would select the old
 	# object file format.  This provides both forward
@@ -181,7 +194,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		fi
 		;;
 	    *)
-	        os=netbsd
+		os=netbsd
 		;;
 	esac
 	# The OS release
@@ -202,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
 	echo "${machine}-${os}${release}"
 	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
     *:OpenBSD:*:*)
 	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
 	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
@@ -224,7 +241,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
 		;;
 	*5.*)
-	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
 		;;
 	esac
 	# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -270,7 +287,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
 	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit ;;
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# Should we change UNAME_MACHINE based on the output of uname instead
@@ -296,12 +316,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	echo s390-ibm-zvmoe
 	exit ;;
     *:OS400:*:*)
-        echo powerpc-ibm-os400
+	echo powerpc-ibm-os400
 	exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
 	exit ;;
-    arm:riscos:*:*|arm:RISCOS:*:*)
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
 	echo arm-unknown-riscos
 	exit ;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
@@ -395,23 +415,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
 	echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+	exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
     m68k:machten:*:*)
 	echo m68k-apple-machten${UNAME_RELEASE}
 	exit ;;
@@ -481,8 +501,8 @@ EOF
 	echo m88k-motorola-sysv3
 	exit ;;
     AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
 	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
 	then
 	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -495,7 +515,7 @@ EOF
 	else
 	    echo i586-dg-dgux${UNAME_RELEASE}
 	fi
- 	exit ;;
+	exit ;;
     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
 	echo m88k-dolphin-sysv3
 	exit ;;
@@ -552,15 +572,16 @@ EOF
 		echo rs6000-ibm-aix3.2
 	fi
 	exit ;;
-    *:AIX:*:[456])
+    *:AIX:*:[4567])
 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
 	else
 		IBM_ARCH=powerpc
 	fi
-	if [ -x /usr/bin/oslevel ] ; then
-		IBM_REV=`/usr/bin/oslevel`
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
 	else
 		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
 	fi
@@ -595,52 +616,52 @@ EOF
 	    9000/[678][0-9][0-9])
 		if [ -x /usr/bin/getconf ]; then
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                    case "${sc_cpu_version}" in
-                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-                      532)                      # CPU_PA_RISC2_0
-                        case "${sc_kernel_bits}" in
-                          32) HP_ARCH="hppa2.0n" ;;
-                          64) HP_ARCH="hppa2.0w" ;;
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
 			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
-                        esac ;;
-                    esac
+			esac ;;
+		    esac
 		fi
 		if [ "${HP_ARCH}" = "" ]; then
 		    eval $set_cc_for_build
-		    sed 's/^              //' << EOF >$dummy.c
+		    sed 's/^		//' << EOF >$dummy.c
 
-              #define _HPUX_SOURCE
-              #include <stdlib.h>
-              #include <unistd.h>
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
 
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
 
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
 EOF
 		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -731,22 +752,22 @@ EOF
 	exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
 	echo c1-convex-bsd
-        exit ;;
+	exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
 	if getsysinfo -f scalar_acc
 	then echo c32-convex-bsd
 	else echo c2-convex-bsd
 	fi
-        exit ;;
+	exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
 	echo c34-convex-bsd
-        exit ;;
+	exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
 	echo c38-convex-bsd
-        exit ;;
+	exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
 	echo c4-convex-bsd
-        exit ;;
+	exit ;;
     CRAY*Y-MP:*:*:*)
 	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
@@ -770,14 +791,14 @@ EOF
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit ;;
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
     5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -789,30 +810,35 @@ EOF
 	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
 	exit ;;
     *:FreeBSD:*:*)
-	case ${UNAME_MACHINE} in
-	    pc98)
-		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
 	    amd64)
 		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	    *)
-		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	esac
 	exit ;;
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
     *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
+    *:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
     i*:windows32*:*)
-    	# uname -m includes "-pc" on this system.
-    	echo ${UNAME_MACHINE}-mingw32
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
 	exit ;;
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
     *:Interix*:*)
-    	case ${UNAME_MACHINE} in
+	case ${UNAME_MACHINE} in
 	    x86)
 		echo i586-pc-interix${UNAME_RELEASE}
 		exit ;;
@@ -849,15 +875,22 @@ EOF
 	exit ;;
     *:GNU:*:*)
 	# the GNU system
-	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
 	exit ;;
     *:GNU/*:*:*)
 	# other systems with GNU libc and userland
-	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
 	exit ;;
     i*86:Minix:*:*)
 	echo ${UNAME_MACHINE}-pc-minix
 	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
     alpha:Linux:*:*)
 	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
 	  EV5)   UNAME_MACHINE=alphaev5 ;;
@@ -867,52 +900,56 @@ EOF
 	  EV6)   UNAME_MACHINE=alphaev6 ;;
 	  EV67)  UNAME_MACHINE=alphaev67 ;;
 	  EV68*) UNAME_MACHINE=alphaev68 ;;
-        esac
+	esac
 	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
-	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     arm*:Linux:*:*)
 	eval $set_cc_for_build
 	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
 	    | grep -q __ARM_EABI__
 	then
-	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	else
-	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
 	fi
 	exit ;;
     avr32*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     cris:Linux:*:*)
-	echo cris-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
     crisv32:Linux:*:*)
-	echo crisv32-axis-linux-gnu
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
 	exit ;;
     frv:Linux:*:*)
-    	echo frv-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     i*86:Linux:*:*)
-	LIBC=gnu
-	eval $set_cc_for_build
-	sed 's/^	//' << EOF >$dummy.c
-	#ifdef __dietlibc__
-	LIBC=dietlibc
-	#endif
-EOF
-	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
-	echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
 	exit ;;
     ia64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m32r*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     m68*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     mips:Linux:*:* | mips64:Linux:*:*)
 	eval $set_cc_for_build
@@ -931,51 +968,63 @@ EOF
 	#endif
 EOF
 	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
 	;;
-    or32:Linux:*:*)
-	echo or32-unknown-linux-gnu
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     padre:Linux:*:*)
-	echo sparc-unknown-linux-gnu
+	echo sparc-unknown-linux-${LIBC}
 	exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-gnu
+	echo hppa64-unknown-linux-${LIBC}
 	exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
 	# Look for CPU level
 	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
-	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
-	  *)    echo hppa-unknown-linux-gnu ;;
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
 	esac
 	exit ;;
     ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-gnu
+	echo powerpc64-unknown-linux-${LIBC}
 	exit ;;
     ppc:Linux:*:*)
-	echo powerpc-unknown-linux-gnu
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
 	exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-	echo ${UNAME_MACHINE}-ibm-linux
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
 	exit ;;
     sh64*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sh*:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     vax:Linux:*:*)
-	echo ${UNAME_MACHINE}-dec-linux-gnu
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
 	exit ;;
     x86_64:Linux:*:*)
-	echo x86_64-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     xtensa*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
 	exit ;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -984,11 +1033,11 @@ EOF
 	echo i386-sequent-sysv4
 	exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
 	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
+	# Use sysv4.2uw... so that sysv4* matches it.
 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 	exit ;;
     i*86:OS/2:*:*)
@@ -1020,7 +1069,7 @@ EOF
 	fi
 	exit ;;
     i*86:*:5:[678]*)
-    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
 	case `/bin/uname -X | grep "^Machine"` in
 	    *486*)	     UNAME_MACHINE=i486 ;;
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
@@ -1048,13 +1097,13 @@ EOF
 	exit ;;
     pc:*:*:*)
 	# Left here for compatibility:
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i586.
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
 	# Note: whatever this is, it MUST be the same as what config.sub
 	# prints for the "djgpp" host, or else GDB configury will decide that
 	# this is a cross-build.
 	echo i586-pc-msdosdjgpp
-        exit ;;
+	exit ;;
     Intel:Mach:3*:*)
 	echo i386-pc-mach3
 	exit ;;
@@ -1089,8 +1138,8 @@ EOF
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
 	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && { echo i486-ncr-sysv4; exit; } ;;
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
     NCR*:*:4.2:* | MPRAS*:*:4.2:*)
 	OS_REL='.3'
 	test -r /etc/.relid \
@@ -1133,10 +1182,10 @@ EOF
 		echo ns32k-sni-sysv
 	fi
 	exit ;;
-    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                      # says <Richard.M.Bartel at ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel at ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes at openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
@@ -1162,11 +1211,11 @@ EOF
 	exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
 	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
+		echo mips-nec-sysv${UNAME_RELEASE}
 	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
+		echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
-        exit ;;
+	exit ;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
 	echo powerpc-be-beos
 	exit ;;
@@ -1179,6 +1228,9 @@ EOF
     BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
 	echo i586-pc-haiku
 	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
     SX-4:SUPER-UX:*:*)
 	echo sx4-nec-superux${UNAME_RELEASE}
 	exit ;;
@@ -1205,19 +1257,31 @@ EOF
 	exit ;;
     *:Darwin:*:*)
 	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-	case $UNAME_PROCESSOR in
-	    i386)
-		eval $set_cc_for_build
-		if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-		  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		      (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-		      grep IS_64BIT_ARCH >/dev/null
-		  then
-		      UNAME_PROCESSOR="x86_64"
-		  fi
-		fi ;;
-	    unknown) UNAME_PROCESSOR=powerpc ;;
-	esac
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
 	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
 	exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
@@ -1231,7 +1295,10 @@ EOF
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
 	echo nse-tandem-nsk${UNAME_RELEASE}
 	exit ;;
     NSR-?:NONSTOP_KERNEL:*:*)
@@ -1276,13 +1343,13 @@ EOF
 	echo pdp10-unknown-its
 	exit ;;
     SEI:*:*:SEIUX)
-        echo mips-sei-seiux${UNAME_RELEASE}
+	echo mips-sei-seiux${UNAME_RELEASE}
 	exit ;;
     *:DragonFly:*:*)
 	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit ;;
     *:*VMS:*:*)
-    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
 	case "${UNAME_MACHINE}" in
 	    A*) echo alpha-dec-vms ; exit ;;
 	    I*) echo ia64-dec-vms ; exit ;;
@@ -1300,158 +1367,10 @@ EOF
     i*86:AROS:*:*)
 	echo ${UNAME_MACHINE}-pc-aros
 	exit ;;
-esac
-
-#echo '(No uname command or uname output not recognized.)' 1>&2
-#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-
-eval $set_cc_for_build
-cat >$dummy.c <<EOF
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-          "4"
-#else
-	  ""
-#endif
-         ); exit (0);
-#endif
-#endif
-
-#if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
-#endif
-
-#if defined (hp300) && !defined (hpux)
-  printf ("m68k-hp-bsd\n"); exit (0);
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-    struct utsname un;
-
-    uname(&un);
-
-    if (strncmp(un.version, "V2", 2) == 0) {
-	printf ("i386-sequent-ptx2\n"); exit (0);
-    }
-    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-	printf ("i386-sequent-ptx1\n"); exit (0);
-    }
-    printf ("i386-sequent-ptx\n"); exit (0);
-
-#endif
-
-#if defined (vax)
-# if !defined (ultrix)
-#  include <sys/param.h>
-#  if defined (BSD)
-#   if BSD == 43
-      printf ("vax-dec-bsd4.3\n"); exit (0);
-#   else
-#    if BSD == 199006
-      printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#    else
-      printf ("vax-dec-bsd\n"); exit (0);
-#    endif
-#   endif
-#  else
-    printf ("vax-dec-bsd\n"); exit (0);
-#  endif
-# else
-    printf ("vax-dec-ultrix\n"); exit (0);
-# endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
-	{ echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
-
-# Convex versions that predate uname can use getsysinfo(1)
-
-if [ -x /usr/convex/getsysinfo ]
-then
-    case `getsysinfo -f cpu_type` in
-    c1*)
-	echo c1-convex-bsd
-	exit ;;
-    c2*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
 	exit ;;
-    c34*)
-	echo c34-convex-bsd
-	exit ;;
-    c38*)
-	echo c38-convex-bsd
-	exit ;;
-    c4*)
-	echo c4-convex-bsd
-	exit ;;
-    esac
-fi
+esac
 
 cat >&2 <<EOF
 $0: unable to guess system type
diff --git a/scripts/config.sub b/scripts/config.sub
index c2d1257..7ffe373 100755
--- a/scripts/config.sub
+++ b/scripts/config.sub
@@ -1,38 +1,31 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-#   Free Software Foundation, Inc.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
 
-timestamp='2010-01-22'
+timestamp='2014-12-03'
 
-# This file is (in principle) common to ALL GNU software.
-# The presence of a machine in this file suggests that SOME GNU software
-# can handle that machine.  It does not imply ALL GNU software can.
-#
-# This file 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
+# This file 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 3 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.
+# 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.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
 
 
-# Please send patches to <config-patches at gnu.org>.  Submit a context
-# diff and a properly formatted GNU ChangeLog entry.
+# Please send patches to <config-patches at gnu.org>.
 #
 # Configuration subroutine to validate and canonicalize a configuration type.
 # Supply the specified configuration type as an argument.
@@ -75,9 +68,7 @@ Report bugs and patches to <config-patches at gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
-Software Foundation, Inc.
+Copyright 1992-2014 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -124,13 +115,18 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
-  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
   kopensolaris*-gnu* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
   *)
     basic_machine=`echo $1 | sed 's/-[^-]*$//'`
     if [ $basic_machine != $1 ]
@@ -153,12 +149,12 @@ case $os in
 	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
 	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
 	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-	-apple | -axis | -knuth | -cray | -microblaze)
+	-apple | -axis | -knuth | -cray | -microblaze*)
 		os=
 		basic_machine=$1
 		;;
-        -bluegene*)
-	        os=-cnk
+	-bluegene*)
+		os=-cnk
 		;;
 	-sim | -cisco | -oki | -wec | -winbond)
 		os=
@@ -174,10 +170,10 @@ case $os in
 		os=-chorusos
 		basic_machine=$1
 		;;
- 	-chorusrdb)
- 		os=-chorusrdb
+	-chorusrdb)
+		os=-chorusrdb
 		basic_machine=$1
- 		;;
+		;;
 	-hiux*)
 		os=-hiuxwe2
 		;;
@@ -222,6 +218,12 @@ case $os in
 	-isc*)
 		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
 		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
 	-lynx*)
 		os=-lynxos
 		;;
@@ -246,20 +248,28 @@ case $basic_machine in
 	# Some are omitted here because they have special meanings below.
 	1750a | 580 \
 	| a29k \
+	| aarch64 | aarch64_be \
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| be32 | be64 \
 	| bfin \
-	| c4x | clipper \
+	| c4x | c8051 | clipper \
 	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
 	| fido | fr30 | frv \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
 	| lm32 \
 	| m32c | m32r | m32rle | m68000 | m68k | m88k \
-	| maxq | mb | microblaze | mcore | mep | metag \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
@@ -273,38 +283,55 @@ case $basic_machine in
 	| mips64vr5900 | mips64vr5900el \
 	| mipsisa32 | mipsisa32el \
 	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
 	| mipsisa64 | mipsisa64el \
 	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
 	| mipsisa64sb1 | mipsisa64sb1el \
 	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
 	| mipstx39 | mipstx39el \
 	| mn10200 | mn10300 \
 	| moxie \
 	| mt \
 	| msp430 \
-	| nios | nios2 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
 	| ns16k | ns32k \
-	| or32 \
+	| open8 | or1k | or1knd | or32 \
 	| pdp10 | pdp11 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
-	| rx \
+	| riscv32 | riscv64 \
+	| rl78 | rx \
 	| score \
 	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu | strongarm \
-	| tahoe | thumb | tic4x | tic80 | tron \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
 	| ubicom32 \
-	| v850 | v850e \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
 	| we32k \
-	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
 		basic_machine=$basic_machine-unknown
 		;;
-	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
-		# Motorola 68HC11/12.
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
 		basic_machine=$basic_machine-unknown
 		os=-none
 		;;
@@ -314,6 +341,21 @@ case $basic_machine in
 		basic_machine=mt-unknown
 		;;
 
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
@@ -328,25 +370,31 @@ case $basic_machine in
 	# Recognize the basic CPU types with company name.
 	580-* \
 	| a29k-* \
+	| aarch64-* | aarch64_be-* \
 	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
+	| be32-* | be64-* \
 	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
-	| clipper-* | craynv-* | cydra-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
 	| lm32-* \
 	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
 	| mips16-* \
 	| mips64-* | mips64el-* \
@@ -360,34 +408,42 @@ case $basic_machine in
 	| mips64vr5900-* | mips64vr5900el-* \
 	| mipsisa32-* | mipsisa32el-* \
 	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
 	| mipsisa64-* | mipsisa64el-* \
 	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
 	| mipsisa64sb1-* | mipsisa64sb1el-* \
 	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
 	| mipstx39-* | mipstx39el-* \
 	| mmix-* \
 	| mt-* \
 	| msp430-* \
-	| nios-* | nios2-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| or1k*-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
 	| pyramid-* \
-	| romp-* | rs6000-* | rx-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
-	| tahoe-* | thumb-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
-	| tile-* | tilegx-* \
+	| tile*-* \
 	| tron-* \
 	| ubicom32-* \
-	| v850-* | v850e-* | vax-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| visium-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
 	| ymp-* \
 	| z8k-* | z80-*)
@@ -412,7 +468,7 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
-    	abacus)
+	abacus)
 		basic_machine=abacus-unknown
 		;;
 	adobe68k)
@@ -482,11 +538,20 @@ case $basic_machine in
 		basic_machine=powerpc-ibm
 		os=-cnk
 		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	c90)
 		basic_machine=c90-cray
 		os=-unicos
 		;;
-        cegcc)
+	cegcc)
 		basic_machine=arm-unknown
 		os=-cegcc
 		;;
@@ -518,7 +583,7 @@ case $basic_machine in
 		basic_machine=craynv-cray
 		os=-unicosmp
 		;;
-	cr16)
+	cr16 | cr16-*)
 		basic_machine=cr16-unknown
 		os=-elf
 		;;
@@ -676,7 +741,6 @@ case $basic_machine in
 	i370-ibm* | ibm*)
 		basic_machine=i370-ibm
 		;;
-# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
 	i*86v32)
 		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
 		os=-sysv32
@@ -715,6 +779,9 @@ case $basic_machine in
 		basic_machine=m68k-isi
 		os=-sysv
 		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+		;;
 	m68knommu)
 		basic_machine=m68k-unknown
 		os=-linux
@@ -734,11 +801,15 @@ case $basic_machine in
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
-        microblaze)
+	microblaze*)
 		basic_machine=microblaze-xilinx
 		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
 	mingw32)
-		basic_machine=i386-pc
+		basic_machine=i686-pc
 		os=-mingw32
 		;;
 	mingw32ce)
@@ -766,6 +837,10 @@ case $basic_machine in
 		basic_machine=powerpc-unknown
 		os=-morphos
 		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
 	msdos)
 		basic_machine=i386-pc
 		os=-msdos
@@ -773,10 +848,18 @@ case $basic_machine in
 	ms1-*)
 		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
 		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
 	mvs)
 		basic_machine=i370-ibm
 		os=-mvs
 		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
 	ncr3000)
 		basic_machine=i486-ncr
 		os=-sysv4
@@ -841,6 +924,12 @@ case $basic_machine in
 	np1)
 		basic_machine=np1-gould
 		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
@@ -923,9 +1012,10 @@ case $basic_machine in
 		;;
 	power)	basic_machine=power-ibm
 		;;
-	ppc)	basic_machine=powerpc-unknown
+	ppc | ppcbe)	basic_machine=powerpc-unknown
 		;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppcle | powerpclittle | ppc-le | powerpc-little)
 		basic_machine=powerpcle-unknown
@@ -950,7 +1040,11 @@ case $basic_machine in
 		basic_machine=i586-unknown
 		os=-pw32
 		;;
-	rdos)
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
 		basic_machine=i386-pc
 		os=-rdos
 		;;
@@ -1019,6 +1113,9 @@ case $basic_machine in
 		basic_machine=i860-stratus
 		os=-sysv4
 		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	sun2)
 		basic_machine=m68000-sun
 		;;
@@ -1075,25 +1172,8 @@ case $basic_machine in
 		basic_machine=t90-cray
 		os=-unicos
 		;;
-	tic54x | c54x*)
-		basic_machine=tic54x-unknown
-		os=-coff
-		;;
-	tic55x | c55x*)
-		basic_machine=tic55x-unknown
-		os=-coff
-		;;
-	tic6x | c6x*)
-		basic_machine=tic6x-unknown
-		os=-coff
-		;;
-        # This must be matched before tile*.
-        tilegx*)
-		basic_machine=tilegx-unknown
-		os=-linux-gnu
-		;;
 	tile*)
-		basic_machine=tile-unknown
+		basic_machine=$basic_machine-unknown
 		os=-linux-gnu
 		;;
 	tx39)
@@ -1163,6 +1243,9 @@ case $basic_machine in
 	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
 	ymp)
 		basic_machine=ymp-cray
 		os=-unicos
@@ -1260,11 +1343,11 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
+	# First match some system type aliases
+	# that might get confused with valid system types.
 	# -solaris* is a basic system type, with this one exception.
-        -auroraux)
-	        os=-auroraux
+	-auroraux)
+		os=-auroraux
 		;;
 	-solaris1 | -solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
@@ -1288,28 +1371,29 @@ case $os in
 	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
 	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
 	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
-	      | -sym* | -kopensolaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
 	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
 	      | -aos* | -aros* \
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* | -cegcc* \
-	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
-	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
 	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1348,7 +1432,7 @@ case $os in
 	-opened*)
 		os=-openedition
 		;;
-        -os400*)
+	-os400*)
 		os=-os400
 		;;
 	-wince*)
@@ -1397,7 +1481,7 @@ case $os in
 	-sinix*)
 		os=-sysv4
 		;;
-        -tpf*)
+	-tpf*)
 		os=-tpf
 		;;
 	-triton*)
@@ -1433,17 +1517,14 @@ case $os in
 	-aros*)
 		os=-aros
 		;;
-	-kaos*)
-		os=-kaos
-		;;
 	-zvmoe)
 		os=-zvmoe
 		;;
 	-dicos*)
 		os=-dicos
 		;;
-        -nacl*)
-	        ;;
+	-nacl*)
+		;;
 	-none)
 		;;
 	*)
@@ -1466,10 +1547,10 @@ else
 # system, and we'll never get to this point.
 
 case $basic_machine in
-        score-*)
+	score-*)
 		os=-elf
 		;;
-        spu-*)
+	spu-*)
 		os=-elf
 		;;
 	*-acorn)
@@ -1481,8 +1562,23 @@ case $basic_machine in
 	arm*-semi)
 		os=-aout
 		;;
-        c4x-* | tic4x-*)
-        	os=-coff
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
 		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
@@ -1502,14 +1598,11 @@ case $basic_machine in
 		;;
 	m68000-sun)
 		os=-sunos3
-		# This also exists in the configure program, but was not the
-		# default.
-		# os=-sunos4
 		;;
 	m68*-cisco)
 		os=-aout
 		;;
-        mep-*)
+	mep-*)
 		os=-elf
 		;;
 	mips*-cisco)
@@ -1536,7 +1629,7 @@ case $basic_machine in
 	*-ibm)
 		os=-aix
 		;;
-    	*-knuth)
+	*-knuth)
 		os=-mmixware
 		;;
 	*-wec)
diff --git a/src/agc/src/agc.c b/src/agc/src/agc.c
index 70a2c20..17b7b92 100644
--- a/src/agc/src/agc.c
+++ b/src/agc/src/agc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2015 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -33,6 +33,9 @@
 // default AGC loop bandwidth
 #define AGC_DEFAULT_BW   (1e-2f)
 
+// internal method definition
+void AGC(_squelch_update_mode)(AGC() _q);
+
 // agc structure object
 struct AGC(_s) {
     // gain variables
@@ -47,6 +50,16 @@ struct AGC(_s) {
 
     // AGC locked flag
     int is_locked;
+
+    // squelch mode
+    agc_squelch_mode squelch_mode;
+
+    // squelch threshold
+    T squelch_threshold;
+
+    // squelch timeout
+    unsigned int squelch_timeout;
+    unsigned int squelch_timer;
 };
 
 // create agc object
@@ -61,6 +74,11 @@ AGC() AGC(_create)(void)
     // reset object
     AGC(_reset)(_q);
 
+    // squelch
+    AGC(_squelch_disable)(_q);
+    AGC(_squelch_set_threshold)(_q, 0.0f);
+    AGC(_squelch_set_timeout  )(_q, 100);
+
     // return object
     return _q;
 }
@@ -75,7 +93,7 @@ void AGC(_destroy)(AGC() _q)
 // print agc object internals
 void AGC(_print)(AGC() _q)
 {
-    printf("agc [rssi: %12.4fdB]:\n", AGC(_get_rssi)(_q));
+    printf("agc [rssi: %12.4f dB]:\n", AGC(_get_rssi)(_q));
 }
 
 // reset agc object's internal state
@@ -89,6 +107,10 @@ void AGC(_reset)(AGC() _q)
 
     // unlock gain control
     AGC(_unlock)(_q);
+
+    // reset squelch state
+    _q->squelch_mode = (_q->squelch_mode == LIQUID_AGC_SQUELCH_DISABLED) ?
+        LIQUID_AGC_SQUELCH_DISABLED : LIQUID_AGC_SQUELCH_ENABLED;
 }
 
 // execute automatic gain control loop
@@ -119,6 +141,9 @@ void AGC(_execute)(AGC() _q,
     // clamp to 120 dB gain
     if (_q->g > 1e6f)
         _q->g = 1e6f;
+
+    // udpate squelch mode appropriately
+    AGC(_squelch_update_mode)(_q);
 }
 
 // execute automatic gain control on block of samples
@@ -268,3 +293,101 @@ void AGC(_init)(AGC()        _q,
     AGC(_set_signal_level)(_q, x2);
 }
 
+// enable squelch mode
+void AGC(_squelch_enable)(AGC() _q)
+{
+    _q->squelch_mode = LIQUID_AGC_SQUELCH_ENABLED;
+}
+
+// disable squelch mode
+void AGC(_squelch_disable)(AGC() _q)
+{
+    _q->squelch_mode = LIQUID_AGC_SQUELCH_DISABLED;
+}
+
+// is squelch enabled?
+int  AGC(_squelch_is_enabled)(AGC() _q)
+{
+    return _q->squelch_mode == LIQUID_AGC_SQUELCH_DISABLED ? 0 : 1;
+}
+
+// set squelch threshold
+//  _q          :   automatic gain control object
+//  _thresh_dB  :   threshold for enabling squelch [dB]
+void AGC(_squelch_set_threshold)(AGC() _q,
+                                 T     _threshold)
+{
+    _q->squelch_threshold = _threshold;
+}
+
+// get squelch threshold [dB]
+T AGC(_squelch_get_threshold)(AGC() _q)
+{
+    return _q->squelch_threshold;
+}
+
+// set squelch timeout
+//  _q       : automatic gain control object
+//  _timeout : timeout before enabling squelch [samples]
+void AGC(_squelch_set_timeout)(AGC()        _q,
+                               unsigned int _timeout)
+{
+    _q->squelch_timeout = _timeout;
+}
+
+// get squelch timeout [samples]
+unsigned int AGC(_squelch_get_timeout)(AGC() _q)
+{
+    return _q->squelch_timeout;
+}
+
+// get squelch mode
+int AGC(_squelch_get_status)(AGC() _q)
+{
+    return _q->squelch_mode;
+}
+
+//
+// internal methods
+//
+
+// update squelch mode appropriately
+void AGC(_squelch_update_mode)(AGC() _q)
+{
+    //
+    int threshold_exceeded = (AGC(_get_rssi)(_q) > _q->squelch_threshold);
+
+    // update state
+    switch (_q->squelch_mode) {
+    case LIQUID_AGC_SQUELCH_ENABLED:
+        _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_RISE : LIQUID_AGC_SQUELCH_ENABLED;
+        break;
+    case LIQUID_AGC_SQUELCH_RISE:
+        _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_SIGNALHI : LIQUID_AGC_SQUELCH_FALL;
+        break;
+    case LIQUID_AGC_SQUELCH_SIGNALHI:
+        _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_SIGNALHI : LIQUID_AGC_SQUELCH_FALL;
+        break;
+    case LIQUID_AGC_SQUELCH_FALL:
+        _q->squelch_mode = threshold_exceeded ? LIQUID_AGC_SQUELCH_SIGNALHI : LIQUID_AGC_SQUELCH_SIGNALLO;
+        _q->squelch_timer = _q->squelch_timeout;
+        break;
+    case LIQUID_AGC_SQUELCH_SIGNALLO:
+        _q->squelch_timer--;
+        if (_q->squelch_timer == 0)
+            _q->squelch_mode = LIQUID_AGC_SQUELCH_TIMEOUT;
+        else if (threshold_exceeded)
+            _q->squelch_mode = LIQUID_AGC_SQUELCH_SIGNALHI;
+        break;
+    case LIQUID_AGC_SQUELCH_TIMEOUT:
+        _q->squelch_mode = LIQUID_AGC_SQUELCH_ENABLED;
+        break;
+    case LIQUID_AGC_SQUELCH_DISABLED:
+        break;
+    case LIQUID_AGC_SQUELCH_UNKNOWN:
+    default:
+        fprintf(stderr,"warning: agc_%s_execute(), invalid squelch mode: %d\n",
+                EXTENSION_FULL, _q->squelch_mode);
+    }
+}
+
diff --git a/src/agc/tests/agc_crcf_autotest.c b/src/agc/tests/agc_crcf_autotest.c
index 0101416..dd0bb57 100644
--- a/src/agc/tests/agc_crcf_autotest.c
+++ b/src/agc/tests/agc_crcf_autotest.c
@@ -168,5 +168,60 @@ void autotest_agc_crcf_rssi_noise()
     agc_crcf_destroy(q);
 }
 
+// 
+// Test squelch functionality
+//
+void autotest_agc_crcf_squelch()
+{
+    // create agc object, set loop bandwidth, and initialize parameters
+    agc_crcf q = agc_crcf_create();
+    agc_crcf_set_bandwidth(q, 0.25);
+    agc_crcf_set_signal_level(q,1e-3f);     // initial guess at starting signal level
+
+    // initialize squelch functionality
+    agc_crcf_squelch_enable(q);             // enable squelch
+    agc_crcf_squelch_set_threshold(q, -50); // threshold for detection [dB]
+    agc_crcf_squelch_set_timeout  (q, 100); // timeout for hysteresis
+
+    // run agc
+    unsigned int num_samples = 2000; // total number of samples to run
+    unsigned int i;
+    for (i=0; i<num_samples; i++) {
+        // generate signal, applying tapering window appropriately
+        float gamma = 0.0f;
+        if      (i <  500) gamma = 1e-3f;
+        else if (i <  550) gamma = 1e-3f + (1e-2f - 1e-3f)*(0.5f - 0.5f*cosf(M_PI*(float)(i- 500)/50.0f));
+        else if (i < 1450) gamma = 1e-2f;
+        else if (i < 1500) gamma = 1e-3f + (1e-2f - 1e-3f)*(0.5f + 0.5f*cosf(M_PI*(float)(i-1450)/50.0f));
+        else               gamma = 1e-3f;
+        float complex x = gamma * cexpf(_Complex_I*2*M_PI*0.0193f*i);
+
+        // apply gain
+        float complex y;
+        agc_crcf_execute(q, x, &y);
+
+        // retrieve signal level [dB]
+        //rssi = agc_crcf_get_rssi(q);
+
+        // get squelch mode
+        int mode = agc_crcf_squelch_get_status(q);
+
+        // check certain conditions based on sample input (assuming 2000 samples)
+        switch (i) {
+            case    0: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_ENABLED);  break;
+            case  500: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_ENABLED);  break;
+            case  600: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_SIGNALHI); break;
+            case 1400: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_SIGNALHI); break;
+            case 1500: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_SIGNALLO); break;
+            case 1600: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_ENABLED);  break;
+            case 1900: CONTEND_EQUALITY(mode, LIQUID_AGC_SQUELCH_ENABLED);  break;
+            default:;
+        }
+    }
+
+    // destroy AGC object
+    agc_crcf_destroy(q);
+}
+
 
 
diff --git a/src/equalization/tests/eqlms_cccf_autotest.c b/src/equalization/tests/eqlms_cccf_autotest.c
index 598e05c..4d62303 100644
--- a/src/equalization/tests/eqlms_cccf_autotest.c
+++ b/src/equalization/tests/eqlms_cccf_autotest.c
@@ -66,8 +66,8 @@ void autotest_eqlms_cccf_blind()
     unsigned int j;
     for (i=0; i<num_symbols; i++) {
         // generate input symbol
-        sym_in[i] = ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 ) +
-                    ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 ) * _Complex_I;
+        sym_in[i]  = ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 );
+        sym_in[i] += ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 )*_Complex_I;
 
         // interpolate
         firinterp_crcf_execute(interp, sym_in[i], buf);
@@ -157,8 +157,8 @@ void autotest_eqlms_cccf_decisiondirected()
     unsigned int j;
     for (i=0; i<num_symbols; i++) {
         // generate input symbol
-        sym_in[i] = ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 ) +
-                    ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 ) * _Complex_I;
+        sym_in[i]  = ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 );
+        sym_in[i] += ( msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2 )*_Complex_I;
 
         // interpolate
         firinterp_crcf_execute(interp, sym_in[i], buf);
diff --git a/src/fec/src/fec.c b/src/fec/src/fec.c
index 2b92975..a70eb9b 100644
--- a/src/fec/src/fec.c
+++ b/src/fec/src/fec.c
@@ -587,7 +587,105 @@ fec fec_recreate(fec _q,
 // destroy fec object
 void fec_destroy(fec _q)
 {
-    free(_q);
+    switch (_q->scheme) {
+    case LIQUID_FEC_UNKNOWN:
+        printf("error: fec_destroy(), cannot destroy fec object of type \"UNKNOWN\"\n");
+        exit(-1);
+    case LIQUID_FEC_NONE:
+        fec_pass_destroy(_q);
+        return;
+    case LIQUID_FEC_REP3:
+        fec_rep3_destroy(_q);
+        return;
+    case LIQUID_FEC_REP5:
+        fec_rep5_destroy(_q);
+        return;
+    case LIQUID_FEC_HAMMING74:
+        fec_hamming74_destroy(_q);
+        return;
+    case LIQUID_FEC_HAMMING84:
+        fec_hamming84_destroy(_q);
+        return;
+    case LIQUID_FEC_HAMMING128:
+        fec_hamming128_destroy(_q);
+        return;
+
+    case LIQUID_FEC_GOLAY2412:
+        fec_golay2412_destroy(_q);
+        return;
+
+    // SEC-DED codecs (single error correction, double error detection)
+    case LIQUID_FEC_SECDED2216:
+        fec_secded2216_destroy(_q);
+        return;
+    case LIQUID_FEC_SECDED3932:
+        fec_secded3932_destroy(_q);
+        return;
+    case LIQUID_FEC_SECDED7264:
+        fec_secded7264_destroy(_q);
+        return;
+
+    // convolutional codes
+#if LIBFEC_ENABLED
+    case LIQUID_FEC_CONV_V27:
+    case LIQUID_FEC_CONV_V29:
+    case LIQUID_FEC_CONV_V39:
+    case LIQUID_FEC_CONV_V615:
+        fec_conv_destroy(_q);
+        return;
+
+    // punctured
+    case LIQUID_FEC_CONV_V27P23:
+    case LIQUID_FEC_CONV_V27P34:
+    case LIQUID_FEC_CONV_V27P45:
+    case LIQUID_FEC_CONV_V27P56:
+    case LIQUID_FEC_CONV_V27P67:
+    case LIQUID_FEC_CONV_V27P78:
+
+    case LIQUID_FEC_CONV_V29P23:
+    case LIQUID_FEC_CONV_V29P34:
+    case LIQUID_FEC_CONV_V29P45:
+    case LIQUID_FEC_CONV_V29P56:
+    case LIQUID_FEC_CONV_V29P67:
+    case LIQUID_FEC_CONV_V29P78:
+        fec_conv_punctured_destroy(_q);
+        return;
+
+    // Reed-Solomon codes
+    case LIQUID_FEC_RS_M8:
+        fec_rs_destroy(_q);
+        return;
+#else
+    case LIQUID_FEC_CONV_V27:
+    case LIQUID_FEC_CONV_V29:
+    case LIQUID_FEC_CONV_V39:
+    case LIQUID_FEC_CONV_V615:
+
+    case LIQUID_FEC_CONV_V27P23:
+    case LIQUID_FEC_CONV_V27P34:
+    case LIQUID_FEC_CONV_V27P45:
+    case LIQUID_FEC_CONV_V27P56:
+    case LIQUID_FEC_CONV_V27P67:
+    case LIQUID_FEC_CONV_V27P78:
+
+    case LIQUID_FEC_CONV_V29P23:
+    case LIQUID_FEC_CONV_V29P34:
+    case LIQUID_FEC_CONV_V29P45:
+    case LIQUID_FEC_CONV_V29P56:
+    case LIQUID_FEC_CONV_V29P67:
+    case LIQUID_FEC_CONV_V29P78:
+        fprintf(stderr,"error: fec_destroy(), convolutional codes unavailable (install libfec)\n");
+        exit(-1);
+
+    case LIQUID_FEC_RS_M8:
+        fprintf(stderr,"error: fec_destroy(), Reed-Solomon codes unavailable (install libfec)\n");
+        exit(-1);
+#endif
+
+    default:
+        printf("error: fec_destroy(), unknown/unsupported scheme: %d\n", _q->scheme);
+        exit(-1);
+    }
 }
 
 // print basic fec object internals
diff --git a/src/fec/src/fec_conv.c b/src/fec/src/fec_conv.c
index 573d817..6462570 100644
--- a/src/fec/src/fec_conv.c
+++ b/src/fec/src/fec_conv.c
@@ -70,6 +70,9 @@ void fec_conv_destroy(fec _q)
     if (_q->vp != NULL)
         _q->delete_viterbi(_q->vp);
 
+    if (_q->enc_bits != NULL)
+        free(_q->enc_bits);
+
     free(_q);
 }
 
diff --git a/src/fec/src/fec_conv_punctured.c b/src/fec/src/fec_conv_punctured.c
index f3f25a5..faa1f6c 100644
--- a/src/fec/src/fec_conv_punctured.c
+++ b/src/fec/src/fec_conv_punctured.c
@@ -79,6 +79,9 @@ void fec_conv_punctured_destroy(fec _q)
     if (_q->vp != NULL)
         _q->delete_viterbi(_q->vp);
 
+    if (_q->enc_bits != NULL)
+        free(_q->enc_bits);
+
     free(_q);
 }
 
diff --git a/src/fec/src/fec_rs.c b/src/fec/src/fec_rs.c
index 32a0fbd..4fad3d2 100644
--- a/src/fec/src/fec_rs.c
+++ b/src/fec/src/fec_rs.c
@@ -73,7 +73,9 @@ fec fec_rs_create(fec_scheme _fs)
 void fec_rs_destroy(fec _q)
 {
     // delete internal Reed-Solomon decoder object
-    free_rs_char(_q->rs);
+    if (_q->rs != NULL) {
+        free_rs_char(_q->rs);
+    }
 
     // delete internal memory arrays
     free(_q->tblock);
diff --git a/src/fec/src/packetizer.c b/src/fec/src/packetizer.c
index e341d64..139bb58 100644
--- a/src/fec/src/packetizer.c
+++ b/src/fec/src/packetizer.c
@@ -165,12 +165,12 @@ packetizer packetizer_recreate(packetizer _p,
     {
         // no change; return input pointer
         return _p;
-    } else {
-        // something has changed; destroy old object and create new one
-        // TODO : rather than completely destroying object, only change values that are necessary
-        packetizer_destroy(_p);
-        return packetizer_create(_n,_crc,_fec0,_fec1);
     }
+
+    // something has changed; destroy old object and create new one
+    // TODO : rather than completely destroying object, only change values that are necessary
+    packetizer_destroy(_p);
+    return packetizer_create(_n,_crc,_fec0,_fec1);
 }
 
 // destroy packetizer object
diff --git a/src/fft/src/asgram.c b/src/fft/src/asgram.c
index 6f641fd..5aebcda 100644
--- a/src/fft/src/asgram.c
+++ b/src/fft/src/asgram.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2015 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -33,7 +33,9 @@
 #include "liquid.internal.h"
 
 struct ASGRAM(_s) {
-    unsigned int nfft;          // transform size
+    unsigned int nfft;          // transform size (display)
+    unsigned int nfftp;         // transform size (processing)
+    unsigned int p;             // over-sampling rate
     SPGRAM()     periodogram;   // spectral periodogram object
     TC *         X;             // spectral periodogram output
     float *      psd;           // power spectral density
@@ -41,8 +43,8 @@ struct ASGRAM(_s) {
     float        levels[10];    // threshold for signal levels
     char         levelchar[10]; // characters representing levels
     unsigned int num_levels;    // number of levels
-    float        scale;         // dB per division
-    float        offset;        // dB offset (max)
+    float        div;           // dB per division
+    float        ref;           // dB reference value
 };
 
 // create asgram object with size _nfft
@@ -57,28 +59,22 @@ ASGRAM() ASGRAM(_create)(unsigned int _nfft)
     // create main object
     ASGRAM() q = (ASGRAM()) malloc(sizeof(struct ASGRAM(_s)));
 
-    q->nfft = _nfft;
+    q->nfft  = _nfft;
+
+    // derived values
+    q->p     = 4;   // over-sampling rate
+    q->nfftp = q->nfft * q->p;
 
     // allocate memory for PSD estimate
-    q->X   = (TC *   ) malloc((q->nfft)*sizeof(TC)   );
-    q->psd = (float *) malloc((q->nfft)*sizeof(float));
+    q->X   = (TC *   ) malloc((q->nfftp)*sizeof(TC)   );
+    q->psd = (float *) malloc((q->nfftp)*sizeof(float));
 
     // create spectral periodogram object
-    q->periodogram = SPGRAM(_create_default)(q->nfft);
+    q->periodogram = SPGRAM(_create)(q->nfftp,LIQUID_WINDOW_HANN,q->nfft,q->nfft/2);
 
     // power spectral density levels
     q->num_levels = 10;
-    q->levelchar[9] = '#';
-    q->levelchar[8] = 'M';
-    q->levelchar[7] = 'N';
-    q->levelchar[6] = '&';
-    q->levelchar[5] = '*';
-    q->levelchar[4] = '+';
-    q->levelchar[3] = '-';
-    q->levelchar[2] = ',';
-    q->levelchar[1] = '.';
-    q->levelchar[0] = ' ';
-
+    ASGRAM(_set_display)(q," .,-+*&NM#");
     ASGRAM(_set_scale)(q, 0.0f, 10.0f);
 
     return q;
@@ -106,23 +102,40 @@ void ASGRAM(_reset)(ASGRAM() _q)
 
 // set scale and offset for spectrogram
 //  _q      :   asgram object
-//  _offset :   signal offset level [dB]
-//  _scale  :   signal scale [dB]
+//  _ref    :   signal reference level [dB]
+//  _div    :   signal division [dB]
 void ASGRAM(_set_scale)(ASGRAM() _q,
-                        float    _offset,
-                        float    _scale)
+                        float    _ref,
+                        float    _div)
 {
-    if (_scale <= 0.0f) {
-        fprintf(stderr,"ASGRAM(_set_scale)(), scale must be greater than zero\n");
+    if (_div <= 0.0f) {
+        fprintf(stderr,"ASGRAM(_set_scale)(), div must be greater than zero\n");
         exit(1);
     }
 
-    _q->offset = _offset;
-    _q->scale  = _scale;
+    _q->ref = _ref;
+    _q->div = _div;
 
     unsigned int i;
     for (i=0; i<_q->num_levels; i++)
-        _q->levels[i] = _q->offset + i*_q->scale;
+        _q->levels[i] = _q->ref + i*_q->div;
+}
+
+// set display characters for output string
+//  _q      :   asgram object
+//  _ascii  :   10-character display, default: " .,-+*&NM#"
+void ASGRAM(_set_display)(ASGRAM()     _q,
+                          const char * _ascii)
+{
+    unsigned int i;
+    for (i=0; i<10; i++) {
+        if (_ascii[i] == '\0') {
+            fprintf(stderr,"warning: asgram%s_set_display(), invalid use of null character\n", EXTENSION);
+            _q->levelchar[i] = '?';
+        } else {
+            _q->levelchar[i] = _ascii[i];
+        }
+    }
 }
 
 // push a single sample into the asgram object
@@ -150,50 +163,60 @@ void ASGRAM(_write)(ASGRAM()     _q,
 
 // compute spectral periodogram output from current buffer contents
 //  _q          :   ascii spectrogram object
-//  _ascii      :   character buffer [size: 1 x n]
+//  _ascii      :   output ASCII string [size: _nfft x 1]
 //  _peakval    :   value at peak (returned value)
 //  _peakfreq   :   frequency at peak (returned value)
-void ASGRAM(_execute)(ASGRAM()  _q,
-                      char *    _ascii,
-                      float *   _peakval,
-                      float *   _peakfreq)
+void ASGRAM(_execute)(ASGRAM() _q,
+                      char *   _ascii,
+                      float *  _peakval,
+                      float *  _peakfreq)
 {
-#if 0
+    // check number of transforms
+    if (SPGRAM(_get_num_transforms)(_q->periodogram)==0) {
+        memset(_ascii,' ',_q->nfft);
+        *_peakval = 0.0f;
+        *_peakfreq = 0.0f;
+        return;
+    }
+
     // execute spectral periodogram
-    SPGRAM(_execute)(_q->periodogram, _q->X);
+    SPGRAM(_get_psd)(_q->periodogram, _q->psd);
+    SPGRAM(_reset)(_q->periodogram);
 
-    // compute PSD magnitude and apply FFT shift
     unsigned int i;
-    for (i=0; i<_q->nfft; i++)
-        _q->psd[i] = 10*log10f(cabsf(_q->X[(i + _q->nfft/2)%_q->nfft]));
-#else
-    unsigned int i;
-    for (i=0; i<_q->nfft; i++)
-        _q->psd[i] = 0.0f;
-#endif
-
     unsigned int j;
-    for (i=0; i<_q->nfft; i++) {
-        // find peak
+    // find peak
+    for (i=0; i<_q->nfftp; i++) {
         if (i==0 || _q->psd[i] > *_peakval) {
             *_peakval = _q->psd[i];
-            *_peakfreq = (float)(i) / (float)(_q->nfft) - 0.5f;
+            *_peakfreq = (float)(i) / (float)(_q->nfftp) - 0.5f;
         }
+    }
 
-        // determine ascii level (which character to use)
+    // down-sample from nfft*p frequency bins to just nfft by retaining
+    // one value (e.g. maximum or average) over range.
+    for (i=0; i<_q->nfft; i++) {
 #if 0
-        for (j=0; j<_q->num_levels-1; j++) {
-            if ( _q->psd[i] > ( _q->offset - j*(_q->scale)) )
-                break;
+        // find maximum within 'p' samples
+        float psd_val = 0.0f;
+        for (j=0; j<_q->p; j++) {
+            unsigned int index = (_q->p*i) + j;
+            psd_val = (j==0 || _q->psd[index] > psd_val) ? _q->psd[index] : psd_val;
         }
-        _ascii[i] = _q->levelchar[j];
 #else
+        // find average over 'p' samples
+        float psd_val = 0.0f;
+        for (j=0; j<_q->p; j++)
+            psd_val += _q->psd[(_q->p*i) + j];
+        psd_val /= (float)(_q->p);
+#endif
+
+        // determine ascii level (which character to use)
         _ascii[i] = _q->levelchar[0];
         for (j=0; j<_q->num_levels; j++) {
-            if ( _q->psd[i] > _q->levels[j] )
+            if ( psd_val > _q->levels[j] )
                 _ascii[i] = _q->levelchar[j];
         }
-#endif
     }
 
     // append null character to end of string
diff --git a/src/fft/src/spgram.c b/src/fft/src/spgram.c
index 50c34db..1511249 100644
--- a/src/fft/src/spgram.c
+++ b/src/fft/src/spgram.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2015 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -68,7 +68,7 @@ void SPGRAM(_step)(SPGRAM() _q);
 
 // create spgram object
 //  _nfft       : FFT size
-//  _window     : window coefficients [size: _window_len x 1]
+//  _wtype      : window type, e.g. LIQUID_WINDOW_HAMMING
 //  _window_len : window length
 //  _delay      : delay between transforms, _delay > 0
 SPGRAM() SPGRAM(_create)(unsigned int _nfft,
@@ -147,7 +147,7 @@ SPGRAM() SPGRAM(_create)(unsigned int _nfft,
     // scale window and copy
     for (i=0; i<q->window_len; i++)
         q->w[i] = g * q->w[i];
-    
+
     // reset the spgram object
     q->num_samples_total    = 0;
     q->num_transforms_total = 0;
@@ -184,12 +184,10 @@ void SPGRAM(_destroy)(SPGRAM() _q)
     free(_q);
 }
 
-// resets the internal state of the spgram object
-void SPGRAM(_reset)(SPGRAM() _q)
+// clears the internal state of the spgram object, but not
+// the internal buffer
+void SPGRAM(_clear)(SPGRAM() _q)
 {
-    // clear the window buffer
-    //WINDOW(_clear)(_q->buffer);
-
     // clear FFT input
     unsigned int i;
     for (i=0; i<_q->nfft; i++)
@@ -205,6 +203,16 @@ void SPGRAM(_reset)(SPGRAM() _q)
         _q->psd[i] = 0.0f;
 }
 
+// reset the spgram object to its original state completely
+void SPGRAM(_reset)(SPGRAM() _q)
+{
+    // reset spgram object except for the window buffer
+    SPGRAM(_clear)(_q);
+
+    // clear the window buffer
+    WINDOW(_reset)(_q->buffer);
+}
+
 // prints the spgram object's parameters
 void SPGRAM(_print)(SPGRAM() _q)
 {
@@ -436,4 +444,3 @@ void SPGRAM(_estimate_psd)(unsigned int _nfft,
     // destroy object
     SPGRAM(_destroy)(q);
 }
-
diff --git a/src/fft/src/spgramcf.c b/src/fft/src/spgramcf.c
index d25fccc..a585107 100644
--- a/src/fft/src/spgramcf.c
+++ b/src/fft/src/spgramcf.c
@@ -32,6 +32,7 @@
 // name-mangling macros
 #define ASGRAM(name)        LIQUID_CONCAT(asgramcf,name)
 #define SPGRAM(name)        LIQUID_CONCAT(spgramcf,name)
+#define SPWATERFALL(name)   LIQUID_CONCAT(spwaterfallcf,name)
 #define WINDOW(name)        LIQUID_CONCAT(windowcf,name)
 #define FFT(name)           LIQUID_CONCAT(fft,name)
 
@@ -48,4 +49,5 @@
 // source files
 #include "asgram.c"
 #include "spgram.c"
+#include "spwaterfall.c"
 
diff --git a/src/fft/src/spgramf.c b/src/fft/src/spgramf.c
index 2255035..17b0ad5 100644
--- a/src/fft/src/spgramf.c
+++ b/src/fft/src/spgramf.c
@@ -32,6 +32,7 @@
 // name-mangling macros
 #define ASGRAM(name)        LIQUID_CONCAT(asgramf,name)
 #define SPGRAM(name)        LIQUID_CONCAT(spgramf,name)
+#define SPWATERFALL(name)   LIQUID_CONCAT(spwaterfallf,name)
 #define WINDOW(name)        LIQUID_CONCAT(windowf,name)
 #define FFT(name)           LIQUID_CONCAT(fft,name)
 
@@ -48,4 +49,5 @@
 // source files
 #include "asgram.c"
 #include "spgram.c"
+#include "spwaterfall.c"
 
diff --git a/src/fft/src/spwaterfall.c b/src/fft/src/spwaterfall.c
new file mode 100644
index 0000000..e5eb2bf
--- /dev/null
+++ b/src/fft/src/spwaterfall.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+//
+// spwaterfall (spectral periodogram waterfall)
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+#include <complex.h>
+#include "liquid.internal.h"
+
+struct SPWATERFALL(_s) {
+    // options
+    unsigned int    nfft;           // FFT length
+    unsigned int    time;           // minimum time buffer
+    SPGRAM()        periodogram;    // spectral periodogram object
+
+    // buffers
+    T *             psd;            // time/frequency buffer [nfft x 2*time]
+    unsigned int    index_time;     // time index for writing to buffer
+    unsigned int    rollover;       // number of FFTs to take before writing to output
+};
+
+//
+// internal methods
+//
+
+// compute spectral periodogram output (complex values) from internal periodogram object
+void SPWATERFALL(_step)(SPWATERFALL() _q);
+
+// consolidate buffer by taking log-average of two separate spectral estimates in time
+void SPWATERFALL(_consolidate_buffer)(SPWATERFALL() _q);
+
+// export files
+int SPWATERFALL(_export_bin)(SPWATERFALL() _q, const char * _filename_base);
+int SPWATERFALL(_export_gnu)(SPWATERFALL() _q, const char * _filename_base);
+
+// create spwaterfall object
+//  _nfft       : FFT size
+//  _wtype      : window type, e.g. LIQUID_WINDOW_HAMMING
+//  _window_len : window length
+//  _delay      : delay between transforms, _delay > 0
+SPWATERFALL() SPWATERFALL(_create)(unsigned int _nfft,
+                                   int          _wtype,
+                                   unsigned int _window_len,
+                                   unsigned int _delay,
+                                   unsigned int _time)
+{
+    // validate input
+    if (_nfft < 2) {
+        fprintf(stderr,"error: spwaterfall%s_create(), fft size must be at least 2\n", EXTENSION);
+        exit(1);
+    } else if (_window_len > _nfft) {
+        fprintf(stderr,"error: spwaterfall%s_create(), window size cannot exceed fft size\n", EXTENSION);
+        exit(1);
+    } else if (_window_len == 0) {
+        fprintf(stderr,"error: spwaterfall%s_create(), window size must be greater than zero\n", EXTENSION);
+        exit(1);
+    } else if (_wtype == LIQUID_WINDOW_KBD && _window_len % 2) {
+        fprintf(stderr,"error: spwaterfall%s_create(), KBD window length must be even\n", EXTENSION);
+        exit(1);
+    } else if (_delay == 0) {
+        fprintf(stderr,"error: spwaterfall%s_create(), delay must be greater than 0\n", EXTENSION);
+        exit(1);
+    } else if (_time == 0) {
+        fprintf(stderr,"error: spwaterfall%s_create(), time must be greater than 0\n", EXTENSION);
+        exit(1);
+    }
+
+    // allocate memory for main object
+    SPWATERFALL() q = (SPWATERFALL()) malloc(sizeof(struct SPWATERFALL(_s)));
+
+    // set input parameters
+    q->nfft = _nfft;
+    q->time = _time;
+
+    // create buffer to hold aggregated power spectral density
+    // NOTE: the buffer is two-dimensional time/frequency grid that is two times
+    //       'nfft' and 'time' to account for log-average consolidation each time
+    //       the buffer gets filled
+    q->psd = (T*) malloc( 2 * q->nfft * q->time * sizeof(T));
+
+    // create spectral periodogram object
+    q->periodogram = SPGRAM(_create)(_nfft, _wtype, _window_len, _delay);
+
+    // reset the object
+    SPWATERFALL(_reset)(q);
+
+    // return new object
+    return q;
+}
+
+// create default spwaterfall object (Kaiser-Bessel window)
+SPWATERFALL() SPWATERFALL(_create_default)(unsigned int _nfft,
+                                           unsigned int _time)
+{
+    // validate input
+    if (_nfft < 2) {
+        fprintf(stderr,"error: spwaterfall%s_create_default(), fft size must be at least 2\n", EXTENSION);
+        exit(1);
+    } else if (_time < 2) {
+        fprintf(stderr,"error: spwaterfall%s_create_default(), fft size must be at least 2\n", EXTENSION);
+        exit(1);
+    }
+
+    return SPWATERFALL(_create)(_nfft, LIQUID_WINDOW_KAISER, _nfft/2, _nfft/4, _time);
+}
+
+// destroy spwaterfall object
+void SPWATERFALL(_destroy)(SPWATERFALL() _q)
+{
+    // free allocated memory
+    free(_q->psd);
+
+    // destroy internal spectral periodogram object
+    SPGRAM(_destroy)(_q->periodogram);
+
+    // free main object
+    free(_q);
+}
+
+// clears the internal state of the spwaterfall object, but not
+// the internal buffer
+void SPWATERFALL(_clear)(SPWATERFALL() _q)
+{
+    memset(_q->psd, 0x00, 2*_q->nfft*_q->time*sizeof(T));
+    _q->index_time = 0;
+}
+
+// reset the spwaterfall object to its original state completely
+void SPWATERFALL(_reset)(SPWATERFALL() _q)
+{
+    SPWATERFALL(_clear)(_q);
+    _q->rollover = 1;
+}
+
+// prints the spwaterfall object's parameters
+void SPWATERFALL(_print)(SPWATERFALL() _q)
+{
+    printf("spwaterfall%s: nfft=%u, time=%u\n", EXTENSION, _q->nfft, _q->time);
+}
+
+// push a single sample into the spwaterfall object
+//  _q      :   spwaterfall object
+//  _x      :   input sample
+void SPWATERFALL(_push)(SPWATERFALL() _q,
+                        TI            _x)
+{
+    SPGRAM(_push)(_q->periodogram, _x);
+    SPWATERFALL(_step)(_q);
+}
+
+// write a block of samples to the spwaterfall object
+//  _q      :   spwaterfall object
+//  _x      :   input buffer [size: _n x 1]
+//  _n      :   input buffer length
+void SPWATERFALL(_write)(SPWATERFALL() _q,
+                         TI *          _x,
+                         unsigned int  _n)
+{
+    // TODO: be smarter about how to write and execute samples
+    unsigned int i;
+    for (i=0; i<_n; i++)
+        SPWATERFALL(_push)(_q, _x[i]);
+}
+
+// export output files
+//  _q             : spwaterfall object
+//  _filename_base : base filename
+int SPWATERFALL(_export)(SPWATERFALL() _q,
+                         const char *  _filename_base)
+{
+    return
+    SPWATERFALL(_export_bin)(_q, _filename_base) +
+    SPWATERFALL(_export_gnu)(_q, _filename_base);
+}
+
+// compute spectral periodogram output from current buffer contents
+//  _q : spwaterfall object
+void SPWATERFALL(_step)(SPWATERFALL() _q)
+{
+    // determine if we need to extract PSD estimate from periodogram
+    if (SPGRAM(_get_num_transforms)(_q->periodogram) >= _q->rollover) {
+        //printf("index : %u\n", _q->index_time);
+        // get PSD estimate from periodogram object, placing result in
+        // proper location in internal buffer
+        SPGRAM(_get_psd)(_q->periodogram, _q->psd + _q->nfft*_q->index_time);
+
+        // soft reset of internal state, counters
+        SPGRAM(_clear)(_q->periodogram);
+
+        // increment buffer counter
+        _q->index_time++;
+
+        // determine if buffer is full and we need to consolidate buffer
+        if (_q->index_time == 2*_q->time)
+            SPWATERFALL(_consolidate_buffer)(_q);
+    }
+}
+
+// consolidate buffer by taking log-average of two separate spectral estimates in time
+//  _q : spwaterfall object
+void SPWATERFALL(_consolidate_buffer)(SPWATERFALL() _q)
+{
+    // assert(_q->index_time == 2*_q->time);
+    printf("consolidating... (rollover = %10u, total samples : %16llu, index : %u)\n",
+            _q->rollover, SPGRAM(_get_num_samples_total)(_q->periodogram), _q->index_time);
+    unsigned int i; // time index
+    unsigned int k; // freq index
+    for (i=0; i<_q->time; i++) {
+        for (k=0; k<_q->nfft; k++) {
+            // compute median
+            T v0  = _q->psd[ (2*i + 0)*_q->nfft + k ];
+            T v1  = _q->psd[ (2*i + 1)*_q->nfft + k ];
+
+            // keep log average (only need double buffer for this, not triple buffer)
+            _q->psd[ i*_q->nfft + k ] = logf(0.5f*(expf(v0) + expf(v1)));
+        }
+    }
+
+    // update time index
+    _q->index_time = _q->time;
+
+    // update rollover counter
+    _q->rollover *= 2;
+}
+
+// export gnuplot file
+//  _q        : spwaterfall object
+//  _filename : input buffer [size: _n x 1]
+int SPWATERFALL(_export_bin)(SPWATERFALL() _q,
+                             const char *  _filename_base)
+{
+    // add '.bin' extension to base
+    int n = strlen(_filename_base);
+    char filename[n+5];
+    sprintf(filename,"%s.bin", _filename_base);
+
+    // open output file for writing
+    FILE * fid = fopen(filename,"w");
+    if (fid == NULL) {
+        fprintf(stderr,"error: spwaterfall%s_export_bin(), could not open '%s' for writing\n",
+                EXTENSION, filename);
+        return -1;
+    }
+
+    unsigned int i;
+    
+    // write header
+    float nfftf = (float)(_q->nfft);
+    fwrite(&nfftf, sizeof(float), 1, fid);
+    for (i=0; i<_q->nfft; i++) {
+        float f = (float)i/nfftf - 0.5f;
+        fwrite(&f, sizeof(float), 1, fid);
+    }
+    
+    // write output spectral estimate
+    // TODO: force converstion from type 'T' to type 'float'
+    uint64_t total_samples = SPGRAM(_get_num_samples_total)(_q->periodogram);
+    for (i=0; i<_q->index_time; i++) {
+        float n = (float)i / (float)(_q->index_time) * (float)total_samples;
+        fwrite(&n, sizeof(float), 1, fid);
+        fwrite(&_q->psd[i*_q->nfft], sizeof(float), _q->nfft, fid);
+    }
+
+    // close it up
+    fclose(fid);
+    printf("results written to %s\n", filename);
+    return 0;
+}
+
+// export gnuplot file
+//  _q        : spwaterfall object
+//  _filename : input buffer [size: _n x 1]
+int SPWATERFALL(_export_gnu)(SPWATERFALL() _q,
+                             const char *  _filename_base)
+{
+    // add '.bin' extension to base
+    int n = strlen(_filename_base);
+    char filename[n+5];
+    sprintf(filename,"%s.gnu", _filename_base);
+
+    // open output file for writing
+    FILE * fid = fopen(filename,"w");
+    if (fid == NULL) {
+        fprintf(stderr,"error: spwaterfall%s_export_gnu(), could not open '%s' for writing\n",
+                EXTENSION, filename);
+        return -1;
+    }
+    
+    // scale to thousands, millions, billions (etc.) automatically
+    uint64_t total_samples = SPGRAM(_get_num_samples_total)(_q->periodogram);
+    char units  = ' ';
+    float scale = 1.0f;
+    if      (total_samples < 4e3 ) { units = ' '; scale = 1e-0f;  }
+    else if (total_samples < 4e6 ) { units = 'k'; scale = 1e-3f;  }
+    else if (total_samples < 4e9 ) { units = 'M'; scale = 1e-6f;  }
+    else if (total_samples < 4e12) { units = 'G'; scale = 1e-9f;  }
+    else if (total_samples < 4e15) { units = 'T'; scale = 1e-12f; }
+    else                           { units = 'P'; scale = 1e-15f; }
+
+    fprintf(fid,"#!/usr/bin/gnuplot\n");
+    fprintf(fid,"reset\n");
+    fprintf(fid,"set terminal png size 800,800 enhanced font 'Verdana,10'\n");
+    fprintf(fid,"set output '%s.png'\n", _filename_base);
+    fprintf(fid,"unset key\n");
+    fprintf(fid,"set style line 11 lc rgb '#808080' lt 1\n");
+    fprintf(fid,"set border 3 front ls 11\n");
+    fprintf(fid,"set style line 12 lc rgb '#888888' lt 0 lw 1\n");
+    fprintf(fid,"set grid front ls 12\n");
+    fprintf(fid,"set tics nomirror out scale 0.75\n");
+    fprintf(fid,"set xrange [-0.5:0.5]\n");
+    fprintf(fid,"set yrange [0:%f]\n", (float)(total_samples-1)*scale);
+    fprintf(fid,"set xlabel 'Normalized Frequency [f/F_s]'\n");
+    fprintf(fid,"set ylabel 'Sample Index'\n");
+    fprintf(fid,"set format y '%%.0f %c'\n", units);
+    fprintf(fid,"# disable colorbar tics\n");
+    fprintf(fid,"set cbtics scale 0\n");
+    fprintf(fid,"set palette negative defined ( \\\n");
+    fprintf(fid,"    0 '#D53E4F',\\\n");
+    fprintf(fid,"    1 '#F46D43',\\\n");
+    fprintf(fid,"    2 '#FDAE61',\\\n");
+    fprintf(fid,"    3 '#FEE08B',\\\n");
+    fprintf(fid,"    4 '#E6F598',\\\n");
+    fprintf(fid,"    5 '#ABDDA4',\\\n");
+    fprintf(fid,"    6 '#66C2A5',\\\n");
+    fprintf(fid,"    7 '#3288BD' )\n");
+    fprintf(fid,"\n");
+    fprintf(fid,"plot '%s.bin' u 1:($2*%e):3 binary matrix with image\n", _filename_base, scale);
+    fclose(fid);
+
+    // close it up
+    printf("results written to %s\n", filename);
+    printf("index time       : %u\n", _q->index_time);
+    printf("rollover         : %u\n", _q->rollover);
+    printf("total transforms : %llu\n", SPGRAM(_get_num_transforms_total)(_q->periodogram));
+    return 0;
+}
+
diff --git a/src/filter/src/firdespm.c b/src/filter/src/firdespm.c
index 69deb31..0a7a94d 100644
--- a/src/filter/src/firdespm.c
+++ b/src/filter/src/firdespm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2015 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -63,6 +63,31 @@
 void firdespm_output_debug_file(firdespm _q);
 #endif
 
+// initialize internal memory and arrays
+void firdespm_init_memory(firdespm     _q,
+                          unsigned int _h_len,
+                          unsigned int _num_bands);
+
+// initialize the frequency grid on the disjoint bounded set
+void firdespm_init_grid(firdespm _q);
+
+// compute interpolating polynomial
+void firdespm_compute_interp(firdespm _q);
+
+// compute error signal from actual response (interpolator
+// output), desired response, and weights
+void firdespm_compute_error(firdespm _q);
+
+// search error curve for _r+1 extremal indices
+void firdespm_iext_search(firdespm _q);
+
+// evaluates result to determine if Remez exchange algorithm
+// has converged
+int firdespm_is_search_complete(firdespm _q);
+
+// compute filter taps (coefficients) from result
+void firdespm_compute_taps(firdespm _q, float * _h);
+
 // structured data type
 struct firdespm_s {
     // constants
@@ -97,6 +122,8 @@ struct firdespm_s {
     unsigned int * iext;        // indices of extrema
     unsigned int num_exchanges; // number of changes in extrema
 
+    firdespm_callback callback; // user-defined callback function
+    void *            userdata; // user-defined structure for callback function
 #if LIQUID_FIRDESPM_DEBUG
     FILE * fid;
 #endif
@@ -112,14 +139,14 @@ struct firdespm_s {
 //  _wtype      :   weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
 //  _btype      :   band type (e.g. LIQUID_FIRDESPM_BANDPASS)
 //  _h          :   output coefficients array [size: _h_len x 1]
-void firdespm_run(unsigned int _h_len,
-                  unsigned int _num_bands,
-                  float * _bands,
-                  float * _des,
-                  float * _weights,
+void firdespm_run(unsigned int            _h_len,
+                  unsigned int            _num_bands,
+                  float *                 _bands,
+                  float *                 _des,
+                  float *                 _weights,
                   liquid_firdespm_wtype * _wtype,
-                  liquid_firdespm_btype _btype,
-                  float * _h)
+                  liquid_firdespm_btype   _btype,
+                  float *                 _h)
 {
     // create object
     firdespm q = firdespm_create(_h_len,_num_bands,_bands,_des,_weights,_wtype,_btype);
@@ -131,6 +158,50 @@ void firdespm_run(unsigned int _h_len,
     firdespm_destroy(q);
 }
 
+// run filter design for basic low-pass filter
+//  _n      : filter length, _n > 0
+//  _fc     : cutoff frequency, 0 < _fc < 0.5
+//  _As     : stop-band attenuation [dB], _As > 0
+//  _mu     : fractional sample offset, -0.5 < _mu < 0.5 [ignored]
+//  _h      : output coefficient buffer, [size: _n x 1]
+void firdespm_lowpass(unsigned int _n,
+                      float        _fc,
+                      float        _As,
+                      float        _mu,
+                      float *      _h)
+{
+    // validate inputs
+    if (_mu < -0.5f || _mu > 0.5f) {
+        fprintf(stderr,"error: firdespm_lowpass(), _mu (%12.4e) out of range [-0.5,0.5]\n", _mu);
+        exit(1);
+    } else if (_fc < 0.0f || _fc > 0.5f) {
+        fprintf(stderr,"error: firdespm_lowpass(), cutoff frequency (%12.4e) out of range (0, 0.5)\n", _fc);
+        exit(1);
+    } else if (_n == 0) {
+        fprintf(stderr,"error: firdespm_lowpass(), filter length must be greater than zero\n");
+        exit(1);
+    }
+
+    // estimate transition band
+    float ft = estimate_req_filter_df(_As, _n);
+
+    // derived values
+    float fp = _fc - 0.5*ft;     // pass-band cutoff frequency
+    float fs = _fc + 0.5*ft;     // stop-band cutoff frequency
+    liquid_firdespm_btype btype = LIQUID_FIRDESPM_BANDPASS;
+
+    // derived values
+    unsigned int num_bands = 2;
+    float bands[4]   = {0.0f, fp, fs, 0.5f};
+    float des[2]     = {1.0f, 0.0f};
+    float weights[2] = {1.0f, 1.0f};
+    liquid_firdespm_wtype wtype[2] = {LIQUID_FIRDESPM_FLATWEIGHT,
+                                      LIQUID_FIRDESPM_EXPWEIGHT};
+
+    // design filter
+    firdespm_run(_n,num_bands,bands,des,weights,wtype,btype,_h);
+}
+
 // create firdespm object
 //  _h_len      :   length of filter (number of taps)
 //  _num_bands  :   number of frequency bands
@@ -139,13 +210,13 @@ void firdespm_run(unsigned int _h_len,
 //  _weights    :   response weighting [size: _num_bands x 1]
 //  _wtype      :   weight types (e.g. LIQUID_FIRDESPM_FLATWEIGHT) [size: _num_bands x 1]
 //  _btype      :   band type (e.g. LIQUID_FIRDESPM_BANDPASS)
-firdespm firdespm_create(unsigned int _h_len,
-                         unsigned int _num_bands,
-                         float * _bands,
-                         float * _des,
-                         float * _weights,
+firdespm firdespm_create(unsigned int            _h_len,
+                         unsigned int            _num_bands,
+                         float *                 _bands,
+                         float *                 _des,
+                         float *                 _weights,
                          liquid_firdespm_wtype * _wtype,
-                         liquid_firdespm_btype _btype)
+                         liquid_firdespm_btype   _btype)
 {
     unsigned int i;
 
@@ -159,6 +230,7 @@ firdespm firdespm_create(unsigned int _h_len,
     for (i=1; i<2*_num_bands; i++)
         bands_valid &= _bands[i] >= _bands[i-1];
     // ensure weights are greater than 0
+    // TODO: ignore weights if pointer is NULL
     for (i=0; i<_num_bands; i++)
         weights_valid &= _weights[i] > 0;
 
@@ -211,13 +283,99 @@ firdespm firdespm_create(unsigned int _h_len,
     for (i=0; i<q->num_bands; i++) {
         q->bands[2*i+0] = _bands[2*i+0];
         q->bands[2*i+1] = _bands[2*i+1];
-
         q->des[i]       = _des[i];
+        q->weights[i]   = _weights == NULL ? 1.0f : _weights[i];
+    }
 
-        if (_weights == NULL)
-            q->weights[i] = 1.0f;
-        else
-            q->weights[i]   = _weights[i];
+    // estimate grid size
+    // TODO : adjust grid density based on expected value for rho
+    q->grid_density = 20;
+    q->grid_size = 0;
+    double df = 0.5/(q->grid_density*q->r); // frequency step
+    for (i=0; i<q->num_bands; i++) {
+        double f0 = q->bands[2*i+0];         // lower band edge
+        double f1 = q->bands[2*i+1];         // upper band edge
+        q->grid_size += (unsigned int)( (f1-f0)/df + 1.0 );
+    }
+
+    // create the grid
+    q->F = (double*) malloc(q->grid_size*sizeof(double));
+    q->D = (double*) malloc(q->grid_size*sizeof(double));
+    q->W = (double*) malloc(q->grid_size*sizeof(double));
+    q->E = (double*) malloc(q->grid_size*sizeof(double));
+    q->callback = NULL;
+    q->userdata = NULL;
+    firdespm_init_grid(q);
+    // TODO : fix grid, weights according to filter type
+
+    // return object
+    return q;
+}
+
+// create firdespm object with user-defined callback
+//  _h_len      :   length of filter (number of taps)
+//  _num_bands  :   number of frequency bands
+//  _bands      :   band edges, f in [0,0.5], [size: _num_bands x 2]
+//  _btype      :   band type (e.g. LIQUID_FIRDESPM_BANDPASS)
+//  _callback   :   user-defined callback for specifying desired response & weights
+//  _userdata   :   user-defined data structure for callback function
+firdespm firdespm_create_callback(unsigned int          _h_len,
+                                  unsigned int          _num_bands,
+                                  float *               _bands,
+                                  liquid_firdespm_btype _btype,
+                                  firdespm_callback     _callback,
+                                  void *                _userdata)
+{
+    unsigned int i;
+
+    // validate input
+    int bands_valid = 1;
+    // ensure bands are withing [0,0.5]
+    for (i=0; i<2*_num_bands; i++)
+        bands_valid &= _bands[i] >= 0.0 && _bands[i] <= 0.5;
+    // ensure bands are non-decreasing
+    for (i=1; i<2*_num_bands; i++)
+        bands_valid &= _bands[i] >= _bands[i-1];
+
+    if (!bands_valid) {
+        fprintf(stderr,"error: firdespm_create(), invalid bands\n");
+        exit(1);
+    } else if (_num_bands == 0) {
+        fprintf(stderr,"error: firdespm_create(), number of bands must be > 0\n");
+        exit(1);
+    }
+
+    // create object
+    firdespm q = (firdespm) malloc(sizeof(struct firdespm_s));
+
+    // compute number of extremal frequencies
+    q->h_len = _h_len;              // filter length
+    q->s     = q->h_len % 2;        // odd/even length
+    q->n     = (q->h_len - q->s)/2; // filter semi-length
+    q->r     = q->n + q->s;         // number of approximating functions
+    q->btype = _btype;              // set band type
+    q->callback = _callback;
+    q->userdata = _userdata;
+
+    // allocate memory for extremal frequency set, interpolating polynomial
+    q->iext  = (unsigned int*) malloc((q->r+1)*sizeof(unsigned int));
+    q->x     = (double*) malloc((q->r+1)*sizeof(double));
+    q->alpha = (double*) malloc((q->r+1)*sizeof(double));
+    q->c     = (double*) malloc((q->r+1)*sizeof(double));
+
+    // allocate memory for arrays
+    q->num_bands = _num_bands;
+    q->bands    = (double*) malloc(2*q->num_bands*sizeof(double));
+    q->des      = (double*) malloc(  q->num_bands*sizeof(double));
+    q->weights  = (double*) malloc(  q->num_bands*sizeof(double));
+    q->wtype = (liquid_firdespm_wtype*) malloc(q->num_bands*sizeof(liquid_firdespm_wtype));
+
+    // copy input arrays
+    for (i=0; i<q->num_bands; i++) {
+        q->bands[2*i+0] = _bands[2*i+0];
+        q->bands[2*i+1] = _bands[2*i+1];
+        q->des[i]       = 0.0f;
+        q->weights[i]   = 0.0f;
     }
 
     // estimate grid size
@@ -342,6 +500,13 @@ void firdespm_execute(firdespm _q, float * _h)
 // internal methods
 //
 
+// initialize internal memory and arrays
+void firdespm_init_memory(firdespm     _q,
+                          unsigned int _h_len,
+                          unsigned int _num_bands)
+{
+}
+
 // initialize the frequency grid on the disjoint bounded set
 void firdespm_init_grid(firdespm _q)
 {
@@ -400,21 +565,23 @@ void firdespm_init_grid(firdespm _q)
             // add frequency points
             _q->F[n] = f0 + j*df;
 
-            // compute desired response
-            // TODO : use function pointer
-            _q->D[n] = _q->des[i];
-
-            // compute weight, applying weighting function
-            // TODO : use function pointer?
-            switch (_q->wtype[i]) {
-            case LIQUID_FIRDESPM_FLATWEIGHT: fw = 1.0f;             break;
-            case LIQUID_FIRDESPM_EXPWEIGHT:  fw = expf(2.0f*j*df);  break;
-            case LIQUID_FIRDESPM_LINWEIGHT:  fw = 1.0f + 2.7f*j*df; break;
-            default:
-                fprintf(stderr,"error: firdespm_init_grid(), invalid weighting specifyer: %d\n", _q->wtype[i]);
-                exit(1);
+            // compute desired response using function pointer if provided
+            if (_q->callback != NULL) {
+                _q->callback(_q->F[n], _q->userdata, &_q->D[n], &_q->W[n]);
+            } else {
+                _q->D[n] = _q->des[i];
+
+                // compute weight, applying weighting function
+                switch (_q->wtype[i]) {
+                case LIQUID_FIRDESPM_FLATWEIGHT: fw = 1.0f;             break;
+                case LIQUID_FIRDESPM_EXPWEIGHT:  fw = expf(2.0f*j*df);  break;
+                case LIQUID_FIRDESPM_LINWEIGHT:  fw = 1.0f + 2.7f*j*df; break;
+                default:
+                    fprintf(stderr,"error: firdespm_init_grid(), invalid weighting specifyer: %d\n", _q->wtype[i]);
+                    exit(1);
+                }
+                _q->W[n] = _q->weights[i] * fw;
             }
-            _q->W[n] = _q->weights[i] * fw;
 
             n++;
         }
diff --git a/src/filter/src/firpfb.c b/src/filter/src/firpfb.c
index 8898592..c9ab206 100644
--- a/src/filter/src/firpfb.c
+++ b/src/filter/src/firpfb.c
@@ -97,7 +97,7 @@ FIRPFB() FIRPFB(_create)(unsigned int _M,
     return q;
 }
 
-// create firpfb from external coefficients
+// create firpfb using kaiser window
 //  _M      : number of filters in the bank
 //  _m      : filter semi-length [samples]
 //  _fc     : filter cut-off frequency 0 < _fc < 0.5
@@ -122,7 +122,7 @@ FIRPFB() FIRPFB(_create_kaiser)(unsigned int _M,
         exit(1);
     }
 
-    // generate square-root Nyquist filter
+    // design filter using kaiser window
     unsigned int H_len = 2*_M*_m + 1;
     float Hf[H_len];
     liquid_firdes_kaiser(H_len, _fc/(float)_M, _As, 0.0f, Hf);
diff --git a/src/filter/src/iirdes.pll.c b/src/filter/src/iirdes.pll.c
index 1b2bd98..967c8c0 100644
--- a/src/filter/src/iirdes.pll.c
+++ b/src/filter/src/iirdes.pll.c
@@ -93,13 +93,13 @@ void iirdes_pll_active_PI(float _w,
 {
     // validate input
     if (_w <= 0.0f) {
-        fprintf(stderr,"error: iirdes_pll_active_lag(), bandwidth must be greater than 0\n");
+        fprintf(stderr,"error: iirdes_pll_active_PI(), bandwidth must be greater than 0\n");
         exit(1);
     } else if (_zeta <= 0.0f) {
-        fprintf(stderr,"error: iirdes_pll_active_lag(), damping factor must be greater than 0\n");
+        fprintf(stderr,"error: iirdes_pll_active_PI(), damping factor must be greater than 0\n");
         exit(1);
     } else if (_K <= 0.0f) {
-        fprintf(stderr,"error: iirdes_pll_active_lag(), gain must be greater than 0\n");
+        fprintf(stderr,"error: iirdes_pll_active_PI(), gain must be greater than 0\n");
         exit(1);
     }
 
diff --git a/src/filter/src/iirfilt.c b/src/filter/src/iirfilt.c
index 910f259..2b2aca3 100644
--- a/src/filter/src/iirfilt.c
+++ b/src/filter/src/iirfilt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2015 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -44,7 +44,7 @@
 //  PRINTVAL()      print macro
 
 // use structured dot product? 0:no, 1:yes
-#define LIQUID_IIRFILT_USE_DOTPROD   (0)
+#define LIQUID_IIRFILT_USE_DOTPROD   (1)
 
 struct IIRFILT(_s) {
     TC * b;             // numerator (feed-forward coefficients)
@@ -71,6 +71,20 @@ struct IIRFILT(_s) {
     unsigned int nsos;      // number of second-order sections
 };
 
+// initialize internal objects/arrays
+void IIRFILT(_init)(IIRFILT() _q)
+{
+    _q->b    = NULL;
+    _q->a    = NULL;
+    _q->v    = NULL;
+    _q->qsos = NULL;
+    _q->nsos = 0;
+#if LIQUID_IIRFILT_USE_DOTPROD
+    _q->dpb  = NULL;
+    _q->dpa  = NULL;
+#endif
+}
+
 // create iirfilt (infinite impulse response filter) object
 //  _b      :   numerator, feed-forward coefficients [size: _nb x 1]
 //  _nb     :   length of numerator
@@ -92,6 +106,7 @@ IIRFILT() IIRFILT(_create)(TC *         _b,
 
     // create structure and initialize
     IIRFILT() q = (IIRFILT()) malloc(sizeof(struct IIRFILT(_s)));
+    IIRFILT(_init)(q);
     q->nb = _nb;
     q->na = _na;
     q->n = (q->na > q->nb) ? q->na : q->nb;
@@ -158,6 +173,7 @@ IIRFILT() IIRFILT(_create_sos)(TC *         _B,
 
     // create structure and initialize
     IIRFILT() q = (IIRFILT()) malloc(sizeof(struct IIRFILT(_s)));
+    IIRFILT(_init)(q);
     q->type = IIRFILT_TYPE_SOS;
     q->nsos = _nsos;
     q->qsos = (IIRFILTSOS()*) malloc( (q->nsos)*sizeof(IIRFILTSOS()) );
@@ -414,22 +430,23 @@ IIRFILT() IIRFILT(_create_pll)(float _w,
 void IIRFILT(_destroy)(IIRFILT() _q)
 {
 #if LIQUID_IIRFILT_USE_DOTPROD
-    DOTPROD(_destroy)(_q->dpa);
-    DOTPROD(_destroy)(_q->dpb);
+    if (_q->dpa != NULL) DOTPROD(_destroy)(_q->dpa);
+    if (_q->dpb != NULL) DOTPROD(_destroy)(_q->dpb);
 #endif
-    free(_q->b);
-    free(_q->a);
+    if (_q->b   != NULL) free(_q->b);
+    if (_q->a   != NULL) free(_q->a);
+    if (_q->v   != NULL) free(_q->v);
+
     // if filter is comprised of cascaded second-order sections,
     // delete sub-filters separately
-    if (_q->type == IIRFILT_TYPE_SOS) {
+    if (_q->qsos != NULL) {
         unsigned int i;
         for (i=0; i<_q->nsos; i++)
             IIRFILTSOS(_destroy)(_q->qsos[i]);
         free(_q->qsos);
-    } else {
-        free(_q->v);
     }
 
+    // free main object memory
     free(_q);
 }
 
@@ -498,7 +515,7 @@ void IIRFILT(_execute_norm)(IIRFILT() _q,
 #if LIQUID_IIRFILT_USE_DOTPROD
     // compute new v
     TI v0;
-    DOTPROD(_execute)(_q->dpa, _q->v+1, & v0);
+    DOTPROD(_execute)(_q->dpa, _q->v+1, &v0);
     v0 = _x - v0;
     _q->v[0] = v0;
 
diff --git a/src/filter/src/iirfiltsos.c b/src/filter/src/iirfiltsos.c
index 25cd99a..1280643 100644
--- a/src/filter/src/iirfiltsos.c
+++ b/src/filter/src/iirfiltsos.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007 - 2015 Joseph Gaeddert
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -35,6 +35,24 @@
 //  TI              input type
 //  PRINTVAL()      print macro(s)
 
+// use structured dot product? 0:no, 1:yes
+#define LIQUID_IIRFILTSOS_USE_DOTPROD   (0)
+
+struct IIRFILTSOS(_s) {
+    TC b[3];    // feed-forward coefficients
+    TC a[3];    // feed-back coefficients
+
+    // internal buffering
+    TI x[3];    // Direct form I  buffer (input)
+    TO y[3];    // Direct form I  buffer (output)
+    TO v[3];    // Direct form II buffer
+
+#if LIQUID_IIRFILTSOS_USE_DOTPROD
+    DOTPROD() dpb;  // numerator dot product
+    DOTPROD() dpa;  // denominator dot product
+#endif
+};
+
 // create iirfiltsos object
 IIRFILTSOS() IIRFILTSOS(_create)(TC * _b,
                                  TC * _a)
@@ -71,14 +89,23 @@ void IIRFILTSOS(_set_coefficients)(IIRFILTSOS() _q,
     _q->b[2] = _b[2] / a0;
 
     // copy feed-back coefficients (denominator)
-    _q->a[0] = _a[0] / a0;
+    _q->a[0] = _a[0] / a0;  // unity
     _q->a[1] = _a[1] / a0;
     _q->a[2] = _a[2] / a0;
+
+#if LIQUID_IIRFILTSOS_USE_DOTPROD
+    _q->dpa = DOTPROD(_create)(_q->a+1, 2);
+    _q->dpb = DOTPROD(_create)(_q->b,   3);
+#endif
 }
 
 // destroy iirfiltsos object, freeing all internal memory
 void IIRFILTSOS(_destroy)(IIRFILTSOS() _q)
 {
+#if LIQUID_IIRFILTSOS_USE_DOTPROD
+    DOTPROD(_destroy)(_q->dpa);
+    DOTPROD(_destroy)(_q->dpb);
+#endif
     free(_q);
 }
 
@@ -146,6 +173,17 @@ void IIRFILTSOS(_execute_df1)(IIRFILTSOS() _q,
     _q->y[2] = _q->y[1];
     _q->y[1] = _q->y[0];
 
+#if LIQUID_IIRFILTSOS_USE_DOTPROD
+    // NOTE: this is actually slower than the non-dotprod version
+    // compute new v
+    TI v;
+    DOTPROD(_execute)(_q->dpb, _q->x, &v);
+
+    // compute new y[0]
+    TI y0;
+    DOTPROD(_execute)(_q->dpa, _q->y+1, &y0);
+    _q->y[0] = v - y0;
+#else
     // compute new v
     TI v = _q->x[0] * _q->b[0] +
            _q->x[1] * _q->b[1] +
@@ -155,12 +193,13 @@ void IIRFILTSOS(_execute_df1)(IIRFILTSOS() _q,
     _q->y[0] = v -
                _q->y[1] * _q->a[1] -
                _q->y[2] * _q->a[2];
+#endif
 
     // set output
     *_y = _q->y[0];
 }
 
-// compute filter output, direct form I method
+// compute filter output, direct form II method
 //  _q      : iirfiltsos object
 //  _x      : input sample
 //  _y      : output sample pointer
@@ -172,8 +211,19 @@ void IIRFILTSOS(_execute_df2)(IIRFILTSOS() _q,
     _q->v[2] = _q->v[1];
     _q->v[1] = _q->v[0];
 
+#if LIQUID_IIRFILTSOS_USE_DOTPROD
+    // NOTE: this is actually slower than the non-dotprod version
+    // compute new v
+    TI v0;
+    DOTPROD(_execute)(_q->dpa, _q->v+1, &v0);
+    v0 = _x - v0;
+    _q->v[0] = v0;
+
+    // compute new y
+    DOTPROD(_execute)(_q->dpb, _q->v, _y);
+#else
     // compute new v[0]
-    _q->v[0] = _x - 
+    _q->v[0] = _x -
                _q->a[1]*_q->v[1] -
                _q->a[2]*_q->v[2];
 
@@ -181,6 +231,7 @@ void IIRFILTSOS(_execute_df2)(IIRFILTSOS() _q,
     *_y = _q->b[0]*_q->v[0] +
           _q->b[1]*_q->v[1] +
           _q->b[2]*_q->v[2];
+#endif
 }
 
 // compute group delay in samples
@@ -199,4 +250,3 @@ float IIRFILTSOS(_groupdelay)(IIRFILTSOS() _q,
     }
     return iir_group_delay(b, 3, a, 3, _fc) + 2.0;
 }
-
diff --git a/src/filter/src/resamp.c b/src/filter/src/resamp.c
index c31f3c7..b56fe6d 100644
--- a/src/filter/src/resamp.c
+++ b/src/filter/src/resamp.c
@@ -200,7 +200,9 @@ unsigned int RESAMP(_get_delay)(RESAMP() _q)
     return _q->m;
 }
 
-// set resampling rate
+// set rate of arbitrary resampler
+//  _q      : resampling object
+//  _rate   : new sampling rate, _rate > 0
 void RESAMP(_set_rate)(RESAMP() _q,
                        float    _rate)
 {
@@ -237,6 +239,38 @@ void RESAMP(_adjust_rate)(RESAMP() _q,
 }
 
 
+// set resampling timing phase
+//  _q      : resampling object
+//  _tau    : sample timing
+void RESAMP(_set_timing_phase)(RESAMP() _q,
+                               float    _tau)
+{
+    if (_tau > 1.0f || _tau < -1.0f) {
+        fprintf(stderr,"error: resamp_%s_set_timing_phase(), timing phase must be in [-1,1], is %f\n.",
+                EXTENSION_FULL, _tau);
+        exit(1);
+    }
+
+    // set internal timing phase
+    _q->tau = _tau;
+}
+
+// adjust resampling timing phase
+//  _q      : resampling object
+//  _delta  : sample timing adjustment
+void RESAMP(_adjust_timing_phase)(RESAMP() _q,
+                                  float    _delta)
+{
+    if (_delta > 1.0f || _delta < -1.0f) {
+        fprintf(stderr,"error: resamp_%s_adjust_timing_phase(), timing phase adjustment must be in [-1,1], is %f\n.",
+                EXTENSION_FULL, _delta);
+        exit(1);
+    }
+
+    // adjust internal timing phase
+    _q->tau += _delta;
+}
+
 // run arbitrary resampler
 //  _q          :   resampling object
 //  _x          :   single input sample
diff --git a/src/filter/src/symsync.c b/src/filter/src/symsync.c
index e709b04..af8c2ec 100644
--- a/src/filter/src/symsync.c
+++ b/src/filter/src/symsync.c
@@ -44,7 +44,7 @@
 #define DEBUG_SYMSYNC_FILENAME  "symsync_internal_debug.m"
 #define DEBUG_BUFFER_LEN        (1024)
 
-// 
+//
 // forward declaration of internal methods
 //
 
@@ -149,7 +149,7 @@ SYMSYNC() SYMSYNC(_create)(unsigned int _k,
 
     // set internal sub-filter length
     q->h_len = (_h_len-1)/q->npfb;
-    
+
     // compute derivative filter
     TC dh[_h_len];
     float hdh_max = 0.0f;
@@ -171,7 +171,7 @@ SYMSYNC() SYMSYNC(_create)(unsigned int _k,
     // apply scaling factor for normalized response
     for (i=0; i<_h_len; i++)
         dh[i] *= 0.06f / hdh_max;
-    
+
     q->mf  = FIRPFB(_create)(q->npfb, _h, _h_len);
     q->dmf = FIRPFB(_create)(q->npfb, dh, _h_len);
 
@@ -183,9 +183,6 @@ SYMSYNC() SYMSYNC(_create)(unsigned int _k,
     SYMSYNC(_reset)(q);
     SYMSYNC(_set_lf_bw)(q, 0.01f);
 
-    // set output rate nominally at 1 sample/symbol (full decimation)
-    SYMSYNC(_set_output_rate)(q, 1);
-
     // unlock loop control
     SYMSYNC(_unlock)(q);
 
@@ -402,7 +399,7 @@ void SYMSYNC(_set_lf_bw)(SYMSYNC() _q,
 
     // set internal parameters of 2nd-order IIR filter
     iirfiltsos_rrrf_set_coefficients(_q->pll, _q->B, _q->A);
-    
+
     // update rate adjustment factor
     _q->rate_adjustment = 0.5*_bt;
 }
@@ -451,13 +448,13 @@ void SYMSYNC(_step)(SYMSYNC()      _q,
     // push sample into MF and dMF filterbanks
     FIRPFB(_push)(_q->mf,  _x);
     FIRPFB(_push)(_q->dmf, _x);
-    
+
     // matched and derivative matched-filter outputs
     TO  mf; // matched filter output
     TO dmf; // derivative matched filter output
 
     unsigned int n=0;
-    
+
     // continue loop until filterbank index rolls over
     while (_q->b < _q->npfb) {
 
@@ -492,7 +489,7 @@ void SYMSYNC(_step)(SYMSYNC()      _q,
 
             // compute dMF output
             FIRPFB(_execute)(_q->dmf, _q->b, &dmf);
-            
+
             // update internal state
             SYMSYNC(_advance_internal_loop)(_q, mf, dmf);
             _q->tau_decim = _q->tau;    // save return value
@@ -694,5 +691,3 @@ void SYMSYNC(_output_debug_file)(SYMSYNC()    _q,
     fclose(fid);
     printf("symsync: internal results written to '%s'\n", _filename);
 }
-
-
diff --git a/src/framing/bench/qdetector_benchmark.c b/src/framing/bench/qdetector_benchmark.c
new file mode 100644
index 0000000..c9965be
--- /dev/null
+++ b/src/framing/bench/qdetector_benchmark.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007 - 2017 Joseph Gaeddert
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+
+#include "liquid.internal.h"
+
+// Helper function to keep code base small
+void qdetector_cccf_bench(struct rusage *     _start,
+                          struct rusage *     _finish,
+                          unsigned long int * _num_iterations,
+                          unsigned int        _n)
+{
+    // adjust number of iterations
+    *_num_iterations *= 4;
+    *_num_iterations /= _n;
+
+    // generate sequence (random)
+    float complex h[_n];
+    unsigned long int i;
+    for (i=0; i<_n; i++) {
+        h[i] = (rand() % 2 ? 1.0f : -1.0f) +
+               (rand() % 2 ? 1.0f : -1.0f)*_Complex_I;
+    }
+
+    // generate synchronizer
+    int          ftype        = LIQUID_FIRFILT_ARKAISER;
+    unsigned int k            =    2;   // samples/symbol
+    unsigned int m            =    7;   // filter delay [symbols]
+    float        beta         = 0.3f;   // excess bandwidth factor
+    float        threshold    = 0.5f;   // threshold for detection
+    float        range        = 0.05f;  // carrier offset search range [radians/sample]
+    qdetector_cccf q = qdetector_cccf_create_linear(h, _n, ftype, k, m, beta);
+    qdetector_cccf_set_threshold(q,threshold);
+    qdetector_cccf_set_range    (q, range);
+
+    // input sequence (random)
+    float complex x[7];
+    for (i=0; i<7; i++) {
+        x[i] = (rand() % 2 ? 1.0f : -1.0f) +
+               (rand() % 2 ? 1.0f : -1.0f)*_Complex_I;
+    }
+
+    // start trials
+    getrusage(RUSAGE_SELF, _start);
+    int detected = 0;
+    for (i=0; i<(*_num_iterations); i++) {
+        // push input sequence through synchronizer
+        detected ^= qdetector_cccf_execute(q, x[0]) != NULL;
+        detected ^= qdetector_cccf_execute(q, x[1]) != NULL;
+        detected ^= qdetector_cccf_execute(q, x[2]) != NULL;
+        detected ^= qdetector_cccf_execute(q, x[3]) != NULL;
+        detected ^= qdetector_cccf_execute(q, x[4]) != NULL;
+        detected ^= qdetector_cccf_execute(q, x[5]) != NULL;
+        detected ^= qdetector_cccf_execute(q, x[6]) != NULL;
+    }
+    getrusage(RUSAGE_SELF, _finish);
+    *_num_iterations *= 7;
+
+    // clean up allocated objects
+    qdetector_cccf_destroy(q);
+}
+
+#define QDETECTOR_CCCF_BENCHMARK_API(N)      \
+(   struct rusage *     _start,             \
+    struct rusage *     _finish,            \
+    unsigned long int * _num_iterations)    \
+{ qdetector_cccf_bench(_start, _finish, _num_iterations, N); }
+
+void benchmark_qdetector_cccf_16   QDETECTOR_CCCF_BENCHMARK_API(16);
+void benchmark_qdetector_cccf_32   QDETECTOR_CCCF_BENCHMARK_API(32);
+void benchmark_qdetector_cccf_64   QDETECTOR_CCCF_BENCHMARK_API(64);
+void benchmark_qdetector_cccf_128  QDETECTOR_CCCF_BENCHMARK_API(128);
+void benchmark_qdetector_cccf_256  QDETECTOR_CCCF_BENCHMARK_API(256);
+
diff --git a/src/framing/src/detector_cccf.c b/src/framing/src/detector_cccf.c
index c618c2b..75f76a9 100644
--- a/src/framing/src/detector_cccf.c
+++ b/src/framing/src/detector_cccf.c
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <math.h>
 #include <assert.h>
+#include <float.h>
 
 #include "liquid.internal.h"
 
@@ -343,6 +344,9 @@ void detector_cccf_update_sumsq(detector_cccf _q,
     wdelayf_read(_q->x2, &x2_0);            // read oldest sample
     wdelayf_push(_q->x2, x2_n);             // push newest sample
     _q->x2_sum = _q->x2_sum + x2_n - x2_0;  // update sum( |x|^2 ) of last 'n' input samples
+    if (_q->x2_sum < FLT_EPSILON) {
+        _q->x2_sum = FLT_EPSILON;
+    }
 #if 0
     // filtered estimate of E{ |x|^2 }
     _q->x2_hat = 0.8f*_q->x2_hat + 0.2f*_q->x2_sum*_q->n_inv;
diff --git a/src/framing/src/flexframegen.c b/src/framing/src/flexframegen.c
index abe6d90..730cd1c 100644
--- a/src/framing/src/flexframegen.c
+++ b/src/framing/src/flexframegen.c
@@ -114,8 +114,8 @@ flexframegen flexframegen_create(flexframegenprops_s * _fgprops)
     q->preamble_pn = (float complex *) malloc(64*sizeof(float complex));
     msequence ms = msequence_create(7, 0x0089, 1);
     for (i=0; i<64; i++) {
-        q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) +
-                            (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I;
+        q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2);
+        q->preamble_pn[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I;
     }
     msequence_destroy(ms);
 
diff --git a/src/framing/src/flexframesync.c b/src/framing/src/flexframesync.c
index 999d671..c4c0367 100644
--- a/src/framing/src/flexframesync.c
+++ b/src/framing/src/flexframesync.c
@@ -157,8 +157,8 @@ flexframesync flexframesync_create(framesync_callback _callback,
     q->preamble_rx = (float complex*) malloc(64*sizeof(float complex));
     msequence ms = msequence_create(7, 0x0089, 1);
     for (i=0; i<64; i++) {
-        q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) +
-                            (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I;
+        q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2);
+        q->preamble_pn[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) * _Complex_I;
     }
     msequence_destroy(ms);
 
@@ -299,6 +299,11 @@ void flexframesync_reset(flexframesync _q)
     _q->framesyncstats.evm = 0.0f;
 }
 
+int flexframesync_is_frame_open(flexframesync _q)
+{
+    return (_q->state == FLEXFRAMESYNC_STATE_DETECTFRAME) ? 0 : 1;
+}
+
 // execute frame synchronizer
 //  _q  :   frame synchronizer object
 //  _x  :   input sample array [size: _n x 1]
diff --git a/src/framing/src/framegen64.c b/src/framing/src/framegen64.c
index e1eff04..e7a2ca5 100644
--- a/src/framing/src/framegen64.c
+++ b/src/framing/src/framegen64.c
@@ -59,8 +59,8 @@ framegen64 framegen64_create()
     // generate pn sequence
     msequence ms = msequence_create(7, 0x0089, 1);
     for (i=0; i<64; i++) {
-        q->pn_sequence[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) +
-                            (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I;
+        q->pn_sequence[i]  = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2);
+        q->pn_sequence[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I;
     }
     msequence_destroy(ms);
 
diff --git a/src/framing/src/framesync64.c b/src/framing/src/framesync64.c
index 4f65540..29ce901 100644
--- a/src/framing/src/framesync64.c
+++ b/src/framing/src/framesync64.c
@@ -133,8 +133,8 @@ framesync64 framesync64_create(framesync_callback _callback,
     // generate p/n sequence
     msequence ms = msequence_create(7, 0x0089, 1);
     for (i=0; i<64; i++) {
-        q->preamble_pn[i] = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2) +
-                            (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I;
+        q->preamble_pn[i]  = (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2);
+        q->preamble_pn[i] += (msequence_advance(ms) ? M_SQRT1_2 : -M_SQRT1_2)*_Complex_I;
     }
     msequence_destroy(ms);
 
diff --git a/src/framing/src/gmskframesync.c b/src/framing/src/gmskframesync.c
index 5f45f27..ba93e19 100644
--- a/src/framing/src/gmskframesync.c
+++ b/src/framing/src/gmskframesync.c
@@ -41,6 +41,10 @@
 // enable pre-demodulation filter (remove out-of-band noise)
 #define GMSKFRAMESYNC_PREFILTER         1
 
+// execute a single, post-filtered sample
+void gmskframesync_execute_sample(gmskframesync _q,
+                                  float complex _x);
+
 // push buffered p/n sequence through synchronizer
 void gmskframesync_pushpn(gmskframesync _q);
 
@@ -326,6 +330,37 @@ void gmskframesync_reset(gmskframesync _q)
         
 }
 
+int gmskframesync_is_frame_open(gmskframesync _q)
+{
+    return (_q->state == STATE_DETECTFRAME) ? 0 : 1;
+}
+
+void gmskframesync_execute_sample(gmskframesync _q,
+                                  float complex _x)
+{
+    switch (_q->state) {
+    case STATE_DETECTFRAME:
+        // look for p/n sequence
+        gmskframesync_execute_detectframe(_q, _x);
+        break;
+
+    case STATE_RXPREAMBLE:
+        // receive p/n sequence symbols
+        gmskframesync_execute_rxpreamble(_q, _x);
+        break;
+
+    case STATE_RXHEADER:
+        // receive header
+        gmskframesync_execute_rxheader(_q, _x);
+        break;
+
+    case STATE_RXPAYLOAD:
+        // receive payload
+        gmskframesync_execute_rxpayload(_q, _x);
+        break;
+    }
+}
+
 // execute frame synchronizer
 //  _q      :   frame synchronizer object
 //  _x      :   input sample array [size: _n x 1]
@@ -349,27 +384,8 @@ void gmskframesync_execute(gmskframesync   _q,
             windowcf_push(_q->debug_x, xf);
 #endif
 
-        switch (_q->state) {
-        case STATE_DETECTFRAME:
-            // look for p/n sequence
-            gmskframesync_execute_detectframe(_q, xf);
-            break;
-
-        case STATE_RXPREAMBLE:
-            // receive p/n sequence symbols
-            gmskframesync_execute_rxpreamble(_q, xf);
-            break;
-
-        case STATE_RXHEADER:
-            // receive header
-            gmskframesync_execute_rxheader(_q, xf);
-            break;
-
-        case STATE_RXPAYLOAD:
-            // receive payload
-            gmskframesync_execute_rxpayload(_q, xf);
-            break;
-        }
+        gmskframesync_execute_sample(_q, xf);
+
     }
 }
 
@@ -483,27 +499,28 @@ void gmskframesync_pushpn(gmskframesync _q)
     nco_crcf_set_frequency(_q->nco_coarse, _q->dphi_hat);
     
     unsigned int buffer_len = (_q->preamble_len + _q->m) * _q->k;
-    for (i=0; i<buffer_len; i++) {
-        if (i < delay) {
-            float complex y;
-            nco_crcf_mix_down(_q->nco_coarse, rc[i], &y);
-            nco_crcf_step(_q->nco_coarse);
-
-            // update instantanenous frequency estimate
-            gmskframesync_update_fi(_q, y);
-
-            // push initial samples into filterbanks
-            firpfb_rrrf_push(_q->mf,  _q->fi_hat);
-            firpfb_rrrf_push(_q->dmf, _q->fi_hat);
-        } else {
-            // run remaining samples through p/n sequence recovery
-            gmskframesync_execute_rxpreamble(_q, rc[i]);
-        }
+    for (i=0; i<delay; i++) {
+        float complex y;
+        nco_crcf_mix_down(_q->nco_coarse, rc[i], &y);
+        nco_crcf_step(_q->nco_coarse);
+
+        // update instantanenous frequency estimate
+        gmskframesync_update_fi(_q, y);
+
+        // push initial samples into filterbanks
+        firpfb_rrrf_push(_q->mf,  _q->fi_hat);
+        firpfb_rrrf_push(_q->dmf, _q->fi_hat);
     }
 
     // set state (still need a few more samples before entire p/n
     // sequence has been received)
     _q->state = STATE_RXPREAMBLE;
+
+    for (i=delay; i<buffer_len; i++) {
+        // run remaining samples through sample state machine
+        gmskframesync_execute_sample(_q, rc[i]);
+    }
+
 }
 
 // 
diff --git a/src/framing/src/ofdmflexframesync.c b/src/framing/src/ofdmflexframesync.c
index 44503bf..ff4790e 100644
--- a/src/framing/src/ofdmflexframesync.c
+++ b/src/framing/src/ofdmflexframesync.c
@@ -258,6 +258,11 @@ void ofdmflexframesync_reset(ofdmflexframesync _q)
     ofdmframesync_reset(_q->fs);
 }
 
+int ofdmflexframesync_is_frame_open(ofdmflexframesync _q)
+{
+    return ofdmframesync_is_frame_open(_q->fs);
+}
+
 // execute synchronizer object on buffer of samples
 void ofdmflexframesync_execute(ofdmflexframesync _q,
                                float complex * _x,
diff --git a/src/framing/src/symtrack.c b/src/framing/src/symtrack.c
index 3218db4..f4fd7cb 100644
--- a/src/framing/src/symtrack.c
+++ b/src/framing/src/symtrack.c
@@ -128,7 +128,7 @@ SYMTRACK() SYMTRACK(_create)(int          _ftype,
     q->demod = MODEM(_create)(q->mod_scheme);
 
     // set default bandwidth
-    SYMTRACK(_set_bandwidth)(q, 0.1f);
+    SYMTRACK(_set_bandwidth)(q, 0.9f);
 
     // reset and return main object
     SYMTRACK(_reset)(q);
@@ -205,10 +205,10 @@ void SYMTRACK(_set_bandwidth)(SYMTRACK() _q,
 
     // set bandwidths accordingly
     // TODO: set bandwidths based on input bandwidth
-    float agc_bandwidth     = 0.02f;
-    float symsync_bandwidth = 0.001f;
-    float eq_bandwidth      = 0.02f;
-    float pll_bandwidth     = 0.001f;
+    float agc_bandwidth     = 0.02f  * _bw;
+    float symsync_bandwidth = 0.001f * _bw;
+    float eq_bandwidth      = 0.02f  * _bw;
+    float pll_bandwidth     = 0.001f * _bw;
 
     // automatic gain control
     AGC(_set_bandwidth)(_q->agc, agc_bandwidth);
diff --git a/src/multichannel/src/ofdmframesync.c b/src/multichannel/src/ofdmframesync.c
index d1e54d0..f35695a 100644
--- a/src/multichannel/src/ofdmframesync.c
+++ b/src/multichannel/src/ofdmframesync.c
@@ -350,6 +350,11 @@ void ofdmframesync_reset(ofdmframesync _q)
     _q->state = OFDMFRAMESYNC_STATE_SEEKPLCP;
 }
 
+int ofdmframesync_is_frame_open(ofdmframesync _q)
+{
+    return (_q->state == OFDMFRAMESYNC_STATE_SEEKPLCP) ? 0 : 1;
+}
+
 void ofdmframesync_execute(ofdmframesync _q,
                            float complex * _x,
                            unsigned int _n)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/liquid-dsp.git



More information about the pkg-hamradio-commits mailing list