Feature: remove module of sox

pull/221/head
xufuji456 2 years ago
parent 1ad8783ff7
commit c21a2cf584
  1. 5
      app/src/main/cpp/CMakeLists.txt
  2. 72
      app/src/main/cpp/sox/CMakeLists.txt
  3. 367
      app/src/main/cpp/sox/adpcm.c
  4. 79
      app/src/main/cpp/sox/adpcm.h
  5. 163
      app/src/main/cpp/sox/delay.c
  6. 85
      app/src/main/cpp/sox/downsample.c
  7. 266
      app/src/main/cpp/sox/echo.c
  8. 278
      app/src/main/cpp/sox/echos.c
  9. 669
      app/src/main/cpp/sox/effects.c
  10. 38
      app/src/main/cpp/sox/effects.h
  11. 483
      app/src/main/cpp/sox/effects_i.c
  12. 645
      app/src/main/cpp/sox/effects_i_dsp.c
  13. 102
      app/src/main/cpp/sox/example0.c
  14. 167
      app/src/main/cpp/sox/example1.c
  15. 1362
      app/src/main/cpp/sox/fft4g.c
  16. 37
      app/src/main/cpp/sox/fft4g.h
  17. 119
      app/src/main/cpp/sox/fifo.h
  18. 1351
      app/src/main/cpp/sox/formats.c
  19. 130
      app/src/main/cpp/sox/formats.h
  20. 545
      app/src/main/cpp/sox/formats_i.c
  21. 2421
      app/src/main/cpp/sox/g711.c
  22. 21
      app/src/main/cpp/sox/g711.h
  23. 349
      app/src/main/cpp/sox/getopt.c
  24. 365
      app/src/main/cpp/sox/ima_rw.c
  25. 84
      app/src/main/cpp/sox/ima_rw.h
  26. 58
      app/src/main/cpp/sox/input.c
  27. 224
      app/src/main/cpp/sox/libsox.c
  28. 116
      app/src/main/cpp/sox/libsox_i.c
  29. 59
      app/src/main/cpp/sox/output.c
  30. 196
      app/src/main/cpp/sox/raw.c
  31. 54
      app/src/main/cpp/sox/raw.h
  32. 277
      app/src/main/cpp/sox/reverb.c
  33. 3036
      app/src/main/cpp/sox/sox.c
  34. 2603
      app/src/main/cpp/sox/sox.h
  35. 416
      app/src/main/cpp/sox/sox_i.h
  36. 370
      app/src/main/cpp/sox/soxconfig.h
  37. 47
      app/src/main/cpp/sox/soxomp.h
  38. 73
      app/src/main/cpp/sox/speed.c
  39. 360
      app/src/main/cpp/sox/tempo.c
  40. 64
      app/src/main/cpp/sox/upsample.c
  41. 304
      app/src/main/cpp/sox/util.c
  42. 184
      app/src/main/cpp/sox/util.h
  43. 329
      app/src/main/cpp/sox/vad.c
  44. 184
      app/src/main/cpp/sox/vol.c
  45. 1650
      app/src/main/cpp/sox/wav.c
  46. 73
      app/src/main/cpp/sox/xmalloc.c
  47. 36
      app/src/main/cpp/sox/xmalloc.h

@ -56,10 +56,6 @@ set_target_properties( ffmpeg
PROPERTIES IMPORTED_LOCATION
../../../../libs/${CMAKE_ANDROID_ARCH_ABI}/libffmpeg.so )
# third-party library: sox
#add_subdirectory(sox)
#include_directories(sox)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(.)
@ -81,7 +77,6 @@ find_library( # Sets the name of the path variable.
target_link_libraries( # Specifies the target library.
media-handle
ffmpeg
# sox
-landroid #native_window
-ljnigraphics #bitmap
-lOpenSLES #openSLES

@ -1,72 +0,0 @@
set(PROJECT_NAME sox)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(CMAKE_COMPILER_IS_GNUCC)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE ver)
string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\1" major "${ver}")
string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\2" minor "${ver}")
math(EXPR ver "100 * ${major} + ${minor}")
if(${ver} LESS 403)
add_definitions(-Wconversion)
else(${ver} LESS 403)
add_definitions(-Wtraditional-conversion)
endif(${ver} LESS 403)
endif(CMAKE_COMPILER_IS_GNUCC)
if (NOT EXTERNAL_GSM)
set(optional_libs ${optional_libs} gsm)
endif (NOT EXTERNAL_GSM)
set(effects_srcs
delay.c
downsample.c
echo.c
echos.c
fft4g.c
input.c
output.c
reverb.c
speed.c
tempo.c
upsample.c
vad.c
vol.c
)
set(formats_srcs
adpcm.c
g711.c
ima_rw.c
raw.c
wav.c
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bit-rot)
add_library(${PROJECT_NAME} STATIC
${effects_srcs}
effects.c
effects_i.c
effects_i_dsp.c
${formats_srcs}
formats_i.c
formats.c
getopt.c
libsox_i.c
libsox.c
util.c
xmalloc.c
)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
find_program(LN ln)
if (LN)
add_custom_target(rec ALL ${LN} -sf sox rec DEPENDS sox)
add_custom_target(play ALL ${LN} -sf sox play DEPENDS sox)
add_custom_target(soxi ALL ${LN} -sf sox soxi DEPENDS sox)
endif (LN)
find_program(CTAGS NAMES exuberant-ctags ctags)
add_custom_target(tags ${CTAGS} --recurse --extra=fq .)

@ -1,367 +0,0 @@
/* adpcm.c codex functions for MS_ADPCM data
* (hopefully) provides interoperability with
* Microsoft's ADPCM format, but, as usual,
* see LACK-OF-WARRANTY information below.
*
* Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.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
*
*/
/*
* November 22, 1999
* specs I've seen are unclear about ADPCM supporting more than 2 channels,
* but these routines support more channels in a manner which looks (IMHO)
* like the most natural extension.
*
* Remark: code still turbulent, encoding very new.
*
*/
#include "sox_i.h"
#include "adpcm.h"
#include <sys/types.h>
#include <stdio.h>
typedef struct {
sox_sample_t step; /* step size */
short coef[2];
} MsState_t;
#define lsbshortldi(x,p) { (x)=((short)((int)(p)[0] + ((int)(p)[1]<<8))); (p) += 2; }
/*
* Lookup tables for MS ADPCM format
*/
/* these are step-size adjust factors, where
* 1.0 is scaled to 0x100
*/
static const
sox_sample_t stepAdjustTable[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
/* TODO : The first 7 lsx_ms_adpcm_i_coef sets are always hardcoded and must
appear in the actual WAVE file. They should be read in
in case a sound program added extras to the list. */
const short lsx_ms_adpcm_i_coef[7][2] = {
{ 256, 0},
{ 512,-256},
{ 0, 0},
{ 192, 64},
{ 240, 0},
{ 460,-208},
{ 392,-232}
};
extern void *lsx_ms_adpcm_alloc(unsigned chans)
{
return lsx_malloc(chans * sizeof(MsState_t));
}
static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state,
sox_sample_t sample1, sox_sample_t sample2)
{
sox_sample_t vlin;
sox_sample_t sample;
sox_sample_t step;
/** Compute next step value **/
step = state->step;
{
sox_sample_t nstep;
nstep = (stepAdjustTable[c] * step) >> 8;
state->step = (nstep < 16)? 16:nstep;
}
/** make linear prediction for next sample **/
vlin =
((sample1 * state->coef[0]) +
(sample2 * state->coef[1])) >> 8;
/** then add the code*step adjustment **/
c -= (c & 0x08) << 1;
sample = (c * step) + vlin;
if (sample > 0x7fff) sample = 0x7fff;
else if (sample < -0x8000) sample = -0x8000;
return (sample);
}
/* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */
const char *lsx_ms_adpcm_block_expand_i(
void *priv,
unsigned chans, /* total channels */
int nCoef,
const short *coef,
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL *obuff, /* output samples, n*chans */
int n /* samples to decode PER channel */
)
{
const unsigned char *ip;
unsigned ch;
const char *errmsg = NULL;
MsState_t *state = priv; /* One decompressor state for each channel */
/* Read the four-byte header for each channel */
ip = ibuff;
for (ch = 0; ch < chans; ch++) {
unsigned char bpred = *ip++;
if (bpred >= nCoef) {
errmsg = "MSADPCM bpred >= nCoef, arbitrarily using 0\n";
bpred = 0;
}
state[ch].coef[0] = coef[(int)bpred*2+0];
state[ch].coef[1] = coef[(int)bpred*2+1];
}
for (ch = 0; ch < chans; ch++)
lsbshortldi(state[ch].step, ip);
/* sample1's directly into obuff */
for (ch = 0; ch < chans; ch++)
lsbshortldi(obuff[chans+ch], ip);
/* sample2's directly into obuff */
for (ch = 0; ch < chans; ch++)
lsbshortldi(obuff[ch], ip);
{
unsigned ch2;
unsigned char b;
short *op, *top, *tmp;
/* already have 1st 2 samples from block-header */
op = obuff + 2*chans;
top = obuff + n*chans;
ch2 = 0;
while (op < top) { /*** N.B. Without int casts, crashes on 64-bit arch ***/
b = *ip++;
tmp = op;
*op++ = AdpcmDecode(b >> 4, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]);
if (++ch2 == chans) ch2 = 0;
tmp = op;
*op++ = AdpcmDecode(b&0x0f, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]);
if (++ch2 == chans) ch2 = 0;
}
}
return errmsg;
}
static int AdpcmMashS(
unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
unsigned chans, /* total channels */
SAMPL v[2], /* values to use as starting 2 */
const short coef[2],/* lin predictor coeffs */
const SAMPL *ibuff, /* ibuff[] is interleaved input samples */
int n, /* samples to encode PER channel */
int *iostep, /* input/output step, REQUIRE 16 <= *st <= 0x7fff */
unsigned char *obuff /* output buffer[blockAlign], or NULL for no output */
)
{
const SAMPL *ip, *itop;
unsigned char *op;
int ox = 0; /* */
int d, v0, v1, step;
double d2; /* long long is okay also, speed abt the same */
ip = ibuff + ch; /* point ip to 1st input sample for this channel */
itop = ibuff + n*chans;
v0 = v[0];
v1 = v[1];
d = *ip - v1; ip += chans; /* 1st input sample for this channel */
d2 = d*d; /* d2 will be sum of squares of errors, given input v0 and *st */
d = *ip - v0; ip += chans; /* 2nd input sample for this channel */
d2 += d*d;
step = *iostep;
op = obuff; /* output pointer (or NULL) */
if (op) { /* NULL means don't output, just compute the rms error */
op += chans; /* skip bpred indices */
op += 2*ch; /* channel's stepsize */
op[0] = step; op[1] = step>>8;
op += 2*chans; /* skip to v0 */
op[0] = v0; op[1] = v0>>8;
op += 2*chans; /* skip to v1 */
op[0] = v1; op[1] = v1>>8;
op = obuff+7*chans; /* point to base of output nibbles */
ox = 4*ch;
}
for (; ip < itop; ip+=chans) {
int vlin,d3,dp,c;
/* make linear prediction for next sample */
vlin = (v0 * coef[0] + v1 * coef[1]) >> 8;
d3 = *ip - vlin; /* difference between linear prediction and current sample */
dp = d3 + (step<<3) + (step>>1);
c = 0;
if (dp>0) {
c = dp/step;
if (c>15) c = 15;
}
c -= 8;
dp = c * step; /* quantized estimate of samp - vlin */
c &= 0x0f; /* mask to 4 bits */
v1 = v0; /* shift history */
v0 = vlin + dp;
if (v0<-0x8000) v0 = -0x8000;
else if (v0>0x7fff) v0 = 0x7fff;
d3 = *ip - v0;
d2 += d3*d3; /* update square-error */
if (op) { /* if we want output, put it in proper place */
op[ox>>3] |= (ox&4)? c:(c<<4);
ox += 4*chans;
lsx_debug_more("%.1x",c);
}
/* Update the step for the next sample */
step = (stepAdjustTable[c] * step) >> 8;
if (step < 16) step = 16;
}
if (op) lsx_debug_more("\n");
d2 /= n; /* be sure it's non-negative */
lsx_debug_more("ch%d: st %d->%d, d %.1f\n", ch, *iostep, step, sqrt(d2));
*iostep = step;
return (int) sqrt(d2);
}
static inline void AdpcmMashChannel(
unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
unsigned chans, /* total channels */
const SAMPL *ip, /* ip[] is interleaved input samples */
int n, /* samples to encode PER channel, REQUIRE */
int *st, /* input/output steps, 16<=st[i] */
unsigned char *obuff /* output buffer[blockAlign] */
)
{
SAMPL v[2];
int n0,s0,s1,ss,smin;
int dmin,k,kmin;
n0 = n/2; if (n0>32) n0=32;
if (*st<16) *st = 16;
v[1] = ip[ch];
v[0] = ip[ch+chans];
dmin = 0; kmin = 0; smin = 0;
/* for each of 7 standard coeff sets, we try compression
* beginning with last step-value, and with slightly
* forward-adjusted step-value, taking best of the 14
*/
for (k=0; k<7; k++) {
int d0,d1;
ss = s0 = *st;
d0=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s0 */
s1 = s0;
AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n0, &s1, NULL);
lsx_debug_more(" s32 %d\n",s1);
ss = s1 = (3*s0+s1)/4;
d1=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s1 */
if (!k || d0<dmin || d1<dmin) {
kmin = k;
if (d0<=d1) {
dmin = d0;
smin = s0;
}else{
dmin = d1;
smin = s1;
}
}
}
*st = smin;
lsx_debug_more("kmin %d, smin %5d, ",kmin,smin);
AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[kmin], ip, n, st, obuff);
obuff[ch] = kmin;
}
void lsx_ms_adpcm_block_mash_i(
unsigned chans, /* total channels */
const SAMPL *ip, /* ip[n*chans] is interleaved input samples */
int n, /* samples to encode PER channel */
int *st, /* input/output steps, 16<=st[i] */
unsigned char *obuff, /* output buffer[blockAlign] */
int blockAlign /* >= 7*chans + chans*(n-2)/2.0 */
)
{
unsigned ch;
unsigned char *p;
lsx_debug_more("AdpcmMashI(chans %d, ip %p, n %d, st %p, obuff %p, bA %d)\n",
chans, (void *)ip, n, (void *)st, obuff, blockAlign);
for (p=obuff+7*chans; p<obuff+blockAlign; p++) *p=0;
for (ch=0; ch<chans; ch++)
AdpcmMashChannel(ch, chans, ip, n, st+ch, obuff);
}
/*
* lsx_ms_adpcm_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
* returns the number of samples/channel which would be
* in the dataLen, given the other parameters ...
* if input samplesPerBlock is 0, then returns the max
* samplesPerBlock which would go into a block of size blockAlign
* Yes, it is confusing usage.
*/
size_t lsx_ms_adpcm_samples_in(
size_t dataLen,
size_t chans,
size_t blockAlign,
size_t samplesPerBlock
){
size_t m, n;
if (samplesPerBlock) {
n = (dataLen / blockAlign) * samplesPerBlock;
m = (dataLen % blockAlign);
} else {
n = 0;
m = blockAlign;
}
if (m >= (size_t)(7*chans)) {
m -= 7*chans; /* bytes beyond block-header */
m = (2*m)/chans + 2; /* nibbles/chans + 2 in header */
if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock;
n += m;
}
return n;
}
size_t lsx_ms_adpcm_bytes_per_block(
size_t chans,
size_t samplesPerBlock
)
{
size_t n;
n = 7*chans; /* header */
if (samplesPerBlock > 2)
n += (((size_t)samplesPerBlock-2)*chans + 1)/2;
return n;
}

@ -1,79 +0,0 @@
/* adpcm.h codex functions for MS_ADPCM data
* (hopefully) provides interoperability with
* Microsoft's ADPCM format, but, as usual,
* see LACK-OF-WARRANTY information below.
*
* Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.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 "sox.h"
#ifndef SAMPL
#define SAMPL short
#endif
/* default coef sets */
extern const short lsx_ms_adpcm_i_coef[7][2];
extern void *lsx_ms_adpcm_alloc(unsigned chans);
/* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */
extern const char *lsx_ms_adpcm_block_expand_i(
void *priv,
unsigned chans, /* total channels */
int nCoef,
const short *coef,
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL *obuff, /* output samples, n*chans */
int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
);
extern void lsx_ms_adpcm_block_mash_i(
unsigned chans, /* total channels */
const SAMPL *ip, /* ip[n*chans] is interleaved input samples */
int n, /* samples to encode PER channel, REQUIRE */
int *st, /* input/output steps, 16<=st[i] */
unsigned char *obuff, /* output buffer[blockAlign] */
int blockAlign /* >= 7*chans + n/2 */
);
/* Some helper functions for computing samples/block and blockalign */
/*
* lsx_ms_adpcm_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
* returns the number of samples/channel which would be
* in the dataLen, given the other parameters ...
* if input samplesPerBlock is 0, then returns the max
* samplesPerBlock which would go into a block of size blockAlign
* Yes, it is confusing usage.
*/
extern size_t lsx_ms_adpcm_samples_in(
size_t dataLen,
size_t chans,
size_t blockAlign,
size_t samplesPerBlock
);
/*
* size_t lsx_ms_adpcm_bytes_per_block(chans, samplesPerBlock)
* return minimum blocksize which would be required
* to encode number of chans with given samplesPerBlock
*/
extern size_t lsx_ms_adpcm_bytes_per_block(
size_t chans,
size_t samplesPerBlock
);

@ -1,163 +0,0 @@
/* libSoX effect: Delay one or more channels (c) 2008 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 "sox_i.h"
#include <string.h>
typedef struct {
size_t argc;
struct { char *str; uint64_t delay; } *args;
uint64_t *max_delay;
uint64_t delay, pre_pad, pad;
size_t buffer_size, buffer_index;
sox_sample_t * buffer;
sox_bool drain_started;
} priv_t;
static int lsx_kill(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
for (i = 0; i < p->argc; ++i)
free(p->args[i].str);
free(p->args);
free(p->max_delay);
return SOX_SUCCESS;
}
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
--argc, ++argv;
p->argc = argc;
p->args = lsx_calloc(p->argc, sizeof(*p->args));
p->max_delay = lsx_malloc(sizeof(*p->max_delay));
for (i = 0; i < p->argc; ++i) {
char const * next = lsx_parseposition(0., p->args[i].str = lsx_strdup(argv[i]), NULL, (uint64_t)0, (uint64_t)0, '=');
if (!next || *next) {
lsx_kill(effp);
return lsx_usage(effp);
}
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
free(p->buffer);
return SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
uint64_t max_delay = 0, last_seen = 0, delay;
uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;
if (effp->flow == 0) {
unsigned i;
if (p->argc > effp->in_signal.channels) {
lsx_fail("too few input channels");
return SOX_EOF;
}
for (i = 0; i < p->argc; ++i) {
if (!lsx_parseposition(effp->in_signal.rate, p->args[i].str, &delay, last_seen, in_length, '=') || delay == SOX_UNKNOWN_LEN) {
lsx_fail("Position relative to end of audio specified, but audio length is unknown");
return SOX_EOF;
}
p->args[i].delay = last_seen = delay;
if (delay > max_delay) {
max_delay = delay;
}
}
*p->max_delay = max_delay;
if (max_delay == 0)
return SOX_EFF_NULL;
effp->out_signal.length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
effp->in_signal.length + max_delay * effp->in_signal.channels :
SOX_UNKNOWN_LEN;
lsx_debug("extending audio by %" PRIu64 " samples", max_delay);
}
max_delay = *p->max_delay;
if (effp->flow < p->argc)
p->buffer_size = p->args[effp->flow].delay;
p->buffer_index = p->delay = p->pre_pad = 0;
p->pad = max_delay - p->buffer_size;
p->buffer = lsx_malloc(p->buffer_size * sizeof(*p->buffer));
p->drain_started = sox_false;
return SOX_SUCCESS;
}
static int 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);
if (!p->buffer_size)
memcpy(obuf, ibuf, len * sizeof(*obuf));
else for (; len; --len) {
if (p->delay < p->buffer_size) {
p->buffer[p->delay++] = *ibuf++;
*obuf++ = 0;
} else {
*obuf++ = p->buffer[p->buffer_index];
p->buffer[p->buffer_index++] = *ibuf++;
p->buffer_index %= p->buffer_size;
}
}
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
size_t len;
if (! p->drain_started) {
p->drain_started = sox_true;
p->pre_pad = p->buffer_size - p->delay;
/* If the input was too short to fill the buffer completely,
flow() has not yet output enough silence to reach the
desired delay. */
}
len = *osamp = min(p->pre_pad + p->delay + p->pad, *osamp);
for (; p->pre_pad && len; --p->pre_pad, --len)
*obuf++ = 0;
for (; p->delay && len; --p->delay, --len) {
*obuf++ = p->buffer[p->buffer_index++];
p->buffer_index %= p->buffer_size;
}
for (; p->pad && len; --p->pad, --len)
*obuf++ = 0;
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_delay_effect_fn(void)
{
static sox_effect_handler_t handler = {
"delay", "{position}", SOX_EFF_LENGTH | SOX_EFF_MODIFY,
create, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
};
return &handler;
}

