From b63845af8c8895acbf53d4cc508b511e7a0bf94c Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 28 Jan 2017 07:47:19 +0000 Subject: [PATCH] minimal set of sox 14.4.1 source files we need; unit test builds and runs OK git-svn-id: https://svn.code.sf.net/p/freetel/code@3001 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-dev/src/fdmdv2_main.cpp | 1 + freedv-dev/src/sox/band.h | 47 + freedv-dev/src/sox/biquad.c | 178 +++ freedv-dev/src/sox/biquad.h | 78 + freedv-dev/src/sox/biquads.c | 400 +++++ freedv-dev/src/sox/effects.c | 544 +++++++ freedv-dev/src/sox/effects.h | 22 + freedv-dev/src/sox/effects_i.c | 379 +++++ freedv-dev/src/sox/formats_i.c | 487 ++++++ freedv-dev/src/sox/libsox.c | 225 +++ freedv-dev/src/sox/sox.h | 2608 ++++++++++++++++++++++++++++++++ freedv-dev/src/sox/sox_i.h | 415 +++++ freedv-dev/src/sox/soxconfig.h | 386 +++++ freedv-dev/src/sox/soxomp.h | 38 + freedv-dev/src/sox/util.h | 231 +++ freedv-dev/src/sox/xmalloc.c | 43 + freedv-dev/src/sox/xmalloc.h | 34 + freedv-dev/src/sox_biquad.c | 15 +- 18 files changed, 6126 insertions(+), 5 deletions(-) create mode 100644 freedv-dev/src/sox/band.h create mode 100644 freedv-dev/src/sox/biquad.c create mode 100644 freedv-dev/src/sox/biquad.h create mode 100644 freedv-dev/src/sox/biquads.c create mode 100644 freedv-dev/src/sox/effects.c create mode 100644 freedv-dev/src/sox/effects.h create mode 100644 freedv-dev/src/sox/effects_i.c create mode 100644 freedv-dev/src/sox/formats_i.c create mode 100644 freedv-dev/src/sox/libsox.c create mode 100644 freedv-dev/src/sox/sox.h create mode 100644 freedv-dev/src/sox/sox_i.h create mode 100644 freedv-dev/src/sox/soxconfig.h create mode 100644 freedv-dev/src/sox/soxomp.h create mode 100644 freedv-dev/src/sox/util.h create mode 100644 freedv-dev/src/sox/xmalloc.c create mode 100644 freedv-dev/src/sox/xmalloc.h diff --git a/freedv-dev/src/fdmdv2_main.cpp b/freedv-dev/src/fdmdv2_main.cpp index 337db40a..49fddfe2 100644 --- a/freedv-dev/src/fdmdv2_main.cpp +++ b/freedv-dev/src/fdmdv2_main.cpp @@ -3183,6 +3183,7 @@ void *MainFrame::designAnEQFilter(const char filterType[], float freqHz, float g assert(argc <= SBQ_MAX_ARGS); sbq = sox_biquad_create(argc-1, (const char **)arg); + assert(sbq != NULL); return sbq; } diff --git a/freedv-dev/src/sox/band.h b/freedv-dev/src/sox/band.h new file mode 100644 index 00000000..5398ff45 --- /dev/null +++ b/freedv-dev/src/sox/band.h @@ -0,0 +1,47 @@ +/* libSoX Bandpass effect file. July 5, 1991 + * Copyright 1991 Lance Norskog And Sundry Contributors + * + * This source code is freely redistributable and may be used for + * any purpose. This copyright notice must be maintained. + * Lance Norskog And Sundry Contributors are not responsible for + * the consequences of using this software. + * + * Algorithm: 2nd order recursive filter. + * Formula stolen from MUSIC56K, a toolkit of 56000 assembler stuff. + * Quote: + * This is a 2nd order recursive band pass filter of the form. + * y(n)= a * x(n) - b * y(n-1) - c * y(n-2) + * where : + * x(n) = "IN" + * "OUT" = y(n) + * c = EXP(-2*pi*cBW/S_RATE) + * b = -4*c/(1+c)*COS(2*pi*cCF/S_RATE) + * if cSCL=2 (i.e. noise input) + * a = SQT(((1+c)*(1+c)-b*b)*(1-c)/(1+c)) + * else + * a = SQT(1-b*b/(4*c))*(1-c) + * endif + * note : cCF is the center frequency in Hertz + * cBW is the band width in Hertz + * cSCL is a scale factor, use 1 for pitched sounds + * use 2 for noise. + * + * + * July 1, 1999 - Jan Paul Schmidt + * + * This looks like the resonator band pass in SPKit. It's a + * second order all-pole (IIR) band-pass filter described + * at the pages 186 - 189 in + * Dodge, Charles & Jerse, Thomas A. 1985: + * Computer Music -- Synthesis, Composition and Performance. + * New York: Schirmer Books. + * Reference from the SPKit manual. + */ + + p->a2 = exp(-2 * M_PI * bw_Hz / effp->in_signal.rate); + p->a1 = -4 * p->a2 / (1 + p->a2) * cos(2 * M_PI * p->fc / effp->in_signal.rate); + p->b0 = sqrt(1 - p->a1 * p->a1 / (4 * p->a2)) * (1 - p->a2); + if (p->filter_type == filter_BPF_SPK_N) { + mult = sqrt(((1+p->a2) * (1+p->a2) - p->a1*p->a1) * (1-p->a2) / (1+p->a2)) / p->b0; + p->b0 *= mult; + } diff --git a/freedv-dev/src/sox/biquad.c b/freedv-dev/src/sox/biquad.c new file mode 100644 index 00000000..c57f1902 --- /dev/null +++ b/freedv-dev/src/sox/biquad.c @@ -0,0 +1,178 @@ +/* libSoX Biquad filter common functions (c) 2006-7 robs@users.sourceforge.net + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "biquad.h" +#include + +typedef biquad_t priv_t; + +static char const * const width_str[] = { + "band-width(Hz)", + "band-width(kHz)", + "band-width(Hz, no warp)", /* deprecated */ + "band-width(octaves)", + "Q", + "slope", +}; +static char const all_width_types[] = "hkboqs"; + + +int lsx_biquad_getopts(sox_effect_t * effp, int argc, char **argv, + int min_args, int max_args, int fc_pos, int width_pos, int gain_pos, + char const * allowed_width_types, filter_t filter_type) +{ + priv_t * p = (priv_t *)effp->priv; + char width_type = *allowed_width_types; + char dummy, * dummy_p; /* To check for extraneous chars. */ + --argc, ++argv; + + p->filter_type = filter_type; + if (argc < min_args || argc > max_args || + (argc > fc_pos && ((p->fc = lsx_parse_frequency(argv[fc_pos], &dummy_p)) <= 0 || *dummy_p)) || + (argc > width_pos && ((unsigned)(sscanf(argv[width_pos], "%lf%c %c", &p->width, &width_type, &dummy)-1) > 1 || p->width <= 0)) || + (argc > gain_pos && sscanf(argv[gain_pos], "%lf %c", &p->gain, &dummy) != 1) || + !strchr(allowed_width_types, width_type) || (width_type == 's' && p->width > 1)) + return lsx_usage(effp); + p->width_type = strchr(all_width_types, width_type) - all_width_types; + if ((size_t)p->width_type >= strlen(all_width_types)) + p->width_type = 0; + if (p->width_type == width_bw_kHz) { + p->width *= 1000; + p->width_type = width_bw_Hz; + } + return SOX_SUCCESS; +} + + +static int start(sox_effect_t * effp) +{ + priv_t * p = (priv_t *)effp->priv; + /* Simplify: */ + p->b2 /= p->a0; + p->b1 /= p->a0; + p->b0 /= p->a0; + p->a2 /= p->a0; + p->a1 /= p->a0; + + p->o2 = p->o1 = p->i2 = p->i1 = 0; + return SOX_SUCCESS; +} + + +int lsx_biquad_start(sox_effect_t * effp) +{ + priv_t * p = (priv_t *)effp->priv; + + start(effp); + + if (effp->global_info->plot == sox_plot_octave) { + printf( + "%% GNU Octave file (may also work with MATLAB(R) )\n" + "Fs=%g;minF=10;maxF=Fs/2;\n" + "sweepF=logspace(log10(minF),log10(maxF),200);\n" + "[h,w]=freqz([%.15e %.15e %.15e],[1 %.15e %.15e],sweepF,Fs);\n" + "semilogx(w,20*log10(h))\n" + "title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)')\n" + "xlabel('Frequency (Hz)')\n" + "ylabel('Amplitude Response (dB)')\n" + "axis([minF maxF -35 25])\n" + "grid on\n" + "disp('Hit return to continue')\n" + "pause\n" + , effp->in_signal.rate, p->b0, p->b1, p->b2, p->a1, p->a2 + , effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width + , effp->in_signal.rate); + return SOX_EOF; + } + if (effp->global_info->plot == sox_plot_gnuplot) { + printf( + "# gnuplot file\n" + "set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)'\n" + "set xlabel 'Frequency (Hz)'\n" + "set ylabel 'Amplitude Response (dB)'\n" + "Fs=%g\n" + "b0=%.15e; b1=%.15e; b2=%.15e; a1=%.15e; a2=%.15e\n" + "o=2*pi/Fs\n" + "H(f)=sqrt((b0*b0+b1*b1+b2*b2+2.*(b0*b1+b1*b2)*cos(f*o)+2.*(b0*b2)*cos(2.*f*o))/(1.+a1*a1+a2*a2+2.*(a1+a1*a2)*cos(f*o)+2.*a2*cos(2.*f*o)))\n" + "set logscale x\n" + "set samples 250\n" + "set grid xtics ytics\n" + "set key off\n" + "plot [f=10:Fs/2] [-35:25] 20*log10(H(f))\n" + "pause -1 'Hit return to continue'\n" + , effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width + , effp->in_signal.rate, effp->in_signal.rate + , p->b0, p->b1, p->b2, p->a1, p->a2); + return SOX_EOF; + } + if (effp->global_info->plot == sox_plot_data) { + printf("# SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)\n" + "# IIR filter\n" + "# rate: %g\n" + "# name: b\n" + "# type: matrix\n" + "# rows: 3\n" + "# columns: 1\n" + "%24.16e\n%24.16e\n%24.16e\n" + "# name: a\n" + "# type: matrix\n" + "# rows: 3\n" + "# columns: 1\n" + "%24.16e\n%24.16e\n%24.16e\n" + , effp->handler.name, p->gain, p->fc, width_str[p->width_type], p->width + , effp->in_signal.rate, effp->in_signal.rate + , p->b0, p->b1, p->b2, 1. /* a0 */, p->a1, p->a2); + return SOX_EOF; + } + return SOX_SUCCESS; +} + + +int lsx_biquad_flow(sox_effect_t * effp, const sox_sample_t *ibuf, + sox_sample_t *obuf, size_t *isamp, size_t *osamp) +{ + priv_t * p = (priv_t *)effp->priv; + size_t len = *isamp = *osamp = min(*isamp, *osamp); + while (len--) { + double o0 = *ibuf*p->b0 + p->i1*p->b1 + p->i2*p->b2 - p->o1*p->a1 - p->o2*p->a2; + p->i2 = p->i1, p->i1 = *ibuf++; + p->o2 = p->o1, p->o1 = o0; + *obuf++ = SOX_ROUND_CLIP_COUNT(o0, effp->clips); + } + return SOX_SUCCESS; +} + +static int create(sox_effect_t * effp, int argc, char * * argv) +{ + priv_t * p = (priv_t *)effp->priv; + double * d = &p->b0; + char c; + + --argc, ++argv; + if (argc == 6) + for (; argc && sscanf(*argv, "%lf%c", d, &c) == 1; --argc, ++argv, ++d); + return argc? lsx_usage(effp) : SOX_SUCCESS; +} + +sox_effect_handler_t const * lsx_biquad_effect_fn(void) +{ + static sox_effect_handler_t handler = { + "biquad", "b0 b1 b2 a0 a1 a2", 0, + create, lsx_biquad_start, lsx_biquad_flow, NULL, NULL, NULL, sizeof(priv_t) + }; + return &handler; +} diff --git a/freedv-dev/src/sox/biquad.h b/freedv-dev/src/sox/biquad.h new file mode 100644 index 00000000..8786ac83 --- /dev/null +++ b/freedv-dev/src/sox/biquad.h @@ -0,0 +1,78 @@ +/* libSoX Biquad filter common definitions (c) 2006-7 robs@users.sourceforge.net + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef biquad_included +#define biquad_included + +#define LSX_EFF_ALIAS +#include "sox_i.h" + +typedef enum { + filter_LPF, + filter_HPF, + filter_BPF_CSG, + filter_BPF, + filter_notch, + filter_APF, + filter_peakingEQ, + filter_lowShelf, + filter_highShelf, + filter_LPF_1, + filter_HPF_1, + filter_BPF_SPK, + filter_BPF_SPK_N, + filter_AP1, + filter_AP2, + filter_deemph, + filter_riaa +} filter_t; + +typedef enum { + width_bw_Hz, + width_bw_kHz, + /* The old, non-RBJ, non-freq-warped band-pass/reject response; + * leaving here for now just in case anybody misses it: */ + width_bw_old, + width_bw_oct, + width_Q, + width_slope +} width_t; + +/* Private data for the biquad filter effects */ +typedef struct { + double gain; /* For EQ filters */ + double fc; /* Centre/corner/cutoff frequency */ + double width; /* Filter width; interpreted as per width_type */ + width_t width_type; + + filter_t filter_type; + + double b0, b1, b2; /* Filter coefficients */ + double a0, a1, a2; /* Filter coefficients */ + + sox_sample_t i1, i2; /* Filter memory */ + double o1, o2; /* Filter memory */ +} biquad_t; + +int lsx_biquad_getopts(sox_effect_t * effp, int n, char **argv, + int min_args, int max_args, int fc_pos, int width_pos, int gain_pos, + char const * allowed_width_types, filter_t filter_type); +int lsx_biquad_start(sox_effect_t * effp); +int lsx_biquad_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf, + size_t *isamp, size_t *osamp); + +#endif diff --git a/freedv-dev/src/sox/biquads.c b/freedv-dev/src/sox/biquads.c new file mode 100644 index 00000000..19793a6d --- /dev/null +++ b/freedv-dev/src/sox/biquads.c @@ -0,0 +1,400 @@ +/* libSoX Biquad filter effects (c) 2006-8 robs@users.sourceforge.net + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + * 2-pole filters designed by Robert Bristow-Johnson + * see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt + * + * 1-pole filters based on code (c) 2000 Chris Bagwell + * Algorithms: Recursive single pole low/high pass filter + * Reference: The Scientist and Engineer's Guide to Digital Signal Processing + * + * low-pass: output[N] = input[N] * A + output[N-1] * B + * X = exp(-2.0 * pi * Fc) + * A = 1 - X + * B = X + * Fc = cutoff freq / sample rate + * + * Mimics an RC low-pass filter: + * + * ---/\/\/\/\-----------> + * | + * --- C + * --- + * | + * | + * V + * + * high-pass: output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1] + * X = exp(-2.0 * pi * Fc) + * A0 = (1 + X) / 2 + * A1 = -(1 + X) / 2 + * B1 = X + * Fc = cutoff freq / sample rate + * + * Mimics an RC high-pass filter: + * + * || C + * ----||---------> + * || | + * < + * > R + * < + * | + * V + */ + + +#include "biquad.h" +#include +#include + +typedef biquad_t priv_t; + + +static int hilo1_getopts(sox_effect_t * effp, int argc, char **argv) { + return lsx_biquad_getopts(effp, argc, argv, 1, 1, 0, 1, 2, "", + *effp->handler.name == 'l'? filter_LPF_1 : filter_HPF_1); +} + + +static int hilo2_getopts(sox_effect_t * effp, int argc, char **argv) { + priv_t * p = (priv_t *)effp->priv; + if (argc > 1 && strcmp(argv[1], "-1") == 0) + return hilo1_getopts(effp, argc - 1, argv + 1); + if (argc > 1 && strcmp(argv[1], "-2") == 0) + ++argv, --argc; + p->width = sqrt(0.5); /* Default to Butterworth */ + return lsx_biquad_getopts(effp, argc, argv, 1, 2, 0, 1, 2, "qohk", + *effp->handler.name == 'l'? filter_LPF : filter_HPF); +} + + +static int bandpass_getopts(sox_effect_t * effp, int argc, char **argv) { + filter_t type = filter_BPF; + if (argc > 1 && strcmp(argv[1], "-c") == 0) + ++argv, --argc, type = filter_BPF_CSG; + return lsx_biquad_getopts(effp, argc, argv, 2, 2, 0, 1, 2, "hkqob", type); +} + + +static int bandrej_getopts(sox_effect_t * effp, int argc, char **argv) { + return lsx_biquad_getopts(effp, argc, argv, 2, 2, 0, 1, 2, "hkqob", filter_notch); +} + + +static int allpass_getopts(sox_effect_t * effp, int argc, char **argv) { + filter_t type = filter_APF; + int m; + if (argc > 1 && strcmp(argv[1], "-1") == 0) + ++argv, --argc, type = filter_AP1; + else if (argc > 1 && strcmp(argv[1], "-2") == 0) + ++argv, --argc, type = filter_AP2; + m = 1 + (type == filter_APF); + return lsx_biquad_getopts(effp, argc, argv, m, m, 0, 1, 2, "hkqo", type); +} + + +static int tone_getopts(sox_effect_t * effp, int argc, char **argv) { + priv_t * p = (priv_t *)effp->priv; + p->width = 0.5; + p->fc = *effp->handler.name == 'b'? 100 : 3000; + return lsx_biquad_getopts(effp, argc, argv, 1, 3, 1, 2, 0, "shkqo", + *effp->handler.name == 'b'? filter_lowShelf: filter_highShelf); +} + + +static int equalizer_getopts(sox_effect_t * effp, int argc, char **argv) { + return lsx_biquad_getopts(effp, argc, argv, 3, 3, 0, 1, 2, "qohk", filter_peakingEQ); +} + + +static int band_getopts(sox_effect_t * effp, int argc, char **argv) { + filter_t type = filter_BPF_SPK; + if (argc > 1 && strcmp(argv[1], "-n") == 0) + ++argv, --argc, type = filter_BPF_SPK_N; + return lsx_biquad_getopts(effp, argc, argv, 1, 2, 0, 1, 2, "hkqo", type); +} + + +static int deemph_getopts(sox_effect_t * effp, int argc, char **argv) { + priv_t * p = (priv_t *)effp->priv; + p->fc = 5283; + p->width = 0.4845; + p->gain = -9.477; + return lsx_biquad_getopts(effp, argc, argv, 0, 0, 0, 1, 2, "s", filter_deemph); +} + + +static int riaa_getopts(sox_effect_t * effp, int argc, char **argv) { + priv_t * p = (priv_t *)effp->priv; + p->filter_type = filter_riaa; + (void)argv; + return --argc? lsx_usage(effp) : SOX_SUCCESS; +} + + +static void make_poly_from_roots( + double const * roots, size_t num_roots, double * poly) +{ + size_t i, j; + poly[0] = 1; + poly[1] = -roots[0]; + memset(poly + 2, 0, (num_roots + 1 - 2) * sizeof(*poly)); + for (i = 1; i < num_roots; ++i) + for (j = num_roots; j > 0; --j) + poly[j] -= poly[j - 1] * roots[i]; +} + +static int start(sox_effect_t * effp) +{ + priv_t * p = (priv_t *)effp->priv; + double w0 = 2 * M_PI * p->fc / effp->in_signal.rate; + double A = exp(p->gain / 40 * log(10.)); + double alpha = 0, mult = dB_to_linear(max(p->gain, 0)); + + if (w0 > M_PI) { + lsx_fail("frequency must be less than half the sample-rate (Nyquist rate)"); + return SOX_EOF; + } + + /* Set defaults: */ + p->b0 = p->b1 = p->b2 = p->a1 = p->a2 = 0; + p->a0 = 1; + + if (p->width) switch (p->width_type) { + case width_slope: + alpha = sin(w0)/2 * sqrt((A + 1/A)*(1/p->width - 1) + 2); + break; + + case width_Q: + alpha = sin(w0)/(2*p->width); + break; + + case width_bw_oct: + alpha = sin(w0)*sinh(log(2.)/2 * p->width * w0/sin(w0)); + break; + + case width_bw_Hz: + alpha = sin(w0)/(2*p->fc/p->width); + break; + + case width_bw_kHz: assert(0); /* Shouldn't get here */ + + case width_bw_old: + alpha = tan(M_PI * p->width / effp->in_signal.rate); + break; + } + switch (p->filter_type) { + case filter_LPF: /* H(s) = 1 / (s^2 + s/Q + 1) */ + p->b0 = (1 - cos(w0))/2; + p->b1 = 1 - cos(w0); + p->b2 = (1 - cos(w0))/2; + p->a0 = 1 + alpha; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha; + break; + + case filter_HPF: /* H(s) = s^2 / (s^2 + s/Q + 1) */ + p->b0 = (1 + cos(w0))/2; + p->b1 = -(1 + cos(w0)); + p->b2 = (1 + cos(w0))/2; + p->a0 = 1 + alpha; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha; + break; + + case filter_BPF_CSG: /* H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) */ + p->b0 = sin(w0)/2; + p->b1 = 0; + p->b2 = -sin(w0)/2; + p->a0 = 1 + alpha; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha; + break; + + case filter_BPF: /* H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) */ + p->b0 = alpha; + p->b1 = 0; + p->b2 = -alpha; + p->a0 = 1 + alpha; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha; + break; + + case filter_notch: /* H(s) = (s^2 + 1) / (s^2 + s/Q + 1) */ + p->b0 = 1; + p->b1 = -2*cos(w0); + p->b2 = 1; + p->a0 = 1 + alpha; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha; + break; + + case filter_APF: /* H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) */ + p->b0 = 1 - alpha; + p->b1 = -2*cos(w0); + p->b2 = 1 + alpha; + p->a0 = 1 + alpha; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha; + break; + + case filter_peakingEQ: /* H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) */ + if (A == 1) + return SOX_EFF_NULL; + p->b0 = 1 + alpha*A; + p->b1 = -2*cos(w0); + p->b2 = 1 - alpha*A; + p->a0 = 1 + alpha/A; + p->a1 = -2*cos(w0); + p->a2 = 1 - alpha/A; + break; + + case filter_lowShelf: /* H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) */ + if (A == 1) + return SOX_EFF_NULL; + p->b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha ); + p->b1 = 2*A*( (A-1) - (A+1)*cos(w0) ); + p->b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha ); + p->a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha; + p->a1 = -2*( (A-1) + (A+1)*cos(w0) ); + p->a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha; + break; + + case filter_deemph: /* See deemph.plt for documentation */ + if (effp->in_signal.rate != 44100) { + lsx_fail("Sample rate must be 44100 (audio-CD)"); + return SOX_EOF; + } + /* Falls through... */ + + case filter_highShelf: /* H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) */ + if (!A) + return SOX_EFF_NULL; + p->b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha ); + p->b1 = -2*A*( (A-1) + (A+1)*cos(w0) ); + p->b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha ); + p->a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha; + p->a1 = 2*( (A-1) - (A+1)*cos(w0) ); + p->a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha; + break; + + case filter_LPF_1: /* single-pole */ + p->a1 = -exp(-w0); + p->b0 = 1 + p->a1; + break; + + case filter_HPF_1: /* single-pole */ + p->a1 = -exp(-w0); + p->b0 = (1 - p->a1)/2; + p->b1 = -p->b0; + break; + + case filter_BPF_SPK: case filter_BPF_SPK_N: { + double bw_Hz; + if (!p->width) + p->width = p->fc / 2; + bw_Hz = p->width_type == width_Q? p->fc / p->width : + p->width_type == width_bw_Hz? p->width : + p->fc * (pow(2., p->width) - 1) * pow(2., -0.5 * p->width); /* bw_oct */ + #include "band.h" /* Has different licence */ + break; + } + + case filter_AP1: /* Experimental 1-pole all-pass from Tom Erbe @ UCSD */ + p->b0 = exp(-w0); + p->b1 = -1; + p->a1 = -exp(-w0); + break; + + case filter_AP2: /* Experimental 2-pole all-pass from Tom Erbe @ UCSD */ + p->b0 = 1 - sin(w0); + p->b1 = -2 * cos(w0); + p->b2 = 1 + sin(w0); + p->a0 = 1 + sin(w0); + p->a1 = -2 * cos(w0); + p->a2 = 1 - sin(w0); + break; + + case filter_riaa: /* http://www.dsprelated.com/showmessage/73300/3.php */ + if (effp->in_signal.rate == 44100) { + static const double zeros[] = {-0.2014898, 0.9233820}; + static const double poles[] = {0.7083149, 0.9924091}; + make_poly_from_roots(zeros, (size_t)2, &p->b0); + make_poly_from_roots(poles, (size_t)2, &p->a0); + } + else if (effp->in_signal.rate == 48000) { + static const double zeros[] = {-0.1766069, 0.9321590}; + static const double poles[] = {0.7396325, 0.9931330}; + make_poly_from_roots(zeros, (size_t)2, &p->b0); + make_poly_from_roots(poles, (size_t)2, &p->a0); + } + else if (effp->in_signal.rate == 88200) { + static const double zeros[] = {-0.1168735, 0.9648312}; + static const double poles[] = {0.8590646, 0.9964002}; + make_poly_from_roots(zeros, (size_t)2, &p->b0); + make_poly_from_roots(poles, (size_t)2, &p->a0); + } + else if (effp->in_signal.rate == 96000) { + static const double zeros[] = {-0.1141486, 0.9676817}; + static const double poles[] = {0.8699137, 0.9966946}; + make_poly_from_roots(zeros, (size_t)2, &p->b0); + make_poly_from_roots(poles, (size_t)2, &p->a0); + } + else { + lsx_fail("Sample rate must be 44.1k, 48k, 88.2k, or 96k"); + return SOX_EOF; + } + { /* Normalise to 0dB at 1kHz (Thanks to Glenn Davis) */ + double y = 2 * M_PI * 1000 / effp->in_signal.rate; + double b_re = p->b0 + p->b1 * cos(-y) + p->b2 * cos(-2 * y); + double a_re = p->a0 + p->a1 * cos(-y) + p->a2 * cos(-2 * y); + double b_im = p->b1 * sin(-y) + p->b2 * sin(-2 * y); + double a_im = p->a1 * sin(-y) + p->a2 * sin(-2 * y); + double g = 1 / sqrt((sqr(b_re) + sqr(b_im)) / (sqr(a_re) + sqr(a_im))); + p->b0 *= g; p->b1 *= g; p->b2 *= g; + } + mult = (p->b0 + p->b1 + p->b2) / (p->a0 + p->a1 + p->a2); + lsx_debug("gain=%f", linear_to_dB(mult)); + break; + } + if (effp->in_signal.mult) + *effp->in_signal.mult /= mult; + return lsx_biquad_start(effp); +} + + +#define BIQUAD_EFFECT(name,group,usage,flags) \ +sox_effect_handler_t const * lsx_##name##_effect_fn(void) { \ + static sox_effect_handler_t handler = { \ + #name, usage, flags, \ + group##_getopts, start, lsx_biquad_flow, 0, 0, 0, sizeof(biquad_t)\ + }; \ + return &handler; \ +} + +BIQUAD_EFFECT(highpass, hilo2, "[-1|-2] frequency [width[q|o|h|k](0.707q)]", 0) +BIQUAD_EFFECT(lowpass, hilo2, "[-1|-2] frequency [width[q|o|h|k]](0.707q)", 0) +BIQUAD_EFFECT(bandpass, bandpass, "[-c] frequency width[h|k|q|o]", 0) +BIQUAD_EFFECT(bandreject,bandrej, "frequency width[h|k|q|o]", 0) +BIQUAD_EFFECT(allpass, allpass, "frequency width[h|k|q|o]", 0) +BIQUAD_EFFECT(bass, tone, "gain [frequency(100) [width[s|h|k|q|o]](0.5s)]", 0) +BIQUAD_EFFECT(treble, tone, "gain [frequency(3000) [width[s|h|k|q|o]](0.5s)]", 0) +BIQUAD_EFFECT(equalizer, equalizer,"frequency width[q|o|h|k] gain", 0) +BIQUAD_EFFECT(band, band, "[-n] center [width[h|k|q|o]]", 0) +BIQUAD_EFFECT(deemph, deemph, NULL, 0) +BIQUAD_EFFECT(riaa, riaa, NULL, 0) diff --git a/freedv-dev/src/sox/effects.c b/freedv-dev/src/sox/effects.c new file mode 100644 index 00000000..435412fa --- /dev/null +++ b/freedv-dev/src/sox/effects.c @@ -0,0 +1,544 @@ +/* SoX Effects chain (c) 2007 robs@users.sourceforge.net + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define LSX_EFF_ALIAS +#include "sox_i.h" +#include +#include +#ifdef HAVE_STRINGS_H + #include +#endif + +#define DEBUG_EFFECTS_CHAIN 0 + +/* Default effect handler functions for do-nothing situations: */ + +static int default_function(sox_effect_t * effp UNUSED) +{ + return SOX_SUCCESS; +} + +/* Pass through samples verbatim */ +int lsx_flow_copy(sox_effect_t * effp UNUSED, const sox_sample_t * ibuf, + sox_sample_t * obuf, size_t * isamp, size_t * osamp) +{ + *isamp = *osamp = min(*isamp, *osamp); + memcpy(obuf, ibuf, *isamp * sizeof(*obuf)); + return SOX_SUCCESS; +} + +/* Inform no more samples to drain */ +static int default_drain(sox_effect_t * effp UNUSED, sox_sample_t *obuf UNUSED, size_t *osamp) +{ + *osamp = 0; + return SOX_EOF; +} + +/* Check that no parameters have been given */ +static int default_getopts(sox_effect_t * effp, int argc, char **argv UNUSED) +{ + return --argc? lsx_usage(effp) : SOX_SUCCESS; +} + +/* Partially initialise the effect structure; signal info will come later */ +sox_effect_t * sox_create_effect(sox_effect_handler_t const * eh) +{ + sox_effect_t * effp = lsx_calloc(1, sizeof(*effp)); + effp->obuf = NULL; + + effp->global_info = sox_get_effects_globals(); + effp->handler = *eh; + if (!effp->handler.getopts) effp->handler.getopts = default_getopts; + if (!effp->handler.start ) effp->handler.start = default_function; + if (!effp->handler.flow ) effp->handler.flow = lsx_flow_copy; + if (!effp->handler.drain ) effp->handler.drain = default_drain; + if (!effp->handler.stop ) effp->handler.stop = default_function; + if (!effp->handler.kill ) effp->handler.kill = default_function; + + effp->priv = lsx_calloc(1, effp->handler.priv_size); + + return effp; +} /* sox_create_effect */ + +int sox_effect_options(sox_effect_t *effp, int argc, char * const argv[]) +{ + int result; + + char * * argv2 = lsx_malloc((argc + 1) * sizeof(*argv2)); + argv2[0] = (char *)effp->handler.name; + memcpy(argv2 + 1, argv, argc * sizeof(*argv2)); + result = effp->handler.getopts(effp, argc + 1, argv2); + free(argv2); + return result; +} /* sox_effect_options */ + +/* Effects chain: */ + +sox_effects_chain_t * sox_create_effects_chain( + sox_encodinginfo_t const * in_enc, sox_encodinginfo_t const * out_enc) +{ + sox_effects_chain_t * result = lsx_calloc(1, sizeof(sox_effects_chain_t)); + result->global_info = *sox_get_effects_globals(); + result->in_enc = in_enc; + result->out_enc = out_enc; + return result; +} /* sox_create_effects_chain */ + +void sox_delete_effects_chain(sox_effects_chain_t *ecp) +{ + if (ecp && ecp->length) + sox_delete_effects(ecp); + free(ecp->effects); + free(ecp); +} /* sox_delete_effects_chain */ + +/* Effect can call in start() or flow() to set minimum input size to flow() */ +int lsx_effect_set_imin(sox_effect_t * effp, size_t imin) +{ + if (imin > sox_globals.bufsiz / effp->flows) { + lsx_fail("sox_bufsiz not big enough"); + return SOX_EOF; + } + + effp->imin = imin; + return SOX_SUCCESS; +} + +/* Effects table to be extended in steps of EFF_TABLE_STEP */ +#define EFF_TABLE_STEP 8 + +/* Add an effect to the chain. *in is the input signal for this effect. *out is + * a suggestion as to what the output signal should be, but depending on its + * given options and *in, the effect can choose to do differently. Whatever + * output rate and channels the effect does produce are written back to *in, + * ready for the next effect in the chain. + */ +int sox_add_effect(sox_effects_chain_t * chain, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out) +{ + int ret, (*start)(sox_effect_t * effp) = effp->handler.start; + unsigned f; + sox_effect_t eff0; /* Copy of effect for flow 0 before calling start */ + + effp->global_info = &chain->global_info; + effp->in_signal = *in; + effp->out_signal = *out; + effp->in_encoding = chain->in_enc; + effp->out_encoding = chain->out_enc; + if (!(effp->handler.flags & SOX_EFF_CHAN)) + effp->out_signal.channels = in->channels; + if (!(effp->handler.flags & SOX_EFF_RATE)) + effp->out_signal.rate = in->rate; + if (!(effp->handler.flags & SOX_EFF_PREC)) + effp->out_signal.precision = (effp->handler.flags & SOX_EFF_MODIFY)? + in->precision : SOX_SAMPLE_PRECISION; + if (!(effp->handler.flags & SOX_EFF_GAIN)) + effp->out_signal.mult = in->mult; + + effp->flows = + (effp->handler.flags & SOX_EFF_MCHAN)? 1 : effp->in_signal.channels; + effp->clips = 0; + effp->imin = 0; + eff0 = *effp, eff0.priv = lsx_memdup(eff0.priv, eff0.handler.priv_size); + eff0.in_signal.mult = NULL; /* Only used in channel 0 */ + ret = start(effp); + if (ret == SOX_EFF_NULL) { + lsx_report("has no effect in this configuration"); + free(eff0.priv); + free(effp->priv); + effp->priv = NULL; + return SOX_SUCCESS; + } + if (ret != SOX_SUCCESS) { + free(eff0.priv); + return SOX_EOF; + } + if (in->mult) + lsx_debug("mult=%g", *in->mult); + + if (!(effp->handler.flags & SOX_EFF_LENGTH)) { + effp->out_signal.length = in->length; + if (effp->out_signal.length != SOX_UNKNOWN_LEN) { + if (effp->handler.flags & SOX_EFF_CHAN) + effp->out_signal.length = + effp->out_signal.length / in->channels * effp->out_signal.channels; + if (effp->handler.flags & SOX_EFF_RATE) + effp->out_signal.length = + effp->out_signal.length / in->rate * effp->out_signal.rate + .5; + } + } + + *in = effp->out_signal; + + if (chain->length == chain->table_size) { + chain->table_size += EFF_TABLE_STEP; + lsx_debug_more("sox_add_effect: extending effects table, " + "new size = %lu", (unsigned long)chain->table_size); + lsx_revalloc(chain->effects, chain->table_size); + } + + chain->effects[chain->length] = + lsx_calloc(effp->flows, sizeof(chain->effects[chain->length][0])); + chain->effects[chain->length][0] = *effp; + + for (f = 1; f < effp->flows; ++f) { + chain->effects[chain->length][f] = eff0; + chain->effects[chain->length][f].flow = f; + chain->effects[chain->length][f].priv = lsx_memdup(eff0.priv, eff0.handler.priv_size); + if (start(&chain->effects[chain->length][f]) != SOX_SUCCESS) { + free(eff0.priv); + return SOX_EOF; + } + } + + ++chain->length; + free(eff0.priv); + return SOX_SUCCESS; +} + +static int flow_effect(sox_effects_chain_t * chain, size_t n) +{ + sox_effect_t * effp1 = &chain->effects[n - 1][0]; + sox_effect_t * effp = &chain->effects[n][0]; + int effstatus = SOX_SUCCESS, f = 0; + size_t i; + const sox_sample_t *ibuf; + size_t idone = effp1->oend - effp1->obeg; + size_t obeg = sox_globals.bufsiz - effp->oend; +#if DEBUG_EFFECTS_CHAIN + size_t pre_idone = idone; + size_t pre_odone = obeg; +#endif + + if (effp->flows == 1) { /* Run effect on all channels at once */ + idone -= idone % effp->in_signal.channels; + effstatus = effp->handler.flow(effp, &effp1->obuf[effp1->obeg], + &effp->obuf[effp->oend], &idone, &obeg); + if (obeg % effp->out_signal.channels != 0) { + lsx_fail("multi-channel effect flowed asymmetrically!"); + effstatus = SOX_EOF; + } + } else { /* Run effect on each channel individually */ + sox_sample_t *obuf = &effp->obuf[effp->oend]; + size_t idone_last = 0, odone_last = 0; /* Initialised to prevent warning */ + + ibuf = &effp1->obuf[effp1->obeg]; + for (i = 0; i < idone; i += effp->flows) + for (f = 0; f < (int)effp->flows; ++f) + chain->ibufc[f][i / effp->flows] = *ibuf++; + +#ifdef HAVE_OPENMP + if (sox_globals.use_threads && effp->flows > 1) + { + #pragma omp parallel for + for (f = 0; f < (int)effp->flows; ++f) { + size_t idonec = idone / effp->flows; + size_t odonec = obeg / effp->flows; + int eff_status_c = effp->handler.flow(&chain->effects[n][f], + chain->ibufc[f], chain->obufc[f], &idonec, &odonec); + if (!f) { + idone_last = idonec; + odone_last = odonec; + } + + if (eff_status_c != SOX_SUCCESS) + effstatus = SOX_EOF; + } + } + else /* sox_globals.use_threads */ +#endif + { + for (f = 0; f < (int)effp->flows; ++f) { + size_t idonec = idone / effp->flows; + size_t odonec = obeg / effp->flows; + int eff_status_c = effp->handler.flow(&chain->effects[n][f], + chain->ibufc[f], chain->obufc[f], &idonec, &odonec); + if (f && (idonec != idone_last || odonec != odone_last)) { + lsx_fail("flowed asymmetrically!"); + effstatus = SOX_EOF; + } + idone_last = idonec; + odone_last = odonec; + + if (eff_status_c != SOX_SUCCESS) + effstatus = SOX_EOF; + } + } + + for (i = 0; i < odone_last; ++i) + for (f = 0; f < (int)effp->flows; ++f) + *obuf++ = chain->obufc[f][i]; + + idone = effp->flows * idone_last; + obeg = effp->flows * odone_last; + } +#if DEBUG_EFFECTS_CHAIN + lsx_report("flow: %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR, + pre_idone, pre_odone, idone, obeg); +#endif + effp1->obeg += idone; + if (effp1->obeg == effp1->oend) + effp1->obeg = effp1->oend = 0; + else if (effp1->oend - effp1->obeg < effp->imin ) { /* Need to refill? */ + memmove(effp1->obuf, &effp1->obuf[effp1->obeg], (effp1->oend - effp1->obeg) * sizeof(*effp1->obuf)); + effp1->oend -= effp1->obeg; + effp1->obeg = 0; + } + + effp->oend += obeg; + + return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF; +} + +/* The same as flow_effect but with no input */ +static int drain_effect(sox_effects_chain_t * chain, size_t n) +{ + sox_effect_t * effp = &chain->effects[n][0]; + int effstatus = SOX_SUCCESS; + size_t i, f; + size_t obeg = sox_globals.bufsiz - effp->oend; +#if DEBUG_EFFECTS_CHAIN + size_t pre_odone = obeg; +#endif + + if (effp->flows == 1) { /* Run effect on all channels at once */ + effstatus = effp->handler.drain(effp, &effp->obuf[effp->oend], &obeg); + if (obeg % effp->out_signal.channels != 0) { + lsx_fail("multi-channel effect drained asymmetrically!"); + effstatus = SOX_EOF; + } + } else { /* Run effect on each channel individually */ + sox_sample_t *obuf = &effp->obuf[effp->oend]; + size_t odone_last = 0; /* Initialised to prevent warning */ + + for (f = 0; f < effp->flows; ++f) { + size_t odonec = obeg / effp->flows; + int eff_status_c = effp->handler.drain(&chain->effects[n][f], chain->obufc[f], &odonec); + if (f && (odonec != odone_last)) { + lsx_fail("drained asymmetrically!"); + effstatus = SOX_EOF; + } + odone_last = odonec; + + if (eff_status_c != SOX_SUCCESS) + effstatus = SOX_EOF; + } + + for (i = 0; i < odone_last; ++i) + for (f = 0; f < effp->flows; ++f) + *obuf++ = chain->obufc[f][i]; + obeg = f * odone_last; + } +#if DEBUG_EFFECTS_CHAIN + lsx_report("drain: %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR, + (size_t)0, pre_odone, (size_t)0, obeg); +#endif + if (!obeg) /* This is the only thing that drain has and flow hasn't */ + effstatus = SOX_EOF; + + effp->oend += obeg; + + return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF; +} + +/* Flow data through the effects chain until an effect or callback gives EOF */ +int sox_flow_effects(sox_effects_chain_t * chain, int (* callback)(sox_bool all_done, void * client_data), void * client_data) +{ + int flow_status = SOX_SUCCESS; + size_t e, source_e = 0; /* effect indices */ + size_t f, max_flows = 0; + sox_bool draining = sox_true; + + for (e = 0; e < chain->length; ++e) { + chain->effects[e][0].obuf = lsx_realloc(chain->effects[e][0].obuf, + sox_globals.bufsiz * sizeof(chain->effects[e][0].obuf[0])); + /* Possibly there is already a buffer, if this is a used effect; + it may still contain samples in that case. */ + /* Memory will be freed by sox_delete_effect() later. */ + max_flows = max(max_flows, chain->effects[e][0].flows); + } + if (max_flows == 1) /* don't need interleave buffers */ + max_flows = 0; + chain->ibufc = lsx_calloc(max_flows, sizeof(*chain->ibufc)); + chain->obufc = lsx_calloc(max_flows, sizeof(*chain->obufc)); + for (f = 0; f < max_flows; ++f) { + chain->ibufc[f] = lsx_calloc(sox_globals.bufsiz / 2, sizeof(chain->ibufc[f][0])); + chain->obufc[f] = lsx_calloc(sox_globals.bufsiz / 2, sizeof(chain->obufc[f][0])); + } + + e = chain->length - 1; + while (source_e < chain->length) { +#define have_imin (e > 0 && e < chain->length && chain->effects[e - 1][0].oend - chain->effects[e - 1][0].obeg >= chain->effects[e][0].imin) + size_t osize = chain->effects[e][0].oend - chain->effects[e][0].obeg; + if (e == source_e && (draining || !have_imin)) { + if (drain_effect(chain, e) == SOX_EOF) { + ++source_e; + draining = sox_false; + } + } else if (have_imin && flow_effect(chain, e) == SOX_EOF) { + flow_status = SOX_EOF; + if (e == chain->length - 1) + break; + source_e = e; + draining = sox_true; + } + if (e < chain->length && chain->effects[e][0].oend - chain->effects[e][0].obeg > osize) /* False for output */ + ++e; + else if (e == source_e) + draining = sox_true; + else if ((int)--e < (int)source_e) + e = source_e; + + if (callback && callback(source_e == chain->length, client_data) != SOX_SUCCESS) { + flow_status = SOX_EOF; /* Client has requested to stop the flow. */ + break; + } + } + + for (f = 0; f < max_flows; ++f) { + free(chain->ibufc[f]); + free(chain->obufc[f]); + } + free(chain->obufc); + free(chain->ibufc); + + return flow_status; +} + +sox_uint64_t sox_effects_clips(sox_effects_chain_t * chain) +{ + unsigned i, f; + uint64_t clips = 0; + for (i = 1; i < chain->length - 1; ++i) + for (f = 0; f < chain->effects[i][0].flows; ++f) + clips += chain->effects[i][f].clips; + return clips; +} + +sox_uint64_t sox_stop_effect(sox_effect_t *effp) +{ + unsigned f; + uint64_t clips = 0; + + for (f = 0; f < effp->flows; ++f) { + effp[f].handler.stop(&effp[f]); + clips += effp[f].clips; + } + return clips; +} + +void sox_push_effect_last(sox_effects_chain_t *chain, sox_effect_t *effp) +{ + if (chain->length == chain->table_size) { + chain->table_size += EFF_TABLE_STEP; + lsx_debug_more("sox_push_effect_last: extending effects table, " + "new size = %lu", (unsigned long)chain->table_size); + lsx_revalloc(chain->effects, chain->table_size); + } + + chain->effects[chain->length++] = effp; +} /* sox_push_effect_last */ + +sox_effect_t *sox_pop_effect_last(sox_effects_chain_t *chain) +{ + if (chain->length > 0) + { + sox_effect_t *effp; + chain->length--; + effp = chain->effects[chain->length]; + chain->effects[chain->length] = NULL; + return effp; + } + else + return NULL; +} /* sox_pop_effect_last */ + +/* Free resources related to effect. + * Note: This currently closes down the effect which might + * not be obvious from name. + */ +void sox_delete_effect(sox_effect_t *effp) +{ + uint64_t clips; + unsigned f; + + if ((clips = sox_stop_effect(effp)) != 0) + lsx_warn("%s clipped %" PRIu64 " samples; decrease volume?", + effp->handler.name, clips); + if (effp->obeg != effp->oend) + lsx_debug("output buffer still held %" PRIuPTR " samples; dropped.", + (effp->oend - effp->obeg)/effp->out_signal.channels); + /* May or may not indicate a problem; it is normal if the user aborted + processing, or if an effect like "trim" stopped early. */ + effp->handler.kill(effp); /* N.B. only one kill; not one per flow */ + for (f = 0; f < effp->flows; ++f) + free(effp[f].priv); + free(effp->obuf); + free(effp); +} + +void sox_delete_effect_last(sox_effects_chain_t *chain) +{ + if (chain->length > 0) + { + chain->length--; + sox_delete_effect(chain->effects[chain->length]); + chain->effects[chain->length] = NULL; + } +} /* sox_delete_effect_last */ + +/* Remove all effects from the chain. + * Note: This currently closes down the effect which might + * not be obvious from name. + */ +void sox_delete_effects(sox_effects_chain_t * chain) +{ + size_t e; + + for (e = 0; e < chain->length; ++e) { + sox_delete_effect(chain->effects[e]); + chain->effects[e] = NULL; + } + chain->length = 0; +} + +/*----------------------------- Effects library ------------------------------*/ + +static sox_effect_fn_t s_sox_effect_fns[] = { +#define EFFECT(f) lsx_##f##_effect_fn, +#include "effects.h" +#undef EFFECT + NULL +}; + +const sox_effect_fn_t* +sox_get_effect_fns(void) +{ + return s_sox_effect_fns; +} + +/* Find a named effect in the effects library */ +sox_effect_handler_t const * sox_find_effect(char const * name) +{ + int e; + sox_effect_fn_t const * fns = sox_get_effect_fns(); + for (e = 0; fns[e]; ++e) { + const sox_effect_handler_t *eh = fns[e] (); + if (eh && eh->name && strcasecmp(eh->name, name) == 0) + return eh; /* Found it. */ + } + return NULL; +} diff --git a/freedv-dev/src/sox/effects.h b/freedv-dev/src/sox/effects.h new file mode 100644 index 00000000..8d7025c8 --- /dev/null +++ b/freedv-dev/src/sox/effects.h @@ -0,0 +1,22 @@ +/* This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Manually edited for FreeDV to contain just the effects we need */ + + EFFECT(bass) + EFFECT(highpass) + EFFECT(treble) + EFFECT(equalizer) + diff --git a/freedv-dev/src/sox/effects_i.c b/freedv-dev/src/sox/effects_i.c new file mode 100644 index 00000000..e5770a94 --- /dev/null +++ b/freedv-dev/src/sox/effects_i.c @@ -0,0 +1,379 @@ +/* Implements a libSoX internal interface for implementing effects. + * All public functions & data are prefixed with lsx_ . + * + * Copyright (c) 2005-8 Chris Bagwell and SoX contributors + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define LSX_EFF_ALIAS +#include "sox_i.h" +#include +#include + +int lsx_usage(sox_effect_t * effp) +{ + if (effp->handler.usage) + lsx_fail("usage: %s", effp->handler.usage); + else + lsx_fail("this effect takes no parameters"); + return SOX_EOF; +} + +char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n) +{ + if (!*usage) { + size_t i, len; + for (len = i = 0; i < n; len += strlen(lines[i++]) + 1); + *usage = lsx_malloc(len); /* FIXME: this memory will never be freed */ + strcpy(*usage, lines[0]); + for (i = 1; i < n; ++i) { + strcat(*usage, "\n"); + strcat(*usage, lines[i]); + } + } + return *usage; +} + +static lsx_enum_item const s_lsx_wave_enum[] = { + LSX_ENUM_ITEM(SOX_WAVE_,SINE) + LSX_ENUM_ITEM(SOX_WAVE_,TRIANGLE) + {0, 0}}; + +lsx_enum_item const * lsx_get_wave_enum(void) +{ + return s_lsx_wave_enum; +} + +void lsx_generate_wave_table( + lsx_wave_t wave_type, + sox_data_t data_type, + void *table, + size_t table_size, + double min, + double max, + double phase) +{ + uint32_t t; + uint32_t phase_offset = phase / M_PI / 2 * table_size + 0.5; + + for (t = 0; t < table_size; t++) + { + uint32_t point = (t + phase_offset) % table_size; + double d; + switch (wave_type) + { + case SOX_WAVE_SINE: + d = (sin((double)point / table_size * 2 * M_PI) + 1) / 2; + break; + + case SOX_WAVE_TRIANGLE: + d = (double)point * 2 / table_size; + switch (4 * point / table_size) + { + case 0: d = d + 0.5; break; + case 1: case 2: d = 1.5 - d; break; + case 3: d = d - 1.5; break; + } + break; + + default: /* Oops! FIXME */ + d = 0.0; /* Make sure we have a value */ + break; + } + d = d * (max - min) + min; + switch (data_type) + { + case SOX_FLOAT: + { + float *fp = (float *)table; + *fp++ = (float)d; + table = fp; + continue; + } + case SOX_DOUBLE: + { + double *dp = (double *)table; + *dp++ = d; + table = dp; + continue; + } + default: break; + } + d += d < 0? -0.5 : +0.5; + switch (data_type) + { + case SOX_SHORT: + { + short *sp = table; + *sp++ = (short)d; + table = sp; + continue; + } + case SOX_INT: + { + int *ip = table; + *ip++ = (int)d; + table = ip; + continue; + } + default: break; + } + } +} + +/* + * lsx_parsesamples + * + * Parse a string for # of samples. If string ends with a 's' + * then the string is interpreted as a user calculated # of samples. + * If string contains ':' or '.' or if it ends with a 't' then its + * treated as an amount of time. This is converted into seconds and + * fraction of seconds and then use the sample rate to calculate + * # of samples. + * Returns NULL on error, pointer to next char to parse otherwise. + */ +char const * lsx_parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def) +{ + int i, found_samples = 0, found_time = 0; + char const * end; + char const * pos; + sox_bool found_colon, found_dot; + char * str = (char *)str0; + + for (;*str == ' '; ++str); + for (end = str; *end && strchr("0123456789:.ets", *end); ++end); + if (end == str) + return NULL; + + pos = strchr(str, ':'); + found_colon = pos && pos < end; + + pos = strchr(str, '.'); + found_dot = pos && pos < end; + + if (found_colon || found_dot || *(end-1) == 't') + found_time = 1; + else if (*(end-1) == 's') + found_samples = 1; + + if (found_time || (def == 't' && !found_samples)) { + for (*samples = 0, i = 0; *str != '.' && i < 3; ++i) { + char * last_str = str; + long part = strtol(str, &str, 10); + if (!i && str == last_str) + return NULL; + *samples += rate * part; + if (i < 2) { + if (*str != ':') + break; + ++str; + *samples *= 60; + } + } + if (*str == '.') { + char * last_str = str; + double part = strtod(str, &str); + if (str == last_str) + return NULL; + *samples += rate * part + .5; + } + return *str == 't'? str + 1 : str; + } + { + char * last_str = str; + double part = strtod(str, &str); + if (str == last_str) + return NULL; + *samples = part + .5; + return *str == 's'? str + 1 : str; + } +} + +#if 0 + +#include + +#define TEST(st, samp, len) \ + str = st; \ + next = lsx_parsesamples(10000, str, &samples, 't'); \ + assert(samples == samp && next == str + len); + +int main(int argc, char * * argv) +{ + char const * str, * next; + uint64_t samples; + + TEST("0" , 0, 1) + TEST("1" , 10000, 1) + + TEST("0s" , 0, 2) + TEST("0s,", 0, 2) + TEST("0s/", 0, 2) + TEST("0s@", 0, 2) + + TEST("0t" , 0, 2) + TEST("0t,", 0, 2) + TEST("0t/", 0, 2) + TEST("0t@", 0, 2) + + TEST("1s" , 1, 2) + TEST("1s,", 1, 2) + TEST("1s/", 1, 2) + TEST("1s@", 1, 2) + TEST(" 01s" , 1, 4) + TEST("1e6s" , 1000000, 4) + + TEST("1t" , 10000, 2) + TEST("1t,", 10000, 2) + TEST("1t/", 10000, 2) + TEST("1t@", 10000, 2) + TEST("1.1t" , 11000, 4) + TEST("1.1t,", 11000, 4) + TEST("1.1t/", 11000, 4) + TEST("1.1t@", 11000, 4) + TEST("1e6t" , 10000, 1) + + TEST(".0", 0, 2) + TEST("0.0", 0, 3) + TEST("0:0.0", 0, 5) + TEST("0:0:0.0", 0, 7) + + TEST(".1", 1000, 2) + TEST(".10", 1000, 3) + TEST("0.1", 1000, 3) + TEST("1.1", 11000, 3) + TEST("1:1.1", 611000, 5) + TEST("1:1:1.1", 36611000, 7) + TEST("1:1", 610000, 3) + TEST("1:01", 610000, 4) + TEST("1:1:1", 36610000, 5) + TEST("1:", 600000, 2) + TEST("1::", 36000000, 3) + + TEST("0.444444", 4444, 8) + TEST("0.555555", 5556, 8) + + assert(!lsx_parsesamples(10000, "x", &samples, 't')); + return 0; +} +#endif + +/* a note is given as an int, + * 0 => 440 Hz = A + * >0 => number of half notes 'up', + * <0 => number of half notes down, + * example 12 => A of next octave, 880Hz + * + * calculated by freq = 440Hz * 2**(note/12) + */ +static double calc_note_freq(double note, int key) +{ + if (key != INT_MAX) { /* Just intonation. */ + static const int n[] = {16, 9, 6, 5, 4, 7}; /* Numerator. */ + static const int d[] = {15, 8, 5, 4, 3, 5}; /* Denominator. */ + static double j[13]; /* Just semitones */ + int i, m = floor(note); + + if (!j[1]) for (i = 1; i <= 12; ++i) + j[i] = i <= 6? log((double)n[i - 1] / d[i - 1]) / log(2.) : 1 - j[12 - i]; + note -= m; + m -= key = m - ((INT_MAX / 2 - ((INT_MAX / 2) % 12) + m - key) % 12); + return 440 * pow(2., key / 12. + j[m] + (j[m + 1] - j[m]) * note); + } + return 440 * pow(2., note / 12); +} + +int lsx_parse_note(char const * text, char * * end_ptr) +{ + int result = INT_MAX; + + if (*text >= 'A' && *text <= 'G') { + result = (int)(5/3. * (*text++ - 'A') + 9.5) % 12 - 9; + if (*text == 'b') {--result; ++text;} + else if (*text == '#') {++result; ++text;} + if (isdigit((unsigned char)*text)) + result += 12 * (*text++ - '4'); + } + *end_ptr = (char *)text; + return result; +} + +/* Read string 'text' and convert to frequency. + * 'text' can be a positive number which is the frequency in Hz. + * If 'text' starts with a '%' and a following number the corresponding + * note is calculated. + * Return -1 on error. + */ +double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key) +{ + double result; + + if (*text == '%') { + result = strtod(text + 1, end_ptr); + if (*end_ptr == text + 1) + return -1; + return calc_note_freq(result, key); + } + if (*text >= 'A' && *text <= 'G') { + int result2 = lsx_parse_note(text, end_ptr); + return result2 == INT_MAX? - 1 : calc_note_freq((double)result2, key); + } + result = strtod(text, end_ptr); + if (end_ptr) { + if (*end_ptr == text) + return -1; + if (**end_ptr == 'k') { + result *= 1000; + ++*end_ptr; + } + } + return result < 0 ? -1 : result; +} + +FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename) +{ + FILE * file; + + if (!filename || !strcmp(filename, "-")) { + if (effp->global_info->global_info->stdin_in_use_by) { + lsx_fail("stdin already in use by `%s'", effp->global_info->global_info->stdin_in_use_by); + return NULL; + } + effp->global_info->global_info->stdin_in_use_by = effp->handler.name; + file = stdin; + } + else if (!(file = fopen(filename, "r"))) { + lsx_fail("couldn't open file %s: %s", filename, strerror(errno)); + return NULL; + } + return file; +} + +int lsx_effects_init(void) +{ + #ifndef __FREEDV__ + init_fft_cache(); + #endif + return SOX_SUCCESS; +} + +int lsx_effects_quit(void) +{ + #ifndef __FREEDV__ + clear_fft_cache(); + #endif + return SOX_SUCCESS; +} diff --git a/freedv-dev/src/sox/formats_i.c b/freedv-dev/src/sox/formats_i.c new file mode 100644 index 00000000..17c40615 --- /dev/null +++ b/freedv-dev/src/sox/formats_i.c @@ -0,0 +1,487 @@ +/* Implements a libSoX internal interface for use in implementing file formats. + * All public functions & data are prefixed with lsx_ . + * + * (c) 2005-8 Chris Bagwell and SoX contributors + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sox_i.h" +#include +#include +#include + +void lsx_fail_errno(sox_format_t * ft, int sox_errno, const char *fmt, ...) +{ + va_list args; + + ft->sox_errno = sox_errno; + + va_start(args, fmt); +#ifdef HAVE_VSNPRINTF + vsnprintf(ft->sox_errstr, sizeof(ft->sox_errstr), fmt, args); +#else + vsprintf(ft->sox_errstr, fmt, args); +#endif + va_end(args); + ft->sox_errstr[255] = '\0'; +} + +void lsx_set_signal_defaults(sox_format_t * ft) +{ + if (!ft->signal.rate ) ft->signal.rate = SOX_DEFAULT_RATE; + if (!ft->signal.precision) ft->signal.precision = SOX_DEFAULT_PRECISION; + if (!ft->signal.channels ) ft->signal.channels = SOX_DEFAULT_CHANNELS; + + if (!ft->encoding.bits_per_sample) + ft->encoding.bits_per_sample = ft->signal.precision; + if (ft->encoding.encoding == SOX_ENCODING_UNKNOWN) + ft->encoding.encoding = SOX_ENCODING_SIGN2; +} + +#ifndef __FREEDV__ +int lsx_check_read_params(sox_format_t * ft, unsigned channels, + sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, + uint64_t num_samples, sox_bool check_length) +{ + ft->signal.length = ft->signal.length == SOX_IGNORE_LENGTH? SOX_UNSPEC : num_samples; + + if (ft->seekable) + ft->data_start = lsx_tell(ft); + + if (channels && ft->signal.channels && ft->signal.channels != channels) + lsx_warn("`%s': overriding number of channels", ft->filename); + else ft->signal.channels = channels; + + if (rate && ft->signal.rate && ft->signal.rate != rate) + lsx_warn("`%s': overriding sample rate", ft->filename); + else ft->signal.rate = rate; + + if (encoding && ft->encoding.encoding && ft->encoding.encoding != encoding) + lsx_warn("`%s': overriding encoding type", ft->filename); + else ft->encoding.encoding = encoding; + + if (bits_per_sample && ft->encoding.bits_per_sample && ft->encoding.bits_per_sample != bits_per_sample) + lsx_warn("`%s': overriding encoding size", ft->filename); + ft->encoding.bits_per_sample = bits_per_sample; + + if (check_length && ft->encoding.bits_per_sample && lsx_filelength(ft)) { + uint64_t calculated_length = div_bits(lsx_filelength(ft) - ft->data_start, ft->encoding.bits_per_sample); + if (!ft->signal.length) + ft->signal.length = calculated_length; + else if (num_samples != calculated_length) + lsx_warn("`%s': file header gives the total number of samples as %" PRIu64 " but file length indicates the number is in fact %" PRIu64, ft->filename, num_samples, calculated_length); + } + + if (sox_precision(ft->encoding.encoding, ft->encoding.bits_per_sample)) + return SOX_SUCCESS; + lsx_fail_errno(ft, EINVAL, "invalid format for this file type"); + return SOX_EOF; +} +#endif + +/* Read in a buffer of data of length len bytes. + * Returns number of bytes read. + */ +size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len) +{ + size_t ret = fread(buf, (size_t) 1, len, (FILE*)ft->fp); + if (ret != len && ferror((FILE*)ft->fp)) + lsx_fail_errno(ft, errno, "lsx_readbuf"); + ft->tell_off += ret; + return ret; +} + +/* Skip input without seeking. */ +int lsx_skipbytes(sox_format_t * ft, size_t n) +{ + unsigned char trash; + + while (n--) + if (lsx_readb(ft, &trash) == SOX_EOF) + return (SOX_EOF); + + return (SOX_SUCCESS); +} + +/* Pad output. */ +int lsx_padbytes(sox_format_t * ft, size_t n) +{ + while (n--) + if (lsx_writeb(ft, '\0') == SOX_EOF) + return (SOX_EOF); + + return (SOX_SUCCESS); +} + +/* Write a buffer of data of length bytes. + * Returns number of bytes written. + */ +size_t lsx_writebuf(sox_format_t * ft, void const * buf, size_t len) +{ + size_t ret = fwrite(buf, (size_t) 1, len, (FILE*)ft->fp); + if (ret != len) { + lsx_fail_errno(ft, errno, "error writing output file"); + clearerr((FILE*)ft->fp); /* Allows us to seek back to write header */ + } + ft->tell_off += ret; + return ret; +} + +uint64_t lsx_filelength(sox_format_t * ft) +{ + struct stat st; + int ret = fstat(fileno((FILE*)ft->fp), &st); + + return (!ret && (st.st_mode & S_IFREG))? (uint64_t)st.st_size : 0; +} + +int lsx_flush(sox_format_t * ft) +{ + return fflush((FILE*)ft->fp); +} + +off_t lsx_tell(sox_format_t * ft) +{ + return ft->seekable? (off_t)ftello((FILE*)ft->fp) : (off_t)ft->tell_off; +} + +int lsx_eof(sox_format_t * ft) +{ + return feof((FILE*)ft->fp); +} + +int lsx_error(sox_format_t * ft) +{ + return ferror((FILE*)ft->fp); +} + +void lsx_rewind(sox_format_t * ft) +{ + rewind((FILE*)ft->fp); + ft->tell_off = 0; +} + +void lsx_clearerr(sox_format_t * ft) +{ + clearerr((FILE*)ft->fp); + ft->sox_errno = 0; +} + +int lsx_unreadb(sox_format_t * ft, unsigned b) +{ + return ungetc((int)b, ft->fp); +} + +/* Implements traditional fseek() behavior. Meant to abstract out + * file operations so that they could one day also work on memory + * buffers. + * + * N.B. Can only seek forwards on non-seekable streams! + */ +int lsx_seeki(sox_format_t * ft, off_t offset, int whence) +{ + if (ft->seekable == 0) { + /* If a stream peel off chars else EPERM */ + if (whence == SEEK_CUR) { + while (offset > 0 && !feof((FILE*)ft->fp)) { + getc((FILE*)ft->fp); + offset--; + ++ft->tell_off; + } + if (offset) + lsx_fail_errno(ft,SOX_EOF, "offset past EOF"); + else + ft->sox_errno = SOX_SUCCESS; + } else + lsx_fail_errno(ft,SOX_EPERM, "file not seekable"); + } else { + if (fseeko((FILE*)ft->fp, offset, whence) == -1) + lsx_fail_errno(ft,errno, "%s", strerror(errno)); + else + ft->sox_errno = SOX_SUCCESS; + } + return ft->sox_errno; +} + +int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample) +{ + double wide_sample = to_sample - (to_sample % ft->signal.channels); + double to_d = wide_sample * ft->encoding.bits_per_sample / 8; + off_t to = to_d; + return (to != to_d)? SOX_EOF : lsx_seeki(ft, (byte_offset + to), SEEK_SET); +} + +/* Read and write known datatypes in "machine format". Swap if indicated. + * They all return SOX_EOF on error and SOX_SUCCESS on success. + */ +/* Read n-char string (and possibly null-terminating). + * Stop reading and null-terminate string if either a 0 or \n is reached. + */ +int lsx_reads(sox_format_t * ft, char *c, size_t len) +{ + char *sc; + char in; + + sc = c; + do + { + if (lsx_readbuf(ft, &in, (size_t)1) != 1) + { + *sc = 0; + return (SOX_EOF); + } + if (in == 0 || in == '\n') + break; + + *sc = in; + sc++; + } while (sc - c < (ptrdiff_t)len); + *sc = 0; + return(SOX_SUCCESS); +} + +/* Write null-terminated string (without \0). */ +int lsx_writes(sox_format_t * ft, char const * c) +{ + if (lsx_writebuf(ft, c, strlen(c)) != strlen(c)) + return(SOX_EOF); + return(SOX_SUCCESS); +} + +/* return swapped 32-bit float */ +static void lsx_swapf(float * f) +{ + union { + uint32_t dw; + float f; + } u; + + u.f= *f; + u.dw= (u.dw>>24) | ((u.dw>>8)&0xff00) | ((u.dw<<8)&0xff0000) | (u.dw<<24); + *f = u.f; +} + +static void swap(void * data, size_t len) +{ + uint8_t * bytes = (uint8_t *)data; + size_t i; + + for (i = 0; i < len / 2; ++i) { + char tmp = bytes[i]; + bytes[i] = bytes[len - 1 - i]; + bytes[len - 1 - i] = tmp; + } +} + +static double lsx_swapdf(double data) +{ + swap(&data, sizeof(data)); + return data; +} + +static uint64_t lsx_swapqw(uint64_t data) +{ + swap(&data, sizeof(data)); + return data; +} + +/* Lookup table to reverse the bit order of a byte. ie MSB become LSB */ +static uint8_t const cswap[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, + 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, + 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, + 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, + 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, + 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, + 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, + 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, + 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, + 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, + 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, + 0x3F, 0xBF, 0x7F, 0xFF +}; + +/* Utilities to byte-swap values, use libc optimized macros if possible */ +#define TWIDDLE_BYTE(ub, type) \ + do { \ + if (ft->encoding.reverse_bits) \ + ub = cswap[ub]; \ + if (ft->encoding.reverse_nibbles) \ + ub = ((ub & 15) << 4) | (ub >> 4); \ + } while (0); + +#define TWIDDLE_WORD(uw, type) \ + if (ft->encoding.reverse_bytes) \ + uw = lsx_swap ## type(uw); + +#define TWIDDLE_FLOAT(f, type) \ + if (ft->encoding.reverse_bytes) \ + lsx_swapf(&f); + +/* N.B. This macro doesn't work for unaligned types (e.g. 3-byte + types). */ +#define READ_FUNC(type, size, ctype, twiddle) \ + size_t lsx_read_ ## type ## _buf( \ + sox_format_t * ft, ctype *buf, size_t len) \ + { \ + size_t n, nread; \ + nread = lsx_readbuf(ft, buf, len * size) / size; \ + for (n = 0; n < nread; n++) \ + twiddle(buf[n], type); \ + return nread; \ + } + +/* Unpack a 3-byte value from a uint8_t * */ +#define sox_unpack3(p) (ft->encoding.reverse_bytes == MACHINE_IS_BIGENDIAN? \ + ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16)) : \ + ((p)[2] | ((p)[1] << 8) | ((p)[0] << 16))) + +/* This (slower) macro works for unaligned types (e.g. 3-byte types) + that need to be unpacked. */ +#define READ_FUNC_UNPACK(type, size, ctype, twiddle) \ + size_t lsx_read_ ## type ## _buf( \ + sox_format_t * ft, ctype *buf, size_t len) \ + { \ + size_t n, nread; \ + uint8_t *data = lsx_malloc(size * len); \ + nread = lsx_readbuf(ft, data, len * size) / size; \ + for (n = 0; n < nread; n++) \ + buf[n] = sox_unpack ## size(data + n * size); \ + free(data); \ + return n; \ + } + +READ_FUNC(b, 1, uint8_t, TWIDDLE_BYTE) +READ_FUNC(w, 2, uint16_t, TWIDDLE_WORD) +READ_FUNC_UNPACK(3, 3, sox_uint24_t, TWIDDLE_WORD) +READ_FUNC(dw, 4, uint32_t, TWIDDLE_WORD) +READ_FUNC(qw, 8, uint64_t, TWIDDLE_WORD) +READ_FUNC(f, sizeof(float), float, TWIDDLE_FLOAT) +READ_FUNC(df, sizeof(double), double, TWIDDLE_WORD) + +#define READ1_FUNC(type, ctype) \ +int lsx_read ## type(sox_format_t * ft, ctype * datum) { \ + if (lsx_read_ ## type ## _buf(ft, datum, (size_t)1) == 1) \ + return SOX_SUCCESS; \ + if (!lsx_error(ft)) \ + lsx_fail_errno(ft, errno, premature_eof); \ + return SOX_EOF; \ +} + +static char const premature_eof[] = "premature EOF"; + +READ1_FUNC(b, uint8_t) +READ1_FUNC(w, uint16_t) +READ1_FUNC(3, sox_uint24_t) +READ1_FUNC(dw, uint32_t) +READ1_FUNC(qw, uint64_t) +READ1_FUNC(f, float) +READ1_FUNC(df, double) + +int lsx_readchars(sox_format_t * ft, char * chars, size_t len) +{ + size_t ret = lsx_readbuf(ft, chars, len); + if (ret == len) + return SOX_SUCCESS; + if (!lsx_error(ft)) + lsx_fail_errno(ft, errno, premature_eof); + return SOX_EOF; +} + +/* N.B. This macro doesn't work for unaligned types (e.g. 3-byte + types). */ +#define WRITE_FUNC(type, size, ctype, twiddle) \ + size_t lsx_write_ ## type ## _buf( \ + sox_format_t * ft, ctype *buf, size_t len) \ + { \ + size_t n, nwritten; \ + for (n = 0; n < len; n++) \ + twiddle(buf[n], type); \ + nwritten = lsx_writebuf(ft, buf, len * size); \ + return nwritten / size; \ + } + +/* Pack a 3-byte value to a uint8_t * */ +#define sox_pack3(p, v) do {if (ft->encoding.reverse_bytes == MACHINE_IS_BIGENDIAN)\ +{(p)[0] = v & 0xff; (p)[1] = (v >> 8) & 0xff; (p)[2] = (v >> 16) & 0xff;} else \ +{(p)[2] = v & 0xff; (p)[1] = (v >> 8) & 0xff; (p)[0] = (v >> 16) & 0xff;} \ +} while (0) + +/* This (slower) macro works for unaligned types (e.g. 3-byte types) + that need to be packed. */ +#define WRITE_FUNC_PACK(type, size, ctype, twiddle) \ + size_t lsx_write_ ## type ## _buf( \ + sox_format_t * ft, ctype *buf, size_t len) \ + { \ + size_t n, nwritten; \ + uint8_t *data = lsx_malloc(size * len); \ + for (n = 0; n < len; n++) \ + sox_pack ## size(data + n * size, buf[n]); \ + nwritten = lsx_writebuf(ft, data, len * size); \ + free(data); \ + return nwritten / size; \ + } + +WRITE_FUNC(b, 1, uint8_t, TWIDDLE_BYTE) +WRITE_FUNC(w, 2, uint16_t, TWIDDLE_WORD) +WRITE_FUNC_PACK(3, 3, sox_uint24_t, TWIDDLE_WORD) +WRITE_FUNC(dw, 4, uint32_t, TWIDDLE_WORD) +WRITE_FUNC(qw, 8, uint64_t, TWIDDLE_WORD) +WRITE_FUNC(f, sizeof(float), float, TWIDDLE_FLOAT) +WRITE_FUNC(df, sizeof(double), double, TWIDDLE_WORD) + +#define WRITE1U_FUNC(type, ctype) \ + int lsx_write ## type(sox_format_t * ft, unsigned d) \ + { ctype datum = (ctype)d; \ + return lsx_write_ ## type ## _buf(ft, &datum, (size_t)1) == 1 ? SOX_SUCCESS : SOX_EOF; \ + } + +#define WRITE1S_FUNC(type, ctype) \ + int lsx_writes ## type(sox_format_t * ft, signed d) \ + { ctype datum = (ctype)d; \ + return lsx_write_ ## type ## _buf(ft, &datum, (size_t)1) == 1 ? SOX_SUCCESS : SOX_EOF; \ + } + +#define WRITE1_FUNC(type, ctype) \ + int lsx_write ## type(sox_format_t * ft, ctype datum) \ + { \ + return lsx_write_ ## type ## _buf(ft, &datum, (size_t)1) == 1 ? SOX_SUCCESS : SOX_EOF; \ + } + +WRITE1U_FUNC(b, uint8_t) +WRITE1U_FUNC(w, uint16_t) +WRITE1U_FUNC(3, sox_uint24_t) +WRITE1U_FUNC(dw, uint32_t) +WRITE1_FUNC(qw, uint64_t) +WRITE1S_FUNC(b, uint8_t) +WRITE1S_FUNC(w, uint16_t) +WRITE1_FUNC(df, double) + +int lsx_writef(sox_format_t * ft, double datum) +{ + float f = datum; + return lsx_write_f_buf(ft, &f, (size_t) 1) == 1 ? SOX_SUCCESS : SOX_EOF; +} diff --git a/freedv-dev/src/sox/libsox.c b/freedv-dev/src/sox/libsox.c new file mode 100644 index 00000000..43620250 --- /dev/null +++ b/freedv-dev/src/sox/libsox.c @@ -0,0 +1,225 @@ +/* Implements the public API for libSoX general functions + * All public functions & data are prefixed with sox_ . + * + * (c) 2006-8 Chris Bagwell and SoX contributors + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sox_i.h" +#include + +const char *sox_version(void) +{ + static char versionstr[20]; + + sprintf(versionstr, "%d.%d.%d", + (SOX_LIB_VERSION_CODE & 0xff0000) >> 16, + (SOX_LIB_VERSION_CODE & 0x00ff00) >> 8, + (SOX_LIB_VERSION_CODE & 0x0000ff)); + return(versionstr); +} + +sox_version_info_t const * sox_version_info(void) +{ +#define STRINGIZE1(x) #x +#define STRINGIZE(x) STRINGIZE1(x) + static char arch[30]; + static sox_version_info_t info = { + /* size */ + sizeof(sox_version_info_t), + /* flags */ + (sox_version_flags_t)( +#if HAVE_POPEN + sox_version_have_popen + +#endif +#if HAVE_MAGIC + sox_version_have_magic + +#endif +#if HAVE_OPENMP + sox_version_have_threads + +#endif +#ifdef HAVE_FMEMOPEN + sox_version_have_memopen + +#endif + sox_version_none), + /* version_code */ + SOX_LIB_VERSION_CODE, + /* version */ + NULL, + /* sox_version_extra */ +#ifdef PACKAGE_EXTRA + PACKAGE_EXTRA, +#else + NULL, +#endif + /* sox_time */ + __DATE__ " " __TIME__, + /* sox_distro */ +#ifdef DISTRO + DISTRO, +#else + NULL, +#endif + /* sox_compiler */ +#if defined __GNUC__ + "gcc " __VERSION__, +#elif defined _MSC_VER + "msvc " STRINGIZE(_MSC_FULL_VER), +#elif defined __SUNPRO_C + fprintf(file, "sun c " STRINGIZE(__SUNPRO_C), +#else + NULL, +#endif + /* sox_arch */ + NULL + }; + + if (!info.version) + { + info.version = sox_version(); + } + + if (!info.arch) + { + snprintf(arch, sizeof(arch), + "%" PRIuPTR "%" PRIuPTR "%" PRIuPTR "%" PRIuPTR + " %" PRIuPTR "%" PRIuPTR " %" PRIuPTR "%" PRIuPTR " %c %s", + sizeof(char), sizeof(short), sizeof(long), sizeof(off_t), + sizeof(float), sizeof(double), sizeof(int *), sizeof(int (*)(void)), + MACHINE_IS_BIGENDIAN ? 'B' : 'L', + (info.flags & sox_version_have_threads) ? "OMP" : ""); + arch[sizeof(arch) - 1] = 0; + info.arch = arch; + } + + return &info; +} + +/* Default routine to output messages; can be overridden */ +static void output_message( + unsigned level, const char *filename, const char *fmt, va_list ap) +{ + if (sox_globals.verbosity >= level) { + char base_name[128]; + sox_basename(base_name, sizeof(base_name), filename); + fprintf(stderr, "%s: ", base_name); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } +} + +static sox_globals_t s_sox_globals = { + 2, /* unsigned verbosity */ + output_message, /* sox_output_message_handler */ + sox_false, /* sox_bool repeatable */ + 8192, /* size_t bufsiz */ + 0, /* size_t input_bufsiz */ + 0, /* int32_t ranqd1 */ + NULL, /* char const * stdin_in_use_by */ + NULL, /* char const * stdout_in_use_by */ + NULL, /* char const * subsystem */ + NULL, /* char * tmp_path */ + sox_false, /* sox_bool use_magic */ + sox_false /* sox_bool use_threads */ +}; + +sox_globals_t * sox_get_globals(void) +{ + return &s_sox_globals; +} + +/* FIXME: Not thread safe using globals */ +static sox_effects_globals_t s_sox_effects_globals = + {sox_plot_off, &s_sox_globals}; + +sox_effects_globals_t * +sox_get_effects_globals(void) +{ + return &s_sox_effects_globals; +} + +char const * sox_strerror(int sox_errno) +{ + static char const * const errors[] = { + "Invalid Audio Header", + "Unsupported data format", + "Can't allocate memory", + "Operation not permitted", + "Operation not supported", + "Invalid argument", + }; + if (sox_errno < SOX_EHDR) + return strerror(sox_errno); + sox_errno -= SOX_EHDR; + if (sox_errno < 0 || (size_t)sox_errno >= array_length(errors)) + return "Unknown error"; + return errors[sox_errno]; +} + +size_t sox_basename(char * base_buffer, size_t base_buffer_len, const char * filename) +{ + if (!base_buffer || !base_buffer_len) + { + return 0; + } + else + { + char const * slash_pos = LAST_SLASH(filename); + char const * base_name = slash_pos ? slash_pos + 1 : filename; + char const * dot_pos = strrchr(base_name, '.'); + size_t i, len; + dot_pos = dot_pos ? dot_pos : base_name + strlen(base_name); + len = dot_pos - base_name; + len = min(len, base_buffer_len - 1); + for (i = 0; i < len; i++) + { + base_buffer[i] = base_name[i]; + } + base_buffer[i] = 0; + return i; + } +} + +#define SOX_MESSAGE_FUNCTION(name,level) \ +void name(char const * fmt, ...) { \ + va_list ap; \ + va_start(ap, fmt); \ + if (sox_globals.output_message_handler) \ + (*sox_globals.output_message_handler)(level,sox_globals.subsystem,fmt,ap); \ + va_end(ap); \ +} + +SOX_MESSAGE_FUNCTION(lsx_fail_impl , 1) +SOX_MESSAGE_FUNCTION(lsx_warn_impl , 2) +SOX_MESSAGE_FUNCTION(lsx_report_impl, 3) +SOX_MESSAGE_FUNCTION(lsx_debug_impl , 4) +SOX_MESSAGE_FUNCTION(lsx_debug_more_impl , 5) +SOX_MESSAGE_FUNCTION(lsx_debug_most_impl , 6) + +#undef SOX_MESSAGE_FUNCTION + +int sox_init(void) +{ + return lsx_effects_init(); +} + +int sox_quit(void) +{ + #ifndef __FREEDV__ + sox_format_quit(); + #endif + return lsx_effects_quit(); +} diff --git a/freedv-dev/src/sox/sox.h b/freedv-dev/src/sox/sox.h new file mode 100644 index 00000000..05372558 --- /dev/null +++ b/freedv-dev/src/sox/sox.h @@ -0,0 +1,2608 @@ +/* libSoX Library Public Interface + * + * Copyright 1999-2011 Chris Bagwell and SoX Contributors. + * + * This source code is freely redistributable and may be used for + * any purpose. This copyright notice must be maintained. + * Chris Bagwell And SoX Contributors are not responsible for + * the consequences of using this software. + */ + +/** @file +Contains the interface exposed to clients of the libSoX library. +Symbols starting with "sox_" or "SOX_" are part of the public interface for +libSoX clients (applications that consume libSoX). Symbols starting with +"lsx_" or "LSX_" are internal use by libSoX and plugins. +LSX_ and lsx_ symbols should not be used by libSoX-based applications. +*/ + +#ifndef SOX_H +#define SOX_H /**< Client API: This macro is defined if sox.h has been included. */ + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Suppress warnings from use of type long long. */ +#if defined __GNUC__ +#pragma GCC system_header +#endif + +/***************************************************************************** +API decoration macros: +Mostly for documentation purposes. For some compilers, decorations also affect +code generation, influence compiler warnings or activate compiler +optimizations. +*****************************************************************************/ + +/** +Plugins API: +Attribute required on all functions exported by libSoX and on all function +pointer types used by the libSoX API. +*/ +#ifdef __GNUC__ +#define LSX_API __attribute__ ((cdecl)) /* libSoX function */ +#elif _MSC_VER +#define LSX_API __cdecl /* libSoX function */ +#else +#define LSX_API /* libSoX function */ +#endif + +/** +Plugins API: +Attribute applied to a parameter or local variable to suppress warnings about +the variable being unused (especially in macro-generated code). +*/ +#ifdef __GNUC__ +#define LSX_UNUSED __attribute__ ((unused)) /* Parameter or local variable is intentionally unused. */ +#else +#define LSX_UNUSED /* Parameter or local variable is intentionally unused. */ +#endif + +/** +Plugins API: +LSX_PRINTF12: Attribute applied to a function to indicate that it requires +a printf-style format string for arg1 and that printf parameters start at +arg2. +*/ +#ifdef __GNUC__ +#define LSX_PRINTF12 __attribute__ ((format (printf, 1, 2))) /* Function has printf-style arguments. */ +#else +#define LSX_PRINTF12 /* Function has printf-style arguments. */ +#endif + +/** +Plugins API: +Attribute applied to a function to indicate that it has no side effects and +depends only its input parameters and global memory. If called repeatedly, it +returns the same result each time. +*/ +#ifdef __GNUC__ +#define LSX_RETURN_PURE __attribute__ ((pure)) /* Function is pure. */ +#else +#define LSX_RETURN_PURE /* Function is pure. */ +#endif + +/** +Plugins API: +Attribute applied to a function to indicate that the +return value is always a pointer to a valid object (never NULL). +*/ +#ifdef _Ret_ +#define LSX_RETURN_VALID _Ret_ /* Function always returns a valid object (never NULL). */ +#else +#define LSX_RETURN_VALID /* Function always returns a valid object (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a function to indicate that the return value is always a +pointer to a valid array (never NULL). +*/ +#ifdef _Ret_valid_ +#define LSX_RETURN_ARRAY _Ret_valid_ /* Function always returns a valid array (never NULL). */ +#else +#define LSX_RETURN_ARRAY /* Function always returns a valid array (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a function to indicate that the return value is always a +pointer to a valid 0-terminated array (never NULL). +*/ +#ifdef _Ret_z_ +#define LSX_RETURN_VALID_Z _Ret_z_ /* Function always returns a 0-terminated array (never NULL). */ +#else +#define LSX_RETURN_VALID_Z /* Function always returns a 0-terminated array (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a function to indicate that the returned pointer may be +null. +*/ +#ifdef _Ret_opt_ +#define LSX_RETURN_OPT _Ret_opt_ /* Function may return NULL. */ +#else +#define LSX_RETURN_OPT /* Function may return NULL. */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to one const element of the pointed-to type (never NULL). +*/ +#ifdef _In_ +#define LSX_PARAM_IN _In_ /* Required const pointer to a valid object (never NULL). */ +#else +#define LSX_PARAM_IN /* Required const pointer to a valid object (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to a const 0-terminated string (never NULL). +*/ +#ifdef _In_z_ +#define LSX_PARAM_IN_Z _In_z_ /* Required const pointer to 0-terminated string (never NULL). */ +#else +#define LSX_PARAM_IN_Z /* Required const pointer to 0-terminated string (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a const +pointer to a 0-terminated printf format string. +*/ +#ifdef _Printf_format_string_ +#define LSX_PARAM_IN_PRINTF _Printf_format_string_ /* Required const pointer to 0-terminated printf format string (never NULL). */ +#else +#define LSX_PARAM_IN_PRINTF /* Required const pointer to 0-terminated printf format string (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to (len) const initialized elements of the pointed-to type, where +(len) is the name of another parameter. +@param len The parameter that contains the number of elements in the array. +*/ +#ifdef _In_count_ +#define LSX_PARAM_IN_COUNT(len) _In_count_(len) /* Required const pointer to (len) valid objects (never NULL). */ +#else +#define LSX_PARAM_IN_COUNT(len) /* Required const pointer to (len) valid objects (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to (len) const bytes of initialized data, where (len) is the name of +another parameter. +@param len The parameter that contains the number of bytes in the array. +*/ +#ifdef _In_bytecount_ +#define LSX_PARAM_IN_BYTECOUNT(len) _In_bytecount_(len) /* Required const pointer to (len) bytes of data (never NULL). */ +#else +#define LSX_PARAM_IN_BYTECOUNT(len) /* Required const pointer to (len) bytes of data (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is either NULL +or a valid pointer to one const element of the pointed-to type. +*/ +#ifdef _In_opt_ +#define LSX_PARAM_IN_OPT _In_opt_ /* Optional const pointer to a valid object (may be NULL). */ +#else +#define LSX_PARAM_IN_OPT /* Optional const pointer to a valid object (may be NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is either NULL +or a valid pointer to a const 0-terminated string. +*/ +#ifdef _In_opt_z_ +#define LSX_PARAM_IN_OPT_Z _In_opt_z_ /* Optional const pointer to 0-terminated string (may be NULL). */ +#else +#define LSX_PARAM_IN_OPT_Z /* Optional const pointer to 0-terminated string (may be NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to one initialized element of the pointed-to type (never NULL). The +function may modify the element. +*/ +#ifdef _Inout_ +#define LSX_PARAM_INOUT _Inout_ /* Required pointer to a valid object (never NULL). */ +#else +#define LSX_PARAM_INOUT /* Required pointer to a valid object (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to (len) initialized elements of the pointed-to type (never NULL). The +function may modify the elements. +@param len The parameter that contains the number of elements in the array. +*/ +#ifdef _Inout_count_x_ +#define LSX_PARAM_INOUT_COUNT(len) _Inout_count_x_(len) /* Required pointer to (len) valid objects (never NULL). */ +#else +#define LSX_PARAM_INOUT_COUNT(len) /* Required pointer to (len) valid objects (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to memory sufficient for one element of the pointed-to type (never +NULL). The function will initialize the element. +*/ +#ifdef _Out_ +#define LSX_PARAM_OUT _Out_ /* Required pointer to an object to be initialized (never NULL). */ +#else +#define LSX_PARAM_OUT /* Required pointer to an object to be initialized (never NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to memory sufficient for (len) bytes of data (never NULL), where (len) +is the name of another parameter. The function may write up to len bytes of +data to this memory. +@param len The parameter that contains the number of bytes in the array. +*/ +#ifdef _Out_bytecap_ +#define LSX_PARAM_OUT_BYTECAP(len) _Out_bytecap_(len) /* Required pointer to writable buffer with room for len bytes. */ +#else +#define LSX_PARAM_OUT_BYTECAP(len) /* Required pointer to writable buffer with room for len bytes. */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to memory sufficient for (len) elements of the pointed-to type (never +NULL), where (len) is the name of another parameter. On return, (filled) +elements will have been initialized, where (filled) is either the dereference +of another pointer parameter (for example "*written") or the "return" +parameter (indicating that the function returns the number of elements +written). +@param len The parameter that contains the number of elements in the array. +@param filled The dereference of the parameter that receives the number of elements written to the array, or "return" if the value is returned. +*/ +#ifdef _Out_cap_post_count_ +#define LSX_PARAM_OUT_CAP_POST_COUNT(len,filled) _Out_cap_post_count_(len,filled) /* Required pointer to buffer for (len) elements (never NULL); on return, (filled) elements will have been initialized. */ +#else +#define LSX_PARAM_OUT_CAP_POST_COUNT(len,filled) /* Required pointer to buffer for (len) elements (never NULL); on return, (filled) elements will have been initialized. */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer to memory sufficient for (len) elements of the pointed-to type (never +NULL), where (len) is the name of another parameter. On return, (filled+1) +elements will have been initialized, with the last element having been +initialized to 0, where (filled) is either the dereference of another pointer +parameter (for example, "*written") or the "return" parameter (indicating that +the function returns the number of elements written). +@param len The parameter that contains the number of elements in the array. +@param filled The dereference of the parameter that receives the number of elements written to the array (not counting the terminating null), or "return" if the value is returned. +*/ +#ifdef _Out_z_cap_post_count_ +#define LSX_PARAM_OUT_Z_CAP_POST_COUNT(len,filled) _Out_z_cap_post_count_(len,filled) /* Required pointer to buffer for (len) elements (never NULL); on return, (filled+1) elements will have been initialized, and the array will be 0-terminated. */ +#else +#define LSX_PARAM_OUT_Z_CAP_POST_COUNT(len,filled) /* Required pointer to buffer for (len) elements (never NULL); on return, (filled+1) elements will have been initialized, and the array will be 0-terminated. */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is either NULL +or a valid pointer to memory sufficient for one element of the pointed-to +type. The function will initialize the element. +*/ +#ifdef _Out_opt_ +#define LSX_PARAM_OUT_OPT _Out_opt_ /* Optional pointer to an object to be initialized (may be NULL). */ +#else +#define LSX_PARAM_OUT_OPT /* Optional pointer to an object to be initialized (may be NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer (never NULL) to another pointer which may be NULL when the function is +invoked. +*/ +#ifdef _Deref_pre_maybenull_ +#define LSX_PARAM_DEREF_PRE_MAYBENULL _Deref_pre_maybenull_ /* Required pointer (never NULL) to another pointer (may be NULL). */ +#else +#define LSX_PARAM_DEREF_PRE_MAYBENULL /* Required pointer (never NULL) to another pointer (may be NULL). */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer (never NULL) to another pointer which will be NULL when the function +returns. +*/ +#ifdef _Deref_post_null_ +#define LSX_PARAM_DEREF_POST_NULL _Deref_post_null_ /* Required pointer (never NULL) to another pointer, which will be NULL on exit. */ +#else +#define LSX_PARAM_DEREF_POST_NULL /* Required pointer (never NULL) to another pointer, which will be NULL on exit. */ +#endif + +/** +Plugins API: +Attribute applied to a parameter to indicate that the parameter is a valid +pointer (never NULL) to another pointer which will be non-NULL when the +function returns. +*/ +#ifdef _Deref_post_notnull_ +#define LSX_PARAM_DEREF_POST_NOTNULL _Deref_post_notnull_ /* Required pointer (never NULL) to another pointer, which will be valid (not NULL) on exit. */ +#else +#define LSX_PARAM_DEREF_POST_NOTNULL /* Required pointer (never NULL) to another pointer, which will be valid (not NULL) on exit. */ +#endif + +/** +Plugins API: +Expression that "uses" a potentially-unused variable to avoid compiler +warnings (especially in macro-generated code). +*/ +#ifdef _PREFAST_ +#define LSX_USE_VAR(x) ((void)(x=0)) /* During static analysis, initialize unused variables to 0. */ +#else +#define LSX_USE_VAR(x) ((void)(x)) /* Parameter or variable is intentionally unused. */ +#endif + +/** +Plugins API: +Compile-time assertion. Causes a compile error if the expression is false. +@param e The expression to test. If expression is false, compilation will fail. +@param f A unique identifier for the test, for example foo_must_not_be_zero. +*/ +#define lsx_static_assert(e,f) enum {lsx_static_assert_##f = 1/((e) ? 1 : 0)} + +/***************************************************************************** +Basic typedefs: +*****************************************************************************/ + +/** +Client API: +Signed twos-complement 8-bit type. Typically defined as signed char. +*/ +#if SCHAR_MAX==127 && SCHAR_MIN==(-128) +typedef signed char sox_int8_t; +#elif CHAR_MAX==127 && CHAR_MIN==(-128) +typedef char sox_int8_t; +#else +#error Unable to determine an appropriate definition for sox_int8_t. +#endif + +/** +Client API: +Unsigned 8-bit type. Typically defined as unsigned char. +*/ +#if UCHAR_MAX==0xff +typedef unsigned char sox_uint8_t; +#elif CHAR_MAX==0xff && CHAR_MIN==0 +typedef char sox_uint8_t; +#else +#error Unable to determine an appropriate definition for sox_uint8_t. +#endif + +/** +Client API: +Signed twos-complement 16-bit type. Typically defined as short. +*/ +#if SHRT_MAX==32767 && SHRT_MIN==(-32768) +typedef short sox_int16_t; +#elif INT_MAX==32767 && INT_MIN==(-32768) +typedef int sox_int16_t; +#else +#error Unable to determine an appropriate definition for sox_int16_t. +#endif + +/** +Client API: +Unsigned 16-bit type. Typically defined as unsigned short. +*/ +#if USHRT_MAX==0xffff +typedef unsigned short sox_uint16_t; +#elif UINT_MAX==0xffff +typedef unsigned int sox_uint16_t; +#else +#error Unable to determine an appropriate definition for sox_uint16_t. +#endif + +/** +Client API: +Signed twos-complement 32-bit type. Typically defined as int. +*/ +#if INT_MAX==2147483647 && INT_MIN==(-2147483647-1) +typedef int sox_int32_t; +#elif LONG_MAX==2147483647 && LONG_MIN==(-2147483647-1) +typedef long sox_int32_t; +#else +#error Unable to determine an appropriate definition for sox_int32_t. +#endif + +/** +Client API: +Unsigned 32-bit type. Typically defined as unsigned int. +*/ +#if UINT_MAX==0xffffffff +typedef unsigned int sox_uint32_t; +#elif ULONG_MAX==0xffffffff +typedef unsigned long sox_uint32_t; +#else +#error Unable to determine an appropriate definition for sox_uint32_t. +#endif + +/** +Client API: +Signed twos-complement 64-bit type. Typically defined as long or long long. +*/ +#if LONG_MAX==9223372036854775807 && LONG_MIN==(-9223372036854775807-1) +typedef long sox_int64_t; +#elif defined(_MSC_VER) +typedef __int64 sox_int64_t; +#else +typedef long long sox_int64_t; +#endif + +/** +Client API: +Unsigned 64-bit type. Typically defined as unsigned long or unsigned long long. +*/ +#if ULONG_MAX==0xffffffffffffffff +typedef unsigned long sox_uint64_t; +#elif defined(_MSC_VER) +typedef unsigned __int64 sox_uint64_t; +#else +typedef unsigned long long sox_uint64_t; +#endif + +#ifndef _DOXYGEN_ +lsx_static_assert(sizeof(sox_int8_t)==1, sox_int8_size); +lsx_static_assert(sizeof(sox_uint8_t)==1, sox_uint8_size); +lsx_static_assert(sizeof(sox_int16_t)==2, sox_int16_size); +lsx_static_assert(sizeof(sox_uint16_t)==2, sox_uint16_size); +lsx_static_assert(sizeof(sox_int32_t)==4, sox_int32_size); +lsx_static_assert(sizeof(sox_uint32_t)==4, sox_uint32_size); +lsx_static_assert(sizeof(sox_int64_t)==8, sox_int64_size); +lsx_static_assert(sizeof(sox_uint64_t)==8, sox_uint64_size); +#endif + +/** +Client API: +Alias for sox_int32_t (beware of the extra byte). +*/ +typedef sox_int32_t sox_int24_t; + +/** +Client API: +Alias for sox_uint32_t (beware of the extra byte). +*/ +typedef sox_uint32_t sox_uint24_t; + +/** +Client API: +Native SoX audio sample type (alias for sox_int32_t). +*/ +typedef sox_int32_t sox_sample_t; + +/** +Client API: +Samples per second is stored as a double. +*/ +typedef double sox_rate_t; + +/** +Client API: +File's metadata, access via sox_*_comments functions. +*/ +typedef char * * sox_comments_t; + +/***************************************************************************** +Enumerations: +*****************************************************************************/ + +/** +Client API: +Boolean type, assignment (but not necessarily binary) compatible with C++ bool. +*/ +typedef enum sox_bool { + sox_false, /**< False = 0. */ + sox_true /**< True = 1. */ +} sox_bool; + +/** +Client API: +no, yes, or default (default usually implies some kind of auto-detect logic). +*/ +typedef enum sox_option_t { + sox_option_no, /**< Option specified as no = 0. */ + sox_option_yes, /**< Option specified as yes = 1. */ + sox_option_default /**< Option unspecified = 2. */ +} sox_option_t; + +/** +Client API: +The libSoX-specific error codes. +libSoX functions may return these codes or others that map from errno codes. +*/ +enum sox_error_t { + SOX_SUCCESS = 0, /**< Function succeeded = 0 */ + SOX_EOF = -1, /**< End Of File or other error = -1 */ + SOX_EHDR = 2000, /**< Invalid Audio Header = 2000 */ + SOX_EFMT, /**< Unsupported data format = 2001 */ + SOX_ENOMEM, /**< Can't alloc memory = 2002 */ + SOX_EPERM, /**< Operation not permitted = 2003 */ + SOX_ENOTSUP, /**< Operation not supported = 2004 */ + SOX_EINVAL /**< Invalid argument = 2005 */ +}; + +/** +Client API: +Flags indicating whether optional features are present in this build of libSoX. +*/ +typedef enum sox_version_flags_t { + sox_version_none = 0, /**< No special features = 0. */ + sox_version_have_popen = 1, /**< popen = 1. */ + sox_version_have_magic = 2, /**< magic = 2. */ + sox_version_have_threads = 4, /**< threads = 4. */ + sox_version_have_memopen = 8 /**< memopen = 8. */ +} sox_version_flags_t; + +/** +Client API: +Format of sample data. +*/ +typedef enum sox_encoding_t { + SOX_ENCODING_UNKNOWN , /**< encoding has not yet been determined */ + + SOX_ENCODING_SIGN2 , /**< signed linear 2's comp: Mac */ + SOX_ENCODING_UNSIGNED , /**< unsigned linear: Sound Blaster */ + SOX_ENCODING_FLOAT , /**< floating point (binary format) */ + SOX_ENCODING_FLOAT_TEXT, /**< floating point (text format) */ + SOX_ENCODING_FLAC , /**< FLAC compression */ + SOX_ENCODING_HCOM , /**< Mac FSSD files with Huffman compression */ + SOX_ENCODING_WAVPACK , /**< WavPack with integer samples */ + SOX_ENCODING_WAVPACKF , /**< WavPack with float samples */ + SOX_ENCODING_ULAW , /**< u-law signed logs: US telephony, SPARC */ + SOX_ENCODING_ALAW , /**< A-law signed logs: non-US telephony, Psion */ + SOX_ENCODING_G721 , /**< G.721 4-bit ADPCM */ + SOX_ENCODING_G723 , /**< G.723 3 or 5 bit ADPCM */ + SOX_ENCODING_CL_ADPCM , /**< Creative Labs 8 --> 2,3,4 bit Compressed PCM */ + SOX_ENCODING_CL_ADPCM16, /**< Creative Labs 16 --> 4 bit Compressed PCM */ + SOX_ENCODING_MS_ADPCM , /**< Microsoft Compressed PCM */ + SOX_ENCODING_IMA_ADPCM , /**< IMA Compressed PCM */ + SOX_ENCODING_OKI_ADPCM , /**< Dialogic/OKI Compressed PCM */ + SOX_ENCODING_DPCM , /**< Differential PCM: Fasttracker 2 (xi) */ + SOX_ENCODING_DWVW , /**< Delta Width Variable Word */ + SOX_ENCODING_DWVWN , /**< Delta Width Variable Word N-bit */ + SOX_ENCODING_GSM , /**< GSM 6.10 33byte frame lossy compression */ + SOX_ENCODING_MP3 , /**< MP3 compression */ + SOX_ENCODING_VORBIS , /**< Vorbis compression */ + SOX_ENCODING_AMR_WB , /**< AMR-WB compression */ + SOX_ENCODING_AMR_NB , /**< AMR-NB compression */ + SOX_ENCODING_CVSD , /**< Continuously Variable Slope Delta modulation */ + SOX_ENCODING_LPC10 , /**< Linear Predictive Coding */ + + SOX_ENCODINGS /**< End of list marker */ +} sox_encoding_t; + +/** +Client API: +Flags for sox_encodings_info_t: lossless/lossy1/lossy2. +*/ +typedef enum sox_encodings_flags_t { + sox_encodings_none = 0, /**< no flags specified (implies lossless encoding) = 0. */ + sox_encodings_lossy1 = 1, /**< encode, decode: lossy once = 1. */ + sox_encodings_lossy2 = 2 /**< encode, decode, encode, decode: lossy twice = 2. */ +} sox_encodings_flags_t; + +/** +Client API: +Type of plot. +*/ +typedef enum sox_plot_t { + sox_plot_off, /**< No plot = 0. */ + sox_plot_octave, /**< Octave plot = 1. */ + sox_plot_gnuplot, /**< Gnuplot plot = 2. */ + sox_plot_data /**< Plot data = 3. */ +} sox_plot_t; + +/** +Client API: +Loop modes: upper 4 bits mask the loop blass, lower 4 bits describe +the loop behaviour, for example single shot, bidirectional etc. +*/ +enum sox_loop_flags_t { + sox_loop_none = 0, /**< single-shot = 0 */ + sox_loop_forward = 1, /**< forward loop = 1 */ + sox_loop_forward_back = 2, /**< forward/back loop = 2 */ + sox_loop_8 = 32, /**< 8 loops (??) = 32 */ + sox_loop_sustain_decay = 64 /**< AIFF style, one sustain & one decay loop = 64 */ +}; + +/** +Plugins API: +Is file a real file, a pipe, or a url? +*/ +typedef enum lsx_io_type +{ + lsx_io_file, /**< File is a real file = 0. */ + lsx_io_pipe, /**< File is a pipe (no seeking) = 1. */ + lsx_io_url /**< File is a URL (no seeking) = 2. */ +} lsx_io_type; + +/***************************************************************************** +Macros: +*****************************************************************************/ + +/** +Client API: +Compute a 32-bit integer API version from three 8-bit parts. +@param a Major version. +@param b Minor version. +@param c Revision or build number. +@returns 32-bit integer API version 0x000a0b0c. +*/ +#define SOX_LIB_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) + +/** +Client API: +The API version of the sox.h file. It is not meant to follow the version +number of SoX but it has historically. Please do not count on +SOX_LIB_VERSION_CODE staying in sync with the libSoX version. +*/ +#define SOX_LIB_VERSION_CODE SOX_LIB_VERSION(14, 4, 1) + +/** +Client API: +Returns the smallest (negative) value storable in a twos-complement signed +integer with the specified number of bits, cast to an unsigned integer; +for example, SOX_INT_MIN(8) = 0x80, SOX_INT_MIN(16) = 0x8000, etc. +@param bits Size of value for which to calculate minimum. +@returns the smallest (negative) value storable in a twos-complement signed +integer with the specified number of bits, cast to an unsigned integer. +*/ +#define SOX_INT_MIN(bits) (1 <<((bits)-1)) + +/** +Client API: +Returns the largest (positive) value storable in a twos-complement signed +integer with the specified number of bits, cast to an unsigned integer; +for example, SOX_INT_MAX(8) = 0x7F, SOX_INT_MAX(16) = 0x7FFF, etc. +@param bits Size of value for which to calculate maximum. +@returns the largest (positive) value storable in a twos-complement signed +integer with the specified number of bits, cast to an unsigned integer. +*/ +#define SOX_INT_MAX(bits) (((unsigned)-1)>>(33-(bits))) + +/** +Client API: +Returns the largest value storable in an unsigned integer with the specified +number of bits; for example, SOX_UINT_MAX(8) = 0xFF, +SOX_UINT_MAX(16) = 0xFFFF, etc. +@param bits Size of value for which to calculate maximum. +@returns the largest value storable in an unsigned integer with the specified +number of bits. +*/ +#define SOX_UINT_MAX(bits) (SOX_INT_MIN(bits)|SOX_INT_MAX(bits)) + +/** +Client API: +Returns 0x7F. +*/ +#define SOX_INT8_MAX SOX_INT_MAX(8) + +/** +Client API: +Returns 0x7FFF. +*/ +#define SOX_INT16_MAX SOX_INT_MAX(16) + +/** +Client API: +Returns 0x7FFFFF. +*/ +#define SOX_INT24_MAX SOX_INT_MAX(24) + +/** +Client API: +Returns 0x7FFFFFFF. +*/ +#define SOX_INT32_MAX SOX_INT_MAX(32) + +/** +Client API: +Bits in a sox_sample_t = 32. +*/ +#define SOX_SAMPLE_PRECISION 32 + +/** +Client API: +Max value for sox_sample_t = 0x7FFFFFFF. +*/ +#define SOX_SAMPLE_MAX (sox_sample_t)SOX_INT_MAX(32) + +/** +Client API: +Min value for sox_sample_t = 0x80000000. +*/ +#define SOX_SAMPLE_MIN (sox_sample_t)SOX_INT_MIN(32) + + +/* Conversions: Linear PCM <--> sox_sample_t + * + * I/O Input sox_sample_t Clips? Input sox_sample_t Clips? + * Format Minimum Minimum I O Maximum Maximum I O + * ------ --------- ------------ -- -- -------- ------------ -- -- + * Float -inf -1 y n inf 1 - 5e-10 y n + * Int8 -128 -128 n n 127 127.9999999 n y + * Int16 -32768 -32768 n n 32767 32767.99998 n y + * Int24 -8388608 -8388608 n n 8388607 8388607.996 n y + * Int32 -2147483648 -2147483648 n n 2147483647 2147483647 n n + * + * Conversions are as accurate as possible (with rounding). + * + * Rounding: halves toward +inf, all others to nearest integer. + * + * Clips? shows whether on not there is the possibility of a conversion + * clipping to the minimum or maximum value when inputing from or outputing + * to a given type. + * + * Unsigned integers are converted to and from signed integers by flipping + * the upper-most bit then treating them as signed integers. + */ + +/** +Client API: +Declares the temporary local variables that are required when using SOX +conversion macros. +*/ +#define SOX_SAMPLE_LOCALS sox_sample_t sox_macro_temp_sample LSX_UNUSED; \ + double sox_macro_temp_double LSX_UNUSED + +/** +Client API: +Sign bit for sox_sample_t = 0x80000000. +*/ +#define SOX_SAMPLE_NEG SOX_INT_MIN(32) + +/** +Client API: +Converts sox_sample_t to an unsigned integer of width (bits). +@param bits Width of resulting sample (1 through 32). +@param d Input sample to be converted. +@param clips Variable that is incremented if the result is too big. +@returns Unsigned integer of width (bits). +*/ +#define SOX_SAMPLE_TO_UNSIGNED(bits,d,clips) \ + (sox_uint##bits##_t)(SOX_SAMPLE_TO_SIGNED(bits,d,clips)^SOX_INT_MIN(bits)) + +/** +Client API: +Converts sox_sample_t to a signed integer of width (bits). +@param bits Width of resulting sample (1 through 32). +@param d Input sample to be converted. +@param clips Variable that is incremented if the result is too big. +@returns Signed integer of width (bits). +*/ +#define SOX_SAMPLE_TO_SIGNED(bits,d,clips) \ + (sox_int##bits##_t)(LSX_USE_VAR(sox_macro_temp_double),sox_macro_temp_sample=(d),sox_macro_temp_sample>SOX_SAMPLE_MAX-(1<<(31-bits))?++(clips),SOX_INT_MAX(bits):((sox_uint32_t)(sox_macro_temp_sample+(1<<(31-bits))))>>(32-bits)) + +/** +Client API: +Converts signed integer of width (bits) to sox_sample_t. +@param bits Width of input sample (1 through 32). +@param d Input sample to be converted. +@returns SoX native sample value. +*/ +#define SOX_SIGNED_TO_SAMPLE(bits,d)((sox_sample_t)(d)<<(32-bits)) + +/** +Client API: +Converts unsigned integer of width (bits) to sox_sample_t. +@param bits Width of input sample (1 through 32). +@param d Input sample to be converted. +@returns SoX native sample value. +*/ +#define SOX_UNSIGNED_TO_SAMPLE(bits,d)(SOX_SIGNED_TO_SAMPLE(bits,d)^SOX_SAMPLE_NEG) + +/** +Client API: +Converts unsigned 8-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_UNSIGNED_8BIT_TO_SAMPLE(d,clips) SOX_UNSIGNED_TO_SAMPLE(8,d) + +/** +Client API: +Converts signed 8-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_SIGNED_8BIT_TO_SAMPLE(d,clips) SOX_SIGNED_TO_SAMPLE(8,d) + +/** +Client API: +Converts unsigned 16-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_UNSIGNED_16BIT_TO_SAMPLE(d,clips) SOX_UNSIGNED_TO_SAMPLE(16,d) + +/** +Client API: +Converts signed 16-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_SIGNED_16BIT_TO_SAMPLE(d,clips) SOX_SIGNED_TO_SAMPLE(16,d) + +/** +Client API: +Converts unsigned 24-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_UNSIGNED_24BIT_TO_SAMPLE(d,clips) SOX_UNSIGNED_TO_SAMPLE(24,d) + +/** +Client API: +Converts signed 24-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_SIGNED_24BIT_TO_SAMPLE(d,clips) SOX_SIGNED_TO_SAMPLE(24,d) + +/** +Client API: +Converts unsigned 32-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_UNSIGNED_32BIT_TO_SAMPLE(d,clips) ((sox_sample_t)(d)^SOX_SAMPLE_NEG) + +/** +Client API: +Converts signed 32-bit integer to sox_sample_t. +@param d Input sample to be converted. +@param clips The parameter is not used. +@returns SoX native sample value. +*/ +#define SOX_SIGNED_32BIT_TO_SAMPLE(d,clips) (sox_sample_t)(d) + +/** +Client API: +Converts 32-bit float to sox_sample_t. +@param d Input sample to be converted, range [-1, 1). +@param clips Variable to increment if the input sample is too large or too small. +@returns SoX native sample value. +*/ +#define SOX_FLOAT_32BIT_TO_SAMPLE(d,clips) (sox_sample_t)(LSX_USE_VAR(sox_macro_temp_sample),sox_macro_temp_double=(d)*(SOX_SAMPLE_MAX+1.),sox_macro_temp_double=SOX_SAMPLE_MAX+1.?sox_macro_temp_double>SOX_SAMPLE_MAX+1.?++(clips),SOX_SAMPLE_MAX:SOX_SAMPLE_MAX:sox_macro_temp_double) + +/** +Client API: +Converts 64-bit float to sox_sample_t. +@param d Input sample to be converted, range [-1, 1). +@param clips Variable to increment if the input sample is too large or too small. +@returns SoX native sample value. +*/ +#define SOX_FLOAT_64BIT_TO_SAMPLE(d,clips) (sox_sample_t)(LSX_USE_VAR(sox_macro_temp_sample),sox_macro_temp_double=(d)*(SOX_SAMPLE_MAX+1.),sox_macro_temp_double<0?sox_macro_temp_double<=SOX_SAMPLE_MIN-.5?++(clips),SOX_SAMPLE_MIN:sox_macro_temp_double-.5:sox_macro_temp_double>=SOX_SAMPLE_MAX+.5?sox_macro_temp_double>SOX_SAMPLE_MAX+1.?++(clips),SOX_SAMPLE_MAX:SOX_SAMPLE_MAX:sox_macro_temp_double+.5) + +/** +Client API: +Converts SoX native sample to an unsigned 8-bit integer. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_UNSIGNED_8BIT(d,clips) SOX_SAMPLE_TO_UNSIGNED(8,d,clips) + +/** +Client API: +Converts SoX native sample to an signed 8-bit integer. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_SIGNED_8BIT(d,clips) SOX_SAMPLE_TO_SIGNED(8,d,clips) + +/** +Client API: +Converts SoX native sample to an unsigned 16-bit integer. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_UNSIGNED_16BIT(d,clips) SOX_SAMPLE_TO_UNSIGNED(16,d,clips) + +/** +Client API: +Converts SoX native sample to a signed 16-bit integer. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_SIGNED_16BIT(d,clips) SOX_SAMPLE_TO_SIGNED(16,d,clips) + +/** +Client API: +Converts SoX native sample to an unsigned 24-bit integer. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_UNSIGNED_24BIT(d,clips) SOX_SAMPLE_TO_UNSIGNED(24,d,clips) + +/** +Client API: +Converts SoX native sample to a signed 24-bit integer. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_SIGNED_24BIT(d,clips) SOX_SAMPLE_TO_SIGNED(24,d,clips) + +/** +Client API: +Converts SoX native sample to an unsigned 32-bit integer. +@param d Input sample to be converted. +@param clips The parameter is not used. +*/ +#define SOX_SAMPLE_TO_UNSIGNED_32BIT(d,clips) (sox_uint32_t)((d)^SOX_SAMPLE_NEG) + +/** +Client API: +Converts SoX native sample to a signed 32-bit integer. +@param d Input sample to be converted. +@param clips The parameter is not used. +*/ +#define SOX_SAMPLE_TO_SIGNED_32BIT(d,clips) (sox_int32_t)(d) + +/** +Client API: +Converts SoX native sample to a 32-bit float. +@param d Input sample to be converted. +@param clips Variable to increment if input sample is too large. +*/ +#define SOX_SAMPLE_TO_FLOAT_32BIT(d,clips) (LSX_USE_VAR(sox_macro_temp_double),sox_macro_temp_sample=(d),sox_macro_temp_sample>SOX_SAMPLE_MAX-128?++(clips),1:(((sox_macro_temp_sample+128)&~255)*(1./(SOX_SAMPLE_MAX+1.)))) + +/** +Client API: +Converts SoX native sample to a 64-bit float. +@param d Input sample to be converted. +@param clips The parameter is not used. +*/ +#define SOX_SAMPLE_TO_FLOAT_64BIT(d,clips) ((d)*(1./(SOX_SAMPLE_MAX+1.))) + +/** +Client API: +Clips a value of a type that is larger then sox_sample_t (for example, int64) +to sox_sample_t's limits and increment a counter if clipping occurs. +@param samp Value (lvalue) to be clipped, updated as necessary. +@param clips Value (lvalue) that is incremented if clipping is needed. +*/ +#define SOX_SAMPLE_CLIP_COUNT(samp, clips) \ + do { \ + if (samp > SOX_SAMPLE_MAX) \ + { samp = SOX_SAMPLE_MAX; clips++; } \ + else if (samp < SOX_SAMPLE_MIN) \ + { samp = SOX_SAMPLE_MIN; clips++; } \ + } while (0) + +/** +Client API: +Clips a value of a type that is larger then sox_sample_t (for example, int64) +to sox_sample_t's limits and increment a counter if clipping occurs. +@param d Value (rvalue) to be clipped. +@param clips Value (lvalue) that is incremented if clipping is needed. +@returns Clipped value. +*/ +#define SOX_ROUND_CLIP_COUNT(d, clips) \ + ((d) < 0? (d) <= SOX_SAMPLE_MIN - 0.5? ++(clips), SOX_SAMPLE_MIN: (d) - 0.5 \ + : (d) >= SOX_SAMPLE_MAX + 0.5? ++(clips), SOX_SAMPLE_MAX: (d) + 0.5) + +/** +Client API: +Clips a value to the limits of a signed integer of the specified width +and increment a counter if clipping occurs. +@param bits Width (in bits) of target integer type. +@param i Value (rvalue) to be clipped. +@param clips Value (lvalue) that is incremented if clipping is needed. +@returns Clipped value. +*/ +#define SOX_INTEGER_CLIP_COUNT(bits,i,clips) ( \ + (i) >(1 << ((bits)-1))- 1? ++(clips),(1 << ((bits)-1))- 1 : \ + (i) <-1 << ((bits)-1) ? ++(clips),-1 << ((bits)-1) : (i)) + +/** +Client API: +Clips a value to the limits of a 16-bit signed integer and increment a counter +if clipping occurs. +@param i Value (rvalue) to be clipped. +@param clips Value (lvalue) that is incremented if clipping is needed. +@returns Clipped value. +*/ +#define SOX_16BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(16,i,clips) + +/** +Client API: +Clips a value to the limits of a 24-bit signed integer and increment a counter +if clipping occurs. +@param i Value (rvalue) to be clipped. +@param clips Value (lvalue) that is incremented if clipping is needed. +@returns Clipped value. +*/ +#define SOX_24BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(24,i,clips) + +#define SOX_SIZE_MAX ((size_t)(-1)) /**< Client API: Maximum value of size_t. */ + +#define SOX_UNSPEC 0 /**< Client API: Members of sox_signalinfo_t are set to SOX_UNSPEC (= 0) if the actual value is not yet known. */ +#define SOX_UNKNOWN_LEN (sox_uint64_t)(-1) /**< Client API: sox_signalinfo_t.length is set to SOX_UNKNOWN_LEN (= -1) within the effects chain if the actual length is not known. Format handlers currently use SOX_UNSPEC instead. */ +#define SOX_IGNORE_LENGTH (sox_uint64_t)(-2) /**< Client API: sox_signalinfo_t.length is set to SOX_IGNORE_LENGTH (= -2) to indicate that a format handler should ignore length information in file headers. */ + +#define SOX_DEFAULT_CHANNELS 2 /**< Client API: Default channel count is 2 (stereo). */ +#define SOX_DEFAULT_RATE 48000 /**< Client API: Default rate is 48000Hz. */ +#define SOX_DEFAULT_PRECISION 16 /**< Client API: Default precision is 16 bits per sample. */ +#define SOX_DEFAULT_ENCODING SOX_ENCODING_SIGN2 /**< Client API: Default encoding is SIGN2 (linear 2's complement PCM). */ + +#define SOX_LOOP_NONE ((unsigned char)sox_loop_none) /**< Client API: single-shot = 0 */ +#define SOX_LOOP_8 ((unsigned char)sox_loop_8) /**< Client API: 8 loops = 32 */ +#define SOX_LOOP_SUSTAIN_DECAY ((unsigned char)sox_loop_sustain_decay) /**< Client API: AIFF style, one sustain & one decay loop = 64 */ + +#define SOX_MAX_NLOOPS 8 /**< Client API: Maximum number of loops supported by sox_oob_t = 8. */ + +#define SOX_FILE_NOSTDIO 0x0001 /**< Client API: Does not use stdio routines */ +#define SOX_FILE_DEVICE 0x0002 /**< Client API: File is an audio device */ +#define SOX_FILE_PHONY 0x0004 /**< Client API: Phony file/device (for example /dev/null) */ +#define SOX_FILE_REWIND 0x0008 /**< Client API: File should be rewound to write header */ +#define SOX_FILE_BIT_REV 0x0010 /**< Client API: Is file bit-reversed? */ +#define SOX_FILE_NIB_REV 0x0020 /**< Client API: Is file nibble-reversed? */ +#define SOX_FILE_ENDIAN 0x0040 /**< Client API: Is file format endian? */ +#define SOX_FILE_ENDBIG 0x0080 /**< Client API: For endian file format, is it big endian? */ +#define SOX_FILE_MONO 0x0100 /**< Client API: Do channel restrictions allow mono? */ +#define SOX_FILE_STEREO 0x0200 /**< Client API: Do channel restrictions allow stereo? */ +#define SOX_FILE_QUAD 0x0400 /**< Client API: Do channel restrictions allow quad? */ + +#define SOX_FILE_CHANS (SOX_FILE_MONO | SOX_FILE_STEREO | SOX_FILE_QUAD) /**< Client API: No channel restrictions */ +#define SOX_FILE_LIT_END (SOX_FILE_ENDIAN | 0) /**< Client API: File is little-endian */ +#define SOX_FILE_BIG_END (SOX_FILE_ENDIAN | SOX_FILE_ENDBIG) /**< Client API: File is big-endian */ + +#define SOX_EFF_CHAN 1 /**< Client API: Effect might alter the number of channels */ +#define SOX_EFF_RATE 2 /**< Client API: Effect might alter sample rate */ +#define SOX_EFF_PREC 4 /**< Client API: Effect does its own calculation of output sample precision (otherwise a default value is taken, depending on the presence of SOX_EFF_MODIFY) */ +#define SOX_EFF_LENGTH 8 /**< Client API: Effect might alter audio length (as measured in time units, not necessarily in samples) */ +#define SOX_EFF_MCHAN 16 /**< Client API: Effect handles multiple channels internally */ +#define SOX_EFF_NULL 32 /**< Client API: Effect does nothing (can be optimized out of chain) */ +#define SOX_EFF_DEPRECATED 64 /**< Client API: Effect will soon be removed from SoX */ +#define SOX_EFF_GAIN 128 /**< Client API: Effect does not support gain -r */ +#define SOX_EFF_MODIFY 256 /**< Client API: Effect does not modify sample values (but might remove or duplicate samples or insert zeros) */ +#define SOX_EFF_ALPHA 512 /**< Client API: Effect is experimental/incomplete */ +#define SOX_EFF_INTERNAL 1024 /**< Client API: Effect present in libSoX but not valid for use by SoX command-line tools */ + +/** +Client API: +When used as the "whence" parameter of sox_seek, indicates that the specified +offset is relative to the beginning of the file. +*/ +#define SOX_SEEK_SET 0 + +/***************************************************************************** +Forward declarations: +*****************************************************************************/ + +typedef struct sox_format_t sox_format_t; +typedef struct sox_effect_t sox_effect_t; +typedef struct sox_effect_handler_t sox_effect_handler_t; +typedef struct sox_format_handler_t sox_format_handler_t; + +/***************************************************************************** +Function pointers: +*****************************************************************************/ + +/** +Client API: +Callback to write a message to an output device (console or log file), +used by sox_globals_t.output_message_handler. +*/ +typedef void (LSX_API * sox_output_message_handler_t)( + unsigned level, /* 1 = FAIL, 2 = WARN, 3 = INFO, 4 = DEBUG, 5 = DEBUG_MORE, 6 = DEBUG_MOST. */ + LSX_PARAM_IN_Z char const * filename, /* Source code __FILENAME__ from which message originates. */ + LSX_PARAM_IN_PRINTF char const * fmt, /* Message format string. */ + LSX_PARAM_IN va_list ap /* Message format parameters. */ + ); + +/** +Client API: +Callback to retrieve information about a format handler, +used by sox_format_tab_t.fn. +@returns format handler information. +*/ +typedef sox_format_handler_t const * (LSX_API * sox_format_fn_t)(void); + +/** +Client API: +Callback to get information about an effect handler, +used by the table returned from sox_get_effect_fns(void). +@returns Pointer to information about an effect handler. +*/ +typedef sox_effect_handler_t const * (LSX_API *sox_effect_fn_t)(void); + +/** +Client API: +Callback to initialize reader (decoder), used by +sox_format_handler.startread. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_format_handler_startread)( + LSX_PARAM_INOUT sox_format_t * ft /**< Format pointer. */ + ); + +/** +Client API: +Callback to read (decode) a block of samples, +used by sox_format_handler.read. +@returns number of samples read, or 0 if unsuccessful. +*/ +typedef size_t (LSX_API * sox_format_handler_read)( + LSX_PARAM_INOUT sox_format_t * ft, /**< Format pointer. */ + LSX_PARAM_OUT_CAP_POST_COUNT(len,return) sox_sample_t *buf, /**< Buffer from which to read samples. */ + size_t len /**< Number of samples available in buf. */ + ); + +/** +Client API: +Callback to close reader (decoder), +used by sox_format_handler.stopread. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_format_handler_stopread)( + LSX_PARAM_INOUT sox_format_t * ft /**< Format pointer. */ + ); + +/** +Client API: +Callback to initialize writer (encoder), +used by sox_format_handler.startwrite. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_format_handler_startwrite)( + LSX_PARAM_INOUT sox_format_t * ft /**< Format pointer. */ + ); + +/** +Client API: +Callback to write (encode) a block of samples, +used by sox_format_handler.write. +@returns number of samples written, or 0 if unsuccessful. +*/ +typedef size_t (LSX_API * sox_format_handler_write)( + LSX_PARAM_INOUT sox_format_t * ft, /**< Format pointer. */ + LSX_PARAM_IN_COUNT(len) sox_sample_t const * buf, /**< Buffer to which samples are written. */ + size_t len /**< Capacity of buf, measured in samples. */ + ); + +/** +Client API: +Callback to close writer (decoder), +used by sox_format_handler.stopwrite. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_format_handler_stopwrite)( + LSX_PARAM_INOUT sox_format_t * ft /**< Format pointer. */ + ); + +/** +Client API: +Callback to reposition reader, +used by sox_format_handler.seek. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_format_handler_seek)( + LSX_PARAM_INOUT sox_format_t * ft, /**< Format pointer. */ + sox_uint64_t offset /**< Sample offset to which reader should be positioned. */ + ); + +/** +Client API: +Callback to parse command-line arguments (called once per effect), +used by sox_effect_handler.getopts. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_effect_handler_getopts)( + LSX_PARAM_INOUT sox_effect_t * effp, /**< Effect pointer. */ + int argc, /**< Number of arguments in argv. */ + LSX_PARAM_IN_COUNT(argc) char *argv[] /**< Array of command-line arguments. */ + ); + +/** +Client API: +Callback to initialize effect (called once per flow), +used by sox_effect_handler.start. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_effect_handler_start)( + LSX_PARAM_INOUT sox_effect_t * effp /**< Effect pointer. */ + ); + +/** +Client API: +Callback to process samples, +used by sox_effect_handler.flow. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_effect_handler_flow)( + LSX_PARAM_INOUT sox_effect_t * effp, /**< Effect pointer. */ + LSX_PARAM_IN_COUNT(*isamp) sox_sample_t const * ibuf, /**< Buffer from which to read samples. */ + LSX_PARAM_OUT_CAP_POST_COUNT(*osamp,*osamp) sox_sample_t * obuf, /**< Buffer to which samples are written. */ + LSX_PARAM_INOUT size_t *isamp, /**< On entry, contains capacity of ibuf; on exit, contains number of samples consumed. */ + LSX_PARAM_INOUT size_t *osamp /**< On entry, contains capacity of obuf; on exit, contains number of samples written. */ + ); + +/** +Client API: +Callback to finish getting output after input is complete, +used by sox_effect_handler.drain. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_effect_handler_drain)( + LSX_PARAM_INOUT sox_effect_t * effp, /**< Effect pointer. */ + LSX_PARAM_OUT_CAP_POST_COUNT(*osamp,*osamp) sox_sample_t *obuf, /**< Buffer to which samples are written. */ + LSX_PARAM_INOUT size_t *osamp /**< On entry, contains capacity of obuf; on exit, contains number of samples written. */ + ); + +/** +Client API: +Callback to shut down effect (called once per flow), +used by sox_effect_handler.stop. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_effect_handler_stop)( + LSX_PARAM_INOUT sox_effect_t * effp /**< Effect pointer. */ + ); + +/** +Client API: +Callback to shut down effect (called once per effect), +used by sox_effect_handler.kill. +@returns SOX_SUCCESS if successful. +*/ +typedef int (LSX_API * sox_effect_handler_kill)( + LSX_PARAM_INOUT sox_effect_t * effp /**< Effect pointer. */ + ); + +/** +Client API: +Callback called while flow is running (called once per buffer), +used by sox_flow_effects.callback. +@returns SOX_SUCCESS to continue, other value to abort flow. +*/ +typedef int (LSX_API * sox_flow_effects_callback)( + sox_bool all_done, + void * client_data + ); + +/** +Client API: +Callback for enumerating the contents of a playlist, +used by the sox_parse_playlist function. +@returns SOX_SUCCESS if successful, any other value to abort playlist enumeration. +*/ +typedef int (LSX_API * sox_playlist_callback_t)( + void * callback_data, + LSX_PARAM_IN_Z char const * filename + ); + +/***************************************************************************** +Structures: +*****************************************************************************/ + +/** +Client API: +Information about a build of libSoX, returned from the sox_version_info +function. +*/ +typedef struct sox_version_info_t { + size_t size; /**< structure size = sizeof(sox_version_info_t) */ + sox_version_flags_t flags; /**< feature flags = popen | magic | threads | memopen */ + sox_uint32_t version_code; /**< version number = 0x140400 */ + char const * version; /**< version string = sox_version(), for example, "14.4.0" */ + char const * version_extra;/**< version extra info or null = "PACKAGE_EXTRA", for example, "beta" */ + char const * time; /**< build time = "__DATE__ __TIME__", for example, "Jan 7 2010 03:31:50" */ + char const * distro; /**< distro or null = "DISTRO", for example, "Debian" */ + char const * compiler; /**< compiler info or null, for example, "msvc 160040219" */ + char const * arch; /**< arch, for example, "1248 48 44 L OMP" */ + /* new info should be added at the end for version backwards-compatibility. */ +} sox_version_info_t; + +/** +Client API: +Global parameters (for effects & formats), returned from the sox_get_globals +function. +*/ +typedef struct sox_globals_t { +/* public: */ + unsigned verbosity; /**< messages are only written if globals.verbosity >= message.level */ + sox_output_message_handler_t output_message_handler; /**< client-specified message output callback */ + sox_bool repeatable; /**< true to use pre-determined timestamps and PRNG seed */ + + /** + Default size (in bytes) used by libSoX for blocks of sample data. + Plugins should use similarly-sized buffers to get best performance. + */ + size_t bufsiz; + + /** + Default size (in bytes) used by libSoX for blocks of input sample data. + Plugins should use similarly-sized buffers to get best performance. + */ + size_t input_bufsiz; + + sox_int32_t ranqd1; /**< Can be used to re-seed libSoX's PRNG */ + + char const * stdin_in_use_by; /**< Private: tracks the name of the handler currently using stdin */ + char const * stdout_in_use_by; /**< Private: tracks the name of the handler currently using stdout */ + char const * subsystem; /**< Private: tracks the name of the handler currently writing an output message */ + char * tmp_path; /**< Private: client-configured path to use for temporary files */ + sox_bool use_magic; /**< Private: true if client has requested use of 'magic' file-type detection */ + sox_bool use_threads; /**< Private: true if client has requested parallel effects processing */ +} sox_globals_t; + +/** +Client API: +Signal parameters; members should be set to SOX_UNSPEC (= 0) if unknown. +*/ +typedef struct sox_signalinfo_t { + sox_rate_t rate; /**< samples per second, 0 if unknown */ + unsigned channels; /**< number of sound channels, 0 if unknown */ + unsigned precision; /**< bits per sample, 0 if unknown */ + sox_uint64_t length; /**< samples * chans in file, 0 if unknown, -1 if unspecified */ + double * mult; /**< Effects headroom multiplier; may be null */ +} sox_signalinfo_t; + +/** +Client API: +Basic information about an encoding. +*/ +typedef struct sox_encodings_info_t { + sox_encodings_flags_t flags; /**< lossy once (lossy1), lossy twice (lossy2), or lossless (none). */ + char const * name; /**< encoding name. */ + char const * desc; /**< encoding description. */ +} sox_encodings_info_t; + +/** +Client API: +Encoding parameters. +*/ +typedef struct sox_encodinginfo_t { + sox_encoding_t encoding; /**< format of sample numbers */ + unsigned bits_per_sample;/**< 0 if unknown or variable; uncompressed value if lossless; compressed value if lossy */ + double compression; /**< compression factor (where applicable) */ + + /** + Should bytes be reversed? If this is default during sox_open_read or + sox_open_write, libSoX will set them to either no or yes according to the + machine or format default. + */ + sox_option_t reverse_bytes; + + /** + Should nibbles be reversed? If this is default during sox_open_read or + sox_open_write, libSoX will set them to either no or yes according to the + machine or format default. + */ + sox_option_t reverse_nibbles; + + /** + Should bits be reversed? If this is default during sox_open_read or + sox_open_write, libSoX will set them to either no or yes according to the + machine or format default. + */ + sox_option_t reverse_bits; + + /** + If set to true, the format should reverse its default endianness. + */ + sox_bool opposite_endian; +} sox_encodinginfo_t; + +/** +Client API: +Looping parameters (out-of-band data). +*/ +typedef struct sox_loopinfo_t { + sox_uint64_t start; /**< first sample */ + sox_uint64_t length; /**< length */ + unsigned count; /**< number of repeats, 0=forever */ + unsigned char type; /**< 0=no, 1=forward, 2=forward/back (see sox_loop_* for valid values). */ +} sox_loopinfo_t; + +/** +Client API: +Instrument information. +*/ +typedef struct sox_instrinfo_t{ + signed char MIDInote; /**< for unity pitch playback */ + signed char MIDIlow; /**< MIDI pitch-bend low range */ + signed char MIDIhi; /**< MIDI pitch-bend high range */ + unsigned char loopmode; /**< 0=no, 1=forward, 2=forward/back (see sox_loop_* values) */ + unsigned nloops; /**< number of active loops (max SOX_MAX_NLOOPS). */ +} sox_instrinfo_t; + +/** +Client API: +File buffer info. Holds info so that data can be read in blocks. +*/ +typedef struct sox_fileinfo_t { + char *buf; /**< Pointer to data buffer */ + size_t size; /**< Size of buffer in bytes */ + size_t count; /**< Count read into buffer */ + size_t pos; /**< Position in buffer */ +} sox_fileinfo_t; + +/** +Client API: +Handler structure defined by each format. +*/ +struct sox_format_handler_t { + unsigned sox_lib_version_code; /**< Checked on load; must be 1st in struct*/ + char const * description; /**< short description of format */ + char const * const * names; /**< null-terminated array of filename extensions that are handled by this format */ + unsigned int flags; /**< File flags (SOX_FILE_* values). */ + sox_format_handler_startread startread; /**< called to initialize reader (decoder) */ + sox_format_handler_read read; /**< called to read (decode) a block of samples */ + sox_format_handler_stopread stopread; /**< called to close reader (decoder); may be null if no closing necessary */ + sox_format_handler_startwrite startwrite; /**< called to initialize writer (encoder) */ + sox_format_handler_write write; /**< called to write (encode) a block of samples */ + sox_format_handler_stopwrite stopwrite; /**< called to close writer (decoder); may be null if no closing necessary */ + sox_format_handler_seek seek; /**< called to reposition reader; may be null if not supported */ + + /** + Array of values indicating the encodings and precisions supported for + writing (encoding). Precisions specified with default precision first. + Encoding, precision, precision, ..., 0, repeat. End with one more 0. + Example: + unsigned const * formats = { + SOX_ENCODING_SIGN2, 16, 24, 0, // Support SIGN2 at 16 and 24 bits, default to 16 bits. + SOX_ENCODING_UNSIGNED, 8, 0, // Support UNSIGNED at 8 bits, default to 8 bits. + 0 // No more supported encodings. + }; + */ + unsigned const * write_formats; + + /** + Array of sample rates (samples per second) supported for writing (encoding). + NULL if all (or almost all) rates are supported. End with 0. + */ + sox_rate_t const * write_rates; + + /** + SoX will automatically allocate a buffer in which the handler can store data. + Specify the size of the buffer needed here. Usually this will be sizeof(your_struct). + The buffer will be allocated and zeroed before the call to startread/startwrite. + The buffer will be freed after the call to stopread/stopwrite. + The buffer will be provided via format.priv in each call to the handler. + */ + size_t priv_size; +}; + +/** +Client API: +Comments, instrument info, loop info (out-of-band data). +*/ +typedef struct sox_oob_t{ + /* Decoded: */ + sox_comments_t comments; /**< Comment strings in id=value format. */ + sox_instrinfo_t instr; /**< Instrument specification */ + sox_loopinfo_t loops[SOX_MAX_NLOOPS]; /**< Looping specification */ + + /* TBD: Non-decoded chunks, etc: */ +} sox_oob_t; + +/** +Client API: +Data passed to/from the format handler +*/ +struct sox_format_t { + char * filename; /**< File name */ + + /** + Signal specifications for reader (decoder) or writer (encoder): + sample rate, number of channels, precision, length, headroom multiplier. + Any info specified by the user is here on entry to startread or + startwrite. Info will be SOX_UNSPEC if the user provided no info. + At exit from startread, should be completely filled in, using + either data from the file's headers (if available) or whatever + the format is guessing/assuming (if header data is not available). + At exit from startwrite, should be completely filled in, using + either the data that was specified, or values chosen by the format + based on the format's defaults or capabilities. + */ + sox_signalinfo_t signal; + + /** + Encoding specifications for reader (decoder) or writer (encoder): + encoding (sample format), bits per sample, compression rate, endianness. + Should be filled in by startread. Values specified should be used + by startwrite when it is configuring the encoding parameters. + */ + sox_encodinginfo_t encoding; + + char * filetype; /**< Type of file, as determined by header inspection or libmagic. */ + sox_oob_t oob; /**< comments, instrument info, loop info (out-of-band data) */ + sox_bool seekable; /**< Can seek on this file */ + char mode; /**< Read or write mode ('r' or 'w') */ + sox_uint64_t olength; /**< Samples * chans written to file */ + sox_uint64_t clips; /**< Incremented if clipping occurs */ + int sox_errno; /**< Failure error code */ + char sox_errstr[256]; /**< Failure error text */ + void * fp; /**< File stream pointer */ + lsx_io_type io_type; /**< Stores whether this is a file, pipe or URL */ + sox_uint64_t tell_off; /**< Current offset within file */ + sox_uint64_t data_start; /**< Offset at which headers end and sound data begins (set by lsx_check_read_params) */ + sox_format_handler_t handler; /**< Format handler for this file */ + void * priv; /**< Format handler's private data area */ +}; + +/** +Client API: +Information about a loaded format handler, including the format name and a +function pointer that can be invoked to get additional information about the +format. +*/ +typedef struct sox_format_tab_t { + char *name; /**< Name of format handler */ + sox_format_fn_t fn; /**< Function to call to get format handler's information */ +} sox_format_tab_t; + +/** +Client API: +Global parameters for effects. +*/ +typedef struct sox_effects_globals_t { + sox_plot_t plot; /**< To help the user choose effect & options */ + sox_globals_t * global_info; /**< Pointer to associated SoX globals */ +} sox_effects_globals_t; + +/** +Client API: +Effect handler information. +*/ +struct sox_effect_handler_t { + char const * name; /**< Effect name */ + char const * usage; /**< Short explanation of parameters accepted by effect */ + unsigned int flags; /**< Combination of SOX_EFF_* flags */ + sox_effect_handler_getopts getopts; /**< Called to parse command-line arguments (called once per effect). */ + sox_effect_handler_start start; /**< Called to initialize effect (called once per flow). */ + sox_effect_handler_flow flow; /**< Called to process samples. */ + sox_effect_handler_drain drain; /**< Called to finish getting output after input is complete. */ + sox_effect_handler_stop stop; /**< Called to shut down effect (called once per flow). */ + sox_effect_handler_kill kill; /**< Called to shut down effect (called once per effect). */ + size_t priv_size; /**< Size of private data SoX should pre-allocate for effect */ +}; + +/** +Client API: +Effect information. +*/ +struct sox_effect_t { + sox_effects_globals_t * global_info; /**< global effect parameters */ + sox_signalinfo_t in_signal; /**< Information about the incoming data stream */ + sox_signalinfo_t out_signal; /**< Information about the outgoing data stream */ + sox_encodinginfo_t const * in_encoding; /**< Information about the incoming data encoding */ + sox_encodinginfo_t const * out_encoding; /**< Information about the outgoing data encoding */ + sox_effect_handler_t handler; /**< The handler for this effect */ + sox_sample_t * obuf; /**< output buffer */ + size_t obeg; /**< output buffer: start of valid data section */ + size_t oend; /**< output buffer: one past valid data section (oend-obeg is length of current content) */ + size_t imin; /**< minimum input buffer content required for calling this effect's flow function; set via lsx_effect_set_imin() */ + sox_uint64_t clips; /**< increment if clipping occurs */ + size_t flows; /**< 1 if MCHAN, number of chans otherwise */ + size_t flow; /**< flow number */ + void * priv; /**< Effect's private data area (each flow has a separate copy) */ +}; + +/** +Client API: +Chain of effects to be applied to a stream. +*/ +typedef struct sox_effects_chain_t { + sox_effect_t **effects; /**< Table of effects to be applied to a stream */ + unsigned table_size; /**< Number of entries in effects table */ + unsigned length; /**< Number of effects to be applied */ + sox_sample_t **ibufc; /**< Channel interleave buffer */ + sox_sample_t **obufc; /**< Channel interleave buffer */ + sox_effects_globals_t global_info; /**< Copy of global effects settings */ + sox_encodinginfo_t const * in_enc; /**< Input encoding */ + sox_encodinginfo_t const * out_enc; /**< Output encoding */ +} sox_effects_chain_t; + +/***************************************************************************** +Functions: +*****************************************************************************/ + +/** +Client API: +Returns version number string of libSoX, for example, "14.4.0". +@returns The version number string of libSoX, for example, "14.4.0". +*/ +LSX_RETURN_VALID_Z LSX_RETURN_PURE +char const * +LSX_API +sox_version(void); + +/** +Client API: +Returns information about this build of libsox. +@returns Pointer to a version information structure. +*/ +LSX_RETURN_VALID LSX_RETURN_PURE +sox_version_info_t const * +LSX_API +sox_version_info(void); + +/** +Client API: +Returns a pointer to the structure with libSoX's global settings. +@returns a pointer to the structure with libSoX's global settings. +*/ +LSX_RETURN_VALID LSX_RETURN_PURE +sox_globals_t * +LSX_API +sox_get_globals(void); + +/** +Client API: +Deprecated macro that returns the structure with libSoX's global settings +as an lvalue. +*/ +#define sox_globals (*sox_get_globals()) + +/** +Client API: +Returns a pointer to the list of available encodings. +End of list indicated by name == NULL. +@returns pointer to the list of available encodings. +*/ +LSX_RETURN_ARRAY LSX_RETURN_PURE +sox_encodings_info_t const * +LSX_API +sox_get_encodings_info(void); + +/** +Client API: +Deprecated macro that returns the list of available encodings. +End of list indicated by name == NULL. +*/ +#define sox_encodings_info (sox_get_encodings_info()) + +/** +Client API: +Fills in an encodinginfo with default values. +*/ +void +LSX_API +sox_init_encodinginfo( + LSX_PARAM_OUT sox_encodinginfo_t * e /**< Pointer to uninitialized encoding info structure to be initialized. */ + ); + +/** +Client API: +Given an encoding (for example, SIGN2) and the encoded bits_per_sample (for +example, 16), returns the number of useful bits per sample in the decoded data +(for example, 16), or returns 0 to indicate that the value returned by the +format handler should be used instead of a pre-determined precision. +@returns the number of useful bits per sample in the decoded data (for example +16), or returns 0 to indicate that the value returned by the format handler +should be used instead of a pre-determined precision. +*/ +LSX_RETURN_PURE +unsigned +LSX_API +sox_precision( + sox_encoding_t encoding, /**< Encoding for which to lookup precision information. */ + unsigned bits_per_sample /**< The number of encoded bits per sample. */ + ); + +/** +Client API: +Returns the number of items in the metadata block. +@returns the number of items in the metadata block. +*/ +size_t +LSX_API +sox_num_comments( + LSX_PARAM_IN_OPT sox_comments_t comments /**< Metadata block. */ + ); + +/** +Client API: +Adds an "id=value" item to the metadata block. +*/ +void +LSX_API +sox_append_comment( + LSX_PARAM_DEREF_PRE_MAYBENULL LSX_PARAM_DEREF_POST_NOTNULL sox_comments_t * comments, /**< Metadata block. */ + LSX_PARAM_IN_Z char const * item /**< Item to be added in "id=value" format. */ + ); + +/** +Client API: +Adds a newline-delimited list of "id=value" items to the metadata block. +*/ +void +LSX_API +sox_append_comments( + LSX_PARAM_DEREF_PRE_MAYBENULL LSX_PARAM_DEREF_POST_NOTNULL sox_comments_t * comments, /**< Metadata block. */ + LSX_PARAM_IN_Z char const * items /**< Newline-separated list of items to be added, for example "id1=value1\\nid2=value2". */ + ); + +/** +Client API: +Duplicates the metadata block. +@returns the copied metadata block. +*/ +LSX_RETURN_OPT +sox_comments_t +LSX_API +sox_copy_comments( + LSX_PARAM_IN_OPT sox_comments_t comments /**< Metadata block to copy. */ + ); + +/** +Client API: +Frees the metadata block. +*/ +void +LSX_API +sox_delete_comments( + LSX_PARAM_DEREF_PRE_MAYBENULL LSX_PARAM_DEREF_POST_NULL sox_comments_t * comments /**< Metadata block. */ + ); + +/** +Client API: +If "id=value" is found, return value, else return null. +@returns value, or null if value not found. +*/ +LSX_RETURN_OPT +char const * +LSX_API +sox_find_comment( + LSX_PARAM_IN_OPT sox_comments_t comments, /**< Metadata block in which to search. */ + LSX_PARAM_IN_Z char const * id /**< Id for which to search */ + ); + +/** +Client API: +Find and load format handler plugins. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_format_init(void); + +/** +Client API: +Unload format handler plugins. +*/ +void +LSX_API +sox_format_quit(void); + +/** +Client API: +Initialize effects library. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_init(void); + +/** +Client API: +Close effects library and unload format handler plugins. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_quit(void); + +/** +Client API: +Returns the table of format handler names and functions. +@returns the table of format handler names and functions. +*/ +LSX_RETURN_ARRAY LSX_RETURN_PURE +sox_format_tab_t const * +LSX_API +sox_get_format_fns(void); + +/** +Client API: +Deprecated macro that returns the table of format handler names and functions. +*/ +#define sox_format_fns (sox_get_format_fns()) + +/** +Client API: +Opens a decoding session for a file. Returned handle must be closed with sox_close(). +@returns The handle for the new session, or null on failure. +*/ +LSX_RETURN_OPT +sox_format_t * +LSX_API +sox_open_read( + LSX_PARAM_IN_Z char const * path, /**< Path to file to be opened (required). */ + LSX_PARAM_IN_OPT sox_signalinfo_t const * signal, /**< Information already known about audio stream, or NULL if none. */ + LSX_PARAM_IN_OPT sox_encodinginfo_t const * encoding, /**< Information already known about sample encoding, or NULL if none. */ + LSX_PARAM_IN_OPT_Z char const * filetype /**< Previously-determined file type, or NULL to auto-detect. */ + ); + +/** +Client API: +Opens a decoding session for a memory buffer. Returned handle must be closed with sox_close(). +@returns The handle for the new session, or null on failure. +*/ +LSX_RETURN_OPT +sox_format_t * +LSX_API +sox_open_mem_read( + LSX_PARAM_IN_BYTECOUNT(buffer_size) void * buffer, /**< Pointer to audio data buffer (required). */ + size_t buffer_size,/**< Number of bytes to read from audio data buffer. */ + LSX_PARAM_IN_OPT sox_signalinfo_t const * signal, /**< Information already known about audio stream, or NULL if none. */ + LSX_PARAM_IN_OPT sox_encodinginfo_t const * encoding, /**< Information already known about sample encoding, or NULL if none. */ + LSX_PARAM_IN_OPT_Z char const * filetype /**< Previously-determined file type, or NULL to auto-detect. */ + ); + +/** +Client API: +Returns true if the format handler for the specified file type supports the specified encoding. +@returns true if the format handler for the specified file type supports the specified encoding. +*/ +sox_bool +LSX_API +sox_format_supports_encoding( + LSX_PARAM_IN_OPT_Z char const * path, /**< Path to file to be examined (required if filetype is NULL). */ + LSX_PARAM_IN_OPT_Z char const * filetype, /**< Previously-determined file type, or NULL to use extension from path. */ + LSX_PARAM_IN sox_encodinginfo_t const * encoding /**< Encoding for which format handler should be queried. */ + ); + +/** +Client API: +Gets the format handler for a specified file type. +@returns The found format handler, or null if not found. +*/ +LSX_RETURN_OPT +sox_format_handler_t const * +LSX_API +sox_write_handler( + LSX_PARAM_IN_OPT_Z char const * path, /**< Path to file (required if filetype is NULL). */ + LSX_PARAM_IN_OPT_Z char const * filetype, /**< Filetype for which handler is needed, or NULL to use extension from path. */ + LSX_PARAM_OUT_OPT char const * * filetype1 /**< Receives the filetype that was detected. Pass NULL if not needed. */ + ); + +/** +Client API: +Opens an encoding session for a file. Returned handle must be closed with sox_close(). +@returns The new session handle, or null on failure. +*/ +LSX_RETURN_OPT +sox_format_t * +LSX_API +sox_open_write( + LSX_PARAM_IN_Z char const * path, /**< Path to file to be written (required). */ + LSX_PARAM_IN sox_signalinfo_t const * signal, /**< Information about desired audio stream (required). */ + LSX_PARAM_IN_OPT sox_encodinginfo_t const * encoding, /**< Information about desired sample encoding, or NULL to use defaults. */ + LSX_PARAM_IN_OPT_Z char const * filetype, /**< Previously-determined file type, or NULL to auto-detect. */ + LSX_PARAM_IN_OPT sox_oob_t const * oob, /**< Out-of-band data to add to file, or NULL if none. */ + LSX_PARAM_IN_OPT sox_bool (LSX_API * overwrite_permitted)(LSX_PARAM_IN_Z char const * filename) /**< Called if file exists to determine whether overwrite is ok. */ + ); + +/** +Client API: +Opens an encoding session for a memory buffer. Returned handle must be closed with sox_close(). +@returns The new session handle, or null on failure. +*/ +LSX_RETURN_OPT +sox_format_t * +LSX_API +sox_open_mem_write( + LSX_PARAM_OUT_BYTECAP(buffer_size) void * buffer, /**< Pointer to audio data buffer that receives data (required). */ + LSX_PARAM_IN size_t buffer_size, /**< Maximum number of bytes to write to audio data buffer. */ + LSX_PARAM_IN sox_signalinfo_t const * signal, /**< Information about desired audio stream (required). */ + LSX_PARAM_IN_OPT sox_encodinginfo_t const * encoding, /**< Information about desired sample encoding, or NULL to use defaults. */ + LSX_PARAM_IN_OPT_Z char const * filetype, /**< Previously-determined file type, or NULL to auto-detect. */ + LSX_PARAM_IN_OPT sox_oob_t const * oob /**< Out-of-band data to add to file, or NULL if none. */ + ); + +/** +Client API: +Opens an encoding session for a memstream buffer. Returned handle must be closed with sox_close(). +@returns The new session handle, or null on failure. +*/ +LSX_RETURN_OPT +sox_format_t * +LSX_API +sox_open_memstream_write( + LSX_PARAM_OUT char * * buffer_ptr, /**< Receives pointer to audio data buffer that receives data (required). */ + LSX_PARAM_OUT size_t * buffer_size_ptr, /**< Receives size of data written to audio data buffer (required). */ + LSX_PARAM_IN sox_signalinfo_t const * signal, /**< Information about desired audio stream (required). */ + LSX_PARAM_IN_OPT sox_encodinginfo_t const * encoding, /**< Information about desired sample encoding, or NULL to use defaults. */ + LSX_PARAM_IN_OPT_Z char const * filetype, /**< Previously-determined file type, or NULL to auto-detect. */ + LSX_PARAM_IN_OPT sox_oob_t const * oob /**< Out-of-band data to add to file, or NULL if none. */ + ); + +/** +Client API: +Reads samples from a decoding session into a sample buffer. +@returns Number of samples decoded, or 0 for EOF. +*/ +size_t +LSX_API +sox_read( + LSX_PARAM_INOUT sox_format_t * ft, /**< Format pointer. */ + LSX_PARAM_OUT_CAP_POST_COUNT(len,return) sox_sample_t *buf, /**< Buffer from which to read samples. */ + size_t len /**< Number of samples available in buf. */ + ); + +/** +Client API: +Writes samples to an encoding session from a sample buffer. +@returns Number of samples encoded. +*/ +size_t +LSX_API +sox_write( + LSX_PARAM_INOUT sox_format_t * ft, /**< Format pointer. */ + LSX_PARAM_IN_COUNT(len) sox_sample_t const * buf, /**< Buffer from which to read samples. */ + size_t len /**< Number of samples available in buf. */ + ); + +/** +Client API: +Closes an encoding or decoding session. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_close( + LSX_PARAM_INOUT sox_format_t * ft /**< Format pointer. */ + ); + +/** +Client API: +Sets the location at which next samples will be decoded. Returns SOX_SUCCESS if successful. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_seek( + LSX_PARAM_INOUT sox_format_t * ft, /**< Format pointer. */ + sox_uint64_t offset, /**< Sample offset at which to position reader. */ + int whence /**< Set to SOX_SEEK_SET. */ + ); + +/** +Client API: +Finds a format handler by name. +@returns Format handler data, or null if not found. +*/ +LSX_RETURN_OPT +sox_format_handler_t const * +LSX_API +sox_find_format( + LSX_PARAM_IN_Z char const * name, /**< Name of format handler to find. */ + sox_bool ignore_devices /**< Set to true to ignore device names. */ + ); + +/** +Client API: +Returns global parameters for effects +@returns global parameters for effects. +*/ +LSX_RETURN_VALID LSX_RETURN_PURE +sox_effects_globals_t * +LSX_API +sox_get_effects_globals(void); + +/** +Client API: +Deprecated macro that returns global parameters for effects. +*/ +#define sox_effects_globals (*sox_get_effects_globals()) + +/** +Client API: +Finds the effect handler with the given name. +@returns Effect pointer, or null if not found. +*/ +LSX_RETURN_OPT LSX_RETURN_PURE +sox_effect_handler_t const * +LSX_API +sox_find_effect( + LSX_PARAM_IN_Z char const * name /**< Name of effect to find. */ + ); + +/** +Client API: +Creates an effect using the given handler. +@returns The new effect, or null if not found. +*/ +LSX_RETURN_OPT +sox_effect_t * +LSX_API +sox_create_effect( + LSX_PARAM_IN sox_effect_handler_t const * eh /**< Handler to use for effect. */ + ); + +/** +Client API: +Applies the command-line options to the effect. +@returns the number of arguments consumed. +*/ +int +LSX_API +sox_effect_options( + LSX_PARAM_IN sox_effect_t *effp, /**< Effect pointer on which to set options. */ + int argc, /**< Number of arguments in argv. */ + LSX_PARAM_IN_COUNT(argc) char * const argv[] /**< Array of command-line options. */ + ); + +/** +Client API: +Returns an array containing the known effect handlers. +@returns An array containing the known effect handlers. +*/ +LSX_RETURN_VALID_Z LSX_RETURN_PURE +sox_effect_fn_t const * +LSX_API +sox_get_effect_fns(void); + +/** +Client API: +Deprecated macro that returns an array containing the known effect handlers. +*/ +#define sox_effect_fns (sox_get_effect_fns()) + +/** +Client API: +Initializes an effects chain. Returned handle must be closed with sox_delete_effects_chain(). +@returns Handle, or null on failure. +*/ +LSX_RETURN_OPT +sox_effects_chain_t * +LSX_API +sox_create_effects_chain( + LSX_PARAM_IN sox_encodinginfo_t const * in_enc, /**< Input encoding. */ + LSX_PARAM_IN sox_encodinginfo_t const * out_enc /**< Output encoding. */ + ); + +/** +Client API: +Closes an effects chain. +*/ +void +LSX_API +sox_delete_effects_chain( + LSX_PARAM_INOUT sox_effects_chain_t *ecp /**< Effects chain pointer. */ + ); + +/** +Client API: +Adds an effect to the effects chain, returns SOX_SUCCESS if successful. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_add_effect( + LSX_PARAM_INOUT sox_effects_chain_t * chain, /**< Effects chain to which effect should be added . */ + LSX_PARAM_INOUT sox_effect_t * effp, /**< Effect to be added. */ + LSX_PARAM_INOUT sox_signalinfo_t * in, /**< Input format. */ + LSX_PARAM_IN sox_signalinfo_t const * out /**< Output format. */ + ); + +/** +Client API: +Runs the effects chain, returns SOX_SUCCESS if successful. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_flow_effects( + LSX_PARAM_INOUT sox_effects_chain_t * chain, /**< Effects chain to run. */ + LSX_PARAM_IN_OPT sox_flow_effects_callback callback, /**< Callback for monitoring flow progress. */ + LSX_PARAM_IN_OPT void * client_data /**< Data to pass into callback. */ + ); + +/** +Client API: +Gets the number of clips that occurred while running an effects chain. +@returns the number of clips that occurred while running an effects chain. +*/ +sox_uint64_t +LSX_API +sox_effects_clips( + LSX_PARAM_IN sox_effects_chain_t * chain /**< Effects chain from which to read clip information. */ + ); + +/** +Client API: +Shuts down an effect (calls stop on each of its flows). +@returns the number of clips from all flows. +*/ +sox_uint64_t +LSX_API +sox_stop_effect( + LSX_PARAM_INOUT_COUNT(effp->flows) sox_effect_t * effp /**< Effect to stop. */ + ); + +/** +Client API: +Adds an already-initialized effect to the end of the chain. +*/ +void +LSX_API +sox_push_effect_last( + LSX_PARAM_INOUT sox_effects_chain_t * chain, /**< Effects chain to which effect should be added. */ + LSX_PARAM_INOUT sox_effect_t * effp /**< Effect to be added. */ + ); + +/** +Client API: +Removes and returns an effect from the end of the chain. +@returns the removed effect, or null if no effects. +*/ +LSX_RETURN_OPT +sox_effect_t * +LSX_API +sox_pop_effect_last( + LSX_PARAM_INOUT sox_effects_chain_t *chain /**< Effects chain from which to remove an effect. */ + ); + +/** +Client API: +Shut down and delete an effect. +*/ +void +LSX_API +sox_delete_effect( + LSX_PARAM_INOUT_COUNT(effp->flows) sox_effect_t *effp /**< Effect to be deleted. */ + ); + +/** +Client API: +Shut down and delete the last effect in the chain. +*/ +void +LSX_API +sox_delete_effect_last( + LSX_PARAM_INOUT sox_effects_chain_t *chain /**< Effects chain from which to remove the last effect. */ + ); + +/** +Client API: +Shut down and delete all effects in the chain. +*/ +void +LSX_API +sox_delete_effects( + LSX_PARAM_INOUT sox_effects_chain_t *chain /**< Effects chain from which to delete effects. */ + ); + +/** +Client API: +Gets the sample offset of the start of the trim, useful for efficiently +skipping the part that will be trimmed anyway (get trim start, seek, then +clear trim start). +@returns the sample offset of the start of the trim. +*/ +sox_uint64_t +LSX_API +sox_trim_get_start( + LSX_PARAM_IN sox_effect_t * effp /**< Trim effect. */ + ); + +/** +Client API: +Clears the start of the trim to 0. +*/ +void +LSX_API +sox_trim_clear_start( + LSX_PARAM_INOUT sox_effect_t * effp /**< Trim effect. */ + ); + +/** +Client API: +Returns true if the specified file is a known playlist file type. +@returns true if the specified file is a known playlist file type. +*/ +sox_bool +LSX_API +sox_is_playlist( + LSX_PARAM_IN_Z char const * filename /**< Name of file to examine. */ + ); + +/** +Client API: +Parses the specified playlist file. +@returns SOX_SUCCESS if successful. +*/ +int +LSX_API +sox_parse_playlist( + LSX_PARAM_IN sox_playlist_callback_t callback, /**< Callback to call for each item in the playlist. */ + void * p, /**< Data to pass to callback. */ + LSX_PARAM_IN char const * const listname /**< Filename of playlist file. */ + ); + +/** +Client API: +Converts a SoX error code into an error string. +@returns error string corresponding to the specified error code, +or a generic message if the error code is not recognized. +*/ +LSX_RETURN_VALID_Z LSX_RETURN_PURE +char const * +LSX_API +sox_strerror( + int sox_errno /**< Error code to look up. */ + ); + +/** +Client API: +Gets the basename of the specified file; for example, the basename of +"/a/b/c.d" would be "c". +@returns the number of characters written to base_buffer, excluding the null, +or 0 on failure. +*/ +size_t +LSX_API +sox_basename( + LSX_PARAM_OUT_Z_CAP_POST_COUNT(base_buffer_len,return) char * base_buffer, /**< Buffer into which basename should be written. */ + size_t base_buffer_len, /**< Size of base_buffer, in bytes. */ + LSX_PARAM_IN_Z char const * filename /**< Filename from which to extract basename. */ + ); + +/***************************************************************************** +Internal API: +WARNING - The items in this section are subject to instability. They only +exist in the public header because sox (the application) currently uses them. +These may be changed or removed in future versions of libSoX. +*****************************************************************************/ + +/** +Plugins API: +Print a fatal error in libSoX. +*/ +void +LSX_API +lsx_fail_impl( + LSX_PARAM_IN_PRINTF char const * fmt, /**< printf-style format string. */ + ...) + LSX_PRINTF12; + +/** +Plugins API: +Print a warning in libSoX. +*/ +void +LSX_API +lsx_warn_impl( + LSX_PARAM_IN_PRINTF char const * fmt, /**< printf-style format string. */ + ...) + LSX_PRINTF12; + +/** +Plugins API: +Print an informational message in libSoX. +*/ +void +LSX_API +lsx_report_impl( + LSX_PARAM_IN_PRINTF char const * fmt, /**< printf-style format string. */ + ...) + LSX_PRINTF12; + +/** +Plugins API: +Print a debug message in libSoX. +*/ +void +LSX_API +lsx_debug_impl( + LSX_PARAM_IN_PRINTF char const * fmt, /**< printf-style format string. */ + ...) + LSX_PRINTF12; + +/** +Plugins API: +Report a fatal error in libSoX; printf-style arguments must follow. +*/ +#define lsx_fail sox_get_globals()->subsystem=__FILE__,lsx_fail_impl + +/** +Plugins API: +Report a warning in libSoX; printf-style arguments must follow. +*/ +#define lsx_warn sox_get_globals()->subsystem=__FILE__,lsx_warn_impl + +/** +Plugins API: +Report an informational message in libSoX; printf-style arguments must follow. +*/ +#define lsx_report sox_get_globals()->subsystem=__FILE__,lsx_report_impl + +/** +Plugins API: +Report a debug message in libSoX; printf-style arguments must follow. +*/ +#define lsx_debug sox_get_globals()->subsystem=__FILE__,lsx_debug_impl + +/** +Plugins API: +String name and integer values for enumerated types (type metadata), for use +with LSX_ENUM_ITEM, lsx_find_enum_text, and lsx_find_enum_value. +*/ +typedef struct lsx_enum_item { + char const *text; /**< String name of enumeration. */ + unsigned value; /**< Integer value of enumeration. */ +} lsx_enum_item; + +/** +Plugins API: +Declares a static instance of an lsx_enum_item structure in format +{ "item", prefixitem }, for use in declaring lsx_enum_item[] arrays. +@param prefix The prefix to prepend to the item in the enumeration symbolic name. +@param item The user-visible text name of the item (must also be a valid C symbol name). +*/ +#define LSX_ENUM_ITEM(prefix, item) {#item, prefix##item}, + +/** +Plugins API: +Flags for use with lsx_find_enum_item. +*/ +enum +{ + lsx_find_enum_item_none = 0, /**< Default parameters (case-insensitive). */ + lsx_find_enum_item_case_sensitive = 1 /**< Enable case-sensitive search. */ +}; + +/** +Plugins API: +Looks up an enumeration by name in an array of lsx_enum_items. +@returns the corresponding item, or null if not found. +*/ +LSX_RETURN_OPT LSX_RETURN_PURE +lsx_enum_item const * +LSX_API +lsx_find_enum_text( + LSX_PARAM_IN_Z char const * text, /**< Name of enumeration to find. */ + LSX_PARAM_IN lsx_enum_item const * lsx_enum_items, /**< Array of items to search, with text == NULL for last item. */ + int flags /**< Search flags: 0 (case-insensitive) or lsx_find_enum_item_case_sensitive (case-sensitive). */ + ); + +/** +Plugins API: +Looks up an enumeration by value in an array of lsx_enum_items. +@returns the corresponding item, or null if not found. +*/ +LSX_RETURN_OPT LSX_RETURN_PURE +lsx_enum_item const * +LSX_API +lsx_find_enum_value( + unsigned value, /**< Enumeration value to find. */ + LSX_PARAM_IN lsx_enum_item const * lsx_enum_items /**< Array of items to search, with text == NULL for last item. */ + ); + +/** +Plugins API: +Looks up a command-line argument in a set of enumeration names, showing an +error message if the argument is not found in the set of names. +@returns The enumeration value corresponding to the matching enumeration, or +INT_MAX if the argument does not match any enumeration name. +*/ +LSX_RETURN_PURE +int +LSX_API +lsx_enum_option( + int c, /**< Option character to which arg is associated, for example with -a, c would be 'a'. */ + LSX_PARAM_IN_Z char const * arg, /**< Argument to find in enumeration list. */ + LSX_PARAM_IN lsx_enum_item const * items /**< Array of items to search, with text == NULL for last item. */ + ); + +/** +Plugins API: +Determines whether the specified string ends with the specified suffix (case-sensitive). +@returns true if the specified string ends with the specified suffix. +*/ +LSX_RETURN_PURE +sox_bool +LSX_API +lsx_strends( + LSX_PARAM_IN_Z char const * str, /**< String to search. */ + LSX_PARAM_IN_Z char const * end /**< Suffix to search for. */ + ); + +/** +Plugins API: +Finds the file extension for a filename. +@returns the file extension, not including the '.', or null if filename does +not have an extension. +*/ +LSX_RETURN_VALID_Z LSX_RETURN_PURE +char const * +LSX_API +lsx_find_file_extension( + LSX_PARAM_IN_Z char const * pathname /**< Filename to search for extension. */ + ); + +/** +Plugins API: +Formats the specified number with up to three significant figures and adds a +metric suffix in place of the exponent, such as 1.23G. +@returns A static buffer with the formatted number, valid until the next time +this function is called (note: not thread safe). +*/ +LSX_RETURN_VALID_Z +char const * +LSX_API +lsx_sigfigs3( + double number /**< Number to be formatted. */ + ); + +/** +Plugins API: +Formats the specified number as a percentage, showing up to three significant +figures. +@returns A static buffer with the formatted number, valid until the next time +this function is called (note: not thread safe). +*/ +LSX_RETURN_VALID_Z +char const * +LSX_API +lsx_sigfigs3p( + double percentage /**< Number to be formatted. */ + ); + +/** +Plugins API: +Allocates, deallocates, or resizes; like C's realloc, except that this version +terminates the running application if unable to allocate the requested memory. +@returns New buffer, or null if buffer was freed. +*/ +LSX_RETURN_OPT +void * +LSX_API +lsx_realloc( + LSX_PARAM_IN_OPT void *ptr, /**< Pointer to be freed or resized, or null if allocating a new buffer. */ + size_t newsize /**< New size for buffer, or 0 to free the buffer. */ + ); + +/** +Plugins API: +Like strcmp, except that the characters are compared without regard to case. +@returns 0 (s1 == s2), negative (s1 < s2), or positive (s1 > s2). +*/ +LSX_RETURN_PURE +int +LSX_API +lsx_strcasecmp( + LSX_PARAM_IN_Z char const * s1, /**< First string. */ + LSX_PARAM_IN_Z char const * s2 /**< Second string. */ + ); + + +/** +Plugins API: +Like strncmp, except that the characters are compared without regard to case. +@returns 0 (s1 == s2), negative (s1 < s2), or positive (s1 > s2). +*/ +LSX_RETURN_PURE +int +LSX_API +lsx_strncasecmp( + LSX_PARAM_IN_Z char const * s1, /**< First string. */ + LSX_PARAM_IN_Z char const * s2, /**< Second string. */ + size_t n /**< Maximum number of characters to examine. */ + ); + +/** +Plugins API: +Is option argument unsupported, required, or optional. +*/ +typedef enum lsx_option_arg_t { + lsx_option_arg_none, /**< Option does not have an argument. */ + lsx_option_arg_required, /**< Option requires an argument. */ + lsx_option_arg_optional /**< Option can optionally be followed by an argument. */ +} lsx_option_arg_t; + +/** +Plugins API: +lsx_getopt_init options. +*/ +typedef enum lsx_getopt_flags_t { + lsx_getopt_flag_none = 0, /**< no flags (no output, not long-only) */ + lsx_getopt_flag_opterr = 1, /**< if set, invalid options trigger lsx_warn output */ + lsx_getopt_flag_longonly = 2 /**< if set, recognize -option as a long option */ +} lsx_getopt_flags_t; + +/** +Plugins API: +lsx_getopt long option descriptor. +*/ +typedef struct lsx_option_t { + char const * name; /**< Name of the long option. */ + lsx_option_arg_t has_arg; /**< Whether the long option supports an argument and, if so, whether the argument is required or optional. */ + int * flag; /**< Flag to set if argument is present. */ + int val; /**< Value to put in flag if argument is present. */ +} lsx_option_t; + +/** +Plugins API: +lsx_getopt session information (initialization data and state). +*/ +typedef struct lsx_getopt_t { + int argc; /**< IN argc: Number of arguments in argv */ + char * const * argv; /**< IN argv: Array of arguments */ + char const * shortopts;/**< IN shortopts: Short option characters */ + lsx_option_t const * longopts; /**< IN longopts: Array of long option descriptors */ + lsx_getopt_flags_t flags; /**< IN flags: Flags for longonly and opterr */ + char const * curpos; /**< INOUT curpos: Maintains state between calls to lsx_getopt */ + int ind; /**< INOUT optind: Maintains the index of next element to be processed */ + int opt; /**< OUT optopt: Receives the option character that caused error */ + char const * arg; /**< OUT optarg: Receives the value of the option's argument */ + int lngind; /**< OUT lngind: Receives the index of the matched long option or -1 if not a long option */ +} lsx_getopt_t; + +/** +Plugins API: +Initializes an lsx_getopt_t structure for use with lsx_getopt. +*/ +void +LSX_API +lsx_getopt_init( + LSX_PARAM_IN int argc, /**< Number of arguments in argv */ + LSX_PARAM_IN_COUNT(argc) char * const * argv, /**< Array of arguments */ + LSX_PARAM_IN_Z char const * shortopts, /**< Short options, for example ":abc:def::ghi" (+/- not supported) */ + LSX_PARAM_IN_OPT lsx_option_t const * longopts, /**< Array of long option descriptors */ + LSX_PARAM_IN lsx_getopt_flags_t flags, /**< Flags for longonly and opterr */ + LSX_PARAM_IN int first, /**< First argv to check (usually 1) */ + LSX_PARAM_OUT lsx_getopt_t * state /**< State object to be initialized */ + ); + +/** +Plugins API: +Gets the next option. Options are parameters that start with "-" or "--". +If no more options, returns -1. If unrecognized short option, returns '?'. +If a recognized short option is missing a required argument, +return (shortopts[0]==':' ? ':' : '?'). If successfully recognized short +option, return the recognized character. If successfully recognized long +option, returns (option.flag ? 0 : option.val). +Note: lsx_getopt does not permute the non-option arguments. +@returns option character (short), val or 0 (long), or -1 (no more). +*/ +int +LSX_API +lsx_getopt( + LSX_PARAM_INOUT lsx_getopt_t * state /**< The getopt state pointer. */ + ); + +/* WARNING END */ + +#if defined(__cplusplus) +} +#endif + +#endif /* SOX_H */ diff --git a/freedv-dev/src/sox/sox_i.h b/freedv-dev/src/sox/sox_i.h new file mode 100644 index 00000000..e2cdbae4 --- /dev/null +++ b/freedv-dev/src/sox/sox_i.h @@ -0,0 +1,415 @@ +/* libSoX Internal header + * + * This file is meant for libSoX internal use only + * + * Copyright 2001-2008 Chris Bagwell and SoX Contributors + * + * This source code is freely redistributable and may be used for + * any purpose. This copyright notice must be maintained. + * Chris Bagwell And SoX Contributors are not responsible for + * the consequences of using this software. + */ + +#ifndef SOX_I_H +#define SOX_I_H + +#include "soxomp.h" /* Note: soxomp.h includes soxconfig.h */ +#include "sox.h" + +#if defined HAVE_FMEMOPEN +#define _GNU_SOURCE +#endif + +#include +#include +#include + +#include "util.h" + +#if defined(LSX_EFF_ALIAS) +#undef lsx_debug +#undef lsx_fail +#undef lsx_report +#undef lsx_warn +#define lsx_debug sox_globals.subsystem=effp->handler.name,lsx_debug_impl +#define lsx_fail sox_globals.subsystem=effp->handler.name,lsx_fail_impl +#define lsx_report sox_globals.subsystem=effp->handler.name,lsx_report_impl +#define lsx_warn sox_globals.subsystem=effp->handler.name,lsx_warn_impl +#endif + +#define RANQD1 ranqd1(sox_globals.ranqd1) +#define DRANQD1 dranqd1(sox_globals.ranqd1) + +typedef enum {SOX_SHORT, SOX_INT, SOX_FLOAT, SOX_DOUBLE} sox_data_t; +typedef enum {SOX_WAVE_SINE, SOX_WAVE_TRIANGLE} lsx_wave_t; +lsx_enum_item const * lsx_get_wave_enum(void); + +/* Define fseeko and ftello for platforms lacking them */ +#ifndef HAVE_FSEEKO +#define fseeko fseek +#define ftello ftell +#endif + +#ifdef _FILE_OFFSET_BITS +assert_static(sizeof(off_t) == _FILE_OFFSET_BITS >> 3, OFF_T_BUILD_PROBLEM); +#endif + +FILE * lsx_tmpfile(void); + +void lsx_debug_more_impl(char const * fmt, ...) LSX_PRINTF12; +void lsx_debug_most_impl(char const * fmt, ...) LSX_PRINTF12; + +#define lsx_debug_more sox_get_globals()->subsystem=__FILE__,lsx_debug_more_impl +#define lsx_debug_most sox_get_globals()->subsystem=__FILE__,lsx_debug_most_impl + +/* Digitise one cycle of a wave and store it as + * a table of samples of a specified data-type. + */ +void lsx_generate_wave_table( + lsx_wave_t wave_type, + sox_data_t data_type, + void * table, /* Really of type indicated by data_type. */ + size_t table_size, /* Number of points on the x-axis. */ + double min, /* Minimum value on the y-axis. (e.g. -1) */ + double max, /* Maximum value on the y-axis. (e.g. +1) */ + double phase); /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */ +char const * lsx_parsesamples(sox_rate_t rate, const char *str, uint64_t *samples, int def); +int lsx_parse_note(char const * text, char * * end_ptr); +double lsx_parse_frequency_k(char const * text, char * * end_ptr, int key); +#define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, INT_MAX) +FILE * lsx_open_input_file(sox_effect_t * effp, char const * filename); + +void lsx_prepare_spline3(double const * x, double const * y, int n, + double start_1d, double end_1d, double * y_2d); +double lsx_spline3(double const * x, double const * y, double const * y_2d, + int n, double x1); + +double lsx_bessel_I_0(double x); +int lsx_set_dft_length(int num_taps); +void init_fft_cache(void); +void clear_fft_cache(void); +void lsx_safe_rdft(int len, int type, double * d); +void lsx_safe_cdft(int len, int type, double * d); +void lsx_power_spectrum(int n, double const * in, double * out); +void lsx_power_spectrum_f(int n, float const * in, float * out); +void lsx_apply_hann_f(float h[], const int num_points); +void lsx_apply_hann(double h[], const int num_points); +void lsx_apply_hamming(double h[], const int num_points); +void lsx_apply_bartlett(double h[], const int num_points); +void lsx_apply_blackman(double h[], const int num_points, double alpha); +void lsx_apply_blackman_nutall(double h[], const int num_points); +double lsx_kaiser_beta(double att); +void lsx_apply_kaiser(double h[], const int num_points, double beta); +double * lsx_make_lpf(int num_taps, double Fc, double beta, double scale, sox_bool dc_norm); +int lsx_lpf_num_taps(double att, double tr_bw, int k); +double * lsx_design_lpf( + double Fp, /* End of pass-band; ~= 0.01dB point */ + double Fc, /* Start of stop-band */ + double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */ + sox_bool allow_aliasing, + double att, /* Stop-band attenuation in dB */ + int * num_taps, /* (Single phase.) 0: value will be estimated */ + int k); /* Number of phases; 0 for single-phase */ +void lsx_fir_to_phase(double * * h, int * len, + int * post_len, double phase0); +#define LSX_TO_6dB .5869 +#define LSX_TO_3dB ((2/3.) * (.5 + LSX_TO_6dB)) +#define LSX_MAX_TBW0 36. +#define LSX_MAX_TBW0A (LSX_MAX_TBW0 / (1 + LSX_TO_3dB)) +#define LSX_MAX_TBW3 floor(LSX_MAX_TBW0 * LSX_TO_3dB) +#define LSX_MAX_TBW3A floor(LSX_MAX_TBW0A * LSX_TO_3dB) +void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2); + +#ifdef HAVE_BYTESWAP_H +#include +#define lsx_swapw(x) bswap_16(x) +#define lsx_swapdw(x) bswap_32(x) +#elif defined(_MSC_VER) +#define lsx_swapw(x) _byteswap_ushort(x) +#define lsx_swapdw(x) _byteswap_ulong(x) +#else +#define lsx_swapw(uw) (((uw >> 8) | (uw << 8)) & 0xffff) +#define lsx_swapdw(udw) ((udw >> 24) | ((udw >> 8) & 0xff00) | ((udw << 8) & 0xff0000) | (udw << 24)) +#endif + + + +/*------------------------ Implemented in libsoxio.c -------------------------*/ + +/* Read and write basic data types from "ft" stream. */ +size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len); +int lsx_skipbytes(sox_format_t * ft, size_t n); +int lsx_padbytes(sox_format_t * ft, size_t n); +size_t lsx_writebuf(sox_format_t * ft, void const *buf, size_t len); +int lsx_reads(sox_format_t * ft, char *c, size_t len); +int lsx_writes(sox_format_t * ft, char const * c); +void lsx_set_signal_defaults(sox_format_t * ft); +#define lsx_writechars(ft, chars, len) (lsx_writebuf(ft, chars, len) == len? SOX_SUCCESS : SOX_EOF) + +size_t lsx_read_3_buf(sox_format_t * ft, sox_uint24_t *buf, size_t len); +size_t lsx_read_b_buf(sox_format_t * ft, uint8_t *buf, size_t len); +size_t lsx_read_df_buf(sox_format_t * ft, double *buf, size_t len); +size_t lsx_read_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len); +size_t lsx_read_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len); +size_t lsx_read_f_buf(sox_format_t * ft, float *buf, size_t len); +size_t lsx_read_w_buf(sox_format_t * ft, uint16_t *buf, size_t len); + +size_t lsx_write_3_buf(sox_format_t * ft, sox_uint24_t *buf, size_t len); +size_t lsx_write_b_buf(sox_format_t * ft, uint8_t *buf, size_t len); +size_t lsx_write_df_buf(sox_format_t * ft, double *buf, size_t len); +size_t lsx_write_dw_buf(sox_format_t * ft, uint32_t *buf, size_t len); +size_t lsx_write_qw_buf(sox_format_t * ft, uint64_t *buf, size_t len); +size_t lsx_write_f_buf(sox_format_t * ft, float *buf, size_t len); +size_t lsx_write_w_buf(sox_format_t * ft, uint16_t *buf, size_t len); + +int lsx_read3(sox_format_t * ft, sox_uint24_t * u3); +int lsx_readb(sox_format_t * ft, uint8_t * ub); +int lsx_readchars(sox_format_t * ft, char * chars, size_t len); +int lsx_readdf(sox_format_t * ft, double * d); +int lsx_readdw(sox_format_t * ft, uint32_t * udw); +int lsx_readqw(sox_format_t * ft, uint64_t * udw); +int lsx_readf(sox_format_t * ft, float * f); +int lsx_readw(sox_format_t * ft, uint16_t * uw); + +#if 1 /* FIXME: use defines */ +UNUSED static int lsx_readsb(sox_format_t * ft, int8_t * sb) +{return lsx_readb(ft, (uint8_t *)sb);} +UNUSED static int lsx_readsw(sox_format_t * ft, int16_t * sw) +{return lsx_readw(ft, (uint16_t *)sw);} +#else +#define lsx_readsb(ft, sb) lsx_readb(ft, (uint8_t *)sb) +#define lsx_readsw(ft, sw) lsx_readb(ft, (uint16_t *)sw) +#endif + +int lsx_write3(sox_format_t * ft, unsigned u3); +int lsx_writeb(sox_format_t * ft, unsigned ub); +int lsx_writedf(sox_format_t * ft, double d); +int lsx_writedw(sox_format_t * ft, unsigned udw); +int lsx_writeqw(sox_format_t * ft, uint64_t uqw); +int lsx_writef(sox_format_t * ft, double f); +int lsx_writew(sox_format_t * ft, unsigned uw); + +int lsx_writesb(sox_format_t * ft, signed); +int lsx_writesw(sox_format_t * ft, signed); + +int lsx_eof(sox_format_t * ft); +int lsx_error(sox_format_t * ft); +int lsx_flush(sox_format_t * ft); +int lsx_seeki(sox_format_t * ft, off_t offset, int whence); +int lsx_unreadb(sox_format_t * ft, unsigned ub); +uint64_t lsx_filelength(sox_format_t * ft); +off_t lsx_tell(sox_format_t * ft); +void lsx_clearerr(sox_format_t * ft); +void lsx_rewind(sox_format_t * ft); + +int lsx_offset_seek(sox_format_t * ft, off_t byte_offset, off_t to_sample); + +void lsx_fail_errno(sox_format_t *, int, const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 3, 4))); +#else +; +#endif + +typedef struct sox_formats_globals { /* Global parameters (for formats) */ + sox_globals_t * global_info; +} sox_formats_globals; + + + +/*------------------------------ File Handlers -------------------------------*/ + +int lsx_check_read_params(sox_format_t * ft, unsigned channels, + sox_rate_t rate, sox_encoding_t encoding, unsigned bits_per_sample, + uint64_t num_samples, sox_bool check_length); +#define LSX_FORMAT_HANDLER(name) \ +sox_format_handler_t const * lsx_##name##_format_fn(void); \ +sox_format_handler_t const * lsx_##name##_format_fn(void) +#define div_bits(size, bits) ((uint64_t)(size) * 8 / bits) + +/* Raw I/O */ +int lsx_rawstartread(sox_format_t * ft); +size_t lsx_rawread(sox_format_t * ft, sox_sample_t *buf, size_t nsamp); +int lsx_rawstopread(sox_format_t * ft); +int lsx_rawstartwrite(sox_format_t * ft); +size_t lsx_rawwrite(sox_format_t * ft, const sox_sample_t *buf, size_t nsamp); +int lsx_rawseek(sox_format_t * ft, uint64_t offset); +int lsx_rawstart(sox_format_t * ft, sox_bool default_rate, sox_bool default_channels, sox_bool default_length, sox_encoding_t encoding, unsigned bits_per_sample); +#define lsx_rawstartread(ft) lsx_rawstart(ft, sox_false, sox_false, sox_false, SOX_ENCODING_UNKNOWN, 0) +#define lsx_rawstartwrite lsx_rawstartread +#define lsx_rawstopread NULL +#define lsx_rawstopwrite NULL + +extern sox_format_handler_t const * lsx_sndfile_format_fn(void); + +char * lsx_cat_comments(sox_comments_t comments); + +/*--------------------------------- Effects ----------------------------------*/ + +int lsx_flow_copy(sox_effect_t * effp, const sox_sample_t * ibuf, + sox_sample_t * obuf, size_t * isamp, size_t * osamp); +int lsx_usage(sox_effect_t * effp); +char * lsx_usage_lines(char * * usage, char const * const * lines, size_t n); +#define EFFECT(f) extern sox_effect_handler_t const * lsx_##f##_effect_fn(void); +#include "effects.h" +#undef EFFECT + +#define NUMERIC_PARAMETER(name, min, max) { \ + char * end_ptr; \ + double d; \ + if (argc == 0) break; \ + d = strtod(*argv, &end_ptr); \ + if (end_ptr != *argv) { \ + if (d < min || d > max || *end_ptr != '\0') {\ + lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \ + return lsx_usage(effp); \ + } \ + p->name = d; \ + --argc, ++argv; \ + } \ +} + +#define TEXTUAL_PARAMETER(name, enum_table) { \ + lsx_enum_item const * e; \ + if (argc == 0) break; \ + e = lsx_find_enum_text(*argv, enum_table, 0); \ + if (e != NULL) { \ + p->name = e->value; \ + --argc, ++argv; \ + } \ +} + +#define GETOPT_NUMERIC(state, ch, name, min, max) case ch:{ \ + char * end_ptr; \ + double d = strtod(state.arg, &end_ptr); \ + if (end_ptr == state.arg || d < min || d > max || *end_ptr != '\0') {\ + lsx_fail("parameter `%s' must be between %g and %g", #name, (double)min, (double)max); \ + return lsx_usage(effp); \ + } \ + p->name = d; \ + break; \ +} + +int lsx_effect_set_imin(sox_effect_t * effp, size_t imin); + +int lsx_effects_init(void); +int lsx_effects_quit(void); + +/*--------------------------------- Dynamic Library ----------------------------------*/ + +#if defined(HAVE_WIN32_LTDL_H) + #include "win32-ltdl.h" + #define HAVE_LIBLTDL 1 + typedef lt_dlhandle lsx_dlhandle; +#elif defined(HAVE_LIBLTDL) + #include + typedef lt_dlhandle lsx_dlhandle; +#else + struct lsx_dlhandle_tag; + typedef struct lsx_dlhandle_tag *lsx_dlhandle; +#endif + +typedef void (*lsx_dlptr)(void); + +typedef struct lsx_dlfunction_info +{ + const char* name; + lsx_dlptr static_func; + lsx_dlptr stub_func; +} lsx_dlfunction_info; + +int lsx_open_dllibrary( + int show_error_on_failure, + const char* library_description, + const char * const library_names[], + const lsx_dlfunction_info func_infos[], + lsx_dlptr selected_funcs[], + lsx_dlhandle* pdl); + +void lsx_close_dllibrary( + lsx_dlhandle dl); + +#define LSX_DLENTRIES_APPLY__(entries, f, x) entries(f, x) + +#define LSX_DLENTRY_TO_PTR__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ + func_return (*func_ptr) func_args; + +#define LSX_DLENTRIES_TO_FUNCTIONS__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ + func_return func_name func_args; + +/* LSX_DLENTRIES_TO_PTRS: Given an ENTRIES macro and the name of the dlhandle + variable, declares the corresponding function pointer variables and the + dlhandle variable. */ +#define LSX_DLENTRIES_TO_PTRS(entries, dlhandle) \ + LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRY_TO_PTR__, 0) \ + lsx_dlhandle dlhandle + +/* LSX_DLENTRIES_TO_FUNCTIONS: Given an ENTRIES macro, declares the corresponding + functions. */ +#define LSX_DLENTRIES_TO_FUNCTIONS(entries) \ + LSX_DLENTRIES_APPLY__(entries, LSX_DLENTRIES_TO_FUNCTIONS__, 0) + +#define LSX_DLLIBRARY_OPEN1__(unused, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ + { #func_name, (lsx_dlptr)(static_func), (lsx_dlptr)(stub_func) }, + +#define LSX_DLLIBRARY_OPEN2__(ptr_container, func_return, func_name, func_args, static_func, stub_func, func_ptr) \ + (ptr_container)->func_ptr = (func_return (*)func_args)lsx_dlfunction_open_library_funcs[lsx_dlfunction_open_library_index++]; + +/* LSX_DLLIBRARY_OPEN: Input an ENTRIES macro, the library's description, + a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }), + the name of the dlhandle variable, the name of the structure that contains + the function pointer and dlhandle variables, and the name of the variable in + which the result of the lsx_open_dllibrary call should be stored. This will + call lsx_open_dllibrary and copy the resulting function pointers into the + structure members. If the library cannot be opened, show a failure message. */ +#define LSX_DLLIBRARY_OPEN(ptr_container, dlhandle, entries, library_description, library_names, return_var) \ + LSX_DLLIBRARY_TRYOPEN(1, ptr_container, dlhandle, entries, library_description, library_names, return_var) + +/* LSX_DLLIBRARY_TRYOPEN: Input an ENTRIES macro, the library's description, + a null-terminated list of library names (i.e. { "libmp3-0", "libmp3", NULL }), + the name of the dlhandle variable, the name of the structure that contains + the function pointer and dlhandle variables, and the name of the variable in + which the result of the lsx_open_dllibrary call should be stored. This will + call lsx_open_dllibrary and copy the resulting function pointers into the + structure members. If the library cannot be opened, show a report or a failure + message, depending on whether error_on_failure is non-zero. */ +#define LSX_DLLIBRARY_TRYOPEN(error_on_failure, ptr_container, dlhandle, entries, library_description, library_names, return_var) \ + do { \ + lsx_dlfunction_info lsx_dlfunction_open_library_infos[] = { \ + LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN1__, 0) \ + {NULL,NULL,NULL} }; \ + int lsx_dlfunction_open_library_index = 0; \ + lsx_dlptr lsx_dlfunction_open_library_funcs[sizeof(lsx_dlfunction_open_library_infos)/sizeof(lsx_dlfunction_open_library_infos[0])]; \ + (return_var) = lsx_open_dllibrary((error_on_failure), (library_description), (library_names), lsx_dlfunction_open_library_infos, lsx_dlfunction_open_library_funcs, &(ptr_container)->dlhandle); \ + LSX_DLENTRIES_APPLY__(entries, LSX_DLLIBRARY_OPEN2__, ptr_container) \ + } while(0) + +#define LSX_DLLIBRARY_CLOSE(ptr_container, dlhandle) \ + lsx_close_dllibrary((ptr_container)->dlhandle) + + /* LSX_DLENTRY_STATIC: For use in creating an ENTRIES macro. func is + expected to be available at link time. If not present, link will fail. */ +#define LSX_DLENTRY_STATIC(f,x, ret, func, args) f(x, ret, func, args, func, NULL, func) + + /* LSX_DLENTRY_DYNAMIC: For use in creating an ENTRIES macro. func need + not be available at link time (and if present, the link time version will + not be used). func will be loaded via dlsym. If this function is not + found in the shared library, the shared library will not be used. */ +#define LSX_DLENTRY_DYNAMIC(f,x, ret, func, args) f(x, ret, func, args, NULL, NULL, func) + + /* LSX_DLENTRY_STUB: For use in creating an ENTRIES macro. func need not + be available at link time (and if present, the link time version will not + be used). If using DL_LAME, the func may be loaded via dlopen/dlsym, but + if not found, the shared library will still be used if all of the + non-stub functions are found. If the function is not found via dlsym (or + if we are not loading any shared libraries), the stub will be used. This + assumes that the name of the stub function is the name of the function + + "_stub". */ +#define LSX_DLENTRY_STUB(f,x, ret, func, args) f(x, ret, func, args, NULL, func##_stub, func) + + /* LSX_DLFUNC_IS_STUB: returns true if the named function is a do-nothing + stub. Assumes that the name of the stub function is the name of the + function + "_stub". */ +#define LSX_DLFUNC_IS_STUB(ptr_container, func) ((ptr_container)->func == func##_stub) + +#endif diff --git a/freedv-dev/src/sox/soxconfig.h b/freedv-dev/src/sox/soxconfig.h new file mode 100644 index 00000000..199f88c0 --- /dev/null +++ b/freedv-dev/src/sox/soxconfig.h @@ -0,0 +1,386 @@ +/* src/soxconfig.h. Generated from soxconfig.h.in by configure. */ +/* src/soxconfig.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to dlopen() amrnb. */ +/* #undef DL_AMRNB */ + +/* Define to dlopen() amrwb. */ +/* #undef DL_AMRWB */ + +/* Define to dlopen() lame. */ +/* #undef DL_LAME */ + +/* Define to dlopen() mad. */ +/* #undef DL_MAD */ + +/* Define to dlopen() sndfile. */ +/* #undef DL_SNDFILE */ + +/* Define to dlopen() libtwolame. */ +/* #undef DL_TWOLAME */ + +/* Define if you are using an external GSM library */ +#define EXTERNAL_GSM 1 + +/* Define if you are using an external LPC10 library */ +/* #undef EXTERNAL_LPC10 */ + +/* Define to 1 if you have alsa. */ +#define HAVE_ALSA 1 + +/* Define to 1 if you have amrnb. */ +/* #undef HAVE_AMRNB */ + +/* Define to 1 if you have amrwb. */ +/* #undef HAVE_AMRWB */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_AMRWB_DEC_H */ + +/* Define to 1 if you have ao. */ +#define HAVE_AO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_BYTESWAP_H 1 + +/* Define to 1 if you have coreaudio. */ +/* #undef HAVE_COREAUDIO */ + +/* 1 if DISTRO is defined */ +/* #undef HAVE_DISTRO */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have ffmpeg. */ +/* #undef HAVE_FFMPEG */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFMPEG_AVCODEC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFMPEG_AVFORMAT_H */ + +/* Define to 1 if you have flac. */ +/* #undef HAVE_FLAC */ + +/* Define to 1 if you have the `fmemopen' function. */ +#define HAVE_FMEMOPEN 1 + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GLOB_H 1 + +/* Define to 1 if you have gsm. */ +#define HAVE_GSM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_GSM_GSM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSM_H */ + +/* Define to 1 if you have id3tag. */ +/* #undef HAVE_ID3TAG */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* 1 if should enable LADSPA */ +/* #undef HAVE_LADSPA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LAME_H */ + +/* Define to 1 if lame supports optional ID3 tags. */ +/* #undef HAVE_LAME_ID3TAG */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LAME_LAME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBAVCODEC_AVCODEC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBAVFORMAT_AVFORMAT_H */ + +/* Define to 1 if you have libltdl */ +/* #undef HAVE_LIBLTDL */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBPNG_PNG_H */ + +/* Define to 1 if you have lpc10. */ +#define HAVE_LPC10 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LPC10_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LTDL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MAD_H */ + +/* Define to 1 if you have magic. */ +/* #undef HAVE_MAGIC */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 1 + +/* Define to 1 if you have mp3. */ +/* #undef HAVE_MP3 */ + +/* Define to 1 if you have oggvorbis. */ +/* #undef HAVE_OGG_VORBIS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OMP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENCORE_AMRNB_INTERF_DEC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENCORE_AMRWB_DEC_IF_H */ + +/* Define to 1 if you have GOMP. */ +/* #undef HAVE_OPENMP */ + +/* Define to 1 if you have oss. */ +/* #undef HAVE_OSS */ + +/* Define to 1 if you have PNG. */ +/* #undef HAVE_PNG */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PNG_H */ + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define to 1 if you have pulseaudio. */ +/* #undef HAVE_PULSEAUDIO */ + +/* Define if you have libsndfile with SFC_SFC_SET_SCALE_INT_FLOAT_WRITE */ +#define HAVE_SFC_SET_SCALE_INT_FLOAT_WRITE 1 + +/* Define to 1 if you have sndfile. */ +#define HAVE_SNDFILE 1 + +/* Define if you have libsndfile >= 1.0.18 */ +#define HAVE_SNDFILE_1_0_18 1 + +/* Define if you have */ +#define HAVE_SNDFILE_H 1 + +/* Define to 1 if you have sndio. */ +/* #undef HAVE_SNDIO */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have sunaudio. */ +/* #undef HAVE_SUN_AUDIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SUN_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIMEB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TWOLAME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have waveaudio. */ +/* #undef HAVE_WAVEAUDIO */ + +/* Define to 1 if you have wavpack. */ +/* #undef HAVE_WAVPACK */ + +/* Define to 1 to use win32 glob */ +/* #undef HAVE_WIN32_GLOB_H */ + +/* Define to 1 to use internal win32 ltdl */ +/* #undef HAVE_WIN32_LTDL_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "sox" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "sox-devel@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "SoX" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "SoX 14.4.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "sox" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "14.4.1" + +/* Define to 1 if you have static alsa. */ +#define STATIC_ALSA 1 + +/* Define to 1 if you have static amrnb. */ +/* #undef STATIC_AMRNB */ + +/* Define to 1 if you have static amrwb. */ +/* #undef STATIC_AMRWB */ + +/* Define to 1 if you have static ao. */ +#define STATIC_AO 1 + +/* Define to 1 if you have static coreaudio. */ +/* #undef STATIC_COREAUDIO */ + +/* Define to 1 if you have static ffmpeg. */ +/* #undef STATIC_FFMPEG */ + +/* Define to 1 if you have static flac. */ +/* #undef STATIC_FLAC */ + +/* Define to 1 if you have static gsm. */ +#define STATIC_GSM 1 + +/* Define to 1 if you have static lpc10. */ +#define STATIC_LPC10 1 + +/* Define to 1 if you have static mp3. */ +/* #undef STATIC_MP3 */ + +/* Define to 1 if you have static oggvorbis. */ +/* #undef STATIC_OGG_VORBIS */ + +/* Define to 1 if you have static oss. */ +/* #undef STATIC_OSS */ + +/* Define to 1 if you have static pulseaudio. */ +/* #undef STATIC_PULSEAUDIO */ + +/* Define to 1 if you have static sndfile. */ +#define STATIC_SNDFILE 1 + +/* Define to 1 if you have static sndio. */ +/* #undef STATIC_SNDIO */ + +/* Define to 1 if you have static sunaudio. */ +/* #undef STATIC_SUN_AUDIO */ + +/* Define to 1 if you have static waveaudio. */ +/* #undef STATIC_WAVEAUDIO */ + +/* Define to 1 if you have static wavpack. */ +/* #undef STATIC_WAVPACK */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "14.4.1" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif diff --git a/freedv-dev/src/sox/soxomp.h b/freedv-dev/src/sox/soxomp.h new file mode 100644 index 00000000..6fce07d9 --- /dev/null +++ b/freedv-dev/src/sox/soxomp.h @@ -0,0 +1,38 @@ +#include "soxconfig.h" + +#ifdef HAVE_OPENMP + #include +#else + +typedef int omp_lock_t; +typedef int omp_nest_lock_t; + +#define omp_set_num_threads(int) (void)0 +#define omp_get_num_threads() 1 +#define omp_get_max_threads() 1 +#define omp_get_thread_num() 0 +#define omp_get_num_procs() 1 +#define omp_in_parallel() 1 + +#define omp_set_dynamic(int) (void)0 +#define omp_get_dynamic() 0 + +#define omp_set_nested(int) (void)0 +#define omp_get_nested() 0 + +#define omp_init_lock(omp_lock_t) (void)0 +#define omp_destroy_lock(omp_lock_t) (void)0 +#define omp_set_lock(omp_lock_t) (void)0 +#define omp_unset_lock(omp_lock_t) (void)0 +#define omp_test_lock(omp_lock_t) 0 + +#define omp_init_nest_lock(omp_nest_lock_t) (void)0 +#define omp_destroy_nest_lock(omp_nest_lock_t) (void)0 +#define omp_set_nest_lock(omp_nest_lock_t) (void)0 +#define omp_unset_nest_lock(omp_nest_lock_t) (void)0 +#define omp_test_nest_lock(omp_nest_lock_t) 0 + +#define omp_get_wtime() 0 +#define omp_get_wtick() 0 + +#endif diff --git a/freedv-dev/src/sox/util.h b/freedv-dev/src/sox/util.h new file mode 100644 index 00000000..89bbe752 --- /dev/null +++ b/freedv-dev/src/sox/util.h @@ -0,0 +1,231 @@ +/* General purpose, i.e. non SoX specific, utility functions and macros. + * + * (c) 2006-8 Chris Bagwell and SoX contributors + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "soxconfig.h" + +#ifdef HAVE_SYS_TYPES_H +#include /* For off_t not found in stdio.h */ +#endif + +#ifdef HAVE_SYS_STAT_H +#include /* Needs to be included before we redefine off_t. */ +#endif + +#include "xmalloc.h" + +/*---------------------------- Portability stuff -----------------------------*/ + +#if defined(HAVE_INTTYPES_H) + #include +#elif defined(HAVE_STDINT_H) + #include +#else + typedef sox_int8_t int8_t; + typedef sox_uint8_t uint8_t; + typedef sox_int16_t int16_t; + typedef sox_uint16_t uint16_t; + typedef sox_int32_t int32_t; + typedef sox_uint32_t uint32_t; + typedef sox_int64_t int64_t; + typedef sox_uint64_t uint64_t; +#endif + +/* Define the format specifier to use for int64_t values. + * Example: printf("You may have already won $ %" PRId64 " !!!", n64); */ +#ifndef PRId64 /* Maybe already defined this. */ +#if defined(_MSC_VER) || defined(__MINGW32__) /* Older versions of msvcrt.dll don't recognize %lld. */ +#define PRId64 "I64d" +#elif LONG_MAX==9223372036854775807 +#define PRId64 "ld" +#else +#define PRId64 "lld" +#endif +#endif /* PRId64 */ + +/* Define the format specifier to use for uint64_t values. */ +#ifndef PRIu64 /* Maybe already defined this. */ +#if defined(_MSC_VER) || defined(__MINGW32__) /* Older versions of msvcrt.dll don't recognize %llu. */ +#define PRIu64 "I64u" +#elif ULONG_MAX==0xffffffffffffffff +#define PRIu64 "lu" +#else +#define PRIu64 "llu" +#endif +#endif /* PRIu64 */ + +/* Define the format specifier to use for size_t values. + * Example: printf("Sizeof(x) = %" PRIuPTR " bytes", sizeof(x)); */ +#ifndef PRIuPTR /* Maybe already defined this. */ +#if defined(_MSC_VER) || defined(__MINGW32__) /* Older versions of msvcrt.dll don't recognize %zu. */ +#define PRIuPTR "Iu" +#else +#define PRIuPTR "zu" +#endif +#endif /* PRIuPTR */ + +#ifdef __GNUC__ +#define NORET __attribute__((noreturn)) +#define UNUSED __attribute__ ((unused)) +#else +#define NORET +#define UNUSED +#endif + +#ifdef _MSC_VER + +#define __STDC__ 1 +#define O_BINARY _O_BINARY +#define O_CREAT _O_CREAT +#define O_RDWR _O_RDWR +#define O_TRUNC _O_TRUNC +#define S_IFMT _S_IFMT +#define S_IFREG _S_IFREG +#define S_IREAD _S_IREAD +#define S_IWRITE _S_IWRITE +#define close _close +#define dup _dup +#define fdopen _fdopen +#define fileno _fileno + +#ifdef _fstati64 +#define fstat _fstati64 +#else +#define fstat _fstat +#endif + +#define ftime _ftime +#define inline __inline +#define isatty _isatty +#define kbhit _kbhit +#define mktemp _mktemp +#define off_t _off_t +#define open _open +#define pclose _pclose +#define popen _popen +#define setmode _setmode +#define snprintf _snprintf + +#ifdef _stati64 +#define stat _stati64 +#else +#define stat _stat +#endif + +#define strdup _strdup +#define timeb _timeb +#define unlink _unlink + +#if defined(HAVE__FSEEKI64) && !defined(HAVE_FSEEKO) +#undef off_t +#define fseeko _fseeki64 +#define ftello _ftelli64 +#define off_t __int64 +#define HAVE_FSEEKO 1 +#endif + +#elif defined(__MINGW32__) + +#if !defined(HAVE_FSEEKO) +#undef off_t +#define fseeko fseeko64 +#define fstat _fstati64 +#define ftello ftello64 +#define off_t off64_t +#define stat _stati64 +#define HAVE_FSEEKO 1 +#endif + +#endif + +#if defined(DOS) || defined(WIN32) || defined(__NT__) || defined(__DJGPP__) || defined(__OS2__) + #define LAST_SLASH(path) max(strrchr(path, '/'), strrchr(path, '\\')) + #define IS_ABSOLUTE(path) ((path)[0] == '/' || (path)[0] == '\\' || (path)[1] == ':') + #define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) + #define POPEN_MODE "rb" +#else + #define LAST_SLASH(path) strrchr(path, '/') + #define IS_ABSOLUTE(path) ((path)[0] == '/') + #define SET_BINARY_MODE(file) +#endif + +#ifdef WORDS_BIGENDIAN + #define MACHINE_IS_BIGENDIAN 1 + #define MACHINE_IS_LITTLEENDIAN 0 +#else + #define MACHINE_IS_BIGENDIAN 0 + #define MACHINE_IS_LITTLEENDIAN 1 +#endif + +/*--------------------------- Language extensions ----------------------------*/ + +/* Compile-time ("static") assertion */ +/* e.g. assert_static(sizeof(int) >= 4, int_type_too_small) */ +#define assert_static(e,f) enum {assert_static__##f = 1/(e)} +#define array_length(a) (sizeof(a)/sizeof(a[0])) +#define field_offset(type, field) ((size_t)&(((type *)0)->field)) +#define unless(x) if (!(x)) + +/*------------------------------- Maths stuff --------------------------------*/ + +#include + +#ifdef min +#undef min +#endif +#define min(a, b) ((a) <= (b) ? (a) : (b)) + +#ifdef max +#undef max +#endif +#define max(a, b) ((a) >= (b) ? (a) : (b)) + +#define range_limit(x, lower, upper) (min(max(x, lower), upper)) + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* natural log of 10 */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 sqrt(2.) +#endif + +#define sqr(a) ((a) * (a)) +#define sign(x) ((x) < 0? -1 : 1) + +/* Numerical Recipes in C, p. 284 */ +#define ranqd1(x) ((x) = 1664525L * (x) + 1013904223L) /* int32_t x */ +#define dranqd1(x) (ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */ + +#define dB_to_linear(x) exp((x) * M_LN10 * 0.05) +#define linear_to_dB(x) (log10(x) * 20) + +extern int lsx_strcasecmp(const char *s1, const char *st); +extern int lsx_strncasecmp(char const *s1, char const *s2, size_t n); + +#ifndef HAVE_STRCASECMP +#define strcasecmp(s1, s2) lsx_strcasecmp((s1), (s2)) +#define strncasecmp(s1, s2, n) lsx_strncasecmp((s1), (s2), (n)) +#endif diff --git a/freedv-dev/src/sox/xmalloc.c b/freedv-dev/src/sox/xmalloc.c new file mode 100644 index 00000000..9bf15969 --- /dev/null +++ b/freedv-dev/src/sox/xmalloc.c @@ -0,0 +1,43 @@ +/* SoX Memory allocation functions + * + * Copyright (c) 2005-2006 Reuben Thomas. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sox_i.h" +#include + +/* Resize an allocated memory area; abort if not possible. + * + * For malloc, `If the size of the space requested is zero, the behavior is + * implementation defined: either a null pointer is returned, or the + * behavior is as if the size were some nonzero value, except that the + * returned pointer shall not be used to access an object' + */ +void *lsx_realloc(void *ptr, size_t newsize) +{ + if (ptr && newsize == 0) { + free(ptr); + return NULL; + } + + if ((ptr = realloc(ptr, newsize)) == NULL) { + lsx_fail("out of memory"); + exit(2); + } + + return ptr; +} diff --git a/freedv-dev/src/sox/xmalloc.h b/freedv-dev/src/sox/xmalloc.h new file mode 100644 index 00000000..9ee77f63 --- /dev/null +++ b/freedv-dev/src/sox/xmalloc.h @@ -0,0 +1,34 @@ +/* libSoX Memory allocation functions + * + * Copyright (c) 2005-2006 Reuben Thomas. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LSX_MALLOC_H +#define LSX_MALLOC_H + +#include +#include + +#define lsx_malloc(size) lsx_realloc(NULL, (size)) +#define lsx_calloc(n,s) (((n)*(s))? memset(lsx_malloc((n)*(s)),0,(n)*(s)) : NULL) +#define lsx_Calloc(v,n) v = lsx_calloc(n,sizeof(*(v))) +#define lsx_strdup(p) ((p)? strcpy((char *)lsx_malloc(strlen(p) + 1), p) : NULL) +#define lsx_memdup(p,s) ((p)? memcpy(lsx_malloc(s), p, s) : NULL) +#define lsx_valloc(v,n) v = lsx_malloc((n)*sizeof(*(v))) +#define lsx_revalloc(v,n) v = lsx_realloc(v, (n)*sizeof(*(v))) + +#endif diff --git a/freedv-dev/src/sox_biquad.c b/freedv-dev/src/sox_biquad.c index f5a0913c..ab19660c 100644 --- a/freedv-dev/src/sox_biquad.c +++ b/freedv-dev/src/sox_biquad.c @@ -5,9 +5,13 @@ // Authors: David Rowe // // To test: -// $ gcc sox_biquad.c -o sox_biquad -DSOX_BIQUAD_UNITTEST -Wall \ -// /path/to/sox-14.4.0/src/.libs/libsox.a -lm -lsndfile -// $ ./sox_biquad +/* + $ gcc sox_biquad.c sox/effects_i.c sox/effects.c sox/formats_i.c \ + sox/biquad.c sox/biquads.c sox/xmalloc.c sox/libsox.c \ + -o sox_biquad -DSOX_BIQUAD_UNITTEST -D__FREEDV__ \ + -Wall -lm -lsndfile -g + $ ./sox_biquad +*/ // // License: // @@ -104,7 +108,7 @@ void sox_biquad_filter(void *sbq, short out[], short in[], int n) #define N 20 int main(void) { void *sbq; - char *argv[10]; + const char *argv[] = {"highpass", "1000"}; short in[N]; short out[N]; int i, argc;; @@ -114,7 +118,8 @@ int main(void) { in[0] = 8000; sox_biquad_start(); - argv[0] = "highpass"; argv[1]="1000"; argc=1; + //argv[0] = "highpass"; argv[1]="1000"; + argc=1; sbq = sox_biquad_create(argc, argv); sox_biquad_filter(sbq, out, in, N); -- 2.25.1