@ -1,85 +0,0 @@
/* libSoX effect: Downsample
*
* First version of this effect written 11/2011 by Ulrich Klauer.
*
* Copyright 2011 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"
typedef struct {
unsigned int factor;
unsigned int carry; /* number of samples still to be discarded,
carried over from last block */
} priv_t;
static int create(sox_effect_t *effp, int argc, char **argv)
{
priv_t *p = (priv_t*)effp->priv;
p->factor = 2;
--argc, ++argv;
do { /* break-able block */
NUMERIC_PARAMETER(factor, 1, 16384)
} while (0);
return argc ? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t *effp)
{
priv_t *p = (priv_t*) effp->priv;
effp->out_signal.rate = effp->in_signal.rate / p->factor;
return p->factor == 1 ? SOX_EFF_NULL : SOX_SUCCESS;
}
static int 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 ilen = *isamp, olen = *osamp;
size_t t;
t = min(p->carry, ilen);
p->carry -= t;
ibuf += t; ilen -= t;
/* NB: either p->carry (usually) or ilen is now zero; hence, a
non-zero value of ilen implies p->carry == 0, and there is no
need to test for this in the following while and if. */
while (ilen >= p->factor && olen) {
*obuf++ = *ibuf;
ibuf += p->factor;
olen--; ilen -= p->factor;
}
if (ilen && olen) {
*obuf++ = *ibuf;
p->carry = p->factor - ilen;
olen--; ilen = 0;
}
*isamp -= ilen, *osamp -= olen;
return SOX_SUCCESS;
}
sox_effect_handler_t const *lsx_downsample_effect_fn(void)
{
static sox_effect_handler_t handler = {"downsample", "[factor (2)]",
SOX_EFF_RATE | SOX_EFF_MODIFY,
create, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
return &handler;
}

@ -1,266 +0,0 @@
/* libSoX Echo effect August 24, 1998
*
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Juergen Mueller And Sundry Contributors are not responsible for
* the consequences of using this software.
*
*
* Flow diagram scheme for n delays ( 1 <= n <= MAX_ECHOS ):
*
* * gain-in ___
* ibuff -----------+------------------------------------------>| |
* | _________ | |
* | | | * decay 1 | |
* +----->| delay 1 |------------------------->| |
* | |_________| | |
* | _________ | + |
* | | | * decay 2 | |
* +---------->| delay 2 |-------------------->| |
* | |_________| | |
* : _________ | |
* | | | * decay n | |
* +--------------->| delay n |--------------->|___|
* |_________| |
* | * gain-out
* |
* +----->obuff
* Usage:
* echo gain-in gain-out delay-1 decay-1 [delay-2 decay-2 ... delay-n decay-n]
*
* Where:
* gain-in, decay-1 ... decay-n : 0.0 ... 1.0 volume
* gain-out : 0.0 ... volume
* delay-1 ... delay-n : > 0.0 msec
*
* Note:
* when decay is close to 1.0, the samples can begin clipping and the output
* can saturate!
*
* Hint:
* 1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n )
*/
#include "sox_i.h"
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
#define DELAY_BUFSIZ ( 50 * 50U * 1024 )
#define MAX_ECHOS 7 /* 24 bit x ( 1 + MAX_ECHOS ) = */
/* 24 bit x 8 = 32 bit !!! */
/* Private data for SKEL file */
typedef struct {
int counter;
int num_delays;
double *delay_buf;
float in_gain, out_gain;
float delay[MAX_ECHOS], decay[MAX_ECHOS];
ptrdiff_t samples[MAX_ECHOS], maxsamples;
size_t fade_out;
} priv_t;
/* Private data for SKEL file */
/*
* Process options
*/
static int sox_echo_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * echo = (priv_t *) effp->priv;
int i;
--argc, ++argv;
echo->num_delays = 0;
if ((argc < 4) || (argc % 2))
return lsx_usage(effp);
i = 0;
sscanf(argv[i++], "%f", &echo->in_gain);
sscanf(argv[i++], "%f", &echo->out_gain);
while (i < argc) {
if ( echo->num_delays >= MAX_ECHOS )
lsx_fail("echo: to many delays, use less than %i delays",
MAX_ECHOS);
/* Linux bug and it's cleaner. */
sscanf(argv[i++], "%f", &echo->delay[echo->num_delays]);
sscanf(argv[i++], "%f", &echo->decay[echo->num_delays]);
echo->num_delays++;
}
return (SOX_SUCCESS);
}
/*
* Prepare for processing.
*/
static int sox_echo_start(sox_effect_t * effp)
{
priv_t * echo = (priv_t *) effp->priv;
int i;
float sum_in_volume;
long j;
echo->maxsamples = 0;
if ( echo->in_gain < 0.0 )
{
lsx_fail("echo: gain-in must be positive!");
return (SOX_EOF);
}
if ( echo->in_gain > 1.0 )
{
lsx_fail("echo: gain-in must be less than 1.0!");
return (SOX_EOF);
}
if ( echo->out_gain < 0.0 )
{
lsx_fail("echo: gain-in must be positive!");
return (SOX_EOF);
}
for ( i = 0; i < echo->num_delays; i++ ) {
echo->samples[i] = echo->delay[i] * effp->in_signal.rate / 1000.0;
if ( echo->samples[i] < 1 )
{
lsx_fail("echo: delay must be positive!");
return (SOX_EOF);
}
if ( echo->samples[i] > (ptrdiff_t)DELAY_BUFSIZ )
{
lsx_fail("echo: delay must be less than %g seconds!",
DELAY_BUFSIZ / effp->in_signal.rate );
return (SOX_EOF);
}
if ( echo->decay[i] < 0.0 )
{
lsx_fail("echo: decay must be positive!" );
return (SOX_EOF);
}
if ( echo->decay[i] > 1.0 )
{
lsx_fail("echo: decay must be less than 1.0!" );
return (SOX_EOF);
}
if ( echo->samples[i] > echo->maxsamples )
echo->maxsamples = echo->samples[i];
}
echo->delay_buf = lsx_malloc(sizeof (double) * echo->maxsamples);
for ( j = 0; j < echo->maxsamples; ++j )
echo->delay_buf[j] = 0.0;
/* Be nice and check the hint with warning, if... */
sum_in_volume = 1.0;
for ( i = 0; i < echo->num_delays; i++ )
sum_in_volume += echo->decay[i];
if ( sum_in_volume * echo->in_gain > 1.0 / echo->out_gain )
lsx_warn("echo: warning >>> gain-out can cause saturation of output <<<");
echo->counter = 0;
echo->fade_out = echo->maxsamples;
effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
return (SOX_SUCCESS);
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
static int sox_echo_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * echo = (priv_t *) effp->priv;
int j;
double d_in, d_out;
sox_sample_t out;
size_t len = min(*isamp, *osamp);
*isamp = *osamp = len;
while (len--) {
/* Store delays as 24-bit signed longs */
d_in = (double) *ibuf++ / 256;
/* Compute output first */
d_out = d_in * echo->in_gain;
for ( j = 0; j < echo->num_delays; j++ ) {
d_out += echo->delay_buf[
(echo->counter + echo->maxsamples - echo->samples[j]) % echo->maxsamples]
* echo->decay[j];
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echo->out_gain;
out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
*obuf++ = out * 256;
/* Store input in delay buffer */
echo->delay_buf[echo->counter] = d_in;
/* Adjust the counter */
echo->counter = ( echo->counter + 1 ) % echo->maxsamples;
}
/* processed all samples */
return (SOX_SUCCESS);
}
/*
* Drain out reverb lines.
*/
static int sox_echo_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * echo = (priv_t *) effp->priv;
double d_in, d_out;
sox_sample_t out;
int j;
size_t done;
done = 0;
/* drain out delay samples */
while ( ( done < *osamp ) && ( done < echo->fade_out ) ) {
d_in = 0;
d_out = 0;
for ( j = 0; j < echo->num_delays; j++ ) {
d_out += echo->delay_buf[
(echo->counter + echo->maxsamples - echo->samples[j]) % echo->maxsamples]
* echo->decay[j];
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echo->out_gain;
out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
*obuf++ = out * 256;
/* Store input in delay buffer */
echo->delay_buf[echo->counter] = d_in;
/* Adjust the counters */
echo->counter = ( echo->counter + 1 ) % echo->maxsamples;
done++;
echo->fade_out--;
};
/* samples played, it remains */
*osamp = done;
if (echo->fade_out == 0)
return SOX_EOF;
else
return SOX_SUCCESS;
}
static int sox_echo_stop(sox_effect_t * effp)
{
priv_t * echo = (priv_t *) effp->priv;
free(echo->delay_buf);
echo->delay_buf = NULL;
return (SOX_SUCCESS);
}
static sox_effect_handler_t sox_echo_effect = {
"echo",
"gain-in gain-out delay decay [ delay decay ... ]",
SOX_EFF_LENGTH | SOX_EFF_GAIN,
sox_echo_getopts,
sox_echo_start,
sox_echo_flow,
sox_echo_drain,
sox_echo_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_echo_effect_fn(void)
{
return &sox_echo_effect;
}

@ -1,278 +0,0 @@
/* libSoX Echo effect August 24, 1998
*
* Copyright (C) 1998 Juergen Mueller And Sundry Contributors
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Juergen Mueller And Sundry Contributors are not responsible for
* the consequences of using this software.
*
*
* Flow diagram scheme for n delays ( 1 <= n <= MAX_ECHOS ):
*
* * gain-in ___
* ibuff --+--------------------------------------------------->| |
* | * decay 1 | |
* | +----------------------------------->| |
* | | * decay 2 | + |
* | | +--------------------->| |
* | | | * decay n | |
* | _________ | _________ | _________ +--->|___|
* | | | | | | | | | | |
* +-->| delay 1 |-+-| delay 2 |-+...-| delay n |--+ | * gain-out
* |_________| |_________| |_________| |
* +----->obuff
* Usage:
* echos gain-in gain-out delay-1 decay-1 [delay-2 decay-2 ... delay-n decay-n]
*
* Where:
* gain-in, decay-1 ... decay-n : 0.0 ... 1.0 volume
* gain-out : 0.0 ... volume
* delay-1 ... delay-n : > 0.0 msec
*
* Note:
* when decay is close to 1.0, the samples can begin clipping and the output
* can saturate!
*
* Hint:
* 1 / out-gain > gain-in ( 1 + decay-1 + ... + decay-n )
*
*/
#include "sox_i.h"
#include <stdlib.h> /* Harmless, and prototypes atof() etc. --dgc */
#define DELAY_BUFSIZ ( 50 * 50U * 1024 )
#define MAX_ECHOS 7 /* 24 bit x ( 1 + MAX_ECHOS ) = */
/* 24 bit x 8 = 32 bit !!! */
/* Private data for SKEL file */
typedef struct {
int counter[MAX_ECHOS];
int num_delays;
double *delay_buf;
float in_gain, out_gain;
float delay[MAX_ECHOS], decay[MAX_ECHOS];
ptrdiff_t samples[MAX_ECHOS], pointer[MAX_ECHOS];
size_t sumsamples;
} priv_t;
/* Private data for SKEL file */
/*
* Process options
*/
static int sox_echos_getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * echos = (priv_t *) effp->priv;
int i;
echos->num_delays = 0;
--argc, ++argv;
if ((argc < 4) || (argc % 2))
return lsx_usage(effp);
i = 0;
sscanf(argv[i++], "%f", &echos->in_gain);
sscanf(argv[i++], "%f", &echos->out_gain);
while (i < argc) {
/* Linux bug and it's cleaner. */
sscanf(argv[i++], "%f", &echos->delay[echos->num_delays]);
sscanf(argv[i++], "%f", &echos->decay[echos->num_delays]);
echos->num_delays++;
if ( echos->num_delays > MAX_ECHOS )
{
lsx_fail("echos: to many delays, use less than %i delays",
MAX_ECHOS);
return (SOX_EOF);
}
}
echos->sumsamples = 0;
return (SOX_SUCCESS);
}
/*
* Prepare for processing.
*/
static int sox_echos_start(sox_effect_t * effp)
{
priv_t * echos = (priv_t *) effp->priv;
int i;
float sum_in_volume;
unsigned long j;
if ( echos->in_gain < 0.0 )
{
lsx_fail("echos: gain-in must be positive!");
return (SOX_EOF);
}
if ( echos->in_gain > 1.0 )
{
lsx_fail("echos: gain-in must be less than 1.0!");
return (SOX_EOF);
}
if ( echos->out_gain < 0.0 )
{
lsx_fail("echos: gain-in must be positive!");
return (SOX_EOF);
}
for ( i = 0; i < echos->num_delays; i++ ) {
echos->samples[i] = echos->delay[i] * effp->in_signal.rate / 1000.0;
if ( echos->samples[i] < 1 )
{
lsx_fail("echos: delay must be positive!");
return (SOX_EOF);
}
if ( echos->samples[i] > (ptrdiff_t)DELAY_BUFSIZ )
{
lsx_fail("echos: delay must be less than %g seconds!",
DELAY_BUFSIZ / effp->in_signal.rate );
return (SOX_EOF);
}
if ( echos->decay[i] < 0.0 )
{
lsx_fail("echos: decay must be positive!" );
return (SOX_EOF);
}
if ( echos->decay[i] > 1.0 )
{
lsx_fail("echos: decay must be less than 1.0!" );
return (SOX_EOF);
}
echos->counter[i] = 0;
echos->pointer[i] = echos->sumsamples;
echos->sumsamples += echos->samples[i];
}
echos->delay_buf = lsx_malloc(sizeof (double) * echos->sumsamples);
for ( j = 0; j < echos->sumsamples; ++j )
echos->delay_buf[j] = 0.0;
/* Be nice and check the hint with warning, if... */
sum_in_volume = 1.0;
for ( i = 0; i < echos->num_delays; i++ )
sum_in_volume += echos->decay[i];
if ( sum_in_volume * echos->in_gain > 1.0 / echos->out_gain )
lsx_warn("echos: warning >>> gain-out can cause saturation of output <<<");
effp->out_signal.length = SOX_UNKNOWN_LEN; /* TODO: calculate actual length */
return (SOX_SUCCESS);
}
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
static int sox_echos_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * echos = (priv_t *) effp->priv;
int j;
double d_in, d_out;
sox_sample_t out;
size_t len = min(*isamp, *osamp);
*isamp = *osamp = len;
while (len--) {
/* Store delays as 24-bit signed longs */
d_in = (double) *ibuf++ / 256;
/* Compute output first */
d_out = d_in * echos->in_gain;
for ( j = 0; j < echos->num_delays; j++ ) {
d_out += echos->delay_buf[echos->counter[j] + echos->pointer[j]] * echos->decay[j];
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echos->out_gain;
out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
*obuf++ = out * 256;
/* Mix decay of delays and input */
for ( j = 0; j < echos->num_delays; j++ ) {
if ( j == 0 )
echos->delay_buf[echos->counter[j] + echos->pointer[j]] = d_in;
else
echos->delay_buf[echos->counter[j] + echos->pointer[j]] =
echos->delay_buf[echos->counter[j-1] + echos->pointer[j-1]] + d_in;
}
/* Adjust the counters */
for ( j = 0; j < echos->num_delays; j++ )
echos->counter[j] =
( echos->counter[j] + 1 ) % echos->samples[j];
}
/* processed all samples */
return (SOX_SUCCESS);
}
/*
* Drain out reverb lines.
*/
static int sox_echos_drain(sox_effect_t * effp, sox_sample_t *obuf, size_t *osamp)
{
priv_t * echos = (priv_t *) effp->priv;
double d_in, d_out;
sox_sample_t out;
int j;
size_t done;
done = 0;
/* drain out delay samples */
while ( ( done < *osamp ) && ( done < echos->sumsamples ) ) {
d_in = 0;
d_out = 0;
for ( j = 0; j < echos->num_delays; j++ ) {
d_out += echos->delay_buf[echos->counter[j] + echos->pointer[j]] * echos->decay[j];
}
/* Adjust the output volume and size to 24 bit */
d_out = d_out * echos->out_gain;
out = SOX_24BIT_CLIP_COUNT((sox_sample_t) d_out, effp->clips);
*obuf++ = out * 256;
/* Mix decay of delays and input */
for ( j = 0; j < echos->num_delays; j++ ) {
if ( j == 0 )
echos->delay_buf[echos->counter[j] + echos->pointer[j]] = d_in;
else
echos->delay_buf[echos->counter[j] + echos->pointer[j]] =
echos->delay_buf[echos->counter[j-1] + echos->pointer[j-1]];
}
/* Adjust the counters */
for ( j = 0; j < echos->num_delays; j++ )
echos->counter[j] =
( echos->counter[j] + 1 ) % echos->samples[j];
done++;
echos->sumsamples--;
};
/* samples played, it remains */
*osamp = done;
if (echos->sumsamples == 0)
return SOX_EOF;
else
return SOX_SUCCESS;
}
/*
* Clean up echos effect.
*/
static int sox_echos_stop(sox_effect_t * effp)
{
priv_t * echos = (priv_t *) effp->priv;
free(echos->delay_buf);
echos->delay_buf = NULL;
return (SOX_SUCCESS);
}
static sox_effect_handler_t sox_echos_effect = {
"echos",
"gain-in gain-out delay decay [ delay decay ... ]",
SOX_EFF_LENGTH | SOX_EFF_GAIN,
sox_echos_getopts,
sox_echos_start,
sox_echos_flow,
sox_echos_drain,
sox_echos_stop,
NULL, sizeof(priv_t)
};
const sox_effect_handler_t *lsx_echos_effect_fn(void)
{
return &sox_echos_effect;
}

@ -1,669 +0,0 @@
/* 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 <assert.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#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;
size_t 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);
effp->handler.kill(effp);
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 = %" PRIuPTR, 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;
}
/* An effect's output buffer (effp->obuf) generally has this layout:
* |. . . A1A2A3B1B2B3C1C2C3. . . . . . . . . . . . . . . . . . |
* ^0 ^obeg ^oend ^bufsiz
* (where A1 is the first sample of channel 1, A2 the first sample of
* channel 2, etc.), i.e. the channels are interleaved.
* However, while sox_flow_effects() is running, output buffers are
* adapted to how the following effect expects its input, to avoid
* back-and-forth conversions. If the following effect operates on
* each of several channels separately (flows > 1), the layout is
* changed to this uninterleaved form:
* |. A1B1C1. . . . . . . A2B2C2. . . . . . . A3B3C3. . . . . . |
* ^0 ^obeg ^oend ^bufsiz
* <--- channel 1 ----><--- channel 2 ----><--- channel 3 ---->
* The buffer is logically subdivided into channel buffers of size
* bufsiz/flows each, starting at offsets 0, bufsiz/flows,
* 2*(bufsiz/flows) etc. Within the channel buffers, the data starts
* at position obeg/flows and ends before oend/flows. In case bufsiz
* is not evenly divisible by flows, there will be an unused area at
* the very end of the output buffer.
* The interleave() and deinterleave() functions convert between these
* two representations.
*/
static void interleave(size_t flows, size_t length, sox_sample_t *from,
size_t bufsiz, size_t offset, sox_sample_t *to);
static void deinterleave(size_t flows, size_t length, sox_sample_t *from,
sox_sample_t *to, size_t bufsiz, size_t offset);
static int flow_effect(sox_effects_chain_t * chain, size_t n)
{
sox_effect_t *effp1 = chain->effects[n - 1];
sox_effect_t *effp = chain->effects[n];
int effstatus = SOX_SUCCESS;
size_t f = 0;
size_t idone = effp1->oend - effp1->obeg;
size_t obeg = sox_globals.bufsiz - effp->oend;
sox_bool il_change = (effp->flows == 1) !=
(chain->length == n + 1 || chain->effects[n+1]->flows == 1);
#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,
il_change ? chain->il_buf : effp->obuf + effp->oend,
&idone, &obeg);
if (obeg % effp->out_signal.channels != 0) {
lsx_fail("multi-channel effect flowed asymmetrically!");
effstatus = SOX_EOF;
}
if (il_change)
deinterleave(chain->effects[n+1]->flows, obeg, chain->il_buf,
effp->obuf, sox_globals.bufsiz, effp->oend);
} else { /* Run effect on each channel individually */
sox_sample_t *obuf = il_change ? chain->il_buf : effp->obuf;
size_t flow_offs = sox_globals.bufsiz/effp->flows;
size_t idone_min = SOX_SIZE_MAX, idone_max = 0;
size_t odone_min = SOX_SIZE_MAX, odone_max = 0;
#ifdef HAVE_OPENMP_3_1
#pragma omp parallel for \
if(sox_globals.use_threads) \
schedule(static) default(none) \
shared(effp,effp1,idone,obeg,obuf,flow_offs,chain,n,effstatus) \
reduction(min:idone_min,odone_min) reduction(max:idone_max,odone_max)
#elif defined HAVE_OPENMP
#pragma omp parallel for \
if(sox_globals.use_threads) \
schedule(static) default(none) \
shared(effp,effp1,idone,obeg,obuf,flow_offs,chain,n,effstatus) \
firstprivate(idone_min,odone_min,idone_max,odone_max) \
lastprivate(idone_min,odone_min,idone_max,odone_max)
#endif
for (f = 0; f < 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],
effp1->obuf + f*flow_offs + effp1->obeg/effp->flows,
obuf + f*flow_offs + effp->oend/effp->flows,
&idonec, &odonec);
idone_min = min(idonec, idone_min); idone_max = max(idonec, idone_max);
odone_min = min(odonec, odone_min); odone_max = max(odonec, odone_max);
if (eff_status_c != SOX_SUCCESS)
effstatus = SOX_EOF;
}
if (idone_min != idone_max || odone_min != odone_max) {
lsx_fail("flowed asymmetrically!");
effstatus = SOX_EOF;
}
idone = effp->flows * idone_max;
obeg = effp->flows * odone_max;
if (il_change)
interleave(effp->flows, obeg, chain->il_buf, sox_globals.bufsiz,
effp->oend, effp->obuf + effp->oend);
}
effp1->obeg += idone;
if (effp1->obeg == effp1->oend)
effp1->obeg = effp1->oend = 0;
else if (effp1->oend - effp1->obeg < effp->imin) { /* Need to refill? */
size_t flow_offs = sox_globals.bufsiz/effp->flows;
for (f = 0; f < effp->flows; ++f)
memcpy(effp1->obuf + f * flow_offs,
effp1->obuf + f * flow_offs + effp1->obeg/effp->flows,
(effp1->oend - effp1->obeg)/effp->flows * sizeof(*effp1->obuf));
effp1->oend -= effp1->obeg;
effp1->obeg = 0;
}
effp->oend += obeg;
#if DEBUG_EFFECTS_CHAIN
lsx_report("\t" "flow: %2" PRIuPTR " (%1" PRIuPTR ") "
"%5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " "
"%5" PRIuPTR " [%" PRIuPTR "-%" PRIuPTR "]",
n, effp->flows, pre_idone, pre_odone, idone, obeg,
effp1->oend - effp1->obeg, effp1->obeg, effp1->oend);
#endif
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];
int effstatus = SOX_SUCCESS;
size_t f = 0;
size_t obeg = sox_globals.bufsiz - effp->oend;
sox_bool il_change = (effp->flows == 1) !=
(chain->length == n + 1 || chain->effects[n+1]->flows == 1);
#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,
il_change ? chain->il_buf : effp->obuf + effp->oend,
&obeg);
if (obeg % effp->out_signal.channels != 0) {
lsx_fail("multi-channel effect drained asymmetrically!");
effstatus = SOX_EOF;
}
if (il_change)
deinterleave(chain->effects[n+1]->flows, obeg, chain->il_buf,
effp->obuf, sox_globals.bufsiz, effp->oend);
} else { /* Run effect on each channel individually */
sox_sample_t *obuf = il_change ? chain->il_buf : effp->obuf;
size_t flow_offs = sox_globals.bufsiz/effp->flows;
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],
obuf + f*flow_offs + effp->oend/effp->flows,
&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;
}
obeg = effp->flows * odone_last;
if (il_change)
interleave(effp->flows, obeg, chain->il_buf, sox_globals.bufsiz,
effp->oend, effp->obuf + effp->oend);
}
if (!obeg) /* This is the only thing that drain has and flow hasn't */
effstatus = SOX_EOF;
effp->oend += obeg;
#if DEBUG_EFFECTS_CHAIN
lsx_report("\t" "drain: %2" PRIuPTR " (%1" PRIuPTR ") "
"%5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR " %5" PRIuPTR,
n, effp->flows, (size_t)0, pre_odone, (size_t)0, obeg);
#endif
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 max_flows = 0;
sox_bool draining = sox_true;
for (e = 0; e < chain->length; ++e) {
sox_effect_t *effp = chain->effects[e];
effp->obuf =
lsx_realloc(effp->obuf, sox_globals.bufsiz * sizeof(*effp->obuf));
/* Memory will be freed by sox_delete_effect() later. */
/* Possibly there was already a buffer, if this is a used effect;
it may still contain samples in that case. */
if (effp->oend > sox_globals.bufsiz) {
lsx_warn("buffer size insufficient; buffered samples were dropped");
/* can only happen if bufsize has been reduced since the last run */
effp->obeg = effp->oend = 0;
}
max_flows = max(max_flows, effp->flows);
}
if (max_flows > 1) /* might need interleave buffer */
chain->il_buf = lsx_malloc(sox_globals.bufsiz * sizeof(sox_sample_t));
else
chain->il_buf = NULL;
/* Go through the effects, and if there are samples in one of the
buffers, deinterleave it (if necessary). */
for (e = 0; e + 1 < chain->length; e++) {
sox_effect_t *effp = chain->effects[e];
if (effp->oend > effp->obeg && chain->effects[e+1]->flows > 1) {
sox_sample_t *sw = chain->il_buf; chain->il_buf = effp->obuf; effp->obuf = sw;
deinterleave(chain->effects[e+1]->flows, effp->oend - effp->obeg,
chain->il_buf, effp->obuf, sox_globals.bufsiz, effp->obeg);
}
}
e = chain->length - 1;
while (source_e < chain->length) {
#define have_imin (e > 0 && e < chain->length && chain->effects[e - 1]->oend - chain->effects[e - 1]->obeg >= chain->effects[e]->imin)
size_t osize = chain->effects[e]->oend - chain->effects[e]->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]->oend - chain->effects[e]->obeg > osize) /* False for output */
++e;
else if (e == source_e)
draining = sox_true;
else if (e < source_e)
e = source_e;
else
--e;
if (callback && callback(source_e == chain->length, client_data) != SOX_SUCCESS) {
flow_status = SOX_EOF; /* Client has requested to stop the flow. */
break;
}
}
/* If an effect's output buffer still has samples, and if it is
uninterleaved, then re-interleave it. Necessary since it might
be reused, and at that time possibly followed by an MCHAN effect. */
for (e = 0; e + 1 < chain->length; e++) {
sox_effect_t *effp = chain->effects[e];
if (effp->oend > effp->obeg && chain->effects[e+1]->flows > 1) {
sox_sample_t *sw = chain->il_buf; chain->il_buf = effp->obuf; effp->obuf = sw;
interleave(chain->effects[e+1]->flows, effp->oend - effp->obeg,
chain->il_buf, sox_globals.bufsiz, effp->obeg, effp->obuf);
}
}
free(chain->il_buf);
return flow_status;
}
sox_uint64_t sox_effects_clips(sox_effects_chain_t * chain)
{
size_t 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)
{
size_t 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 = %" PRIuPTR, 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;
size_t 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;
}
/*----------------------------- Helper functions -----------------------------*/
/* interleave() parameters:
* flows: number of samples per wide sample
* length: number of samples to copy
* [pertaining to the (non-interleaved) source buffer:]
* from: start address
* bufsiz: total size
* offset: position at which to start reading
* [pertaining to the (interleaved) destination buffer:]
* to: start address
*/
static void interleave(size_t flows, size_t length, sox_sample_t *from,
size_t bufsiz, size_t offset, sox_sample_t *to)
{
size_t i;
const size_t wide_samples = length/flows;
const size_t flow_offs = bufsiz/flows;
from += offset/flows;
for (i = 0; i < wide_samples; i++) {
sox_sample_t *inner_from = from + i;
sox_sample_t *inner_to = to + i * flows;
size_t f;
for (f = 0; f < flows; f++) {
*inner_to++ = *inner_from;
inner_from += flow_offs;
}
}
}
/* deinterleave() parameters:
* flows: number of samples per wide sample
* length: number of samples to copy
* [pertaining to the (interleaved) source buffer:]
* from: start address
* [pertaining to the (non-interleaved) destination buffer:]
* to: start address
* bufsiz: total size
* offset: position at which to start writing
*/
static void deinterleave(size_t flows, size_t length, sox_sample_t *from,
sox_sample_t *to, size_t bufsiz, size_t offset)
{
const size_t wide_samples = length/flows;
const size_t flow_offs = bufsiz/flows;
size_t f;
to += offset/flows;
for (f = 0; f < flows; f++) {
sox_sample_t *inner_to = to + f*flow_offs;
sox_sample_t *inner_from = from + f;
size_t i = wide_samples;
while (i--) {
*inner_to++ = *inner_from;
inner_from += flows;
}
}
}

@ -1,38 +0,0 @@
/* 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
*/
/* FIXME: generate this list automatically */
EFFECT(delay)
EFFECT(downsample)
EFFECT(echo)
EFFECT(echos)
EFFECT(input)
#ifdef HAVE_LADSPA_H
EFFECT(ladspa)
#endif
EFFECT(output)
EFFECT(reverb)
#ifdef HAVE_PNG
EFFECT(spectrogram)
#endif
EFFECT(speed)
#ifdef HAVE_SPEEXDSP
EFFECT(speexdsp)
#endif
EFFECT(tempo)
EFFECT(upsample)
EFFECT(vad)
EFFECT(vol)

@ -1,483 +0,0 @@
/* Implements a libSoX internal interface for implementing effects.
* All public functions & data are prefixed with lsx_ .
*
* Copyright (c) 2005-2012 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 <string.h>
#include <ctype.h>
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. The input consists of one or more
* parts, with '+' or '-' between them indicating if the sample count
* should be added to or subtracted from the previous value.
* If a part ends with a 's' then it is interpreted as a
* user-calculated # of samples.
* If a part contains ':' or '.' but no 'e' or if it ends with a 't'
* then it is treated as an amount of time. This is converted into
* seconds and fraction of seconds, then the sample rate is used to
* calculate # of samples.
* Parameter def specifies which interpretation should be the default
* for a bare number like "123". It can either be 't' or 's'.
* Returns NULL on error, pointer to next char to parse otherwise.
*/
static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def, int combine);
char const * lsx_parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def)
{
*samples = 0;
return parsesamples(rate, str0, samples, def, '+');
}
static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, int def, int combine)
{
char * str = (char *)str0;
do {
uint64_t samples_part;
sox_bool found_samples = sox_false, found_time = sox_false;
char const * end;
char const * pos;
sox_bool found_colon, found_dot, found_e;
for (;*str == ' '; ++str);
for (end = str; *end && strchr("0123456789:.ets", *end); ++end);
if (end == str)
return NULL; /* error: empty input */
pos = strchr(str, ':');
found_colon = pos && pos < end;
pos = strchr(str, '.');
found_dot = pos && pos < end;
pos = strchr(str, 'e');
found_e = pos && pos < end;
if (found_colon || (found_dot && !found_e) || *(end-1) == 't')
found_time = sox_true;
else if (*(end-1) == 's')
found_samples = sox_true;
if (found_time || (def == 't' && !found_samples)) {
int i;
if (found_e)
return NULL; /* error: e notation in time */
for (samples_part = 0, i = 0; *str != '.' && i < 3; ++i) {
char * last_str = str;
long part = strtol(str, &str, 10);
if (!i && str == last_str)
return NULL; /* error: empty first component */
samples_part += rate * part;
if (i < 2) {
if (*str != ':')
break;
++str;
samples_part *= 60;
}
}
if (*str == '.') {
char * last_str = str;
double part = strtod(str, &str);
if (str == last_str)
return NULL; /* error: empty fractional part */
samples_part += rate * part + .5;
}
if (*str == 't')
str++;
} else {
char * last_str = str;
double part = strtod(str, &str);
if (str == last_str)
return NULL; /* error: no sample count */
samples_part = part + .5;
if (*str == 's')
str++;
}
if (str != end)
return NULL; /* error: trailing characters */
switch (combine) {
case '+': *samples += samples_part; break;
case '-': *samples = samples_part <= *samples ?
*samples - samples_part : 0;
break;
}
combine = '\0';
if (*str && strchr("+-", *str))
combine = *str++;
} while (combine);
return str;
}
#if 0
#include <assert.h>
#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)
assert(!lsx_parsesamples(10000, "1e6t", &samples, 't'));
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'));
TEST("1:23+37", 1200000, 7)
TEST("12t+12s", 120012, 7)
TEST("1e6s-10", 900000, 7)
TEST("10-2:00", 0, 7)
TEST("123-45+12s+2:00-3e3s@foo", 1977012, 20)
TEST("1\0" "2", 10000, 1)
return 0;
}
#endif
/*
* lsx_parseposition
*
* Parse a string for an audio position. Similar to lsx_parsesamples
* above, but an initial '=', '+' or '-' indicates that the specified time
* is relative to the start of audio, last used position or end of audio,
* respectively. Parameter def states which of these is the default.
* Parameters latest and end are the positions to which '+' and '-' relate;
* end may be SOX_UNKNOWN_LEN, in which case "-0" is the only valid
* end-relative input and will result in a position of SOX_UNKNOWN_LEN.
* Other parameters and return value are the same as for lsx_parsesamples.
*
* A test parse that only checks for valid syntax can be done by
* specifying samples = NULL. If this passes, a later reparse of the same
* input will only fail if it is relative to the end ("-"), not "-0", and
* the end position is unknown.
*/
char const * lsx_parseposition(sox_rate_t rate, const char *str0, uint64_t *samples, uint64_t latest, uint64_t end, int def)
{
char *str = (char *)str0;
char anchor, combine;
if (!strchr("+-=", def))
return NULL; /* error: invalid default anchor */
anchor = def;
if (*str && strchr("+-=", *str))
anchor = *str++;
combine = '+';
if (strchr("+-", anchor)) {
combine = anchor;
if (*str && strchr("+-", *str))
combine = *str++;
}
if (!samples) {
/* dummy parse, syntax checking only */
uint64_t dummy = 0;
return parsesamples(0., str, &dummy, 't', '+');
}
switch (anchor) {
case '=': *samples = 0; break;
case '+': *samples = latest; break;
case '-': *samples = end; break;
}
if (anchor == '-' && end == SOX_UNKNOWN_LEN) {
/* "-0" only valid input here */
char const *l;
for (l = str; *l && strchr("0123456789:.ets+-", *l); ++l);
if (l == str+1 && *str == '0') {
/* *samples already set to SOX_UNKNOWN_LEN */
return l;
}
return NULL; /* error: end-relative position, but end unknown */
}
return parsesamples(rate, str, samples, 't', combine);
}
/* 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, sox_bool text_mode)
{
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, text_mode ? "r" : "rb"))) {
lsx_fail("couldn't open file %s: %s", filename, strerror(errno));
return NULL;
}
return file;
}
int lsx_effects_init(void)
{
init_fft_cache();
return SOX_SUCCESS;
}
int lsx_effects_quit(void)
{
clear_fft_cache();
return SOX_SUCCESS;
}

@ -1,645 +0,0 @@
/* libSoX internal DSP functions.
* All public functions & data are prefixed with lsx_ .
*
* Copyright (c) 2008,2012 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
*/
#ifdef NDEBUG /* Enable assert always. */
#undef NDEBUG /* Must undef above assert.h or other that might include it. */
#endif
#include "sox_i.h"
#include <assert.h>
#include <string.h>
/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971:*/
#if defined HAVE_OPENMP
typedef struct {
int readcount, writecount; /* initial value = 0 */
omp_lock_t mutex_1, mutex_2, mutex_3, w, r; /* initial value = 1 */
} ccrw2_t; /* Problem #2: `writers-preference' */
#define ccrw2_become_reader(p) do {\
omp_set_lock(&p.mutex_3);\
omp_set_lock(&p.r);\
omp_set_lock(&p.mutex_1);\
if (++p.readcount == 1) omp_set_lock(&p.w);\
omp_unset_lock(&p.mutex_1);\
omp_unset_lock(&p.r);\
omp_unset_lock(&p.mutex_3);\
} while (0)
#define ccrw2_cease_reading(p) do {\
omp_set_lock(&p.mutex_1);\
if (!--p.readcount) omp_unset_lock(&p.w);\
omp_unset_lock(&p.mutex_1);\
} while (0)
#define ccrw2_become_writer(p) do {\
omp_set_lock(&p.mutex_2);\
if (++p.writecount == 1) omp_set_lock(&p.r);\
omp_unset_lock(&p.mutex_2);\
omp_set_lock(&p.w);\
} while (0)
#define ccrw2_cease_writing(p) do {\
omp_unset_lock(&p.w);\
omp_set_lock(&p.mutex_2);\
if (!--p.writecount) omp_unset_lock(&p.r);\
omp_unset_lock(&p.mutex_2);\
} while (0)
#define ccrw2_init(p) do {\
omp_init_lock(&p.mutex_1);\
omp_init_lock(&p.mutex_2);\
omp_init_lock(&p.mutex_3);\
omp_init_lock(&p.w);\
omp_init_lock(&p.r);\
} while (0)
#define ccrw2_clear(p) do {\
omp_destroy_lock(&p.r);\
omp_destroy_lock(&p.w);\
omp_destroy_lock(&p.mutex_3);\
omp_destroy_lock(&p.mutex_2);\
omp_destroy_lock(&p.mutex_1);\
} while (0)
#else
#define ccrw2_become_reader(x) (void)0
#define ccrw2_cease_reading(x) (void)0
#define ccrw2_become_writer(x) (void)0
#define ccrw2_cease_writing(x) (void)0
#define ccrw2_init(x) (void)0
#define ccrw2_clear(x) (void)0
#endif /* HAVE_OPENMP */
/* Numerical Recipes cubic spline: */
void lsx_prepare_spline3(double const * x, double const * y, int n,
double start_1d, double end_1d, double * y_2d)
{
double p, qn, sig, un, * u = lsx_malloc((n - 1) * sizeof(*u));
int i;
if (start_1d == HUGE_VAL)
y_2d[0] = u[0] = 0; /* Start with natural spline or */
else { /* set the start first derivative */
y_2d[0] = -.5;
u[0] = (3 / (x[1] - x[0])) * ((y[1] - y[0]) / (x[1] - x[0]) - start_1d);
}
for (i = 1; i < n - 1; ++i) {
sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
p = sig * y_2d[i - 1] + 2;
y_2d[i] = (sig - 1) / p;
u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) -
(y[i] - y[i - 1]) / (x[i] - x[i - 1]);
u[i] = (6 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
}
if (end_1d == HUGE_VAL)
qn = un = 0; /* End with natural spline or */
else { /* set the end first derivative */
qn = .5;
un = 3 / (x[n - 1] - x[n - 2]) * (end_1d - (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]));
}
y_2d[n - 1] = (un - qn * u[n - 2]) / (qn * y_2d[n - 2] + 1);
for (i = n - 2; i >= 0; --i)
y_2d[i] = y_2d[i] * y_2d[i + 1] + u[i];
free(u);
}
double lsx_spline3(double const * x, double const * y, double const * y_2d,
int n, double x1)
{
int t, i[2] = {0, 0};
double d, a, b;
for (i[1] = n - 1; i[1] - i[0] > 1; t = (i[1] + i[0]) >> 1, i[x[t] > x1] = t);
d = x[i[1]] - x[i[0]];
assert(d != 0);
a = (x[i[1]] - x1) / d;
b = (x1 - x[i[0]]) / d;
return a * y[i[0]] + b * y[i[1]] +
((a * a * a - a) * y_2d[i[0]] + (b * b * b - b) * y_2d[i[1]]) * d * d / 6;
}
double lsx_bessel_I_0(double x)
{
double term = 1, sum = 1, last_sum, x2 = x / 2;
int i = 1;
do {
double y = x2 / i++;
last_sum = sum, sum += term *= y * y;
} while (sum != last_sum);
return sum;
}
int lsx_set_dft_length(int num_taps) /* Set to 4 x nearest power of 2 */
{ /* or half of that if danger of causing too many cache misses. */
int min = sox_globals.log2_dft_min_size;
double d = log((double)num_taps) / log(2.);
return 1 << range_limit((int)(d + 2.77), min, max((int)(d + 1.77), 17));
}
#include "fft4g.h"
static int * lsx_fft_br;
static double * lsx_fft_sc;
static int fft_len = -1;
#if defined HAVE_OPENMP
static ccrw2_t fft_cache_ccrw;
#endif
void init_fft_cache(void)
{
assert(lsx_fft_br == NULL);
assert(lsx_fft_sc == NULL);
assert(fft_len == -1);
ccrw2_init(fft_cache_ccrw);
fft_len = 0;
}
void clear_fft_cache(void)
{
assert(fft_len >= 0);
ccrw2_clear(fft_cache_ccrw);
free(lsx_fft_br);
free(lsx_fft_sc);
lsx_fft_sc = NULL;
lsx_fft_br = NULL;
fft_len = -1;
}
static sox_bool update_fft_cache(int len)
{
assert(lsx_is_power_of_2(len));
assert(fft_len >= 0);
ccrw2_become_reader(fft_cache_ccrw);
if (len > fft_len) {
ccrw2_cease_reading(fft_cache_ccrw);
ccrw2_become_writer(fft_cache_ccrw);
if (len > fft_len) {
int old_n = fft_len;
fft_len = len;
lsx_fft_br = lsx_realloc(lsx_fft_br, dft_br_len(fft_len) * sizeof(*lsx_fft_br));
lsx_fft_sc = lsx_realloc(lsx_fft_sc, dft_sc_len(fft_len) * sizeof(*lsx_fft_sc));
if (!old_n)
lsx_fft_br[0] = 0;
return sox_true;
}
ccrw2_cease_writing(fft_cache_ccrw);
ccrw2_become_reader(fft_cache_ccrw);
}
return sox_false;
}
static void done_with_fft_cache(sox_bool is_writer)
{
if (is_writer)
ccrw2_cease_writing(fft_cache_ccrw);
else ccrw2_cease_reading(fft_cache_ccrw);
}
void lsx_safe_rdft(int len, int type, double * d)
{
sox_bool is_writer = update_fft_cache(len);
lsx_rdft(len, type, d, lsx_fft_br, lsx_fft_sc);
done_with_fft_cache(is_writer);
}
void lsx_safe_cdft(int len, int type, double * d)
{
sox_bool is_writer = update_fft_cache(len);
lsx_cdft(len, type, d, lsx_fft_br, lsx_fft_sc);
done_with_fft_cache(is_writer);
}
void lsx_power_spectrum(int n, double const * in, double * out)
{
int i;
double * work = lsx_memdup(in, n * sizeof(*work));
lsx_safe_rdft(n, 1, work);
out[0] = sqr(work[0]);
for (i = 2; i < n; i += 2)
out[i >> 1] = sqr(work[i]) + sqr(work[i + 1]);
out[i >> 1] = sqr(work[1]);
free(work);
}
void lsx_power_spectrum_f(int n, float const * in, float * out)
{
int i;
double * work = lsx_malloc(n * sizeof(*work));
for (i = 0; i< n; ++i) work[i] = in[i];
lsx_safe_rdft(n, 1, work);
out[0] = sqr(work[0]);
for (i = 2; i < n; i += 2)
out[i >> 1] = sqr(work[i]) + sqr(work[i + 1]);
out[i >> 1] = sqr(work[1]);
free(work);
}
void lsx_apply_hann_f(float h[], const int num_points)
{
int i, m = num_points - 1;
for (i = 0; i < num_points; ++i) {
double x = 2 * M_PI * i / m;
h[i] *= .5 - .5 * cos(x);
}
}
void lsx_apply_hann(double h[], const int num_points)
{
int i, m = num_points - 1;
for (i = 0; i < num_points; ++i) {
double x = 2 * M_PI * i / m;
h[i] *= .5 - .5 * cos(x);
}
}
void lsx_apply_hamming(double h[], const int num_points)
{
int i, m = num_points - 1;
for (i = 0; i < num_points; ++i) {
double x = 2 * M_PI * i / m;
h[i] *= .53836 - .46164 * cos(x);
}
}
void lsx_apply_bartlett(double h[], const int num_points)
{
int i, m = num_points - 1;
for (i = 0; i < num_points; ++i) {
h[i] *= 2. / m * (m / 2. - fabs(i - m / 2.));
}
}
void lsx_apply_blackman(double h[], const int num_points, double alpha /*.16*/)
{
int i, m = num_points - 1;
for (i = 0; i < num_points; ++i) {
double x = 2 * M_PI * i / m;
h[i] *= (1 - alpha) *.5 - .5 * cos(x) + alpha * .5 * cos(2 * x);
}
}
void lsx_apply_blackman_nutall(double h[], const int num_points)
{
int i, m = num_points - 1;
for (i = 0; i < num_points; ++i) {
double x = 2 * M_PI * i / m;
h[i] *= .3635819 - .4891775 * cos(x) + .1365995 * cos(2 * x) - .0106411 * cos(3 * x);
}
}
double lsx_kaiser_beta(double att, double tr_bw)
{
if (att >= 60) {
static const double coefs[][4] = {
{-6.784957e-10,1.02856e-05,0.1087556,-0.8988365+.001},
{-6.897885e-10,1.027433e-05,0.10876,-0.8994658+.002},
{-1.000683e-09,1.030092e-05,0.1087677,-0.9007898+.003},
{-3.654474e-10,1.040631e-05,0.1087085,-0.8977766+.006},
{8.106988e-09,6.983091e-06,0.1091387,-0.9172048+.015},
{9.519571e-09,7.272678e-06,0.1090068,-0.9140768+.025},
{-5.626821e-09,1.342186e-05,0.1083999,-0.9065452+.05},
{-9.965946e-08,5.073548e-05,0.1040967,-0.7672778+.085},
{1.604808e-07,-5.856462e-05,0.1185998,-1.34824+.1},
{-1.511964e-07,6.363034e-05,0.1064627,-0.9876665+.18},
};
double realm = log(tr_bw/.0005)/log(2.);
double const * c0 = coefs[range_limit( (int)realm, 0, (int)array_length(coefs)-1)];
double const * c1 = coefs[range_limit(1+(int)realm, 0, (int)array_length(coefs)-1)];
double b0 = ((c0[0]*att + c0[1])*att + c0[2])*att + c0[3];
double b1 = ((c1[0]*att + c1[1])*att + c1[2])*att + c1[3];
return b0 + (b1 - b0) * (realm - (int)realm);
}
if (att > 50 ) return .1102 * (att - 8.7);
if (att > 20.96) return .58417 * pow(att -20.96, .4) + .07886 * (att - 20.96);
return 0;
}
void lsx_apply_kaiser(double h[], const int num_points, double beta)
{
int i, m = num_points - 1;
for (i = 0; i <= m; ++i) {
double x = 2. * i / m - 1;
h[i] *= lsx_bessel_I_0(beta * sqrt(1 - x * x)) / lsx_bessel_I_0(beta);
}
}
void lsx_apply_dolph(double h[], const int N, double att)
{
double b = cosh(acosh(pow(10., att/20)) / (N-1)), sum, t, c, norm = 0;
int i, j;
for (c = 1 - 1 / (b*b), i = (N-1) / 2; i >= 0; --i) {
for (sum = !i, b = t = j = 1; j <= i && sum != t; b *= (i-j) * (1./j), ++j)
t = sum, sum += (b *= c * (N - i - j) * (1./j));
sum /= (N - 1 - i), sum /= (norm = norm? norm : sum);
h[i] *= sum, h[N - 1 - i] *= sum;
}
}
double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho,
double scale, sox_bool dc_norm)
{
int i, m = num_taps - 1;
double * h = calloc(num_taps, sizeof(*h)), sum = 0;
double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho);
assert(Fc >= 0 && Fc <= 1);
lsx_debug("make_lpf(n=%i Fc=%.7g β=%g ρ=%g dc-norm=%i scale=%g)", num_taps, Fc, beta, rho, dc_norm, scale);
if (!h)
return NULL;
for (i = 0; i <= m / 2; ++i) {
double z = i - .5 * m, x = z * M_PI, y = z * mult1;
h[i] = x? sin(Fc * x) / x : Fc;
sum += h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult;
if (m - i != i)
sum += h[m - i] = h[i];
}
for (i = 0; dc_norm && i < num_taps; ++i) h[i] *= scale / sum;
return h;
}
void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps)
{
*beta = *beta < 0? lsx_kaiser_beta(att, tr_bw * .5 / Fc): *beta;
att = att < 60? (att - 7.95) / (2.285 * M_PI * 2) :
((.0007528358-1.577737e-05**beta)**beta+.6248022)**beta+.06186902;
*num_taps = !*num_taps? ceil(att/tr_bw + 1) : *num_taps;
}
double * lsx_design_lpf(
double Fp, /* End of pass-band */
double Fs, /* Start of stop-band */
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */
double att, /* Stop-band attenuation in dB */
int * num_taps, /* 0: value will be estimated */
int k, /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */
double beta) /* <0: value will be estimated */
{
int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1);
double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75;
Fp /= fabs(Fn), Fs /= fabs(Fn); /* Normalise to Fn = 1 */
tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */
tr_bw /= phases, Fs /= phases;
tr_bw = min(tr_bw, .5 * Fs);
Fc = Fs - tr_bw;
assert(Fc - tr_bw >= 0);
lsx_kaiser_params(att, Fc, tr_bw, &beta, num_taps);
if (!n)
*num_taps = phases > 1? *num_taps / phases * phases + phases - 1 : (*num_taps + modulo - 2) / modulo * modulo + 1;
return Fn < 0? 0 : lsx_make_lpf(
*num_taps, Fc, beta, rho, (double)phases, sox_false);
}
static double safe_log(double x)
{
assert(x >= 0);
if (x)
return log(x);
lsx_debug("log(0)");
return -26;
}
void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase)
{
double * pi_wraps, * work, phase1 = (phase > 50 ? 100 - phase : phase) / 50;
int i, work_len, begin, end, imp_peak = 0, peak = 0;
double imp_sum = 0, peak_imp_sum = 0;
double prev_angle2 = 0, cum_2pi = 0, prev_angle1 = 0, cum_1pi = 0;
for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1);
work = lsx_calloc((size_t)work_len + 2, sizeof(*work)); /* +2: (UN)PACK */
pi_wraps = lsx_malloc((((size_t)work_len + 2) / 2) * sizeof(*pi_wraps));
memcpy(work, *h, *len * sizeof(*work));
lsx_safe_rdft(work_len, 1, work); /* Cepstral: */
LSX_UNPACK(work, work_len);
for (i = 0; i <= work_len; i += 2) {
double angle = atan2(work[i + 1], work[i]);
double detect = 2 * M_PI;
double delta = angle - prev_angle2;
double adjust = detect * ((delta < -detect * .7) - (delta > detect * .7));
prev_angle2 = angle;
cum_2pi += adjust;
angle += cum_2pi;
detect = M_PI;
delta = angle - prev_angle1;
adjust = detect * ((delta < -detect * .7) - (delta > detect * .7));
prev_angle1 = angle;
cum_1pi += fabs(adjust); /* fabs for when 2pi and 1pi have combined */
pi_wraps[i >> 1] = cum_1pi;
work[i] = safe_log(sqrt(sqr(work[i]) + sqr(work[i + 1])));
work[i + 1] = 0;
}
LSX_PACK(work, work_len);
lsx_safe_rdft(work_len, -1, work);
for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len;
for (i = 1; i < work_len / 2; ++i) { /* Window to reject acausal components */
work[i] *= 2;
work[i + work_len / 2] = 0;
}
lsx_safe_rdft(work_len, 1, work);
for (i = 2; i < work_len; i += 2) /* Interpolate between linear & min phase */
work[i + 1] = phase1 * i / work_len * pi_wraps[work_len >> 1] +
(1 - phase1) * (work[i + 1] + pi_wraps[i >> 1]) - pi_wraps[i >> 1];
work[0] = exp(work[0]), work[1] = exp(work[1]);
for (i = 2; i < work_len; i += 2) {
double x = exp(work[i]);
work[i ] = x * cos(work[i + 1]);
work[i + 1] = x * sin(work[i + 1]);
}
lsx_safe_rdft(work_len, -1, work);
for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len;
/* Find peak pos. */
for (i = 0; i <= (int)(pi_wraps[work_len >> 1] / M_PI + .5); ++i) {
imp_sum += work[i];
if (fabs(imp_sum) > fabs(peak_imp_sum)) {
peak_imp_sum = imp_sum;
peak = i;
}
if (work[i] > work[imp_peak]) /* For debug check only */
imp_peak = i;
}
while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0)
--peak;
if (!phase1)
begin = 0;
else if (phase1 == 1)
begin = peak - *len / 2;
else {
begin = (.997 - (2 - phase1) * .22) * *len + .5;
end = (.997 + (0 - phase1) * .22) * *len + .5;
begin = peak - (begin & ~3);
end = peak + 1 + ((end + 3) & ~3);
*len = end - begin;
*h = lsx_realloc(*h, *len * sizeof(**h));
}
for (i = 0; i < *len; ++i) (*h)[i] =
work[(begin + (phase > 50 ? *len - 1 - i : i) + work_len) & (work_len - 1)];
*post_len = phase > 50 ? peak - begin : begin + *len - (peak + 1);
lsx_debug("nPI=%g peak-sum@%i=%g (val@%i=%g); len=%i post=%i (%g%%)",
pi_wraps[work_len >> 1] / M_PI, peak, peak_imp_sum, imp_peak,
work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1));
free(pi_wraps), free(work);
}
void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2)
{
int i, N = lsx_set_dft_length(num_points);
if (type == sox_plot_gnuplot) {
double * h1 = lsx_calloc(N, sizeof(*h1));
double * H = lsx_malloc((N / 2 + 1) * sizeof(*H));
memcpy(h1, h, sizeof(*h1) * num_points);
lsx_power_spectrum(N, h1, H);
printf(
"# gnuplot file\n"
"set title '%s'\n"
"set xlabel 'Frequency (Hz)'\n"
"set ylabel 'Amplitude Response (dB)'\n"
"set grid xtics ytics\n"
"set key off\n"
"plot '-' with lines\n"
, title);
for (i = 0; i <= N/2; ++i)
printf("%g %g\n", i * rate / N, 10 * log10(H[i]));
printf(
"e\n"
"pause -1 'Hit return to continue'\n");
free(H);
free(h1);
}
else if (type == sox_plot_octave) {
printf("%% GNU Octave file (may also work with MATLAB(R) )\nb=[");
for (i = 0; i < num_points; ++i)
printf("%24.16e\n", h[i]);
printf("];\n"
"[h,w]=freqz(b,1,%i);\n"
"plot(%g*w/pi,20*log10(h))\n"
"title('%s')\n"
"xlabel('Frequency (Hz)')\n"
"ylabel('Amplitude Response (dB)')\n"
"grid on\n"
"axis([0 %g %g %g])\n"
"disp('Hit return to continue')\n"
"pause\n"
, N, rate * .5, title, rate * .5, y1, y2);
}
else if (type == sox_plot_data) {
printf("# %s\n"
"# FIR filter\n"
"# rate: %g\n"
"# name: b\n"
"# type: matrix\n"
"# rows: %i\n"
"# columns: 1\n", title, rate, num_points);
for (i = 0; i < num_points; ++i)
printf("%24.16e\n", h[i]);
}
}
#if HAVE_FENV_H
#include <fenv.h>
#if defined FE_INVALID
#if HAVE_LRINT && LONG_MAX == 2147483647
#define lrint32 lrint
#elif defined __GNUC__ && defined __x86_64__
#define lrint32 lrint32
static __inline sox_int32_t lrint32(double input) {
sox_int32_t result;
__asm__ __volatile__("fistpl %0": "=m"(result): "t"(input): "st");
return result;
}
#endif
#endif
#endif
#if defined lrint32
#define _ dest[i] = lrint32(src[i]), ++i,
#pragma STDC FENV_ACCESS ON
static void rint_clip(sox_sample_t * const dest, double const * const src,
size_t i, size_t const n, sox_uint64_t * const clips)
{
for (; i < n; ++i) {
dest[i] = lrint32(src[i]);
if (fetestexcept(FE_INVALID)) {
feclearexcept(FE_INVALID);
dest[i] = src[i] > 0? SOX_SAMPLE_MAX : SOX_SAMPLE_MIN;
++*clips;
}
}
}
void lsx_save_samples(sox_sample_t * const dest, double const * const src,
size_t const n, sox_uint64_t * const clips)
{
size_t i;
feclearexcept(FE_INVALID);
for (i = 0; i < (n & ~7);) {
_ _ _ _ _ _ _ _ 0;
if (fetestexcept(FE_INVALID)) {
feclearexcept(FE_INVALID);
rint_clip(dest, src, i - 8, i, clips);
}
}
rint_clip(dest, src, i, n, clips);
}
void lsx_load_samples(double * const dest, sox_sample_t const * const src,
size_t const n)
{
size_t i;
for (i = 0; i < n; ++i)
dest[i] = src[i];
}
#pragma STDC FENV_ACCESS OFF
#undef _
#else
void lsx_save_samples(sox_sample_t * const dest, double const * const src,
size_t const n, sox_uint64_t * const clips)
{
SOX_SAMPLE_LOCALS;
size_t i;
for (i = 0; i < n; ++i)
dest[i] = SOX_FLOAT_64BIT_TO_SAMPLE(src[i], *clips);
}
void lsx_load_samples(double * const dest, sox_sample_t const * const src,
size_t const n)
{
size_t i;
for (i = 0; i < n; ++i)
dest[i] = SOX_SAMPLE_TO_FLOAT_64BIT(src[i],);
}
#endif

@ -1,102 +0,0 @@
/* Simple example of using SoX libraries
*
* Copyright (c) 2007-8 robs@users.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef NDEBUG /* N.B. assert used with active statements so enable always. */
#undef NDEBUG /* Must undef above assert.h or other that might include it. */
#endif
#include "sox.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
/*
* Reads input file, applies vol & flanger effects, stores in output file.
* E.g. example1 monkey.au monkey.aiff
*/
int main(int argc, char * argv[])
{
static sox_format_t * in, * out; /* input and output files */
sox_effects_chain_t * chain;
sox_effect_t * e;
char * args[10];
assert(argc == 3);
/* All libSoX applications must start by initialising the SoX library */
assert(sox_init() == SOX_SUCCESS);
/* Open the input file (with default parameters) */
assert((in = sox_open_read(argv[1], NULL, NULL, NULL)));
/* Open the output file; we must specify the output signal characteristics.
* Since we are using only simple effects, they are the same as the input
* file characteristics */
assert((out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL)));
/* Create an effects chain; some effects need to know about the input
* or output file encoding so we provide that information here */
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
/* The first effect in the effect chain must be something that can source
* samples; in this case, we use the built-in handler that inputs
* data from an audio file */
e = sox_create_effect(sox_find_effect("input"));
args[0] = (char *)in, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
/* This becomes the first `effect' in the chain */
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* Create the `vol' effect, and initialise it with the desired parameters: */
e = sox_create_effect(sox_find_effect("vol"));
args[0] = "3dB", assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
/* Add the effect to the end of the effects processing chain: */
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
args[0] = "--wet-only";
args[1] = "50"; // reverberance [0, 100] 50%
args[2] = "50"; // hf_damping [0, 100] 50%
args[3] = "100"; // room_scale [0, 100] 100%
args[4] = "100"; // stereo_depth [0, 100] 100%
args[5] = "0"; // pre_delay_ms [0, 500] 0ms
args[6] = "0"; // wet_gain_dB [-10, 10] 0dB
e = sox_create_effect(sox_find_effect("reverb"));
assert(sox_effect_options(e, 7, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* The last effect in the effect chain must be something that only consumes
* samples; in this case, we use the built-in handler that outputs
* data to an audio file */
e = sox_create_effect(sox_find_effect("output"));
args[0] = (char *)out, assert(sox_effect_options(e, 1, args) == SOX_SUCCESS);
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* Flow samples through the effects processing chain until EOF is reached */
sox_flow_effects(chain, NULL, NULL);
/* All done; tidy up: */
sox_delete_effects_chain(chain);
sox_close(out);
sox_close(in);
sox_quit();
return 0;
}

@ -1,167 +0,0 @@
/* Simple example of using SoX libraries
*
* Copyright (c) 2007-8 robs@users.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef NDEBUG /* N.B. assert used with active statements so enable always. */
#undef NDEBUG /* Must undef above assert.h or other that might include it. */
#endif
#include "sox.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
static sox_format_t * in, * out; /* input and output files */
/* The function that will be called to input samples into the effects chain.
* In this example, we get samples to process from a SoX-openned audio file.
* In a different application, they might be generated or come from a different
* part of the application. */
static int input_drain(
sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
(void)effp; /* This parameter is not needed in this example */
/* ensure that *osamp is a multiple of the number of channels. */
*osamp -= *osamp % effp->out_signal.channels;
/* Read up to *osamp samples into obuf; store the actual number read
* back to *osamp */
*osamp = sox_read(in, obuf, *osamp);
/* sox_read may return a number that is less than was requested; only if
* 0 samples is returned does it indicate that end-of-file has been reached
* or an error has occurred */
if (!*osamp && in->sox_errno)
fprintf(stderr, "%s: %s\n", in->filename, in->sox_errstr);
return *osamp? SOX_SUCCESS : SOX_EOF;
}
/* The function that will be called to output samples from the effects chain.
* In this example, we store the samples in a SoX-opened audio file.
* In a different application, they might perhaps be analysed in some way,
* or displayed as a wave-form */
static int output_flow(sox_effect_t *effp LSX_UNUSED, sox_sample_t const * ibuf,
sox_sample_t * obuf LSX_UNUSED, size_t * isamp, size_t * osamp)
{
/* Write out *isamp samples */
size_t len = sox_write(out, ibuf, *isamp);
/* len is the number of samples that were actually written out; if this is
* different to *isamp, then something has gone wrong--most often, it's
* out of disc space */
if (len != *isamp) {
fprintf(stderr, "%s: %s\n", out->filename, out->sox_errstr);
return SOX_EOF;
}
/* Outputting is the last `effect' in the effect chain so always passes
* 0 samples on to the next effect (as there isn't one!) */
*osamp = 0;
(void)effp; /* This parameter is not needed in this example */
return SOX_SUCCESS; /* All samples output successfully */
}
/* A `stub' effect handler to handle inputting samples to the effects
* chain; the only function needed for this example is `drain' */
static sox_effect_handler_t const * input_handler(void)
{
static sox_effect_handler_t handler = {
"input", NULL, SOX_EFF_MCHAN, NULL, NULL, NULL, input_drain, NULL, NULL, 0
};
return &handler;
}
/* A `stub' effect handler to handle outputting samples from the effects
* chain; the only function needed for this example is `flow' */
static sox_effect_handler_t const * output_handler(void)
{
static sox_effect_handler_t handler = {
"output", NULL, SOX_EFF_MCHAN, NULL, NULL, output_flow, NULL, NULL, NULL, 0
};
return &handler;
}
/*
* Reads input file, applies vol & flanger effects, stores in output file.
* E.g. example1 monkey.au monkey.aiff
*/
int main(int argc, char * argv[])
{
sox_effects_chain_t * chain;
sox_effect_t * e;
char * vol[] = {"3dB"};
assert(argc == 3);
/* All libSoX applications must start by initialising the SoX library */
assert(sox_init() == SOX_SUCCESS);
/* Open the input file (with default parameters) */
assert(in = sox_open_read(argv[1], NULL, NULL, NULL));
/* Open the output file; we must specify the output signal characteristics.
* Since we are using only simple effects, they are the same as the input
* file characteristics */
assert(out = sox_open_write(argv[2], &in->signal, NULL, NULL, NULL, NULL));
/* Create an effects chain; some effects need to know about the input
* or output file encoding so we provide that information here */
chain = sox_create_effects_chain(&in->encoding, &out->encoding);
/* The first effect in the effect chain must be something that can source
* samples; in this case, we have defined an input handler that inputs
* data from an audio file */
e = sox_create_effect(input_handler());
/* This becomes the first `effect' in the chain */
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* Create the `vol' effect, and initialise it with the desired parameters: */
e = sox_create_effect(sox_find_effect("vol"));
assert(sox_effect_options(e, 1, vol) == SOX_SUCCESS);
/* Add the effect to the end of the effects processing chain: */
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* Create the `flanger' effect, and initialise it with default parameters: */
e = sox_create_effect(sox_find_effect("flanger"));
assert(sox_effect_options(e, 0, NULL) == SOX_SUCCESS);
/* Add the effect to the end of the effects processing chain: */
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* The last effect in the effect chain must be something that only consumes
* samples; in this case, we have defined an output handler that outputs
* data to an audio file */
e = sox_create_effect(output_handler());
assert(sox_add_effect(chain, e, &in->signal, &in->signal) == SOX_SUCCESS);
free(e);
/* Flow samples through the effects processing chain until EOF is reached */
sox_flow_effects(chain, NULL, NULL);
/* All done; tidy up: */
sox_delete_effects_chain(chain);
sox_close(out);
sox_close(in);
sox_quit();
return 0;
}

File diff suppressed because it is too large Load Diff

@ -1,37 +0,0 @@
/* 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 FFT4G_MAX_SIZE 262144
void lsx_cdft(int, int, double *, int *, double *);
void lsx_rdft(int, int, double *, int *, double *);
void lsx_ddct(int, int, double *, int *, double *);
void lsx_ddst(int, int, double *, int *, double *);
void lsx_dfct(int, double *, double *, int *, double *);
void lsx_dfst(int, double *, double *, int *, double *);
void lsx_cdft_f(int, int, float *, int *, float *);
void lsx_rdft_f(int, int, float *, int *, float *);
void lsx_ddct_f(int, int, float *, int *, float *);
void lsx_ddst_f(int, int, float *, int *, float *);
void lsx_dfct_f(int, float *, float *, int *, float *);
void lsx_dfst_f(int, float *, float *, int *, float *);
#define dft_br_len(l) (2 + (1 << (int)(log(l / 2 + .5) / log(2.)) / 2))
#define dft_sc_len(l) (l / 2)
/* Over-allocate h by 2 to use these macros */
#define LSX_PACK(h, n) h[1] = h[n]
#define LSX_UNPACK(h, n) h[n] = h[1], h[n + 1] = h[1] = 0;

@ -1,119 +0,0 @@
/* Addressable FIFO buffer Copyright (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
*/
#ifndef fifo_included
#define fifo_included
#include <string.h>
#ifndef FIFO_SIZE_T
#define FIFO_SIZE_T size_t
#endif
typedef struct {
char * data;
size_t allocation; /* Number of bytes allocated for data. */
size_t item_size; /* Size of each item in data */
size_t begin; /* Offset of the first byte to read. */
size_t end; /* 1 + Offset of the last byte byte to read. */
} fifo_t;
#define FIFO_MIN 0x4000
UNUSED static void fifo_clear(fifo_t * f)
{
f->end = f->begin = 0;
}
UNUSED static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n)
{
n *= f->item_size;
if (f->begin == f->end)
fifo_clear(f);
while (1) {
if (f->end + n <= f->allocation) {
void *p = f->data + f->end;
f->end += n;
return p;
}
if (f->begin > FIFO_MIN) {
memmove(f->data, f->data + f->begin, f->end - f->begin);
f->end -= f->begin;
f->begin = 0;
continue;
}
f->allocation += n;
f->data = lsx_realloc(f->data, f->allocation);
}
}
UNUSED static void * fifo_write(fifo_t * f, FIFO_SIZE_T n, void const * data)
{
void * s = fifo_reserve(f, n);
if (data)
memcpy(s, data, n * f->item_size);
return s;
}
UNUSED static void fifo_trim_to(fifo_t * f, FIFO_SIZE_T n)
{
n *= f->item_size;
f->end = f->begin + n;
}
UNUSED static void fifo_trim_by(fifo_t * f, FIFO_SIZE_T n)
{
n *= f->item_size;
f->end -= n;
}
UNUSED static FIFO_SIZE_T fifo_occupancy(fifo_t * f)
{
return (f->end - f->begin) / f->item_size;
}
UNUSED static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data)
{
char * ret = f->data + f->begin;
n *= f->item_size;
if (n > (FIFO_SIZE_T)(f->end - f->begin))
return NULL;
if (data)
memcpy(data, ret, (size_t)n);
f->begin += n;
return ret;
}
#define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL)
UNUSED static void fifo_delete(fifo_t * f)
{
free(f->data);
}
UNUSED static void fifo_create(fifo_t * f, FIFO_SIZE_T item_size)
{
f->item_size = item_size;
f->allocation = FIFO_MIN;
f->data = lsx_malloc(f->allocation);
fifo_clear(f);
}
#endif

File diff suppressed because it is too large Load Diff

@ -1,130 +0,0 @@
/* libSoX static formats list (c) 2006-9 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
*/
/*-------------------------- Static format handlers --------------------------*/
// FORMAT(aifc)
// FORMAT(aiff)
// FORMAT(al)
// FORMAT(au)
// FORMAT(avr)
// FORMAT(cdr)
// FORMAT(cvsd)
// FORMAT(cvu)
// FORMAT(dat)
// FORMAT(dvms)
// FORMAT(f4)
// FORMAT(f8)
// FORMAT(gsrt)
// FORMAT(hcom)
// FORMAT(htk)
// FORMAT(ima)
// FORMAT(la)
// FORMAT(lu)
// FORMAT(maud)
// FORMAT(nul)
// FORMAT(prc)
// FORMAT(raw)
// FORMAT(s1)
// FORMAT(s2)
// FORMAT(s3)
// FORMAT(s4)
// FORMAT(sf)
// FORMAT(sln)
// FORMAT(smp)
// FORMAT(sounder)
// FORMAT(soundtool)
// FORMAT(sox)
// FORMAT(sphere)
// FORMAT(svx)
// FORMAT(txw)
// FORMAT(u1)
// FORMAT(u2)
// FORMAT(u3)
// FORMAT(u4)
// FORMAT(ul)
// FORMAT(voc)
// FORMAT(vox)
FORMAT(wav)
// FORMAT(wve)
// FORMAT(xa)
/*--------------------- Plugin or static format handlers ---------------------*/
#if defined HAVE_ALSA && (defined STATIC_ALSA || !defined HAVE_LIBLTDL)
FORMAT(alsa)
#endif
#if defined HAVE_AMRNB && (defined STATIC_AMRNB || !defined HAVE_LIBLTDL)
FORMAT(amr_nb)
#endif
#if defined HAVE_AMRWB && (defined STATIC_AMRWB || !defined HAVE_LIBLTDL)
FORMAT(amr_wb)
#endif
#if defined HAVE_AO && (defined STATIC_AO || !defined HAVE_LIBLTDL)
FORMAT(ao)
#endif
#if defined HAVE_COREAUDIO && (defined STATIC_COREAUDIO || !defined HAVE_LIBLTDL)
FORMAT(coreaudio)
#endif
#if defined HAVE_FLAC && (defined STATIC_FLAC || !defined HAVE_LIBLTDL)
FORMAT(flac)
#endif
#if defined HAVE_GSM && (defined STATIC_GSM || !defined HAVE_LIBLTDL)
FORMAT(gsm)
#endif
#if defined HAVE_LPC10 && (defined STATIC_LPC10 || !defined HAVE_LIBLTDL)
FORMAT(lpc10)
#endif
#if defined HAVE_MP3 && (defined STATIC_MP3 || !defined HAVE_LIBLTDL)
FORMAT(mp3)
#endif
#if defined HAVE_OPUS && (defined STATIC_OPUS || !defined HAVE_LIBLTDL)
FORMAT(opus)
#endif
#if defined HAVE_OSS && (defined STATIC_OSS || !defined HAVE_LIBLTDL)
FORMAT(oss)
#endif
#if defined HAVE_PULSEAUDIO && (defined STATIC_PULSEAUDIO || !defined HAVE_LIBLTDL)
FORMAT(pulseaudio)
#endif
#if defined HAVE_WAVEAUDIO && (defined STATIC_WAVEAUDIO || !defined HAVE_LIBLTDL)
FORMAT(waveaudio)
#endif
#if defined HAVE_SNDIO && (defined STATIC_SNDIO || !defined HAVE_LIBLTDL)
FORMAT(sndio)
#endif
#if defined HAVE_SNDFILE && (defined STATIC_SNDFILE || !defined HAVE_LIBLTDL)
FORMAT(sndfile)
FORMAT(caf)
FORMAT(fap)
FORMAT(mat4)
FORMAT(mat5)
FORMAT(paf)
FORMAT(pvf)
FORMAT(sd2)
FORMAT(w64)
FORMAT(xi)
#endif
#if defined HAVE_SUNAUDIO && (defined STATIC_SUNAUDIO || !defined HAVE_LIBLTDL)
FORMAT(sunau)
#endif
#if defined HAVE_OGGVORBIS && (defined STATIC_OGGVORBIS || !defined HAVE_LIBLTDL)
FORMAT(vorbis)
#endif
#if defined HAVE_WAVPACK && (defined STATIC_WAVPACK || !defined HAVE_LIBLTDL)
FORMAT(wavpack)
#endif

@ -1,545 +0,0 @@
/* 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 <string.h>
#include <sys/stat.h>
#include <stdarg.h>
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;
}
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;
}
/* 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;
}
sox_uint64_t lsx_filelength(sox_format_t * ft)
{
struct stat st;
int ret = ft->fp ? fstat(fileno((FILE*)ft->fp), &st) : 0;
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;
}
int lsx_read_fields(sox_format_t *ft, uint32_t *len, const char *spec, ...)
{
int err = SOX_SUCCESS;
va_list ap;
#define do_read(type, f, n) do { \
size_t nr; \
if (*len < n * sizeof(type)) { \
err = SOX_EOF; \
goto end; \
} \
nr = lsx_read_##f##_buf(ft, va_arg(ap, type *), r); \
if (nr != n) \
err = SOX_EOF; \
*len -= nr * sizeof(type); \
} while (0)
va_start(ap, spec);
while (*spec) {
unsigned long r = 1;
char c = *spec;
if (c >= '0' && c <= '9') {
char *next;
r = strtoul(spec, &next, 10);
spec = next;
c = *spec;
} else if (c == '*') {
r = va_arg(ap, int);
c = *++spec;
}
switch (c) {
case 'b': do_read(uint8_t, b, r); break;
case 'h': do_read(uint16_t, w, r); break;
case 'i': do_read(uint32_t, dw, r); break;
case 'q': do_read(uint64_t, qw, r); break;
case 'x': err = lsx_skipbytes(ft, r); break;
default:
lsx_fail("lsx_read_fields: invalid format character '%c'", c);
err = SOX_EOF;
break;
}
if (err)
break;
spec++;
}
end:
va_end(ap);
#undef do_read
return err;
}
/* 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;
}

File diff suppressed because it is too large Load Diff

@ -1,21 +0,0 @@
/* libSoX G711.h - include for G711 u-law and a-law conversion routines
*
* Copyright (C) 2001 Chris Bagwell
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. This software is provided "as is" without express or
* implied warranty.
*/
extern const uint8_t lsx_13linear2alaw[0x2000];
extern const int16_t lsx_alaw2linear16[256];
#define sox_13linear2alaw(sw) (lsx_13linear2alaw[((sw) + 0x1000)])
#define sox_alaw2linear16(uc) (lsx_alaw2linear16[uc])
extern const uint8_t lsx_14linear2ulaw[0x4000];
extern const int16_t lsx_ulaw2linear16[256];
#define sox_14linear2ulaw(sw) (lsx_14linear2ulaw[((sw) + 0x2000)])
#define sox_ulaw2linear16(uc) (lsx_ulaw2linear16[uc])

@ -1,349 +0,0 @@
/* lsx_getopt for SoX
*
* (c) 2011 Doug Cook 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.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
void
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 option characters */
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 argument to check (usually 1) */
LSX_PARAM_OUT lsx_getopt_t * state) /* State object to initialize */
{
assert(argc >= 0);
assert(argv != NULL);
assert(shortopts);
assert(first >= 0);
assert(first <= argc);
assert(state);
if (state)
{
if (argc < 0 ||
!argv ||
!shortopts ||
first < 0 ||
first > argc)
{
memset(state, 0, sizeof(*state));
}
else
{
state->argc = argc;
state->argv = argv;
state->shortopts =
(shortopts[0] == '+' || shortopts[0] == '-') /* Requesting GNU special behavior? */
? shortopts + 1 /* Ignore request. */
: shortopts; /* No special behavior requested. */
state->longopts = longopts;
state->flags = flags;
state->curpos = NULL;
state->ind = first;
state->opt = '?';
state->arg = NULL;
state->lngind = -1;
}
}
}
static void CheckCurPosEnd(
LSX_PARAM_INOUT lsx_getopt_t * state)
{
if (!state->curpos[0])
{
state->curpos = NULL;
state->ind++;
}
}
int
lsx_getopt(
LSX_PARAM_INOUT lsx_getopt_t * state)
{
int oerr;
assert(state);
if (!state)
{
lsx_fail("lsx_getopt called with state=NULL");
return -1;
}
assert(state->argc >= 0);
assert(state->argv != NULL);
assert(state->shortopts);
assert(state->ind >= 0);
assert(state->ind <= state->argc + 1);
oerr = 0 != (state->flags & lsx_getopt_flag_opterr);
state->opt = 0;
state->arg = NULL;
state->lngind = -1;
if (state->argc < 0 ||
!state->argv ||
!state->shortopts ||
state->ind < 0)
{ /* programmer error */
lsx_fail("lsx_getopt called with invalid information");
state->curpos = NULL;
return -1;
}
else if (
state->argc <= state->ind ||
!state->argv[state->ind] ||
state->argv[state->ind][0] != '-' ||
state->argv[state->ind][1] == '\0')
{ /* return no more options */
state->curpos = NULL;
return -1;
}
else if (state->argv[state->ind][1] == '-' && state->argv[state->ind][2] == '\0')
{ /* skip "--", return no more options. */
state->curpos = NULL;
state->ind++;
return -1;
}
else
{ /* Look for the next option */
char const * current = state->argv[state->ind];
char const * param = current + 1;
if (state->curpos == NULL ||
state->curpos <= param ||
param + strlen(param) <= state->curpos)
{ /* Start parsing a new parameter - check for a long option */
state->curpos = NULL;
if (state->longopts &&
(param[0] == '-' || (state->flags & lsx_getopt_flag_longonly)))
{
size_t nameLen;
int doubleDash = param[0] == '-';
if (doubleDash)
{
param++;
}
for (nameLen = 0; param[nameLen] && param[nameLen] != '='; nameLen++)
{}
/* For single-dash, you have to specify at least two letters in the name. */
if (doubleDash || nameLen >= 2)
{
lsx_option_t const * pCur;
lsx_option_t const * pMatch = NULL;
int matches = 0;
for (pCur = state->longopts; pCur->name; pCur++)
{
if (0 == strncmp(pCur->name, param, nameLen))
{ /* Prefix match. */
matches++;
pMatch = pCur;
if (nameLen == strlen(pCur->name))
{ /* Exact match - no ambiguity, stop search. */
matches = 1;
break;
}
}
}
if (matches == 1)
{ /* Matched. */
state->ind++;
if (param[nameLen])
{ /* --name=value */
if (pMatch->has_arg)
{ /* Required or optional arg - done. */
state->arg = param + nameLen + 1;
}
else
{ /* No arg expected. */
if (oerr)
{
lsx_warn("`%s' did not expect an argument from `%s'",
pMatch->name,
current);
}
return '?';
}
}
else if (pMatch->has_arg == lsx_option_arg_required)
{ /* Arg required. */
state->arg = state->argv[state->ind];
state->ind++;
if (state->ind > state->argc)
{
if (oerr)
{
lsx_warn("`%s' requires an argument from `%s'",
pMatch->name,
current);
}
return state->shortopts[0] == ':' ? ':' : '?'; /* Missing required value. */
}
}
state->lngind = pMatch - state->longopts;
if (pMatch->flag)
{
*pMatch->flag = pMatch->val;
return 0;
}
else
{
return pMatch->val;
}
}
else if (matches == 0 && doubleDash)
{ /* No match */
if (oerr)
{
lsx_warn("parameter not recognized from `%s'", current);
}
state->ind++;
return '?';
}
else if (matches > 1)
{ /* Ambiguous. */
if (oerr)
{
lsx_warn("parameter `%s' is ambiguous:", current);
for (pCur = state->longopts; pCur->name; pCur++)
{
if (0 == strncmp(pCur->name, param, nameLen))
{
lsx_warn("parameter `%s' could be `--%s'", current, pCur->name);
}
}
}
state->ind++;
return '?';
}
}
}
state->curpos = param;
}
state->opt = state->curpos[0];
if (state->opt == ':')
{ /* ':' is never a valid short option character */
if (oerr)
{
lsx_warn("option `%c' not recognized", state->opt);
}
state->curpos++;
CheckCurPosEnd(state);
return '?'; /* unrecognized option */
}
else
{ /* Short option needs to be matched from option list */
char const * pShortopt = strchr(state->shortopts, state->opt);
state->curpos++;
if (!pShortopt)
{ /* unrecognized option */
if (oerr)
{
lsx_warn("option `%c' not recognized", state->opt);
}
CheckCurPosEnd(state);
return '?';
}
else if (pShortopt[1] == ':' && state->curpos[0])
{ /* Return the rest of the parameter as the option's value */
state->arg = state->curpos;
state->curpos = NULL;
state->ind++;
return state->opt;
}
else if (pShortopt[1] == ':' && pShortopt[2] != ':')
{ /* Option requires a value */
state->curpos = NULL;
state->ind++;
state->arg = state->argv[state->ind];
state->ind++;
if (state->ind <= state->argc)
{ /* A value was present, so we're good. */
return state->opt;
}
else
{ /* Missing required value. */
if (oerr)
{
lsx_warn("option `%c' requires an argument",
state->opt);
}
return state->shortopts[0] == ':' ? ':' : '?';
}
}
else
{ /* Option without a value. */
CheckCurPosEnd(state);
return state->opt;
}
}
}
}
#ifdef TEST_GETOPT
#include <stdio.h>
int main(int argc, char const * argv[])
{
static int help = 0;
static lsx_option_t longopts[] =
{
{"a11", 0, 0, 101},
{"a12", 0, 0, 102},
{"a122", 0, 0, 103},
{"rarg", 1, 0, 104},
{"oarg", 2, 0, 105},
{"help", 0, &help, 106},
{0}
};
int ch;
lsx_getopt_t state;
lsx_getopt_init(argc, argv, "abc:d:v::0123456789", longopts, sox_true, 1, &state);
while (-1 != (ch = lsx_getopt(&state)))
{
printf(
"H=%d ch=%d, ind=%d opt=%d lng=%d arg=%s\n",
help,
ch,
state.ind,
state.opt,
state.lngind,
state.arg ? state.arg : "NULL");
}
return 0;
}
#endif /* TEST_GETOPT */

@ -1,365 +0,0 @@
/* libSoX ima_rw.c -- codex utilities for WAV_FORMAT_IMA_ADPCM
* Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.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 "sox_i.h"
#include "ima_rw.h"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
/*
*
* Lookup tables for IMA ADPCM format
*
*/
#define ISSTMAX 88
static const int imaStepSizeTable[ISSTMAX + 1] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
27086, 29794, 32767
};
#define imaStateAdjust(c) (((c)<4)? -1:(2*(c)-6))
/* +0 - +3, decrease step size */
/* +4 - +7, increase step size */
/* -0 - -3, decrease step size */
/* -4 - -7, increase step size */
static unsigned char imaStateAdjustTable[ISSTMAX+1][8];
void lsx_ima_init_table(void)
{
int i,j,k;
for (i=0; i<=ISSTMAX; i++) {
for (j=0; j<8; j++) {
k = i + imaStateAdjust(j);
if (k<0) k=0;
else if (k>ISSTMAX) k=ISSTMAX;
imaStateAdjustTable[i][j] = k;
}
}
}
static void ImaExpandS(
unsigned ch, /* channel number to decode, REQUIRE 0 <= ch < chans */
unsigned chans, /* total channels */
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL *obuff, /* obuff[n] will be output samples */
int n, /* samples to decode PER channel, REQUIRE n % 8 == 1 */
unsigned o_inc /* index difference between successive output samples */
)
{
const unsigned char *ip;
int i_inc;
SAMPL *op;
int i, val, state;
ip = ibuff + 4*ch; /* input pointer to 4-byte block state-initializer */
i_inc = 4*(chans-1); /* amount by which to incr ip after each 4-byte read */
val = (short)(ip[0] + (ip[1]<<8)); /* need cast for sign-extend */
state = ip[2];
if (state > ISSTMAX) {
lsx_warn("IMA_ADPCM block ch%d initial-state (%d) out of range", ch, state);
state = 0;
}
/* specs say to ignore ip[3] , but write it as 0 */
ip += 4+i_inc;
op = obuff;
*op = val; /* 1st output sample for this channel */
op += o_inc;
for (i = 1; i < n; i++) {
int step,dp,c,cm;
if (i&1) { /* 1st of pair */
cm = *ip & 0x0f;
} else {
cm = (*ip++)>>4;
if ((i&7) == 0) /* ends the 8-sample input block for this channel */
ip += i_inc; /* skip ip for next group */
}
step = imaStepSizeTable[state];
/* Update the state for the next sample */
c = cm & 0x07;
state = imaStateAdjustTable[state][c];
dp = 0;
if (c & 4) dp += step;
step = step >> 1;
if (c & 2) dp += step;
step = step >> 1;
if (c & 1) dp += step;
step = step >> 1;
dp += step;
if (c != cm) {
val -= dp;
if (val<-0x8000) val = -0x8000;
} else {
val += dp;
if (val>0x7fff) val = 0x7fff;
}
*op = val;
op += o_inc;
}
return;
}
/* lsx_ima_block_expand_i() outputs interleaved samples into one output buffer */
void lsx_ima_block_expand_i(
unsigned chans, /* total channels */
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL *obuff, /* output samples, n*chans */
int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
)
{
unsigned ch;
for (ch=0; ch<chans; ch++)
ImaExpandS(ch, chans, ibuff, obuff+ch, n, chans);
}
/* lsx_ima_block_expand_m() outputs non-interleaved samples into chan separate output buffers */
void lsx_ima_block_expand_m(
unsigned chans, /* total channels */
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL **obuffs, /* chan output sample buffers, each takes n samples */
int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
)
{
unsigned ch;
for (ch=0; ch<chans; ch++)
ImaExpandS(ch, chans, ibuff, obuffs[ch], n, 1);
}
static int ImaMashS(
unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
unsigned chans, /* total channels */
int v0, /* value to use as starting prediction0 */
const SAMPL *ibuff, /* ibuff[] is interleaved input samples */
int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
int *st, /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */
unsigned char *obuff /* output buffer[blockAlign], or NULL for no output */
)
{
const SAMPL *ip, *itop;
unsigned char *op;
int o_inc = 0; /* set 0 only to shut up gcc's 'might be uninitialized' */
int i, val;
int state;
double d2; /* long long is okay also, speed abt the same */
ip = ibuff + ch; /* point ip to 1st input sample for this channel */
itop = ibuff + n*chans;
val = *ip - v0; ip += chans;/* 1st input sample for this channel */
d2 = val*val;/* d2 will be sum of squares of errors, given input v0 and *st */
val = v0;
op = obuff; /* output pointer (or NULL) */
if (op) { /* NULL means don't output, just compute the rms error */
op += 4*ch; /* where to put this channel's 4-byte block state-initializer */
o_inc = 4*(chans-1); /* amount by which to incr op after each 4-byte written */
*op++ = val; *op++ = val>>8;
*op++ = *st; *op++ = 0; /* they could have put a mid-block state-correction here */
op += o_inc; /* _sigh_ NEVER waste a byte. It's a rule! */
}
state = *st;
for (i = 0; ip < itop; ip+=chans) {
int step,d,dp,c;
d = *ip - val; /* difference between last prediction and current sample */
step = imaStepSizeTable[state];
c = (abs(d)<<2)/step;
if (c > 7) c = 7;
/* Update the state for the next sample */
state = imaStateAdjustTable[state][c];
if (op) { /* if we want output, put it in proper place */
int cm = c;
if (d<0) cm |= 8;
if (i&1) { /* odd numbered output */
*op++ |= (cm<<4);
if (i == 7) /* ends the 8-sample output block for this channel */
op += o_inc; /* skip op for next group */
} else {
*op = cm;
}
i = (i+1) & 0x07;
}
dp = 0;
if (c & 4) dp += step;
step = step >> 1;
if (c & 2) dp += step;
step = step >> 1;
if (c & 1) dp += step;
step = step >> 1;
dp += step;
if (d<0) {
val -= dp;
if (val<-0x8000) val = -0x8000;
} else {
val += dp;
if (val>0x7fff) val = 0x7fff;
}
{
int x = *ip - val;
d2 += x*x;
}
}
d2 /= n; /* be sure it's non-negative */
*st = state;
return (int) sqrt(d2);
}
/* mash one channel... if you want to use opt>0, 9 is a reasonable value */
inline static void ImaMashChannel(
unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
unsigned chans, /* total channels */
const SAMPL *ip, /* ip[] is interleaved input samples */
int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
int *st, /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */
unsigned char *obuff, /* output buffer[blockAlign] */
int opt /* non-zero allows some cpu-intensive code to improve output */
)
{
int snext;
int s0,d0;
s0 = *st;
if (opt>0) {
int low,hi,w;
int low0,hi0;
snext = s0;
d0 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL);
w = 0;
low=hi=s0;
low0 = low-opt; if (low0<0) low0=0;
hi0 = hi+opt; if (hi0>ISSTMAX) hi0=ISSTMAX;
while (low>low0 || hi<hi0) {
if (!w && low>low0) {
int d2;
snext = --low;
d2 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL);
if (d2<d0) {
d0=d2; s0=low;
low0 = low-opt; if (low0<0) low0=0;
hi0 = low+opt; if (hi0>ISSTMAX) hi0=ISSTMAX;
}
}
if (w && hi<hi0) {
int d2;
snext = ++hi;
d2 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL);
if (d2<d0) {
d0=d2; s0=hi;
low0 = hi-opt; if (low0<0) low0=0;
hi0 = hi+opt; if (hi0>ISSTMAX) hi0=ISSTMAX;
}
}
w=1-w;
}
*st = s0;
}
ImaMashS(ch, chans, ip[ch], ip,n,st, obuff);
}
/* mash one block. if you want to use opt>0, 9 is a reasonable value */
void lsx_ima_block_mash_i(
unsigned chans, /* total channels */
const SAMPL *ip, /* ip[] is interleaved input samples */
int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
int *st, /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */
unsigned char *obuff, /* output buffer[blockAlign] */
int opt /* non-zero allows some cpu-intensive code to improve output */
)
{
unsigned ch;
for (ch=0; ch<chans; ch++)
ImaMashChannel(ch, chans, ip, n, st+ch, obuff, opt);
}
/*
* lsx_ima_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
* returns the number of samples/channel which would go
* in the dataLen, given the other parameters ...
* if input samplesPerBlock is 0, then returns the max
* samplesPerBlock which would go into a block of size blockAlign
* Yes, it is confusing.
*/
size_t lsx_ima_samples_in(
size_t dataLen,
size_t chans,
size_t blockAlign,
size_t samplesPerBlock
)
{
size_t m, n;
if (samplesPerBlock) {
n = (dataLen / blockAlign) * samplesPerBlock;
m = (dataLen % blockAlign);
} else {
n = 0;
m = blockAlign;
}
if (m >= (size_t)4*chans) {
m -= 4*chans; /* number of bytes beyond block-header */
m /= 4*chans; /* number of 4-byte blocks/channel beyond header */
m = 8*m + 1; /* samples/chan beyond header + 1 in header */
if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock;
n += m;
}
return n;
/*wSamplesPerBlock = ((wBlockAlign - 4*wChannels)/(4*wChannels))*8 + 1;*/
}
/*
* size_t lsx_ima_bytes_per_block(chans, samplesPerBlock)
* return minimum blocksize which would be required
* to encode number of chans with given samplesPerBlock
*/
size_t lsx_ima_bytes_per_block(
size_t chans,
size_t samplesPerBlock
)
{
size_t n;
/* per channel, ima has blocks of len 4, the 1st has 1st sample, the others
* up to 8 samples per block,
* so number of later blocks is (nsamp-1 + 7)/8, total blocks/chan is
* (nsamp-1+7)/8 + 1 = (nsamp+14)/8
*/
n = ((size_t)samplesPerBlock + 14)/8 * 4 * chans;
return n;
}

@ -1,84 +0,0 @@
/* libSoX ima_rw.h -- codex utilities for WAV_FORMAT_IMA_ADPCM
* Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.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 "sox.h"
#ifndef SAMPL
#define SAMPL short
#endif
/*
* call lsx_ima_init_table() before any other Ima* functions,
* to create the fast lookup tables
*/
extern void lsx_ima_init_table(void);
/* lsx_ima_block_expand_i() outputs interleaved samples into one output buffer */
extern void lsx_ima_block_expand_i(
unsigned chans, /* total channels */
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL *obuff, /* output samples, n*chans */
int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
);
/* lsx_ima_block_expand_m() outputs non-interleaved samples into chan separate output buffers */
extern void lsx_ima_block_expand_m(
unsigned chans, /* total channels */
const unsigned char *ibuff,/* input buffer[blockAlign] */
SAMPL **obuffs, /* chan output sample buffers, each takes n samples */
int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
);
/* mash one block. if you want to use opt>0, 9 is a reasonable value */
extern void lsx_ima_block_mash_i(
unsigned chans, /* total channels */
const SAMPL *ip, /* ip[] is interleaved input samples */
int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
int *st, /* input/output state[chans], REQUIRE 0 <= st[ch] <= ISSTMAX */
unsigned char *obuff, /* output buffer[blockAlign] */
int opt /* non-zero allows some cpu-intensive code to improve output */
);
/* Some helper functions for computing samples/block and blockalign */
/*
* lsx_ima_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
* returns the number of samples/channel which would go
* in the dataLen, given the other parameters ...
* if input samplesPerBlock is 0, then returns the max
* samplesPerBlock which would go into a block of size blockAlign
* Yes, it is confusing usage.
*/
extern size_t lsx_ima_samples_in(
size_t dataLen,
size_t chans,
size_t blockAlign,
size_t samplesPerBlock
);
/*
* size_t lsx_ima_bytes_per_block(chans, samplesPerBlock)
* return minimum blocksize which would be required
* to encode number of chans with given samplesPerBlock
*/
extern size_t lsx_ima_bytes_per_block(
size_t chans,
size_t samplesPerBlock
);

@ -1,58 +0,0 @@
/* libSoX effect: Input audio from a file (c) 2008 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 "sox_i.h"
typedef struct {sox_format_t * file;} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
if (argc != 2 || !(p->file = (sox_format_t *)argv[1]) || p->file->mode != 'r')
return SOX_EOF;
return SOX_SUCCESS;
}
static int drain(
sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
/* ensure that *osamp is a multiple of the number of channels. */
*osamp -= *osamp % effp->out_signal.channels;
/* Read up to *osamp samples into obuf; store the actual number read
* back to *osamp */
*osamp = sox_read(p->file, obuf, *osamp);
/* sox_read may return a number that is less than was requested; only if
* 0 samples is returned does it indicate that end-of-file has been reached
* or an error has occurred */
if (!*osamp && p->file->sox_errno)
lsx_fail("%s: %s", p->file->filename, p->file->sox_errstr);
return *osamp? SOX_SUCCESS : SOX_EOF;
}
sox_effect_handler_t const * lsx_input_effect_fn(void)
{
static sox_effect_handler_t handler = {
"input", NULL, SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_INTERNAL,
getopts, NULL, NULL, drain, NULL, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,224 +0,0 @@
/* 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 <string.h>
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 */
10 /* size_t log2_dft_min_size */
};
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)
{
sox_format_quit();
return lsx_effects_quit();
}

@ -1,116 +0,0 @@
/* libSoX internal functions that apply to both formats and effects
* All public functions & data are prefixed with lsx_ .
*
* Copyright (c) 2008 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 "sox_i.h"
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#define MKTEMP_X _O_BINARY|_O_TEMPORARY
#else
#define MKTEMP_X 0
#endif
#ifndef HAVE_MKSTEMP
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#define mkstemp(t) open(mktemp(t), MKTEMP_X|O_RDWR|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE)
#define FAKE_MKSTEMP "fake "
#else
#define FAKE_MKSTEMP
#endif
#ifdef WIN32
static int check_dir(char * buf, size_t buflen, char const * name)
{
struct stat st;
if (!name || stat(name, &st) || (st.st_mode & S_IFMT) != S_IFDIR)
{
return 0;
}
else
{
strncpy(buf, name, buflen);
buf[buflen - 1] = 0;
return strlen(name) == strlen(buf);
}
}
#endif
FILE * lsx_tmpfile(void)
{
char const * path = sox_globals.tmp_path;
/*
On Win32, tmpfile() is broken - it creates the file in the root directory of
the current drive (the user probably doesn't have permission to write there!)
instead of in a valid temporary directory (like TEMP or TMP). So if tmp_path
is null, figure out a reasonable default.
To force use of tmpfile(), set sox_globals.tmp_path = "".
*/
#ifdef WIN32
if (!path)
{
static char default_path[260] = "";
if (default_path[0] == 0
&& !check_dir(default_path, sizeof(default_path), getenv("TEMP"))
&& !check_dir(default_path, sizeof(default_path), getenv("TMP"))
#ifdef __CYGWIN__
&& !check_dir(default_path, sizeof(default_path), "/tmp")
#endif
)
{
strcpy(default_path, ".");
}
path = default_path;
}
#endif
if (path && path[0]) {
/* Emulate tmpfile (delete on close); tmp dir is given tmp_path: */
char const * const end = "/libSoX.tmp.XXXXXX";
char * name = lsx_malloc(strlen(path) + strlen(end) + 1);
int fildes;
strcpy(name, path);
strcat(name, end);
fildes = mkstemp(name);
#ifdef HAVE_UNISTD_H
lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (unlinked)", name);
unlink(name);
#else
lsx_debug(FAKE_MKSTEMP "mkstemp, name=%s (O_TEMPORARY)", name);
#endif
free(name);
return fildes == -1? NULL : fdopen(fildes, "w+b");
}
/* Use standard tmpfile (delete on close); tmp dir is undefined: */
lsx_debug("tmpfile()");
return tmpfile();
}

@ -1,59 +0,0 @@
/* libSoX effect: Output audio to a file (c) 2008 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 "sox_i.h"
typedef struct {sox_format_t * file;} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
if (argc != 2 || !(p->file = (sox_format_t *)argv[1]) || p->file->mode != 'w')
return SOX_EOF;
return SOX_SUCCESS;
}
static int flow(sox_effect_t *effp, sox_sample_t const * ibuf,
sox_sample_t * obuf, size_t * isamp, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
/* Write out *isamp samples */
size_t len = sox_write(p->file, ibuf, *isamp);
/* len is the number of samples that were actually written out; if this is
* different to *isamp, then something has gone wrong--most often, it's
* out of disc space */
if (len != *isamp) {
lsx_fail("%s: %s", p->file->filename, p->file->sox_errstr);
return SOX_EOF;
}
/* Outputting is the last `effect' in the effect chain so always passes
* 0 samples on to the next effect (as there isn't one!) */
(void)obuf, *osamp = 0;
return SOX_SUCCESS; /* All samples output successfully */
}
sox_effect_handler_t const * lsx_output_effect_fn(void)
{
static sox_effect_handler_t handler = {
"output", NULL, SOX_EFF_MCHAN | SOX_EFF_INTERNAL,
getopts, NULL, flow, NULL, NULL, NULL, sizeof(priv_t)
};
return &handler;
}

@ -1,196 +0,0 @@
/* libSoX raw I/O
*
* Copyright 1991-2007 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.
*/
#include "sox_i.h"
#include "g711.h"
typedef sox_uint16_t sox_uint14_t;
typedef sox_uint16_t sox_uint13_t;
typedef sox_int16_t sox_int14_t;
typedef sox_int16_t sox_int13_t;
#define SOX_ULAW_BYTE_TO_SAMPLE(d,clips) SOX_SIGNED_16BIT_TO_SAMPLE(sox_ulaw2linear16(d),clips)
#define SOX_ALAW_BYTE_TO_SAMPLE(d,clips) SOX_SIGNED_16BIT_TO_SAMPLE(sox_alaw2linear16(d),clips)
#define SOX_SAMPLE_TO_ULAW_BYTE(d,c) sox_14linear2ulaw(SOX_SAMPLE_TO_UNSIGNED(14,d,c) - 0x2000)
#define SOX_SAMPLE_TO_ALAW_BYTE(d,c) sox_13linear2alaw(SOX_SAMPLE_TO_UNSIGNED(13,d,c) - 0x1000)
int lsx_rawseek(sox_format_t * ft, uint64_t offset)
{
return lsx_offset_seek(ft, (off_t)ft->data_start, (off_t)offset);
}
/* Works nicely for starting read and write; lsx_rawstart{read,write}
* are #defined in sox_i.h */
int lsx_rawstart(sox_format_t * ft, sox_bool default_rate,
sox_bool default_channels, sox_bool default_length,
sox_encoding_t encoding, unsigned size)
{
if (default_rate && ft->signal.rate == 0) {
lsx_warn("`%s': sample rate not specified; trying 8kHz", ft->filename);
ft->signal.rate = 8000;
}
if (default_channels && ft->signal.channels == 0) {
lsx_warn("`%s': # channels not specified; trying mono", ft->filename);
ft->signal.channels = 1;
}
if (encoding != SOX_ENCODING_UNKNOWN) {
if (ft->mode == 'r' && ft->encoding.encoding != SOX_ENCODING_UNKNOWN &&
ft->encoding.encoding != encoding)
lsx_report("`%s': Format options overriding file-type encoding",
ft->filename);
else
ft->encoding.encoding = encoding;
}
if (size != 0) {
if (ft->mode == 'r' && ft->encoding.bits_per_sample != 0 &&
ft->encoding.bits_per_sample != size)
lsx_report("`%s': Format options overriding file-type sample-size",
ft->filename);
else
ft->encoding.bits_per_sample = size;
}
if (!ft->signal.length && ft->mode == 'r' && default_length &&
ft->encoding.bits_per_sample)
ft->signal.length =
div_bits(lsx_filelength(ft), ft->encoding.bits_per_sample);
return SOX_SUCCESS;
}
#define READ_SAMPLES_FUNC(type, size, sign, ctype, uctype, cast) \
static size_t sox_read_ ## sign ## type ## _samples( \
sox_format_t * ft, sox_sample_t *buf, size_t len) \
{ \
size_t n, nread; \
SOX_SAMPLE_LOCALS; \
ctype *data = lsx_malloc(sizeof(ctype) * len); \
LSX_USE_VAR(sox_macro_temp_sample), LSX_USE_VAR(sox_macro_temp_double); \
nread = lsx_read_ ## type ## _buf(ft, (uctype *)data, len); \
for (n = 0; n < nread; n++) \
*buf++ = cast(data[n], ft->clips); \
free(data); \
return nread; \
}
READ_SAMPLES_FUNC(b, 1, u, uint8_t, uint8_t, SOX_UNSIGNED_8BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(b, 1, s, int8_t, uint8_t, SOX_SIGNED_8BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(b, 1, ulaw, uint8_t, uint8_t, SOX_ULAW_BYTE_TO_SAMPLE)
READ_SAMPLES_FUNC(b, 1, alaw, uint8_t, uint8_t, SOX_ALAW_BYTE_TO_SAMPLE)
READ_SAMPLES_FUNC(w, 2, u, uint16_t, uint16_t, SOX_UNSIGNED_16BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(w, 2, s, int16_t, uint16_t, SOX_SIGNED_16BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(3, 3, u, sox_uint24_t, sox_uint24_t, SOX_UNSIGNED_24BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(3, 3, s, sox_int24_t, sox_uint24_t, SOX_SIGNED_24BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(dw, 4, u, uint32_t, uint32_t, SOX_UNSIGNED_32BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(dw, 4, s, int32_t, uint32_t, SOX_SIGNED_32BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(f, sizeof(float), su, float, float, SOX_FLOAT_32BIT_TO_SAMPLE)
READ_SAMPLES_FUNC(df, sizeof(double), su, double, double, SOX_FLOAT_64BIT_TO_SAMPLE)
#define WRITE_SAMPLES_FUNC(type, size, sign, ctype, uctype, cast) \
static size_t sox_write_ ## sign ## type ## _samples( \
sox_format_t * ft, sox_sample_t const * buf, size_t len) \
{ \
SOX_SAMPLE_LOCALS; \
size_t n, nwritten; \
ctype *data = lsx_malloc(sizeof(ctype) * len); \
LSX_USE_VAR(sox_macro_temp_sample), LSX_USE_VAR(sox_macro_temp_double); \
for (n = 0; n < len; n++) \
data[n] = cast(buf[n], ft->clips); \
nwritten = lsx_write_ ## type ## _buf(ft, (uctype *)data, len); \
free(data); \
return nwritten; \
}
WRITE_SAMPLES_FUNC(b, 1, u, uint8_t, uint8_t, SOX_SAMPLE_TO_UNSIGNED_8BIT)
WRITE_SAMPLES_FUNC(b, 1, s, int8_t, uint8_t, SOX_SAMPLE_TO_SIGNED_8BIT)
WRITE_SAMPLES_FUNC(b, 1, ulaw, uint8_t, uint8_t, SOX_SAMPLE_TO_ULAW_BYTE)
WRITE_SAMPLES_FUNC(b, 1, alaw, uint8_t, uint8_t, SOX_SAMPLE_TO_ALAW_BYTE)
WRITE_SAMPLES_FUNC(w, 2, u, uint16_t, uint16_t, SOX_SAMPLE_TO_UNSIGNED_16BIT)
WRITE_SAMPLES_FUNC(w, 2, s, int16_t, uint16_t, SOX_SAMPLE_TO_SIGNED_16BIT)
WRITE_SAMPLES_FUNC(3, 3, u, sox_uint24_t, sox_uint24_t, SOX_SAMPLE_TO_UNSIGNED_24BIT)
WRITE_SAMPLES_FUNC(3, 3, s, sox_int24_t, sox_uint24_t, SOX_SAMPLE_TO_SIGNED_24BIT)
WRITE_SAMPLES_FUNC(dw, 4, u, uint32_t, uint32_t, SOX_SAMPLE_TO_UNSIGNED_32BIT)
WRITE_SAMPLES_FUNC(dw, 4, s, int32_t, uint32_t, SOX_SAMPLE_TO_SIGNED_32BIT)
WRITE_SAMPLES_FUNC(f, sizeof(float), su, float, float, SOX_SAMPLE_TO_FLOAT_32BIT)
WRITE_SAMPLES_FUNC(df, sizeof (double), su, double, double, SOX_SAMPLE_TO_FLOAT_64BIT)
#define GET_FORMAT(type) \
static ft_##type##_fn * type##_fn(sox_format_t * ft) { \
switch (ft->encoding.bits_per_sample) { \
case 8: \
switch (ft->encoding.encoding) { \
case SOX_ENCODING_SIGN2: return sox_##type##_sb_samples; \
case SOX_ENCODING_UNSIGNED: return sox_##type##_ub_samples; \
case SOX_ENCODING_ULAW: return sox_##type##_ulawb_samples; \
case SOX_ENCODING_ALAW: return sox_##type##_alawb_samples; \
default: break; } \
break; \
case 16: \
switch (ft->encoding.encoding) { \
case SOX_ENCODING_SIGN2: return sox_##type##_sw_samples; \
case SOX_ENCODING_UNSIGNED: return sox_##type##_uw_samples; \
default: break; } \
break; \
case 24: \
switch (ft->encoding.encoding) { \
case SOX_ENCODING_SIGN2: return sox_##type##_s3_samples; \
case SOX_ENCODING_UNSIGNED: return sox_##type##_u3_samples; \
default: break; } \
break; \
case 32: \
switch (ft->encoding.encoding) { \
case SOX_ENCODING_SIGN2: return sox_##type##_sdw_samples; \
case SOX_ENCODING_UNSIGNED: return sox_##type##_udw_samples; \
case SOX_ENCODING_FLOAT: return sox_##type##_suf_samples; \
default: break; } \
break; \
case 64: \
switch (ft->encoding.encoding) { \
case SOX_ENCODING_FLOAT: return sox_##type##_sudf_samples; \
default: break; } \
break; \
default: \
lsx_fail_errno(ft, SOX_EFMT, "this handler does not support this data size"); \
return NULL; } \
lsx_fail_errno(ft, SOX_EFMT, "this encoding is not supported for this data size"); \
return NULL; }
typedef size_t(ft_read_fn)
(sox_format_t * ft, sox_sample_t * buf, size_t len);
GET_FORMAT(read)
/* Read a stream of some type into SoX's internal buffer format. */
size_t lsx_rawread(sox_format_t * ft, sox_sample_t * buf, size_t nsamp)
{
ft_read_fn * read_buf = read_fn(ft);
if (read_buf && nsamp)
return read_buf(ft, buf, nsamp);
return 0;
}
typedef size_t(ft_write_fn)
(sox_format_t * ft, sox_sample_t const * buf, size_t len);
GET_FORMAT(write)
/* Writes SoX's internal buffer format to buffer of various data types. */
size_t lsx_rawwrite(
sox_format_t * ft, sox_sample_t const * buf, size_t nsamp)
{
ft_write_fn * write_buf = write_fn(ft);
if (write_buf && nsamp)
return write_buf(ft, buf, nsamp);
return 0;
}

@ -1,54 +0,0 @@
/* libSoX file formats: raw (c) 2007-8 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 RAW_FORMAT0(id, size, flags, encoding) \
static int id ## _start(sox_format_t * ft) { \
return lsx_rawstart(ft, sox_true, sox_true, sox_true, SOX_ENCODING_ ## encoding, size); \
} \
const sox_format_handler_t *lsx_ ## id ## _format_fn(void); \
const sox_format_handler_t *lsx_ ## id ## _format_fn(void) { \
static unsigned const write_encodings[] = { \
SOX_ENCODING_ ## encoding, size, 0, 0}; \
static sox_format_handler_t handler = { \
SOX_LIB_VERSION_CODE, "Raw audio", \
names, flags, \
id ## _start, lsx_rawread , NULL, \
id ## _start, lsx_rawwrite, NULL, \
NULL, write_encodings, NULL, 0 \
}; \
return &handler; \
}
#define RAW_FORMAT(id, size, flags, encoding) \
static char const *names[] = {#id, NULL}; \
RAW_FORMAT0(id, size, flags, encoding)
#define RAW_FORMAT1(id, alt, size, flags, encoding) \
static char const *names[] = {#id, alt, NULL}; \
RAW_FORMAT0(id, size, flags, encoding)
#define RAW_FORMAT2(id, alt1, alt2, size, flags, encoding) \
static char const *names[] = {#id, alt1, alt2, NULL}; \
RAW_FORMAT0(id, size, flags, encoding)
#define RAW_FORMAT3(id, alt1, alt2, alt3, size, flags, encoding) \
static char const *names[] = {#id, alt1, alt2, alt3, NULL}; \
RAW_FORMAT0(id, size, flags, encoding)
#define RAW_FORMAT4(id, alt1, alt2, alt3, alt4, size, flags, encoding) \
static char const *names[] = {#id, alt1, alt2, alt3, alt4, NULL}; \
RAW_FORMAT0(id, size, flags, encoding)

@ -1,277 +0,0 @@
/* libSoX effect: stereo reverberation
* Copyright (c) 2007 robs@users.sourceforge.net
* Filter design based on freeverb by Jezar at Dreampoint.
*
* 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 "fifo.h"
#define lsx_zalloc(var, n) var = lsx_calloc(n, sizeof(*var))
#define filter_advance(p) if (--(p)->ptr < (p)->buffer) (p)->ptr += (p)->size
#define filter_delete(p) free((p)->buffer)
typedef struct {
size_t size;
float * buffer, * ptr;
float store;
} filter_t;
static float comb_process(filter_t * p, /* gcc -O2 will inline this */
float const * input, float const * feedback, float const * hf_damping)
{
float output = *p->ptr;
p->store = output + (p->store - output) * *hf_damping;
*p->ptr = *input + p->store * *feedback;
filter_advance(p);
return output;
}
static float allpass_process(filter_t * p, /* gcc -O2 will inline this */
float const * input)
{
float output = *p->ptr;
*p->ptr = *input + output * .5;
filter_advance(p);
return output - *input;
}
static const size_t /* Filter delay lengths in samples (44100Hz sample-rate) */
comb_lengths[] = {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617},
allpass_lengths[] = {225, 341, 441, 556};
#define stereo_adjust 12
typedef struct {
filter_t comb [array_length(comb_lengths)];
filter_t allpass[array_length(allpass_lengths)];
} filter_array_t;
static void filter_array_create(filter_array_t * p, double rate,
double scale, double offset)
{
size_t i;
double r = rate * (1 / 44100.); /* Compensate for actual sample-rate */
for (i = 0; i < array_length(comb_lengths); ++i, offset = -offset)
{
filter_t * pcomb = &p->comb[i];
pcomb->size = (size_t)(scale * r * (comb_lengths[i] + stereo_adjust * offset) + .5);
pcomb->ptr = lsx_zalloc(pcomb->buffer, pcomb->size);
}
for (i = 0; i < array_length(allpass_lengths); ++i, offset = -offset)
{
filter_t * pallpass = &p->allpass[i];
pallpass->size = (size_t)(r * (allpass_lengths[i] + stereo_adjust * offset) + .5);
pallpass->ptr = lsx_zalloc(pallpass->buffer, pallpass->size);
}
}
static void filter_array_process(filter_array_t * p,
size_t length, float const * input, float * output,
float const * feedback, float const * hf_damping, float const * gain)
{
while (length--) {
float out = 0, in = *input++;
size_t i = array_length(comb_lengths) - 1;
do out += comb_process(p->comb + i, &in, feedback, hf_damping);
while (i--);
i = array_length(allpass_lengths) - 1;
do out = allpass_process(p->allpass + i, &out);
while (i--);
*output++ = out * *gain;
}
}
static void filter_array_delete(filter_array_t * p)
{
size_t i;
for (i = 0; i < array_length(allpass_lengths); ++i)
filter_delete(&p->allpass[i]);
for (i = 0; i < array_length(comb_lengths); ++i)
filter_delete(&p->comb[i]);
}
typedef struct {
float feedback;
float hf_damping;
float gain;
fifo_t input_fifo;
filter_array_t chan[2];
float * out[2];
} reverb_t;
static void reverb_create(reverb_t * p, double sample_rate_Hz,
double wet_gain_dB,
double room_scale, /* % */
double reverberance, /* % */
double hf_damping, /* % */
double pre_delay_ms,
double stereo_depth,
size_t buffer_size,
float * * out)
{
size_t i, delay = pre_delay_ms / 1000 * sample_rate_Hz + .5;
double scale = room_scale / 100 * .9 + .1;
double depth = stereo_depth / 100;
double a = -1 / log(1 - /**/.3 /**/); /* Set minimum feedback */
double b = 100 / (log(1 - /**/.98/**/) * a + 1); /* Set maximum feedback */
memset(p, 0, sizeof(*p));
p->feedback = 1 - exp((reverberance - b) / (a * b));
p->hf_damping = hf_damping / 100 * .3 + .2;
p->gain = dB_to_linear(wet_gain_dB) * .015;
fifo_create(&p->input_fifo, sizeof(float));
memset(fifo_write(&p->input_fifo, delay, 0), 0, delay * sizeof(float));
for (i = 0; i <= ceil(depth); ++i) {
filter_array_create(p->chan + i, sample_rate_Hz, scale, i * depth);
out[i] = lsx_zalloc(p->out[i], buffer_size);
}
}
static void reverb_process(reverb_t * p, size_t length)
{
size_t i;
for (i = 0; i < 2 && p->out[i]; ++i)
filter_array_process(p->chan + i, length, (float *) fifo_read_ptr(&p->input_fifo), p->out[i], &p->feedback, &p->hf_damping, &p->gain);
fifo_read(&p->input_fifo, length, NULL);
}
static void reverb_delete(reverb_t * p)
{
size_t i;
for (i = 0; i < 2 && p->out[i]; ++i) {
free(p->out[i]);
filter_array_delete(p->chan + i);
}
fifo_delete(&p->input_fifo);
}
/*------------------------------- SoX Wrapper --------------------------------*/
typedef struct {
double reverberance, hf_damping, pre_delay_ms;
double stereo_depth, wet_gain_dB, room_scale;
sox_bool wet_only;
size_t ichannels, ochannels;
struct {
reverb_t reverb;
float * dry, * wet[2];
} chan[2];
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *)effp->priv;
p->reverberance = p->hf_damping = 50; /* Set non-zero defaults */
p->stereo_depth = p->room_scale = 100;
--argc, ++argv;
p->wet_only = argc && (!strcmp(*argv, "-w") || !strcmp(*argv, "--wet-only"))
&& (--argc, ++argv, sox_true);
do { /* break-able block */
NUMERIC_PARAMETER(reverberance, 0, 100)
NUMERIC_PARAMETER(hf_damping, 0, 100)
NUMERIC_PARAMETER(room_scale, 0, 100)
NUMERIC_PARAMETER(stereo_depth, 0, 100)
NUMERIC_PARAMETER(pre_delay_ms, 0, 500)
NUMERIC_PARAMETER(wet_gain_dB, -10, 10)
} while (0);
return argc ? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
size_t i;
p->ichannels = p->ochannels = 1;
effp->out_signal.rate = effp->in_signal.rate;
if (effp->in_signal.channels > 2 && p->stereo_depth) {
lsx_warn("stereo-depth not applicable with >2 channels");
p->stereo_depth = 0;
}
if (effp->in_signal.channels == 1 && p->stereo_depth)
effp->out_signal.channels = p->ochannels = 2;
else effp->out_signal.channels = effp->in_signal.channels;
if (effp->in_signal.channels == 2 && p->stereo_depth)
p->ichannels = p->ochannels = 2;
else effp->flows = effp->in_signal.channels;
for (i = 0; i < p->ichannels; ++i) reverb_create(
&p->chan[i].reverb, effp->in_signal.rate, p->wet_gain_dB, p->room_scale,
p->reverberance, p->hf_damping, p->pre_delay_ms, p->stereo_depth,
effp->global_info->global_info->bufsiz / p->ochannels, p->chan[i].wet);
if (effp->in_signal.mult)
*effp->in_signal.mult /= !p->wet_only + 2 * dB_to_linear(max(0,p->wet_gain_dB));
return SOX_SUCCESS;
}
static int 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 c, i, w, len = min(*isamp / p->ichannels, *osamp / p->ochannels);
SOX_SAMPLE_LOCALS;
*isamp = len * p->ichannels, *osamp = len * p->ochannels;
for (c = 0; c < p->ichannels; ++c)
p->chan[c].dry = fifo_write(&p->chan[c].reverb.input_fifo, len, 0);
for (i = 0; i < len; ++i) for (c = 0; c < p->ichannels; ++c)
p->chan[c].dry[i] = SOX_SAMPLE_TO_FLOAT_32BIT(*ibuf++, effp->clips);
for (c = 0; c < p->ichannels; ++c)
reverb_process(&p->chan[c].reverb, len);
if (p->ichannels == 2) for (i = 0; i < len; ++i) for (w = 0; w < 2; ++w) {
float out = (1 - p->wet_only) * p->chan[w].dry[i] +
.5 * (p->chan[0].wet[w][i] + p->chan[1].wet[w][i]);
*obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(out, effp->clips);
}
else for (i = 0; i < len; ++i) for (w = 0; w < p->ochannels; ++w) {
float out = (1 - p->wet_only) * p->chan[0].dry[i] + p->chan[0].wet[w][i];
*obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(out, effp->clips);
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
size_t i;
for (i = 0; i < p->ichannels; ++i)
reverb_delete(&p->chan[i].reverb);
return SOX_SUCCESS;
}
sox_effect_handler_t const *lsx_reverb_effect_fn(void)
{
static sox_effect_handler_t handler = {"reverb",
"[-w|--wet-only]"
" [reverberance (50%)"
" [HF-damping (50%)"
" [room-scale (100%)"
" [stereo-depth (100%)"
" [pre-delay (0ms)"
" [wet-gain (0dB)"
"]]]]]]",
SOX_EFF_MCHAN, getopts, start, flow, NULL, stop, NULL, sizeof(priv_t)
};
return &handler;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,416 +0,0 @@
/* libSoX Internal header
*
* This file is meant for libSoX internal use only
*
* Copyright 2001-2012 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#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);
char const * lsx_parseposition(sox_rate_t rate, const char *str, uint64_t *samples, uint64_t latest, uint64_t end, 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, sox_bool text_mode);
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);
#define lsx_is_power_of_2(x) !(x < 2 || (x & (x - 1)))
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, double tr_bw);
void lsx_apply_kaiser(double h[], const int num_points, double beta);
void lsx_apply_dolph(double h[], const int num_points, double att);
double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho,
double scale, sox_bool dc_norm);
void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps);
double * lsx_design_lpf(
double Fp, /* End of pass-band */
double Fs, /* Start of stop-band */
double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */
double att, /* Stop-band attenuation in dB */
int * num_taps, /* 0: value will be estimated */
int k, /* >0: number of phases; <0: num_taps ≡ 1 (mod -k) */
double beta); /* <0: value will be estimated */
void lsx_fir_to_phase(double * * h, int * len,
int * post_len, double phase0);
void lsx_plot_fir(double * h, int num_points, sox_rate_t rate, sox_plot_t type, char const * title, double y1, double y2);
void lsx_save_samples(sox_sample_t * const dest, double const * const src,
size_t const n, sox_uint64_t * const clips);
void lsx_load_samples(double * const dest, sox_sample_t const * const src,
size_t const n);
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#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_read_fields(sox_format_t *ft, uint32_t *len, const char *spec, ...);
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); Temporarily Moved to sox.h. */
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_LOCAL_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); \
} \
name = d; \
break; \
}
#define GETOPT_NUMERIC(state, ch, name, min, max) GETOPT_LOCAL_NUMERIC(state, ch, p->name, min, max)
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_LIBLTDL)
#include <ltdl.h>
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

@ -1,370 +0,0 @@
/* 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 SSP C support is enabled. */
#define ENABLE_SSP_CC 1
/* Define if you are using an external GSM library */
/* #undef EXTERNAL_GSM */
/* Define if you are using an external LPC10 library */
/* #undef EXTERNAL_LPC10 */
/* Define to 1 if you have alsa. */
/* #undef HAVE_ALSA */
/* 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 <amrwb/dec.h> header file. */
/* #undef HAVE_AMRWB_DEC_H */
/* Define to 1 if you have ao. */
/* #undef HAVE_AO */
/* Define to 1 if you have the <byteswap.h> 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 <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <fenv.h> header file. */
#define HAVE_FENV_H 1
/* Define to 1 if you have flac. */
/* #undef HAVE_FLAC */
/* Define to 1 if you have the `fmemopen' function. */
/* #undef HAVE_FMEMOPEN */
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
/* #undef HAVE_FSEEKO */
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the <glob.h> header file. */
//#define HAVE_GLOB_H 1 //TODO
/* Define to 1 if you have gsm. */
//#define HAVE_GSM 1 //TODO
/* Define to 1 if you have the <gsm/gsm.h> header file. */
/* #undef HAVE_GSM_GSM_H */
/* Define to 1 if you have the <gsm.h> header file. */
/* #undef HAVE_GSM_H */
/* Define to 1 if you have id3tag. */
/* #undef HAVE_ID3TAG */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* 1 if should enable LADSPA */
/* #undef HAVE_LADSPA_H */
/* Define to 1 if you have the <lame.h> 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 <lame/lame.h> header file. */
/* #undef HAVE_LAME_LAME_H */
/* Define to 1 if you have libltdl */
/* #undef HAVE_LIBLTDL */
/* Define to 1 if you have the <libpng/png.h> header file. */
/* #undef HAVE_LIBPNG_PNG_H */
/* Define to 1 if you have lpc10. */
//#define HAVE_LPC10 1 //TODO
/* Define to 1 if you have the <lpc10.h> header file. */
/* #undef HAVE_LPC10_H */
/* Define to 1 if you have the `lrint' function. */
#define HAVE_LRINT 1
/* Define to 1 if you have the <ltdl.h> header file. */
/* #undef HAVE_LTDL_H */
/* Define to 1 if you have the <machine/soundcard.h> header file. */
/* #undef HAVE_MACHINE_SOUNDCARD_H */
/* Define to 1 if you have the <mad.h> header file. */
/* #undef HAVE_MAD_H */
/* Define to 1 if you have magic. */
/* #undef HAVE_MAGIC */
/* Define to 1 if you have the <memory.h> 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 <opencore-amrnb/interf_dec.h> header file. */
/* #undef HAVE_OPENCORE_AMRNB_INTERF_DEC_H */
/* Define to 1 if you have the <opencore-amrwb/dec_if.h> header file. */
/* #undef HAVE_OPENCORE_AMRWB_DEC_IF_H */
/* Define to 1 if you have opus. */
//#define HAVE_OPUS 1 //TODO
/* 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 <png.h> 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. */
/* #undef HAVE_SNDFILE */
/* Define if you have libsndfile >= 1.0.18 */
#define HAVE_SNDFILE_1_0_18 1
/* Define if you have <sndfile.h> */
#define HAVE_SNDFILE_H 1
/* Define to 1 if you have sndio. */
/* #undef HAVE_SNDIO */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> 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 <sun/audioio.h> header file. */
/* #undef HAVE_SUN_AUDIOIO_H */
/* Define to 1 if you have the <sys/audioio.h> header file. */
/* #undef HAVE_SYS_AUDIOIO_H */
/* Define to 1 if you have the <sys/soundcard.h> header file. */
/* #undef HAVE_SYS_SOUNDCARD_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/timeb.h> header file. */
/* #undef HAVE_SYS_TIMEB_H */
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/utsname.h> header file. */
#define HAVE_SYS_UTSNAME_H 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <twolame.h> header file. */
/* #undef HAVE_TWOLAME_H */
/* Define to 1 if you have the <unistd.h> 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 where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* 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.2"
/* 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.2"
/* Define to 1 if you have static alsa. */
/* #undef STATIC_ALSA */
/* 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. */
/* #undef STATIC_AO */
/* Define to 1 if you have static coreaudio. */
/* #undef STATIC_COREAUDIO */
/* 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 opus. */
#define STATIC_OPUS 1
/* 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. */
/* #undef STATIC_SNDFILE */
/* 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.2"
/* 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. */
#define _FILE_OFFSET_BITS 64
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#define _LARGEFILE_SOURCE 1
/* 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

@ -1,47 +0,0 @@
#include "soxconfig.h"
#ifdef _OPENMP
#if _OPENMP >= 200805 /* OpenMP 3.0 */
#define HAVE_OPENMP 1
#endif
#if _OPENMP >= 201107 /* OpenMP 3.1 */
#define HAVE_OPENMP_3_1 1
#endif
#endif
#ifdef HAVE_OPENMP
#include <omp.h>
#else
typedef int omp_lock_t;
typedef int omp_nest_lock_t;
#define omp_set_num_threads(int) (void)0
#define omp_get_num_threads() 1
#define omp_get_max_threads() 1
#define omp_get_thread_num() 0
#define omp_get_num_procs() 1
#define omp_in_parallel() 1
#define omp_set_dynamic(int) (void)0
#define omp_get_dynamic() 0
#define omp_set_nested(int) (void)0
#define omp_get_nested() 0
#define omp_init_lock(omp_lock_t) (void)0
#define omp_destroy_lock(omp_lock_t) (void)0
#define omp_set_lock(omp_lock_t) (void)0
#define omp_unset_lock(omp_lock_t) (void)0
#define omp_test_lock(omp_lock_t) 0
#define omp_init_nest_lock(omp_nest_lock_t) (void)0
#define omp_destroy_nest_lock(omp_nest_lock_t) (void)0
#define omp_set_nest_lock(omp_nest_lock_t) (void)0
#define omp_unset_nest_lock(omp_nest_lock_t) (void)0
#define omp_test_nest_lock(omp_nest_lock_t) 0
#define omp_get_wtime() 0
#define omp_get_wtick() 0
#endif

@ -1,73 +0,0 @@
/* libSoX Effect: Adjust the audio speed (pitch and tempo together)
* (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
*
*
* Adjustment is given as the ratio of the new speed to the old speed, or as
* a number of cents (100ths of a semitone) to change. Speed change is
* actually performed by whichever resampling effect is in effect.
*/
#include "sox_i.h"
#include <string.h>
typedef struct {
double factor;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *) effp->priv;
sox_bool is_cents = sox_false;
--argc, ++argv;
if (argc == 1) {
char c, dummy;
int scanned = sscanf(*argv, "%lf%c %c", &p->factor, &c, &dummy);
if (scanned == 1 || (scanned == 2 && c == 'c')) {
is_cents |= scanned == 2;
if (is_cents || p->factor > 0) {
p->factor = is_cents? pow(2., p->factor / 1200) : p->factor;
return SOX_SUCCESS;
}
}
}
return lsx_usage(effp);
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
if (p->factor == 1)
return SOX_EFF_NULL;
effp->out_signal.rate = effp->in_signal.rate * p->factor;
effp->out_signal.length = effp->in_signal.length;
/* audio length if measured in samples doesn't change */
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_speed_effect_fn(void)
{
static sox_effect_handler_t handler = {
"speed", "factor[c]",
SOX_EFF_MCHAN | SOX_EFF_RATE | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
getopts, start, lsx_flow_copy, 0, 0, 0, sizeof(priv_t)};
return &handler;
}

@ -1,360 +0,0 @@
/* libSoX effect: change tempo (and duration) or pitch (maintain duration)
* Copyright (c) 2007,8 robs@users.sourceforge.net
* Based on ideas from Olli Parviainen's SoundTouch Library.
*
* 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 "fifo.h"
#include <math.h>
typedef struct {
/* Configuration parameters: */
size_t channels;
sox_bool quick_search; /* Whether to quick search or linear search */
double factor; /* 1 for no change, < 1 for slower, > 1 for faster. */
size_t search; /* Wide samples to search for best overlap position */
size_t segment; /* Processing segment length in wide samples */
size_t overlap; /* In wide samples */
size_t process_size; /* # input wide samples needed to process 1 segment */
/* Buffers: */
fifo_t input_fifo;
float * overlap_buf;
fifo_t output_fifo;
/* Counters: */
uint64_t samples_in;
uint64_t samples_out;
uint64_t segments_total;
uint64_t skip_total;
} tempo_t;
/* Waveform Similarity by least squares; works across multi-channels */
static float difference(const float * a, const float * b, size_t length)
{
float diff = 0;
size_t i = 0;
#define _ diff += sqr(a[i] - b[i]), ++i; /* Loop optimisation */
do {_ _ _ _ _ _ _ _} while (i < length); /* N.B. length ≡ 0 (mod 8) */
#undef _
return diff;
}
/* Find where the two segments are most alike over the overlap period. */
static size_t tempo_best_overlap_position(tempo_t * t, float const * new_win)
{
float * f = t->overlap_buf;
size_t j, best_pos, prev_best_pos = (t->search + 1) >> 1, step = 64;
size_t i = best_pos = t->quick_search? prev_best_pos : 0;
float diff, least_diff = difference(new_win + t->channels * i, f, t->channels * t->overlap);
int k = 0;
if (t->quick_search) do { /* hierarchical search */
for (k = -1; k <= 1; k += 2) for (j = 1; j < 4 || step == 64; ++j) {
i = prev_best_pos + k * j * step;
if ((int)i < 0 || i >= t->search)
break;
diff = difference(new_win + t->channels * i, f, t->channels * t->overlap);
if (diff < least_diff)
least_diff = diff, best_pos = i;
}
prev_best_pos = best_pos;
} while (step >>= 2);
else for (i = 1; i < t->search; i++) { /* linear search */
diff = difference(new_win + t->channels * i, f, t->channels * t->overlap);
if (diff < least_diff)
least_diff = diff, best_pos = i;
}
return best_pos;
}
static void tempo_overlap(
tempo_t * t, const float * in1, const float * in2, float * output)
{
size_t i, j, k = 0;
float fade_step = 1.0f / (float) t->overlap;
for (i = 0; i < t->overlap; ++i) {
float fade_in = fade_step * (float) i;
float fade_out = 1.0f - fade_in;
for (j = 0; j < t->channels; ++j, ++k)
output[k] = in1[k] * fade_out + in2[k] * fade_in;
}
}
static void tempo_process(tempo_t * t)
{
while (fifo_occupancy(&t->input_fifo) >= t->process_size) {
size_t skip, offset;
/* Copy or overlap the first bit to the output */
if (!t->segments_total) {
offset = t->search / 2;
fifo_write(&t->output_fifo, t->overlap, (float *) fifo_read_ptr(&t->input_fifo) + t->channels * offset);
} else {
offset = tempo_best_overlap_position(t, fifo_read_ptr(&t->input_fifo));
tempo_overlap(t, t->overlap_buf,
(float *) fifo_read_ptr(&t->input_fifo) + t->channels * offset,
fifo_write(&t->output_fifo, t->overlap, NULL));
}
/* Copy the middle bit to the output */
fifo_write(&t->output_fifo, t->segment - 2 * t->overlap,
(float *) fifo_read_ptr(&t->input_fifo) +
t->channels * (offset + t->overlap));
/* Copy the end bit to overlap_buf ready to be mixed with
* the beginning of the next segment. */
memcpy(t->overlap_buf,
(float *) fifo_read_ptr(&t->input_fifo) +
t->channels * (offset + t->segment - t->overlap),
t->channels * t->overlap * sizeof(*(t->overlap_buf)));
/* Advance through the input stream */
skip = t->factor * (++t->segments_total * (t->segment - t->overlap)) + 0.5;
t->skip_total += skip -= t->skip_total;
fifo_read(&t->input_fifo, skip, NULL);
}
}
static float * tempo_input(tempo_t * t, float const * samples, size_t n)
{
t->samples_in += n;
return fifo_write(&t->input_fifo, n, samples);
}
static float const * tempo_output(tempo_t * t, float * samples, size_t * n)
{
t->samples_out += *n = min(*n, fifo_occupancy(&t->output_fifo));
return fifo_read(&t->output_fifo, *n, samples);
}
/* Flush samples remaining in overlap_buf & input_fifo to the output. */
static void tempo_flush(tempo_t * t)
{
uint64_t samples_out = t->samples_in / t->factor + .5;
size_t remaining = samples_out > t->samples_out ?
(size_t)(samples_out - t->samples_out) : 0;
float * buff = lsx_calloc(128 * t->channels, sizeof(*buff));
if (remaining > 0) {
while (fifo_occupancy(&t->output_fifo) < remaining) {
tempo_input(t, buff, (size_t) 128);
tempo_process(t);
}
fifo_trim_to(&t->output_fifo, remaining);
t->samples_in = 0;
}
free(buff);
}
static void tempo_setup(tempo_t * t,
double sample_rate, sox_bool quick_search, double factor,
double segment_ms, double search_ms, double overlap_ms)
{
size_t max_skip;
t->quick_search = quick_search;
t->factor = factor;
t->segment = sample_rate * segment_ms / 1000 + .5;
t->search = sample_rate * search_ms / 1000 + .5;
t->overlap = max(sample_rate * overlap_ms / 1000 + 4.5, 16);
t->overlap &= ~7; /* Make divisible by 8 for loop optimisation */
if (t->overlap * 2 > t->segment)
t->overlap -= 8;
t->overlap_buf = lsx_malloc(t->overlap * t->channels * sizeof(*t->overlap_buf));
max_skip = ceil(factor * (t->segment - t->overlap));
t->process_size = max(max_skip + t->overlap, t->segment) + t->search;
memset(fifo_reserve(&t->input_fifo, t->search / 2), 0, (t->search / 2) * t->channels * sizeof(float));
}
static void tempo_delete(tempo_t * t)
{
free(t->overlap_buf);
fifo_delete(&t->output_fifo);
fifo_delete(&t->input_fifo);
free(t);
}
static tempo_t * tempo_create(size_t channels)
{
tempo_t * t = lsx_calloc(1, sizeof(*t));
t->channels = channels;
fifo_create(&t->input_fifo, t->channels * sizeof(float));
fifo_create(&t->output_fifo, t->channels * sizeof(float));
return t;
}
/*------------------------------- SoX Wrapper --------------------------------*/
typedef struct {
tempo_t * tempo;
sox_bool quick_search;
double factor, segment_ms, search_ms, overlap_ms;
} priv_t;
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * p = (priv_t *)effp->priv;
enum {Default, Music, Speech, Linear} profile = Default;
static const double segments_ms [] = { 82,82, 35 , 20};
static const double segments_pow[] = { 0, 1, .33 , 1};
static const double overlaps_div[] = {6.833, 7, 2.5 , 2};
static const double searches_div[] = {5.587, 6, 2.14, 2};
int c;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, "+qmls", NULL, lsx_getopt_flag_none, 1, &optstate);
p->segment_ms = p->search_ms = p->overlap_ms = HUGE_VAL;
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
case 'q': p->quick_search = sox_true; break;
case 'm': profile = Music; break;
case 's': profile = Speech; break;
case 'l': profile = Linear; p->search_ms = 0; break;
default: lsx_fail("unknown option `-%c'", optstate.opt); return lsx_usage(effp);
}
argc -= optstate.ind, argv += optstate.ind;
do { /* break-able block */
NUMERIC_PARAMETER(factor ,0.1 , 100 )
NUMERIC_PARAMETER(segment_ms , 10 , 120)
NUMERIC_PARAMETER(search_ms , 0 , 30 )
NUMERIC_PARAMETER(overlap_ms , 0 , 30 )
} while (0);
if (p->segment_ms == HUGE_VAL)
p->segment_ms = max(10, segments_ms[profile] / max(pow(p->factor, segments_pow[profile]), 1));
if (p->overlap_ms == HUGE_VAL)
p->overlap_ms = p->segment_ms / overlaps_div[profile];
if (p->search_ms == HUGE_VAL)
p->search_ms = p->segment_ms / searches_div[profile];
p->overlap_ms = min(p->overlap_ms, p->segment_ms / 2);
lsx_report("quick_search=%u factor=%g segment=%g search=%g overlap=%g",
p->quick_search, p->factor, p->segment_ms, p->search_ms, p->overlap_ms);
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
if (p->factor == 1)
return SOX_EFF_NULL;
p->tempo = tempo_create((size_t)effp->in_signal.channels);
tempo_setup(p->tempo, effp->in_signal.rate, p->quick_search, p->factor,
p->segment_ms, p->search_ms, p->overlap_ms);
effp->out_signal.length = SOX_UNKNOWN_LEN;
if (effp->in_signal.length != SOX_UNKNOWN_LEN) {
uint64_t in_length = effp->in_signal.length / effp->in_signal.channels;
uint64_t out_length = in_length / p->factor + .5;
effp->out_signal.length = out_length * effp->in_signal.channels;
}
return SOX_SUCCESS;
}
static int 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 i, odone = *osamp /= effp->in_signal.channels;
float const * s = tempo_output(p->tempo, NULL, &odone);
SOX_SAMPLE_LOCALS;
for (i = 0; i < odone * effp->in_signal.channels; ++i)
*obuf++ = SOX_FLOAT_32BIT_TO_SAMPLE(*s++, effp->clips);
if (*isamp && odone < *osamp) {
float * t = tempo_input(p->tempo, NULL, *isamp / effp->in_signal.channels);
for (i = *isamp; i; --i)
*t++ = SOX_SAMPLE_TO_FLOAT_32BIT(*ibuf++, effp->clips);
tempo_process(p->tempo);
}
else *isamp = 0;
*osamp = odone * effp->in_signal.channels;
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
{
priv_t * p = (priv_t *)effp->priv;
static size_t isamp = 0;
tempo_flush(p->tempo);
return flow(effp, 0, obuf, &isamp, osamp);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
tempo_delete(p->tempo);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_tempo_effect_fn(void)
{
static sox_effect_handler_t handler = {
"tempo", "[-q] [-m | -s | -l] factor [segment-ms [search-ms [overlap-ms]]]",
SOX_EFF_MCHAN | SOX_EFF_LENGTH,
getopts, start, flow, drain, stop, NULL, sizeof(priv_t)
};
return &handler;
}
/*---------------------------------- pitch -----------------------------------*/
static int pitch_getopts(sox_effect_t * effp, int argc, char **argv)
{
double d;
char dummy, arg[100], **argv2 = lsx_malloc(argc * sizeof(*argv2));
int result, pos = (argc > 1 && !strcmp(argv[1], "-q"))? 2 : 1;
if (argc <= pos || sscanf(argv[pos], "%lf %c", &d, &dummy) != 1)
return lsx_usage(effp);
d = pow(2., d / 1200); /* cents --> factor */
sprintf(arg, "%g", 1 / d);
memcpy(argv2, argv, argc * sizeof(*argv2));
argv2[pos] = arg;
result = getopts(effp, argc, argv2);
free(argv2);
return result;
}
static int pitch_start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
int result = start(effp);
effp->out_signal.rate = effp->in_signal.rate / p->factor;
return result;
}
sox_effect_handler_t const * lsx_pitch_effect_fn(void)
{
static sox_effect_handler_t handler;
handler = *lsx_tempo_effect_fn();
handler.name = "pitch";
handler.usage = "[-q] shift-in-cents [segment-ms [search-ms [overlap-ms]]]",
handler.getopts = pitch_getopts;
handler.start = pitch_start;
handler.flags &= ~SOX_EFF_LENGTH;
handler.flags |= SOX_EFF_RATE;
return &handler;
}

@ -1,64 +0,0 @@
/* libSoX effect: Upsample (zero stuff) (c) 2011 robs@users.sourceforge.net
*
* Sometimes filters perform better at higher sampling rates, so e.g.
* sox -r 48k input output upsample 4 filter rate 48k vol 4
*
* 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"
typedef struct {unsigned factor, pos;} priv_t;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
p->factor = 2;
--argc, ++argv;
do {NUMERIC_PARAMETER(factor, 1, 256)} while (0);
return argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *) effp->priv;
effp->out_signal.rate = effp->in_signal.rate * p->factor;
return p->factor == 1? SOX_EFF_NULL : SOX_SUCCESS;
}
static int 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 ilen = *isamp, olen = *osamp;
while (sox_true) {
for (; p->pos && olen; p->pos = (p->pos + 1) % p->factor, --olen)
*obuf++ = 0;
if (!ilen || !olen)
break;
*obuf++ = *ibuf++;
--olen, --ilen;
++p->pos;
}
*isamp -= ilen, *osamp -= olen;
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_upsample_effect_fn(void)
{
static sox_effect_handler_t handler = {"upsample", "[factor (2)]",
SOX_EFF_RATE | SOX_EFF_MODIFY, create, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
return &handler;
}

@ -1,304 +0,0 @@
/* General purpose, i.e. non SoX specific, utility functions.
* Copyright (c) 2007-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
*/
#include "sox_i.h"
#include <ctype.h>
#include <stdio.h>
int lsx_strcasecmp(const char * s1, const char * s2)
{
#if defined(HAVE_STRCASECMP)
return strcasecmp(s1, s2);
#elif defined(_MSC_VER)
return _stricmp(s1, s2);
#else
while (*s1 && (toupper(*s1) == toupper(*s2)))
s1++, s2++;
return toupper(*s1) - toupper(*s2);
#endif
}
int lsx_strncasecmp(char const * s1, char const * s2, size_t n)
{
#if defined(HAVE_STRCASECMP)
return strncasecmp(s1, s2, n);
#elif defined(_MSC_VER)
return _strnicmp(s1, s2, n);
#else
while (--n && *s1 && (toupper(*s1) == toupper(*s2)))
s1++, s2++;
return toupper(*s1) - toupper(*s2);
#endif
}
sox_bool lsx_strends(char const * str, char const * end)
{
size_t str_len = strlen(str), end_len = strlen(end);
return str_len >= end_len && !strcmp(str + str_len - end_len, end);
}
char const * lsx_find_file_extension(char const * pathname)
{
/* First, chop off any path portions of filename. This
* prevents the next search from considering that part. */
char const * result = LAST_SLASH(pathname);
if (!result)
result = pathname;
/* Now look for an filename extension */
result = strrchr(result, '.');
if (result)
++result;
return result;
}
lsx_enum_item const * lsx_find_enum_text(char const * text, lsx_enum_item const * enum_items, int flags)
{
lsx_enum_item const * result = NULL; /* Assume not found */
sox_bool sensitive = !!(flags & lsx_find_enum_item_case_sensitive);
while (enum_items->text) {
if ((!sensitive && !strcasecmp(text, enum_items->text)) ||
( sensitive && ! strcmp(text, enum_items->text)))
return enum_items; /* Found exact match */
if ((!sensitive && !strncasecmp(text, enum_items->text, strlen(text))) ||
( sensitive && ! strncmp(text, enum_items->text, strlen(text)))) {
if (result != NULL && result->value != enum_items->value)
return NULL; /* Found ambiguity */
result = enum_items; /* Found sub-string match */
}
++enum_items;
}
return result;
}
lsx_enum_item const * lsx_find_enum_value(unsigned value, lsx_enum_item const * enum_items)
{
for (;enum_items->text; ++enum_items)
if (value == enum_items->value)
return enum_items;
return NULL;
}
int lsx_enum_option(int c, char const * arg, lsx_enum_item const * items)
{
lsx_enum_item const * p = lsx_find_enum_text(arg, items, sox_false);
if (p == NULL) {
size_t len = 1;
char * set = lsx_malloc(len);
*set = 0;
for (p = items; p->text; ++p) {
set = lsx_realloc(set, len += 2 + strlen(p->text));
strcat(set, ", "); strcat(set, p->text);
}
lsx_fail("-%c: `%s' is not one of: %s.", c, arg, set + 2);
free(set);
return INT_MAX;
}
return p->value;
}
char const * lsx_sigfigs3(double number)
{
static char const symbols[] = "\0kMGTPEZY";
static char string[16][10]; /* FIXME: not thread-safe */
static unsigned n; /* ditto */
unsigned a, b, c;
sprintf(string[n = (n+1) & 15], "%#.3g", number);
switch (sscanf(string[n], "%u.%ue%u", &a, &b, &c)) {
case 2: if (b) return string[n]; /* Can fall through */
case 1: c = 2; break;
case 3: a = 100*a + b; break;
}
if (c < array_length(symbols) * 3 - 3) switch (c%3) {
case 0: sprintf(string[n], "%u.%02u%c", a/100,a%100, symbols[c/3]); break;
case 1: sprintf(string[n], "%u.%u%c" , a/10 ,a%10 , symbols[c/3]); break;
case 2: sprintf(string[n], "%u%c" , a , symbols[c/3]); break;
}
return string[n];
}
char const * lsx_sigfigs3p(double percentage)
{
static char string[16][10];
static unsigned n;
sprintf(string[n = (n+1) & 15], "%.1f%%", percentage);
if (strlen(string[n]) < 5)
sprintf(string[n], "%.2f%%", percentage);
else if (strlen(string[n]) > 5)
sprintf(string[n], "%.0f%%", percentage);
return string[n];
}
int lsx_open_dllibrary(
int show_error_on_failure,
const char* library_description,
const char* const library_names[] UNUSED,
const lsx_dlfunction_info func_infos[],
lsx_dlptr selected_funcs[],
lsx_dlhandle* pdl)
{
int failed = 0;
lsx_dlhandle dl = NULL;
/* Track enough information to give a good error message about one failure.
* Let failed symbol load override failed library open, and let failed
* library open override missing static symbols.
*/
const char* failed_libname = NULL;
const char* failed_funcname = NULL;
#ifdef HAVE_LIBLTDL
if (library_names && library_names[0])
{
const char* const* libname;
if (lt_dlinit())
{
lsx_fail(
"Unable to load %s - failed to initialize ltdl.",
library_description);
return 1;
}
for (libname = library_names; *libname; libname++)
{
lsx_debug("Attempting to open %s (%s).", library_description, *libname);
dl = lt_dlopenext(*libname);
if (dl)
{
size_t i;
lsx_debug("Opened %s (%s).", library_description, *libname);
for (i = 0; func_infos[i].name; i++)
{
union {lsx_dlptr fn; lt_ptr ptr;} func;
func.ptr = lt_dlsym(dl, func_infos[i].name);
selected_funcs[i] = func.fn ? func.fn : func_infos[i].stub_func;
if (!selected_funcs[i])
{
lt_dlclose(dl);
dl = NULL;
failed_libname = *libname;
failed_funcname = func_infos[i].name;
lsx_debug("Cannot use %s (%s) - missing function \"%s\".", library_description, failed_libname, failed_funcname);
break;
}
}
if (dl)
break;
}
else if (!failed_libname)
{
failed_libname = *libname;
}
}
if (!dl)
lt_dlexit();
}
#endif /* HAVE_LIBLTDL */
if (!dl)
{
size_t i;
for (i = 0; func_infos[i].name; i++)
{
selected_funcs[i] =
func_infos[i].static_func
? func_infos[i].static_func
: func_infos[i].stub_func;
if (!selected_funcs[i])
{
if (!failed_libname)
{
failed_libname = "static";
failed_funcname = func_infos[i].name;
}
failed = 1;
break;
}
}
}
if (failed)
{
size_t i;
for (i = 0; func_infos[i].name; i++)
selected_funcs[i] = NULL;
#ifdef HAVE_LIBLTDL
#define LTDL_MISSING ""
#else
#define LTDL_MISSING " (Dynamic library support not configured.)"
#endif /* HAVE_LIBLTDL */
if (failed_funcname)
{
if (show_error_on_failure)
lsx_fail(
"Unable to load %s (%s) function \"%s\"." LTDL_MISSING,
library_description,
failed_libname,
failed_funcname);
else
lsx_report(
"Unable to load %s (%s) function \"%s\"." LTDL_MISSING,
library_description,
failed_libname,
failed_funcname);
}
else if (failed_libname)
{
if (show_error_on_failure)
lsx_fail(
"Unable to load %s (%s)." LTDL_MISSING,
library_description,
failed_libname);
else
lsx_report(
"Unable to load %s (%s)." LTDL_MISSING,
library_description,
failed_libname);
}
else
{
if (show_error_on_failure)
lsx_fail(
"Unable to load %s - no dynamic library names selected." LTDL_MISSING,
library_description);
else
lsx_report(
"Unable to load %s - no dynamic library names selected." LTDL_MISSING,
library_description);
}
}
*pdl = dl;
return failed;
}
void lsx_close_dllibrary(
lsx_dlhandle dl UNUSED)
{
#ifdef HAVE_LIBLTDL
if (dl)
{
lt_dlclose(dl);
lt_dlexit();
}
#endif /* HAVE_LIBLTDL */
}

@ -1,184 +0,0 @@
/* 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 <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "soxconfig.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* For off_t not found in stdio.h */
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* Needs to be included before we redefine off_t. */
#endif
#include "xmalloc.h"
/*---------------------------- Portability stuff -----------------------------*/
#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 <math.h>
#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

@ -1,329 +0,0 @@
/* libSoX effect: Voice Activity Detector (c) 2009 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 "sox_i.h"
#include <string.h>
typedef struct {
double * dftBuf, * noiseSpectrum, * spectrum, * measures, meanMeas;
} chan_t;
typedef struct { /* Configuration parameters: */
double bootTime, noiseTcUp, noiseTcDown, noiseReductionAmount;
double measureFreq, measureDuration, measureTc, preTriggerTime;
double hpFilterFreq, lpFilterFreq, hpLifterFreq, lpLifterFreq;
double triggerTc, triggerLevel, searchTime, gapTime;
/* Working variables: */
sox_sample_t * samples;
unsigned dftLen_ws, samplesLen_ns, samplesIndex_ns, flushedLen_ns, gapLen;
unsigned measurePeriod_ns, measuresLen, measuresIndex;
unsigned measureTimer_ns, measureLen_ws, measureLen_ns;
unsigned spectrumStart, spectrumEnd, cepstrumStart, cepstrumEnd; /* bins */
int bootCountMax, bootCount;
double noiseTcUpMult, noiseTcDownMult;
double measureTcMult, triggerMeasTcMult;
double * spectrumWindow, * cepstrumWindow;
chan_t * channels;
} priv_t;
#define GETOPT_FREQ(optstate, c, name, min) \
case c: p->name = lsx_parse_frequency(optstate.arg, &parseIndex); \
if (p->name < min || *parseIndex) return lsx_usage(effp); \
break;
static int create(sox_effect_t * effp, int argc, char * * argv)
{
priv_t * p = (priv_t *)effp->priv;
#define opt_str "+b:N:n:r:f:m:M:h:l:H:L:T:t:s:g:p:"
int c;
lsx_getopt_t optstate;
lsx_getopt_init(argc, argv, opt_str, NULL, lsx_getopt_flag_none, 1, &optstate);
p->bootTime = .35;
p->noiseTcUp = .1;
p->noiseTcDown = .01;
p->noiseReductionAmount = 1.35;
p->measureFreq = 20;
p->measureDuration = 2 / p->measureFreq; /* 50% overlap */
p->measureTc = .4;
p->hpFilterFreq = 50;
p->lpFilterFreq = 6000;
p->hpLifterFreq = 150;
p->lpLifterFreq = 2000;
p->triggerTc = .25;
p->triggerLevel = 7;
p->searchTime = 1;
p->gapTime = .25;
while ((c = lsx_getopt(&optstate)) != -1) switch (c) {
char * parseIndex;
GETOPT_NUMERIC(optstate, 'b', bootTime , .1 , 10)
GETOPT_NUMERIC(optstate, 'N', noiseTcUp , .1 , 10)
GETOPT_NUMERIC(optstate, 'n', noiseTcDown ,.001 , .1)
GETOPT_NUMERIC(optstate, 'r', noiseReductionAmount,0 , 2)
GETOPT_NUMERIC(optstate, 'f', measureFreq , 5 , 50)
GETOPT_NUMERIC(optstate, 'm', measureDuration, .01 , 1)
GETOPT_NUMERIC(optstate, 'M', measureTc , .1 , 1)
GETOPT_FREQ( optstate, 'h', hpFilterFreq , 10)
GETOPT_FREQ( optstate, 'l', lpFilterFreq , 1000)
GETOPT_FREQ( optstate, 'H', hpLifterFreq , 10)
GETOPT_FREQ( optstate, 'L', lpLifterFreq , 1000)
GETOPT_NUMERIC(optstate, 'T', triggerTc , .01 , 1)
GETOPT_NUMERIC(optstate, 't', triggerLevel , 0 , 20)
GETOPT_NUMERIC(optstate, 's', searchTime , .1 , 4)
GETOPT_NUMERIC(optstate, 'g', gapTime , .1 , 1)
GETOPT_NUMERIC(optstate, 'p', preTriggerTime, 0 , 4)
default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
}
return optstate.ind !=argc? lsx_usage(effp) : SOX_SUCCESS;
}
static int start(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i, fixedPreTriggerLen_ns, searchPreTriggerLen_ns;
fixedPreTriggerLen_ns = p->preTriggerTime * effp->in_signal.rate + .5;
fixedPreTriggerLen_ns *= effp->in_signal.channels;
p->measureLen_ws = effp->in_signal.rate * p->measureDuration + .5;
p->measureLen_ns = p->measureLen_ws * effp->in_signal.channels;
for (p->dftLen_ws = 16; p->dftLen_ws < p->measureLen_ws; p->dftLen_ws <<= 1);
lsx_debug("dftLen_ws=%u measureLen_ws=%u", p->dftLen_ws, p->measureLen_ws);
p->measurePeriod_ns = effp->in_signal.rate / p->measureFreq + .5;
p->measurePeriod_ns *= effp->in_signal.channels;
p->measuresLen = ceil(p->searchTime * p->measureFreq);
searchPreTriggerLen_ns = p->measuresLen * p->measurePeriod_ns;
p->gapLen = p->gapTime * p->measureFreq + .5;
p->samplesLen_ns =
fixedPreTriggerLen_ns + searchPreTriggerLen_ns + p->measureLen_ns;
lsx_Calloc(p->samples, p->samplesLen_ns);
lsx_Calloc(p->channels, effp->in_signal.channels);
for (i = 0; i < effp->in_signal.channels; ++i) {
chan_t * c = &p->channels[i];
lsx_Calloc(c->dftBuf, p->dftLen_ws);
lsx_Calloc(c->spectrum, p->dftLen_ws);
lsx_Calloc(c->noiseSpectrum, p->dftLen_ws);
lsx_Calloc(c->measures, p->measuresLen);
}
lsx_Calloc(p->spectrumWindow, p->measureLen_ws);
for (i = 0; i < p->measureLen_ws; ++i)
p->spectrumWindow[i] = -2./ SOX_SAMPLE_MIN / sqrt((double)p->measureLen_ws);
lsx_apply_hann(p->spectrumWindow, (int)p->measureLen_ws);
p->spectrumStart = p->hpFilterFreq / effp->in_signal.rate * p->dftLen_ws + .5;
p->spectrumStart = max(p->spectrumStart, 1);
p->spectrumEnd = p->lpFilterFreq / effp->in_signal.rate * p->dftLen_ws + .5;
p->spectrumEnd = min(p->spectrumEnd, p->dftLen_ws / 2);
lsx_Calloc(p->cepstrumWindow, p->spectrumEnd - p->spectrumStart);
for (i = 0; i < p->spectrumEnd - p->spectrumStart; ++i)
p->cepstrumWindow[i] = 2 / sqrt((double)p->spectrumEnd - p->spectrumStart);
lsx_apply_hann(p->cepstrumWindow,(int)(p->spectrumEnd - p->spectrumStart));
p->cepstrumStart = ceil(effp->in_signal.rate * .5 / p->lpLifterFreq);
p->cepstrumEnd = floor(effp->in_signal.rate * .5 / p->hpLifterFreq);
p->cepstrumEnd = min(p->cepstrumEnd, p->dftLen_ws / 4);
if (p->cepstrumEnd <= p->cepstrumStart)
return SOX_EOF;
p->noiseTcUpMult = exp(-1 / (p->noiseTcUp * p->measureFreq));
p->noiseTcDownMult = exp(-1 / (p->noiseTcDown * p->measureFreq));
p->measureTcMult = exp(-1 / (p->measureTc * p->measureFreq));
p->triggerMeasTcMult = exp(-1 / (p->triggerTc * p->measureFreq));
p->bootCountMax = p->bootTime * p->measureFreq - .5;
p->measureTimer_ns = p->measureLen_ns;
p->bootCount = p->measuresIndex = p->flushedLen_ns = p->samplesIndex_ns = 0;
effp->out_signal.length = SOX_UNKNOWN_LEN; /* depends on input data */
return SOX_SUCCESS;
}
static int flowFlush(sox_effect_t * effp, sox_sample_t const * ibuf,
sox_sample_t * obuf, size_t * ilen, size_t * olen)
{
priv_t * p = (priv_t *)effp->priv;
size_t odone = min(p->samplesLen_ns - p->flushedLen_ns, *olen);
size_t odone1 = min(odone, p->samplesLen_ns - p->samplesIndex_ns);
memcpy(obuf, p->samples + p->samplesIndex_ns, odone1 * sizeof(*obuf));
if ((p->samplesIndex_ns += odone1) == p->samplesLen_ns) {
memcpy(obuf + odone1, p->samples, (odone - odone1) * sizeof(*obuf));
p->samplesIndex_ns = odone - odone1;
}
if ((p->flushedLen_ns += odone) == p->samplesLen_ns) {
size_t olen1 = *olen - odone;
(effp->handler.flow = lsx_flow_copy)(effp, ibuf, obuf +odone, ilen, &olen1);
odone += olen1;
}
else *ilen = 0;
*olen = odone;
return SOX_SUCCESS;
}
static double measure(
priv_t * p, chan_t * c, size_t index_ns, unsigned step_ns, int bootCount)
{
double mult, result = 0;
size_t i;
for (i = 0; i < p->measureLen_ws; ++i, index_ns = (index_ns + step_ns) % p->samplesLen_ns)
c->dftBuf[i] = p->samples[index_ns] * p->spectrumWindow[i];
memset(c->dftBuf + i, 0, (p->dftLen_ws - i) * sizeof(*c->dftBuf));
lsx_safe_rdft((int)p->dftLen_ws, 1, c->dftBuf);
memset(c->dftBuf, 0, p->spectrumStart * sizeof(*c->dftBuf));
for (i = p->spectrumStart; i < p->spectrumEnd; ++i) {
double d = sqrt(sqr(c->dftBuf[2 * i]) + sqr(c->dftBuf[2 * i + 1]));
mult = bootCount >= 0? bootCount / (1. + bootCount) : p->measureTcMult;
c->spectrum[i] = c->spectrum[i] * mult + d * (1 - mult);
d = sqr(c->spectrum[i]);
mult = bootCount >= 0? 0 :
d > c->noiseSpectrum[i]? p->noiseTcUpMult : p->noiseTcDownMult;
c->noiseSpectrum[i] = c->noiseSpectrum[i] * mult + d * (1 - mult);
d = sqrt(max(0, d - p->noiseReductionAmount * c->noiseSpectrum[i]));
c->dftBuf[i] = d * p->cepstrumWindow[i - p->spectrumStart];
}
memset(c->dftBuf + i, 0, ((p->dftLen_ws >> 1) - i) * sizeof(*c->dftBuf));
lsx_safe_rdft((int)p->dftLen_ws >> 1, 1, c->dftBuf);
for (i = p->cepstrumStart; i < p->cepstrumEnd; ++i)
result += sqr(c->dftBuf[2 * i]) + sqr(c->dftBuf[2 * i + 1]);
result = log(result / (p->cepstrumEnd - p->cepstrumStart));
return max(0, 21 + result);
}
static int flowTrigger(sox_effect_t * effp, sox_sample_t const * ibuf,
sox_sample_t * obuf, size_t * ilen, size_t * olen)
{
priv_t * p = (priv_t *)effp->priv;
sox_bool hasTriggered = sox_false;
size_t i, idone = 0, numMeasuresToFlush = 0;
while (idone < *ilen && !hasTriggered) {
p->measureTimer_ns -= effp->in_signal.channels;
for (i = 0; i < effp->in_signal.channels; ++i, ++idone) {
chan_t * c = &p->channels[i];
p->samples[p->samplesIndex_ns++] = *ibuf++;
if (!p->measureTimer_ns) {
size_t x = (p->samplesIndex_ns + p->samplesLen_ns - p->measureLen_ns) % p->samplesLen_ns;
double meas = measure(p, c, x, effp->in_signal.channels, p->bootCount);
c->measures[p->measuresIndex] = meas;
c->meanMeas = c->meanMeas * p->triggerMeasTcMult +
meas *(1 - p->triggerMeasTcMult);
if (hasTriggered |= c->meanMeas >= p->triggerLevel) {
unsigned n = p->measuresLen, k = p->measuresIndex;
unsigned j, jTrigger = n, jZero = n;
for (j = 0; j < n; ++j, k = (k + n - 1) % n)
if (c->measures[k] >= p->triggerLevel && j <= jTrigger + p->gapLen)
jZero = jTrigger = j;
else if (!c->measures[k] && jTrigger >= jZero)
jZero = j;
j = min(j, jZero);
numMeasuresToFlush = range_limit(j, numMeasuresToFlush, n);
}
lsx_debug_more("%12g %12g %u",
meas, c->meanMeas, (unsigned)numMeasuresToFlush);
}
}
if (p->samplesIndex_ns == p->samplesLen_ns)
p->samplesIndex_ns = 0;
if (!p->measureTimer_ns) {
p->measureTimer_ns = p->measurePeriod_ns;
++p->measuresIndex;
p->measuresIndex %= p->measuresLen;
if (p->bootCount >= 0)
p->bootCount = p->bootCount == p->bootCountMax? -1 : p->bootCount + 1;
}
}
if (hasTriggered) {
size_t ilen1 = *ilen - idone;
p->flushedLen_ns = (p->measuresLen - numMeasuresToFlush) * p->measurePeriod_ns;
p->samplesIndex_ns = (p->samplesIndex_ns + p->flushedLen_ns) % p->samplesLen_ns;
(effp->handler.flow = flowFlush)(effp, ibuf, obuf, &ilen1, olen);
idone += ilen1;
}
else *olen = 0;
*ilen = idone;
return SOX_SUCCESS;
}
static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * olen)
{
size_t ilen = 0;
return effp->handler.flow(effp, NULL, obuf, &ilen, olen);
}
static int stop(sox_effect_t * effp)
{
priv_t * p = (priv_t *)effp->priv;
unsigned i;
for (i = 0; i < effp->in_signal.channels; ++i) {
chan_t * c = &p->channels[i];
free(c->measures);
free(c->noiseSpectrum);
free(c->spectrum);
free(c->dftBuf);
}
free(p->channels);
free(p->cepstrumWindow);
free(p->spectrumWindow);
free(p->samples);
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_vad_effect_fn(void)
{
static sox_effect_handler_t handler = {"vad", NULL,
SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
create, start, flowTrigger, drain, stop, NULL, sizeof(priv_t)
};
static char const * lines[] = {
"[options]",
"\t-t trigger-level (7)",
"\t-T trigger-time-constant (0.25 s)",
"\t-s search-time (1 s)",
"\t-g allowed-gap (0.25 s)",
"\t-p pre-trigger-time (0 s)",
"Advanced options:",
"\t-b noise-est-boot-time (0.35 s)",
"\t-N noise-est-time-constant-up (0.1 s)",
"\t-n noise-est-time-constant-down (0.01 s)",
"\t-r noise-reduction-amount (1.35)",
"\t-f measurement-frequency (20 Hz)",
"\t-m measurement-duration (0.1 s)",
"\t-M measurement-time-constant (0.4 s)",
"\t-h high-pass-filter (50 Hz)",
"\t-l low-pass-filter (6000 Hz)",
"\t-H high-pass-lifter (150 Hz)",
"\t-L low-pass-lifter (2000 Hz)",
};
static char * usage;
handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));
return &handler;
}

@ -1,184 +0,0 @@
/* Copyright (c) 20/03/2000 Fabien COELHO <fabien@coelho.net>
* Copyright (c) 2000-2007 SoX contributors
*
* SoX vol effect; change volume with basic linear amplitude formula.
* Beware of saturations! Clipping is checked and reported.
*
* FIXME: deprecate or remove the limiter in favour of compand.
*/
#define vol_usage \
"GAIN [TYPE [LIMITERGAIN]]\n" \
"\t(default TYPE=amplitude: 1 is constant, < 0 change phase;\n" \
"\tTYPE=power 1 is constant; TYPE=dB: 0 is constant, +6 doubles ampl.)\n" \
"\tThe peak limiter has a gain much less than 1 (e.g. 0.05 or 0.02) and\n" \
"\tis only used on peaks (to prevent clipping); default is no limiter."
#include "sox_i.h"
typedef struct {
double gain; /* amplitude gain. */
sox_bool uselimiter;
double limiterthreshhold;
double limitergain;
uint64_t limited; /* number of limited values to report. */
uint64_t totalprocessed;
} priv_t;
enum {vol_amplitude, vol_dB, vol_power};
static lsx_enum_item const vol_types[] = {
LSX_ENUM_ITEM(vol_,amplitude)
LSX_ENUM_ITEM(vol_,dB)
LSX_ENUM_ITEM(vol_,power)
{0, 0}};
/*
* Process options: gain (float) type (amplitude, power, dB)
*/
static int getopts(sox_effect_t * effp, int argc, char **argv)
{
priv_t * vol = (priv_t *) effp->priv;
char type_string[11];
char * type_ptr = type_string;
char dummy; /* To check for extraneous chars. */
sox_bool have_type;
--argc, ++argv;
vol->gain = 1; /* Default is no change. */
vol->uselimiter = sox_false; /* Default is no limiter. */
/* Get the vol, and the type if it's in the same arg. */
if (!argc || (have_type = sscanf(argv[0], "%lf %10s %c", &vol->gain, type_string, &dummy) - 1) > 1)
return lsx_usage(effp);
++argv, --argc;
/* No type yet? Get it from the next arg: */
if (!have_type && argc) {
have_type = sox_true;
type_ptr = *argv;
++argv, --argc;
}
if (have_type) {
lsx_enum_item const * p = lsx_find_enum_text(type_ptr, vol_types, 0);
if (!p)
return lsx_usage(effp);
switch (p->value) {
case vol_dB: vol->gain = dB_to_linear(vol->gain); break;
case vol_power: /* power to amplitude, keep phase change */
vol->gain = vol->gain > 0 ? sqrt(vol->gain) : -sqrt(-vol->gain);
break;
}
}
if (argc) {
if (fabs(vol->gain) < 1 || sscanf(*argv, "%lf %c", &vol->limitergain, &dummy) != 1 || vol->limitergain <= 0 || vol->limitergain >= 1)
return lsx_usage(effp);
vol->uselimiter = sox_true;
/* The following equation is derived so that there is no
* discontinuity in output amplitudes */
/* and a SOX_SAMPLE_MAX input always maps to a SOX_SAMPLE_MAX output
* when the limiter is activated. */
/* (NOTE: There **WILL** be a discontinuity in the slope
* of the output amplitudes when using the limiter.) */
vol->limiterthreshhold = SOX_SAMPLE_MAX * (1.0 - vol->limitergain) / (fabs(vol->gain) - vol->limitergain);
}
lsx_debug("mult=%g limit=%g", vol->gain, vol->limitergain);
return SOX_SUCCESS;
}
/*
* Start processing
*/
static int start(sox_effect_t * effp)
{
priv_t * vol = (priv_t *) effp->priv;
if (vol->gain == 1)
return SOX_EFF_NULL;
vol->limited = 0;
vol->totalprocessed = 0;
return SOX_SUCCESS;
}
/*
* Process data.
*/
static int flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
size_t *isamp, size_t *osamp)
{
priv_t * vol = (priv_t *) effp->priv;
register double gain = vol->gain;
register double limiterthreshhold = vol->limiterthreshhold;
register double sample;
register size_t len;
len = min(*osamp, *isamp);
/* report back dealt with amount. */
*isamp = len; *osamp = len;
if (vol->uselimiter)
{
vol->totalprocessed += len;
for (;len>0; len--)
{
sample = *ibuf++;
if (sample > limiterthreshhold)
{
sample = (SOX_SAMPLE_MAX - vol->limitergain * (SOX_SAMPLE_MAX - sample));
vol->limited++;
}
else if (sample < -limiterthreshhold)
{
sample = -(SOX_SAMPLE_MAX - vol->limitergain * (SOX_SAMPLE_MAX + sample));
/* FIXME: MIN is (-MAX)-1 so need to make sure we
* don't go over that. Probably could do this
* check inside the above equation but I didn't
* think it thru.
*/
if (sample < SOX_SAMPLE_MIN)
sample = SOX_SAMPLE_MIN;
vol->limited++;
} else
sample = gain * sample;
SOX_SAMPLE_CLIP_COUNT(sample, effp->clips);
*obuf++ = sample;
}
}
else
{
/* quite basic, with clipping */
for (;len>0; len--)
{
sample = gain * *ibuf++;
SOX_SAMPLE_CLIP_COUNT(sample, effp->clips);
*obuf++ = sample;
}
}
return SOX_SUCCESS;
}
static int stop(sox_effect_t * effp)
{
priv_t * vol = (priv_t *) effp->priv;
if (vol->limited) {
lsx_warn("limited %" PRIu64 " values (%d percent).",
vol->limited, (int) (vol->limited * 100.0 / vol->totalprocessed));
}
return SOX_SUCCESS;
}
sox_effect_handler_t const * lsx_vol_effect_fn(void)
{
static sox_effect_handler_t handler = {
"vol", vol_usage, SOX_EFF_MCHAN | SOX_EFF_GAIN, getopts, start, flow, 0, stop, 0, sizeof(priv_t)
};
return &handler;
}

File diff suppressed because it is too large Load Diff

@ -1,73 +0,0 @@
/* 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 <stdlib.h>
static void *lsx_checkptr(void *ptr)
{
if (!ptr) {
lsx_fail("out of memory");
exit(2);
}
return ptr;
}
/* 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;
}
return lsx_checkptr(realloc(ptr, newsize));
}
void *lsx_malloc(size_t size)
{
return lsx_checkptr(malloc(size + !size));
}
void *lsx_calloc(size_t n, size_t size)
{
return lsx_checkptr(calloc(n + !n, size + !size));
}
void *lsx_realloc_array(void *p, size_t n, size_t size)
{
if (n > (size_t)-1 / size) {
lsx_fail("malloc size overflow");
exit(2);
}
return lsx_realloc(p, n * size);
}
char *lsx_strdup(const char *s)
{
return lsx_checkptr(strdup(s));
}

@ -1,36 +0,0 @@
/* 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 <stddef.h>
#include <string.h>
LSX_RETURN_VALID void *lsx_malloc(size_t size);
LSX_RETURN_VALID void *lsx_calloc(size_t n, size_t size);
LSX_RETURN_VALID void *lsx_realloc_array(void *p, size_t n, size_t size);
LSX_RETURN_VALID char *lsx_strdup(const char *s);
#define lsx_Calloc(v,n) v = lsx_calloc(n,sizeof(*(v)))
#define lsx_memdup(p,s) ((p)? memcpy(lsx_malloc(s), p, s) : NULL)
#define lsx_valloc(v,n) v = lsx_realloc_array(NULL, n, sizeof(*(v)))
#define lsx_revalloc(v,n) v = lsx_realloc_array(v, n, sizeof(*(v)))
#endif
Loading…
Cancel
Save